Go Down

Topic: [Fatto] Accendere led con sms. Sim900 shield senza librerie sim900.h (Read 5647 times) previous topic - next topic

hermit274

Apr 22, 2013, 12:03 am Last Edit: Apr 22, 2013, 12:40 am by hermit274 Reason: 1
Ciao ragazzi, era da un paio di giorni che stavo lavorando su questo piccola parte di codice e volevo condividerla su questo forum spettacolare in modo da aiutare e non far perdere tanto tempo agli smanettoni principianti come me in futuro.

Innanzi tutto dico a tutti che un pò di giorni fa ho acquistato una GSM/GPRS shield di questo tipo:
http://www.geeetech.com/wiki/index.php/Arduino_GPRS_Shield
All'inizio è stato abbastanza traumatico capire come funzionasse, ma dopo aver rivisto un pò di volte il codice mi sono reso conto che era davvero semplice.
Quello che volevo fare, come progetto basilare era semplicemente accendere un led attraverso un comando mandato tramite sms del tipo "accendi".
Ho iniziato a girare un pò il web e dopo ore e ore di ricerche non ho trovato nulla. Tutti consigliavano di utilizzare la libreria sim900.h, ma non sono contento delle cose precotte, inoltre non mi pareva il caso installare un'intera libreria per poter leggere semplicemente un sms.
Così dopo svariati milioni di sms inviati alla mia shield, e dopo ore a capire come funzionasse questa scheda, sono riuscito nell'impresa.
Posto il codice in modo tale che sia utile a qualcuno in futuro :)
Code: [Select]
#define led 13

#include <SoftwareSerial.h>

SoftwareSerial sim900(7,8);
char istruzioni_sim[100];

void setup(){
 Serial.begin(19200);
 sim900.begin(19200);
 pinMode(led, OUTPUT);
 delay(500);
}

void loop(){
 leggi_da_sim900();
}

void leggi_da_sim900(){  
 boolean ricevuto_sms = false;
 int i = 0;
 int numero_sms = 0;

 while(sim900.available() >0){
   char carattere = sim900.read();
   istruzioni_sim[i] = carattere;

   if(strcmp(istruzioni_sim, "\r\n+CMTI: \"SM\",")==0){   //vuol dire che ho ricevuto dalla shield la funzione di un nuovo sms
     carattere = sim900.read() -'0';                      //il carattere dopo la virgola è un numero; rappresenta l'ultimo sms
     numero_sms = carattere;  
     istruzioni_sim[i+1] = carattere;                      //salvo ugualmente il numero nel vettore istruzioni_sim
     ricevuto_sms = true;                                  //mi servirà per leggere l'sms solo quando lo ricevo
   }
   i++;
   delay(5);
 }

 if(ricevuto_sms == true){                                 //a questo punto vuol dire che ho ricevuto un sms
   while(i>0){
     istruzioni_sim[i] = NULL;                             //posso svuotare il vettore
     i--;
   }
   leggi_sms(numero_sms);                                  //passo alla funzione leggi_sms il valore dell'ultimo sms da leggere
   i=0;
   ricevuto_sms = false;
 }
}


