aquarium light controller wannabe

Dependencies:   DS3231 FastPWM Menu QEI TextLCD _24LCXXX mbed

main.cpp

Committer:
rakware
Date:
2015-11-09
Revision:
2:c50dfa998b4c
Parent:
1:b0e2b4fdeb12

File content as of revision 2:c50dfa998b4c:

#include "mbed.h"
#include "TextLCD.h"
#include "QEI.h"
#include "Menu.h"
#include "FastPWM.h"
#include "DS3231.h"
#include "_24LCXXX.h"


Serial pc(USBTX, USBRX); //DEBUG
DigitalOut myled(LED1); //DEBUG

// I2C Bus
I2C i2c(PB_4, PA_8); // SDA, SCL

TextLCD_I2C lcd(&i2c, PCF8574_SA7);
_24LCXXX eeprom(&i2c, 0x57);
DS3231 rtc(PB_4, PA_8);
//End I2C BUS

QEI qei(PH_0, PH_1, NC, 80, QEI::X4_ENCODING); //Index is NC(see QEI class), we use PC_13 as digital input
DigitalIn qei_idx(PC_13);

bool qei_pb() //check and debounces qei_idx
{
    int check = qei_idx;
    wait_us(5);
    if((!check) && !qei_idx) {
        return true;
    } else return false;
}

//PA_11 = ESP SERIAL!!!
FastPWM Pwm_Array[] = {PA_7,PA_5,PA_6,PB_6,PA_9,PB_3,PB_5,PB_7,PA_10,PB_10,PC_8,PB_8,PA_11,PC_9,PB_9};

//Ticker Pwm_Ticker[sizeof(Pwm_Array)/sizeof(FastPWM)];
Ticker Sunrise_Ticker;
Ticker Sunset_Ticker;

//uint8_t Pwm_Min_Max_Array[sizeof(Pwm_Array)/sizeof(FastPWM)][1][2] = {
//    { {0, 100} },
//    { {20, 80} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} },
//    { {0, 100} }
//};


uint8_t Pwm_Min_Max_Array[sizeof(Pwm_Array)/sizeof(FastPWM)][2] = {
    {0, 1}, //violet
    {1, 35}, //royal blue
    {0, 40}, //20000k
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35},
    {0, 35}
};

int pwm_idx = 0;

uint8_t SunRiseSet[2][2] = {{8,0},{20,30}};

uint8_t ramptime = 30; //in minutes

bool refresh_display = true;

enum { IDLE,
       MAIN,
       SETTINGS,
       PWM_MIN,
       PWM_MAX,
       SUNRISE,
       SUNSET,
       RAMPTIME,
       SUNRISE_HOUR,
       SUNRISE_MINUTE,
       SUNSET_HOUR,
       SUNSET_MINUTE,
       SET_DATE_TIME,
       SET_DATE_DAY,
       SET_DATE_MONTH,
       SET_DATE_YEAR,
       SET_TIME_HOUR,
       SET_TIME_MINUTE,
       SET_TIME_SECOND
     } menu_state = MAIN ;       // Initial state = MAIN ;

int cursorPos = 0;
Menu *activeMenu;

//struct tm *t; //read time
struct tm t; //mktime

Ticker qei_t; //ticker for qei_cb()

