LEDs leuchten bei laufendem Motor

Hi Arduino Community ,
bin gerade am Programmieren ein klein projekt und habe paar schwerigkeit bei der Steuerung des Steppermotors ( A4988 Driver)gleichzeitg mit LEDs ( rot, blau , gelb ...) getroffen . das Projekt enthält 1 Schrittmotor und 5 Leds.
jede LED ist für eine bestimme Schritte-Nr geeignet. das Heißt sobald mein Schrittmotor geeignte schritte erreicht hat sollte ein LED Blinken. Die LED s sind abhäging von Anzahl der Schrittnummern des Motors. ich kriege leider das nicht hin dass die LEDS beleuchten sobald der definierten Schritten ereicht hat

//.. Function für die Steuerung  alles funktionniert super nur  hier  der Motor  stoppt um die Leds //blinken zu lassen, Leds sollen  bei laufendem Motor blinekn
    for(int x=0; x< maxValue;x++){
    stepz(); // steuerung Step pin schrittmotor
    delayMicroseconds(StepPeriodUs);
      for ( int s=0;s<4;s++){  // hier sollte das Programm  durchsuchen ob die eing LED daten 
 //erreicht sind
      if(Ledschritt[s]== maxValue-s){
        digitalWrite( LED[s],HIGH);
        delay_ms(ms);
        digitalWrite(LED[s],LOW);
      }
    }

void stepz() // Pulse Z-achse StepperMotor
{
  digitalWrite(ZstepPin, HIGH);
  delayMicroseconds(3);
  digitalWrite(ZstepPin, LOW);
  delayMicroseconds(3);
}

wie kann man die LED bei laufendem Motor blinken lassen ohne ihn zu unterbrechen ?

Mit freundlichen Grüßen
Mo

Hallo
Zeige den Schaltplan und den Sketch dazu. So können wir sehen wie wir dir helfen können.

1 Like

Ja, ohne den kompletten Sketch und die Schaltung kann man nicht helfen.
Wenn Du mehrere Dinge gleichzeitig machen willst, ist es wichtig, dass Du blockadefrei programmierst - also keine delay verwenden.
Evtl. könntest Du auch meine MobaTools Lib verwenden. Da werden die Schritte für den Motor im Hintergrund erzeugt, und stören den loop() nicht. Außerdem gibt es Timing-Funktion z.B. um eine Led blinken zu lassen.

1 Like

Vielen Dank euch alle für die Rückmeldung .
ich finde die MobaTools sehr hilffreich danke dir Micro und jetzt ich versuche anders zu programmieren.
Eine Frage noch , kann man überhaupt die Anzahl der Schritten des Motors , der im Hintergrund läuft mit myStepper.rotate(1) , überwachen ? wie kann man am besten der laufenden Schrittmotor überwachen ?
danke nochmals

Mit readSteps() kannst Du jederzeit abfragen wo der Stepper gerade ist.

1 Like

Hi Micro ,
Super Vielen Dank.

Ich habe mittels Mobatools mein Programm aufgebaut, leider habe ich paar Schwerigkeiten ,um die funktionen richtig zu Nuten. Vielleicht kannst du mir paar tips geben bzw helfen ,es wäre lieb von dir :slight_smile:

Konzept : 10-5Leds ( Rot , Blau , Grün ...)in abhängikeit aktuellen Steps_Nr Stepper Motor Nema
17 steueren bzw blinken lassen.
Ablauf
1: Eingabe über Serial Monitor : LedNr1:StepsNR1,LedNr2:StepsNr2, usw...
2 : einlesen
3: Motor CW richtung laufen lassen
4:Tickerzeit einstellen um Feedback über aktuel Steps_nr des Motors zu haben und die Led steuern zu können
5: Led blinken lassen : 1.st maxwert bis minwert
6: Motor halten
7: CCW laufen lassen und feedback immer auf steps zu haben
8: Led blinken lassen . 1. minwert bis maxwert
Ziel : Die Leds steuern unabhähig voneinander und in abhängikeit vom Schrittnummer
Fragen :
Wie kann mann die steps auf 0 setzen und meine zähler zurücksetzen zu können ? ( setZero () )
Wie kann immer diekontrolle auf Steps_Nr immer haben um es zu benutzen bei Ledsteuerung
Anbei das Programmcode : ( No solution ;( )

#include <MobaTools.h>
#include <stdlib.h>
const byte ZdirPin = 10;
const byte ZstepPin = 11;
const byte EnabZ = 12;
const int STEPS_REVOLUTION = 200;
MoToStepper myStepperz( STEPS_REVOLUTION, STEPDIR );  // 200 Steps/ Umdrehung full Steps
MoToTimebase readIntervall;// Zeitinterval zur  Stepsüberwachug
int Led_array[] = {2, 3, 4, 5, 6};//  Pins  defintion
const byte indexMessageMax = 200;
char message[indexMessageMax + 1];
int led_array[5]; // Led_Nr
int steps_array[5]; // Steps_Nr 
int maxValue; // max eingegeben Steps_ Nr 
const char endMarker = '\n';
boolean save = false;// Schlüssel
boolean rueckfahrt = false; //Schlüssel für die Rückfahrt

boolean orderAvailable() { //  Eingabe einlesen Format  LedNr1:StepsNR1,LedNr2:StepsNr2,..
  static byte indexMessage = 0;
  boolean messageInProgress = true;
  while (Serial.available()&& messageInProgress) {
    int c = Serial.read();
    save = true;
    if (c != -1) {
      switch (c) {
        case endMarker:
          message[indexMessage] = '\0';
          indexMessage = 0;
          messageInProgress = false;
          break;
        case '\r': break;
        default:
          if (indexMessage <= indexMessageMax - 1) message[indexMessage++] = (char) c;
          break;
      }
    }
  }
  return !messageInProgress;
}

void setup() {
  myStepperz.attach(ZstepPin, ZdirPin);
  myStepperz.setSpeed(200);
  readIntervall.setBasetime(100);   // 100ms Tickerzeit
  for (int i = 0 ; i < 5; i++) {
    pinMode(Led_array[i], OUTPUT); // Led als output definieren
  }
  Serial.begin(115200);
  Serial.print(" Format 1:200,2:500,5:300,4:100.\n");
}

void loop() {
  if(orderAvailable()) {
    myStepperz.rotate(1); //  Cw richtung Motor 500 steps im hintergrund laufen lassen dann erst Leds in Abhängikeit Steps_Nr steuern lassen
  }
  while(rueckfahrt == false) {
    ledssteuerungCw();
  }
  if(rueckfahrt == true ) {
    myStepperz.rotate(-1);
  }
  while(rueckfahrt == false) {
    ledssteuerungCcw();
  }
}

void auswerten(int *led_array, int *steps_array, int *maxvalue) { // Eingaben zerlegen :Format  LedNr1:StepsNR1,LedNr2:StepsNr2,.. in tabellen speichern
  char *ptr, *p, *savePtr, *saveP;  //pointer
  const char delim[] = ",";
  int k = 0;
  int j = 0;
  if (save == true) { // tabellen initialisieren
    for (int s = 0; s < 5; ++s) {
      led_array[s] = 0;
      steps_array[s] = 0;
    }
  }
  ptr = strtok_r(message, delim, &savePtr);
  while (ptr != NULL) {
    if (strchr(ptr, ':')) {
      p = strtok_r(ptr, ":", &saveP);
      if (p != NULL) {
        if ( j < 5) {
          led_array[j++] = atoi (p);
        }
      }
      p = strtok_r(NULL, ":", &saveP);
      if (p != NULL) {
        if ( k < 5) {
          steps_array[k++] = atol(p);
        }
      }
    }
    ptr = strtok_r(NULL, delim, &savePtr);
  }
  for (int y = 1; y < 4; y++) { // maxValue definieren
    if (steps_array[y] > maxValue) {
      maxValue = steps_array[y];
    }
  }
}

void ledssteuerungCw() {
  int led_array[5];
  int step_array[5];
  int maxWert;
  int steps_nr;
  auswerten(led_array, step_array, maxWert); // eingaben einlesen z.b  1-LED : 300 Steps+
  if (readIntervall.tick()){ //Steps alle 100ms neu einlesen und  überwachen //ich weisse nicht ob es hier gut passt aber die Idee ist über Tick ein Feedback auf StepsNr vom Motor zu haben um die Leds  in echzeit zu steuern
    steps_nr = myStepperz.readSteps();
    if (steps_nr == 500) { // erst  nach 500 Steps fängt der zähler  an
      for (int i = 0; i < 5; i++) {
        if (step_array[i] == maxWert) { // Led die maxSteps_Nr hat  als 1.st blinken lassen
          digitalWrite(Led_array[i], HIGH);
          delay_ms(200);
          digitalWrite(Led_array[i], LOW);
        }
      }
    }
    if (steps_nr > 500) { // erst  nach 500 Steps fängt der zähler  an
      for (int i =0 ; i < 5; i++) {
        if (step_array[i] == (maxWert -(steps_nr + 500))){ // Led blinken lassen wenn maxWert - (steps_nr motor+ 500'') = Steps --> Led (eingaben)  ''steps counter fängt  ab 500 steps : stepsled1>stepsled3>stepsled5 > stepsLed4
          digitalWrite(Led_array[i], HIGH);
          delay_ms(200);
          digitalWrite(Led_array[i], LOW);
        }
      }
    }
    if (steps_nr == (maxWert + 500)) { // max Steps erreicht hat + 500 frei steps am anfang
      myStepperz.rotate(0); // Stop Motor
      rueckfahrt == true ; //  Motor in Gegenrichtung laufen lassen biz zu -maxwert
      myStepperz.setZero(); //  ?  Steps_Nr wieder auf 0 setzen ?? für CCW gegnrichtung steuerung
    }
  }
}
void ledssteuerungCcw() {
  int led_array[5];
  int step_array[5];
  int maxWert;
  int steps_nr;
  auswerten(led_array, step_array, maxWert); // eingaben einlesen z.b  1-LED : 300 Steps+
  if (readIntervall.tick()) { // ich weisse nicht ob es hier gut passt aber die Idee ist über Tick ein Feedback auf StepsNr vom Motor zu haben um die Leds  in echzeit zu steuern
    steps_nr = myStepperz.readSteps();
    if (steps_nr > 0){
      for (int i = 0 ; i < 5 ; i++) {
        if (step_array[i] == steps_nr) { //  Led mit nidrigstem STEps-Nr blinkt als 1.st ( CCW - CW Richtung gegenseitig steuern in abhängikeit von Steps_nr
          digitalWrite(Led_array [i], HIGH);
          delay_ms(200);
          digitalWrite(Led_array [i], LOW);
        }
      }
    }
    if (steps_nr == maxWert) {
      myStepperz.rotate(0); // Stop Motor
      rueckfahrt == false ; //  Motor in Gegenrichtung laufen lassen biz zu -maxwert
      myStepperz.setZero(); //  ?????  Steps_Nr wieder auf 0 setzen ?? für CCW gegnrichtung steuerung
      save == true ; // tabellen löschen für die nächste eingabe
    }
  }
}

void delay_ms(uint16_t ms) {
  uint16_t tmp_millis = 0, tmp_diff = 0;
  uint16_t thres = 0;
  thres = ms;
  tmp_millis = (uint16_t)millis();
  tmp_diff = 0;
  while (tmp_diff < thres)
  {
    if ((uint16_t)millis() >= tmp_millis) {
      tmp_diff += ((uint16_t)millis() - tmp_millis);
      tmp_millis = (uint16_t)millis();
    }
    else {
      tmp_millis = 0;
      tmp_diff += ((uint16_t)millis() - tmp_millis);
      tmp_millis = (uint16_t)millis();
    }
  }
}

Hallo FouFou,

so lange dein Code nicht richtig formatiert ist schaue ich mir das nicht an.

Es gibt eine automatische Formatierungs-Funktion in der Arduino-IDE

Man drückt einfach Strg-T, Ctrl-T. Und schon sind alle Einrückungen richtig gesetzt.
Und dann würde eine Leerzeile zwischen den functions für Übersichtlichkeit sorgen.
Manchmal sind da keine Leerzeile und an anderer Stelle dann wieder fünf Leerzeilen.

Diese Art den Code zu schreiben lässt mich vermuten, dass du eher unordentlich bist und deinen Code nicht sorgfältig auf Fehler überprüfst.

Unordentlichkeit passt für mich persönlich nicht zum programmieren. Das ganze hier ist freiwillig.
Bei so unordentlich programmiertem Code habe ich keine Lust mir das näher anzuschauen.

vgs

1 Like

Das ist sehr komisches deutsch. Das verstehe ich nicht.
Schreibe ein Beispiel in dem für alles Zahlen geschrieben sind.

vgs

Falls dies ein Versuch sein sollte, auf das blockierende delay() zu verzichten: da muss ich dier leider sagen, dass das so nicht funktioniert. denn Deine Delay-Funktion blockiert den Code genauso wie das delay() selbst.
Du wendest hier das milis() völlig falsch an. Schaue Dir in der IDE das Beispiel Blink without delay nochmals geneau an.
Bei verwendung von milis() im Vergleich , ob die zeit schon abgelaufen ist, musst Du den Vergleich immer so setzen:
if ( zeitJETZT - zeitVORHER > zeitINTERVAL)
und nehme für die Variablen , die in Verbindung mit Milis() und Deinem Vergleich stehen, also zeitJETZT, zeitVORHER, zeitINTERVAL immer uint32_t Variablen.

1 Like

Was mir beim ersten Überfliegen deines Sketches aufgefallen ist, dass Du die Steppositionen auf Gleichheit prüfst:

Bei 200 Steps/Umdrehung und einem Temp von 20 Umdr/Minute ( myStepperz.setSpeed(200); ) ergibt sich, dass alle 15ms ein Step ausgeführt wird. Du fragst aber die Stepposition nur alle 100ms ab. Es ist also sehr wahrscheinlich, dass Du den Abfragepunkt gar nicht genau erwischt. Du musst also grundsätzlich auf '>=' oder '<=' - je nach Drehrichtung - abfragen. Wenn Du Aktionen nur beim Überschreiten der Grenze einmalig ausführen willst, musst Du das mit einem Flag realisieren.

Für nicht blockierende Zeit- und Verzögerungsfunktionen kannst Du auch die MoToTimer Klasse verwenden. Da sind auch Beispiele dabei, wie man das macht. Meiner Meinung nach ist das im Code übersichtlicher als mit millis() direkt zu hantieren.

1 Like

@Foufou
Guter Rat von MicroBahner! Da du ja die MoBaTools eh für die Stepper eingebunden hast, ist das natürlich das Idealste, auch die Timer daraus zu nutzen.

1 Like

Danke für die schnelle Rückmeldung,
anbei paar Korrekturen

#include <MobaTools.h>
#include <stdlib.h>
const byte ZdirPin = 10;
const byte ZstepPin = 11;
const byte EnabZ = 12;
const int STEPS_REVOLUTION = 200;
MoToStepper myStepperz( STEPS_REVOLUTION, STEPDIR );  // 200 Steps/ Umdrehung full Steps
MoToTimebase readIntervall;// Zeitinterval zur  Stepsüberwachug
MoToTimer Blinkzeit;
int Led_array[] = {2, 3, 4, 5, 6};//  Pins  defintion
const byte indexMessageMax = 200;
char message[indexMessageMax + 1];
int led_array[5]; // Led_Nr
int steps_array[5]; // Steps_Nr
int maxValue;
const char endMarker = '\n';
boolean save = false;// Schlüssel
boolean rueckfahrt = false; //Schlüssel für die Rückfahrt
boolean flag1 = false;
boolean orderAvailable() { //  Eingabe einlesen Format  LedNr1:StepsNR1,LedNr2:StepsNr2,..
  static byte indexMessage = 0;
  boolean messageInProgress = true;
  while (Serial.available() && messageInProgress) {
    int c = Serial.read();
    save = true;
    if (c != -1) {
      switch (c) {
        case endMarker:
          message[indexMessage] = '\0';
          indexMessage = 0;
          messageInProgress = false;
          break;
        case '\r': break;
        default:
          if (indexMessage <= indexMessageMax - 1) message[indexMessage++] = (char) c;
          break;
      }
    }
  }
  return !messageInProgress;
}

void setup() {
  myStepperz.attach(ZstepPin, ZdirPin);
  //myStepperz.attachEnable **need Halttmoment
  myStepperz.setSpeed(200);
  //  myStepperz.setRampLen(100);**ohne rampe
  readIntervall.setBasetime(15);   // 15ms Tickerzeit
  for (int i = 0; i < 5; i++) {
    pinMode(Led_array[i], OUTPUT); // Led als output definieren
  }
  Serial.begin(115200);
  Serial.print(" Format 1:200,2:500,5:300,4:100.\n");
}

void loop() {
  if (orderAvailable()) {
    flag1 == true;
    myStepperz.rotate(1); //  Cw richtung Motor 500 steps im hintergrund laufen lassen dann erst Leds in Abhängikeit Steps_Nr steuern lassen
  }
  while (rueckfahrt == false) {
    ledssteuerungCw();
  }
  if (rueckfahrt == true ) {
    myStepperz.rotate(-1);
  }
  while (rueckfahrt == true) {
    ledssteuerungCcw();
  }
}

void auswerten(int *led_array, int *steps_array, int *maxvalue) { // Eingaben zerlegen :Format  LedNr1:StepsNR1,LedNr2:StepsNr2,.. in tabellen speichern
  char *ptr, *p, *savePtr, *saveP;  //pointer
  const char delim[] = ",";
  int k = 0;
  int j = 0;
  if (save == true) { // tabellen initialisieren
    for (int s = 0; s < 5; ++s) {
      led_array[s] = 0;
      steps_array[s] = 0;
    }
  }
  ptr = strtok_r(message, delim, &savePtr);
  while (ptr != NULL) {
    if (strchr(ptr, ':')) {
      p = strtok_r(ptr, ":", &saveP);
      if (p != NULL) {
        if ( j < 5) {
          led_array[j++] = atoi (p);
        }
      }
      p = strtok_r(NULL, ":", &saveP);
      if (p != NULL) {
        if ( k < 5) {
          steps_array[k++] = atol(p);
        }
      }
    }
    ptr = strtok_r(NULL, delim, &savePtr);
  }
  for (int y = 1; y < 4; y++) { // maxValue definieren
    if (steps_array[y] > maxValue) {
      maxValue = steps_array[y];
    }
  }
}

void ledssteuerungCw() {
  int led_array[5];
  int step_array[5];
  int maxWert;
  int steps_nr;
  auswerten(led_array, step_array, maxWert); // eingaben einlesen z.b  1-LED : 300 Steps+
  if (readIntervall.tick()) { //Steps alle 100ms neu einlesen und  überwachen //ich weisse nicht ob es hier gut passt aber die Idee ist über Tick ein Feedback auf StepsNr vom Motor zu haben um die Leds  in echzeit zu steuern
    steps_nr = myStepperz.readSteps();
    if (steps_nr >= 500 && flag1 == true) { // erst  nach 500 Steps fängt der zähler  an
      for (int i = 0; i < 5; i++) {
        if (step_array[i] == maxWert) { // Led die maxSteps_Nr hat  als 1.st blinken lassen
          digitalWrite(Led_array[i], HIGH);
          Blinkzeit.setTime(200);
          digitalWrite(Led_array[i], LOW);
          flag1 == false;
        }
      }
    }
    if (steps_nr > 500 && flag1 == false) { // erst  nach 500 Steps fängt der zähler  an
      for (int i = 0 ; i < 5 ; i++) {
        if (step_array[i] == (maxWert - (steps_nr + 500) )) { // Led blinken lassen wenn maxWert - (steps_nr motor+ 500'') = Steps --> Led (eingaben)  ''steps counter fängt  ab 500 steps : stepsled1>stepsled3>stepsled5 > stepsLed4
          digitalWrite(Led_array[i], HIGH);
          Blinkzeit.setTime(200);
          digitalWrite(Led_array[i], LOW);
        }
      }
    }
    if (steps_nr >= (maxWert + 500)) { // max Steps erreicht hat + 500 frei steps am anfang
      myStepperz.rotate(0); // Stop Motor
      rueckfahrt == true ; //  Motor in Gegenrichtung laufen lassen biz zu -maxwert
      myStepperz.setZero(); //  ?????  Steps_Nr wieder auf 0 setzen ?? für CCW gegnrichtung steuerung
    }
  }
}

void ledssteuerungCcw() {
  int led_array[5];
  int step_array[5];
  int maxWert;
  int steps_nr;
  auswerten(led_array, step_array, maxWert); // eingaben einlesen z.b  1-LED : 300 Steps+
  if (readIntervall.tick()) { // ich weisse nicht ob es hier gut passt aber die Idee ist über Tick ein Feedback auf StepsNr vom Motor zu haben um die Leds  in echzeit zu steuern
    steps_nr = myStepperz.readSteps();
    if (steps_nr > 0) {
      for (int i = 0 ; i < 5 ; i++) {
        if (step_array[i] == steps_nr) { //  Led mit nidrigstem STEps-Nr blinkt als 1.st ( CCW - CW Richtung gegenseitig steuern in abhängikeit von Steps_nr
          digitalWrite(Led_array [i], HIGH);
          Blinkzeit.setTime(200);
          digitalWrite(Led_array [i], LOW);
        }
      }
    }
    if (steps_nr >= maxWert) {
      myStepperz.rotate(0); // Stop Motor
      rueckfahrt == false ; //   Motor in Gegenrichtung laufen lassen biz zu -maxwert
      myStepperz.setZero(); //  ?????  Steps_Nr wieder auf 0 setzen ?? für CCW gegnrichtung steuerung
      save == true ; // tabellen löschen für die nächste Eingabe

    }
  }
}

Setzt " myStepperz.setZero()" die Schrittnummer des Motors wieder auf 0 ?
Ich muss nach jeder Bewegung die Steps_nr wieder auf 0 setzen

Ja, so ist es.

Das mit den Blink/Verzögerungszeiten musst Du dir nochmal klarmachen. Du steckst immer noch im 'delay' denken.

          digitalWrite(Led_array[i], HIGH);
          Blinkzeit.setTime(200);
          digitalWrite(Led_array[i], LOW);

Mit setTime ziehst Du sozusagen einen 'kurzzeitwecker' auf, der dann im Hintergrund abläuft. Das Programm bleibt NICHT - wie delay - an der Stelle stehen bis die Zeit abgelaufen ist. Das ist so ähnlich wie mit deinen Steppern. Die laufen auch im Hintergrund, und Du fragst regelmäßig ab, wo sie gerade sind. Du musst also in deinem Programm auch regelmäßig abfragen, ob der Timer abgelaufen ist:
if ( Blinkzeit.expired() ) { //schalte Led ab }
Gegebenenfalls kannst Du da auch die Zeit wieder neu aufziehen, um den Zyklus neu zu starten damit es auch zyklisch blinkt. Schau dir mal die Beispiele zum Timer in der Lib an.

Auch dein loop() ist durch die while-Schleifen blockierend aufgebaut. Auch das solltest Du auflösen, dann geht das mit dem Blinken auch einfacher.

P.S. So ganz habe ich auch noch nicht verstanden, wie das Ganze letztendlich ablaufen soll.

Es ist sehr hilfreich
Vielen Dank

Konzept: Überwachung eines Schrittmotors über Led_ control

Ablauf-Programm

1.Eingabe über Serial Monitor: enthält Informationen von Led_number und Steps_number im Format: 1: 200, 5: 300, 4: 700 (Led _ blinkt, wenn der Motor die eingegebenen Schritte erreicht hat -> Led_1 blinkt bei 200 steps ,LED 5_ blinkt bei 300steps, LED4_ blinkt bei 700 steps).

2.Wenn die Eingabe gültig ist, läuft der Schrittmotor im Hintergrund in CW-Richtung. (In Richtung CW blinken die LEDs in absteigender Reihenfolge --> 1.Led_4 2.Led_5 3.led_1

3.Wenn der Motor die 500 Schritte erreicht hat(der Zähler beginnt bei 500 steps), blinkt die Led_ 4.

4.Mit Überwachung der Anzahl der Schritte des laufenden Motors, lassen sich led_5 und led_1 blinken, ( Led_5 wenn der Motor (1200-300) 900 Schritte erreicht, Led_1, wenn der Motor (1200-200) 1000 Schritte erreicht.

5.Wenn der Schrittmotor alle eingegebenen Schritte in CW richtung erreicht hat ( 500+700) und der Zähler der Motorschritte wieder auf 0 gesetzt ist (Zähler in CCW) beginnt bei 0 steps , läuft der Motor in CCW-Richtung (In Richtung CCW blinken die LEDs in aufsteigender Reihenfolge --> 1.Led_1 2.Led_5 3.led_4-

6.Wenn der Motor alle eingegebenen Schrittzahlen ( maxValue 700 steps) erreicht hat --> Motor Stop

Ich habe jetzt einen Text den ich auf englisch geschrieben habe 1:1 durch google-translate durchgeschoben. Das heißt die Grammatik ist nicht so doll
aber ich denke es wird troztdem verständlich
wie nichtblockierendes Timing funktioniert

als alltägliches Beispiel mit leicht verständlichen Zahlen
delay() blockiert. Solange die Verzögerung "verzögert", kann nichts anderes vom Code ausgeführt werden.
Jetzt gibt es eine Technik des nicht-blockierenden Timings.
Das Grundprinzip des nicht-blockierenden Timings unterscheidet sich grundlegend von der Verwendung von delay()

Sie müssen zuerst den Unterschied verstehen und dann in den Code schauen.

andernfalls könnten Sie versuchen, im millis()-Code ein "delay-analog-thing" zu "sehen", was es wirklich nicht ist
Der Versuch, in millis() ein "Verzögerungs-Analog-Ding" zu sehen, macht es schwer, millis() zu verstehen
Wenn man das Grundprinzip des blockierungsfreien Timings basierend auf millis() verstanden hat, ist es leicht zu verstehen.

Stellen Sie sich vor, Sie backen eine gefrostete Pizza
auf dem Deckel steht für die Zubereitung Backofen auf 200°C vorheizen
dann Pizza einlegen.
Backzeit 10 Minuten

Sie schätzen den Aufheizbedarf von 3 Minuten
Du schaust auf deine Uhr, es ist 13:02 (Zeitmoment)
Du fängst an, die Zeitung zu lesen und schaust ab und zu auf deine Uhr
Uhr zeigt 13:02. 13:02 - 13:02 = 0 Minuten verstrichen noch keine Zeit
Uhr zeigt 13:03. 13:03 - 13:02 = 1 Minute ist noch nicht vorbei
Uhr zeigt 13:04. 13:04 - 13:02 = 2 Minuten verstrichen noch keine Zeit

Sendungen ansehen 13:05 Wann habe ich um 13:02 angefangen? OK 13:05 - 13:02 = 3 Minuten Zeit um die Pizza in den Ofen zu schieben

Neue Basiszeit 13:05 (die Momentaufnahme der Zeit)
Uhr 13:06 noch keine Zeit
Uhr 13:07 noch keine Zeit
13:08 Uhr noch keine Uhrzeit ansehen (13:08 - 13:05 Uhr = 3 Minuten sind weniger als 10 Minuten
Uhr 13:09 noch keine Zeit
13:10 Uhr noch nicht Zeit
Uhr 13:11 noch nicht Zeit
Uhr 13:12 noch nicht Zeit
Uhr 13:13 noch nicht Zeit
13:14 Uhr noch keine Uhrzeit ansehen (13:14 - 13:05 Uhr = 9 Minuten sind weniger als 10 Minuten
Uhr 13:15 wann habe ich angefangen 13:05 OK 13:15 - 13:05 = 10 Minuten Zeit um Pizza zu essen (lecker lecker)

Du hast wiederholt verglichen, wie viel Zeit vergangen ist
Dies ist, was nicht blockierendes Timing bewirkt

Im Code ist der Blick auf "Wie viel Zeit vergangen ist" erledigt

currentTime - startTime >= Backzeit

Backzeit beträgt 10 Minuten

13:06 - 13:05 = 1 Minute >= Backzeit ist falsch
13:07 - 13:05 = 2 Minuten >= Backzeit ist falsch
...
13:14 - 13:05 = 9 Minuten >= Backzeit ist falsch
13:15 - 13:05 = 10 Minuten >= Backzeit ist TRUE Zeit für zeitgesteuerte Aktion!!

Also tut Ihre Schleife ()

Leere Schleife ()
// alle möglichen Sachen machen, wie zum Beispiel die Zeitung lesen

if (currentTime - previousTime >= period) {
vorherigeZeit = aktuelleZeit; // Das erste, was Sie tun müssen, ist die Momentaufnahme der Zeit zu aktualisieren
// Zeit für zeitgesteuerte Aktion
}

es muss genau so codiert werden, weil es auf diese Weise den Rollover von Max zurück auf Null verwaltet
der Funktion millis() automatisch

baldengineer.com hat auch ein sehr gutes Tutorial zum Timing mit der Funktion millis() .

Es gibt einen Absatz, der den Unterschied zwischen den Funktionen delay() und millis() auf den Punkt bringt:

Die Funktion millis() ist eine der mächtigsten Funktionen der Arduino-Bibliothek. Diese Funktion gibt die Anzahl der Millisekunden zurück, die der aktuelle Sketch seit dem letzten Zurücksetzen ausgeführt wurde. Zuerst denkst du vielleicht, das ist nicht alles sinnvoll! Aber bedenken Sie, wie Sie die Uhrzeit tagsüber angeben. Effektiv sehen Sie sich an, wie viele Minuten seit Mitternacht vergangen sind. Das ist die Idee hinter millis()!

Anstatt wie bei delay() „eine bestimmte Zeit zu warten“, können Sie millis() verwenden, um zu fragen, „wie viel Zeit vergangen ist“?

1 Like

Stell Dir vor, sowas haben sich ganz schlaue Leute ohne Translate und grammatikalisch schick als Nachtwächtererklärung ausgedacht...

Warum das Rad immer wieder neu erfunden werden muss...

muss es nicht. Das ist doch prima das du diesen Link gepostet hast.
Bisher habe ich immer nur so Kurzhinweise auf BWD-Beispiele gelesen.
Habe ich den bookmarks hinzugefügt.

vgs

dann den auch noch - in der Kurzfassung:
Theseus erklärt millis()

@Foufou : Du solltest dein Programm auf alle Fälle mal schrittweise neu aufbauen.
Wenn ich mir das ansehe, kann das noch nie halbwegs ordentlich gelaufen sein, weil da prinzipielle Fehler drin sind ( nicht syntaktisch, aber semantisch).
Das Einschalten der Compiler Warnungen kann auch sehr hilfreich sein. Du verwechselst ein paar mal '==' und '=' und auch deine Pointerverwendung passt nicht immer. Da macht dich der Compiler mit Warnungen drauf aufmerksam. Die Verwendung von Pointern ist auch recht fehleranfällig. Wo es nicht notwendig ist, sollte man darauf verzichten. Da z.B. led_array und steps_array global definiert sind, macht es wenig Sinn in 'auswerten' per Pointer darauf zuzugreifen - und dann noch mit identischen Namen.
Ebenso zum debuggen Ausgaben auf den seriellen Monitor einbauen.

Also schrittweise deine Funktionen testen ( mit Serial.print ), und erst wenn eins funktioniert weitermachen. Beginnen mit dem Einlesen und Auswerten vom seriellen Monitor. Dann lernen wie man eine Led blinken lässt, ohne den Ablauf zu blockieren ( Beispiele in den MobaTools). Und ganz zum Schluß das ganze mit dem Stepper kombinieren. Und immer erst wenn ein Schritt komplett funktioniert zum nächsten gehen und erweitern.

Und bei dem schrittweisen Neuaufbau kannst Du gleich die oben angegebenen Tips zum blockadefreien Programmieren beherzuigen. Auch wenn Du die Timer der MobaTools verwendest musst Du dieses Prinzip der blockadefreien Programmierung einhalten.

1 Like