Software EgoAlarmA volte è utile avere un modulo che effettua chiamate sul cellulare nel caso si verifichi un qualche evento, come ad esempio un allarme.
In questo articolo viene presentata la logica di controllo ed il sistema di segnalazione tramite chiamate GSM e messaggi SMS.
Alla fine di questa guida avrai un dispositivo che farà chiamate e invierà SMS ai numeri che imposterai, al verificarsi di un evento come ad esempio la chiusura di un contatto.
Il sistema è composto da Arduino Uno, comandabile via seriale USB, ed il modem GSM Keyestudio KS0254 basato su SIM800C.
Di seguito i link per comprarli:
Modem GSMModulo per chiamate e sms su rete cellulare |
|
Arduino UNOArduino della stessa ditta del modulo GSM. Il modulo sopra si monta “on top”. |
Comprare una SIM per allarme (o provare con quella del proprio telefono).
Istruzioni passo passo
Se vuoi puoi aiutare questo sito comprando l’ultima versione del software:
Software EgoGSM per miniallarme
Oppure puoi comprare il tutto già montato:
Come prima cosa compra i due moduli sopra indicati. Se li compri passando dai link proposti, aiuti questo sito.
Comprare anche una SIM con il traffico adatto. Prima di inserirla del modulo, inseriscila in un cellulare e togli il pin.
Dopo scarica il software per programmare Arduino:
https://www.arduino.cc/en/Main/Software
Installa il software.
Scarica le librerie specifiche da questa pagina:
https://www.domoticachepassione.it/wp/download/richiesta-software-allarme-gsm/
Una volta ottenuto il file egogsmlib.zip, scompattalo.
Le quattro cartelle
SIM800H EgoMiniTimer EgoSignalManager EgoStringUtil
vanno spostate nella cartella delle librerie di Arduino.
In Windows la cartella è dentro
Documenti
nella cartella
Arduino.
A questo punto lanciare il software Arduino.
Nella pagina che appare copiare ed incollare il seguente sorgente:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * Code by Ennio Balocchi https://www.domoticachepassione.it */ #include <SoftwareSerial.h> #include "Timer.h" //ci vuole altrimenti non lo trova compilando in arduino #include "EgoStringUtil.h" #include "EgoSignalManager.h" //Per vedere come gestire la memoria //https://www.arduino.cc/en/Tutorial/Memory //https://www.arduino.cc/en/Reference/PROGMEM #include <avr/pgmspace.h> Timer EgoSignalManager::timer; typedef void (*SimpleFunction) (); const char* const EgoSignalManager::inputDescr0[] ={"Sens tranquillo"}; const char* const EgoSignalManager::inputDescr1[] ={"Sens attivo"}; int* EgoSignalManager::simulateTimerId; const char* const EgoSignalManager::outputDescr0[]={ "o1 L", "o2 L"}; const char* const EgoSignalManager::outputDescr1[]={ "o1 H", "o4 H"}; //byte EgoSignalManager::statusN=1; //const char* const EgoSignalManager::statusDescr0[]={"Per spento","Int spento"}; //const char* const EgoSignalManager::statusDescr1[]={"Per acceso","Int acceso"}; const char* const EgoSignalManager::statusDescr0[]={"Per spento"}; const char* const EgoSignalManager::statusDescr1[]={"Per acceso"}; char seq=0; //numero di cicli di chiamate #define CALLATTEMPT 2 char tentativi=0; byte EgoSignalManager::inputSnapShot; byte EgoSignalManager::outputSnapShot; int EgoSignalManager::statusSnapShot; String EgoSignalManager::inputString; //se un pin va a 1 //imposta il contatore di impulsi al valore N ed il contatore di secondi a N //ogni volta che da 0 va a 1 decrementa il contatore di impulsi //ogni volta che passa un secondo decrementa il contatore di secondi //se il contatore di secondi va a 0 e il contatore di impulsi supera il conteggio allora invia allarme byte EgoSignalManager::inputPulseN[]= {1,1}; byte EgoSignalManager::inputPulseCounter[]={0,0}; long EgoSignalManager::inputTimerN[]= {1000,1000}; long EgoSignalManager::inputTimer[]= {0,0}; byte EgoSignalManager::simulateInputs=0; //setta a 1 i bit degli input da forzare byte EgoSignalManager::simulateValues=0; //valore per i bit da simulare; const byte zone=1; //byte zona[]={B01110000,B10001010}; byte zona[]={B00000001}; void doCheckTriggerSeAllarmeAcceso(byte pin){ #ifdef DEBUG Serial.println("Check trigger se allarme acceso "+String(pin)); #endif for(byte z=0;z<zone;z++){//per ogni zona if(bitRead(EgoSignalManager::statusSnapShot,z)==HIGH){//se zona accesa #ifdef DEBUG Serial.println("Zona accesa "+String(z)); Serial.println(bitRead(zona[z],pin),BIN); Serial.println(zona[z],BIN); #endif if(bitRead(zona[z],pin)){ //se il pin fa parte della zona Serial.println("pin "+String(pin)+" attivo e allarme acceso, controllo timer"); EgoSignalManager::doCheckTrigger1(pin); //fa partire i timer per controllare se non è un disturbo ma è allarme vero. Se allarme vero viene richiamato doTrigger } } } } void doPreAllarme(byte pin){ } /////////////////////////////// ////////////////////////////7 DoActionFunction EgoSignalManager::doAction0[]={ EgoSignalManager::doPrintIn0,doActivateAlarm }; DoActionFunction EgoSignalManager::doAction1[]={ doAllarme,doDeactivateAlarm }; void doCheckAllarme(byte pin){ //if(bitRead(EgoSignalManager::statusSnapShot,ALLARME_ACCESO)==HIGH){ //segnala //} } void doCheckPreAllarme(byte pin){ //if(bitRead(EgoSignalManager::statusSnapShot,ALLARME_ACCESO)==HIGH){ //segnala //} } DoActionFunction EgoSignalManager::doTrigger[]={ doAllarme }; DoActionFunction EgoSignalManager::doShortTrigger[]={ doPreAllarme }; //SoftwareSerial gsmSerial(7, 8); // RX, TX #include <sim800cmd.h> unsigned char gsmcmd=0; char* number[]={"+39329800",NULL,NULL,NULL,NULL}; unsigned char numbers=1; #define MAXNUMBERS 5 #define NUMBERS 1 //application callback function void fundebug(void) { } //initialize the library instance //fundebug is an application callback function,when someon is calling. Sim800Cmd sim800demo(fundebug); void sendSMS(String msg){ for(char i=0;i<numbers;i++){ //char p1[number[i].length()+1]; //number[i].toCharArray(p1,number[i].length()+1); char p2[msg.length()+1]; msg.toCharArray(p2,msg.length()+1); p2[msg.length()]='\0'; //sim800demo.sendSMSDirectly(number[i],p2); //sim800demo.sendSimpleSMS(p1,p2); char* n=sim800demo.asciiToUCS2(number[i]); char* m=sim800demo.asciiToUCS2(p2); sim800demo.sendSMS(n,m); free(n); free(m); sim800demo.atsendcmd("AT",200,200); } } void doActivateAlarm(byte pin){ EgoSignalManager::statusHigh(0); } void doDeactivateAlarm(byte pin){ EgoSignalManager::statusLow(0); } void doAllarme(byte pin){ if(bitRead(EgoSignalManager::statusSnapShot,0)==LOW){//se zona non accesa return; } Serial.print(F("Allarme: ")); Serial.println(EgoSignalManager::inputDescr1[pin]); EgoSignalManager::outputHigh(1); String s=F("allarme"); Serial.println(s); sendSMS(s); //EgoSignalManager::timer.after(10*1000,EgoSignalManager::outputHigh(0),pin); EgoSignalManager::timer.after(60000,EgoSignalManager::outputLow,1); gsmcmd=1; } void commandPlugin(String inputS){ //Serial.println("sono qui"); //Serial.print(inputS); //Serial.println("<-"); //Serial.print("invece inputstring "); //Serial.println(inputS); if (inputS.startsWith("call")) { gsmcmd=1; } if (inputS.startsWith("add:")) { String s=EgoStringUtil::tail(inputS,':'); s.trim(); addNumber(s); } if (inputS.startsWith("clear")) { for(char i=0;i<numbers;i++){ free(number[i]); } numbers=0; } if (inputS.startsWith("list")) { listNumbers(); } if (inputS.startsWith("send:")) { String s=EgoStringUtil::tail(inputS,':'); sendSMS(s); // Serial.print("s="); // Serial.println(s); // for(char i=0;i<numbers;i++){ // //char p1[number[i].length()+1]; // //number[i].toCharArray(p1,number[i].length()+1); // char p2[s.length()+1]; // // s.toCharArray(p2,s.length()+1); // p2[s.length()-1]='\0'; // //Serial.print("p2="); // //Serial.println(p2); // // sim800demo.sendSMSDirectly(number[i],p2); // } } if (inputS.startsWith("stop")) { tentativi=0; seq=0; gsmcmd=0; } if (inputS.startsWith("reset")) { digitalWrite(9,HIGH); delay(2000); digitalWrite(9,HIGH); resetSw(); } if (inputS.startsWith("cmd:")) { String s=EgoStringUtil::tail(inputS,':'); _Serial.println(s); } } Plugin EgoSignalManager::cmdPlugin=commandPlugin; void smsFunc(){ Serial.println("Ricevuto"); } void resetHw(){ Serial.println(F("reset hw")); pinMode(9,OUTPUT); digitalWrite(9,HIGH);// delay(2000); digitalWrite(9,LOW);// } void resetSw(){ Serial.println("iniziamo..."); //initialize the digital pin as an output. pinMode(13,OUTPUT); resetHw(); //delay(3000); //digitalWrite(12,HIGH);// //initialize SIM800H,return 1 when initialize success. byte i=0;//tentativi while((sim800demo.sim800init()) == 0){ Serial.print(F("attempt ")); Serial.println(i); delay(10); if(i>=3){//tentativi resetHw(); i=0; } i++; }; Serial.println("inizializzazione completata."); // EgoSignalManager::setCmdPlugin(commandPlugin); sim800demo.setSMSEnablePrompt(OPEN); sim800demo.setSMSHandlefunction(smsFunc); } //the setup routine runs once when you press reset: void setup() { EgoSignalManager::init(); //start serial connection Serial.begin(19200); //configure pin2 as an input and enable the internal pull-up resistor EgoSignalManager::setupIn(); EgoSignalManager::setupOutLow(); resetSw(); } void call(byte n){ unsigned char csq = 0; //To obtain the signal strength, return 1 when obtain success. sim800demo.cancelCall(); if( sim800demo.callReadCSQ(&csq) ) { Serial.print(F("chiamo ")); Serial.println(number[n]); //Make Voice Call char *_str; _str = (char *)malloc(strlen(number[n])+2); strcpy(_str,number[n]); strcat(_str,";"); sim800demo.dialTelephoneNumber(_str); free(_str); delay(20000); sim800demo.cancelCall(); } } //the loop routine runs over and over again forever: void loop() { EgoSignalManager::loop(); //Signal strength if(gsmcmd==1){//chiama call(seq); seq++; if(seq>=numbers){ seq=0; tentativi++; if(tentativi>=CALLATTEMPT){ tentativi=0; gsmcmd=0; } } } // digitalWrite(13,HIGH);//turn the LED on by making the voltage HIGH // delay(500); // digitalWrite(13,LOW);//turn the LED off by making the voltage LOW // delay(500); } //void addNumber(String num){ // if(numbers>=MAXNUMBERS){ // Serial.println("too many numbers."); // return; // } // char m=min((num.length()),(strlen(number[numbers])+1)); // for(char i=0;i<m;i++){ // number[numbers][i]=num[i]; // } // number[numbers][m]='\0'; // numbers++; //} void addNumber(String num){ if(numbers>=MAXNUMBERS){ Serial.println("too many numbers."); return; } char l=num.length()+1; char* str = (char *)malloc(l); num.toCharArray(str,l); number[numbers]=str; numbers++; } void listNumbers(){ for(char i=0;i<numbers;i++){ Serial.println(number[i]); } } void serialEvent() { EgoSignalManager::readSerialCommand(); }
Salvare il file scegliendo File|Salva con nome…
e dandogli il nome egogsm.
Inserire il numero di telefono
All’interno del file sorgente che è stato copiato, cercare la frase:
SCRIVI I TUOI NUMERI DA CHIAMARE QUI
ed inserire nella lista i propri numeri di telefono.
A questi numeri sarà inviato un SMS e vengono chiamati uno dopo l’altro.
Salvare il file scegliendo File|Salva.
Compilazione del sorgente (sketch)
Dare il comando Sketch|Verifica/compila
Controllare che la compilazione vada a buon fine con una frase del tipo:
Lo sketch usa 16240 byte (50%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Assemblaggio Arduino e modulo GSM
Montare il modulo GSM sulla scheda di Arduino UNO, come da foto, allineando i pin.
Posizionare i due jumper in modo che sia selezionato D7 e D8 come Rx e Tx della porta seriale.
Impostare l’alimentazione del circuito su Arduino.
Inserire il cavo USB in Arduino UNO ed nel PC.
Caricare lo sketch su Arduino UNO
Andare su Strumenti|Scheda e scegliere Arduino/Genuino UNO.
Cliccare su Strumenti|Porta e selezionare la porta USB (COM o tty) su cui è collegato Arduino UNO. Se non si riesce a capire, provare a scollegare Arduino UNO e vedere nella lista delle porte quale sparisce. Ricollegare e controllare quale porta appare che prima non era nella lista.
Controllare che su Strumenti|Programmatore sia selezionato AVRISP mkII.
Cliccare su Sketch|Carica.
Aspettare che appaia in fondo alla pagina “Caricamento completato”.
Test di funzionamento
Scegliere Strumenti|Monitor seriale.
Selezionare la velocità in basso 19200 baud.
Scegliere A capo (NL).
Accendere il modulo GSM. Premere per qualche secondo il pulsantino di lato. Si devono accendere due led rossi.
Devono cominciare ad apparire dei messaggi del tipo:
iniziamo...>AT >AT
e una volta acceso il modulo GSM
<<OK << <<RDY << <<+CFUN: 1
Dopo un po’ appare:
inizializzazione completata.
Per provarlo, chiudere il contatto D5 (pin n.6) collegandolo a GND, per entrare in modalità allarme.
Poi chiudere il contatto D6 (pin n.7) collegandolo a GND e poi aprire il contatto, per provare se invia l’allarme.
Prima viene mandato un SMS ad ogni numero della lista, e poi viene chiamato ogni numero della lista per 1 minuto.
__________________________________
iniziamo... >AT < <<OK << >AT < <<OK << >ATE0 < <<OK << >AT+CNMI=2,1,0,1,0 < <<OK << >AT+CMGF=1 < <<OK << >AT+CSCS="UCS2" < <<OK << >AT+CSMP=17,167,2,25 < <<OK << >AT+CSQ < <<+CSQ: 26,0 << <<OK << inizializzazione completata. Diversi 10 11 status: Sens tranquillo. In0 L 1 Diversi 11 10 Diversi 1 11 status: Per acceso Diversi 11 1 status: Per spento Diversi 1 11 status: Per acceso Diversi 11 1 status: Per spento Diversi 1 11 status: Per acceso Diversi 0 1 status: Sens tranquillo. In0 L 1 Diversi 1 0 Allarme: Sens attivo status: o4 H allarme >AT+CMGS="002B0033003900" < <<> >0061006C006C00610072006D0065 >AT >AT >AT >AT >AT >AT >AT >AT >AT >AT >AT >AT >AT >AT < <<+CMGS: 42 << <<OK << <<OK << >AT < <<OK << >ATH0 < <<OK << chiamo +39329800**** >ATD+39329800***; < <<OK << >ATH0 >ATH0 chiamo +39329800**** >ATD+39329800****; <⸮T⸮ <<OK << >AT+CSQ < <<+CSQ: 26,0 << <<OK <<
Bell’articolo!
Progetto interessante. Si può aggiungere una sirena che suoni per un tempo prestabilito dopo il rilevamento di intrusioni? Se si come posso fare per il software e per l’hardware?
Il progetto ha in sè tutte le potenzialità che richiede. Il sorgente, ma anche il modo in cui è strutturato, permette personalizzazioni. Se riesco a trovare il tempo questi giorni magari ci faccio un articolo.
Giusto per darle qualche idea, il progetto funziona come una macchina a stati, nel senso che esiste una tabella di transizione che al verificarsi di certe condizioni richiama delle funzioni che possono essere definite con un minimo di personalizzazione.
Buona giornata.
possibile ritardare l’accensione del dispositivo e ritardare l’attivazione della chiamata/sms ?
A che scopo ritardare l’accensione?
Se intendi una volta acceso, far aspettare altro tempo, prima di iniziare i controlli, si può metere un delay(xxx) prima di resetSw.
A che scopo ritardare le chiamate? Intendi far partire le chiamate se lo stato di allarme perdura per un certo numero di millisecondi?