(Pro Micro) - Einbinden eines Displays in bestehendes Programm

Guten Tag alle beieinander,

ich habe mich hier registriert, da ich schon seit ungefähr einem Jahr hobbymäßig mit dem Arduino arbeite. Ich habe schon diverse kleine Projekte realisiert, jedoch habe ich selbst nie irgendeine Programmiersprache gelernt. Somit ist alles zusammengeschustert aus Internetguides und logischem Verständnis der Programme. Manchmal stößt man aber an seine Grenzen und braucht einfach Hilfe von Erfahreneren.

Aktuell bin ich an einem Projekt, in dem es um eine Art Rollo geht, welches schnell hoch und runter gefahren werden soll. Das funktioniert auch soweit ganz gut und ich erreiche Zeiten von 4,2 Sekunden für einen Weg von 2,1 Meter.

Der Aufbau ist etwas… vllt unnötig verkompliziert, aber es tut was es soll. Der Motortreiber hat leider das Problem, dass er den ENB-Pin nicht ordentlich schalten kann. Somit ist der Motor dauerhaft auf Enable. Das habe ich über ein verbliebenes Relais gelöst, welches über einen Transistor vom Arduino geschaltet wird… Es ginge einfacher, aber das hatte ich gerade rumliegen.
Somit nicht wundern, dass hier ein Relais vorgeschaltet ist und der ENB-Pin trotzdem noch definiert ist.

Das Ganze hat eine zwei-einhalbfache Ansteuerung.

  1. Ultraschall-Distanzsensor unter der Zugangstreppe - wird die erste Stufe betreten, senkt sich die Stufe um weniger als einen Millimeter. Dies registriert der Sensor und gibt das Signal.

  2. Wenn man auf der anderen Seite ist, hat man einen Tastschalter - auch hier wieder einwandfrei.

  3. Auf dem Weg nach oben ist ein Kippschalter, welcher beim Umlegen entsprechend die bool-Variable von ‘false’ auf ‘true’ setzt. Bei den beiden ersten Funktionen ist ein Delay von einigen Sekunden integriert - nach dem Delay wird abgefragt, ob diese bool auf “true” steht - wenn ja, wird das Rollo so lange oben gehalten, bis die bool wieder auf ‘false’ gesetzt wird.

Mein Problem nach diesem Winter: Die Treppe (Stahl) reagiert auf die Temperaturen. Mal steht sie höher, mal niedriger. Obendrein sind die Personen, die diese Treppe betreten, verschiedenen Gewichts. Also dachte ich mir: "Warum nicht ein Display anschließen, welches mir die Distanz des Distanzsensors (IST) anzeigt und ein Poti nebendran gehangen, der den SOLL Wert anpasst - somit kann ich ganz einfach den Grenzwert festlegen und jederzeit anpassen.

Dazu hatte ich ein kleines (Noname) Adafruit Display (128x32 px) besorgt welches im Testcode auch einwandfrei diese Daten wiedergegeben hat.

Beim Anschließen in den Kreislauf jedoch… nichts. Weder mein Rollo funktioniert noch, noch zeigt das DIsplay irgendetwas an. Irgendwo ist ein Fehler drin, welcher aber für mich nicht ersichtlich ist.

Option 1: Das Display darf nicht in den “Loop” sondern muss ins “Setup” - da bin ich zum Einen unbedarft und die Zeit zum testen hatte ich bisher nicht mehr (das ganze Setup steht in der Firma)

Option 2: Ich hab beim Verkabeln nen Fehler gemacht - was aber nicht die fehlende Funktion des Rollos unterzeichnet.

Wenn ich richtig gelesen habe, muss SCL und SDA vom Display an 2 und 3 vom Arduino Micro. Gesagt getan - ohne Erfolg.

Ich habe einmal die “Display-Test” angefügt, womit ich den Test durchgeführt habe. Ich habe den Example-Code von Adafruit einfach nur auskommentiert.
Dabei ist auch mein volles Programm für das Rollo. (Bitte beachten: Formattierung mag nicht “der Norm entsprechend” sein und die Kommentare sind mal Englisch und mal Deutsch - teilweise C&P, teilweise Eigenverschulden :D)

