SOLVED: Servo geht nicht in switch - case Anweisung

Hallo,
ich versuche seit Stunden den Fehler zu finden ....
Ich arbeite an einem Programm für einen Piezo Klopf Sensor. Wenn der richtige Code geklopft wird, soll ein Servo ein Schloss freigeben. Der Servo funktioniert und wird im setup einmal hin- und her gefahren. Wenn der richtige Code erkannt wird, bewegt sich der Servo allerdings nicht. Dass Programm durchläuft den Programmteil, das sehe ich an der seriellen Ausgabe.

Hier das komplette Programm

#include <Servo.h>

/* Piezo Klopf Sensor - Piezo mit R=10k und C=10n parallel an A0 *
 Empfindlichkeit mir AnalogReadSerial ausprobieren */

Servo myservo;  

int state=0;
int knocks;
byte code=0b110000;
byte testcode;
unsigned long startm, startl;
unsigned long dauer;
unsigned int duration[6];

void setup() {
  Serial.begin(115200);
  Serial.println("Knock Sensor detect");
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  myservo.write(0);          // test servo  
  delay(800);  
  myservo.write(180);   // Ausgangsposition
}

void loop() {
  switch (state) {
  case 0:    // initial loop for first detection
    if ((millis()-startm)>2000){
      knocks=0;
    }
    if (analogRead(A0)>50) {
      while (analogRead(A0)>10) {
      }
      startl=startm;
      startm=millis();
      /*      Serial.print("Knock ");
       Serial.print(knocks);
       Serial.print(" erkannt - ");
       Serial.print(startm-startl);
       Serial.println(" Pause");*/
      duration[knocks]=startm-startl;
      knocks++;
      if (knocks>=7) {
        state=1;
        knocks=0;
      } 
    }
    break;

  case 1:    // detect knocks and check if valid
    int groesster = 0;
    int kleinster = 1023;
    for (int i=1;i<=6;i++) {
      if (duration[i]>groesster) groesster=duration[i];
      if (duration[i]<kleinster) kleinster=duration[i];
      Serial.print(duration[i]);
      Serial.print("\t");
    }
    Serial.println();
    Serial.print(kleinster);
    Serial.print("\t");
    Serial.println(groesster);
    int kleinster_plus=kleinster+(kleinster>>2);
    int groesster_minus=groesster-(groesster>>2);
    Serial.print(kleinster_plus);
    Serial.print("\t");
    Serial.println(groesster_minus);
    for (int i=1;i<=6;i++) {   // 1=lang, 0=kurz
      if (duration[i]==groesster) Serial.print("i");
      else if (duration[i]==kleinster) Serial.print("o");
      else if (duration[i]>=groesster_minus) Serial.print("1");
      else if (duration[i]<=kleinster_plus) Serial.print("0"); 
    }
    Serial.println();
    for (int i=1;i<=6;i++) {   // 1=lang, 0=kurz
      testcode <<= 1;
      if (duration[i]==groesster) testcode |= 0b00000001;
      else if (duration[i]==kleinster) testcode &= 0b1111110;
      else if (duration[i]>=groesster_minus) testcode |= 0b00000001;
      else if (duration[i]<=kleinster_plus) testcode &= 0b1111110; 
    }
    Serial.println(testcode,BIN);
    Serial.println();
    if (testcode==code) {
      myservo.write(0);          // open
      Serial.println("Safe open");
      delay(800);  
      myservo.write(180);   // close
      delay(1000); 
    }
    state=0;
    break;
  } 
}

Die Stelle, wo der Servo sich nicht bewegt ist

    if (testcode==code) {
      myservo.write(0);          // open
      Serial.println("Safe open");
      delay(800);  
      myservo.write(180);   // close
      delay(1000); 
    }

Wie gesagt: die Ausgabe "Safe open" wird seriell ausgegeben

Wer weiß Rat ?

Gruß
Reinhard

Hallo,

habe neue Erkenntnisse, die mich aber eher verwirren, als weiterbringen.
Um zu prüfen, ob der Servo "attached" ist habe ich an verschiedenen Stellen des Programms den Befehl Serial.println(myservo.attached()); ausgeben lassen.
Solange das Programm in der "case 0" Schleife ist, ist der Servo "attached". Wenn das Programm 7 Klopfer erkannt hat und in die case 1 Schleife gewechselt wird ist der Servo "not attached".

      if (knocks>=7) {
        state=1;   // Auswertung
        knocks=0;
      } 
    }
    Serial.print("case 0 ");  
    Serial.println(myservo.attached());  
    break;

Vor dem Übergang wechselt der Zustand myservo.attached().

case 0 1
case 0 0
0
553	536	283	282	42	232	
42	553
52	415
i1o
110000

0
Safe open

Ich versteh das nicht - Ihr ?

Gruß
Reinhard

Würde sagen ein typisches Dingsda-Problem mit Arrays.

unsigned int duration[6];
...
if (analogRead(A0)>50) {
      ...
      startl=startm;
      startm=millis();
      ...
      duration[knocks]=startm-startl;
      knocks++;
      if (knocks>=7) {
        state=1;
        knocks=0;
      } 
    }

Du benutzt einen Index der größer gleich als 7 werden kann ( 8 Array-elemente) bei einem Array das 6 Elemente groß ist. Du überschreibst so das Ram nach dem Array und bringst die Variablen die dort hinterlegt sind durcheinander.

In diesem Fall produziert ein Sketch die tollsten unlogischsten Fehler. Ich hatte mal einen solchen Fehler da funktionierte eine for Schleife nicht und nach einfügen eine Serial.Print(); ging alles.

Mache das Array größer und kontrolliere ob der Index nie größer ist.

Auch verstehe ich nicht wieso Du bei Index 1 startest:

for (int i=1;i<=6;i++) {
      if (duration[i]>groesster) groesster=duration[i];
      if (duration[i]<kleinster) kleinster=duration[i];
      Serial.print(duration[i]);
      Serial.print("\t");
    }

ein unsigned int duration[6]; Array geht von duration[0] bis duration[5].

Grüße Uwe

Oh Mann Uwe, du bist der Held !

ich hatte vermutet, dass es ein "doofer Fehler" ist, habe aber habe den Wald vor lauter ... du weißt schon.
Index vergrößert und alles funktioniert.

Auch verstehe ich nicht wieso Du bei Index 1 startest:

Der erste Wert mit Index 0 wird gespeichert, wurde anfangs mal ausgegeben, aber nun nicht weiter verwendet. Das kommt davon, wenn man bei der Entwicklung des Programms "toten Code" stehen lässt und nicht optimiert. Aber danke für den Tip.

ein unsigned int duration[6]; Array geht von duration[0] bis duration[5].

Wahrscheinlich hab' ich Depp gedacht "geht von 1 bis 6 plus 0 sind 7 Elemente" .

Vielen Dank, der Tag ist gerettet
Reinhard

Ja, Diese naturbelassenen Wälder kenne ich ...
Gut, daß ich Dir helfen konnte.
Schönen Sonntag
Uwe