Mal wieder ein Problem !

ich finde den fehler nicht !
hier erstmal mein programm :

#define STEPS_COUNT 8
int stepsOn1[STEPS_COUNT] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
int stepsOn2[STEPS_COUNT] = {HIGH, LOW,  HIGH, LOW,  HIGH, LOW,  HIGH,  LOW};
int stepsOn3[STEPS_COUNT] = {HIGH, LOW,  LOW,  LOW,  HIGH, LOW,  LOW,   LOW};
int stepsOn4[STEPS_COUNT] = {HIGH, LOW,  LOW,  LOW,  LOW,  LOW,  LOW,   LOW};
int stepsOn5[STEPS_COUNT] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH,  HIGH};
int stepsOn6[STEPS_COUNT] = {HIGH, LOW,  HIGH, LOW,  HIGH, LOW,  HIGH,  LOW};
int stepsOn7[STEPS_COUNT] = {HIGH, LOW,  LOW,  LOW,  HIGH, LOW,  LOW,   LOW};
int stepsOn8[STEPS_COUNT] = {HIGH, LOW,  LOW,  LOW,  LOW,  LOW,  LOW,   LOW};

int stepsOff[STEPS_COUNT] =  {LOW,  LOW,  LOW,  LOW,  LOW,  LOW, LOW,   LOW};

int stepCounter = 0;
bool firstRun = true;

long previousMillis = 0;
long interval = 100;

int clockIn = 3;
int greenLed = 12;


//--------------------------------------------------------------------------
void setup(){
  
    pinMode(greenLed, OUTPUT);
    pinMode(clockIn, INPUT);


}


//--------------------------------------------------------------------------
void loop(){
  
    
      if(digitalRead(clockIn) == HIGH && firstRun) {
            previousMillis = millis();  
            digitalWrite(greenLed, stepsOn1[stepCounter]);
            firstRun = false;
      }

            
      if((millis() - previousMillis > interval) && !firstRun) {
            //previousMillis = millis();  
            digitalWrite(greenLed, stepsOff[stepCounter]);}
            
               if(digitalRead(clockIn) == LOW){
                  firstRun = true;
                  }
               
      
          stepCounter = (++stepCounter);
          if(stepCounter >= 8) {
          delay(2000);
          stepCounter = 0;
          } 
      
}

an clockIn=3 hängt ein NE555 der mir die clock macht.
doch leider funktioniert das ganze nicht so wie es soll.
meine greenLed leuchtet im 2 sekunden-takt.
also durch meine delay(2000).
ich gehe mal davon aus das meine bedingungen nicht richtig sind und :

               if(digitalRead(clockIn) == LOW){
                  firstRun = true;
                  }

nicht zum richtigen zeitpunkt angenommen wird.
ich möchet das die erste if bedingung ausgeführt wird und greenLed leuchtet.
durch die zweite if bedingung wird sie wieder ausgeschaltet und soll dann warten bis die clock ein low-signal gibt um den nächsten schritt durchzuführen.

wo ist mein denkfehler ?
ich hoffe, ihr könnt mir auf die sprünge helfen.
danke schon mal im voraus !

Ein moeglicher fehler modus ist folgender:

Das 'interval' ist kleiner als die on-zeit deines rechtecksignals (auch nur geringfuegig). Ist dies der fall, dann ist die bedingung 'clockin == LOW' natuerlich nicht erfuellt. Die loop() rauscht dann schnellstmoeglich mehrmals durch, bis dein counter ueberlaeuft und das delay(2000) zuschlaegt.

