MODULI: Esempio GSM MODULE
Per costruire i seguenti esempi occorre procurarci un modulo GSM ad esempio iComSat v. 1.1
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).
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.
Ecco l'immagine del circuito
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.
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
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
.
Se abbiamo dimenticato inizialmente di premere il tasto POWER sul modulo GMS allora sul Serial Monitor verrà mostrato il seguente messaggio di errore:
Se inviamo un SMS con il messaggio "STATUS" riceviamo in risposta un SMS con lo stato corrente 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.
Innestiamo il modulo GSM sopra Arduino e costruiamo il seguente progetto
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:
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.
Quando scatta l'allarme (simulato con la pressione del pulsante) viene inviato un SMS di allarme al cellulare autorizzato.
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!
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:
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: