Menu

all about electronic and microcontrollers

Wednesday, July 23, 2014

GSM Click (Warning Action via SMS)

OK Folks, we will continue our experiments with this GSM module, and we will show how we can send an warning message. Obviously we will create the warning situation trough a button, but of course it can be changed with everything else for example a couple of movement sensors, etc.

Hardware setup:
After we spoke "the given situation" is set by a button set on RD7. The info led set on RB7 show the situation as follow:
  • After initialize, it flash for 2 seconds.
  • After the message is sent, it flashing ten times.
Some adjustments are needed on Easypic v7 motherboard to establish our connections. The adjustments are as follow:
  1. Turn on portB LEDs on SW3 (SW3.2).
  2. Place GSM click board into mikroBUS socket 1.
  3. Place power selection jumper (J5) into 3.3V position.


Video:

For hardware details, please study the EasyPic v7 and Telit GL865 datasheets.

Software:
The program is written in mikroC Pro for PIC (version v6.4.0).
Below is my software version:

warning action.c
/*
 * Project name:
     Warning Action via SMS.
 * Copyright:
     (c) Macovei Aureliu Raducu, 2014.
 * Revision History:
     1.1
 * Description:
     This is an Warning Action via SMS project who are able to send a 
     warning message for a given situation.
     In this experiment "the given situation" is one button set on RD7.
     The info led set on RB7 show the situation as follow:
         - After initialize, it flash for 2 seconds.
         - After the message is sent, it flashing ten times.
 * Test configuration:
     MCU:             PIC18F45k22
                      http://ww1.microchip.com/downloads/en/DeviceDoc/41412F.pdf
     Ddev.board:       EasyPIC7
                      http://www.mikroe.com/easypic/
     Oscillator:      HS-PLL 32.0000 MHz, 8.0000 MHz Crystal
     Ext. Modules:    GSM click
                      http://www.mikroe.com/click/gsm/
     SW:              mikroC PRO for PIC
                      http://www.mikroe.com/mikroc/pic/
 * NOTES:
     Adjust the number to which the SMS will be sent and recompile the project
     now have HEX file ready for programming.
*/
// Configure phone number on which the SMS warning will be sent
// Use international code + your phone number
char phoneNumber1[] = "your number1";    // This is the first number
char phoneNumber2[] = "your number2";    // This is the second number

#include "Telit_GL865.h"

// Pin definitions
sbit LD1 at LATB7_bit;                    // Set LED1 at port RB7
sbit LD1_Direction at TRISB7_bit;         // Set LED1 at port RB7

sbit T1 at RD7_bit;                       // Set Button at port RD7.
sbit T1_Direction at TRISD7_bit;          // Set Button at port RD7
// Pin definitions

void Delay_LD(){
  Delay_ms(100);                          // Led Delay 100ms
}

// Simple LED action indicating a button press
void Blink(){
  LD1 = 1;
  Delay_LD();
  LD1 = 0;
  Delay_LD();
  LD1 = 1;
  Delay_LD();
  LD1 = 0;
}

void check_status(){
 LD1 = 1;
 delay_ms(2000);           // Add 2s delay
 LD1 = 0;
}

void MCU_Init()
{
  ANSELA = 0;              // Set all ports as digital
  ANSELB = 0;
  ANSELC = 0;
  ANSELD = 0;
  ANSELE = 0;              // Set all ports as digital

  // GSM definitions
  PWRMON_Direction = 1;
  RST = 0;
  RST_Direction = 0;
  // GSM definitions

  // Button on RD7;
  T1_Direction = 1;             // Button pins are set as input
  // Button on RD7;

  // Led Indicator set on RB7
  LD1 = 0;                      // Turn OFF the LED
  LD1_Direction = 0;            // Set direction for LEDS
  // Led Indicator set on RB7

  UART1_Init(9600);       // Using default baud rate 9600
  Delay_ms(200);          // Wait a while till the GSM network is configured
}