So… Ich hoffe, mir kann hier jemand helfen.
Besten Dank im Voraus!

E: @HotSystems
Vielen Dank. Ich hab mir irgendwie gedacht es muss doch was einfacheres gegeben - dass der Code hier in Fenster eingebettet wird, ist natürlich super! :slight_smile: Ich lass sie trotzdem mal als runterladbaren Anhang drin!

MotorFinal.ino (4.9 KB)

DisplayTest.ino (9.94 KB)

Wir helfen gern.
Poste dazu deine Sketche direkt im Forum, aber bitte in Code-Tags, damit wir alle diese lesen können.
Verwende dazu die Schaltfläche </> oben links im Editorfenster.

Da der erste Beitrag die 9000 Character-Marke knackt…

Display-Test (gekürzt):

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
int potiPin = A0;
float poti;


#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {                
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  // init done
  
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();

}

void loop (){
  poti = map(analogRead(potiPin), 0, 1024, 900, 1412);
  poti = (poti / 100);
  display.setTextSize(1.8);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  String Str1 = "Soll: ";
  String Str2 = Str1 + poti;
  display.println(Str2);
  //display.display();
  display.setCursor(10,18);
  //display.clearDisplay();
  String Str3 = "Ist: ";
  String Str4 = Str3 + poti;
  display.println(Str4);
  display.display();
  delayMicroseconds(1000);
}

MotorFinal:

// Display init
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

// Pin Definition

// Motor Control
const int relPin = 16; // Relais
const int enbPin = 14; // Enable/Disable
const int stepPin = 4; // Pulse
const int dirPin = 5; // Direction

// Steuerungseinheiten
const int button = 7; // Manueller Button
const int leverPin = 8; // Kippschalter

const int trigPin = 9; // TriggerUltrasonic
const int echoPin = 10; // EchoUltrasonic

// Analog Poti
const int potiPin = A0; // Potentiometer

// Steuervariablen
bool shutterstat = false; //Status Rolladen
bool whilefn = false; //Status While Lever
int statbutton = 0; //Status Knopf
int statlever = LOW; //Dauerschalter
long duration;
float distance;
float poti;


