/* This code is developed to a project : Timer Power Plug. puplished on instructables created by : Motaz Bany-Amer 2/9/2016 */ /* this code will derive an arduino uno(or mega) with the components : ~common_cathode 7Seg ~LED ~2push buttons ~relay and ~external power plug. the product will connect/disconnect the power to a ~plug connected to the ~relay the user will be abel to connect/disconnect the power to the ~plug with specific durations the duration (in Hours) will be shown on a ~7Seg display, and can be set will a 2 ~pushbuttons a ~pushbutton to set the time, the other to reset the timer. The prograram uses the arduino timer 1 to achive 1Hz frequancy interrupt (overflow interrupt) by adding some counters, it can manage the time with hours. the code is commented with max possible details. and it can be modified easly. */ //******************************************* //duration initialization #define hour0 0 //0 Hour in Seconds #define hour1 3600 //1 Hour in Seconds #define hour2 7200 //2 Hours in Seconds #define hour3 10800 //3 Hours in Seconds #define hour4 14400 //4 Hours in Seconds #define hour5 18000 //5 Hours in Seconds #define hour6 21600 //6 Hours in Seconds //7Seg pins #define a 2 #define b 3 #define c 4 #define d 5 #define e 6 #define f 7 #define g 8 #define del 250 //deboncing delay #define indicationLed 13 //to indicate the timer is active #define timeSettingBtnPin 11 //connect setting Button Input to this pin #define timeResetBtnPin 12 //connect reset Button Input to this pin #define relayPin 9 //connect the relay input to this pin //7Seg show num functions /* please note that these functions are valid for a coomon cathode 7seg display these functions can be used with a common anode display by reversing 0's and 1's i.e common cathode : digitalWrite(a,1); common anode : digitalWrite(a,0); */ void num0() { digitalWrite(a, 1); digitalWrite(b, 1); digitalWrite(c, 1); digitalWrite(d, 1); digitalWrite(e, 1); digitalWrite(f, 1); digitalWrite(g, 0); } void num1() { digitalWrite(a, 0); digitalWrite(b, 1); digitalWrite(c, 1); digitalWrite(d, 0); digitalWrite(e, 0); digitalWrite(f, 0); digitalWrite(g, 0); } void num2() { digitalWrite(a, 1); digitalWrite(b, 1); digitalWrite(c, 0); digitalWrite(d, 1); digitalWrite(e, 1); digitalWrite(f, 0); digitalWrite(g, 1); } void num3() { digitalWrite(a, 1); digitalWrite(b, 1); digitalWrite(c, 1); digitalWrite(d, 1); digitalWrite(e, 0); digitalWrite(f, 0); digitalWrite(g, 1); } void num4() { digitalWrite(a, 0); digitalWrite(b, 1); digitalWrite(c, 1); digitalWrite(d, 0); digitalWrite(e, 0); digitalWrite(f, 1); digitalWrite(g, 1); } void num5() { digitalWrite(a, 1); digitalWrite(b, 0); digitalWrite(c, 1); digitalWrite(d, 1); digitalWrite(e, 0); digitalWrite(f, 1); digitalWrite(g, 1); } void num6() { digitalWrite(a, 1); digitalWrite(b, 0); digitalWrite(c, 1); digitalWrite(d, 1); digitalWrite(e, 1); digitalWrite(f, 1); digitalWrite(g, 1); } //counters /* the volatile key word, is prefered to be used in any program, specially where there an ISR in your code the function of this key word, is to teel the compiler that this variable, is very important, so it does not delete it or miss with it unless the code tell it so. you can see arduino referance, or any c/c++ referance available, to learn more about it. any way, I ADVICE TO USE IT. */ volatile long secondsCounter = 0; //this counter will count the seconds the timer steps volatile byte hoursCounter = 0; //this counter will count the hourse every time the second counter reachs 3600 volatile long secondsNeeded = 0; // volatile byte hoursSetting = 0; //a variable to handle the user input, to set the time wanted. volatile boolean timeSettingBtnState = 0; //hold the state of the pin 1/0 volatile boolean timeResetBtnState = 0; //hold the state of the pin 1/0 void setup() { //Buttons pins setup /* set them to pullup mode so we dont have to use an external resistor of curse the input signal will have to be digial 0 (PULLUP INPUT MODE) */ pinMode(timeSettingBtnPin, INPUT_PULLUP); pinMode(timeResetBtnPin, INPUT_PULLUP); //7 segmant pins setup pinMode(a, OUTPUT); pinMode(b, OUTPUT); pinMode(c, OUTPUT); pinMode(d, OUTPUT); pinMode(e, OUTPUT); pinMode(f, OUTPUT); pinMode(g, OUTPUT); //indication Led on pin 13, to indicate the timer is activated. //IT's NOT ESSENTIAL, YOU CAN DELETE IT IF YOU WANT, i just like to add it in my timer. pinMode(indicationLed, OUTPUT); //set the indicationLed to OUTPUT state to derive the LED pinMode(relayPin, OUTPUT); //set the relayPin to OUTPUT state to derive the relay //timer setup noInterrupts(); // disable all interrupts TCCR1A = 0; TCCR1B = 0; TCNT1 = 3036; // preload timer 65536-16MHz/256/1Hz TCCR1B |= (1 << CS12); // 256 prescaler TIMSK1 &= ~(1 << TOIE1); //disable timer interrupt interrupts(); // enable all interrupts //Serial setup /* Serial monitor is just used for debigging and monitorring variables values IT IS NOT ESSENTIAL, YOU GET RED OF IT,IF YOU WANT! AND EVERY SERIAL COMMAND IN THIS CODE AS WILL. */ Serial.begin(9600); //initial state of the timer /* the initial state is, the timer is set is 0 the timer is disabled and the indicationLed is turned off */ secondsCounter = 0; num0(); digitalWrite(indicationLed, 0); /* the relay has two outputs terminals, NC (normally closed) NO(normaaly opened. the state of the IN to the relay defines where the relay is connected I have connected my plug to NO terminal, and these settings work for me you can change(reverse) these setting as your relay or connection you can use an LED with a Resistor to check the settings(connect 5v with a RES to COM, and a LED to NO, when you OUTPUT digital 0 on the relay IN pin, the LED is ON) */ digitalWrite(relayPin, 1); } ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt { //every 1 hour, the value shown on the 7 seg, decreased. if (secondsCounter == hour0) //when the counter reach 0, show 0 and turn off led. { num0(); //turn off every thing digitalWrite(indicationLed, 0); digitalWrite(relayPin, 1); //set all variables to initial state, because the counter has finished hoursCounter = 0; hoursSetting = 0; secondsNeeded = 0; } if (secondsCounter == hour1)//when the counter reach hour1 seconds value, show 1. { num1(); } if (secondsCounter == hour2) { num2(); } if (secondsCounter == hour3) { num3(); } if (secondsCounter == hour4) { num4(); } if (secondsCounter == hour5) { num5(); } if (secondsCounter == hour6) { num6(); } secondsCounter--; //decrease the counter every second Serial.println(secondsCounter); //debugging TCNT1 = 3036; // preload timer, to ensure the ISR run every 1secound } void loop() { //update the state of the leds timeSettingBtnState = digitalRead(timeSettingBtnPin); timeResetBtnState = digitalRead(timeResetBtnPin); if (!timeSettingBtnState) //seting button presed { delay(del); //debouncing hoursSetting++; //increase the time setting by 1 if (hoursSetting > 6) //the max hours the timer can be set to is 6 { hoursSetting = 0; } //debuging Serial.print("H : "); Serial.println(hoursSetting); digitalWrite(indicationLed, 1); //turn on the led, to indicate the timer is active digitalWrite(relayPin, 0); //setting options conditions if (hoursSetting == 0) { secondsNeeded = hour0; } if (hoursSetting == 1) { secondsNeeded = hour1; } if (hoursSetting == 2) { secondsNeeded = hour2; } if (hoursSetting == 3) { secondsNeeded = hour3; } if (hoursSetting == 4) { secondsNeeded = hour4; } if (hoursSetting == 5) { secondsNeeded = hour5; } if (hoursSetting == 6) { secondsNeeded = hour6; } //after the setting is sellected, activate timer,and set the second counter value //after seetting the timer value, it will start dicreasing every 1second, in the ISR //every 1 hour, the 7SEG displays a different value secondsCounter = secondsNeeded; TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt } if (!timeResetBtnState) //reset button presed { delay(del); //debouncing //return all variables and objecs to initial state TIMSK1 &= ~(1 << TOIE1); //disable timer interrupt secondsCounter = 0; hoursCounter = 0; hoursSetting = 0; secondsNeeded = 0; digitalWrite(indicationLed, 0); digitalWrite(relayPin, 1); num0(); } }