// main function
void main() {
  MCU_Init();                   // Initialize MCU pins and modules
  if (GSM_Init() == 0)          // Initialize GSM module, if AT is received LED1 is ON
  check_status();               // Shown by LD1

  while(1){                     // Endless loop
  if (T1 == 1){                 // With Button1 we activate "the given situation"
    SendSMS(phoneNumber1);      // First things first, send the SMS
    delay_ms(3500);
    SendSMS(phoneNumber2);
    Blink();Blink();            // Blink ten times, after message sent
    Blink();Blink();
    Blink();
    }
  }
}

telite_GL865.c
#include "Telit_GL865.h"

void GSMcmd(char *ch)                 // GSM commands
{
 while(*ch)
 if(UART1_Tx_Idle() == 1)
 UART1_Write(*ch++);
 UART1_Write(0x0D);                  // Send CR - command terminate character
}

char GSM_Init(){
  char cmdTO = 0, readTO = 0;         // TimeOut counters
  char gsmRes[26]={0}, resCnt = 0;    // Response from GSM module
  while(PWRMON != 0){};               // Wait for POWER to be generated by the GSM module
  Delay_ms(3500);
  while(cmdTO++ < 5){                 // Check the communication by sending AT command for few times
    UART1_Read();
    GSMcmd("AT");                     // AT commamd.
    while(readTO++ < 10){
      Delay_us(300);                  // 1/9600 * 3 = 312.5us takse a UART HW buffer to fill up.
      while(UART1_Data_Ready()){      // Place the received bytes to buffer array(gsamRes[])
        readTO = 0;
        gsmRes[resCnt++] = UART1_Read();
        gsmRes[resCnt] = 0;
        if (resCnt == 25){
         resCnt = 0;
        }
      }
    }
    readTO = 0;
    if (strstr(gsmRes,"AT\r\r\nOK\r\n")){   // Check for occurrence of expected string
      GSMcmd("ATE1");                       // Few more GSM module configuration commands.
      GSMcmd("AT+CMGF=1");                  // Select Text Mode.
      GSMcmd("AT#GPIO=5,0,2");              // Set GPIO5 pin as RFTXMON OUTPUT
      return 0;
    }
  }
  return 1;
}

void SMSbegin(char *phoneNo){               // Sending an SMS requires three easy steps
                                            // 1. Begin with SMS command  +CMGS
  UART1_Write_Text("AT+CMGS=\"");           // AT+CMGS="+39xxxxxxxxxx"[CR]
  UART1_Write_Text(phoneNo);
  GSMcmd("\"");
}

void SMSwrite(char *text){
  UART1_Write_Text(text);                   // 2. After SMS command, SMS text is expected
}

void SMSsend(){
  GSMcmd("\x1A");     // 3. At the end CTRL + Z is sent as terminating character
}
// Function sends an SMS to predefined number with predefined text(warning)
void SendSMS(char *phone){
  SMSbegin(phone);
  Delay_ms(100);
  SMSwrite("WARNING!!\r\n");                            // This is our message line1
  SMSwrite("We have a situation here!\r\n");            // This is our message line2
  SMSwrite("(someone somehow has press the button)");   // This is our message line3
  SMSsend();
}

telite_GL865.h
// GSM definitions
sbit PWRMON           at PORTA.B2;
sbit PWRMON_Direction at TRISA2_bit;
sbit RST              at LATE1_bit;
sbit RST_Direction    at TRISE1_bit;
// GSM definitions

char GSM_Init();
void SendSMS(char *phone);

Monday, July 21, 2014

GSM Click (Temperature & Controll via SMS)

Today I will share with you an experiment made with the module Telit GL856-Quad wich is mounted on a pcb board called "GSM Click Board" designed by Mikroelektronika. The GSM click board is attached to the EasyPIC v7 motherboard trough mikroBUS™ host connector, making our hardware platform.


Telit GL865 Module.

Features:
  1. The Telit GL865-Quad module family can be controlled via the serial interface using the standard AT commands. 
  2. Ultra Compact; GPRS Class 10; LCC Package
  3. Quad Band GSM/GPRS 850/900/1800/1900MHz
  4. Embedded TCP/IP Stack
  5. Supply voltage range: 3.22 - 4.5V DC (3.8V DC recommended)
  6. Power consumption (typical values): Power off: <5 uA
  7. Idle (registered, power saving): 1.5 mA @ DRX=9
  8. Dedicated mode: 230mA @ max power level
  9. GPRS class 10: 360 mA @ max power level
  10. Sensitivity: 108 dBm (typ.) @ 850/900MHz; 106 dBm (typ.) @ 1800/1900MHz.
