"Risolto" Problemi con sim 900

Ciao a tutti,
sto usando il modulo gsm sim 900 collegato a arduino uno con il seguente sketch funzionante:

/* -----------------------------------------------------------------------------------
 Accende e spegne un RELE a secondo dell'SMS inviato:
 ON  => Accende il RELE
 OFF => Spegne il RELE
 STATO => Stato del pin
 Altro => Messaggio di errore sul Serial Monitor

 Per maggiori info: www.progettiarduino.com
 ---------------------------------------------------------------------------------- */
#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 rele = 12; // Il Pin 12 è quello connesso al relè
int numdata;
boolean started=false;
char smsbuffer[160];
char Mittente[20];

void setup() 
{
  Serial.begin(9600);
  Serial.println("ESEMPIO INVIO/RICEZIONE SMS");
  pinMode(rele, OUTPUT);   // imposta il pin 12 come pin di OUTPUT.
  digitalWrite(rele, 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(rele, HIGH);   // Accende il RELE impostando il voltaggio a HIGH
         Serial.println(" => Accendo il RELE");
      }
      else if (strcmp(smsbuffer,"OFF")==0)
      {
         digitalWrite(rele, LOW);    // Spengo il RELE impostando il voltaggio a LOW
         Serial.println(" => Spengo il RELE");
      }
      else if (strcmp(smsbuffer,"STATO")==0)
      {
          if (digitalRead(rele)==HIGH)
          {
             sms.SendSMS(Mittente, "STATUS: RELE Acceso"); // restituisce true se invia l'SMS
             Serial.println(" => il RELE e' Acceso");
          }
          else
          {
             sms.SendSMS(Mittente, "STATUS: RELE Spento"); // restituisce true se invia l'SMS
             Serial.println(" => il RELE e' Spento");
          }
      }
      else
         Serial.println(" => non riconosciuto!");
      sms.DeleteSMS(position); // Elimina l'SMS appena analizzato
    }
    delay(1000);
  }
};

Il problema è che ogni volta che tolgo e ricollego la tensione a arduino, il modulo parte a leggere i vecchi sms ricevuti eseguendoli senza aver inviato alcun sms.
Difatti aprendo il monitor seriale vedo che legge tutti gli sms ricevuti a partire dal più vecchio e li esegue tutti finchè non arriva all’ultimo sms ,(ne legge uno per volta ogni 10 secondi circa, facendo diventare il relè un intermittenza continua di on off) dopodichè funziona tutto correttamente.
sembra che il comando sms.DeleteSMS(position); non venga realmente eseguito.
Voi che ne pensate?
Grazie a tutti
Enzo

Che ci vuole una funzione che memorizza informazioni dell' ultimo ricevuto (forse il numero sequenziale) e lo mette in EEPROM. Quando si riaccende riprende il numero e parte a cercare solo gli SMS dopo quel numero. Percui, dovresti salvare position ad ogni nuovo messaggio ricevuto. Tanto una singola cella di EEPROM la puoi scrivere 100`000 volte, al massimo passi a quella successiva, dopo un tot di scritture.