void qei_cb()
{
    if(qei.getCurrentState() == 3 && qei.getPulses() < 0) { //one tab left
        refresh_display = true;
        switch (menu_state) {
            case SETTINGS:
                cursorPos--;
                if (cursorPos < 0)
                    cursorPos = activeMenu->selections.size()-1;
                break;
            case PWM_MIN:
                if (Pwm_Min_Max_Array[cursorPos][0] > 0)
                    Pwm_Min_Max_Array[cursorPos][0]--;
                break;
            case PWM_MAX:
                if (Pwm_Min_Max_Array[cursorPos][1] > 0)
                    Pwm_Min_Max_Array[cursorPos][1]--;
                break;
            case RAMPTIME:
                ramptime--;
                break;
            case SUNRISE_HOUR:
                SunRiseSet[0][0]--;
                break;
            case SUNRISE_MINUTE:
                SunRiseSet[0][1]--;
                break;
            case SUNSET_HOUR:
                SunRiseSet[1][0]--;
                break;
            case SUNSET_MINUTE:
                SunRiseSet[1][1]--;
                break;
        }
        qei.reset();
    } else if(qei.getCurrentState() == 3 && qei.getPulses() > 0) { //one tab right
        refresh_display = true;
        switch (menu_state) {
            case SETTINGS:
                cursorPos++;
                if (cursorPos >= activeMenu->selections.size())
                    cursorPos = 0;
                break;
            case PWM_MIN:
                if (Pwm_Min_Max_Array[cursorPos][0] < 100)
                    Pwm_Min_Max_Array[cursorPos][0]++;
                break;
            case PWM_MAX:
                if (Pwm_Min_Max_Array[cursorPos][1] < 100)
                    Pwm_Min_Max_Array[cursorPos][1]++;
                break;
            case RAMPTIME:
                ramptime++;
                break;
            case SUNRISE_HOUR:
                SunRiseSet[0][0]++;
                break;
            case SUNRISE_MINUTE:
                SunRiseSet[0][1]++;
                break;
            case SUNSET_HOUR:
                SunRiseSet[1][0]++;
                break;
            case SUNSET_MINUTE:
                SunRiseSet[1][1]++;
                break;
        }
        qei.reset();
    }

    if(qei_pb()) { //button press
        Timer qei_pb_t;
        if (qei_pb_t.read() == 0) {
            qei_pb_t.start();
        }
        while(qei_pb()) { //check long press
            if(qei_pb_t.read() > 1) {
                qei_pb_t.stop();
                pc.printf("long press");//do stuff on long press
                refresh_display = true;
                lcd.cls();
                lcd.locate(0,0);
                lcd.printf("%s", activeMenu->menuID);
                lcd.locate(0,1);
                lcd.printf("%s", activeMenu->selections[cursorPos].selText);

                menu_state = SETTINGS;
                wait(0.5);
            }
        }
        if(qei_pb_t.read() < 1) {
            qei_pb_t.stop();
            //do stuff on short press
            pc.printf("short press");
            refresh_display = true;
            switch (menu_state) {
                case MAIN:
                    break;
                case SETTINGS:
                    pc.printf("apasat SETTINGS\n");
                    if(activeMenu->selections[cursorPos].fun != NULL) {
                        (activeMenu->selections[cursorPos].fun)();
                    }
                    if(activeMenu->selections[cursorPos].childMenu != NULL) {
                        activeMenu = activeMenu->selections[cursorPos].childMenu;
                        cursorPos = 0;
                    }
                    //            print_menu();
                    wait(0.2);
                    break;
                case PWM_MIN:
                    menu_state = SETTINGS;
                    wait(0.2);
                    break;
                case PWM_MAX:
                    menu_state = SETTINGS;
                    wait(0.2);
                    break;
                case SUNRISE:
                    wait(0.2);
                    menu_state = SUNRISE_HOUR;
                    break;
                case SUNRISE_HOUR:
                    wait(0.2);
                    menu_state = SUNRISE_MINUTE;
                    break;
                case SUNSET:
                    wait(0.2);
                    menu_state = SUNSET_HOUR;
                    break;
                case SUNSET_HOUR:
                    wait(0.2);
                    menu_state = SUNSET_MINUTE;
                    break;
                default:
                    menu_state = SETTINGS;
                    wait(0.2);
                    break;
            }
            wait(0.2);
        }
    }
}

void exit_settings()
{
//    menu_state = SAVE_SETTINGS;
//    lcd.locate(0,1);
//    lcd.printf("<N    SAVE    Y>");
    menu_state = MAIN;
}

void pwm_min()
{
    menu_state = PWM_MIN;
}

void pwm_max()
{
    menu_state = PWM_MAX;
}

void sun_rise()
{
    menu_state = SUNRISE;
}

void sun_set()
{
    menu_state = SUNSET;
}

void ramp_time()
{
    menu_state = RAMPTIME;
}

void set_date_time()
{
    menu_state = SET_DATE_TIME;
}

//    void inc() {
//        _pin = _pin + 0.01/8.0;  // 0.01 = 1% => 0.125% increments, if you modify this you need to modify 'ramp/8' too
//    }
//    void dec() {
//        _pin = _pin - 0.01/8.0;
//    }

