modulo sim900 si blocca all'improvviso

Ciao a tutti,
dopo tanto tempo, torno a consultarmi con voi per un piccolo e banalissimo progetto composto da arduino uno e modulo sim 900.
Il modulo sim900 deve semplicemente richiamare uno script ogni 30 secondi.
Lo sketch da me composto, sembra funzionare bene, a parte il fatto che a volte dopo 8 ore circa, si blocca!!!
ecco il mio codice:

// Richiamare uno script ogni 30 secondi circa, con modulo sim900!!!

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(2, 3);

void setup()
{
  digitalWrite(7, HIGH); //attiva pulsante power on sim 900
  delay(1500);  
  digitalWrite(7, LOW);
  delay(2500); 
  
  gprsSerial.begin(2400);
  Serial.begin(19200);
  Serial.println("Configigurazione SIM900...");
  delay(10000);//prima di avviare la comunicazione seriale, attendo che si connette alla linea!
  Serial.println("il modulo è pronto!...");
  gprsSerial.flush();
  Serial.flush();

  // connessione o disconnessione dal servizio GPRS
  gprsSerial.println("AT+CGATT?");
  delay(100);
  toSerial();


  // impostiamo i parametri
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
  delay(2000);
  toSerial();

  // impostiamo il servizio apn
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"iliad\"");
  delay(2000);
  toSerial();

  
  gprsSerial.println("AT+SAPBR=1,1");
  delay(2000);//2000
  toSerial();
}


void loop()
{
   // inizializzare il servizio http
   gprsSerial.println("AT+HTTPINIT");
   delay(1000); 
   toSerial();

   // settiamo i parametri della pagina da richiamare
   gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://server/attivo.php\""); 
   delay(10000);// calcolando tutti i delay impiega circa 30 secondi a richiamare la pagina
   toSerial();

   // imposta il tipo di azione http 0 = GET, 1 = POST, 2 = HEAD
   gprsSerial.println("AT+HTTPACTION=0");
   delay(3000);
   toSerial();

   // leggi le risposte dal server
   gprsSerial.println("AT+HTTPREAD"); 
   delay(1000);
   toSerial();

   gprsSerial.println("");
   gprsSerial.println("AT+HTTPTERM");
   toSerial();
   delay(300);

   gprsSerial.println("");
   delay(5000);
}

void toSerial()
{
  while(gprsSerial.available()!=0)
  {
    Serial.write(gprsSerial.read());
  }
}

Ci tengo a precisare che il modulo lo sto provando a banco ed il segnale iliad arriva bene.
Dal punto di vista codice cosa si potrebbe migliorare secondo voi?
Ringrazio anticipatamente per eventuali suggerimenti.

aggiornamento : quando si blocca, tolgo e rimetto l'alimentazione e per 2 ore funziona correttamente, poi sembra che entri in automatico in modalità sleep.
Qualcuno ha già riscontrato questo problema?

ecco cosa ho scoperto quando non funziona: sul serial monitor ottengo +HTTPACTION:0,601,0 anzichè +HTTPACTION:0,200,13
siccome al momento non ho ancora capito come mai dopo un tot di ore questo stato si crei automaticamente,
ho creato una funzione che sconnette e riconnette il modulo:

void connetti(void)
{
     gprsSerial.println("AT+SAPBR=0,1");
     toSerial();
     delay(2000);
     gprsSerial.println("AT+SAPBR=1,1");
     toSerial();
     delay(2000);
}

e nel void loop:

if(gprsSerial.read()!='+HTTPACTION:0,601,0'){
     connetti();
     }

al momento sembra funzionare.
Vi tengo aggiornati.
Salutii.

aggiornamento: niente da fare, dopo un paio d'ore, il modulo sim900 si blocca anche dopo la correzione postata prima.
Adesso provo a tenere il monitor seriale aperto per tutto il tempo finchè non si ripresenta il problema ma sospetto fortemente che per qualche motivo sconosciuto entri in automatico in modalità sleep e la seriale non stampa più nulla

Ciao,
premesso che non ho esperienza di SIM900 in modalità GPRS, ma incuriosito ho fatto qualche ricerca.
L’errore 601 è abbastanza generico (Network Error), quindi può voler dire tutto e niente, quindi io andrei per tentativi.

Visto che il problema potrebbe essere anche lato server:

  • che server usi? Hai provato con server noti, cioè che sicuramente non hanno problemi?
  • hai verificato lo script php lato server? Sicuro che non vada in timeout per qualche motivo?
  • dici che fai richieste circa ogni 30sec, hai provato a randomizzare il tempo tra una richiesta e l’altra? Ad alcuni server non piacciono le richieste temporizzate!

