Friday 30 May 2014

Smart Home Automation using AVR

In this technological world, automatic systems are being preferred over manual system. In this series Home Automation plays an important role for humans. In this unit we talk about basic needs to understand the project well and also for its future advancements.
We are going to talk about different types of sensors (i.e. Temperature Sensor, LPG Gas Sensor, LDR) and input and output devices (i.e. 2x2 matrix Keypad, Buzzer, DC Motor, 16x2 Char LCD Display, Power Supply section etc.). Now we are going to Interface all those with the brain of the system ‘Microcontroller(i.e. ATmega16/16L)’ and let’s find out what the individual role of each component are and how they act as Smart Home System together.
BLOCK DIAGRAM
Smart Home Automation
BLOCK DIAGRAM DESCRIPTION
MQ-5 LPG SENSOR
It senses the leakage of LPG. The out put of this sensor is ‘high’ at normal condition. The output goes low, when it senses the LPG.
LDR
LDR is used to check Sun light intensity; so that we can know it is Day or Night.
LM35 Temp Sensor
It is used to measure room temperature and give it to microcontroller for desirable action.
16x2 Char LCD Display
It is used to display all sensors’ value and action taken by system on display.
2x2 Matrix Keypad
It is used for enter password to access the door.
DC Motor
It is used for opening and closing the door.
WORKING PRINCIPLE
In this project I used three analog sensors i.e. Temp, LPG Gas and LDR. These are given analog output. So as per interfacing required, I connected all the analog output of the sensors to in-build ADC to get digital values and keypad, DC Motor, LCD Display, buzzer, transistors and LED’s to i/o pins of the microcontroller. For connections, please refer schematic diagram as given below.
Now when power on, first Red LED indicates the power status of the system and if it is then all peripherals are initialized and their current value will be displayed on LCD after welcome message ‘WELCOME TO SMART HOME’. Now every sensor has their threshold value according to ADC conversion mentioned in C Source Code according to the requirements and all o/p device are controlled by microcontroller based on sensors output and act accordingly. We can change those threshold values according to our need by changing in C Source code any time.
For better understanding, let’s take the example of Temp sensor. After ADC process, in my project I assign 50*C as a threshold for temp sensor. So when the temp sensor’s ADC value rises more than its threshold value that point of time microcontroller gives signal to buzzer for beeping and LCD to display ‘Temp Increased’ and if value is under the threshold value, then everything is normal. So like this, every sensor has its threshold value and microcontroller always compare the current ADC value with threshold value and if it exceeded, desirable action takes place by the microcontroller.
I have also interfaced to NPN (BC547) transistor for relay to operate. If I want to switch ON/OFF any AC device according to Temp Sensor or LDR, I can connect relay to transistor to operate.
This home automation project has three different LED with different colour. First is Red colour LED, which indicates about power supply in the system. Second is Blue colour, which indicates the LPG Gas leakage and third is White colour which indicates the ON/OFF state of transistors.
I have also interfaced a 2x2 Matrix keypad which is used to type password to open the door.
In my code, ‘123’ is the password to open the door. When you pressed ‘123’ by keypad shown in diagram and a ‘enter’ button is also there with ‘enter’ signed. When you pressed ‘enter’ button, your current password is compared with password written in C source code. If it is right, then DC motor rotates and door will be open, if wrong then a short beep by buzzer and a message ‘Wrong Pass’ will be displayed on LCD. Now you have to try again.
So in this way every component and circuit has its individual role which is continuous monitored by microcontroller. 
MICROCONTROLLER CIRCUIT WITH PHERIPHERALS
Smart Home Automation

POWER SUPPLY
Power supply for the complete unit can be derived from the mains using a step-down transformer of 230V AC primary to 0-12V, 500mA secondary. A full- wave rectifier followed by a capacitor filter is the output voltage and feeds it to the 5-volt regulator (LM7805) whose output is used to the power supply requirements of microcontroller circuit, other IC’s.
Power Supply Circuit Diagram

Power Supply DIY


FLOWCHART

CONCLUSION
An automated home can be easily implemented with the grouping of simple controls or it can be more compelled if we are going to use electrical appliances or remote controlled electrical appliances. A compelled system cost more than this in different parameters.
Well more knowledge is gained and more experiences are faced. Lot of information’s are collected ultimately, I have concluded with a great pleasure for achieving our aim.
 I have planned to fulfill my technical requirements. The knowledge I have attained with this project really would follow till the end of my career.