//void bl(uint8_t pwmnameArray[10][3], PwmOut &pwmname, Ticker &pwmname_t, Ramp &pwmname_r) //pwmnameArray, pwmname, pwmname_t, pwmname_r
//void bl()
//{
//    struct tm *t;
//    time_t seconds = time(NULL);
//    t = localtime(&seconds);
//
//    int timerica = (t->tm_hour*3600) + (t->tm_min*60) + t->tm_sec;
//
//    for (uint8_t index = 0; index < 10; index++) { //cycle array (sizeof(pwmArray)/sizeof(pwmArray[0])) = 0?
//
////        if (pwmnameArray[index][2] != 255 && pwmnameArray[index+1][2] != 255) {
////
////            if ( timerica == (pwmnameArray[index][0]*3600) + (pwmnameArray[index][1]*60) ) {
////
////                pwmname_t.detach();
////
////                pwmname = pwmnameArray[index][2]/100.0;
////
////                float ramp = float( (((pwmnameArray[index+1][0]*3600) + (pwmnameArray[index+1][1]*60))-((pwmnameArray[index][0]*3600) + (pwmnameArray[index][1]*60))) ) / float( (pwmnameArray[index+1][2]-pwmnameArray[index][2]) ) ;
////
////                pc.printf("ramp ?%f\n", ramp);
////
////                if (ramp > 0) {
////                    pwmname_t.attach(&pwmname_r, &Ramp::inc, ramp/8);
////                }
////                if (ramp < 0) {
////                    pwmname_t.attach(&pwmname_r, &Ramp::dec, ramp/8);
////                }
////
////                pc.printf("PWMSTART\n");
////                pc.printf("index %d\n",index);
////            }
////        }
//
////        if (pwmnameArray[index][2] != 255 && pwmnameArray[index+1][2] == 255) { //pwm_end = 255
////            if ( timerica == (pwmnameArray[index][0]*3600) + (pwmnameArray[index][1]*60) ) {
////
////                pwmname_t.detach();
////
////                pwmname = pwmnameArray[index][2]/100.0;
////
////                pc.printf("PWMZERO\n");
////                pc.printf("index %d\n",index);
////            }
////        }
//    }
//}

void incs()
{
    for(uint8_t index = 0; index < sizeof(Pwm_Array)/sizeof(FastPWM); index++) { //index < sizeof(Pwm_Array)/sizeof(FastPWM)

        double ramp = double( (Pwm_Min_Max_Array[index][1]-Pwm_Min_Max_Array[index][0]) ) / double( (( ((SunRiseSet[0][0]*3600) + (SunRiseSet[0][1]*60))+(ramptime*60) )-( (SunRiseSet[0][0]*3600) + (SunRiseSet[0][1]*60) )) ) ;

        if (Pwm_Array[index].read() < Pwm_Min_Max_Array[index][1]/100.0) {
            Pwm_Array[index] = Pwm_Array[index].read() + double(ramp/100.0);
            pc.printf("sunrise:[%i]%f ", index, Pwm_Array[index].read());
        }
        if (Pwm_Array[index].read() > Pwm_Min_Max_Array[index][1]/100.0) {
            Pwm_Array[index] = Pwm_Min_Max_Array[index][1]/100.0;
            Sunrise_Ticker.detach();
            pc.printf("\n sunrise end:[%i]%f \n", index, Pwm_Array[index].read());
        }
    }
}

void decs()
{
    for(uint8_t index = 0; index < sizeof(Pwm_Array)/sizeof(FastPWM); index++) { //index < sizeof(Pwm_Array)/sizeof(FastPWM)

        double ramp = double( (Pwm_Min_Max_Array[index][1]-Pwm_Min_Max_Array[index][0]) ) / double( (( ((SunRiseSet[1][0]*3600) + (SunRiseSet[1][1]*60))+(ramptime*60) )-( (SunRiseSet[1][0]*3600) + (SunRiseSet[1][1]*60) )) ) ;

        if (Pwm_Array[index].read() > Pwm_Min_Max_Array[index][0]/100.0) {
            Pwm_Array[index] = Pwm_Array[index].read() - double(ramp/100.0);
            pc.printf("sunset:[%i]%f ", index, Pwm_Array[index].read());
        }
        if (Pwm_Array[index].read() < Pwm_Min_Max_Array[index][0]/100.0) {
            Pwm_Array[index] = Pwm_Min_Max_Array[index][0]/100.0;
            Sunset_Ticker.detach();
            pc.printf("\n sunset end:[%i]%f \n", index, Pwm_Array[index].read());
        }
    }
}