Das ist richtig, der interval ist kürzer als das pulssignal.
Mein versuch war es ja das pulssignal als trigger zu nutzen um die befehle auszuführen.
Ist das pulssignal HIGH, soll :
digitalWrite(greenLed, stepsOn1[stepCounter]
ausgeführt werden.
Die zweite if-bedingung bewirkt wie lange die led leuchtet.
Um auf den nächsten HIGH-impuls zu warten habe ich die :

if(digitalRead(clockIn) == LOW {
    FirstRun = true;
    }

Bedingung geschrieben.
Aber so wie es aussieht bin ich da auf dem holzweg.
Nur hab ich immer noch nicht kappiert wo mein denkfehler ist.
Wird nachdem die ersten beiden if-bedingungen abgearbeitet sind nicht auf das clockIn==LOW gewartet ?

Warum sollte das so sein :wink:

Folgendes prograemmchen laesst eine LED nur an den flanken eines rechtecksignals blinken und dann an oder aus.

void setup() {
  pinMode(13,OUTPUT);
  pinMode(8,INPUT);
  digitalWrite(8,HIGH); // pull-up on
}

bool firstRun = true;

void loop() {
 if(digitalRead(8) == HIGH && firstRun) {
   digitalWrite(13, LOW);
   delay(120);
   digitalWrite(13, HIGH);
   delay(120);
   digitalWrite(13, LOW);
   firstRun = false;
 }
 if(digitalRead(8) == LOW && !firstRun) {
   digitalWrite(13, HIGH);
   delay(120);
   digitalWrite(13, LOW);
   delay(120);
   digitalWrite(13, HIGH);   
   firstRun = true;
 }
}

Erst wenn :

               if(digitalRead(clockIn) == LOW){
                           firstRun = true;
                  }

wird firstRun auf true gesetzt.
Erst dann sollte der nächste durchlauf des loops starten.
Aber so wie es aussieht steckt der fehler in meiner programmstruktur/ablauf.
:~

Wenn ich ganz ehrlich bin, werde ich nicht ganz schlau aus deinem beispiel-code.
Bei meinem code soll die led ja schon vor dem nächsten LOW-impuls ausgehen.

Vielleicht solltest du erst einmal in worten exakt klarstellen, was dein code ueberhaupt machen soll. Bei einem rechtecksignal gibt es ja mehr als eine stelle, an der etwas passieren koennte. Und das dein code nicht auf einen low pegel wartet ist vollkommen klar, weil davon nichts drinnen steht.

loop() laeuft immer. Wenn du das nicht willst, musst du ihn explizit warten lassen. Wobei das blosse warten ziemlich sub-optimal ist, weil in der zeit nichts anderes mehr getan werden kann.

Im idealfall pruefst du in der hauptschleife, ob bestimme bedingungen erfuellt sind und handelst danach. Wenn nichts zutrifft kannst du etwas anderes machen lassen. Deine logik muss also jeden moeglichen fall abbilden und entsprechend handeln.

eldopa:
Die zweite if-bedingung bewirkt wie lange die led leuchtet.
Um auf den nächsten HIGH-impuls zu warten habe ich die :

if(digitalRead(clockIn) == LOW {

FirstRun = true;
   }



Bedingung geschrieben.
Aber so wie es aussieht bin ich da auf dem holzweg.
Nur hab ich immer noch nicht kappiert wo mein denkfehler ist.
Wird nachdem die ersten beiden if-bedingungen abgearbeitet sind nicht auf das clockIn==LOW gewartet ?

Weil if eben nicht wartet, sondern nur entscheidet, ob die Bedingung erfüllt ist oder nicht. Du könntest z. B: eine Warteschleife einbauen

while (digitalRead(clockIn) == LOW) {
    // do nothing
    }

wobei ja madworm schon darauf hingewiesen hat, dass das suboptimal ist, weil dadurch nichts anderes passieren kann.
Wenn du das nicht willst, dann musst du die Bedingungen eben genauso formulieren, dass loop() zwar immer wieder läuft, aber es eben keien andere Alternative gibt, die ausgeführt wird.

Rudi

PS: Und das Problem genau beschreiben, ist immer gut :slight_smile:

ich hab noch mal einige andere sachen ausprobiert, wo ich dachte das sie richtig sind.
aber denkste,.. nix geht weiter.

also ich beschreib noch mal was ich genau machen will :

ich habe einen NE555 der mir ein clocksignal an clockIn=3 sendet.
wenn ich an dem clockIn ein HIGH habe, möchte ich das durch

digitalWrite(greenLed, stepsOn1[stepCounter]);

die led leuchtet und dann durch

if(millis() - previousMillis > interval) { 
 digitalWrite(greenLed, stepsOff[STEPS_COUNT]);

wieder ausgeschaltet wird.
beim nächsten durchlauf soll natürlich stepCounter um 1 erhöht werden und das gleich läuft wieder durch bis stepCounter bei 8 gelandet ist. dann kommt das delay(2000) und dann das ganze wieder von vorn.

mein gedankengang war so, das wenn an clockIn ein HIGH anliegt sollte das so aussehen :

if(digitalRead(clockIn) == HIGH && firstRun) {
            previousMillis = millis();  
            digitalWrite(greenLed, stepsOn1[stepCounter]);
      
          if((millis() - previousMillis > interval) && !firstRun) { 
            digitalWrite(greenLed, stepsOff[stepCounter]);
            firstRun = false;}

da ja clockIn immer noch HIGH ist, habe ich firstRun eingebaut damit dieser schritt nicht nochmal ausgeführt wird und eingentlich nix passiert.
bis durch ein LOW signal an clockIn :

               if(digitalRead(clockIn) == LOW){
                  firstRun = true;
                  }

firstRun wieder true ist und beim nächsten HIGH alles von vorn beginnt.
(ok, ich herausgefunden das dieser teil nicht funktioniert, aber warum nicht ?)

ich hoffe, das ist einigermaßen verständlich und ihr könnt mir auf die sprünge helfen.

Nichts in deinem code setzt dein gewuenschtes "bis durch" um, keine warteschleife, keine "immer noch high" logik.

In deinem code fehlt es schlicht und einfach an if( "immer noch HIGH" ) bzw. if( "noch nicht LOW" ).

Deine 2-te if-abfrage ist ja erst wahr, wenn eine gewisse zeit abgelaufen ist. Vorher ist der pegel immer noch HIGH (nicht LOW), daher geht die LED nicht sofort wieder aus (klar) UND weil das 3-te if auch noch nicht wahr ist, zaehlt der step-coutner quasi sofort hoch bis zum anschlag hoch.

JEDER moegliche zustand muss durch deine programm-logik abgebildet und abgefangen werden. Wenn keine if-abfrage zutrifft rutscht das programm bis zum ende durch und zaehlt hoch. Ganz normal.

Wenn etwas passieren oder nicht passieren soll / muss, dann muss das auch im code explizit und eindeutig representiert sein.

ich bin ein stück weiter gekommen.
nur hab ich etwas gemogelt und das ganze mit delay() gemacht.

void loop(){

  if(digitalRead(clockIn) == HIGH && firstRun) {

    digitalWrite(greenLed, stepsOn1[stepCounter]);
    delay(100);
    digitalWrite(greenLed, LOW);
    firstRun = false;
  }


  if(digitalRead(clockIn) == LOW && !firstRun) {
    firstRun = true;
    stepCounter = (++stepCounter);
  }  


  if(stepCounter >= 8) {
    delay(2000);
    stepCounter = 0; 
  } 
}

geht das in die richtung die du meinst madworm ?

ich hab natürlich auch versucht das ganze mit millis() zu schreiben aber das läuft nicht.
aber ich arbeite daran.

jetzt läuft es auch mit millis(), aber !

ich denke mal es ist zufall das es jetzt so aussieht als ob es laufen würde.
denn es ist wohl noch ein fehler drin.
erstmal den code, so wie er jetzt ist :

#define STEPS_COUNT 8
int stepsOn1[STEPS_COUNT] = {
  HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
int stepsOn2[STEPS_COUNT] = {
  HIGH, LOW,  HIGH, LOW,  HIGH, LOW,  HIGH,  LOW};
int stepsOn3[STEPS_COUNT] = {
  HIGH, LOW,  LOW,  LOW,  HIGH, LOW,  LOW,   LOW};
int stepsOn4[STEPS_COUNT] = {
  HIGH, LOW,  LOW,  LOW,  LOW,  LOW,  LOW,   LOW};
int stepsOn5[STEPS_COUNT] = {
  HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH,  HIGH};
int stepsOn6[STEPS_COUNT] = {
  HIGH, LOW,  HIGH, LOW,  HIGH, LOW,  HIGH,  LOW};
int stepsOn7[STEPS_COUNT] = {
  HIGH, LOW,  LOW,  LOW,  HIGH, LOW,  LOW,   LOW};
int stepsOn8[STEPS_COUNT] = {
  HIGH, LOW,  LOW,  LOW,  LOW,  LOW,  LOW,   LOW};

int stepsOff[STEPS_COUNT] =  {
  LOW,  LOW,  LOW,  LOW,  LOW,  LOW, LOW,   LOW};

int stepCounter = 0;
bool firstRun = true;

long previousMillis = 0;
long interval = 200;

int clockIn = 3;
int greenLed = 12;


//--------------------------------------------------------------------------
void setup(){

  pinMode(greenLed, OUTPUT);
  pinMode(clockIn, INPUT);


}


//--------------------------------------------------------------------------
void loop(){

  if(digitalRead(clockIn) == HIGH && firstRun) {

    digitalWrite(greenLed, stepsOn1[stepCounter]);
    previousMillis = millis(); 
    firstRun = false;
  }
  
    if((millis() - previousMillis > interval) && !firstRun) {
    digitalWrite(greenLed, LOW);
    
    }
  


  if(digitalRead(clockIn) == LOW && !firstRun) {
    firstRun = true;
    stepCounter = (++stepCounter);
  }  


  if(stepCounter >= 8) {
    delay(2000);
    stepCounter = 0; 
  } 

}

wenn ich jetzt :

    if((millis() - previousMillis > interval) && !firstRun) {
    digitalWrite(greenLed, LOW);

wieder so umschreibe wie ich es am anfang hatte :

    if((millis() - previousMillis > interval) && !firstRun) {
    digitalWrite(greenLed, stepsOff[STEPS_COUNT]);

läuft die ganze sache nicht mehr, was mich wundert, denn dort steht ja auch nur das greenLed auf LOW gesetzt wird.
ich wäre euch mal wieder danbar für einen tip !

digitalWrite(greenLed, stepsOff[STEPS_COUNT]);

Wie gross ist STEPS_COUNT ?

komischer weise laeuft es heute mit :

digitalWrite(greenLed, stepsOff[STEPS_COUNT]);

keine ahnung was ich anders gemacht habe.

trotzdem wuerde ich gern wissen ob der code :

void loop(){

  if(digitalRead(clockIn) == HIGH && firstRun) {

    digitalWrite(greenLed, stepsOn1[stepCounter]);
    previousMillis = millis(); 
    firstRun = false;
  }
  
    if((millis() - previousMillis > interval) && !firstRun) {
    digitalWrite(greenLed, stepsOff[stepCounter]);
    
    }
  


  if(digitalRead(clockIn) == LOW && !firstRun) {
    firstRun = true;
    stepCounter = (++stepCounter);
  }  


  if(stepCounter >= 8) {
    delay(2000);
    stepCounter = 0; 
  } 

}

so richtig ist, oder ob ich das auch anders haette schreiben koennen.
ich muss ehrlich zugeben das ich nicht zu 100% verstanden habe was ich da gemacht habe.
und da madworm auch noch mal nachgefragt hat

Wie gross ist STEPS_COUNT ?

bin ich etwas verunsichert !
da ich mit dem code noch weiter arbeiten will und noch ein paar funktionen dazu kommen, moechte ich mir sichersein das alles richtig ist und ich nicht spaeter noch fehler drin habe die sich erst mit anderen ablaeufen herausstellen.

Wenn du schon wegen der Frage nach STEPS_COUNT verunsichert bist, warum verrätst du uns den Wert nicht einfach? :slight_smile:

Ohne jetzt deine Code genau analysiert zu haben, fallen mir doch einige Dinge auf:

if(digitalRead(clockIn) == LOW && !firstRun) {
    firstRun = true;
    stepCounter = (++stepCounter);
  }

Was soll eigentlich die Zeile

    stepCounter = (++stepCounter);

bewirken?

Du erhöhst eine Variable und weist diesen erhöhten Wert der gleichen Variable wieder zu. Das ist bestenfalls unnötig und unsinnig, schlimmstenfalls ein Fehler, wenn du nämlich den erhöhten Inhalt von stepCounter einer ganz anderen Variablen zuweisen willst.

Wilst du nur stepCounter erhöhen, dann reicht

 ++stepCounter;

locker aus.
Und wenn du im obigen Code firstRun auf TRUE setzt, müsste dann nicht auch stepCounter zurück (auf 0) gesetzt werden?
Das passiert aber erst im folgenden Code:

  if(stepCounter >= 8) {
    delay(2000);
    stepCounter = 0; 
  }

Woher kommt plötzlich die ominöse Zahl 8?

Rudi

madworm:

digitalWrite(greenLed, stepsOff[STEPS_COUNT]);

Wie gross ist STEPS_COUNT ?

ok, muss natürlich :

digitalWrite(greenLed, stepsOff[stepCounter]

heißen.

danke für den hinweis :

stepCounter = (++stepCounter);

wird sofort geändert.

Woher kommt plötzlich die ominöse Zahl 8?

#define STEPS_COUNT 8
int stepsOn1[STEPS_COUNT] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};

mein STEP_COUNT array hat ja 8 werte und die sollen der reihe nach bei jedem neuen durchlauf des loops abgearbeitet werden,
und nach dem 8ten mal wieder von vorn beginnen.

Und wenn du im obigen Code firstRun auf TRUE setzt, müsste dann nicht auch stepCounter zurück (auf 0) gesetzt werden?

dann würde ja immer nur STEP_COUNT[1] ausgeführt werden, oder verstehe ich das falsch ?

Wenn Du schon für die 8 eine Definition anlegst (was ja sinnvoll ist), dann benutze diese aber auch durchgängig (sonnst macht es keinen Sinn).

  if(stepCounter >= STEPS_COUNT) {

Ein Grund der Definitionen ist ja, einen Wert nur an einer Stelle festzulegen um ihn leicht ändern zu können.
Der zweite Grund wäre noch, dass STEPS_COUNT aussagekräftiger ist als 8.

danke fuers draufhinweisen !

keine ahnung warum ich da die 8 wieder genommen habe.
mir fehlt halt noch die routine.