#include "main.h" void taster_abfrage(); void set_lichtszene(); void set_moveszene(); bool licht_update(); void szene_oh_tannebaum(); void szene_nachts_dorf(); void szene_schnee_dorf(); void szene_nachts(); void szene_tag_dorf(); void move_zugoben(); void move_zugunten(); void move_schiene_oben(); void show_counters(); void updateNVS(); void disco(); void disco_licht(); unsigned int licht_all_count = 0; unsigned int move_all_count = 0; unsigned int disco_all_count = 0; unsigned long last_updated_NVS = 0; bool licht_is_fading = false; bool mp3_isused = false; void setup() { Serial.begin(115200); randomSeed(analogRead(0)); taster_aussen_licht.begin(); taster_aussen_move.begin(); //taster_train_unten.begin(); //taster_train_oben.begin(); //taster_schiene.begin(); relais_wolke_schiene.begin(); relais_spiegel.begin(); //relais_wolke.begin(); zugoben.begin(); zugunten.begin(); licht.begin(); NVS.begin(); licht_all_count = NVS.getInt("licht_cnt"); //1985 delay(500); move_all_count = NVS.getInt("move_cnt"); //978 delay(500); disco_all_count = NVS.getInt("disco_cnt"); //100 moni.init(); moni.setBrigthness(100); licht_state_flag = LSTERNBILD1 | LSTERNBILD2 | LSTERNBILD3 | LSTERNE1 | LSTERNE2 | LTANNE; mp3ply.begin(); mp3ply.stop(); led_sterne1.setBrigthness(20); led_sterne2.setBrigthness(20); led_sternbilder1.setBrigthness(220); led_sternbilder2.setBrigthness(220); led_sternbilder3.setBrigthness(220); led_bauhof.setBrigthness(40); led_burg.setBrigthness(40); led_teich.setBrigthness(1); led_back.setBrigthness(200); //blau led_back.setHS(32000,200); led_back.setHS(9000,180); led_teich.setHS(40000,255); } void loop() { updateNVS(); show_counters(); taster_abfrage(); set_lichtszene(); set_moveszene(); licht_is_fading = licht_update(); } bool next_licht_szene_possible = true; bool next_move_szene_possible = true; uint8_t licht_szene = 0; uint8_t move_szene = 0; unsigned long szene_time_ms = 0; unsigned long szene_overall_time_ms = 0; void set_lichtszene() { if(next_licht_szene_possible == false) { szene_overall_time_ms = millis(); switch(licht_szene) { case 0: szene_nachts(); break; case 1: szene_nachts_dorf(); break; case 2: szene_schnee_dorf(); break; case 3: szene_tag_dorf(); break; case 4: szene_oh_tannebaum(); break; default: licht_szene = 0; } } if(millis() - szene_overall_time_ms > SZENE_TIMEOUT_TO_SET_TO_DEFAULT_MS) { szene_overall_time_ms = millis(); Serial.printf("Setting Licht backt to default night withe Tannenbaum\n"); licht_state_flag = LSTERNBILD1 | LSTERNBILD2 | LSTERNBILD3 | LSTERNE1 | LSTERNE2 | LTANNE; licht_szene = 0; taster_aussen_licht.reset(); next_licht_szene_possible = true; } } void set_moveszene() { if(next_move_szene_possible == false) { switch(move_szene) { case 0: move_zugoben(); break; case 1: move_zugunten(); break; case 2: move_schiene_oben(); break; default: move_szene = 0; break; } } } const byte TANNENBAUM_VOL = 20; const unsigned long TANNENBAUM_PLAY_MUSIC_MS = 135000; typedef enum {TA_INIT = 0, TA_LIGHT_READY, TA_MIN_PLAYING,TA_PLAYING, TA_STOP_PLAYING, TA_FINSIHED} szene_tanne_t; szene_tanne_t tanne_state = TA_INIT; void szene_oh_tannebaum() { unsigned long msecs = millis(); switch(tanne_state) { case TA_INIT: Serial.printf("Tannenbaum spielt\n"); licht_state_flag = LSTERNBILD1 | LSTERNBILD2 | LSTERNBILD3 | LSTERNE1 | LSTERNE2 | LTANNE; tanne_state = TA_LIGHT_READY; break; case TA_LIGHT_READY: if(licht_is_fading == false) { if(mp3_isused == true) tanne_state = TA_FINSIHED; else{ mp3_isused = true; tanne_state = TA_MIN_PLAYING; Serial.printf("All lights are ready for Oh Tannebaum\n"); //mp3ply.play_vol(SONG_OH_TANNEBAUM, TANNENBAUM_VOL); mp3ply.play_vol(SONG_WINTER, TANNENBAUM_VOL); szene_time_ms = msecs; } } break; case TA_MIN_PLAYING: taster_aussen_licht.reset(); if(msecs - szene_time_ms > 1000) tanne_state = TA_PLAYING; break; case TA_PLAYING: if(msecs - szene_time_ms > TANNENBAUM_PLAY_MUSIC_MS || taster_aussen_licht.pressed() == true ) tanne_state = TA_STOP_PLAYING; break; case TA_STOP_PLAYING: if(mp3ply.fade_out() == false) { Serial.printf("Oh Tannebaum faded out and stopped\n"); tanne_state = TA_FINSIHED; mp3_isused = false; } break; case TA_FINSIHED: tanne_state = TA_INIT; next_licht_szene_possible = true; //taster_aussen_licht.reset(); Serial.printf("Tannenbaum finished\n"); break; } } typedef enum {NA_INIT = 0, NA_LIGHT_READY, NA_FINISHED} szene_nacht_t; szene_nacht_t nacht_state = NA_INIT; void szene_nachts_dorf() { switch(nacht_state) { case NA_INIT: Serial.printf("Nachts im Dorf\n"); licht_state_flag = LSTERNBILD1 | LSTERNBILD2 | LSTERNBILD3 | LSTERNE1 | LSTERNE2 | LTANNE | LBURG | LBAUHOF | LTEICH | LHAEUSER; nacht_state = NA_LIGHT_READY; break; case NA_LIGHT_READY: if(licht_is_fading == false) { nacht_state = NA_FINISHED; Serial.printf("All lights are ready for Nachts im Dorf\n"); } break; case NA_FINISHED: nacht_state = NA_INIT; next_licht_szene_possible = true; taster_aussen_licht.reset(); Serial.printf("Nachts im Dorf finished\n"); break; } } typedef enum {SD_INIT = 0, SD_LIGHT_READY, SD_FINISHED} szene_schnee_t; szene_schnee_t schnee_state = SD_INIT; void szene_schnee_dorf() { switch(schnee_state) { case SD_INIT: Serial.printf("Schnee im Dorf\n"); licht_state_flag = LSTERNE1 | LSTERNE2 | LTANNE | LBURG | LBAUHOF | LTEICH | LSPIEGEL | LHAEUSER; schnee_state = SD_LIGHT_READY; break; case SD_LIGHT_READY: if(licht_is_fading == false) { schnee_state = SD_FINISHED; Serial.printf("All lights are ready for Schnee im Dorf\n"); } break; case SD_FINISHED: schnee_state = SD_INIT; next_licht_szene_possible = true; taster_aussen_licht.reset(); Serial.printf("Schnee im Dorf finished\n"); break; } } typedef enum {DU_INIT = 0, DU_LIGHT_READY, DU_FINISHED} szene_dunkel_t; szene_dunkel_t dunkel_state = DU_INIT; void szene_nachts() { switch(dunkel_state) { case DU_INIT: Serial.printf("Dunkel im Dorf\n"); licht_state_flag = LSTERNBILD1 | LSTERNBILD2 | LSTERNBILD3 | LSTERNE1 | LSTERNE2; dunkel_state = DU_LIGHT_READY; break; case DU_LIGHT_READY: if(licht_is_fading == false) { dunkel_state = DU_FINISHED; Serial.printf("All lights are ready for Dunkel im Dorf\n"); } break; case DU_FINISHED: dunkel_state = DU_INIT; next_licht_szene_possible = true; taster_aussen_licht.reset(); Serial.printf("Dunkel im Dorf finished\n"); break; } } typedef enum {TAG_INIT = 0, TAG_LIGHT_READY, TAG_FINISHED} szene_tag_t; szene_tag_t tag_state = TAG_INIT; void szene_tag_dorf() { switch(tag_state) { case TAG_INIT: Serial.printf("Tag im Dorf\n"); licht_state_flag = LTANNE | LBACK; tag_state = TAG_LIGHT_READY; break; case TAG_LIGHT_READY: if(licht_is_fading == false) { tag_state = TAG_FINISHED; Serial.printf("All lights are ready for Tag im Dorf\n"); } break; case TAG_FINISHED: tag_state = TAG_INIT; next_licht_szene_possible = true; taster_aussen_licht.reset(); Serial.printf("Tag im Dorf finished\n"); break; } } unsigned int zugunten_error = 0; const unsigned int ZUGUNTEN_MAX_ERROR_COUNT = 5; const unsigned long ZUGUNTEN_DRIVES_TO_STATION_MS = 4300; const unsigned long ZUGUNTEN_STOPPED_AT_STATION_MS = 5000; const unsigned long ZUGUNTEN_MAX_TIME_TO_HOME_MS = 35000;///21000; ///timeout time typedef enum {ZU_INIT = 0, ZU_AT_HOME , ZU_DRIVES_TO_STATION, ZU_STOPPES_AT_STATION, ZU_STOPPED_AT_STATION, ZU_DRIVES_HOME, ZU_STOPPES_AT_HOME, ZU_STOPPED_PLAYING, ZU_DONE} szene_zugunten_t; szene_zugunten_t zugunten_state = ZU_INIT; bool mp3_zugunten = false; void move_zugunten() { unsigned long msecs = millis(); switch(zugunten_state) { case ZU_INIT: Serial.printf("Zugunten fährt\n"); //taster_train_unten.reset(); if (zugunten_error > ZUGUNTEN_MAX_ERROR_COUNT) { zugunten_state = ZU_DONE; Serial.printf("Zugunten . More errors than allowed - will stop here."); } else { zugunten_state = ZU_AT_HOME; if(mp3_isused == false) { Serial.printf("Playing Eine Insel\n"); //mp3ply.play_vol(SONG_EINE_INSEL, 20); mp3ply.play_vol(SONG_WEIHNACHTSZEIT, 20); mp3_zugunten = true; mp3_isused = true; } else mp3_zugunten = false; } break; case ZU_AT_HOME: szene_time_ms = msecs; if(zugunten.fade_on() == false) //zugunten_state = ZU_DRIVES_TO_STATION; zugunten_state = ZU_DRIVES_HOME; break; case ZU_DRIVES_TO_STATION: if(msecs - szene_time_ms > ZUGUNTEN_DRIVES_TO_STATION_MS) { zugunten_state = ZU_STOPPES_AT_STATION; zugunten.switch_zero_relais(false); } break; case ZU_STOPPES_AT_STATION: szene_time_ms = msecs; if(zugunten.fade_off() == false) zugunten_state = ZU_STOPPED_AT_STATION; break; case ZU_STOPPED_AT_STATION: if(msecs - szene_time_ms > ZUGUNTEN_STOPPED_AT_STATION_MS) { zugunten_state = ZU_DRIVES_HOME; szene_time_ms = msecs; } break; case ZU_DRIVES_HOME: //if(zugunten.fade_on() == false) if( (msecs-szene_time_ms) > ZUGUNTEN_MAX_TIME_TO_HOME_MS ) //taster_train_unten.pressed() == true ||) { if( (msecs-szene_time_ms) > ZUGUNTEN_MAX_TIME_TO_HOME_MS) { Serial.printf("Train unten runs ins timeout while driving back at Home\n"); // zugunten_error++; } else{ Serial.printf("Train unten back at Home pressed\n"); zugunten_error = 0; } zugunten_state = ZU_STOPPES_AT_HOME; zugunten.switch_zero_relais(true); } break; case ZU_STOPPES_AT_HOME: if(zugunten.fade_off() == false) zugunten_state = ZU_STOPPED_PLAYING; break; case ZU_STOPPED_PLAYING: if(mp3_zugunten == true) { if(mp3ply.fade_out() == false ) //&& mp3ply.is_playing() == 0) { zugunten_state = ZU_DONE; mp3_isused = false; } } else zugunten_state = ZU_DONE; break; case ZU_DONE: next_move_szene_possible = true; taster_aussen_move.reset(); zugunten_state = ZU_INIT; Serial.printf("Zugunten stopped\n"); break; } } bool mp3_zugoben = false; unsigned int zugoben_error = 0; const unsigned int ZUGOBEN_MAX_ERROR_COUNT = 5; const unsigned long ZUGOBEN_DRIVES_TO_BRIDGE_MS = 1000; const unsigned long ZUGOBEN_DRIVES_ON_BRIDGE_MS = 5500; const unsigned long ZUGOBEN_MAX_TIME_TO_HOME_MS = 3*11550; ///timeout time const uint8_t ZUGOBEN_SPEED_ON_BRIDGE = 80; typedef enum {ZO_INIT = 0, ZO_AT_HOME, ZO_DRIVES_HOME, ZO_STOPPES_AT_HOME,ZO_STOPPED_PLAYING,ZO_DONE} szene_zugoben_t; szene_zugoben_t zugoben_state = ZO_INIT; void move_zugoben() { unsigned long msecs = millis(); switch(zugoben_state) { case ZO_INIT: Serial.printf("Zugoben fährt\n"); //taster_train_oben.reset(); if (zugoben_error > ZUGOBEN_MAX_ERROR_COUNT) zugoben_state = ZO_STOPPES_AT_HOME; else { if(mp3_isused == false) { Serial.printf("Playing Weihnachtsbahn\n"); //mp3ply.play_vol(SONG_WEIHNACHTSBAHN, 20); mp3ply.play_vol(SONG_ZEIT_ANGEKOMMEN, 20); mp3_zugoben = true; mp3_isused = true; } else mp3_zugoben = false; zugoben_state = ZO_AT_HOME; } break; case ZO_AT_HOME: szene_time_ms = msecs; if(zugoben.fade_on() == false) zugoben_state = ZO_DRIVES_HOME; break; case ZO_DRIVES_HOME: if(zugoben.fade_on() == false) if( (msecs-szene_time_ms) > ZUGOBEN_MAX_TIME_TO_HOME_MS ) //||taster_train_oben.pressed() == true ) { if((msecs-szene_time_ms) > ZUGOBEN_MAX_TIME_TO_HOME_MS) { Serial.printf("Train oben runs in time out while driving back at home\n"); // zugoben_error++; } else { Serial.printf("Train oben back at Home pressed\n"); zugoben_error = 0; } zugoben_state = ZO_STOPPES_AT_HOME; } break; case ZO_STOPPES_AT_HOME: if(zugoben.fade_off() == false) zugoben_state = ZO_STOPPED_PLAYING; break; case ZO_STOPPED_PLAYING: if(mp3_zugoben == true) { if(mp3ply.fade_out() == false ) { zugoben_state = ZO_DONE; mp3_isused = false; } } else zugoben_state = ZO_DONE; break; case ZO_DONE: zugoben_state = ZO_INIT; next_move_szene_possible = true; taster_aussen_move.reset(); Serial.printf("Zugoben stopped at home\n"); break; } } bool mp3_soben = false; unsigned int soben_error = 0; const unsigned int SOBEN_MAX_ERROR_COUNT = 5; const unsigned long SOBEN_MAX_DRIVES_TIME_MS = 30400; ///timeout time typedef enum {SO_INIT = 0, SO_AT_HOME, SO_DRIVES_HOME, SO_STOPPES_AT_HOME,SO_STOPPED_PLAYING, SO_DONE} szene_soben_t; szene_soben_t soben_state = SO_INIT; void move_schiene_oben() { unsigned long msecs = millis(); switch(soben_state) { case SO_INIT: Serial.printf("Schiene oben fährt\n"); //taster_schiene.reset(); if(soben_error > SOBEN_MAX_ERROR_COUNT) soben_state = SO_STOPPES_AT_HOME; else { if(mp3_isused == false) { Serial.printf("Playing Weihnachtsbäckerei\n"); if( random(0, 2) == 0 ) mp3ply.play_vol(SONG_WEIHNACHTSBAECKEREI, 23); else mp3ply.play_vol(SONG_WEIHNACHTSTRAUM, 23); mp3_soben = true; mp3_isused = true; } else mp3_soben = false; soben_state = SO_AT_HOME; } break; case SO_AT_HOME: szene_time_ms = millis(); relais_wolke_schiene.on(); //relais_wolke.on(); soben_state = SO_DRIVES_HOME; break; case SO_DRIVES_HOME: if( (msecs-szene_time_ms) > SOBEN_MAX_DRIVES_TIME_MS) //||taster_schiene.pressed() == true ) { if((msecs-szene_time_ms) > SOBEN_MAX_DRIVES_TIME_MS) { // soben_error++; Serial.printf("Schiene oben timeout while driving home.\n"); } else { soben_error = 0; Serial.printf("Schiene oben back at Home pressed\n"); } soben_state = SO_STOPPES_AT_HOME; } break; case SO_STOPPES_AT_HOME: relais_wolke_schiene.off(); //relais_wolke.off(); soben_state = SO_STOPPED_PLAYING; break; case SO_STOPPED_PLAYING: if(mp3_soben == true) { if(mp3ply.fade_out() == false ) //&& mp3ply.is_playing() == 0) { soben_state = SO_DONE; mp3_isused = false; } } else soben_state = SO_DONE; break; case SO_DONE: soben_state = SO_INIT; next_move_szene_possible = true; taster_aussen_move.reset(); Serial.printf("Schiene oben stopped at home\n"); break; } } void disco() { unsigned long disco_time = millis(); disco_all_count++; uint32_t stored_licht_state_flag = licht_state_flag; uint8_t randSongNumber = random(0, 4); Serial.printf("Disco! Playing Song %d\n", randSongNumber); switch(randSongNumber) { case 0: mp3ply.play_vol(SONG_DISCO_LASTCHRISTMAS,25); break; case 1: mp3ply.play_vol(SONG_DISCO_DOTHEYKNOWITSCHRISTMAS,25); break; case 2: mp3ply.play_vol(SONG_DISCO_MARYSBOYCHILD,25); break; case 3: mp3ply.play_vol(SONG_DISCO_MERRY_CHRISTMAS,25); break; default: mp3ply.play_vol(SONG_DISCO_LASTCHRISTMAS,25); break; } /* while(mp3ply.is_playing() == 0) { disco_licht(); Serial.printf("Waiting until MP3 player starts\n"); delay(100); } */ while(millis() - disco_time < MAX_DISCO_TIME) { disco_licht(); Serial.printf("Playing Disco!!!\n"); } while(mp3ply.fade_out()==true) {delay(100);} Serial.printf("Disco done.\n"); rgb_leds.clear(); rgb_leds.show(); licht_state_flag = 0; licht_update(); licht_state_flag = stored_licht_state_flag; while( true == licht_update()) {delay(1);} taster_aussen_licht.reset(); taster_aussen_move.reset(); } bool licht_update() { bool fade_updated = false; bool rainbow_updated = false; fade_updated = led_sterne1.update() || fade_updated; fade_updated = led_sterne2.update() || fade_updated; fade_updated = led_sternbilder1.update() || fade_updated; fade_updated = led_sternbilder2.update() || fade_updated; fade_updated = led_sternbilder3.update()|| fade_updated; rainbow_updated = led_tanne.update(leds::UP_RAINBOW) || rainbow_updated; fade_updated = led_bauhof.update() || fade_updated; fade_updated = led_burg.update() || fade_updated; rainbow_updated = led_teich.update(leds::UP_BLUE) || rainbow_updated; fade_updated = led_back.update() || fade_updated; if((licht_state_flag & LHAEUSER) == 0) { //Serial.printf("Fade off lights at houses"); fade_updated = licht.fade_off() || fade_updated; } else { //Serial.printf("Fade on lights at houses"); fade_updated = licht.fade_on() || fade_updated; } if((licht_state_flag & LSPIEGEL) == 0) relais_spiegel.off(); else relais_spiegel.on(); if(true == rainbow_updated || true == fade_updated) { rgb_leds.show(); } return(fade_updated); } void disco_licht() { led_sterne1.theaterChaseRainbow(); led_sterne2.theaterChaseRainbow(); led_sternbilder1.theaterChaseRainbow(); led_sternbilder2.theaterChaseRainbow(); led_sternbilder3.theaterChaseRainbow(); led_tanne.theaterChaseRainbow(); led_bauhof.theaterChaseRainbow(); led_burg.theaterChaseRainbow(); led_teich.theaterChaseRainbow(); led_back.theaterChaseRainbow(); licht.fade_off(); relais_spiegel.on(); rgb_leds.show(); } void taster_abfrage() { if(next_licht_szene_possible == true && next_move_szene_possible == true && digitalRead(PIN_TASTER_AUSSEN_LICHT) == LOW && digitalRead(PIN_TASTER_AUSSEN_MOVE) == LOW) { disco(); } else { if(next_licht_szene_possible == true) { if(taster_aussen_licht.pressed() == true) { Serial.printf("Aussenlicht pressed\n"); licht_szene++; licht_all_count++; next_licht_szene_possible = false; } } if(next_move_szene_possible == true) { if(taster_aussen_move.pressed() == true) { Serial.printf("Move pressed\n"); move_szene++; move_all_count++; next_move_szene_possible = false; } } } } uint8_t nvs_value = 0; void updateNVS() { if(millis() - last_updated_NVS > 1000) { last_updated_NVS = millis(); switch(nvs_value) { case 0: NVS.setInt("licht_cnt", licht_all_count); break; case 1: NVS.setInt("move_cnt", move_all_count); break; case 2: NVS.setInt("disco_cnt", disco_all_count); break; } if(nvs_value == 2) nvs_value = 0; else nvs_value++; } } unsigned long display_time_ms = 0; const unsigned long MAX_DISPLAY_TIME_BEFORE_FLIP_MS = 600000; void show_counters() { if(millis() - display_time_ms > MAX_DISPLAY_TIME_BEFORE_FLIP_MS) { display_time_ms = millis(); moni.flipScreenVert(); } moni.clear(); moni.header("Zaehler"); moni.data(20,12,(uint64_t)licht_all_count, "Licht"); moni.data(60,12, (uint64_t)disco_all_count, "Disco"); moni.data(100,12, (uint64_t)move_all_count, "Moves"); moni.data(15,38,(uint64_t)zugunten_error, "ZUErr"); moni.data(60,38,(uint64_t)zugoben_error, "ZOErr"); moni.data(100,38,(uint64_t)soben_error, "SOErr"); moni.show(); }