//TODO
//init RTC

void set_time_from_rtc()
{
    int rtc_hour;
    int rtc_min;
    int rtc_sec;
    int rtc_dow; //day of week
    int rtc_mday;
    int rtc_mon;
    int rtc_year;

    rtc.readDateTime(&rtc_dow,&rtc_mday,&rtc_mon,&rtc_year,&rtc_hour,&rtc_min,&rtc_sec);
//TODO
//asuming that day of week is allways != 0, return an error if dow == 0.
    lcd.cls();
    lcd.printf("rtc: %i / %02i-%02i-%02i %02i:%02i:%02i",rtc_dow,rtc_mday,rtc_mon,rtc_year,rtc_hour,rtc_min,rtc_sec);


    t.tm_sec = rtc_sec;    // 0-59
    t.tm_min = rtc_min;    // 0-59
    t.tm_hour = rtc_hour;   // 0-23
    t.tm_mday = rtc_mday;   // 1-31
    t.tm_mon = rtc_mon;     // 0-11
    t.tm_year = rtc_year-1900;  // year since 1900

    // convert to timestamp and set (1256729737)
    time_t epoch = mktime(&t);
    set_time(epoch);
    wait(1); //not necessary
    lcd.cls();
    epoch = time(NULL);
    lcd.printf("stm: %i / %02i-%02i-%02i %02i:%02i:%02i",rtc_dow,localtime(&epoch)->tm_mday,localtime(&epoch)->tm_mon,localtime(&epoch)->tm_year+1900,localtime(&epoch)->tm_hour,localtime(&epoch)->tm_min,localtime(&epoch)->tm_sec);
    wait(1); //not necessary
}

void read_eeprom() //int nbyte_read( int mem_addr, void *data, int size ); //TODO
{
    char data2[4096]; //32Kbit eeprom
//    pc.printf("memory int data read!\n");
    eeprom.nbyte_read( 0, &data2, 4096 ); //MAXADR_24LCXXX <=4096
    //lcd.printf("int:%d sizeofint:%d",data2, sizeof(uint8_t));
//    pc.printf("\nend\n");
    lcd.printf("sizeof: %d", sizeof(data2));
}