// ####################  HERE STARTS THE UP CODE
void Up() {
  if (shutterstat == false)
  {
    delayMicroseconds(100);
    digitalWrite (relPin, HIGH); // Activate Relay
    delayMicroseconds(100);
    digitalWrite (dirPin, HIGH);
    for (int t = 450; t >= 250; t--){
      for (int y = 0; y < 5; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    for (int y = 0; y < 6400; y++){
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(250);
    }
    for (int t = 250; t <= 450; t++){
      for (int y = 0; y < 2; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
  shutterstat = true;
  }
}


//  ####################  HERE STARTS THE DOWN CODE
void Down() {
  if (shutterstat == true)
  {
    digitalWrite (dirPin, LOW);
    for (int t = 450; t >= 250; t--){
      for (int y = 0; y < 5; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    for (int y = 0; y < 6400; y++){
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(250);
    }
    for (int t = 250; t <= 450; t++){
      for (int y = 0; y < 2; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
  shutterstat = false;
  delay(5000);
  digitalWrite(relPin, LOW); // Deactivate Relay
  }
}

void setup() {
  pinMode(relPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enbPin, OUTPUT);
  pinMode(button, INPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(leverPin, INPUT);
  pinMode(potiPin, INPUT);
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
}

void loop() {

// THIS IS THE DISTANCE SENSOR
  digitalWrite(trigPin, LOW);
  delay(100);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  distance = duration*0.034/2; 

//  Serial.print("Distance: ");
//  Serial.println(distance);  


  poti = map(analogRead(potiPin), 0, 1024, 900, 1412);
  poti = (poti / 100);
  display.setTextSize(1.8);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  String Str1 = "Soll: ";
  String Str2 = Str1 + poti;
  display.println(Str2);
  //display.display();
  display.setCursor(10,18);
  //display.clearDisplay();
  String Str3 = "Ist: ";
  String Str4 = Str3 + distance;
  display.println(Str4);
  display.display();
  delayMicroseconds(1000);

  if (distance <= poti) 
  {  
    Up();
    
    delay(10000); // delay of 10 seconds
// THIS IS THE LEVER

    statlever = digitalRead(leverPin);
    if (statlever == HIGH) 
    {
      while (digitalRead(leverPin) == HIGH)
      {
      //do nothing, wait until exit
      }
    }
    delay(5000);
    Down();
  }


// THIS IS THE LEVER

  statlever = digitalRead(leverPin);
  if (statlever == HIGH) 
  {
    if (shutterstat == false)
    {
      Up();
      delay(10000);
    }
    while (digitalRead(leverPin) == HIGH)
    {
    //do nothing, wait until exit
    }
    delay(5000); // delay of 5 seconds
    Down();
  }

// THIS IS THE BUTTON READER
  statbutton = digitalRead(button);
  if (statbutton == HIGH) 
  {  
    Up();

    delay(10000); // delay of 10 seconds
    statlever = digitalRead(leverPin);
    if (statlever == HIGH) 
    {
      while (digitalRead(leverPin) == HIGH)
      {
      //do nothing, wait until exit
      }
      delay(5000);
    }
    Down();
  }
}

JKF2015:
… Adafruit …

Ich kann den Kram von Adafruit nicht leiden. Mag sein, dass das irre gut und schnell und sonstwas ist – ich find’s schwer durchschaubar und für Kleinkram wie der Ansteuerung eines SSD1306-basierten Displays umständlich. Vor allem, weil die Bibliotheken z. T. aufeinander aufbauen (und dementsprechend voneinander abhängig sind).

Deshalb habe ich mir für meine Display-Spiele eine eigene Bibliothek geschrieben. Die ist sehr klein, hängt von nichts ab und ist dementsprechend gut zu durchschauen, einzusetzen und anzupassen. Einen nicht allzu aktuellen aber funktionierenden Stand habe ich hier ins Netz gekippt. Vielleicht hilfts :slight_smile:

Den Code für die Initialisierung und teilweise den für die Manipulation eines einzelnen Pixels habe ich aus diesem Weblog. Den Rest habe ich selbst gestrickt.

Gruß

Gregor

Der Sketch sieht leider nicht sehr vertrauenswürdig aus, daher ist dieser auch schwer zu lesen. Ich sehe mir den aber später am PC nochmal an.

Mein Tipp: Teste dein Display erst mal nur mit einem kleinen Testsketch und wenn dieser funktioniert, baust du den als zusetzliche Funktion in deinen bestehenden Sketch ein. So kannst du das mit dem Display besser testen.

Für den Anfang wäre ein einfaches LCD-Display besser und einfacher gewesen.

Edit: Bist du sicher, dass es ein I2C-Display ist ?

HotSystems: Der Sketch sieht leider nicht sehr vertrauenswürdig aus, daher ist dieser auch schwer zu lesen. ...

Beziehst Du Dich auf mein Posting? Ich finde mich absolut vertrauenswürdig :-)

Gruß

Gregor

gregorss: Beziehst Du Dich auf mein Posting? Ich finde mich absolut vertrauenswürdig :-)

Ich habe vom Sketch geschrieben, nicht von dir. Und ich kann nichts dafür, wenn du dich vordrängelst. ;) ;)

Hi ihr zwei,

danke für eure zügige Antwort :)

@Gregor Ich bin kein Fan von den Preisen von Adafruit - wie gesagt, ist ein NoName ableger, der mit der Bibliothek aber funktioniert. Hatte ich mal günstig in der Bucht geschossen und dachte mir, hier wäre der perfekte Einsatzzweck.

Mit dem "selbst schreiben" einer Bibliothek wäre ein totaler Overkill gewesen - wie gesagt, ich hab den Example-Code mir angeschaut, Try&Error gemacht, welche Zeile was bewirkt und dementsprechend auf mich umgemünzt. Wie heißt es so schön - viele Wege führen nach Rom.. Aber ich schaue mir das auf jedenfall morgen mal an!

@Dieter Inwiefern "nicht vertrauenswürdig"? Wie erwähnt, er weicht höchstwahrscheinlich von der "Norm" ab - aber er läuft... :D Danke, dass du ihn dir später anschaust!

Das Display wurde an einem ArduinoMega2560 getestet. Dort wurde der DisplayTest.ino 1:1 aufgespielt und es lief einwandfrei. Per Poti konnte ich hier die Variable ändern und sie wurde auch 1:1 aufm Display so angezeigt.

Also dachte ich mir: Wenn das so 1A funktioniert, muss ich nur das entsprechend rauskopieren und in meinen Hauptcode einfügen und aufn ProMicro spielen - natürlich mit angepassten Pins. Allerdings glaube ich, dass hier irgendwas nicht einher geht. Entweder es is der Pin vom ProMicro, der einfach nicht den SDA und SCL Port wiederspiegelt, oder aber ich hab irgendwas zwischendrin verbockt .. Jedoch wundert es mich, dass nicht mal mehr das Rollo geht wenn ich den Code drin habe :/

Deshalb solltest du das Display mal allein am Pro micro betreiben. Hast du I2C auch richtig angeschlossen ? 2=SDA, 3=SCL.

Und nochmals, mach es als eigene Funktion, das ist übersichtlicher.

Achja....vertrauenswürdig beziehe ich auf die While-Schleife innerhalb der loop und den langen delays.

HotSystems:
Ich habe vom Sketch geschrieben, nicht von dir.

Stimmt. Das Wort „Sketch“ habe ich übersehen.

HotSystems:
Und ich kann nichts dafür, wenn du dich vordrängelst. :wink: :wink:

Ich auch nicht.

Gruß

Gregor

Jein und Ja.

Ich hab mir das mit dem 2=SDA 3=SCL gemerkt, weil es genau verkehrt herum ist wie auf dem Display (Display 3=SCL 4= SDA) - das ist definitiv korrekt angeschlossen gewesen. Lustigerweise hab ich durch meine eigene Doofheit mir den ProMicro abgeschossen (inkl Magic Smoke, dank falscher Verkabelung meinerseits...) und daraufhin den Mega 2560 angeschlossen - wobei ich dort entsprechend alle Kabel so zugeführt habe, wie der ProMicro sie hatte - ohne Erfolg. Es ging immer noch nichts. Somit gehe ich wirklich davon aus, dass der Code das Problem darstellt - und nicht der ProMicro... Der Ersatz-ProMicro sollte hoffentlich die Tage eintreffen, so dass ich dann noch mal das Display mit dem DisplayTest Code auf dem ProMicro betreiben kann...

Und was die While-Schleife und die Delays bezieht - Erklärung: Nach dem Up-Code soll das Rollo für einen Zeitraum oben bleiben, 10 Sekunden standardtechnisch. Danach soll er runter fahren. Wird währenddessen der "Statlever" betätigt, startet die while-Schleife, die ihn einfach oben lässt, bis er wieder betätigt wird... :) Ich habe keine bessere Lösung gefunden und so schien es mir eigentlich am Einfachsten, wobei mir inzw klar ist, dass wahrscheinlich gerade währenddessen das Display bspw nicht mehr "refresht" wird.

Ok....wenn es alles funktioniert, können die delays bleiben, aber wie du schon schriebst, die verhindern ein richtigen funktionieren des Displays. Während eines delay wartet der Controller bis die Zeit um ist und reagiert auf keinerlei andere Dinge. Er macht einfach nichts außer warten.

Und die While-Schleife kannst du sicher anders lösen. Du hast mit der loop ja schon eine Schleife, das reicht normal aus.

HotSystems: Und die While-Schleife kannst du sicher anders lösen. Du hast mit der loop ja schon eine Schleife, das reicht normal aus.

also ich gehe auch stark davon aus, dass man es anders lösen kann.. Der punkt ist halt, dass während dieser "statlever" betätigt ist, die anderen beiden Schalter (Ultraschall & Taster) Nicht agieren dürfen. Wobei mir da auch wieder die Idee kommt, am Anfang von denen einfach nur eine if-Abfrage zu setzen...

Ich hab kein Problem damit, den Code komplett überarbeitet neu zu schreiben, wenn damit am Ende das Display funktioniert :) Ich denke, den Delay kann ich auch mit einem Timer umgehen, der wiederum mit einer if-Abfrage bei erreichten 10 Sekunden die Funktion "Down" ausführt. Erneut -viele Wege. Und wenn damit das Display am Ende läuft - IMMER! :D Dafür muss es nur erstmal laufen...

Ok....ich sehe schon, du wirst deinen Sketch optimieren. Das ist gut.

Und wenn dein Display auch auf dem Micro läuft, ist der Weg nicht mehr so weit. Eine While-Schleife ist blockierend und kann schnell den Sketch zum Absturz bringen.

Was die delays betrifft, sieh dir mal BlinkWithoutDelay in den Beispielen der IDE an.

Edit: Es ist deutlich! Dein Konstrukt aus "delay und While-Schleife" blockiert die Funktion deines Displays.

Das musst du ändern, damit das Display auch richtig anzeigt.

HotSystems:
Ok…ich sehe schon, du wirst deinen Sketch optimieren. Das ist gut.

Und wenn dein Display auch auf dem Micro läuft, ist der Weg nicht mehr so weit.
Eine While-Schleife ist blockierend und kann schnell den Sketch zum Absturz bringen.

Was die delays betrifft, sieh dir mal BlinkWithoutDelay in den Beispielen der IDE an.

Edit:
Es ist deutlich!
Dein Konstrukt aus “delay und While-Schleife” blockiert die Funktion deines Displays.

Das musst du ändern, damit das Display auch richtig anzeigt.

Okay, super! Gut zu lesen, dass jemand Erfahrenes mir sagen kann, dass die While-Schleife und das Delay mir das Display negieren. Dann werd ich mich da dran setzen und das abändern.

D.h. auch, wenn du sagst, die Dinge lieber in Funktionen zu packen… Dann sollte ich entsprechend in den Loop die Funktion “Display” (später: void Display():wink: und UltraSonic (später: void UltraSonic():wink: reinpacken, einfach, damit dieser “Codeblock” den Loop nicht zumüllt, korrekt?

JKF2015: Okay, super! Gut zu lesen, dass jemand Erfahrenes mir sagen kann, dass die While-Schleife und das Delay mir das Display negieren. Dann werd ich mich da dran setzen und das abändern.

D.h. auch, wenn du sagst, die Dinge lieber in Funktionen zu packen... Dann sollte ich entsprechend in den Loop die Funktion "Display" (später: void Display();) und UltraSonic (später: void UltraSonic();) reinpacken, einfach, damit dieser "Codeblock" den Loop nicht zumüllt, korrekt?

Ja, das ist richtig. Es wird übersichtlicher und du kannst die Funktionen schnell mal deaktivieren, um Fehler zu suchen.

Du solltest so auch bei einem neuen Sketch mit dem Display anfangen, wenn das funktioniert, die anderen Funktionen hinzuschreiben.

// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)


void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  }
}

Wobei dieser Code eine >Dauerschleife< ist. Ich möchte ja im Endeffekt nur in meiner Funktion zählen…
Zum einen brauche ich zwei Interval-Variablen. Interval5 = 5000; und Interval10 = 10000;

Also würde ich im Loop eine Variable X haben, die dauerhaft die millis(); zählt… Und bei meinen Delays wird dann eine Variable Y haben, die = X gesetzt wird (Aktuelle Zeit), X zählt weiter. Und die if-Abfrage fragt dann ab, ob X - Y = Interval5 oder Interval10 ist, je nach Notwendigkeit…
Also:

void loop ()
{
  unsigned long currentmillis = millis();
}

void button()
{
// THIS IS THE BUTTON READER
  statbutton = digitalRead(button);
  if (statbutton == HIGH) 
  {  
    Up();
    unsigned long counter = currentmillis;

    if(currentMillis - counter >= interval10)
    {
      Down();
    }
  }
}

Damit würde er nach 10 Sekunden entsprechend runterfahren… Der einzige Gedankengang dazu noch - nachdem die If-Schleife ihre Bedinung nicht erfüllt (die 10 Sekunden sind noch nicht erreicht), verlässt er doch die erste If-Schleife, weil der statbutton != HIGH ist. Ich müsste also die komplette Zeitabfrage davon loskoppeln, oder? Am besten sogar als eigene Funktion einbetten?

Oh… es is definitiv zu spät :confused:

E:
Ich hab mir das ganze noch mal angeschaut und kam noch zu einem weiteren Problem.
Die “shutterstat” variable ist ja prinzipiell meine “Status” Variable - ist das Rollo oben => Du kannst keine “Up” Funktion mehr starten. Ist es unten => du kannst keine “Down” Funktion mehr starten.

Allerdings weiß ich noch nicht genau, wie ich die “while-schleife” umgehen kann. Sollte ich hierfür meine “bool shutterstat” lieber in eine “int” verwandeln mit 0 1 2, wobei 0 = false, 1 = true und 2 = dauerhaft ist. So wird bei der “lever” Funktion nach dem “Up” shutterstat = 2 gesetzt, und sobald der Lever-pin wieder ein “LOW” empfängt, wird shutterstat = 1 gesetzt - womit die “Down” Funktion gestartet werden kann, welche “shutterstat = 0” wieder setzt.
Jedoch… Mit welcher Funktion kann ich die Statusänderung dauerhaft abfragen? Weil “Lever = LOW” ist ja prinzipiell der Dauerzustand. Oder baue ich in den loop eine

if ((Lever == LOW) && (shutterstat == 2))
{ 
  shutterstat = 1;
  Down();
}

?

// Display init
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

// Pin Definition

// Motor Control
const int relPin = 16; // Relais
const int enbPin = 14; // Enable/Disable
const int stepPin = 4; // Pulse
const int dirPin = 5; // Direction

// Steuerungseinheiten
const int button = 7; // Manueller Button
const int leverPin = 8; // Kippschalter

const int trigPin = 9; // TriggerUltrasonic
const int echoPin = 10; // EchoUltrasonic

// Analog Poti
const int potiPin = A0; // Potentiometer

// Steuervariablen
int shutterstat = 0; //Status Rolladen, 0 = Unten, 1 = Oben, 2 = Dauer
int statbutton = 0; //Status Knopf
int statlever = LOW; //Dauerschalter
long duration;
float distance;
float poti;
int delay10 = 10000;
int delay5 = 5000;
unsigned long currentMillis;
unsigned long previousMillis;



void setup() {
  pinMode(relPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enbPin, OUTPUT);
  pinMode(button, INPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(leverPin, INPUT);
  pinMode(potiPin, INPUT);
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
}

void loop() {
  ultrasonic();
  
  disp();

  ultrasoniccheck();

  button1();

  lever();
  
}

void disp()
{
  poti = map(analogRead(potiPin), 0, 1024, 900, 1412);
  poti = (poti / 100);
  display.setTextSize(1.8);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  String Str1 = "Soll: ";
  String Str2 = Str1 + poti;
  display.println(Str2);
  //display.display();
  display.setCursor(10,18);
  //display.clearDisplay();
  String Str3 = "Ist: ";
  String Str4 = Str3 + distance;
  display.println(Str4);
  display.display();
  delayMicroseconds(1000);
}

// THIS IS THE DISTANCE SENSOR LOOP
void ultrasonic()
{  
  digitalWrite(trigPin, LOW);
  delay(100);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  distance = duration*0.034/2; 
}

// THIS IS THE DISTANCE SENSOR CHECK
void ultrasoniccheck()
{
  if (distance <= poti) 
  {  
    Up();

    currentMillis = millis();
    previousMillis = currentMillis;

    if (currentMillis - previousMillis >= delay10) 
    {     
      lever();
    
      Down();
    }
  }
}


// THIS IS THE BUTTON READER
void button1()
{
  statbutton = digitalRead(button);
  if (statbutton == HIGH) 
  {  
    Up();

    currentMillis = millis();
    previousMillis = currentMillis;

    if (currentMillis - previousMillis >= delay10) 
    {     
      lever();
    
      Down();
    }
  }
}


void lever()
{
// THIS IS THE LEVER

  statlever = digitalRead(leverPin);
  if (statlever == HIGH) 
  {
    Up();
    shutterstat = 2;
    if ((statlever == LOW) && (shutterstat == 2))
    {
      currentMillis = millis();
      previousMillis = currentMillis;

      if (currentMillis - previousMillis >= delay5) 
      {     
        Down();
      }
    }
  }
}



// ####################  HERE STARTS THE UP CODE
void Up() 
{
  if (shutterstat == 0)
  {
    delayMicroseconds(100);
    digitalWrite (relPin, HIGH); // Activate Relay
    delayMicroseconds(100);
    digitalWrite (dirPin, HIGH);
    for (int t = 450; t >= 250; t--){
      for (int y = 0; y < 5; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    for (int y = 0; y < 6400; y++){
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(250);
    }
    for (int t = 250; t <= 450; t++){
      for (int y = 0; y < 2; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
  shutterstat = 1;
  }
}


//  ####################  HERE STARTS THE DOWN CODE
void Down() 
{
  if (shutterstat == 1)
  {
    digitalWrite (dirPin, LOW);
    for (int t = 450; t >= 250; t--){
      for (int y = 0; y < 5; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    for (int y = 0; y < 6400; y++){
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(250);
    }
    for (int t = 250; t <= 450; t++){
      for (int y = 0; y < 2; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    shutterstat = 0;
  
    currentMillis = millis();
    previousMillis = currentMillis;

    if (currentMillis - previousMillis >= delay10) 
    {     
      digitalWrite(relPin, LOW); // Deactivate Relay
    }
  }
}

Ich habe nun den gesamten Code einmal überarbeitet. Testen konnte ich ihn noch nicht. Ich frage mich aber insbesondere bei den neuen “delays”, ob er nicht vorher schon die jeweilige Schleife verlässt und ich sie davon entkoppeln muss - und somit über neue Variablen das ganze im Loop triggern muss.

// Display init
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

// Pin Definition

// Motor Control
const int relPin = 6; // Relais
const int enbPin = 7; // Enable/Disable
const int stepPin = 4; // Pulse
const int dirPin = 5; // Direction

// Steuerungseinheiten
const int button = 10; // Manueller Button
const int leverPin = 16; // Kippschalter

const int trigPin = 8; // TriggerUltrasonic
const int echoPin = 9; // EchoUltrasonic

// Analog Poti
const int potiPin = A0; // Potentiometer

// potiSave
const int potibutPin = 14; // Button für Potisave

// Steuervariablen
int shutterstat = 0; //Status Rolladen, 0 = Unten, 1 = Oben, 2 = Dauer
int statbutton = 0; //Status Knopf
int statlever = LOW; //Dauerschalter
long duration;
float distance;
float poti;
float potisave = 10.55;

// Timervariablen
unsigned long t1;
unsigned long t5;
unsigned long t10;
unsigned long td10;
int ts1 = 0;
int ts1e = 0;
int ts5 = 0;
int ts5e = 0;
int ts10 = 0;
int ts10e = 0;
int tsd10 = 0;
int tsd10e = 0;



void setup() {
  pinMode(relPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enbPin, OUTPUT);
  pinMode(button, INPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(leverPin, INPUT);
  pinMode(potiPin, INPUT);
  pinMode(potibutPin, INPUT);
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.setRotation(2);
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
}

void loop() {
  ultrasonic();

  potiread ();
  
  disp();

  ultrasoniccheck();

  button1();

//  lever();

  downend();

  buttonend();

  leverend();
}

void leverend()
{
  if (millis() - t5 >= 5000) 
  {     
    shutterstat = 1;
    Down();

    ts5e = 0;
  }
}

void buttonend()
{
  if ((millis() - t10 >= 10000) && (ts10e == 1))
  {     
    lever();
    
    Down();
      
    ts10e = 0;
  }
}

void downend()
{
  if ((millis() - td10 >= 10000) && (tsd10e == 1))
  {     
    digitalWrite(relPin, LOW); // Deactivate Relay
    shutterstat = 0;
    tsd10e = 0;
  }
}
void potiread()
{
  timer1();
  if (millis() - t1 >= 250)
  {    
    poti = map(analogRead(potiPin), 0, 1024, 900, 1412);
    poti = (poti / 100); 
    ts1 = 0;
  }
}
void disp()
{
  potibutsave();
  display.setTextSize(1.8);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  String Str1 = "Soll: ";
  String Str2 = Str1 + poti;
  display.println(Str2);
  //display.display();
  display.setCursor(10,9);
  //display.clearDisplay();
  String Str3 = "Ist: ";
  String Str4 = Str3 + distance;
  display.println(Str4);
  display.setCursor(10,18);
  String Str5 = "Save: ";
  String Str6 = Str5 + potisave;
  display.println(Str6);
  display.display();
  delay(10);
}

void potibutsave()
{
  if (digitalRead(potibutPin) == HIGH)
    {
      potisave = poti;

    }
}

// THIS IS THE DISTANCE SENSOR LOOP
void ultrasonic()
{  
  digitalWrite(trigPin, LOW);
  delayMicroseconds(100);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  distance = duration*0.034/2; 
}

// THIS IS THE DISTANCE SENSOR CHECK
void ultrasoniccheck()
{
  if ((distance <= potisave) && (ts10e == 0))
  {  
    Up();

    ts10 = 1;
    ts10e = 1;
    timer10();
  }
  if ((millis() - t10 >= 10000) && (ts10e == 1))
  { 
    lever();
    
    Down();

    ts10e = 0;
  }
}


// THIS IS THE BUTTON READER
void button1()
{
  statbutton = digitalRead(button);
  if ((statbutton == HIGH) && (ts10e == 0))
  {  
    Up();

    ts10 = 1;
    ts10e = 1;
    timer10();
  }
}


void lever()
{
// ================= THIS IS THE LEVER =================

  statlever = digitalRead(leverPin);
  if ((statlever == HIGH) && (ts5e == 0))
  {
    Up();
    shutterstat = 2;
  }
  if ((statlever == LOW) && (shutterstat == 2) && (ts5e == 0))
  {
    ts5 = 1;
    ts5e = 1;
    timer5();
  }
}


void timer1()
{
  if (ts1 == 0)
  {
    t1 = millis();
    ts1 = 1;
  }
}

void timer5()
{
  if (ts5 == 1)
  {
    t5 = millis();
    ts5 = 0;
  }
}

void timer10()
{
  if (ts10 == 1)
  {
    t10 = millis();
    ts10 = 0;
  }
}

void timer10d()
{
  if (tsd10 == 1)
  {
    td10 = millis();
    tsd10 = 0;
  }
}


// ####################  HERE STARTS THE UP CODE
void Up() 
{
  if (shutterstat == 0)
  {
    delayMicroseconds(100);
    digitalWrite (relPin, HIGH); // Activate Relay
    delayMicroseconds(100);
    digitalWrite (dirPin, HIGH);
    for (int t = 450; t >= 250; t--){
      for (int y = 0; y < 5; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    for (int y = 0; y < 6400; y++){
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(250);
    }
    for (int t = 250; t <= 450; t++){
      for (int y = 0; y < 2; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
  shutterstat = 1;
  }
}


//  ####################  HERE STARTS THE DOWN CODE
void Down() 
{
  if (shutterstat == 1)
  {
    digitalWrite (dirPin, LOW);
    for (int t = 450; t >= 250; t--){
      for (int y = 0; y < 5; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    for (int y = 0; y < 6400; y++){
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(250);
    }
    for (int t = 250; t <= 450; t++){
      for (int y = 0; y < 2; y++){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(t);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(t);
      }
    }
    tsd10 = 1;
    tsd10e = 1;
    timer10d();
  }
}

Okay - das letzte hat wieder nicht funktioniert. Hier sind die Timer getestet und funktionieren… Das Display läuft nebenher. Ich fragte mich jetzt nur: Ist das “Konform” oder fehlt irgendwo etwas?

Edit:
Okay… heute wieder in der Firma und konnte es einbauen. Ich habe nichts am Code verändert, außer entsprechend die Timer noch in die anderen Funktionen eingebaut…
Ergebnis:
Zu Hause, trocken am Labornetzteil hab ich nen flüssiges Display gehabt - bis “Up” oder “Down” ausgelöst wurde. Dort hat er natürlich kurz gestockt wegen der Delays für den Motor. Das ist auch okay.

Jetzt hab ichs eingebaut - Bootscreen (Adafruit) und 2 sekunden flüssige Wertausgabe… Und auf einmal krieg ich eine 5 (!) Sekunden Latenz rein. das Display refresht sich nur noch alle 5 Sekunden. Auch alle anderen Befehle (potisave, button1 etc) werden nur alle 5 Sekunden gezogen. Und die “up” oder “down” Funktion läuft nicht.

Irgendeine Idee? :confused: