alarmclock with 2 alarm times, 128x64 LCD with KS0108, displays time / time&date / a menu to change time & alarms, rotary encoder with push button, relay which switsches on a hi-fi system or something else, a 1F- Cap as a backup supply
Alarmclock
features:
- alarmclock with 2 alarm times
- 128x64 LCD with KS0108
- displays time / time&date / a menu to change time & alarms
- sleeptimer, relay is switched of when timer runs out
- rotary encoder with push button
- relay which switsches on a hi-fi system or something else
- a 1F- Cap as a backup supply
todo/ desired improvements/ known issues:
- a more precise real time clock would be nice
- a speaker or beeper directly connected to the mbed
- there is a bug where the big font is not displayed correctly
Schematic:
/media/uploads/gaebu/alarmclock_mbed_128x64.pdf
main.cpp
- Committer:
- gaebu
- Date:
- 2016-01-05
- Revision:
- 2:fbf734bc04de
- Parent:
- 1:8a7f4f79f84d
File content as of revision 2:fbf734bc04de:
/* * @author gaebu * * @section LICENSE * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * @section DESCRIPTION //---------------------------------------------------------------- // Alarmclock // ----------- // features: // - alarmclock with 2 alarm times // - 128x64 LCD with KS0108 // - displays time / time&date / a menu to change time & alarms // - sleeptimer, relay is switched of when timer runs out // - rottary encoder with push button // - relay which switsches on a hi-fi system or something else // - a 1F- Cap as a backup supply // - the relay is manualy switched on/off by pressing the button // longer than 2s //---------------------------------------------------------------- // todo/ desired improvements: // - a more precise real time clock would be nice // - a speaker or beeper directly connected to the mbed // - there is a bug in displaying fonts //---------------------------------------------------------------- */ #include "mbed.h" #include "KS0108.h" #include "QEI.h" //#include "math.h" //#include "Arial12.h" //#include "Arial14.h" //#include "arial_bold_14.h" //#include "Comic24.h" //#include "SystemFont5x7.h" //#include "vivaldi16.h" //#include "MyPhone_40.h" //#include "Buxton32.h" #include "Pointy48.h" //#include "Buxton48B.h" //#include "GoodDog48B.h" //#include "SnapITC32.h" #include "alarmclock.h" //#include <string> // _RST,_DI, _RW, _E, _CS2, _CS1,DB0, DB1, DB2, DB3, DB4, DB5, DB6, DB7) KS0108 display(p13, p12, p14, p11, p30, p29, p21, p22, p23, p24, p25, p26, p27, p28); QEI wheel (p17, p16, NC, 18, QEI::X2_ENCODING); DigitalIn wheelpush(p18); DigitalOut led1(LED1), led2(LED2), relay(p15), enbackligth(p19), beeper(p20); int main() { //general init beeper=0; menu=1; menuDisp=1; alarmon=0; alarmset2=0; sleeptimer=0; wheelpushchanged=1; alarm.tm_sec = 00; // 0-59 alarm.tm_min = 00; // 0-59 alarm.tm_hour = 6; // 0-23 alarm2.tm_sec = 00; // 0-59 alarm2.tm_min = 00; // 0-59 alarm2.tm_hour = 5; // 0-23 //display title & frame display.ClearScreen(); display.PutString(0,30,"alarmclock"); display.EmptyRectangle(0,0,127,63,BLACK); display.HLine(0,127,7,BLACK); //display.GotoXY(10,16); //display.SelectFont(Comic24,BLACK,ReadData); //display.PrintString("by_gaebu!"); display.PutString(10,16,"by_gaebu!"); display.PutString(30,26,"V1.2"); wait(2); clearmenu(); wheel.reset(); //mainloop //--------------------------------------------------------------- while (1) { //read time seconds = time(NULL); led1=relay; //ckeck if button pressed or wheel turned checkbutton(); pulses=wheel.getPulses(); //display.PrintInteger(pulses,0,0); if (pulses!=0){ blTimeout.attach(&blTimeout_tick, 5.0); //blstate=1; //backlight(blstate); backlight(1); if (pulses>0){ menu++; if (menu>7) menu=0; } if (pulses<0){ if (menu==0) menu=7; else menu--; } wheel.reset(); display.PrintInteger(menu,0,100); } //ring the alarm? if(alarmon | alarmon2) { relay=1; //blstate=!blstate; backlight(1);//blstate); if(menuold!=menu) { //ring until any button pressed alarmon=0; alarmon2=0; relay=0; backlight(blstate);//old); } } //check alarm if(alarmset & !alarmon) { newtime = localtime(&seconds); if(alarm.tm_min==newtime->tm_min & alarm.tm_hour==newtime->tm_hour & alarm.tm_sec==newtime->tm_sec) { alarmon=1; } } if(alarmset2 & !alarmon2) { newtime = localtime(&seconds); if(alarm2.tm_min==newtime->tm_min & alarm2.tm_hour==newtime->tm_hour & alarm2.tm_sec==newtime->tm_sec) { alarmon2=1; } } //display menu //--------------------------------------------------------------- if (menu!=menuold) { menuDisp=menu; if (menu<2 | (menu==2&menuold==1) | (menu==7&menuold==0)){ clearmenu(); } menuold=menu; } else if (menu>1 & !(wheelpushed|wheelpushedlong)) //don't redraw menu if no time is diplayed or no input made menuDisp=99; else menuDisp=menu; switch (menuDisp) { //--- Menu 1 --- date&time case 0: strftime(x_day, 20, "%a, %d %b %Y\n", localtime(&seconds)); display.PutString(3,20,x_day); strftime(x_time, 16, "%X\n", localtime(&seconds)); display.PutString(4,30,x_time); if (wheelpushed) { //switch backlight if button pressed blstate=!blstate; backlight(blstate); } if (wheelpushedlong) { //switch relay if button pressed long relay=!relay; } break; //--- Menu 2 --- time big case 1: strftime(x_time, 16, "%H:%M .", localtime(&seconds)); // display.GotoXY(32,24); display.GotoXY(8,16); //hint: position must be a product of 8 display.SelectFont(Pointy48,BLACK,ReadData); //display.SelectFont(Comic24,BLACK,ReadData); display.PrintString(x_time); if (wheelpushed) { //switch backlight if button pressed blstate=!blstate; backlight(blstate); } if (wheelpushedlong) { //switch relay if button pressed long relay=!relay; } break; //--- Menu 3 --- display menu, alarm1 on/off case 2: if (wheelpushed) { alarmset=!alarmset; } printmenu(2); break; //--- Menu 4 --- display menu, alarm2 on/off case 3: if (wheelpushed) { alarmset2=!alarmset2; } printmenu(3); break; //--- Menu 5 --- set alarm 1 case 4: if (wheelpushed) { setalarm(1); } printmenu(4); break; //--- Menu 6 --- set alarm 2 case 5: if (wheelpushed) { setalarm(2); } printmenu(5); break; //--- Menu 7 --- set time&date case 6: if (wheelpushed) { settimedate(); } printmenu(6); break; //--- Menu 8 --- sleep timer case 7: if (wheelpushed) { if (sleeptimer>0) //if sleeptimer already set then reset sleeptimer=0; else setsleeptimer(); } printmenu(7); break; case 99: //do nothing break; default: display.PutString(0,100,"error"); //exit(1); } } } //functions //------------------------------------------ void clearmenu() { //display.FullRectangle(1,9,126,62,WHITE); //display title & frame display.ClearScreen(); display.PutString(0,30,"alarmclock"); display.EmptyRectangle(0,0,127,63,BLACK); display.HLine(0,127,7,BLACK); } //------------------------------------------ void printmenu(int selectedline) { //zeile1 //zeile2 display.PutString(2,20,"Alarm 1: "); if (alarmset) display.PutString(2,80,"on "); else display.PutString(2,80,"off "); //zeile3 display.PutString(3,20,"Alarm 2: "); if (alarmset2) display.PutString(3,80,"on "); else display.PutString(3,80,"off "); //zeile4 display.PutString(4,20,"set Alarm 1"); strftime(alarmtime, 6, "%H:%M\n", &alarm); display.PutString(4,85,alarmtime); //zeile5 display.PutString(5,20,"set Alarm 2"); strftime(alarmtime, 6, "%H:%M\n", &alarm2); display.PutString(5,85,alarmtime); //zeile6 display.PutString(6,20,"set Time/ Date"); //zeile7 display.PutString(7,20,"sleep timer"); // if (sleeptimerstart) { if (sleeptimer>0) { display.PrintInteger(sleeptimer,7,85); // display.PutString(7,40,sleeptime_set); } //select line for (i=2;i<8;i++) display.PutString(i,2," "); display.PutString(selectedline,2,"~~"); //frame display.EmptyRectangle(0,0,127,63,BLACK); } //------------------------------------------ void setsleeptimer(){ sleeptimer=30; clearmenu(); wheel.reset(); change_sleeptimer=true; display.PutString(3,30,"set sleeptimer"); display.PutString(5,30,"min:"); while(change_sleeptimer){ if (sleeptimer<10) display.PutString(5,65," "); if (sleeptimer<100) display.PutString(5,70," "); if (sleeptimer<1000) display.PutString(5,75," "); if (sleeptimer<10000) display.PutString(5,80," "); display.PrintInteger(sleeptimer,5,60); checkbutton(); if (wheel.getPulses()>0){ if (sleeptimer<1080) sleeptimer+=5; } else if (wheel.getPulses()<0){ if (sleeptimer>5) sleeptimer-=5; } if (wheel.getPulses()!=0) wheel.reset(); if (wheelpushed) { change_sleeptimer=false; wheelpushed=false; wheel.reset(); ticker.attach(&ticker_tick, 60.0); relay=1; display.ClearScreen(); } } } //------------------------------------------ void setalarm(char alnb) { clearmenu(); wheel.reset(); change_alarm_hour=1; display.PutString(4,30,"-- "); if (alnb == 1) al_to_change=alarm; else al_to_change=alarm2; while (change_alarm_hour) { strftime(alarmtime, 6, "%H:%M\n", &al_to_change); display.PutString(3,30,alarmtime); checkbutton(); if (wheel.getPulses()>0) wheelturned='r'; else if (wheel.getPulses()<0) wheelturned='l'; if (wheel.getPulses()==0) wheelturned=0; else wheel.reset(); if (wheelturned=='r') { al_to_change.tm_hour++; if (al_to_change.tm_hour>23) al_to_change.tm_hour=0; } if (wheelturned=='l') { al_to_change.tm_hour--; if (al_to_change.tm_hour<0) al_to_change.tm_hour=23; } if (wheelpushed) { change_alarm_hour=0; change_alarm_min=1; display.PutString(4,30," --"); } } while (change_alarm_min) { strftime(alarmtime, 6, "%H:%M\n", &al_to_change); display.PutString(3,30,alarmtime); checkbutton(); if (wheel.getPulses()>0) wheelturned='r'; else if (wheel.getPulses()<0) wheelturned='l'; if (wheel.getPulses()==0) wheelturned=0; else wheel.reset(); if (wheelturned=='r') { al_to_change.tm_min++; if (al_to_change.tm_min>59) al_to_change.tm_min=0; } if (wheelturned=='l') { al_to_change.tm_min--; if (al_to_change.tm_min<0) al_to_change.tm_min=59; } if (wheelpushed) { change_alarm_min=0; if (alnb == 1) alarm=al_to_change; else alarm2=al_to_change; wheelturned=0; wheelpushed=false; wheel.reset(); } } } //------------------------------------------ void settimedate() { clearmenu(); wheel.reset(); seconds = time(NULL); newtime = localtime(&seconds); set_td_menu=1; wheelturned=1; //menuold=0; display.PutString(4,30,"-- "); if (newtime->tm_year==70) newtime->tm_year=113; while(set_td_menu>0) { if(wheelturned>0) { //update display if changed strftime(x_day, 20, "%d.%m.%Y\n", newtime); display.PutString(5,30,x_day); char x_time[16]; strftime(x_time, 16, "%H:%M\n", newtime); display.PutString(3,30,x_time); } checkbutton(); //menu=wheel.getPulses(); //display.PrintInteger(menu,0,100); //if (menu>menuold) if (wheel.getPulses()>0) wheelturned='r'; else if (wheel.getPulses()<0) wheelturned='l'; if (wheel.getPulses()==0) wheelturned=0; else wheel.reset(); //menuold=menu; switch(set_td_menu) { case 0: break; // Invalid entry case 1: //set hour if (wheelturned=='r') { newtime->tm_hour++; if (newtime->tm_hour>23) newtime->tm_hour=0; } if (wheelturned=='l') { newtime->tm_hour--; if (newtime->tm_hour<0) newtime->tm_hour=23; } if (wheelpushed) { set_td_menu++; display.PutString(4,30," --"); } break; case 2: //set min if (wheelturned=='r') { newtime->tm_min++; if (newtime->tm_min>59) newtime->tm_min=0; } if (wheelturned=='l') { newtime->tm_min--; if (newtime->tm_min<0) newtime->tm_min=59; } if (wheelpushed) { set_td_menu++; display.PutString(4,30," "); display.PutString(6,30,"-- "); } break; case 3: //set day if (wheelturned=='r') { newtime->tm_mday++; if (newtime->tm_mday>31) newtime->tm_mday=1; } if (wheelturned=='l') { newtime->tm_mday--; if (newtime->tm_mday<1) newtime->tm_mday=31; } if (wheelpushed) { set_td_menu++; display.PutString(6,30," -- "); } break; case 4: //set month if (wheelturned=='r') { newtime->tm_mon++; if (newtime->tm_mon>11) newtime->tm_mon=0; } if (wheelturned=='l') { newtime->tm_mon--; if (newtime->tm_mon<0) newtime->tm_mon=11; } if (wheelpushed) { set_td_menu++; display.PutString(6,30," ----"); } break; case 5: //set month if (wheelturned=='r') { newtime->tm_year++; if (newtime->tm_year>200) newtime->tm_year=100; } if (wheelturned=='l') { newtime->tm_year--; if (newtime->tm_year<100) newtime->tm_year=200; } if (wheelpushed) { set_td_menu=0; display.PutString(6,30," "); // convert to timestamp and set set_time(mktime(newtime)); wheelturned=0; wheelpushed=false; //menuDisp=0; //menuold=0; wheel.reset(); } break; default: display.PutString(0,100,"error"); exit(1); } } } //------------------------------------------ void ticker_tick() //called every 60s when sleeptimer set { if (sleeptimer==0){ relay=0; led1=0; blstate=0; ticker.detach(); } else sleeptimer--; } //------------------------------------------ void backlight (bool onoff) { led2=onoff; enbackligth=onoff; } //------------------------------------------ void blTimeout_tick() //called after 5s when wheel is turned { //cklight(blstate); //blticker.detach(); led2=0; enbackligth=0; } //------------------------------------------ void checkbutton() { wheelpushed=false; wheelpushedlong=false; if (!wheelpush) { if (wheelpushchanged) { temp=0; while(!wheelpush & temp<=200) { //if pressed longer than 2s.. wait(0.01); temp++; } if (temp>200) wheelpushedlong=true; else wheelpushed=true; wheelpushchanged=0; } } else wheelpushchanged=1; }