Lato Arduino:

  • c’è un particolare motivo per il baudrate a 2400? La SIM900 può tranquillamente lavorare a velocità superiori, prova a 19200 (che dovrebbe essere quella preimpostata).
  • invece di gestire l’errore, potresti effettuare la richiesta solo se la connessione è attiva, cioè testi la connessione, se attiva, fai la richiesti, altrimenti ti riconnetti.

Mi spiace non poterti aiutare concretamente, ma queste solo le prime cose che farei io.

Federico

Ciao Federico,
scusa se rispondo solo ora ma sono appena rientrato dal lavoro,
intanto ti ringrazio per aver risposto pur non avendo il modulo sim900.
Parto a farti subito chiarezza sulle domande che hai postato:
Per quanto riguarda il server, sto usando altervista e il codice funziona molto bene è stato testato più volte e come suggerivi ho provato anche a randomizzare il tempo tra una richiesta e l'altra.
Inoltre il codice lato server è stato testato anche in locale e da remoto, su un raspberry con lamp e php funzionando sempre correttamente.
Il codice tra l'altro non è neanche tanto complesso, ho una pagina chiamata server.html dove visualizzo un contatore che parte da 0 e arriva a 60 e ripete il ciclo, mentre al modulo sim900, faccio semplicemente richiamare uno script php che ogni 30 secondi, porta il contatore a 0.
Lo scopo è: se il contatore arriva a 60, vengo avvisato via email come se fosse una specie di manomissione in quanto il modulo non ha richiamato lo script portando il contatore a 0.

Per quanto riguarda arduino, già ieri sera mi era frullata anche a me per la testa l'idea che il baudrate era troppo basso a 2400 ed ho già provveduto tramite uno sketch con comandi at , a modificare il baudrate a 19200.
Ho riavviato arduino ieri alle 23 circa con la modifica al baudrate e fino ad adesso non ho ricevuto nessuna email e sulla seriale vedo che sta continuando a svolgere il suo lavoro.
Non voglio parlare troppo presto perchè ho riscontrato che a volte si blocca anche dopo 15 ore.
Vi tengo aggiornati.

Federico66:

  • invece di gestire l'errore, potresti effettuare la richiesta solo se la connessione è attiva, cioè testi la connessione, se attiva, fai la richiesti, altrimenti ti riconnetti.

Se dovesse ripresentarsi il problema, tengo in considerazione il tuo consiglio!!!

Enzo--:
Non voglio parlare troppo presto perchè ho riscontrato che a volte si blocca anche dopo 15 ore.

Incrocio le dita per te :wink:

Federico

Domanda lato server:
Se al server (in questo caso altervista) dessero fastidio tutte queste richieste, non avrebbe funzionato già dopo qualche ora o sbaglio?

Enzo--:
Domanda lato server:
Se al server dessero fastidio tutte queste richieste, non avrebbe funzionato già dopo qualche ora o sbaglio?

In realtà anche molto meno, dipende da come lo hanno configurato per bloccare gli attacchi DoS, o semplicemente le richieste "non umane" :slight_smile:

In alcuni casi, per il blocco dell'ip, bastano due richieste entro pochi sec.

Visto che va avanti da tante ore, ipotizzerei che non ci sono verifiche di questo tipo, poi sai, i sistemisti sono una strana categoria :slight_smile: (con affetto per i sistemisti) :slight_smile:

Federico

aggiornamento: aveva superato le 48 ore lavorando perfettamente e verso le 17:30 di oggi, la spia verde pwrkey si è spenta perdendo quindi il segnale.

Quindi devo adottare 2 modifiche :
la prima come suggeriva Federico66 - invece di gestire l'errore, potrei effettuare la richiesta solo se la connessione è attiva, se attiva, faccio la richiesta, altrimenti mi riconnetto.
La seconda funzione che mi è venuta in mente ma non ho capito come fare, è di controllare lo stato del pwrkey,
mi sono letto tutti i comandi AT disponibili ma non ho trovato nulla che riguarda lo stato del pwrkey.
Come potrei fare?
Ringrazio anticipatamente

Enzo--:
aggiornamento: aveva superato le 48 ore lavorando perfettamente...

Mi spiace, non avendoti sentito, pensavo bene :wink:
Non ho presente cosa sia la pwrkey, ma imho se adotti il sistema di verificare la connessione prima della richiesta, dovresti risolvere.
In questo modo dovrebbe autogestirsi.

Tienici aggiornati

Federico

>Enzo--: Hai già studiato QUESTO documento e le varie modalità di power-saving ?

