adventsfenster/src/main.cpp

769 lines
21 KiB
C++

#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();
}