DEMO VIDEO:

For code contact me ...    

Wednesday 14 May 2014

Bluetooth controlled Robot

In the previous tutorial I have explained how to setup a basic serial connection between an Atmega16 controller Board and a computer/laptop. In this article we’ll learn how to control a robot using the computer/laptop wirelessly through Bluetooth.
Components Required
1. Atmega16 development board with 16MHz crystal 2. Serial Bluetooth Module(AUBTM/HC-05/HC-04/BLUSMIRF) 3.PC/Laptop running Windows XP/7/8 4.USB Bluetooth(Not required if you laptop/PC has inbuilt hardware) 5.Motor Driver L293D 6.2 X 12V 100RPM Geared DC motor 7.2 X Wheels 8.Chassis 9. Castor wheel 10.Female jumper wires
Software Required
Serial Port Software on your PC (RealTerm/HyperTerminal/TeraTerm/Putty/ Your own Program)
Block-Diagram
Wireless Robot
Mechanical Construction:

Mechanical Assembly for Wireless Robot
Let us start with the hardware assembly part first. It should be simple since we are using a ready-made chassis. Start by attaching the motors and castor wheel to the chassis.

Mechanical Assembly for Robot
Next attach the wheels to the motor shafts using the screw provided on the wheel.

Attaching wheels to a robot

Robot Body
Connect the wires emerging from the two motors to the output pins of the L293D motor driver.
Mechanical robot machine
 After all connections are made, this is how it looks.

Fully Assembled Mechanical Robot
 Remember: RX (PIN 14) of controller to TX of modem and TX (PIN 15) of controller to RX of modem.
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
// Right motor ( + ) = PB1 , Right motor ( - ) = PB2
// Left motor ( + ) = PB4 , Left motor ( - ) = PB3
void USARTInit(uint16_t ubrr_value)
{
   //Set Baud rate
   UBRRL = ubrr_value;
   UBRRH = (ubrr_value>>8);
   /*Set Frame Format
   >> Asynchronous mode
   >> No Parity
   >> 1 StopBit
   >> char size 8
   */
   UCSRC=(1<<URSEL)|(3<<UCSZ0);
   //Enable The receiver and transmitter
   UCSRB=(1<<RXEN)|(1<<TXEN);
}
//This function is used to read the available data
//from USART. This function will wait untill data is
//available.
char USARTReadChar()
{
   //Wait untill a data is available
  while(!(UCSRA & (1<<RXC)))
   {
      //Do nothing
   }
   //Now USART has got data from host
   //and is available is buffer
   return UDR;
}
//This fuction writes the given "data" to
//the USART which then transmit it via TX line
void USARTWriteChar(char data)
{
   //Wait untill the transmitter is ready
   while(!(UCSRA & (1<<UDRE)))
   {
      //Do nothing
   }
   //Now write the data to USART buffer
UDR=data;
}
void main()
{
   DDRB=0b00011110;  //PB1, PB2, PB3, PB4 as output port
  //Varriable Declaration
   char data;
/*First Initialize the USART with baud rate = 9600bps
    for Baud rate = 9600bps

   UBRR value = 12 //// 1Mhz // atmega16
   // For 16 Mhz check the UBRR value in datasheet
   */
 USARTInit(12);    //UBRR = 12
 //Loop forever
while(1)
   {
      //Read data
    data=USARTReadChar();
   if((data==t))
{
PORTB=0b00000000;  //stop
}

if((data==d))
                                 
{

PORTB=0b00010000;    //turn right
}

if((data==a))
                                 
{

PORTB=0b00000010;   //turn left

}
              if((data==w))
{
PORTB=0b00010010;  //move forward

}
             if((data==s))
{
PORTB=0b00001100;  //move reverse

}
   }
}

NOTE : if you r facing any problem info me.

Monday 12 May 2014

Sending and Receiving SMS using SIM300 or SIM900 GSM Module

schematic to interface with GSM Module


                                     
Hi friends in this part we will have a look at the functions related to text messages. By the end of this article you will have a clear idea of how to wait for a text message, read the message, send a new text message and deleted a received message. 