As can be seen from it's datasheet, the communications are achieved in UART mode (TX,RX), with a Baud rate from 300 to 115,200bps.

Hardware setup:
In example, "FAN1ON" command turns ON the output on RD0, "FAN2OFF" turns OFF the output on RD1. In this experiment we used two leds instead fans (just to prove the output commands.)
PORT RD0 and RD1 leads two digital output and RA0 one analog input.
Some adjustments are needed on Easypic v7 motherboard to establish our connections:
The adjustments are as follow:
  1. Turn on portD LEDs on SW3 (SW3.4).
  2. Place GSM click board into mikroBUS socket 1.
  3. Place power selection jumper (J5) into 3.3V position.





Video:

Pin Configurations.

For hardware details, please study the EasyPic v7 and Telit GL865 datasheets.

Software:
The program is written in mikroC Pro for PIC (version v6.0.0).
Below is my software version:
/*
 * Project name:
    GSM Click (Temperature & Controll via SMS).
 * Copyright:
     Macovei Aureliu Raducu, 2014.
 * Description:
     Program uses GSM module GL865 for sending and receiving SMS.
     The scenario of this experiment is as follows:
     User can interrogate the EasyPIC v7 development board via SMS, and receive
     the status situation of the motherboard.
     Port RD0 and RD1 are used to control two Fans and port RA0 is used to 
     measure the temperature of LM35 sensor.
     As a bonus the temperature is displayed in both format, Celsius and Fahrenheit.
 * Test configuration:
     MCU:             PIC18F45K22
                      http://ww1.microchip.com/downloads/en/DeviceDoc/41412F.pdf
     dev.board:       EasyPIC7
                      http://www.mikroe.com/easypic/
     Oscillator:      HS-PLL 32.0000 MHz, 8.0000 MHz Crystal
     ext. modules:    gsm click : 
                      http://www.mikroe.com/click/gsm/
                      Telit GL865-QUAD
                      http://www.telit.com/en/products.php?p_id=3&p_ac=show&p=110
                      LM35 (Analog temperature sensor)
                      http://www.ti.com/lit/ds/symlink/lm35.pdf
     SW:              mikroC PRO for PIC
                      http://www.mikroe.com/mikroc/pic/
 * NOTES:
     - Due different mobile operators some adjustments may be required, please consult Telit AT commands
       reference guide at http://www.telit.com/module/infopool/download.php?id=542
     - The SMS messages (which GL865 receives) contain commands: "FAN1ON" or "FAN1OFF", "FAN2ON" or "FAN2OFF"
       and "Status?" (it is case sensitive and without quotes).
       In example, "FAN1ON"  command turns ON the output on RD0, "FAN2OFF" turns OFF the output on RD1.
       In this experiment we used two leds instead fans (just to prove the output commands.)
       You can send only the "Status?" inquiry via your SMS (or add it to the SMS containg relay commands) 
       and then you'll receive an info about the state of EasyPic7 motherboard.
       PORT RD0 and RD1 leads two digital output and RA0 one analog input.
       An example of one control message is below:
       "FAN1ON FAN2OFF Status?"  (Note that there is no need for separation chars (spaces in this case)).
       Valid message is also: "FAN2OFFFAN1ONStatus?"; just be careful about the case of letters.

     - Turn on portD LEDs on SW3 (SW3.4).
     - Place GSM click board into mikroBUS socket 1.
     - Place power selection jumper (J5) into 3.3V position.
 */

//  Set VREF according to the voltage reference for LM35:
//  5.00 - power supply jumper set to 5V position (reference = 5V)
//  3.30 - power supply jumper set to 3.3V position (reference = 3.3V)
const unsigned short VREF = 3.30;

// Set of basic AT commands
const char atc0[] = "AT";                        // Every AT command starts with "AT"
const char atc1[] = "ATE0";                      // Disable command echo
const char atc2[] = "AT+CMGF=1";                 // TXT messages
      char atc3[] = "AT+CMGS=\"";                // sends SMS to desired number