int main()
{
    //lcd init
    lcd.setBacklight(TextLCD::LightOn);
    lcd.setMode(TextLCD::DispOn);

    //TODO
    //rtc init (set 32KHz output to enable, erase OSF, etc?


    char buffer[32];
    struct tm *twhile;

    set_time_from_rtc(); //read time from DS3231, set time to STM32
    //read external EEPROM and restore saved values (what values?)
    //lcd.cls();
    //read_eeprom();
    //wait(4);

    //TODO set initial pwm_channel state (ie: if it's betweeen sunrise_end and sunset_start set it to sunrise_max, if it's ramping calculate the initial value

    //initial state = pwm_min
    for(uint8_t index = 0; index < sizeof(Pwm_Array)/sizeof(FastPWM); index++) {
        Pwm_Array[index].period_ms(2); //500Hz
        Pwm_Array[index] = Pwm_Min_Max_Array[index][0]/100.0;
    }

    //see if we are between sunrise and sunset
    time_t seconds = time(NULL);
    twhile = localtime(&seconds);

    int timerica = (twhile->tm_hour*3600) + (twhile->tm_min*60) + twhile->tm_sec;

    if ((timerica > (SunRiseSet[0][0]*3600) + (SunRiseSet[0][1]*60)) && (timerica < (SunRiseSet[1][0]*3600) + (SunRiseSet[1][1]*60))) {
        for(uint8_t index = 0; index < sizeof(Pwm_Array)/sizeof(FastPWM); index++) {
            Pwm_Array[index] = Pwm_Min_Max_Array[index][1]/100.0; //add smoothing
            pc.printf("pwm:[%i]%f ", index, Pwm_Array[index].read());
        }
    }



    qei_idx.mode(PullUp);
    qei_t.attach(&qei_cb, 0.05); //calls qei_cb every 50ms

    Menu settingsMenu("SettingsID");

    Menu pwm_minMenu("PWM MinID");
    pwm_minMenu.add(Selection(&pwm_min, 0, NULL, "<     CH00     >"));
    pwm_minMenu.add(Selection(&pwm_min, 1, NULL, "<     CH01     >"));
    pwm_minMenu.add(Selection(&pwm_min, 2, NULL, "<     CH02     >"));
    pwm_minMenu.add(Selection(&pwm_min, 3, NULL, "<     CH03     >"));
    pwm_minMenu.add(Selection(&pwm_min, 4, NULL, "<     CH04     >"));
    pwm_minMenu.add(Selection(&pwm_min, 5, NULL, "<     CH05     >"));
    pwm_minMenu.add(Selection(&pwm_min, 6, NULL, "<     CH06     >"));
    pwm_minMenu.add(Selection(&pwm_min, 7, NULL, "<     CH07     >"));
    pwm_minMenu.add(Selection(&pwm_min, 8, NULL, "<     CH08     >"));
    pwm_minMenu.add(Selection(&pwm_min, 9, NULL, "<     CH09     >"));
    pwm_minMenu.add(Selection(NULL, 10, &settingsMenu, "<    Return    >"));

    Menu pwm_maxMenu("PWM MaxID");
    pwm_maxMenu.add(Selection(&pwm_max, 0, NULL, "<     CH00     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 1, NULL, "<     CH01     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 2, NULL, "<     CH02     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 3, NULL, "<     CH03     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 4, NULL, "<     CH04     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 5, NULL, "<     CH05     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 6, NULL, "<     CH06     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 7, NULL, "<     CH07     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 8, NULL, "<     CH08     >"));
    pwm_maxMenu.add(Selection(&pwm_max, 9, NULL, "<     CH09     >"));
    pwm_maxMenu.add(Selection(NULL, 10, &settingsMenu, "<    Return    >"));

//    Menu sunriseMenu("PWM MaxID");
//
//    Menu sunsetMenu("PWM MaxID");

//    Menu ramptimeMenu("RampTimeID");

    settingsMenu.add(Selection(NULL, 0, &pwm_maxMenu, "<PWM Day>"));
    settingsMenu.add(Selection(NULL, 1, &pwm_minMenu, "<PWM Night>"));
    settingsMenu.add(Selection(&sun_rise, 2, NULL, "<Sunrise>"));
    settingsMenu.add(Selection(&sun_set, 3, NULL, "<Sunset>"));
    settingsMenu.add(Selection(&ramp_time, 4, NULL, "<Ramp Time>"));
    settingsMenu.add(Selection(&set_date_time, 5, NULL, "<Set Date/Time>"));

    settingsMenu.add(Selection(&exit_settings, 6, NULL, "<Exit Setup>"));

    activeMenu = &settingsMenu;

    while(1) {

        time_t seconds = time(NULL);
        strftime(buffer, 32, "%H:%M:%S", localtime(&seconds));


        twhile = localtime(&seconds);

        int timerica = (twhile->tm_hour*3600) + (twhile->tm_min*60) + twhile->tm_sec;


        pc.printf("time: %s in seconds: %d sunrise: %d sunset: %d\n", buffer, timerica, (SunRiseSet[0][0]*3600) + (SunRiseSet[0][1]*60), (SunRiseSet[1][0]*3600) + (SunRiseSet[1][1]*60) );

        if (timerica == (SunRiseSet[0][0]*3600) + (SunRiseSet[0][1]*60)) { //TODO attach once at start out of while()
            Sunrise_Ticker.attach(&incs,1); //TODO check if allready attached
        }

        if (timerica == (SunRiseSet[1][0]*3600) + (SunRiseSet[1][1]*60)) {
            Sunset_Ticker.attach(&decs,1); //TODO check if allready attached
            pc.printf("sunset timer attached to decs\n");
        }

//        for(uint8_t index = 0; index < 3; index++) { //index < sizeof(Pwm_Array)/sizeof(FastPWM)
//            pc.printf("pwm:[%i]%f ", index, Pwm_Array[index].read());
//        }


        if (refresh_display == true) {
            switch(menu_state) {
                case MAIN:
                    lcd.cls();
                    lcd.printf("     BAT-LED    ");
                    lcd.printf("     v.1.0      ");
                    refresh_display = false;
                    break;
                case SETTINGS:
                    lcd.cls();
                    lcd.locate(0,0);
                    lcd.printf("%s", activeMenu->menuID);
                    lcd.locate(0,1);
                    lcd.printf("%s", activeMenu->selections[cursorPos].selText);
                    refresh_display = false;
                    break;
                case PWM_MIN:
                    lcd.cls();
                    lcd.printf("%s %2i", activeMenu->menuID, cursorPos);
                    lcd.locate(0,1);
                    lcd.printf("<-    %3i%%    +>", Pwm_Min_Max_Array[cursorPos][0]);
                    refresh_display = false;
                    break;
                case PWM_MAX:
                    lcd.cls();
                    lcd.printf("%s %2i", activeMenu->menuID, cursorPos);
                    lcd.locate(0,1);
                    lcd.printf("<-    %3i%%    +>", Pwm_Min_Max_Array[cursorPos][1]);
                    refresh_display = false;
                    break;
                case SUNRISE:
                    lcd.cls();
                    lcd.printf("%s %2i", activeMenu->menuID, cursorPos);
                    lcd.locate(0,1);
                    lcd.printf("%02d:%02d", SunRiseSet[0][0],SunRiseSet[0][1]);
                    refresh_display = false;
                    break;
                case SUNRISE_HOUR:
                    while(menu_state == SUNRISE_HOUR) {
                        lcd.locate(0,1);
                        lcd.printf("  ");
                        wait(0.1);
                        lcd.locate(0,1);
                        lcd.printf("%02d",SunRiseSet[0][0]);
                        wait(0.2);
                    }
                    break;
                case SUNRISE_MINUTE:
                    while(menu_state == SUNRISE_MINUTE) {
                        lcd.locate(3,1);
                        lcd.printf("  ");
                        wait(0.1);
                        lcd.locate(3,1);
                        lcd.printf("%02d",SunRiseSet[0][1]);
                        wait(0.2);
                    }
                    break;
                case SUNSET:
                    lcd.cls();
                    lcd.printf("%s %2i", activeMenu->menuID, cursorPos);
                    lcd.locate(0,1);
                    lcd.printf("%02d:%02d", SunRiseSet[1][0],SunRiseSet[1][1]);
                    refresh_display = false;
                    break;
                case SUNSET_HOUR:
                    while(menu_state == SUNSET_HOUR) {
                        lcd.locate(0,1);
                        lcd.printf("  ");
                        wait(0.1);
                        lcd.locate(0,1);
                        lcd.printf("%02d",SunRiseSet[1][0]);
                        wait(0.2);
                    }
                    break;
                case SUNSET_MINUTE:
                    while(menu_state == SUNSET_MINUTE) {
                        lcd.locate(3,1);
                        lcd.printf("  ");
                        wait(0.1);
                        lcd.locate(3,1);
                        lcd.printf("%02d",SunRiseSet[1][1]);
                        wait(0.2);
                    }
                    break;
                case RAMPTIME:
                    lcd.cls();
                    lcd.printf("%s %2i", activeMenu->menuID, cursorPos);
                    lcd.locate(0,1);
                    lcd.printf("<-    %3i     +>", ramptime);
                    refresh_display = false;
                    break;
                case SET_DATE_TIME:
                    lcd.cls();
                    lcd.printf("%02d/%02d/%04d",twhile->tm_mday, twhile->tm_mon, twhile->tm_year + 1900);
                    lcd.locate(0,1);
                    lcd.printf("%02d:%02d:%02d",twhile->tm_hour, twhile->tm_min, twhile->tm_sec);
                    refresh_display = false;
                    break;
            }
        }
        wait(0.5);
    }
}