Waiting for a text message (SMS)

When a text message (SMS) arrives on SIM300 GSM Module it sends a unsolicited response <CR><LF>+CMTI: <mem>,<n><CR><LF>
I have already told in previous article that <CR> refers to a control character whose ASCII is 0D (Hex) and <LF> with ASCII code of 0A(Hex). The new thing you will learn about is unsolicited response. Earlier I told commands are followed by response. But the response discussed above is not followed by any command, it can come at any moment. So it is called an unsolicited response.
value of mem is the storage location where the sms was stored. Usually its value is SM, which stands for SIM memory.
the value of n is the sms slot on which the incoming message was stored. Depending on the size of storage in your SIM card their may me 20 or so slots in your card. When a message is received it is stored in the lowest numbered empty slot. For example you first received 4 messages then deleted the 1st message, then 5th message will get stored in slot 1.
Code Example showing how Wait for a message.

int8_t   SIM300WaitForMsg(uint8_t *id)
{
   //Wait for a unsolicited response for 250ms  
   uint8_t len=SIM300WaitForResponse(250);

   if(len==0)
      return SIM300_TIMEOUT;

   sim300_buffer[len-1]='\0';

   //Check if the response is +CMTI (Incoming msg indicator)
   if(strncasecmp(sim300_buffer+2,"+CMTI:",6)==0)
   {
      char str_id[4];

      char *start;

      start=strchr(sim300_buffer,',');
      start++;

      strcpy(str_id,start);

      *id=atoi(str_id);

      return SIM300_OK;
   }
   else
      return SIM300_FAIL;
}
Code Walkthrough
  1. We wait for a response from SIM300 with a time-out of 250 millisecond. That means if nothing comes for 250 millisecond we give up!
  2. If we get a response, SIM300WaitForResponse() returns its length till trailing <CR>. So suppose we got <CR><LF>+CMTI: SM,1<CR><LF> then len will be 14.
  3. Next line sim300_buffer[len-1]='\0'; puts an NULL character at position len - 1 that is 13(points to last <CR>). So the response actually becomes <CR><LF>+CMTI: SM,1
  4. Now we want to check if the first 6 characters are +CMTI: or not, we check first 6 characters only because the <n> following +CMTI is variable. Remember it is the slot number where the message is stored! Also while comparing we want to ignore the case, that means +CMTI or +cMtI are same. This type of string comparison is easily done using the standard C library function strncasecmp(). Well if you have ever attended a C training session in school you must have remembered strcmp() , so you can look strncasecmp().So you can see only an n and case is added in the name of the function. n in the name indicate you don't have to compare the whole string, you can check the first n characters. While the case in the name indicate a case in-sensitive match. Also you notice we don't passsim300_buffer (which holds the response) directly to the comparison function, but we passsim300_buffer + 2, this removes the leading <CR><LF> in the response string.
  5. If the response matches the next step is to extract the value of <n>, i.e. the message slot id. As you can see the slot id is after the first comma(,) in the response. So we search for the position of first comma in the response. This is done using strchr() standard library function. Now start points to a string which is ",1".
  6. The we do start++, this makes start points to a string which is "1", but remember it is still a string. So we use standard library function atoi() which converts a string to a integer. Which we store in *id. Remember the parameter id is pass by reference type, if you don't know what does that means go and revise your C book!
  7. Finally we return SIM300_OK which is a constant defined in sim300.h indicating a success to caller.

Reading the Content of Text Message

The command that is used to read a text message from any slot is AT+CMGR=<n> where <n> is an integer value indicating the sms slot to read. As I have already discussed that their are several slots to hold incoming messages.
The response is like this
+CMGR: "STATUS","OA",,"SCTS"<CR><LF>Message Body<CR><LF><CR><LF>OK<CR><LF>
where STATUS indicate the status of message it could be REC UNREAD or REC READ
OA is the Originating Address that means the mobile number of the sender.
SCTS is the Service Center Time Stamp.
This is a simple example so we discard the first line data i.e. STATUS, OA and SCTS. We only read the Message Body.
One of the most interesting thing to note is that three things can happen while attempting to read a message ! They are listed below.
  1. Successful read in that case the response is like that discussed above.
  2. Empty slot ! That means an attempt has been make to read a slot that does not have any message stored in it. In this case the response is <CR><LF>OK<CR><LF>
  3. SIM card not ready! In this case +CMS ERROR: 517 is returned.
