MODULI: Esempio GSM MODULE

Per costruire i seguenti esempi occorre procurarci un modulo GSM ad esempio iComSat v. 1.1

Modulo GSM: IComSat v. 1.1  IComSat 1.1 - Retro

ll modulo SIM900 è un modem seriale, ossia comunica con Arduino attraverso due pin in modalità Tx/Rx e si alimenta tramite i +5v e Gnd direttamente da Arduino. Il modulo GSM consente di configurare opportunamente quali pin di Arduino siano associati a TX e RX  (nella foto sottostante i pin associati a TX e RX sono rispettivamente il pin 2 e 3).

Particolare

Inoltre il microswitch, evidenziato in giallo (foto sopra) deve essere posizionato su UART (si tratta di un ricevitore/trasmettitore che converte flussi di bit da un formato parallelo ad un formato seriale asincrono  e viceversa. Ha il compito di gestire la comunicazione delle interfacce seriali).

Come tutti i modem seriali è possibile utilizzare i comandi AT. Nel caso venga utilizzata la libreria GSM.cpp i pin abbinati a TX/RX devono essere il 2 (TX) e il 3 (RX) come si può desumere dalle seguenti define interne alla libreria:

#define _GSM_TXPIN_ 2
#define _GSM_RXPIN_ 3

L'elenco completo dei comandi AT disponibili sul modulo SIM900 (è il dispositivo GSM/GPPRS montato sul modulo utilizzato nelle nostre prove. E' sostanzialmente un cellulare privo di tastiera, display, alimentatore ed antenna. Il colloquio con il dispositivo avviene tramite comunicazione seriale. Tra tle funzioni disponibili tramite semplici comandi AT abbiamo: voce, Sms, Fax, GPRS, Stack TCP/IP, protocolli Ftp e Http.) è disponibile sul manuale ufficiale scaricabile su questo link. Per quanto riguarda l'aspetto hardware del modulo SIM900 consulta invece quest'altro link.

Codice Sorgente A