const char atc4[] = "AT+CMGR=1";                 // Command for reading message from location 1 from inbox
const char atc5[] = "AT+CMGD=1,4";               // Erasing all messages from inbox
const char atc6[] = "AT+CMGL=\"ALL\"";           // Check status of received SMS
const char atc7[] = "AT#SLED=2";                 // Activate STAT_LED pin
const char atc8[] = "AT#SLEDSAV";                // Save previous command
const char atc9[] = "AT#GPIO=5,0,2";             // Set GPIO5 pin as RFTXMON OUTPUT (the GPIO5 pin is set
                                                 // in output direction; the setting is saved at module power off.)

// Responses to parse
const GSM_OK                       = 0;
const GSM_Ready_To_Receive_Message = 1;
const GSM_ERROR                    = 2;
const GSM_UNREAD                   = 3;
//

// Telit GL865 Module settings
sbit PWRMON at PORTA.B2;
sbit PWRMON_Direction at TRISA2_bit;

sbit RTS at LATE0_bit;
sbit RTS_Direction at TRISE0_bit;

sbit GL865_ON_OFF at LATE1_bit;
sbit GL865_ON_OFF_Direction at TRISE1_bit;
//

//Fan Connections
sbit FAN1 at LATD0_bit;
sbit FAN2 at LATD1_bit;

sbit FAN1_Direction at TRISD0_bit;
sbit FAN2_Direction at TRISD1_bit;
//

// Temperature sensor connections
sbit LM35 at PORTA.B0;
sbit LM35_Direction at TRISA0_bit;
//

// SMS Message string
char SMS_Message[300];

// LM35 data string
char LM35_dataC[15];
char LM35_dataF[15];
//
// phone number string
char phone_number[20];

// State machine control variables
char gsm_state = 0;
char response_rcvd = 0;
short responseID = -1, response = -1;
char gsm_number = 0;
char Unread_flag;
char status_req = 0; // Status request variable

// Send command or data to the Telit GL865 Module - (const)
void GL865_Send(const char *s)
{
// Send command or data string
   while(*s) {
    UART1_Write(*s++);
   }
// Terminatation by CR
   UART_Wr_Ptr(0x0D);
}

// Send command or data to the Telit GL865 Module - (RAM)
void GL865_Send_Ram(char *s1)   //
{
// Send command or data string
   while(*s1) {
    UART_Wr_Ptr(*s1++);
   }
// Terminatation by CR
   UART_Wr_Ptr(0x0D);
}

// Get GSM response, if there is any
short Get_response() {
    if (response_rcvd) {
      response_rcvd = 0;
      return responseID;
    }
    else
      return -1;
}

// Wait for GSM response (infinite loop)
void Wait_response(char rspns) {
char test = 1;

  while (test){
  test = Get_response();
  if ((test == rspns) || (test == GSM_ERROR))
    test = 0;
  else
    test = 1;
  }
}

// Compose Status SMS
unsigned ComposeMessage(char* Message);

// Send Status SMS
void Send_Msg(char* Msg){
  char atc[33];

  atc[0] = 0;                        // clear atc string
  strcat(atc, atc3);                 // atc3 command for sending messages
  strcat(atc, phone_number);         // add phone number
  strcat(atc, "\"");                 // complete AT command
  GL865_Send_Ram(atc);               // send AT command for SMS sending
  Wait_response(GSM_Ready_To_Receive_Message); // Wait for appropriate ready signal

  GL865_Send_Ram(Msg);               // Send message content
  UART_Wr_Ptr(0x1A);                 // Send CTRL + Z as end character
  UART_Wr_Ptr(0x0D);                 // Send CR
  Wait_response(GSM_OK);             // Wait OK as confirmation that the message was sent
}

// Send status SMS to the cell phone number defined by the atc3 const string
void Send_Status(){
 ComposeMessage(SMS_Message);
 Send_Msg(SMS_Message);
}

// 5sec pause
void Wait(){
   Delay_ms(5000);
}

