kleine State Machine

Hi :smiley:

So, Ich habe schon seit einiger Zeit nicht mehr programmiert und wollte nun ein kleines Programm f√ľr eine Requisite schreiben die ich gebaut habe.

Der Code ist noch nicht fertig, und die FSM auch nicht. Dennoch sollte zumindest irgendetwas funktionieren, und das bekomme ich nicht hin :-/

Es wäre sehr nett wenn sich jemand eben meinen kurzen Code anschauen könnte, ich finde den fehler einfach nicht.

Achja

Irgendwie hängt er in einem der States und die Buttons machen nix ^^

In dem angehängten Bild ist meine Verkabelung :smiley:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIXELOUT 0
#define BUTTON1 1
#define BUTTON2 2

int Modus = 3;
int state1 = LOW;
int laststate1 = LOW;
int state2 = LOW;
int laststate2 = LOW;



// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
Adafruit_NeoPixel strip = Adafruit_NeoPixel(20, PIXELOUT, NEO_GRB + NEO_KHZ800);


void setup() {
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  
  pinMode(BUTTON1, INPUT);
  pinMode(BUTTON2, INPUT);
  digitalWrite(BUTTON1, HIGH);
  digitalWrite(BUTTON2, HIGH);


  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
 
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

 state1 = digitalRead (BUTTON1);
 state2 = digitalRead (BUTTON2);
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 0) {
    Modus=1;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 1) {
    Modus=0;
 }
 
 if(laststate2 == LOW && state2 == HIGH && Modus == 0) {
 Modus=2;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 2) {
    Modus=3;
 }
 
 if(laststate2 == LOW && state2 == HIGH && Modus == 2) {
    Modus=4;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 3) {
    Modus=5;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 5) {
    Modus=2;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 4) {
    Modus=0;
 }
 
 
 switch(Modus){
 case 0: 
 break;
 
 case 1: //Light
 colorWipe(strip.Color(255, 255, 255), 50);
 break;
 
 case 2: //heal1
 colorWipe(strip.Color(255, 0, 0), 50);
 //theaterChase(strip.Color(255, 0, 0), 50); // Red
 break;
 
 case 3: //heal2
 colorWipe(strip.Color(0, 255, 0), 50);
 //theaterChase(strip.Color(0, 0, 255), 50); // Blue
 break;
 
 case 4: //research
 colorWipe(strip.Color(0, 0, 255), 50);
 //rainbowCycle(20);
 break;
 
 case 5: //heal3
 colorWipe(strip.Color(0, 255, 255), 50);
 //theaterChase(strip.Color(0, 255, 0), 50); // Blue
 break;
 }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}


void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Unbenannt.PNG

Du solltest schon schreiben, was der Sketch machen soll und welchen Fehler der Sketch hat.
Woher sollen wir sonst wissen, nach was wir suchen sollen.

Zudem ist der Sketch völlig undokumentiert und damit schwer zu lesen.
Wo ist der her ?

Oh tut mir leid, im eifers des Gefechts vergessen.

Ich möchte mit Button1 und Button2 in verschiedene Modi/States wechseln die die Neopixel unterschiedliche leuchten lassen.

In die unterschiedlichen States kann nur gewechselt werden wenn eine Flanke an einem der Buttons ist.

Ich habe gerade unten im loop noch laststate1 = state1; laststate2 = state2; hinzugef√ľgt. hatte ich ganz vergessen. Das sind die Flankenabfragen.

Die Funtionen unter dem Loop sind einfach nur die Beispiele die es in der Neopixel library gibt, alles was dar√ľber steht habe ich selber geschrieben.

Ein teil des Sketch stammt aus einem Beispiel der Adafruit Neopixel-Lib. Dazu hat er 2 Buttons hinzugef√ľgt, mit denen er die verschidenen Leuchtmuster, die das Beispiel normalerweise hintereinander abspielt, aufzurufen versucht.
Aber trotzdem muss er uns sagen, was denn nicht funktioniert.

LG Stefan

ja lordgort,

Welchen Fehler?
Bekommst Du irgendeine Fehlermeldung?
Kannst Du den Sketch kompilieren?
Kannst Du den Sketch auf Dein Board hochladen?
Funktioniert der einfache Blink-Sketch auf Deinem Board?

Du musst uns etwas genauer sagen, was funktioniert und was nicht, sonst wird das ein ganz grosses r√§tselraten f√ľr uns und es wird sehr schwer bis fast unm√∂glich, Dir zu helfen.

LG Stefan