Our function handles all the three situations.

int8_t   SIM300ReadMsg(uint8_t i, char *msg)
{
   //Clear pending data in queue
   UFlushBuffer();

   //String for storing the command to be sent
   char cmd[16];

   //Build command string
   sprintf(cmd,"AT+CMGR=%d",i);

   //Send Command
   SIM300Cmd(cmd);

   uint8_t len=SIM300WaitForResponse(1000);

   if(len==0)
      return SIM300_TIMEOUT;

   sim300_buffer[len-1]='\0';

   //Check of SIM NOT Ready error
   if(strcasecmp(sim300_buffer+2,"+CMS ERROR: 517")==0)
   {
      //SIM NOT Ready
      return SIM300_SIM_NOT_READY;
   }

   //MSG Slot Empty
   if(strcasecmp(sim300_buffer+2,"OK")==0)
   {
      return SIM300_MSG_EMPTY;
   }

   //Now read the actual msg text
   len=SIM300WaitForResponse(1000);

   if(len==0)
      return SIM300_TIMEOUT;

   sim300_buffer[len-1]='\0';
   strcpy(msg,sim300_buffer+1);//+1 for removing trailing LF of prev line

   return SIM300_OK;
}
Code Walkthrough
  1. Clear pending data in the buffer.
  2. A command string is built using the standard library function sprintf().
    1. sprintf(cmd,"AT+CMGR=%d",i);
    2. You must be knowing that the above code gives a string in which placeholder %d is replaced by the value of i.
  3. Command is sent to the SIM300 module.
  4. Then we wait for the response.
  5. Response is analyzed.
  6. Finally messages is read and copied to the memory address pointed by *msg using standard library function strcpy().

Sending a New Text Message

We will develop a function to easily send message to any mobile number. This function has the argument
  • num (IN) - Phone number where to send the message ex "+919939XXXXXX"
  • msg (IN) - Message Body ex "This a message body"
  • msg_ref (OUT) - After successful send, the function stores a unique message reference in this variable.
The function returns an integer value indicating the result of operation which may be
  • SIM300_TIMEOUT - When their is some problem in communication line or the GSM module is not responding or switched off.
  • SIM300_FAIL - Message Sending Failed. A possible reason may be not enough balance in your prepaid account !
  • SIM300_OK - Message Send Success!

int8_t   SIM300SendMsg(const char *num, const char *msg,uint8_t *msg_ref)
{
   UFlushBuffer();

   char cmd[25];

   sprintf(cmd,"AT+CMGS= %s",num);

   cmd[8]=0x22; //"

   uint8_t n=strlen(cmd);

   cmd[n]=0x22; //"
   cmd[n+1]='\0';

   //Send Command
   SIM300Cmd(cmd);

   _delay_ms(100);

   UWriteString(msg);

   UWriteData(0x1A);
 
 //Wait for echo
   while(   UDataAvailable()<(strlen(msg)+5)   );

   //Remove Echo
   UReadBuffer(sim300_buffer,strlen(msg)+5);

   uint8_t len=SIM300WaitForResponse(6000);

   if(len==0)
      return SIM300_TIMEOUT;

   sim300_buffer[len-1]='\0';

   if(strncasecmp(sim300_buffer+2,"CMGS:",5)==0)
   {

      *msg_ref=atoi(sim300_buffer+8);

      UFlushBuffer();

      return SIM300_OK;
   }
   else
   {
      UFlushBuffer();
      return SIM300_FAIL;
   }
}