Guglielmo

gpb01:
>Enzo--: Hai già studiato QUESTO documento e le varie modalità di power-saving ?

Guglielmo

Si perchè avevo un forte sospetto che entrasse in modalità sleep, e quindi tramite i comandi at, ho inviato il comando AT+CSCLK=0 ed ho ricevuto la risposta ok .
Mi sorge un piccolo dubbio:
questo comando viene memorizzato nella eprom del modem o devo inviarlo ogni qual volta che creo un nuovo sketch per utilizzare il modulo?

Enzo--:
questo comando viene memorizzato nella eprom del modem o devo inviarlo ogni qual volta che creo un nuovo sketch per utilizzare il modulo?

NO, non viene memorizzato, per memorizzare una configurazione ricordo che c'era un apposito comando AT ... ::slight_smile:

Guglielmo

Edit: Guarda "AT&W" (Store active profile)

Federico66:
Non ho presente cosa sia la pwrkey

Il pwrkey è un tasto fisico presente sul modulo che serve per registrarsi alla rete gsm.
Fortunatamente è possibile simulare la pressione via software utilizzando questo comando:

void pwrkey(void)//simula pressione pulsante powerKey sim900
{
  digitalWrite(7, HIGH); 
  delay(1500);  
  digitalWrite(7, LOW);
  delay(2500); 
}

Il problema si presenta quando cade la linea gsm e quindi non è più registrato alla rete gsm, non ho la possibilità di inviare e ricevere risposte dal modulo.
Di conseguenza al momento non saprei come creare una funzione per gestire questa cosa.

gpb01:
NO, non viene memorizzato, per memorizzare una configurazione ricordo che c'era un apposito comando AT ... ::slight_smile:

Bene allora aggiungo nel setup questo comando.
Mi rimane solo il problema che se mi cade la linea gsm, non posso più comunicare con il modulo e quindi non posso creare una funzione di riconnessione dal momento che non posso leggere lo stato del pwrkey tramite comandi at.

Ciao, sto cercando di inserire nel mio sketch la considerazione di #Federico66 ma le seriali vanno in conflitto:

// Richiamare uno script ogni 30 secondi circa, con modulo sim900!!!

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(2, 3);

boolean started=false;

void pwrkey(void)//simula pressione pulsante powerKey sim900
{
  digitalWrite(7, HIGH); 
  delay(1500);  
  digitalWrite(7, LOW);
  delay(2500); 
}

void setup()
{ 
  //pwrkey();
  Serial.begin(9600);
  Serial.println("Configigurazione SIM900...");
  delay(10000);//prima di avviare la comunicazione seriale, attendo che si connette alla linea!
  //Serial.println("il modulo è pronto!...");
  gprsSerial.flush();
  Serial.flush();
  gprsSerial.begin(19200);// the SoftSerial baud rate  
  delay(500);
  if (gprserial.begin(19200)) {
          Serial.println("connesso");
          started=true;
     }; else Serial.println("non connesso");

     if(started) {
  gprsSerial.println("AT+IPR=19200");    //set the baud of SIM900
  delay(1000);
  toSerial();
  
  gprsSerial.println("AT+CSCLK=0"); //disattiva modalità sleep
  delay(1000);
  toSerial();
  
  gprsSerial.println("AT+CREG?");// stato della rete
  delay(1000);  
  toSerial();
  
  gprsSerial.println("AT+CSQ");//stato rete
  delay(1000);
  toSerial();

 // connessione o disconnessione dal servizio GPRS
  gprsSerial.println("AT+CGATT?");
  delay(1000);
  toSerial();
  // impostiamo i parametri
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
  delay(2000);
  toSerial();

  // impostiamo il servizio apn
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"iliad\"");
  delay(2000);
  toSerial();


  gprsSerial.println("AT+SAPBR=1,1");  
  delay(2000);//2000
  toSerial();
}
else pwrkey();
}

void loop()
{ 
   // inizializzare il servizio http
   gprsSerial.println("AT+HTTPINIT");
   delay(1000); 
   toSerial();

   // settiamo i parametri della pagina da richiamare
   gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://server/attivo.php\""); 
   delay(10000);// calcolando tutti i delay impiega circa 30 secondi a richiamare la pagina
   toSerial();

   // imposta il tipo di azione http 0 = GET, 1 = POST, 2 = HEAD
   gprsSerial.println("AT+HTTPACTION=0");
   delay(1000);
   toSerial();

   // leggi le risposte dal server
   gprsSerial.println("AT+HTTPREAD"); 
   delay(1000);
   toSerial();

   gprsSerial.println("");
   gprsSerial.println("AT+HTTPTERM");
   toSerial();
   delay(300);

   gprsSerial.println("");
   delay(5000);
}