void leggi_sms(int ultimo_sms){
 String sms;                                            //ho utilizzato una variabile string perchè non sapevo quanto dovesse essere lungo un sms
 int inizio_sms = 0;
 int count = 0;
 sim900.print("AT+CMGR=");                              //invio alla shield, la richiesta di lettura di sms
 sim900.println(ultimo_sms);                            //attenzione al println
 delay(200);

 while(sim900.available() >0){
   char carattere = sim900.read();                      //inizio a leggere l'sms
   if(carattere == '\"'){
     inizio_sms = count;                                //questa funzione si occupa di vedere dove inizia il testo dell'sms visto che la strnga ricevuta è del tipo ABC"\r\nTESTOSMS\r\n\r\n\r\nOK
   }
   sms += carattere;
   count++;
   delay(5);
 }

 sms.toLowerCase();                                                 //rendo tutto minuscolo
 
 //Serial.print(sms.substring((inizio_sms+3), (count-8)));         //questo perchè la stringa è composta come segue: ABC"\r\nBLA\r\n\r\n\r\nOK, comunque se abiliti questo Serial.print viene visualizzato il corpo dell'sms
 if(sms.substring((inizio_sms+3), (count-8)) == "accendi"){        //la parola accendi, è la mia parola chiave, può essere comunque cambiata per eseuire diverse azioni
   digitalWrite(led, HIGH);
 }
 else if(sms.substring((inizio_sms+3), (count-8)) == "spegni"){
   digitalWrite(led, LOW);
 }
  sms="";
 sim900.print("AT+CMGD=");                                          //invio alla shield la richiesta di eliminare l'ultimo_sms
 sim900.println(ultimo_sms);
 delay(100);
}


Se ci sono problemi o consigli per migliorarlo scrivete pure!

hermit274

Volevo solo chiedervi perchè la variabile

char istruzioni_sim[100];

deve essere dichiarata in modo globale. Se la dichiaro all'interno della funzione leggi_da_sim900() non funziona, ovvero:

Code: [Select]

void leggi_da_sim900(){
char istruzioni_sim[100];
.
.
.
if(strcmp(istruzioni_sim, "\r\n+CMTI: \"SM\",")==0){   //vuol dire che ho ricevuto dalla shield la funzione di un nuovo sms
      carattere = sim900.read() -'0';                      //il carattere dopo la virgola è un numero; rappresenta l'ultimo sms
      numero_sms = carattere; 
      istruzioni_sim[i+1] = carattere;                      //salvo ugualmente il numero nel vettore istruzioni_sim
      ricevuto_sms = true;                                  //mi servirà per leggere l'sms solo quando lo ricevo
    }
.
.
.
}

L'if che ho scritto non funziona...come mai?Non viene eseguita la funzione strcmp

leo72

Perché strcmp vuole 2 stringhe di char mentre tu gli passi un array, forse non hai messo il terminatore "\0" in fondo a quell'array e la stringa non è riconosciuta come tale.

hermit274

Mmmm... Però il modo in cui riempo il vettore di char è lo stesso, sia se la variabile è dichiarata globale, sia che è dichiarata nella funzione. Quindi se mancasse il carattere di fine stringa, non dovrebbe funzionare in nessun modo no?

ganakil

sono disperato... ho lo stesso shield gprs della geeetech con sim900 ma non riesco a farlo funzionare con nessuno sketch... nemmeno con questo :(  L'sms che mandi contiene "acceso" e si dovrebbe accendere il led 13 vero? Uso arduino duemilanove con atmega 328... I jumpers sono impostati su sw, xduino o gprs?

cyberhs

Anche tu commetti lo stesso errore di un tuo collega: il comando AT deve essere terminato da un <CR> e non da <CR><LF>, perciò non puoi usare il println

Riguardo alla questione della dichiarazione globale della stringa istruzioni è consigliabile farlo perché non sempre le routine chiamate dispongono di molta memoria SRAM: meglio allocare lo spazio all'inizio del programma,

marg1ch

Salve, io ho un problema.
Anche io ho una Shield con un Sim.900
e sto cercando come te di programmare senza librerie sim900.h

il mio problema è che: Riesco a ricevere gli SMS e me li salva in una memoria

come: +CMTI: "SM",6 dove 6 è la memoria

poi cerco di richiamarlo con

mySerial.print( "AT+CMGR=" );                 
mySerial.println( SmsStorePos );

ma la Sim.900 non da segno di vita

avete dei consigli per me?

Grazie Mille

Ho provato sia con
#include <SoftwareSerial.h>   
SoftwareSerial mySerial(7, 8);

che

#include <SoftwareSerial.h>   
SoftwareSerial mySerial(0, 1);




marg1ch

Ho cmq provato a scaricare il tuo programma sull mio arduino e non mi funziona...


Go Up