Da sind zu viele blockierende for-Schleifen mit jeweils delays drin. Da hat kein Taster eine Chance zeitnah abgefragt zu werden.

Gruß Tommy

Du solltest deinen Sketch erst mal aufräumen.

Da sehe ich massig Funktionen, die nicht aufgerufen werden.

Warum willst du uns so aufs Glatteis f√ľhren ?

Du hast nat√ľrlich vollkommen recht. Tut mir leid, ich schreib zu wenig in Foren und hab einfach nicht daran gedacht das jemand anders sich erstmal in den code reindenken muss.

Wenn ich jetzt den Strom einschalte leuchten sofort alle Pixel Gr√ľn. Die Buttons haben keinen effekt.

Button 1 soll von Modus 0 nach Modus 1 und dann wieder nach Modus 0 schalten.

Button 2 schaltet von Modus 0 nach Modus 2 und nach weiterem dr√ľcken nach Modus 4.

Von Modus 4 komme ich mit Button 1 wieder nach Modus 0.

Vom Modus 2 kann ich noch mit Button 1 in den Modus 3 und danach ebenfalls mit dem Button 1 in dem Modus 5 (Sackgasse).

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIXELOUT 0
#define BUTTON1 1
#define BUTTON2 2

int Modus = 0;
int state1 = LOW;
int laststate1 = LOW;
int state2 = LOW;
int laststate2 = LOW;



// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
Adafruit_NeoPixel strip = Adafruit_NeoPixel(20, PIXELOUT, NEO_GRB + NEO_KHZ800);


void setup() {

  #if defined (__AVR_ATtiny85__) //Trinket initialisierung (vorgegeben)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  
  pinMode(BUTTON1, INPUT); //Button initialisierung
  pinMode(BUTTON2, INPUT);
  digitalWrite(BUTTON1, HIGH);
  digitalWrite(BUTTON2, HIGH);


  strip.begin();
  strip.show(); // Initialize all pixels to 'off' //Neopixel initialisierung
 
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

 state1 = digitalRead (BUTTON1); //Buttonabfrage
 state2 = digitalRead (BUTTON2);
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 0) { //Im letzten Loop Button nicht gedr√ľckt und jetzt gedr√ľckt und Modus=0?
    Modus=1; //Dann schalte in Modus 1
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 1) {
    Modus=0;
 }
 
 if(laststate2 == LOW && state2 == HIGH && Modus == 0) {
 Modus=2;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 2) {
    Modus=3;
 }
 
 if(laststate2 == LOW && state2 == HIGH && Modus == 2) {
    Modus=4;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 3) {
    Modus=5;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 5) {
    Modus=2;
 }
 
 if(laststate1 == LOW && state1 == HIGH && Modus == 4) {
    Modus=0;
 }
 
 
 switch(Modus){
 case 0:  //nach dem Einschalten werden keine Pixel aktiviert
 break;
 
 case 1: //Light
 colorWipe(strip.Color(255, 255, 255), 1); //alle Pixel sollen weiß leuchten
 break;
 
 case 2: //heal1
 colorWipe(strip.Color(255, 0, 0), 1); //alle Pixel sollen rot leuchten
 break;
 
 case 3: //heal2
 colorWipe(strip.Color(0, 255, 0), 1); //alle Pixel sollen gr√ľn leuchten
 break;
 
 case 4: //research
 colorWipe(strip.Color(0, 0, 255), 1); //alle Pixel sollen blau leuchten
 break;
 
 case 5: //heal3
 colorWipe(strip.Color(0, 255, 255), 1); //alle Pixel sollen cyan leuchten
 break;
 }

laststate1 = state1; 
laststate2 = state2; //hier wird der Buttonstatus der Taster f√ľr den n√§chsten n√§chsten loop zwischengespeichert um zu sehen ob eine Flanke auftritt

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////


//Diese Funktionen sind aus einem Neopixel Beispiel von Adafruit

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

Eigentlich ist der Aufbau nicht so schlecht, enth√§lt aber drei ungl√ľckliche Punkte:

  • Ein delay() mit Tasteneingaben harmoniert nicht (siehe #5).
  • Tasten m√ľssen entprellt werden.
  • Die Abfrage der Flanken ist gut, die auswertenden Bedingungen machen sich aber reilweise wieder r√ľckg√§ngig, da fehlt else.

So ver√§ndert l√§uft der Sketch f√ľr den UNO. Ob die Logik stimmt und alle Modi erreicht werden, habe ich nicht √ľberpr√ľft. Auf jeden Fall sieht man verschiedene Farben. Ich habe nur neun NeoPixel (siehe Avartar), da ich APA102 (DotStar) bevorzuge.

#include <Adafruit_NeoPixel.h>
#define PIN            6    // Data am ArduinoPin
#define NUMPIXELS      9    // Anzahl der LEDS
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);

