/* *This code is for an instructable named "IR 'Smart Outlet'" at: * "" *code and project by: Adam Berger *You are free to use this code anyway you'd like. Thank you for your interest *in my project! */ #include #include #include #include #include #define DS1307_ADDRESS 0x68 #define relayPin 9 //Initialize IR Pin (Pin 10) int RECV_PIN = 10 ; IRrecv irrecv(RECV_PIN); decode_results results; //time keeping arrays int startTime[] = {0,0,0,0,0,0}; int time[] = {0,0,0,0,0,0}; int stopTime[] = {0,0,0,0,0,0}; //Millis (for timers) unsigned long pMillis = millis(); // initialization of lcd library with pins: E RS D4 D5 D6 D7 LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Variable initialization: String minutes, hours, seconds, IRIn = "NONE"; boolean enableTimer = false, outletStatus = false; void setup() { //Setup relayPin as an ouput pinMode(relayPin, OUTPUT); //set up the LCD's number of columns and rows: lcd.begin(16, 2); //Print welcome message lcd.print(" WELCOME TO"); lcd.setCursor(0,1); lcd.print("IR SMART OUTLET!"); delay(1500); lcd.clear(); lcd.print(" ENTERING"); lcd.setCursor(0,1); lcd.print(" SELECT MODE..."); delay(750); lcd.clear(); // Start the IR receiver irrecv.enableIRIn(); } void loop() { //Select Mode: lcd.clear(); IRIn="?"; lcd.print(" 1 2 3 4"); lcd.setCursor(0, 1); lcd.print("HLP TMR OPTS IDL"); while(IRIn!="1"&IRIn!="2"&IRIn!="3"&IRIn!="4"){ remoteListener(); } if(IRIn=="1"){ lcd.clear(); lcd.print(" ENTERING"); lcd.setCursor(0,1); lcd.print(" HELP MODE..."); delay(750); lcd.clear(); helpMode(); } else if(IRIn=="2"){ lcd.clear(); lcd.print(" ENTERING"); lcd.setCursor(0,1); lcd.print(" TIMER MODE..."); delay(750); lcd.clear(); setMode(); } else if(IRIn=="3"){ lcd.clear(); lcd.print(" ENTERING"); lcd.setCursor(0,1); lcd.print(" OPTIONS MODE..."); delay(750); lcd.clear(); optionsMode(); } else if(IRIn=="4"){ lcd.clear(); lcd.print(" ENTERING"); lcd.setCursor(0,1); lcd.print(" IDLE MODE..."); delay(750); lcd.clear(); idleMode(); } } void helpMode(){ IRIn = "?"; lcd.clear(); lcd.print(" Help Mode:"); lcd.setCursor(0,1); lcd.print("Press > to cont."); while(IRIn!=">"){ if(IRIn=="*"){ lcd.clear(); return;} remoteListener(); } lcd.clear(); String helpMessage = "Hello! Welcome to IR SMART OUTLET. Controls: Press * to go back. # for 'enter'. To control outlet, you must be in 'IDLE' mode. Made by: Adam Berger. Enjoy!"; //loop for scrolling through "helpMessage": for(int i=0; (i)<5; i++){ IRIn = "?"; lcd.print(helpMessage.substring((i+i)*16,((i+i)+1)*16)); lcd.setCursor(0,1); lcd.print(helpMessage.substring(((i+i)+1)*16,((i+i)+2)*16)); while(IRIn!=">"){ remoteListener(); if(IRIn=="*"){ lcd.clear(); return;} else if(IRIn=="<"){ if(i>=1){i-=2; break;}} } lcd.clear(); } } void setMode(){ IRIn="?"; lcd.clear(); lcd.print(" Enable timer?"); lcd.setCursor(0,1); lcd.print(" 1.YES 2.NO"); while(true){ remoteListener(); if(IRIn=="*"){ lcd.clear(); return;} if(IRIn=="1") break; else if(IRIn=="2") break; } if(IRIn=="1") { lcd.clear(); lcd.print(" TIMER ENABLED"); delay(1000); lcd.clear(); enableTimer = true; } else if(IRIn=="2") { lcd.clear(); lcd.print(" TIMER DISABLED"); delay(1000); lcd.clear(); enableTimer = false; IRIn="?"; return; } int currentCursor = 0; //set alarm's begin time: IRIn = "?"; lcd.clear(); while(IRIn!="#"){ if(IRIn=="*"){ lcd.clear(); return;} lcd.setCursor(0,0); lcd.print(" Time: "+getTime()); lcd.setCursor(0,1); lcd.print("Start: "+(String)startTime[0]+startTime[1]+":"+startTime[2]+startTime[3]+":"+startTime[4]+startTime[5]); if(IRIn=="0"||IRIn=="1"||IRIn=="2"||IRIn=="3"||IRIn=="4"||IRIn=="5"||IRIn=="6"||IRIn=="7"||IRIn=="8"||IRIn=="9"){ startTime[currentCursor] = IRIn.toInt(); currentCursor++;} if(IRIn==">") currentCursor++; else if(IRIn=="<") currentCursor--; if(currentCursor>6) currentCursor=0; else if(currentCursor<0) currentCursor=6; lcd.setCursor(7+currentCursor+(currentCursor>=2?1:0)+(currentCursor>=4?1:0),1); lcd.blink(); IRIn = "?"; while(millis()-pMillis<200){ remoteListener(); if(IRIn!="?") break; } pMillis=millis(); lcd.noBlink(); if(startTime[0]>2) startTime[0]=2; else if(startTime[0]==2&&startTime[1]>3) startTime[1]=3; else if(startTime[2]>5) startTime[2]=5; else if(startTime[3]>9) startTime[3]=9; else if(startTime[4]>5) startTime[4]=5; else if(startTime[5]>9) startTime[5]=9; } lcd.clear(); lcd.print("START TIME SAVED"); lcd.setCursor(0,1); lcd.print(" ENTER END TIME"); delay(1500); lcd.clear(); //set alarm's end time: IRIn = "?"; currentCursor = 0; lcd.clear(); while(IRIn!="#"){ if(IRIn=="*"){ lcd.clear(); return;} lcd.setCursor(0,0); lcd.print(" Time: "+getTime()); lcd.setCursor(0,1); lcd.print(" End: "+(String)stopTime[0]+stopTime[1]+":"+stopTime[2]+stopTime[3]+":"+stopTime[4]+stopTime[5]); if(IRIn=="0"||IRIn=="1"||IRIn=="2"||IRIn=="3"||IRIn=="4"||IRIn=="5"||IRIn=="6"||IRIn=="7"||IRIn=="8"||IRIn=="9"){ stopTime[currentCursor] = IRIn.toInt(); currentCursor++;} if(IRIn==">") currentCursor++; else if(IRIn=="<") currentCursor--; if(currentCursor>6) currentCursor=0; else if(currentCursor<0) currentCursor=6; lcd.setCursor(7+currentCursor+(currentCursor>=2?1:0)+(currentCursor>=4?1:0),1); lcd.blink(); IRIn = "?"; while(millis()-pMillis<200){ remoteListener(); if(IRIn!="?") break; } pMillis=millis(); lcd.noBlink(); if(stopTime[0]>2) stopTime[0]=2; else if(stopTime[0]==2&&stopTime[1]>3) stopTime[1]=3; else if(stopTime[2]>5) stopTime[2]=5; else if(stopTime[3]>9) stopTime[3]=9; else if(stopTime[4]>5) stopTime[4]=5; else if(stopTime[5]>9) stopTime[5]=9; } lcd.clear(); lcd.print(" END TIME SAVED"); lcd.setCursor(0,1); lcd.print("DEVICE WILL BE:"); delay(2000); lcd.clear(); lcd.print(" ON AT:"+(String)startTime[0]+startTime[1]+":"+startTime[2]+startTime[3]+":"+startTime[4]+startTime[5]); lcd.setCursor(0,1); lcd.print("OFF AT:"+(String)stopTime[0]+stopTime[1]+":"+stopTime[2]+stopTime[3]+":"+stopTime[4]+stopTime[5]); delay(2000); lcd.clear(); } void optionsMode(){ IRIn= "?"; lcd.clear(); remoteListener(); lcd.print(" 1 2 "); lcd.setCursor(0, 1); lcd.print("CHKTIMRS SETTIME"); while(IRIn!="1"&IRIn!="2"&IRIn!="3"){ remoteListener(); if(IRIn=="*") {lcd.clear(); return;} } if(IRIn=="1"){ lcd.clear(); lcd.print("TIMER = "+(String)(enableTimer?"ENABLED":"DISABLED")); if(!enableTimer) delay(1500); else if(enableTimer){ lcd.setCursor(0,1); lcd.print("OUTLET WILL BE:"); delay(1750); lcd.clear(); while(IRIn!="*"){ remoteListener(); lcd.print(" ON AT:"+(String)startTime[0]+startTime[1]+":"+startTime[2]+startTime[3]+":"+startTime[4]+startTime[5]); lcd.setCursor(0,1); lcd.print("OFF AT:"+(String)stopTime[0]+stopTime[1]+":"+stopTime[2]+stopTime[3]+":"+stopTime[4]+stopTime[5]); } } } else if(IRIn=="2"){ IRIn = "?"; int currentCursor = 0; lcd.clear(); while(IRIn!="#"){ if(IRIn=="*"){ lcd.clear(); return;} lcd.setCursor(0,0); lcd.print(" SET TIME:"); lcd.setCursor(0,1); lcd.print(" "+(String)time[0]+time[1]+":"+time[2]+time[3]+":"+time[4]+time[5]); if(IRIn=="0"||IRIn=="1"||IRIn=="2"||IRIn=="3"||IRIn=="4"||IRIn=="5"||IRIn=="6"||IRIn=="7"||IRIn=="8"||IRIn=="9"){ time[currentCursor] = IRIn.toInt(); currentCursor++;} if(IRIn==">") currentCursor++; else if(IRIn=="<") currentCursor--; if(currentCursor>6) currentCursor=0; else if(currentCursor<0) currentCursor=6; lcd.setCursor(4+currentCursor+(currentCursor>=2?1:0)+(currentCursor>=4?1:0),1); lcd.blink(); IRIn = "?"; while(millis()-pMillis<200){ remoteListener(); if(IRIn!="?") break; } pMillis=millis(); lcd.noBlink(); if(time[0]>2) time[0]=2; else if(time[0]==2&&time[1]>3) time[1]=3; else if(time[2]>5) time[2]=5; else if(time[3]>9) time[3]=9; else if(time[4]>5) time[4]=5; else if(time[5]>9) time[5]=9; } setRTC((time[0]*10)+time[1],(time[2]*10)+time[3],(time[4]*10)+time[5]); lcd.clear(); lcd.print(" TIME SAVED!"); delay(1500); lcd.clear(); } } void idleMode(){ if(!enableTimer){ lcd.clear(); while(true){ if(IRIn=="#"&!outletStatus){ digitalWrite(relayPin, HIGH); outletStatus=true; IRIn="?"; lcd.clear(); lcd.print(" OUTLET ON!"); delay(750); lcd.clear(); }else if(IRIn=="#"&outletStatus){ digitalWrite(relayPin, LOW); outletStatus=false; IRIn="?"; lcd.clear(); lcd.print(" OUTLET OFF!"); delay(750); lcd.clear(); } lcd.print(" PRESS '#' TO"); lcd.setCursor(0,1); lcd.print(" CONTROL OUTLET"); remoteListener(); if(IRIn=="*"){lcd.clear(); return;} } } else{ tmElements_t tm; String time = getTime(); int currentTime[] = {(int)time.charAt(0),(int)time.charAt(1),(int)time.charAt(3),(int)time.charAt(4),(int)time.charAt(6),(int)time.charAt(7)}; while(true){ if(timeUntil(startTime)=="00:00:00") { digitalWrite(relayPin, HIGH); outletStatus=true; IRIn="?"; lcd.clear(); lcd.print(" OUTLET ON!"); delay(1000); lcd.clear(); }else if(timeUntil(stopTime)=="00:00:00") { digitalWrite(relayPin, LOW); outletStatus=false; IRIn="?"; lcd.clear(); lcd.print(" OUTLET OFF!"); delay(1000); lcd.clear(); } if(IRIn=="#"&!outletStatus){ digitalWrite(relayPin, HIGH); outletStatus=true; IRIn="?"; lcd.clear(); lcd.print(" OUTLET ON!"); delay(750); lcd.clear(); }else if(IRIn=="#"&outletStatus){ digitalWrite(relayPin, LOW); outletStatus=false; IRIn="?"; lcd.clear(); lcd.print(" OUTLET OFF!"); delay(750); lcd.clear(); } lcd.print("TIMER COUNTDOWN:"); lcd.setCursor(0,1); remoteListener(); if(!outletStatus){ lcd.print(" ON IN: "+ timeUntil(startTime));//Display when outlet will turn on if(IRIn=="*"){lcd.clear(); return;} } else if(outletStatus){ lcd.print("OFF IN: "+ timeUntil(stopTime));//Display when outlet will turn off if(IRIn=="*"){lcd.clear(); return;} } } } } String remoteListener(){ //listens for remote and assigns "IRIn" a value accordingly if(irrecv.decode(&results)){ switch(results.value){ //Directions case 0xFF629D: IRIn = "^"; break; case 0xFF22DD: IRIn= "<"; break; case 0xFFC23D: IRIn= ">"; break; case 0xFFA857: IRIn= "v"; break; case 0xFF02FD: IRIn= "OK"; //Numbers/Symbols case 0xFF6897: IRIn= "1"; break; case 0xFF9867: IRIn= "2"; break; case 0xFFB04F: IRIn= "3"; break; case 0xFF30CF: IRIn= "4"; break; case 0xFF18E7: IRIn= "5"; break; case 0xFF7A85: IRIn= "6"; break; case 0xFF10EF: IRIn= "7"; break; case 0xFF38C7: IRIn= "8"; break; case 0xFF5AA5: IRIn= "9"; break; case 0xFF42BD: IRIn= "*"; break; case 0xFF4AB5: IRIn= "0"; break; case 0xFF52AD: IRIn= "#"; break; } irrecv.resume(); } return(IRIn); } String getTime(){ //returns time in HH:MM:SS tmElements_t tm; if (RTC.read(tm)) { if (tm.Minute >= 0 && tm.Minute < 10){ minutes = '0'+ (String) tm.Minute; }else{ minutes = (String) tm.Minute; } if (tm.Hour >= 0 && tm.Hour < 10){ hours = '0'+ (String) tm.Hour; }else{ hours = (String) tm.Hour; } if (tm.Second >= 0 && tm.Second < 10){ seconds = '0'+ (String) tm.Second; }else{ seconds = (String) tm.Second; } }else{ return("??:??"); } return(hours+":"+minutes+":"+seconds); } String timeUntil(int secondTime[8]){ //calculates the time until tmElements_t tm; RTC.read(tm); long diffSeconds; unsigned int alarmTime = HHMMSStoSeconds(secondTime),//(secondHour*3600) + (secondMinute*60) + (secondSecond), currentTime = (tm.Hour*3600) + (tm.Minute*60) + (tm.Second); if(alarmTime>=currentTime) diffSeconds=alarmTime-currentTime; else diffSeconds = (alarmTime)+(86400-currentTime); return(formatIntoHHMMSS(diffSeconds)); } void setRTC(byte setHour, byte setMinute, byte setSecond){ //library code for setting RTC's time byte second = setSecond; //0-59 byte minute = setMinute; //0-59 byte hour = setHour; //0-23 byte weekDay = 0; //1-7 byte monthDay = 0; //1-31 byte month = 0; //1-12 byte year = 0; //0-99 Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x00); //stop Oscillator Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(weekDay)); Wire.write(decToBcd(monthDay)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.write(0x00); //start Wire.endTransmission(); } byte decToBcd(byte val){ // Convert normal decimal numbers to binary coded decimal return ( (val/10*16) + (val%10) ); } byte bcdToDec(byte val) { // Convert binary coded decimal to normal decimal numbers return ( (val/16*10) + (val%16) ); } unsigned int HHMMSStoSeconds(int secondTime[6]){ long secondHour = (secondTime[0]*10)+secondTime[1], secondMinute = (secondTime[2]*10)+secondTime[3], secondSecond = (secondTime[4]*10)+secondTime[5]; unsigned int alarmTime = (secondHour*3600) + (secondMinute*60) + (secondSecond); return(alarmTime); } /*https://answers.yahoo.com/question/index?qid=20080905173323AArLUVA * The following code was taken from the link above. */ String formatIntoHHMMSS(unsigned long secsIn){ unsigned int hr = secsIn / 3600, remainder = secsIn % 3600, min = remainder / 60, sec = remainder % 60; return ( (String)(hr < 10 ? "0" : "") + hr + ":" + (min < 10 ? "0" : "") + min + ":" + (sec< 10 ? "0" : "") + sec ); }