Obiettivo progetto: pilotare un led mediante dei comandi inviati tramite SMS (ON: accende il Led, OFF:; spegne il Led, STATUS: invia lo stato del Led al numero autorizzato che ha inviato l'SMS)

soluzione:

Innestiamo il modulo GSM sopra Arduino e colleghiamo il catodo del diodo LED su GND e l’anodo all’uscita digitale 13.

Led

Ecco l'immagine del circuito

Modulo GSM

Prima di mandare in esecuzione il programma occorre premere il tasto "POWER" (1) del modulo GSM. Il led Status si accende mentre il led NET (di rete) lampeggia con una frequenza elevata ogni 800 millisecondi fino a quando il modulo GSM aggancia la rete. A questo punto il lampeggio diventa meno frequente, circa una volta ogni 3 secondi. 

Modulo GSM - Bottone Power

Per poter utilizzare questo codice è necessario installare la libreria GSM disponibile in questo link. Per installarla basta scompattare il file e copiare la cartella prodotta (GSMSHIELD) all'interno della cartella contenente le librerie di Arduino (solitamente C:\Program Files\Arduino\libraries). Terminare aggiungendo la cartella appena copiata, mediante il menu "Add Library", all'interno dell'IDE di Arduino

Agiunta libreria

al termine dell'importazione i files vengono ricopiati nella cartella C:\Users\<User>\Documents\Arduino\libraries. Se ci sono problemi nell'installazione occorre svuotare la cartella di libreria appena ricopiata.

Ecco il codice che consente di raggiungere l'obiettivo prefissato

/* -----------------------------------------------------------------------------------
 Accende e spegne un LED a secondo dell'SMS inviato:
 ON  => Accende il LED
 OFF => Spegne il LED
 Altro => Messaggio di errore sul Serial Monitor
 ---------------------------------------------------------------------------------- */
#include "SIM900.h"
#include <SoftwareSerial.h> // necessaria alla libreria gsm.h richiamata in sms.h
// #include "inetGSM.h"     // necessaria per l'uso di HTTP
#include "sms.h"            // Libreria per la gestione degli SMS

SMSGSM sms;
int led = 13; // Il Pin 13 è quello connesso al LED
int numdata;
boolean started=false;
char smsbuffer[160];
char Mittente[20];

void setup() 
{
  Serial.begin(9600);
  Serial.println("ESEMPIO INVIO/RICEZIONE SMS");
  pinMode(led, OUTPUT);   // imposta il pin 13 come pin di OUTPUT.
  digitalWrite(led, LOW); // spegne inizialmente il led
  // Inizializzo la connessione GSM impostando il baudrate
  // Per l'utilizzo di HTTP è opportuno usare 4800 baud o meno
  if ( gsm.begin(2400) )
  {
     Serial.println("STATUS Modulo GSM = PRONTO");
     started=true;  
  }
  else 
     Serial.println("STATUS Modulo GSM = INATTIVO");
};

// legge una stringa dal Serial Monitor
//   Questa procedura serve solo nella fase di TEST ovvero 
//   quando provo a simulare i comandi SMS tramite il SERIAL MONITOR
boolean SerialRead(char s[])
{
  int i=0;
  if (Serial.available() > 0)
  {            
    while (Serial.available() > 0) 
    {
      s[i]=Serial.read();
      delay(10);
      i++;      
    }
  }
  s[i]='\0'; // Metto il terminatore di stringa
  return (i!=0);
}
// legge una stringa dal Serial Monitor
//    Questa è la versione proposta da Arduino Lab
// int readSerial(char result[])
// {
//    int i = 0;
//    while(1)
//    {
//       while (Serial.available() > 0)
//       {
//          char inChar = Serial.read();
//          if (inChar == '\n') // Line Feed
//          {
//             result[i] = '\0';
//             Serial.flush();
//             return 0;
//           }
//           if(inChar!='\r') // Scarta i Carriage Return
//           {
//              result[i] = inChar;
//              i++;
//            }
//       }
//    }
//  }

void loop() 
{
  char inSerial[50];
  char position;
  if (started)
  {
     // -- Righe commentate poichè utilizzate per nei test
     // strcpy(Mittente,"3380000000");
     // if (SerialRead(smsbuffer))
     // ------------------------------------------------------
    // Legge se ci sono messaggi disponibili sulla SIM Card
    // e li visualizza sul Serial Monitor.
    position = sms.IsSMSPresent(SMS_ALL); // Valore da 1..20
    if (position) 
    {
      // Leggo il messaggio SMS e stabilisco chi sia il mittente
      sms.GetSMS(position, Mittente, smsbuffer, 160);
      Serial.print("Comando Ricevuto [tel. "+String(Mittente)+String("]: ") + String(smsbuffer));
      if (strcmp(smsbuffer,"ON")==0)
      {
         digitalWrite(led, HIGH);   // Accende il LED impostando il voltaggio a HIGH
         Serial.println(" => Accendo il LED");
      }
      else if (strcmp(smsbuffer,"OFF")==0)
      {
         digitalWrite(led, LOW);    // Spengo il LED impostando il voltaggio a LOW
         Serial.println(" => Spengo il LED");
      }
      else if (strcmp(smsbuffer,"STATUS")==0)
      {
          if (digitalRead(led)==HIGH)
          {
             sms.SendSMS(Mittente, "STATUS: LED Acceso"); // restituisce true se invia l'SMS
             Serial.println(" => il LED e' Acceso");
          }
          else
          {
             sms.SendSMS(Mittente, "STATUS: LED Spento"); // restituisce true se invia l'SMS
             Serial.println(" => il LED e' Spento");
          }
      }
      else
         Serial.println(" => non riconosciuto!");
      sms.DeleteSMS(position); // Elimina l'SMS appena analizzato
    }
    delay(1000);
  }
};

Sul  serial monitor appare il LOG dei comandi SMS inviati

Serial Monitor - Modulo GSM.

Se abbiamo dimenticato inizialmente di premere il tasto POWER sul modulo GMS allora sul Serial Monitor verrà mostrato il seguente messaggio di errore:

Serial Monitor -  Errore di trasmissione

Se inviamo un SMS con il messaggio "STATUS" riceviamo in risposta un SMS con lo stato corrente del LED:

SMS  stato del LED

Codice Sorgente B

Obiettivo progetto: inviare un SMS appena schiaccio un push button.

soluzione:

Per il nostro progetto occorrono un pushbutton e una resistenza di 10k

Ricordiamoci che i piedini A e C sono sempre connessi fra loro, così come i piedini B e D. Quando il pulsante viene premuto tutti i piedini risultano connessi tra loro.

Schema Push Button - Normally Open

Innestiamo il modulo GSM sopra Arduino e costruiamo il seguente progetto

 Schema Allarme con GSM Module

Il circuito è praticamente lo stesso presentato nell'esempio Push Button/LED solo che è montato sul GSM Module (che purtroppo non riporta le sigle dei pin!)

Nel codice sorgente si osservi la compilazione condizionale che permette di gestire nello stesso codice sia l'ambiente di TEST (che ci permette di provare senza dover utilizzare gli sms) che quello effettivo.

/* -----------------------------------------------------------------------------------
 Scopo del programma è simulare la gestione di un Allarme (simulato con la pressione
 di un PUSHBUTTON). L'allarme puo' essere disinserito con un opportuno SMS inviato
 da un cellulare autorizzato
----------------------------------------------------------------------------------- */
#define AMBIENTEDIPROVA true     // Commentare quando si usa l'ambiente GSM
#include "SIM900.h"
#ifndef AMBIENTEDIPROVA          // Compilazione condizionale
   #include <SoftwareSerial.h>   // Necessaria alla libreria gsm.h richiamata in sms.h
   #include "sms.h"              // Libreria per la gestione degli SMS
   SMSGSM sms;
#endif
#define LED 13        // LED collegato al pin digitale 13  
#define BOTTONE 7     // pin di input collegato al pulsante  
int val = 0;          // val conserva lo stato attuale del pin di input (7) 
int prec_val;         // Variabile per valutare lo stato nel precedente Loop
boolean acceso;       // Acceso = true  => il LED è acceso
boolean GSMstarted=false;
boolean SMSInviato;
char smsbuffer[160];
char CellulareAutorizzato[20];
char Mittente[20];

#ifdef AMBIENTEDIPROVA
// legge una stringa dal Serial Monitor
//   Questa procedura serve solo nella fase di TEST ovvero se 
//   i comandi sono inviati tramite il SERIAL MONITOR
boolean SerialRead(char s[])
{
  int i=0;
  if (Serial.available() > 0)
  {            
    while (Serial.available() > 0) 
    {
      s[i]=Serial.read();
      delay(10);
      i++;      
    }
  }
  s[i]='\0';
  return (i!=0);
}
#endif

void Reset_AlarmSystem()
{
  digitalWrite(LED, LOW);     // spegne inizialmente il LED che indica l'allarme
  acceso = false;             // Indica che il LED non è acceso (allarme OFF)
  SMSInviato=false;           // Indica che se avrò un allarme invia un SMS di avviso
  Serial.println(" => Sistema di allarme attivo");
}

void Activate_AlarmSystem()
{
  digitalWrite(LED, HIGH);  // accende il LED simulando un allarme
  acceso = true;            // Indica che il LED è acceso (allarme ON => pushbutton schiacciato)
  Serial.println(" => Allarme in corso ...");
}

void setup() 
{  
  pinMode(LED, OUTPUT);       // imposta il pin digitale (13) come output  
  pinMode(BOTTONE, INPUT);    // imposta il pin digitale (7) come input  
  // La parte del SERIAL MONITOR è solo per il TEST
  Serial.begin(9600);
  Serial.println("ESEMPIO GESTIONE ALLARME");
  Reset_AlarmSystem();
  strcpy(CellulareAutorizzato,"+393380000000");
  #ifdef AMBIENTEDIPROVA
      // -- Righe utilizzate per i test
      Serial.println(" => STATUS Ambiente TEST = PRONTO");
      GSMstarted=true; 
  #else
      // Inizializzo la connessione GSM impostando il baudrate
      // Per l'utilizzo di HTTP è opportuno usare 4800 baud o meno
      if ( gsm.begin(2400) )
      {
         Serial.println(" => STATUS Modulo GSM = PRONTO");
         GSMstarted=true;  
      }
      else 
         Serial.println(" => STATUS Modulo GSM = INATTIVO");
  #endif 
}  
  
void loop() 
{ 
  char inSerial[50];
  char position;
  if (GSMstarted) // Se il sistema GSM si è attivato
  {
      if (!SMSInviato && acceso) // se l'allarme è attivato per la prima volta invia l'SMS
      {
          #ifndef AMBIENTEDIPROVA          // Compilazione condizionale
             sms.SendSMS(CellulareAutorizzato, "ALLARME ATTIVATO!"); // restituisce true se invia l'SMS
             delay(500);
          #endif 
          SMSInviato=true;
          Serial.println(" => SMS di Allarme inviato!");
      }
      #ifdef AMBIENTEDIPROVA                // Compilazione condizionale
          position=SerialRead(smsbuffer);   // Test
          strcpy(Mittente,"+393380000000"); // Usato nei test per valutare se il mittente è autorizzato
      #else
          // Controllo se ci sono degli SMS in ingresso. Se l'allarme è spento allora li ignoro
          position = sms.IsSMSPresent(SMS_ALL); // Valore da 1..20
      #endif 
      if (position) 
      {
          #ifndef AMBIENTEDIPROVA          // Compilazione condizionale
              sms.GetSMS(position, Mittente, smsbuffer, 160);
          #endif 
          Serial.print("Comando Ricevuto [tel. "+String(Mittente)+String("]: ") + String(smsbuffer));
          if (strncmp(Mittente,CellulareAutorizzato,13)==0)
          {  
              if ((strcmp(smsbuffer,"ALARM-OFF")==0) && acceso)
                 Reset_AlarmSystem();
              else 
                 Serial.println(" => Comando non autorizzato!");
          }
          else
              Serial.println(" => Cellulare non autorizzato!");
          #ifndef AMBIENTEDIPROVA      // Compilazione condizionale
              sms.DeleteSMS(position); // Elimina l'SMS appena analizzato
              delay(500);
          #endif 
      }
  }
  else
     return; // se il GSM non parte il sistema di allarme non viene gestito.
  if (!acceso)
  {
    val = digitalRead(BOTTONE);  // leggo il valore dell'input e lo conservo in val  
    if (val == HIGH)             // se il pushbutton è premuto parte l'allarme
      Activate_AlarmSystem();
  }
}

Sul  serial monitor durante l'esecuizione appare il seguente LOG:

GSM Module - Esempio sistema d'allarme

ATTENZIONE! Ricordarsi, prima di mandare in esecuzione il programma, che occorre premere il tasto "POWER" (1) sul modulo GSM. Il led Status si accende mentre il led NET (di rete) lampeggia con una frequenza elevata ogni 800 millisecondi fino a quando il modulo GSM aggancia la rete. A questo punto il lampeggio diventa meno frequente, circa una volta ogni 3 secondi.  Se non procediamo con l'accensione sul Serial Monitor otteniamo questo messaggio di errore.

GSMModule  - Esempio Allarme

Quando scatta l'allarme (simulato con la pressione del pulsante) viene inviato un SMS di allarme al cellulare autorizzato.

SMS Allarme

Codice Sorgente C

Obiettivo progetto: Scrivere 4 programmi che, utilizzando i comandi AT, consentano:
- chiamare un telefono
- inviare un SMS.
- ricevere un SMS
- inviare comandi AT

soluzione: Per implementare il circuito necessario ai nostri scopi ci basta agganciare il modulo GSM ad Arduino. Ricordarsi di accendere il  modulo GSM!

Modulo GSM - Power Button

Programma 1: Chiama un numero telefonico

/* -----------------------------------------------------------------------------------
 Esempio creato partendo dal codice sul sito: 
 http://tronixstuff.com/2014/01/08/tutorial-arduino-and-sim900-gsm-modules/
 Chiama un numero di telefono
 ---------------------------------------------------------------------------------- */
#include <SoftwareSerial.h>
SoftwareSerial SIM900(2, 3); // configuro TX/RX (2 TDX - 3 RDX)
 
void setup()
{
  SIM900.begin(19200);               
  //  delay(20000);  // eventuale attesa il collegamento alla rete cellulare. 
}
 
void loop()
{
    // Chiama un cellulare
    SIM900.println("ATD + +39338000000;");
    delay(100);
    SIM900.println();
    delay(30000);            // aspetta 30 secondi...
    SIM900.println("ATH");   // Si disconnette
    do {} while (1); // loop a vuoto infinito
}

Programma: Invia un SMS

/* -----------------------------------------------------------------------------------
 Esempio creato partendo dal codice sul sito: 
 http://tronixstuff.com/2014/01/08/tutorial-arduino-and-sim900-gsm-modules/
 Invia un SMS
 ---------------------------------------------------------------------------------- */
#include <SoftwareSerial.h>
SoftwareSerial SIM900(2, 3); // configuro TX/RX (2 TDX - 3 RDX)
 
void setup()
{
  SIM900.begin(19200);
  // delay(20000);  // eventuale attesa il collegamento alla rete cellulare.
}

void loop()
{
  // Invio SMS
  SIM900.print("AT+CMGF=1\r");     // Comando AT per spedire un messaggio SMS
  delay(100);
  SIM900.print("AT+CSCS=\"GSM\"\r"); // Imposta la codifica GSM
  delay(100);
  SIM900.println("AT + CMGS = \"+393380000000\"");  // Il numero va scritto con il prefisso nazionale
  delay(100);
  // vedi http://www.smssolutions.net/tutorials/gsm/sendsmsat/ per la gestione delle 
  // lettere accentate
  SIM900.println("Salve Mondo. Questo e' un messaggio da Arduino.");
  delay(100);
  SIM900.println((char)26);  // Fine del comando AT indicato con un ^Z, codice ASCII 26
  delay(100); 
  SIM900.println();
  delay(5000);   // Lascia il tempo al modulo GSM di spedire il messaggio
  do {} while (1); // loop a vuoto infinito
}

Programma: Ricezione SMS

/* -----------------------------------------------------------------------------------
 Esempio creato partendo dal codice sul sito: 
 http://tronixstuff.com/2014/01/08/tutorial-arduino-and-sim900-gsm-modules/
 Mostra sul serial monitor tutti i caratteri in uscita sulla porta seriale del 
 modulo GSM e tra questi anche gli SMS
 ---------------------------------------------------------------------------------- */
#include <SoftwareSerial.h>
SoftwareSerial SIM900(2, 3);  // configuro TX/RX (2 TDX - 3 RDX)

char incoming_char=0;

void setup()
{
  Serial.begin(19200); // Ricordarsi di porre la connessione sulla finestra del Serial
                       // monitor a 19200
  SIM900.begin(19200); // setta la velocità di comunicazione sulla seriale del cellulare
  // delay(20000);     // eventuale attesa per il collegamento alla rete cellulare. .

  SIM900.print("AT+CMGF=1\r");  // Imposta la modalità SMS a testo
  delay(100);
  SIM900.print("AT+CNMI=2,2,0,0,0\r"); // trasferisce il contenuto di un nuovo messaggio 
                                       // SMS all'uscita seriale del modulo GSM.
  delay(100);
  SIM900.print("AT+CSCS=\"GSM\"\r"); // Imposta la codifica GSM
  delay(100);
}

void loop()
{
  if(SIM900.available() >0)
  {
    incoming_char=SIM900.read(); // Legge il carattere sulla porta seriale del cellulare
    Serial.print(incoming_char); // e lo mostra sul serial monitor
  }
}

Che mostra sul serial monitor le seguenti informazioni:

Ricezione SMS con Comandi AT

Programma: Terminale comandi AT

Infine ecco il codice che consente di digitare direttamente sul serial monitor i comandi AT da inviare al modulo GSM:

/* -----------------------------------------------------------------------------------
 Consente di inviare i comandi AT direttamente dal Serial Monitor
 ---------------------------------------------------------------------------------- */
#include <SoftwareSerial.h>
SoftwareSerial SIM900(2, 3);
char smsbuffer[160];
char incoming_char=0;

// legge una stringa dal Serial Monitor e traduce \n e \r in 
boolean SerialRead(char s[])
{
  int i=0;
  boolean EscCode=false;
  boolean CtrlCode=false;
  if (Serial.available() > 0)
  {            
    while (Serial.available() > 0) 
    {
      s[i]=Serial.read();
      if (EscCode)
      {
          // sostituisco le stringhe "\n" e "\r" con le
          // i caratteri '\r' e '\n'
          if (s[i]=='r')
             s[i]='\r'; // carattere CR
          else if (s[i]=='n')
             s[i]='\n'; // carattere LF
          else
          {
            i++;
            s[i]=s[i-1];
            s[i-1]='\\';
          }
          i++;
          EscCode=false;
      }
      else if (CtrlCode)
      {
        if (s[i]=='z')
        {
           s[i]=(char)26; // ctrl+Z
      Serial.print("^Z\n");  
      }else
        {
            i++;
            s[i]=s[i-1];
            s[i-1]='^';
        }
        i++;
        CtrlCode=false;
      }
      else if (s[i]=='\\')
         EscCode=true;
      else if (s[i]=='^')
         CtrlCode=true;
      else
         i++;      
      delay(10);
    }
  }
  s[i]='\0';
  return (i!=0);
}
void setup()
{
  Serial.begin(19200); // Ricordarsi di porre la connessione sulla finestra del Serial
                       // monitor a 19200
  SIM900.begin(19200); // Setta la velocità di comunicazione sulla seriale del cellulare
  Serial.print("Terminale Comandi AT:\n");
}

void loop()
{
  char position;
  if(SIM900.available() >0)
  {
    incoming_char=SIM900.read(); // Legge il carattere sulla porta seriale del cellulare
    Serial.print(incoming_char); // e lo mostra sul serial monitor
  }
  position=SerialRead(smsbuffer); 
  if (position)
     SIM900.print(smsbuffer);
}

Per provarlo ci basta inserire sul serial monitor la sequente sequenza AT (lo \r, [new line su MACOS prime di X] \n [new line in Unix/MacX] e ^z sono codifiche del mio programma per inviare i caratteri CR, LF e CTRL+Z):

AT+CMGF=1\r
AT+CSCS="GSM"\r
AT+CMGS="+393385555555"\r
Salve Mondo!\r
^z\r

La digitazione dei comandi qui sopra produce il seguente risultato sul serial monitor:

Output Comandi AT