[TUT][GCC][SOFT] AVR GSM module SIM800(FONA)

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear Freaks,

This is my first tutorial so please be patiend.

This tutorial works with atmega16 and FONA sim800L and avr studio5  but i think that works fine with any avr and any module with SIM chipg.

 

1)First of all we must read the sim800 at commands <a href="https://www.adafruit.com/datashe...">pdf</a>.

We understaund that this module communicates with usart. So first of all we have to check if everything is ok connecting the gsm with a terminal of our PC.

 

2)I use this  <a href="https://sites.google.com/site/te...">terminal</a>. You can use any.

 

3)This is an other<a href="https://learn.adafruit.com/downl...">pdf</a>who sais how to connect FONA with your PC. If you do not use arduino IDE read until the page 30.

If you do not have adafruits usb to serial converter you can use any using this circuit.

I use 5Volt power supply(the same with avr) and i connect a diode(any diode) from vio(diode:A) to batery(diode:K) because i do not want to use a battery.

 

So from  the step 2 and the circuit of step 3 we connect the gsm module to our PC.

 

4)We setup out module  <AT>

We check the signal state <AT+CSQ>

And we send some sms or phone calls to "play" with our module.

 

5)If we are fine we connect the module to our avr. Now we do not use MAX232 to connect the module with our AVR. We just connect (GSM)TX->(AVR)RX and (GSM)RX->(AVR)TX and of cource the (GSM)GND to (AVR)GND.

 

6) Lets write some code.

First of all we need to set up avr usart.

I use 16MHZ clock and 9600bps to my usart. I prefer to use interupt receive usart because i do not want to miss any data.

 

6.1)Setting up th usart(For Atmega16)  <a href="http://www.avrfreaks.net/forum/t...">TUT</a>

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}

int main(void)
{serial_init();

}

ISR ( USART_RXC_vect )
{

}

 

 

6.2)Because we use not just chars but strings we need to make a serial buffers to receive and transmit the data.

 

So we create 2 voids the first transmits chars and the second the strings.

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}

int main(void)
{serial_init();

}

ISR ( USART_RXC_vect )
{

}

And we create a character array who receives the data.

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;
int main(void)
{serial_init();

}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR; a++;

}

6.3) For make our life easier we use this struct and we create a uint_8t memory for using some bits. <a href="http://www.avrfreaks.net/forum/t...">TUT</a>

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

 uint8_t  mem=0;
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define   SBIT(x,y)       SBIT_(x,y) 

#define INTERUPT          SBIT( mem, 0 )
#define INDEX_SMS          SBIT( mem, 1 )
#define DECODE_SMS         SBIT( mem, 2 )

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;
int main(void)
{

}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR; a++;

}

6.4) Now we need a void who clears our serial receive bufferser_rec

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

 uint8_t  mem=0;
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define   SBIT(x,y)       SBIT_(x,y) 

#define INTERUPT          SBIT( mem, 0 )
#define INDEX_SMS          SBIT( mem, 1 )
#define DECODE_SMS         SBIT( mem, 2 )

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;

void clear_sec_rec(){
    i=0;  while( i<=100){ ser_rec[i]==0;i++;} i=0;a=0;
    }	

int main(void)
{

}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR; a++;

}

6.5) now we are going to make a void who inits the GSM

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

 uint8_t  mem=0;
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define   SBIT(x,y)       SBIT_(x,y) 

#define INTERUPT          SBIT( mem, 0 )
#define INDEX_SMS          SBIT( mem, 1 )
#define DECODE_SMS         SBIT( mem, 2 )

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;

void clear_sec_rec(){
    i=0;  while( i<=100){ ser_rec[i]==0;i++;} i=0;a=0;
    }
void gsm_init(){
UART_Transmit_string("AT\r");_delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
//send some times AT to set up the gsm
UART_Transmit_string("AT+CMGF=1\r"); _delay_ms(200);//set text mode

UART_Transmit_string("ATE0\r"); _delay_ms(200);//disable ECHO

}
int main(void)
{serial_init();
    gsm_init();
}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR; a++;

}

 

 

6.6) Now we are going to make a void who sends SMS.

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

 uint8_t  mem=0;
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define   SBIT(x,y)       SBIT_(x,y) 

