{{ :elektronik:simon_spiel:header.jpg?nolink&3000 |}} ===== Simon Spiel ===== Baustelle, noch nicht fertig :-) Da mir das programmieren von kleinen Spielen sehr Spaß macht, habe ich mal wieder etwas gesucht was man bauen könnte. Ich bin dann auf das Spiel Simon gekommen. Hierzu mal der Wikipedia-Eintrag: {{wp:de>Senso (Spiel)}} Hier mal ein Video von meiner provisorischen Variante:\\ {{:elektronik:simon_spiel:simon_video.mp4|}} ===== Aufbau ===== Ich habe mich dafür entschieden die Taster aus transparentem PLA zu drucken und in dem Taster eine RGB-LED zu intigrieren. Somit dient die Eingabe gleichzeitig auch als Anzeige. Als Taster habe ich Kurzhubtaster auf eine Platine gelötet. Im Nachhinein stellte sich das als nicht so Optimal heraus, da die mechanischen Anforderungen relativ hoch sind. So ist bei mir der Druckpunkt der Taster nicht wirklich schön und ich muss im richtigen Winkel drücken (sieht man auch im Video ganz gut). Andererseits ist das optische Ergebnis mit den RGB-LEDs und dem transparenten PLA echt super. Die WS2812B-LEDs habe ich in den Kunststoff eingedrückt, nachdem ich ihn über eine Heißluftpistole erwärmt habe. ===== Bilder ===== {{:elektronik:simon_spiel:simon_game.jpg?direct&300|}} \\ Zusammengebaut {{:elektronik:simon_spiel:simon_game_an.jpg?direct&300|}} \\ Angeschaltete LEDs {{:elektronik:simon_spiel:simon_game_an_rueckseite.jpg?direct&300|}} \\ Inhalt des Gehäuses {{:elektronik:simon_spiel:leds_platine.jpg?direct&300|}} \\ Platine mit LEDs {{:elektronik:simon_spiel:led.jpg?direct&300|}} \\ WS2812B-LED ===== Software ===== Es handelt sich hier um eines meiner ersten Projekte mit PlattformIO. Ich bereue es ehrlich gesagt, mich nicht schon früher damit beschäftigt zu haben. An externen Abhängigkeiten wird nur die Adafruit NeoPixel-Library verwendet. An sich ist die Software mit einer State-Machine als Programmsteuerung aufgebaut. Damit lässt sich so ein Ablauf sehr einfach realisieren. Es gibt diese vier Zustände: intro Startanimation fail Fehlerfall, warten auf Eingabe input Eingabe der gemerkten Farben show Vorspielen der neuen, zu merkenden Farben ==== Ablauf / Zustandsautomat ==== {{:elektronik:simon_spiel:Simon_Ablauf.svg?100x100&units:%|}} \\ ==== Quelltext ==== ++++ main.cpp | #include #define PIN_LED 2 #define NUMPIXELS 4 //LED-Key-Zuordnung const uint8_t key[] = { 4, A2, 12, 7 }; const uint8_t led[] = { 2, 3, 1, 0 }; Adafruit_NeoPixel pixels(NUMPIXELS, PIN_LED, NEO_GRB + NEO_KHZ800); //Funktion für LED aktiver/inaktiver Zustand void set_led(int l, bool state) { uint32_t colors_en[] = { pixels.Color(0, 255, 0), pixels.Color(255, 0, 0), pixels.Color(0, 0, 255), pixels.Color(255, 255, 0) }; uint32_t colors_dis[] = { pixels.Color(0, 50, 0), pixels.Color(50, 0, 0), pixels.Color(0, 0, 50), pixels.Color(25, 25, 0) }; if(state) { pixels.setPixelColor(led[l], colors_en[l]); } else pixels.setPixelColor(led[l], colors_dis[l]); pixels.show(); } void setup() { pixels.begin(); randomSeed(analogRead(0)+analogRead(1)+analogRead(3)+analogRead(4)); //Eingänge pinMode(key[0], INPUT); pinMode(key[1], INPUT); pinMode(key[2], INPUT); pinMode(key[3], INPUT); //Pullup digitalWrite(key[0], HIGH); digitalWrite(key[1], HIGH); digitalWrite(key[2], HIGH); digitalWrite(key[3], HIGH); } //Zustände enum { intro, fail, input, show }; int state = intro; int intro_ct = 50; int error_red_val = 255; uint8_t valuehistory[255]; uint8_t valuehistory_position = 0; unsigned long timer1 = millis(); void loop() { //Introanimation if(state == intro) { int i = random(4); set_led(0, i==0); set_led(1, i==1); set_led(2, i==2); set_led(3, i==3); delay(100); intro_ct--; if(intro_ct == 0) state = fail; } //Rot Blinken if(state == fail) { //Animation if(millis()-timer1 > 100) { error_red_val = (error_red_val==255) ? 50 : 255; timer1 = millis(); } for (uint8_t i = 0; i < 4; i++) { pixels.setPixelColor(i, pixels.Color(error_red_val, 0, 0)); } pixels.show(); //reset saved values valuehistory_position = 0; //Tansaktion if(!digitalRead(key[0])||!digitalRead(key[1])||!digitalRead(key[2])||!digitalRead(key[3])) { state = show; set_led(0, false); set_led(1, false); set_led(2, false); set_led(3, false); delay(1000); } } //Abspielen if(state == show) { valuehistory[valuehistory_position] = random(4); for (uint8_t i = 0; i <= valuehistory_position; i++) { set_led(0, valuehistory[i]==0); set_led(1, valuehistory[i]==1); set_led(2, valuehistory[i]==2); set_led(3, valuehistory[i]==3); delay(500); set_led(0, false); set_led(1, false); set_led(2, false); set_led(3, false); delay(500); } state = input; } //Eingabe if(state == input) { for(uint8_t i = 0; i <= valuehistory_position; i++) { while(digitalRead(key[0])&&digitalRead(key[1])&&digitalRead(key[2])&&digitalRead(key[3])); bool correct = (valuehistory[i]==0&&!digitalRead(key[0])) || (valuehistory[i]==1&&!digitalRead(key[1])) || (valuehistory[i]==2&&!digitalRead(key[2])) || (valuehistory[i]==3&&!digitalRead(key[3])); set_led(0, !digitalRead(key[0])); set_led(1, !digitalRead(key[1])); set_led(2, !digitalRead(key[2])); set_led(3, !digitalRead(key[3])); delay(500); set_led(0, false); set_led(1, false); set_led(2, false); set_led(3, false); if(correct) { state = show; delay(100); } else { state = fail; break; } } delay(1000); valuehistory_position++; } } ++++ ===== 3D Modelle ===== {{:elektronik:simon_spiel:taster.stl?s=300&bgcolor=#ffffff|Taster}} {{:elektronik:simon_spiel:gehaeuse_oben.stl?s=300&bgcolor=#ffffff|Gehäuse}} {{tag>[arduino plattformio simon led ws2812b]}} \\ ~~DISQUS~~