Arduino AVR alarm clock using ATMEGA328P
OBJECTIVE: -
In this
project, we designed an Arduino based Time Clock with alarm. When we turn on
the clock start run because now, we didn’t use any RTC module we hope we will
use RTC module later but when we push alarm button then alarm will on, and we
can adjust time of clock and alarm clock by respective button. By pressing
alarm button, we set alarm and we can select hour and min on which we want set
alarm and when clock time match alarm time then whole min buzz will make sound.
PRTEUS SIMULATION
FLOW CHART
· Sir yet we didn’t use the rtc module I
didn’t visit they city when I go there I will pick it up now we are working
with simple clock start from 00:00:00 and time goes up
Requirements
·
Arduino UNO(ATMEGA328P)
·
16X02 Character LCD Screen
·
Active Buzzer 5V
·
9V Battery and Connector
·
Push Buttons
·
Bread Board
·
Jumper cables
·
Header Pins
·
Resistors
·
IR SENSOR
Features
·
Digital Clock displays in Hours, Minutes and Seconds.
·
Alarm Set Mode.
·
Dual key press to Alternate between Alarm set mode/Timer set mode
·
Alarm On/Off Button.
How it work:-
First, the
clock we choose here is 16000000 Hz, dividing it by 1024 gives 10800. So, for
every second we get 15625 pulses. So, we are going to start a counter with 1024
pre-scaler to get the counter clock as 10800 Hz. Second, we are going to use
the CTC (Clear Timer Counter) mode of ATMEGA. There will be a 16 bit register
where we can store a value (compare value), when the counter counts to the
compare value an interrupt is set to generate.
We are
going to set the compare value to 15625, so basically, we will have a ISR
(Interrupt Service Routine on every comparison) for every second. So, we are
going to use this timely routine to get the clock we needed.
TCCRIB |
ICNC1 |
ICES1 |
- |
WGM13 |
WGM12 |
CS12 |
CS12 |
CS12 |
YELLOW(WGM12): These bits are
for selecting (CTC) mode of operation for timer.
Now since we want the CTC mode
with compare value in OCR1A byte, we just must set WGM12 to one,
remaining are left as they are zero by default.
YELLOW (CS10, CS11, CS12):
These three bits are for choosing the pre-scalar and so getting appropriate
counter clock.
Since we want a 1024 as
pre-scaling, we must set both CS12 and CS10.
TCCRIB |
ICNC1 |
ICES1 |
- |
WGM13 |
WGM12 |
CS12 |
CS11 |
CS10 |
Now there is another register
which we should consider:
TIMSK1 |
- |
- |
ICE1 |
- |
- |
OCIE1B |
OCIE1A |
TOIE1 |
YELLOW (OCIE1A): This bit
must be set for getting an interrupt on compare match between counter value and
OCR1A value (15625) which we set.
OCR1A value (counter compare
value), is written in above register.
How to use
Push
buttons increments the time variables. Clicking both HOU,MIN buttons alternate
to alarm time setting mode along with making the Alarms status ON. Otherwise
ALM is also can be used to change the alarms status without setting up the
alarm time.ALM button will on/off the buzzer with the alarm mode.
COMPELETE PROJECT:- GITHUB
SOURCE CODE:-
Main.c #include <avr/io.h> #define F_CPU 16000000 #include <util/delay.h> #include <stdio.h> #include <avr/interrupt.h> void init_lcd(void); void moveto(unsigned char, unsigned char); void stringout(char *); void writecommand(unsigned char); void writedata(unsigned char); void writenibble(unsigned char); ISR(TIMER1_COMPA_vect); int SEC2 = 5;//allocating integer memory for storing seconds int SEC1 = 5; int MIN2 = 0;// allocating integer memory for storing minutes int MIN1 =0; int HOU2 =0;// allocating integer memory for storing hours int HOU1 =0; int ALMMIN2 = 1;// storing alarm minutes int ALMMIN1 =0; int ALMHOU2 =0;// storing alarm hours int ALMHOU1 =0; int ALMstatus=0; // pass 0 or 1 for alarm status 1-> on 0-> off void displayAlmststus(int ALMstatus); //print the alarm status to the display void setbuzzer(int MIN1,int MIN2,int HOU1,int HOU2,int ALMMIN1,int ALMMIN2,int ALMHOU1,int AIMHOU2,int ALMstatus); // compare the time value and alarm time int timer; int backtime=0; int main(void) { init_lcd(); char str[80]; char str1[80]; char ALM[80]; DDRC |=0b00000001; //set output to buzzer DDRC &= ~(1<<PCINT9); //set A1 as a input // new add DDRC &= ~(1<<PCINT10); //set A2 as a input DDRC &= ~(1<<PCINT11); //set A3 as a input DDRC &= ~(1<<PCINT12); //set A4 as a input DDRC &= ~(1<<PCINT13); //set A4 as a input //for the IR senser // alarm status button and backlight button DDRB &= ~(1<<PCINT3); //set 11 as a input DDRB &= ~(1<<PCINT4); //set 12 as a input DDRB |= (1<<PCINT2); //pin 10 output to the Backlight DDRD |=0b00000100; PORTD |=0b00000100; _delay_ms(10000); TCCR1B=(1<<WGM12); OCR1A = 15625; TIMSK1=(1<<OCIE1A); sei(); TCCR1B |=(1<<CS12)|(1<<CS10); sprintf(str1, "IBRAR"); stringout(str1); _delay_ms(10000); while (1) { // Loop forever moveto(0,0); sprintf(str, "%d%d:%d%d:%d%d",HOU1,HOU2,MIN1,MIN2,SEC1,SEC2);//send data to display stringout(str); moveto(0,9); sprintf(ALM, "ALM:"); stringout(ALM); if((PINC & 0x02)== 0x02 ) //If switch is pressed change min of Clock { MIN2++; _delay_ms(3000); if (MIN2 == 10) { MIN2 = 0; MIN1= MIN1 + 1; if (MIN1 == 6) { MIN1 =0; MIN2 =0; } } } if((PINC & 0x04)== 0x04 ) //If switch is pressed change hou of CLock { HOU2=HOU2+1; _delay_ms(3000); if (HOU1 ==2 && HOU2 == 4 ) { HOU2 = 0; HOU1 = 0; } else { if (HOU2==10) { HOU2=0; HOU1=HOU1+1; } } } // set the alarm mode if((PINC & 0x02)== 0x02 && (PINC & 0x04)== 0x04 ) { moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); ALMstatus =1; _delay_ms(3000); } // IR senser ditect if((PINC & 0b00100000)== 0b00100000 ) { backtime=SEC2; if(backtime < 5) { backtime+5; } if (backtime >= 5) { backtime-5; } _delay_ms(250); PORTB |= (1<<PCINT2); // ON backlight _delay_ms(250); } if((PINC & 0x08)== 0x08 ) //If switch is pressed change ALMmin { ALMMIN2++; ALMstatus=1; _delay_ms(3000); moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); if (ALMMIN2 == 10) { ALMMIN2 = 0; ALMMIN1= ALMMIN1 + 1; moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); if (ALMMIN1 == 6) { ALMMIN1 =0; ALMMIN2 =0; moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); } } } if((PINC & 0x10)== 0x10 ) //If switch is pressed change ALMHOU { ALMHOU2++; ALMstatus=1; _delay_ms(3000); moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); if (ALMHOU1 ==2 && ALMHOU2 == 4 ) { ALMHOU2 = 0; ALMHOU1 = 0; moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); } else { if (ALMHOU2==10) { ALMHOU2=0; ALMHOU1=ALMHOU1+1; moveto(1,0); sprintf(str1, "%d%d:%d%d:ALARM",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); } } } if((PINC & 0x08)== 0x08 && (PINC & 0x10)== 0x10 ) //If switch is pressed backlight on for 5 seconds { //backtime=SEC2; if(backtime < 5) { backtime+5; } if (backtime >= 5) { backtime-5; } _delay_ms(250); PORTB |= (1<<PCINT2); // ON backlight //PORTB &= ~(1<<PCINT2); // OFF backlight } // check the alarm button status and change the alarm mode _delay_ms(100); if((PINB & 0x10)== 0x10 ) { if (ALMstatus==0) { ALMstatus=1; _delay_ms(3000); setbuzzer(MIN1,MIN2,HOU1,HOU2,ALMMIN1,ALMMIN2,ALMHOU1,ALMHOU2,ALMstatus); } else { ALMstatus=0; _delay_ms(3000); setbuzzer(MIN1,MIN2,HOU1,HOU2,ALMMIN1,ALMMIN2,ALMHOU1,ALMHOU2,ALMstatus); moveto(1,0); sprintf(str1, " ",ALMHOU1,ALMHOU2,ALMMIN1,ALMMIN2);//send ALM data to display stringout(str1); } } displayAlmststus(ALMstatus); // calling the alarm function _delay_ms(200); moveto(0,14); setbuzzer(MIN1,MIN2,HOU1,HOU2,ALMMIN1,ALMMIN2,ALMHOU1,ALMHOU2,ALMstatus); } return 0; } ISR(TIMER1_COMPA_vect){ //This is the interrupt request SEC2++; //backlight off session //################################# if (SEC2 == backtime ) { PORTB &= ~(1<<PCINT2); // OFF backlight } //############################### if (SEC2 == 10) { SEC2 = 0; //backlight off session //################################# if (SEC2 == backtime ) { PORTB &= ~(1<<PCINT2); // OFF backlight } SEC1 = SEC1 +1; PORTB &= ~(1<<PCINT2); // OFF backlight if (SEC1 == 6) { SEC2 = 0; SEC1 = 0; MIN2 = MIN2 +1; if (MIN2 == 10) { MIN2 = 0; MIN1= MIN1 + 1; if (MIN1 == 6) { MIN1 =0; MIN2 =0; HOU2 = HOU2 +1; if (HOU2 ==10 && HOU1 == 1 || HOU1==0) { HOU2 = 0; HOU1 = HOU1 +1; } else{ HOU1 =0; HOU2 =0; } } } } } } void displayAlmststus(int ALMstatus){ // print alarm status char ALM[80]; if(ALMstatus == 0 ) { moveto(0,13); sprintf(ALM, "OFF"); stringout(ALM); } else { moveto(0,13); sprintf(ALM, " ON"); stringout(ALM); } } void setbuzzer(int MIN1,int MIN2,int HOU1,int HOU2,int ALMMIN1,int ALMMIN2,int ALMHOU1,int ALMHOU2,int ALMstatus){ if(ALMstatus == 1 ) { if (MIN1==ALMMIN1 && MIN2==ALMMIN2 && HOU1==ALMHOU1 && HOU2==ALMHOU2) { PORTC|=0b00000001; _delay_ms(1000); PORTC &= ~(0b00000001); _delay_ms(1000); } }else{ PORTC&=0b11111110; } } /* init_lcd - Configure the I/O ports and send the initialization commands */ void init_lcd() { /* ??? */ // Set the DDR register bits for ports B and D DDRD|=0xF0; DDRB|=0x03; _delay_ms(15); // Delay at least 15ms writecommand(0x03); /* ??? */ // Use writenibble to send 0011 _delay_ms(5); // Delay at least 4msec writecommand(0x03); /* ??? */ // Use writenibble to send 0011 _delay_us(120); // Delay at least 100usec /* ??? */ // Use writenibble to send 0011, no delay needed writecommand(0x03); writecommand(0x02); /* ??? */ // Use writenibble to send 0010 _delay_ms(2); // Delay at least 2ms writecommand(0x28); // Function Set: 4-bit interface, 2 lines _delay_ms(2); writecommand(0x0f); // Display and cursor on _delay_ms(25); writecommand(0x01); _delay_ms(25); //writecommand(1); } /* moveto - Move the cursor to the row (0 or 1) and column (0 to 15) specified */ void moveto(unsigned char row, unsigned char col) { if(row==0){ writecommand(0x80+col); } if(row==1){ writecommand(0xc0+col); } } /* stringout - Write the string pointed to by "str" at the current position */ void stringout(char *str) { do{ writedata(*str); str++; }while(*str!= '\0'); } /* writecommand - Send the 8-bit byte "cmd" to the LCD command register */ void writecommand(unsigned char cmd) { unsigned char temp; PORTB&=~(0x01); temp=cmd&0xF0; writenibble(temp); temp=cmd&0x0F; temp=temp<<4; writenibble(temp); _delay_ms(3); } /* writedata - Send the 8-bit byte "dat" to the LCD data register */ void writedata(unsigned char dat) { unsigned char temp; PORTB|=0x01; temp=dat&0xF0; writenibble(temp); temp=dat&0x0F; temp=temp<<4; writenibble(temp); _delay_ms(3); } /* writenibble - Send four bits of the byte "lcdbits" to the LCD */ void writenibble(unsigned char lcdbits) { PORTD = lcdbits;//&0xF0; //PORTB |= 0x02; PORTB &= ~(0x02); PORTB |= 0x02; PORTB &= ~(0x02); }
إرسال تعليق