#define INTERUPT          SBIT( mem, 0 )
#define INDEX_SMS          SBIT( mem, 1 )
#define DECODE_SMS         SBIT( mem, 2 )

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;

void clear_sec_rec(){
    i=0;  while( i<=100){ ser_rec[i]==0;i++;} i=0;a=0;
    }
void gsm_init(){
UART_Transmit_string("AT\r");_delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
//send some times AT to set up the gsm
UART_Transmit_string("AT+CMGF=1\r"); _delay_ms(200);//set text mode

UART_Transmit_string("ATE0\r"); _delay_ms(200);//disable ECHO

}
    void gsm_send_AVRFREAK(){
UART_Transmit_string("AT+CMGS=");
UART_Transmit_char(34);
 UART_Transmit_string("xxxxxx");//the phone number
 UART_Transmit_char(34);
 UART_Transmit_string("\r");
  _delay_ms(3000);
UART_Transmit_string("AVRFREAK\r");_delay_ms(3000);
UART_Transmit_char(0x1A);
  _delay_ms(3000);
}

int main(void)
{  serial_init();
    gsm_init();//init gsm
    gsm_send_AVRFREAK();//sends sms
}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR; a++;

}

6.7) the hard part is to receive the sms.

 

Lets say that our system waits an sms to do PORTC.0=1. 

 

a)First of all we declaire the PORTC.0->Relay

b)The SMS must be K1=1 for this code

c) when the GSM receives the message is going to transmit to the AVR this: +CMTI: "SM",x (x=1,2,3,4...sms index)

d)to read the message we need to transmit this: AT+CMGR=x (x=1,2,3,4...sms index)

e) and the gms will transmit something like this: 

+CMGR: "REC UNREAD","+30xxx(phone number)","","15/10/31,18:52:52+08"
K1=1 (or whatever you write to the SMS)

 

1)So to read a SMS we first need to get the sms index (x).

2)Then to send it with this AT command  AT+CMGR

3) and finaly to understaund if the message is this who activates the PIN.

4)delete the message

 

The logic of the code is to activate a Bit of a memory (mem) when we have interupt after we wait some secs. and then we read the receive bufer ser_rec

 

6.7.1) This part of code gets the sms index and ask from the gsm the text message.

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

 uint8_t  mem=0;
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define   SBIT(x,y)       SBIT_(x,y) 

#define INTERUPT          SBIT( mem, 0 )
#define INDEX_SMS          SBIT( mem, 1 )
#define DECODE_SMS         SBIT( mem, 2 )

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;

void clear_sec_rec(){
    i=0;  while( i<=100){ ser_rec[i]==0;i++;} i=0;a=0;
    }
void gsm_init(){
UART_Transmit_string("AT\r");_delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
//send some times AT to set up the gsm
UART_Transmit_string("AT+CMGF=1\r"); _delay_ms(200);//set text mode

UART_Transmit_string("ATE0\r"); _delay_ms(200);//disable ECHO

}

    void gsm_send_AVRFREAK(){
UART_Transmit_string("AT+CMGS=");
UART_Transmit_char(34);
 UART_Transmit_string("xxxxxx");//the phone number
 UART_Transmit_char(34);
 UART_Transmit_string("\r");
  _delay_ms(3000);
UART_Transmit_string("AVRFREAK\r");_delay_ms(3000);
UART_Transmit_char(0x1A);
  _delay_ms(3000);
}

char sms_index1(){
i=0;
while( i<=50){i++; //check if gsm sends SM",
if(ser_rec[i]==((char) 'S')){
 i++; if(ser_rec[i]==((char) 'M')){
i++;  if(ser_rec[i]==((char) '"')){ i++;  if(ser_rec[i]==((char) ',')){
i++;  return sms_index; i=51; M1=1; }}}}}//returns it
i=0; a=0; 

if(M1==0){return 0;} M1=0; // if not returns 0
clear_sec_rec();  //clears the ser_rec buffer
}
int main(void)
{    serial_init();
     gsm_init();//init gsm
     while(1)
{
    if((INTERUPT==1)&&(DECODE_SMS==0)){  _delay_ms(3000);  //if there is interupt get the sms_index
    sms_index=sms_index1();
    INTERUPT=0;
    if(sms_index!=0){INDEX_SMS=1;}}  //and activate the next part of code

}
}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR;
if((ser_rec[a]!=0xd)&&(ser_rec[a]!=0xa)){//we do not need theese bytes 0xd,0xa
      a++;
      INTERUPT=1;
}
}

 

 