// Main
void main(){
  ANSELA = 0;             // Set all ports as digital
  ANSELB = 0;
  ANSELC = 0;
  ANSELD = 0;
  ANSELE = 0;

  SLRCON = 0;             // Set output slew rate on all ports at standard rate

  ANSELA |= 0x01;         // Configure RA0 pins as analog
  LM35_Direction = 1;     // Configure RA0 pin as input

  //Initialy, FAN's are turned off
  FAN1=0;
  FAN2=0;
  
  FAN1_Direction=0;
  FAN2_Direction=0;
  //

// Setup interrupts
  RC1IE_bit = 1;          // Enable Rx1 intterupts
  PEIE_bit = 1;           // Enable peripheral interrupts
  GIE_bit  = 1;           // Enable global interrupts
//

  // Initial state of Telit GL865 Module pins
  PWRMON_Direction = 1;   // Make PWRMON(RA2) as input

  RTS = 0;                //  Set RTS pin to zero (we will use only RX and TX)
  RTS_Direction  = 0;

  GL865_ON_OFF = 0;
  GL865_ON_OFF_Direction = 0;
  //
  
// Turn on the GM865 module
  GL865_ON_OFF = 1;       // hardware reset
  Delay_ms(2500);         // hold it at least for two seconds
  GL865_ON_OFF = 0;
//

  UART1_Init(9600);
  ADC_Init();

  Wait();                 // Wait a while till the GSM network is configured

// Negotiate baud rate
  while(1) {
    GL865_Send(atc0);                 // Send "AT" string until GSM862 sets up its baud rade
    Delay_ms(100);                    // and gets it correctly
    if (Get_response() == GSM_OK)     // If GSM862 says "OK" on our baud rate we program can continue
      break;
  }

 GL865_Send(atc1);                    // Disable command echo
 Wait_response(GSM_OK);

 GL865_Send(atc2);                    // Set message type as TXT
 Wait_response(GSM_OK);
 
 GL865_Send(atc7);                    // Activate STAT_LED pin
 Wait_response(GSM_OK);
 
 GL865_Send(atc8);                    // Then save it
 Wait_response(GSM_OK);
 
 GL865_Send(atc9);                    // Set GPIO5 pin as RFTXMON OUTPUT
 Wait_response(GSM_OK);

 while(1){
   GL865_Send(atc5);             // Delete all messages (if any)
   if (get_response() == GSM_OK) // If messages are deleted
     break;                      // break from while
   Delay_ms(500);
 }
  // infinite loop
  while(1) {
    GL865_Send(atc6);        // Read status of the messages and read message it self
    Delay_ms(100);           // Wait until the message is read

    while(1) {
      GL865_Send(atc0);      // Wait until the module is ready
      Delay_ms(50);
      if (Get_response() == GSM_OK)
        break;
    }
    
    if (Unread_flag){
      while(1) {
        GL865_Send(atc0);    // Wait until the module is ready
        Delay_ms(50);
        if (Get_response() == GSM_OK)
          break;
      }

      if (status_req){       // Send status SMS if it's been requested
        status_req = 0;
        Send_Status();
      }

      Unread_flag = 0;
    }

    while(1){
      GL865_Send(atc5);  // Delete all messages (if any)
      Delay_ms(50);
      if (get_response() == GSM_OK) // If messages are deleted
        break;           // break from while
      Delay_ms(50);
      if (Unread_flag){  // if we have received message in mean time
        Unread_flag = 0;
        break;           // break from while
      }
    }
    Wait();
  }
}

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