void toSerial()
{
  while(gprsSerial.available()!=0){
  Serial.write(gprsSerial.read());
  }
   
}

Enzo--:
Ciao, sto cercando di inserire nel mio sketch la considerazione di #Federico66 ma le seriali vanno in conflitto:

Ciao, ripeto, non ho esperienza di gprs, ma cercando sulla rete ho trovato una serie di soluzioni, al problema error 601, e quasi tutti consigliano di verificare la connessione prima dell'action, nel caso di riscontro negativo, consigliano di effettuare nuovamente il login. Dai un'occhiata a questi, link1, link2, link3.

Per la verifica consigliano di controllare che AT+CGATT? ritorni 1 (attached) e con AT+SAPBR=2,1 e
AT+CIFSR che effettivamente ti sia stato assegnato un ip.

Spero ti sia d'aiuto.

Federico

PS
Cosa intendi con "le seriali vanno in conflitto"?

Ciao, si ho letto i consigli sui vari forum per l’errore 601 e per come ho strutturato adesso il mio sketch, il problema sembra risolto.

Adesso sto studiando come creare la verifica se il modulo è connesso o no alla rete, ma sto riscontrando un problema :

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(2, 3);
boolean started = false;

void pwrkey(void)//simula pressione pulsante powerKey sim900
{
  digitalWrite(7, HIGH);
  delay(1500);
  digitalWrite(7, LOW);
  delay(2500);
}

void setup()
{
  Serial.begin(9600);
  Serial.println("Configigurazione SIM900");
  if (gprsSerial.available())
  {
    Serial.println("Modulo connesso");
    started = true;
  }
  else
  {
    Serial.println("modulo non connesso provo a riconnettermi....");
    pwrkey();
    delay(5000);
    started = true;
  }

  Serial.println("il modulo è pronto!...");
  gprsSerial.flush();
  Serial.flush();
  gprsSerial.begin(4800);// the SoftSerial baud rate
  delay(500);

  if (started)
  {
    gprsSerial.println("AT+IPR=4800");    //set the baud of SIM900
    delay(1000);
    toSerial();

    gprsSerial.println("AT+CSCLK=0"); //disattiva modalità sleep
    delay(1000);
    toSerial();

    gprsSerial.println("AT+CREG?");// stato della rete
    delay(1000);
    toSerial();

    gprsSerial.println("AT+CSQ");//stato rete
    delay(1000);
    toSerial();

    // connessione o disconnessione dal servizio GPRS
    gprsSerial.println("AT+CGATT?");
    delay(1000);
    toSerial();

    // impostiamo i parametri
    gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
    delay(2000);
    toSerial();

    // impostiamo il servizio apn
    gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"iliad\"");
    delay(2000);
    toSerial();

    gprsSerial.println("AT+SAPBR=1,1");
    delay(2000);//2000
    toSerial();
  }
}

void loop()
{
  gprsSerial.println("AT+HTTPINIT");   // inizializzare il servizio http
  delay(1000);
  toSerial();

  gprsSerial.println("AT+HTTPPARA=\"CID\",1");
  delay(1000);
  toSerial();

  gprsSerial.println("AT+SAPBR=0,1");  //chiudi e riapri la connessione
  delay(1000);//2000
  toSerial();

  gprsSerial.println("AT+SAPBR=1,1");
  delay(1000);//2000
  toSerial();

  // settiamo i parametri della pagina da richiamare
  gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://attivato.php\"");
  delay(10000);// calcolando tutti i delay impiega circa 30 secondi a richiamare la pagina
  toSerial();

  // imposta il tipo di azione http 0 = GET, 1 = POST, 2 = HEAD
  gprsSerial.println("AT+HTTPACTION=0");
  delay(1000);
  toSerial();

  // leggi le risposte dal server
  gprsSerial.println("AT+HTTPREAD");
  delay(1000);
  toSerial();

  gprsSerial.println("");
  gprsSerial.println("AT+HTTPTERM");
  toSerial();
  delay(300);

  gprsSerial.println("");
  delay(3000);
}

void toSerial()
{
  while (gprsSerial.available() != 0) {
    Serial.write(gprsSerial.read());
  }
}

Dichiarando lo stato della boolean started = false; all’inizio del progetto, se provo a riavviare il monitor serial ed il modulo in realtà è connesso, me lo spegne!
E poi volevo richiamare la stessa funzione di verifica anche nel void loop.