6.7.2,3,4)Now we need to send the sms_index to the gsm and decode the sms

 

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

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

 uint8_t  mem=0;
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define   SBIT(x,y)       SBIT_(x,y) 

#define K1_DIR          SBIT( DDRC, 0 )
#define K1          SBIT( PORTC, 0 ) 

#define INTERUPT          SBIT( mem, 0 )
#define INDEX_SMS          SBIT( mem, 1 )
#define DECODE_SMS         SBIT( mem, 2 )

void serial_init(){
UCSRB = (1 << RXEN ) | (1 << TXEN );
UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 );
UBRRH = ( BAUD_PRESCALE >> 8);
UBRRL = BAUD_PRESCALE ;
UCSRB |= (1 << RXCIE );
sei ();
}
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;
}
void UART_Transmit_string( char string[] )
{
   int i=0;
   while ( string[i] > 0)
   UART_Transmit_char(string[i++]);
}
volatile char ser_rec[100];  uint8_t a=0;

void clear_sec_rec(){
    i=0;  while( i<=100){ ser_rec[i]==0;i++;} i=0;a=0;
    }
void gsm_init(){
UART_Transmit_string("AT\r");_delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
UART_Transmit_string("AT\r"); _delay_ms(200);
//send some times AT to set up the gsm
UART_Transmit_string("AT+CMGF=1\r"); _delay_ms(200);//set text mode

UART_Transmit_string("ATE0\r"); _delay_ms(200);//disable ECHO

}

    void gsm_send_AVRFREAK(){
UART_Transmit_string("AT+CMGS=");
UART_Transmit_char(34);
 UART_Transmit_string("xxxxxx");//the phone number
 UART_Transmit_char(34);
 UART_Transmit_string("\r");
  _delay_ms(3000);
UART_Transmit_string("AVRFREAK\r");_delay_ms(3000);
UART_Transmit_char(0x1A);
  _delay_ms(3000);
}

char sms_index1(){
i=0;
while( i<=50){i++; //check if gsm sends SM",
if(ser_rec[i]==((char) 'S')){
 i++; if(ser_rec[i]==((char) 'M')){
i++;  if(ser_rec[i]==((char) '"')){ i++;  if(ser_rec[i]==((char) ',')){
i++;  return sms_index; i=51; M1=1; }}}}}//returns it
i=0; a=0; 

if(M1==0){return 0;} M1=0; // if not returns 0
clear_sec_rec();  //clears the ser_rec buffer
}

void sms_decode(){
i=0;
_delay_ms(3000);
while( i<=100){i++;
if(ser_rec[i]==((char) 'K')){i++;
if(ser_rec[i]==((char) '1')){i++;
if(ser_rec[i]==((char) '=')){i++;
if(ser_rec[i]==((char) '1')){i++;
K1=1;}}}}}//activates the port
i=0;
clear_sec_rec();_delay_ms(200);//clears the buffer
if(sms_index!=0)//delete the sms
{
    UART_Transmit_string("AT+CMGD=");
    UART_Transmit_char(sms_index);
    UART_Transmit_string("\r");}
}
int main(void)
{   serial_init();//inits the serial port
    gsm_init();//init gsm
    K1_DIR=1;//sets portc.0 as output
     while(1)
{
    if((INTERUPT==1)&&(DECODE_SMS==0)){  _delay_ms(3000);  //if there is interupt get the sms_index
    sms_index=sms_index1();
    INTERUPT=0;
    if(sms_index!=0){INDEX_SMS=1;}}  //and activate the next part of code

    if((INTERUPT==1)&&(DECODE_SMS==1))//decodes the sms
    {sms_decode(); DECODE_SMS=0; INTERUPT=0;}

}
}

ISR ( USART_RXC_vect )
{ser_rec[a]=UDR;
if((ser_rec[a]!=0xd)&&(ser_rec[a]!=0xa)){//we do not need theese bytes 0xd,0xa
      a++;
      INTERUPT=1;
}
}

 

 

Last Edited: Sun. Nov 8, 2015 - 09:55 AM