ExperimentUno:
Che ci vuole una funzione che memorizza informazioni dell’ ultimo ricevuto (forse il numero sequenziale) e lo mette in EEPROM. Quando si riaccende riprende il numero e parte a cercare solo gli SMS dopo quel numero.
Percui, dovresti salvare position ad ogni nuovo messaggio ricevuto. Tanto una singola cella di EEPROM la puoi scrivere 100`000 volte, al massimo passi a quella successiva, dopo un tot di scritture.

Ciao, quindi secondo quello che mi dici dovrei fare una cosa del genere?:

#include "SIM900.h"
#include <SoftwareSerial.h> // necessaria alla libreria gsm.h richiamata in sms.h
#include "sms.h"            // Libreria per la gestione degli SMS
#include <EEPROM.h>
int conteggio = 0; // variabile da usare in eeprom
byte valore;
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);
}


void loop() 
{ 
  char inSerial[50];
  char position;
  
  //prova salva sms 
  valore = EEPROM.read(conteggio);
  Serial.print(valore);
  conteggio=position+1;
  if (conteggio == 1024)
  conteggio= 0;
  delay(500);
  //fine 
  
  if (started)
  { // 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);
  }
};

Grazie
Enzo

Non vedo l' opzione di salvare in EEPROM l' ultimo comando valido. Io penso che si potrebbe aggiungere

#define led 13      // non serve la variabile per un valore costante

unsigned long currTime;
int lastSaved;
// il tuo programma

void loop() 
{ 
  if ((millis()-5000) >= currTime)      // faccio l'operazione di scrivere nella eeprom ogni 5 secondi
  {
     currTime = millis();
     if ( lastSaved != conteggio)        //  se  c'e' un messaggio nuovo.
     {
         //prova salva sms 
         Serial.print(EEPROM.read(conteggio));
        if (conteggio > 1024) conteggio = 0;   // se nel limite, altrimenti azzera
        else conteggio = position + 1;             // altrimenti aumenta di uno
        //fine 
        lastSaved = conteggio;           // ricordo la posizione vecchia
        EEPROM.write(conteggio);      // e scrivo la eeprom
     }
   }
      // il resto del programma

}

Il programma non è provato, è solo una idea di come avrei implementato il mio concetto. Spero sia didatticamente utile.

Ma perché tieni gli sms in memoria ?? Secondo me sarebbe più facile se ogni volta che ricevi un sms ne esegui i comandi po lo cancelli..

ciao

ExperimentUno:
Non vedo l’ opzione di salvare in EEPROM l’ ultimo comando valido.
Io penso che si potrebbe aggiungere

#define led 13      // non serve la variabile per un valore costante

unsigned long currTime;
int lastSaved;
// il tuo programma

void loop()
{
  if ((millis()-5000) >= currTime)      // faccio l’operazione di scrivere nella eeprom ogni 5 secondi
  {
    currTime = millis();
    if ( lastSaved != conteggio)        //  se  c’e’ un messaggio nuovo.
    {
        //prova salva sms
        Serial.print(EEPROM.read(conteggio));
        if (conteggio > 1024) conteggio = 0;  // se nel limite, altrimenti azzera
        else conteggio = position + 1;            // altrimenti aumenta di uno
        //fine
        lastSaved = conteggio;          // ricordo la posizione vecchia
        EEPROM.write(conteggio);      // e scrivo la eeprom
    }
  }
      // il resto del programma

}



Il programma non è provato, è solo una idea di come avrei implementato il mio concetto. Spero sia didatticamente utile.

Ciao ho provato a integrare la tua idea nel mio sketch ma ottengo un errore in fare di compilazione sulla EEPROM.write.

#include "SIM900.h"
#include "sms.h"
#include <SoftwareSerial.h> 
#include <EEPROM.h>
#define rele 12  

SMSGSM sms;
int numdata;
boolean started=false;
char smsbuffer[160];
char Mittente[20];
unsigned long currTime;
int lastSaved;
int conteggio = 0; // variabile da usare in eeprom

void setup() 
{
  Serial.begin(9600);
  Serial.println("ESEMPIO INVIO/RICEZIONE SMS");
  pinMode(rele, OUTPUT);   // imposta il pin 12 come pin di OUTPUT.
  digitalWrite(rele, LOW); // spegne inizialmente il led
  
  if ( gsm.begin(2400) )
  {
     Serial.println("STATUS Modulo GSM = PRONTO");
     started=true;  
  }
  else 
     Serial.println("STATUS Modulo GSM = INATTIVO");
}

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);
}

void loop() 
{ 
  char inSerial[50];
  char position;
  if (started)
  {
    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(rele, HIGH);   // Accende il RELE impostando il voltaggio a HIGH
         Serial.println(" => Accendo il RELE");
      }
      else if (strcmp(smsbuffer,"OFF")==0)
      {
         digitalWrite(rele, LOW);    // Spengo il RELE impostando il voltaggio a LOW
         Serial.println(" => Spengo il RELE");
      }
      else if (strcmp(smsbuffer,"STATO")==0)
      {
          if (digitalRead(rele)==HIGH)
          {
             sms.SendSMS(Mittente, "STATUS: RELE Acceso"); // restituisce true se invia l'SMS
             Serial.println(" => il RELE e' Acceso");
          }
          else
          {
             sms.SendSMS(Mittente, "STATUS: RELE Spento"); // restituisce true se invia l'SMS
             Serial.println(" => il RELE e' Spento");
          }
      }
      else
         Serial.println(" => non riconosciuto!");
      sms.DeleteSMS(position); // Elimina l'SMS appena analizzato
    }
    delay(1000);
  }

  
  if ((millis()-5000) >= currTime)      // faccio l'operazione di scrivere nella eeprom ogni 5 secondi
  {
     currTime = millis();
     if ( lastSaved != conteggio)        //  se  c'e' un messaggio nuovo.
     {
         //prova salva sms 
         Serial.print(EEPROM.read(conteggio));
        if (conteggio > 1024) conteggio = 0;   // se nel limite, altrimenti azzera
        else conteggio = position + 1;             // altrimenti aumenta di uno
        //fine 
        lastSaved = conteggio;           // ricordo la posizione vecchia
        EEPROM.write(conteggio);      // e scrivo la eeprom
     }}}

vic_20: Ma perché tieni gli sms in memoria ?? Secondo me sarebbe più facile se ogni volta che ricevi un sms ne esegui i comandi po lo cancelli..

ciao

Ciao, si infatti ho inserito questa stringa sms.DeleteSMS(position); // Elimina l'SMS appena analizzato Ma non li cancella!

Infatti ho definito che [u]non era provato[/u]. Probabilmente, manca il parametro dell' indirizzo della EEPROM. Bastava leggere qui ;)

ExperimentUno: Infatti ho definito che [u]non era provato[/u]. Probabilmente, manca il parametro dell' indirizzo della EEPROM. Bastava leggere qui ;)

Ciao, ti ringrazio molto per il tuo consiglio. Alla fine studiando bene la libreria,bastava sostituire questa stringa:position = sms.IsSMSPresent(SMS_ALL); con questa :position = sms.IsSMSPresent(SMS_UNREAD); in questa maniera esegue solo i messaggi non letti ;) ;) ;) Grazie mille per l'aiuto. Ciao a tutti e tanti auguri!!! Enzo