This project would show you how to control an AC appliance remotely from anywhere using your mobile phone. This kind of project is useful in various applications. Say for example a farmer can switch ON or OFF the motor pump present near his field remotely. In this way he need not travel all the way to the field to control it, especially at night times.It is assumed that the reader has gone through the project How to get started with AVR and Interface LCD with AVR.
Components Required
1. ATMega16 Development board
2. LCD board
3. SIM 300/900 GSM Module
4. 12V/2A Power Supply
5. SIM card with balance (or at least message offer maybe)
6. SPDT Relay Switch
7. Transistor BC547
8. Diode 1N4007
9. 10k Resistor
10. A PC or a Laptop (Optional. Needed in case of debugging)
Initial Setup
See my previous tutorial “GSM BASED INTRUDER ALERTER” if you are using the GSM modem for the first time.
Fig. 1: Prototype of AVR ATMega16 and GSM Module based Mobile controlled Home Automation System
About Relays
The switches at our home need to be operated manually by hand or “mechanically triggered” in order to work. If we need to control the switch using a microcontroller which does nothing but produces 5V or 0V at its output pins then we would require extra mechanical arrangements like a servo with an arm, to press the switch. Instead of building such complicated arrangements we can go with a relay. These can directly be controlled by electrical means.
Working of Relay
Fig. 2: Image of LCd module attached to Home Automation System displaying appliance status
Fig. 3: Circuit Diagram showing NC connection of SPDT Relay
The above shown diagram is of a SPDT (Single Pole Double Throw) Relay. It consists of 5 terminals. Two of them are from the coil where the input to drive the relay is supposed to be given. The other three are NO (Normally Open), NC (Normally Closed) and COM (Common).
When no input is given to the coil, there is no magnetic field produced. So the “NC” and “COM” terminals are connected and the “NO” terminal is left free.
Fig. 4: Circuit Diagram showing NO connection of SPDT Relay
When the input is given, the current flowing through the coil produces magnetic field (Basic physics) and thus attracting the lever, which breaks the connection between “COM” à “NC” and makes a connection between “COM” à “NO” terminals.
Again when the input is removed, the spring attached to the lever pulls it back and “COM” à “NC” connection is re-established.
Free-wheeling diode
There is a problem in connecting a relay directly to an electronic circuit. When the input power is suddenly removed to switch OFF the relay, a voltage spike occurs due to the presence of the inductive load (The coil inside the relay is an inductor right?). This voltage spike can permanently damage the electronic circuit to which the relay is connected to. And thus we require a diode.
A diode connected in reverse bias with respect to the input supply, will prevent the voltage spike (produced by the relay when the supply is suddenly switched OFF) from reaching the other part of the control circuit.
Fig. 5: Circuit Diagram showing Free-Whelling Diode connected to Relayto prevent voltage spike
Next, we need something to supply enough current to the relay input so that it doesn’t trip unexpectedly. So we use a transistor in between microcontroller and relay. And the circuit becomes like this:
Fig. 6: Circuit Diagram of BC547 Transistor based Relay Driver
Advantages of Relay
No degradation of the switched signal.
1. Offers isolation between the AC supply and the Circuit.
2. Lower Impedance and easier to interface.
3. Robust.
Code Explanation
The code is build mostly around the library files “GSM.h” (Thanks to Engineers Garage tutorials) and “LCD.h” which contain the necessary functions for GSM modem interfacing and LCD interfacing.
GSM.h contains the following functions:
gsm_init() : Does the initial testing like checking for response after sending “ATr”, checks for the presence of SIM card, Network and then sets the modem into Text Mode.
gsm_read() : Tries to read the message stored at location ‘1’ of the SIM. If there is a message then it stores the first 9 characters of it in the array “msg[]”. Then checks if the string in “msg[]” matches with the keyword or not.
gsm_delete() : Deletes the message stored at location ‘1’ of the SIM.
gsm_waitfor(char c) : Waits for a particular characters specified in the variable ‘c’ . If the wait is longer than the timer set in the Watch Dog timer then the whole program resets.
Algorithm
1. Set PB2 as output and initialize the LCD function
2. Initialize the GSM modem and set the Message format to text mode.
3. Delete the message at location ‘1’ on the SIM.
4. Enter an infinite loop and check for an incoming message constantly.
5. If there is an incoming message, then store the number and the 1st nine characters of the message in the arrays “number[]” and “msg[]”.
6. Display the phone number and the message on the LCD screen.
7. Compare the saved message with the keyword “Motor on ”and if they match then set PB2 to high state.
8. Compare the saved message with the keyword “Motor off” and if they match then set PB2 to low state.
9. Delete the read message and go to the next iteration.
Trouble shooting
1. LCD doesn’t show anything/ Shows blocks on the first line
Adjust the potentiometer connected to the contrast pin/Make sure all the connections are right.
2. Motor doesn’t get turned ON
Check whether you are sending the correct message or not. Remember you need to add a space after “Motor on” and no space after “Motor off”. Check the LCD after sending the message to see if the controller is grasping your text correctly.
Project Source Code
### /* * gsmEG.c * * Created: 3/14/2014 1:21:32 PM * Author: GANESH SELVARAJ */ #define F_CPU 16000000UL #include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #include <string.h> #include "GSM.h" #include "lcd.h" void gsm_read() { int k; clrscr(); LCD_write_string("System Activated"); gotoxy(1,16); UART_Transmit_string("AT+CMGR=1r"); gsm_waitfor('r'); gsm_waitfor('n'); if(UART_Receive()=='+') { gsm_waitfor('M'); if(UART_Receive()=='G') { gsm_waitfor('A'); gsm_waitfor(','); gsm_waitfor('"'); for(k=0;k<13;k++) number[k] = UART_Receive(); gsm_waitfor(','); gsm_waitfor(','); gsm_waitfor('+'); gsm_waitfor('n'); for(k=0;k<9;k++) msg[k]=UART_Receive(); gsm_waitfor('K'); gsm_waitfor('n'); _delay_ms(300); clrscr(); LCD_write_string("Ph:"); LCD_write_string(number); gotoxy(1,0); LCD_write_string("Msg:"); LCD_write_string(msg); _delay_ms(2000); if(!strcmp(msg,"Motor on ")) { PORTB |= (1<<PB2); } if(!strcmp(msg,"Motor off")) { PORTB &= ~(1<<PB2); } gsm_delete(); } } _delay_ms(1000); } int main(void) { DDRB |= (1<<PB2); lcd_init(); LCD_write_string("Initializing... "); gsm_init(); gsm_delete(); while(1) { gsm_read(); } return 0; } GSM #ifndef GSM #define GSM #include <avr/io.h> #include <util/delay.h> #include <string.h> #include <avr/wdt.h> #include <avr/interrupt.h> #include "lcd.h" char msg[10]; char number[14]; int i,j; void UART_Init( unsigned int baud ); void UART_Transmit_char( unsigned char data ); unsigned char UART_Receive( void ); void UART_Transmit_string( char *string ); void UART_Init( unsigned int baud ) { /* Set baud rate */ UBRRH = (unsigned char)(baud>>8); UBRRL = (unsigned char)baud; /* Enable receiver and transmitter */ UCSRB = (1<<RXEN)|(1<<TXEN); /* Set frame format: 8data, 1stop bit */ UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0); } void UART_Transmit_char( unsigned char data ) { /* Wait for empty transmit buffer */ while ( !( UCSRA & (1<<UDRE)) ) ; /* Put data into buffer, sends the data */ UDR = data; } unsigned char UART_Receive( void ) { /* Wait for data to be received */ while ( !(UCSRA & (1<<RXC)) ) ; /* Get and return received data from buffer */ return UDR; } void UART_Transmit_string( char string[] ) { int i=0; while ( string[i] > 0) UART_Transmit_char(string[i++]); } /*************************************************************/ void gsm_init(void); void gsm_read(void); void gsm_send(char *number,char *string); void gsm_delete(void); void gsm_waitfor(char c); void gsm_waitfor(char c) { //enabling watchdogtimer with a time of 2.1secs wdt_enable(7); //waiting for the byte to be received while(UART_Receive()!= c); //resetting watchdogtimer and turning off the watchdogtimer wdt_reset(); wdt_disable(); } void gsm_init() { UART_Init(103); // baudrate=9600 gotoxy(1,0); LCD_write_string(" Testing Modem "); _delay_ms(500); UART_Transmit_string("ATr"); gsm_waitfor('O'); gsm_waitfor('K'); gotoxy(1,0); LCD_write_string(" Modem : OK "); _delay_ms(1000); INS: gotoxy(1,0); LCD_write_string(" Checking SIM "); _delay_ms(500); UART_Transmit_string("AT+CSMINS?r"); gsm_waitfor( 'n'); gsm_waitfor(','); if(UART_Receive() == '2') { gotoxy(1,0); LCD_write_string(" SIM NOTFOUND "); _delay_ms(1000); goto INS; } else if(UART_Receive() == '1'); gsm_waitfor( 'K'); gsm_waitfor( 'n'); gotoxy(1,0); LCD_write_string(" SIM FOUND "); _delay_ms(1000); REG: gotoxy(1,0); LCD_write_string(" Network Status "); _delay_ms(500); UART_Transmit_string("AT+CREG?r"); gsm_waitfor( 'n'); gsm_waitfor(','); if(UART_Receive() == '2') { gotoxy(1,0); LCD_write_string("Network NotFound"); _delay_ms(1000); goto REG; } else if(UART_Receive() == '1'); gsm_waitfor( 'K'); gsm_waitfor( 'n'); gotoxy(1,0); LCD_write_string(" Network Found "); _delay_ms(1000); UART_Transmit_string("AT+CMGF=1r"); gotoxy(1,0); LCD_write_string("Setting Textmode"); gsm_waitfor('O'); gsm_waitfor('K'); gotoxy(1,0); LCD_write_string(" Textmode set "); _delay_ms(1000); } void gsm_delete() { UART_Transmit_string("AT+CMGD=1r"); gsm_waitfor('K'); gsm_waitfor('n'); _delay_ms(500); } #endif LCD #include<avr/io.h> #include<util/delay.h> #include<inttypes.h> #include "lcd.h" void LCD_write_string(const char *str) //store address value of t he string in pointer *str { int i=0; while(str[i]!='