// Compose Status SMS
unsigned ComposeMessage(char* Message){
  unsigned int adc_value1 = 0;
  float Celsius_format, Fahrenheit_format;
 
  RC1IE_bit = 0;                // Disable Rx1 intterupts

  Message[0] = '\0';
//================================================================
  // SMS header
  strcat(Message, "EasyPIC7 Info:");
  strcat(Message, "\r\n");              // Add new line (CR + LF)
  //
  if(FAN1)
     strcat(Message, "FAN1: ON");
  else
     strcat(Message, "FAN1: OFF");
  strcat(Message, "\r\n");              // Add new line (CR + LF)
  
  if(FAN2)
     strcat(Message, "FAN2: ON");
  else
     strcat(Message, "FAN2: OFF");
  strcat(Message, "\r\n");              // Add new line (CR + LF)
//================================================================

  // Adding Temperature values to the SMS
  adc_value1 = ADC_Get_Sample(0);                 // RA0
  Celsius_format = (adc_value1 * VREF)/10.240;    // Calculate temperature in Celsuis
  FloatToStr(Celsius_format, LM35_dataC);
  LM35_dataC[4] =0;                               // Use just four string value

  strcat(Message, "TEMP: +");
  strcat(Message, LM35_dataC);
  strcat(Message, "'C");                          // Celsius degree symbol
  strcat(Message, " / +");                        // Delimitation and + symbol
  
  Fahrenheit_format = (Celsius_format *9/5)+32;   // °F =°C*9/5 + 32 transformation formula
  FloatToStr(Fahrenheit_format, LM35_dataF);
  LM35_dataF[4] =0;                               // Use just four string value
  strcat(Message, LM35_dataF);
  strcat(Message, "'F");
  strcat(Message, "\r\n");                        // Add new line (CR + LF)
  // SMS footer
  strcat(Message, "End.");
  strcat(Message, "\r\n");                        // Add new line (CR + LF)
  //
  RC1IE_bit = 1;                                  // Enable Rx1 intterupts

  return strlen(Message);
}