Code Walkthrough
  1. The beginning of the function implementation is similar to those done above, first we flush the buffer and build command string. Command string must be like this :-
    • AT+CMGS=<DA>, Where DA is the destination address i.e. the mobile number like AT+CMGS="+919939XXXXXX"
    • This function sprintf(cmd,"AT+CMGS= %s",num); gives a string like this AT+CMGS= +919939XXXXXX
    • cmd[8]=0x22//" this like replaces the space just before +91 with " so we have a string like this AT+CMGS="+919939XXXXXX
    • cmd[n]=0x22//" this adds a " in the end also so the string becomes AT+CMGS="+919939XXXXXX", but caution it removes the '\0' the null character that must be present to mark the end of string in C. So the following statement adds a NULL character at the end.
    • cmd[n+1]='\0';
  2. Then we send the command string prepared above.\
  3. We now write the message body to SIM300 module using the function UWriteString(msg);
  4. UWriteData(0x1A);Is used to send the control character called EOF (End of File) to mark the end of message.
  5. Since SIM300 echoes back everything we write to it, so we remove the echo by reading the data from the buffer.
  6. Finally we wait for the response, read the response and compare it to find out whether we succeeded or not.

Deleting a Text Message

This function takes an integer input which should be slot number of the message you wish to delete. Function may return the following values.
  • SIM300_TIMEOUT - When their is some problem in communication line or the GSM module is not responding or switched off.
  • SIM300_FAIL - Message Deleting Failed. A possible reason may be an incorrect slot number id.
  • SIM300_OK - Message Delete Success!
AT command of deleting a message is AT+CMGD=<n> where n is an slot of number of message you wish to delete. If delete is successful it returns OK. The function implementation is very simple compared to above functions. The steps are similar, that involves building a command string, sending command, waiting for response and verifying response.

int8_t   SIM300DeleteMsg(uint8_t i)
{
   UFlushBuffer();

   //String for storing the command to be sent
   char cmd[16];

   //Build command string
   sprintf(cmd,"AT+CMGD=%d",i);

   //Send Command
   SIM300Cmd(cmd);

   uint8_t len=SIM300WaitForResponse(1000);

   if(len==0)
      return SIM300_TIMEOUT;

   sim300_buffer[len-1]='\0';

   //Check if the response is OK
   if(strcasecmp(sim300_buffer+2,"OK")==0)
      return SIM300_OK;
   else
      return SIM300_FAIL;
}

SIM300 Message Send Receive Demo

To show all the above functions in working demo we have developed a small program. This program does all the basic routine task on boot up, that include the following :-
  • Initialize the LCD Module and the SIM300 GSM Module.
  • Print IMEI, Manufacturer name and model name.
  • Then it checks SIM card presence and connects to network.
  • When network connection succeeds its show name of the network. Eg. Airtel or Vodafone etc.
  • Finally it sends a message with message body "Test".
  • Then it waits for a message, when a message arrives reads it and displays on LCD.
  • Then the message is deleted.

/******************************************************************************

A basic demo program showing sms functions.

*******************************************************************************/


#include <avr/io.h>
#include <util/delay.h>

#include "lib/lcd/lcd.h"
#include "lib/sim300/sim300.h"