#define BUTTON1 2
#define BUTTON2 3

byte wipeLed = 0, Modus = 0;
bool state1 = LOW;
bool laststate1 = LOW;
bool state2 = LOW;
bool laststate2 = LOW;
uint32_t aktMillis, buttonMillis;

void setup() {
  pinMode(BUTTON1, INPUT_PULLUP); //Button initialisierung
  pinMode(BUTTON2, INPUT_PULLUP);

  strip.begin();
  strip.setBrightness(50);
  strip.show(); // Initialize all pixels to 'off' //Neopixel initialisierung
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  aktMillis = millis();
  laststate1 = state1;
 ¬†laststate2 = state2; //hier wird der Buttonstatus der Taster f√ľr den n√§chsten n√§chsten loop zwischengespeichert um zu sehen ob eine Flanke auftritt
  if (aktMillis - buttonMillis >= 30) { // zum Entprellen
    state1 = digitalRead (BUTTON1); //Buttonabfrage
    state2 = digitalRead (BUTTON2);
  }

 ¬†if (laststate1 == LOW && state1 == HIGH && Modus == 0) { //Im letzten Loop Button nicht gedr√ľckt und jetzt gedr√ľckt und Modus=0?
    Modus = 1; //Dann schalte in Modus 1
    wipeLed = 0;
  } else if (laststate1 == LOW && state1 == HIGH && Modus == 1) {
    Modus = 0;
    wipeLed = 0;
  } else if (laststate2 == LOW && state2 == HIGH && Modus == 0) {
    Modus = 2;
    wipeLed = 0;
  } else if (laststate1 == LOW && state1 == HIGH && Modus == 2) {
    Modus = 3;
    wipeLed = 0;
  } else if (laststate2 == LOW && state2 == HIGH && Modus == 2) {
    Modus = 4;
    wipeLed = 0;
  } else if (laststate1 == LOW && state1 == HIGH && Modus == 3) {
    Modus = 5;
    wipeLed = 0;
  } else if (laststate1 == LOW && state1 == HIGH && Modus == 5) {
    Modus = 2;
    wipeLed = 0;
  } else if (laststate1 == LOW && state1 == HIGH && Modus == 4) {
    Modus = 0;
    wipeLed = 0;
  }

  switch (Modus) {
    case 0:  //nach dem Einschalten werden keine Pixel aktiviert
      colorWipe(strip.Color(0, 0, 0), 100); //alle Pixel aus
      break;

    case 1: //Light
      colorWipe(strip.Color(255, 255, 255), 100); //alle Pixel sollen weiß leuchten
      break;

    case 2: //heal1
      colorWipe(strip.Color(255, 0, 0), 100); //alle Pixel sollen rot leuchten
      break;

    case 3: //heal2
 ¬† ¬† ¬†colorWipe(strip.Color(0, 255, 0), 100); //alle Pixel sollen gr√ľn leuchten
      break;

    case 4: //research
      colorWipe(strip.Color(0, 0, 255), 100); //alle Pixel sollen blau leuchten
      break;

    case 5: //heal3
      colorWipe(strip.Color(0, 255, 255), 100); //alle Pixel sollen cyan leuchten
      break;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  static uint32_t wipeMillis = aktMillis;
  if ((aktMillis - wipeMillis >= wait) && (wipeLed < strip.numPixels())) {
    wipeMillis = aktMillis;
    strip.setPixelColor(wipeLed, c);
    strip.show();
    wipeLed++;
  }
}

Anmerkung f√ľr Fortgeschrittene: Die globale Verwendung von wipeLed gef√§llt mir nicht, aber ich komme gerade auf keine bessere L√∂sung :-[

Danke dir :smiley:
das mit dem entprellen hat mir ein Problem weniger beschert.

Ich musste in der Bedingungen noch √ľberall else if schreiben, sonst konnten sich die Zust√§nde im gleichen loop mehrmals √§ndern.

außerdem konnte ich den pin2 nicht als Eingang nutzen... irgendwie nur als Ausgang

Auf jedenfall geht es jetzt.

Ich danke allen die mir helfen wollten oder geholfen haben :smiley: ihr seit super