// state machine
// Reading the data from UART in the interuppt routine
void interrupt(){
char tmp,i;

  if (RCIF_bit == 1) {                           // Do we have uart rx interrupt request?
    tmp = UART_Rd_Ptr();                         // Get received byte

// Process reception through state machine
// We are parsing only "OK" and "> " responses
    switch (gsm_state) {
      case  0: {
                response = -1;                   // Clear response
                if (tmp == 'O')                  // We have 'O', it could be "OK"
                  gsm_state = 1;                 // Expecting 'K'
                if (tmp == '>')                  // We have '>', it could be "> "
                  gsm_state = 10;                // Expecting ' '
                if (tmp == 'E')                  // We have 'E', it could be "> "
                  gsm_state = 30;                // Expecting 'R'
                if (tmp == 'S')                  // We have 'S', it could be "Status?"
                  gsm_state = 40;                // Expecting 't'
                if (tmp == 'F')                  // We have 'F', it could be "FANxON or FANxOFF"
                  gsm_state = 50;                // Expecting A
                if (tmp == 'U')                  // We have 'U', it could be "UNREAD"
                  gsm_state = 70;                // Expecting 'N'
                break;
               }
      case  1: {
                if (tmp == 'K') {                // We have 'K' ->
                  response = GSM_OK;             // We have "OK" response
                  gsm_state = 20;                // Expecting CR+LF
                }
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }
      case 10: {
                if (tmp == ' ') {
                  response_rcvd = 1;             // We have "> " response
                  response = GSM_Ready_To_Receive_Message; // Set reception flag
                  responseID = response;         // Set response ID
                }
                gsm_state = 0;                   // Reset state machine
                break;
                }

      case 20: {
                if (tmp == 13)                   // We have 13, it could be CR+LF
                  gsm_state = 21;                // Expecting LF
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }
      case 21: {
                if (tmp == 10) {                 // We have LF, response is complete
                  response_rcvd = 1;             // Set reception flag
                  responseID = response;         // Set response ID
                }
                gsm_state = 0;                   // Reset state machine
                break;
               }

      case 30: {
                if (tmp == 'R')                  // We have 'R', it could be "ERROR"
                  gsm_state = 31;                // Expecting 'R'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }
      case 31: {
                if (tmp == 'R')                  // We have 'R', it could be "ERROR"
                  gsm_state = 32;                // Expecting 'O'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }
      case 32: {
                if (tmp == 'O')                  // We have 'O', it could be "ERROR"
                  gsm_state = 33;                // Expecting 'R'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }
      case 33: {
                if (tmp == 'R'){                 // We have 'R'
                  response_rcvd = 1;             // We have "ERROR" response
                  response = GSM_ERROR;          // Set reception flag
                  responseID = response;         // Set response ID
                }
                gsm_state = 0;                   // Reset state machine
                break;
                }
      case 40: {
                if (tmp == 't')                  // We have 't', it could be "Status?"
                  gsm_state = 41;                // Expecting 'a'
                else
                  gsm_state = 0;               // Reset state machine
                break;
                }
      case 41: {
                if (tmp == 'a')                  // We have 'a', it could be "Status?"
                  gsm_state = 42;                // Expecting 't'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }
      case 42: {
                if (tmp == 't')                  // We have 't', it could be "Status?"
                  gsm_state = 43;                // Expecting 'u'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }

      case 43: {
                if (tmp == 'u')                  // We have 'u', it could be "Status?"
                  gsm_state = 44;                // Expecting 's'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }

      case 44: {
                if (tmp == 's')                  // We have 's', it could be "Status?"
                  gsm_state = 45;                // Expecting '?'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }

      case 45: {
                if (tmp == '?'){                 // We have '?'
                  status_req = 1;                // Status has been requested!
                }
                gsm_state = 0;                   // Reset state machine
                break;
                }

      case 50: {
                if (tmp == 'A')                  // We have 'A', it could be "FANx"
                  gsm_state = 51;                // Expecting 'N'
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }

      case 51: {
                if (tmp == 'N')                  // We have 'N', it could be "FANx"
                  gsm_state = 52;                // Expecting number
                else
                  gsm_state = 0;                 // Reset state machine
                break;
               }

      case 52: {
                if (tmp == '1')
                   gsm_state = 53;
                else
                if (tmp == '2')
                   gsm_state = 60;
                else
                   gsm_state = 0;
                break;
                }
                
      case 53: {
                if (tmp == 'O')
                gsm_state = 54;
                else
                gsm_state = 0;
                break;
               }
               
      case 54: {
                if (tmp == 'N'){
                   FAN1 = 1;
                   gsm_state = 0;}
                else
                if (tmp == 'F')
                   gsm_state = 55;
                else
                   gsm_state = 0;
                break;
               }
      case 55: {
                if (tmp == 'F'){
                   FAN1 = 0;
                   gsm_state = 0;}
                else
                   gsm_state = 0;
                break;
                }
      case 60: {
                if (tmp == 'O')
                   gsm_state = 61;
                else
                   gsm_state = 0;
                break;
                }
      case 61: {
                if (tmp == 'N'){
                   FAN2 = 1;
                   gsm_state = 0;}
                else
                   if (tmp = 'F')
                   gsm_state = 62;
                else
                   gsm_state = 0;
                break;
                }
      case 62: {
                if (tmp == 'F'){
                   FAN2 = 0;
                   gsm_state = 0;}
                else
                   gsm_state = 0;
                break;
                }
      case 70: {
                if (tmp == 'N')
                   gsm_state = 71;
                else
                   gsm_state = 0;
                break;
                }
      case 71: {
                if (tmp == 'R')
                   gsm_state = 72;
                else
                   gsm_state = 0;
                break;
                }
      case 72: {
                if (tmp == 'E')
                   gsm_state = 73;
                else
                   gsm_state = 0;
                break;
                }
      case 73: {
                if (tmp == 'A')
                   gsm_state = 74;
                else
                   gsm_state = 0;
                break;
                }
      case 74: {
                if (tmp == 'D'){
                   response_rcvd = 1;             // We have "ERROR" response
                   response = GSM_UNREAD;         // Set reception flag
                   responseID = response;         // Set response ID
                   Unread_flag = 1;
                   }
                gsm_state = 0;
                break;
                }
      default: {                                 // Unwanted character
                gsm_state = 0;                   // Reset state machine
               }
    }
    // parse phone number on which we should reply
    switch (gsm_number) {
      case 0 :{
               if (tmp == '"'){
                 gsm_number = 1;
                 i = 0;
               }
              }; break;
      case 1 :{
               if (tmp == '+'){
                 phone_number[i] = tmp;
                 i ++;
                 gsm_number = 2;
               }
               else{
                 gsm_number = 0;
                 i = 0;
               }
              }; break;
      case 2 :{
               if (tmp >= '0' && tmp <= '9'){
                 phone_number[i] = tmp;
                 i ++;
               }
               else
                 if (tmp == '"'){
                   phone_number[i] = 0;
                   i = 0;
                   gsm_number = 0;
                 }
                 else{
                   phone_number[0] = 0;
                   i = 0;
                   gsm_number = 0;
                 }
              }; break;
      default : {
                 phone_number[0] = 0;
                 i = 0;
                 gsm_number = 0;
                }
    }
 }
}
/******************************************************************************/