void Halt();
int main(void)
{
   //Initialize LCD Module
   LCDInit(LS_NONE);

   //Intro Message
   LCDWriteString("SIM300 Demo !");
   LCDWriteStringXY(0,1,"By kannupandiyan");

   _delay_ms(1000);

   LCDClear();


   //Initialize SIM300 module
   LCDWriteString("Initializing ...");
   int8_t r= SIM300Init();

   _delay_ms(1000);

   //Check the status of initialization
   switch(r)
   {
      case SIM300_OK:
         LCDWriteStringXY(0,1,"OK !");
         break;
      case SIM300_TIMEOUT:
         LCDWriteStringXY(0,1,"No response");
         Halt();
      case SIM300_INVALID_RESPONSE:
         LCDWriteStringXY(0,1,"Inv response");
         Halt();
      case SIM300_FAIL:
         LCDWriteStringXY(0,1,"Fail");
         Halt();
      default:
         LCDWriteStringXY(0,1,"Unknown Error");
         Halt();
   }

   _delay_ms(1000);

   //IMEI No display
   LCDClear();

   char imei[16];

   r=SIM300GetIMEI(imei);

   if(r==SIM300_TIMEOUT)
   {
      LCDWriteString("Comm Error !");
      Halt();
   }

   LCDWriteString("Device IMEI:");
   LCDWriteStringXY(0,1,imei);

   _delay_ms(1000);

   //Manufacturer ID
   LCDClear();

   char man_id[48];

   r=SIM300GetManufacturer(man_id);

   if(r==SIM300_TIMEOUT)
   {
      LCDWriteString("Comm Error !");
      Halt();
   }

   LCDWriteString("Manufacturer:");
   LCDWriteStringXY(0,1,man_id);

   _delay_ms(1000);

   //Manufacturer ID
   LCDClear();

   char model[48];

   r=SIM300GetModel(model);

   if(r==SIM300_TIMEOUT)
   {
      LCDWriteString("Comm Error !");
      Halt();
   }

   LCDWriteString("Model:");
   LCDWriteStringXY(0,1,model);

   _delay_ms(1000);



   //Check Sim Card Presence
   LCDClear();
   LCDWriteString("Checking SIMCard");

   _delay_ms(1000);

   r=SIM300IsSIMInserted();

   if (r==SIM300_SIM_NOT_PRESENT)
   {
      //Sim card is NOT present
      LCDWriteStringXY(0,1,"No SIM Card !");

      Halt();
   }
   else if(r==SIM300_TIMEOUT)
   {
      //Communication Error
      LCDWriteStringXY(0,1,"Comm Error !");

      Halt();
   }
   else if(r==SIM300_SIM_PRESENT)
   {
      //Sim card present
      LCDWriteStringXY(0,1,"SIM Card Present");

      _delay_ms(1000);
   }

   //Network search
   LCDClear();
   LCDWriteStringXY(0,0,"SearchingNetwork");

   uint8_t     nw_found=0;
   uint16_t tries=0;
   uint8_t     x=0;

   while(!nw_found)
   {
      r=SIM300GetNetStat();

      if(r==SIM300_NW_SEARCHING)
      {
         LCDWriteStringXY(0,1,"%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0");
         LCDWriteStringXY(x,1,"%1");
         LCDGotoXY(17,1);

         x++;

         if(x==16) x=0;

         _delay_ms(50);

         tries++;

         if(tries==600)
            break;
      }
      else
         break;

   }
   LCDClear();

   if(r==SIM300_NW_REGISTERED_HOME)
   {
      LCDWriteString("Network Found");
   }
   else
   {
      LCDWriteString("Cant Connt to NW!");
      Halt();
   }

   _delay_ms(1000);

   LCDClear();

   //Show Provider Name
   char pname[32];
   r=SIM300GetProviderName(pname);

   if(r==0)
   {
      LCDWriteString("Comm Error !");
      Halt();
   }

   LCDWriteString(pname);

   _delay_ms(1000);

   //Send MSG
   LCDClear();
   LCDWriteString("Sending Msg");

   uint8_t ref;


   r=SIM300SendMsg("+919939XXXXXX","Test",&ref);//Change phone number to some valid value!

   if(r==SIM300_OK)
   {
      LCDWriteStringXY(0,1,"Success");
      LCDWriteIntXY(9,1,ref,3);
   }
   else if(r==SIM300_TIMEOUT)
   {
      LCDWriteStringXY(0,1,"Time out !");
   }
   else
   {
      LCDWriteStringXY(0,1,"Fail  !");
   }

   _delay_ms(2000);

   //Wait for MSG
   uint8_t id;

   UFlushBuffer();

   while(1)
   {
      LCDClear();

      LCDWriteStringXY(0,0,"Waiting for msg");

      x=0;
      int8_t vx=1;

      while(SIM300WaitForMsg(&id)!=SIM300_OK)
      {
         LCDWriteStringXY(0,1,"%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0");
         LCDWriteStringXY(x,1,"%1");
         LCDGotoXY(17,1);

         x+=vx;

         if(x==15 || x==0) vx=vx*-1;
      }

      LCDWriteStringXY(0,1,"MSG Received    ");

      _delay_ms(1000);

      //Now read and display msg
      LCDClear();
      char msg[300];

      r=SIM300ReadMsg(id,msg);

      if(r==SIM300_OK)
      {

         LCDWriteStringXY(0,0,msg);

         _delay_ms(3000);

      }
      else
      {
         LCDWriteString("Err Reading Msg !");

         _delay_ms(3000);

      }

      //Finally delete the msg
      if (SIM300DeleteMsg(id)!=SIM300_OK)
      {
         LCDWriteString("Err Deleting Msg !");

         _delay_ms(3000);
      }

   }


   Halt();
}

void Halt()
{
   while(1);
}

Downloads