Arduino + GSM Shield comportamento strano

Ciao a tutti,
sono nuovo del mondo Arduino ma ho voluto cominciare con un progetto forse troppo ambizioso..

Ho un Arduino UNO REV3 con Shield GSM ufficiale, e, per finire una proto shield fatta da me che integra le seguenti funzioni:
Un telecomando per cancello automatico (pin 4).
3 led, verde, giallo e rosso rispettivamente collegato ai pin 13, 12 e 11.
Un sensore digitale DHT11 per temperatura e umidità, al pin 10.
Infine un relé con bobbina da 200V collegato alla rete elettrica di casa e visto da Arduino tramite il pin 9.
Un fotoresistore collegato al pin analogico 0.

Il DHT11 sul pin 10 è pilotato tramite una libreria.
Il relè praticamente è visto come un interruttore, se è presente la 220v sulla obbina sul pin non arrivano i 5v
I led servono solo per indicare all'utente cosa sta facendo Arduino, una sorta di debug visivo.
Il telecomando del cancello è integrado in modo da dare alimentazione allo stesso per aprire il cancello elettrico di casa.
Il tutto è alimentato dal jack di alimentazione nero di Arduino con alimentatore da 9v 1200mA

Faccio notare che nella documentazione della Shield GSM è raccomandato di usare dai 750 ai 1000 mA, è un problema averne 1200?

Tutte queste funzioni sono state testate perfettamente con mini progetti su breadboard.
Il progetto prevede di attivare le varie funzioni inviando SMS, avendo come risposta un SMS al proprio numero con i dati richiesti.

Ora passiamo al problema: la GSM Shield è poco affidabile!!!
L'invio di SMS al mittente è ok ma ogni tanto, anzi spesso, nella lettura dei messaggi Arduino rimane bloccato!!!

Dai test che ho fatto sembra che il software si incagli un punto preciso:

Di seguito posto la parte del programma dedicata a leggere gli SMS:

if (sms.available()) {

digitalWrite(LedRosso, HIGH);
delay(15);

sms.remoteNumber(senderNumber, 20);
//Serial.println("SMS ricevuto da:");
//Serial.println(senderNumber);

if (sms.peek() == '#') {
sms.flush();
}
// legge SMS

while (c = sms.read()) {
message += c;
}
//Serial.println(message);

// cancella SMS ricevuto
sms.flush();
Serial.println("SMS Cancellato");
delay(2000);
digitalWrite(LedRosso, LOW);

}

Il punto dove si incaglia spesso sembra essere è questo:
while (c = sms.read())
message += c;

Ogni tanto si riavvia Arduino quindi credo che ci sia un problema di alimentazione non corretta.

Qualche consiglio? Grazie

Faccio notare che nella documentazione della Shield GSM è raccomandato di usare dai 750 ai 1000 mA, è un problema averne 1200?

:fearful: :fearful:
Ti rispondo che potresti avere milioni di Ampere ma se il voltaggio è corretto mal che vada c'è un ripple minore e questo ti fa solo bene, comunque no non è un problema anzi.
per quanto riguarda i 9 volt e l'ampere di assorbimento da parte del povero regolatore di tensione non penso faccia troppo bene al regolatore a lungo andare...magari se lo shield funziona a 5 volt usa un buon alimentatore a 5 volt fidati :wink:

  1. pubblica il codice usando i tag CODE, non fare dall'IDE "copia per il forum" che non va bene
  2. che tipo di dato è "message"? Non si potrebbe vedere tutto lo sketch?

Ecco il mio codice completo, ci sono delle stringhe che per privacy :smiley: ho sostituito, numcellulare, numcellularemoglie e numArduino rispettivamente con il mio cellulare, quello della moglie e il numero della SIM contenuta nella GSM shield.

In realtà per fare dei test senza consumare SMS dalla mia scheda in questa versione è presente un pulsante sul pin 8 che se premuto Arduino manda un SMS a se stesso (la SIM di Arduino ha gli SMS infiniti $) $) $)!!!) con il comando “Apri cancello” .

Altra cosa che ho dimenticato nel post precedente… ma ha cosa serve il pin 7 riservato alla shield GSM???

// Ardu-Does V1.1

//27/02/2014 13.23

// include la libreria GSM
#include <GSM.h>
//include libreria Temperatura e e umidità
#include <dht11.h>
dht11 DHT;

//definisci pin analogici usati
#define LucePin 0
// definisci pin digitali usati
//#define Pin 0 riservato trasmissione Rx
//#define Pin 1 riservato trasmissione Tx
//#define Pin 2 riservato comunicazione GSM SHIELD
//#define Pin 3 riservato comunicazione GSM SHIELD
#define CancelloPin 4
//#define Rele1Pin 5
//#define Rele2Pin 6
//#define Rele3Pin 7 //riservato GSM SHIELD
//#define Rele4Pin 8
#define RetePin 9
#define DHT11_PIN 10
#define LedRosso 11
#define LedGiallo 12
#define LedVerde 13

#define Test1Pin 8


// istanza libreria
GSM gsmAccess;
GSM_SMS sms;

// array numero chiamate
char remoteNumber[20];
char checkNumber1[20] = numcellulare;
char checkNumber2[20] = numcellularemoglie;

// messaggio sms
String message = "";
boolean flgGSM = false;
boolean flgSTS = false;
boolean flgCMD = false;
byte memRete = LOW;
byte memLuce = 0;
byte memTemp = 0;
byte memUmid = 0;

// stringhe conteneti ricpettivamente il comando e la periferica inviata
String commandID, deviceID;

void setup()
{
  // settaggio pin di uscita periferiche
  pinMode(CancelloPin, OUTPUT);
  pinMode(LucePin, INPUT);
  pinMode(RetePin, INPUT);
  //pinMode(Rele1Pin, OUTPUT);
  //pinMode(Rele2Pin, OUTPUT);
  //pinMode(Rele3Pin, OUTPUT);
  //pinMode(Rele4Pin, OUTPUT);
  pinMode(LedRosso, OUTPUT);
  pinMode(LedGiallo, OUTPUT);
  pinMode(LedVerde, OUTPUT);
  
  pinMode(Test1Pin, INPUT);


  digitalWrite(LedRosso, HIGH);
  digitalWrite(LedGiallo, HIGH);
  digitalWrite(LedVerde, HIGH);

  // attiva comunicazione
  Serial.begin(9600);

  // Stato connessione
  boolean notConnected = true;
  Serial.println("Verifica GSM in corso...");
  // Avvio connessione GSM
  while (notConnected)
  {
    if (gsmAccess.begin() == GSM_READY)
      notConnected = false;
    else
    {
      digitalWrite(LedGiallo, LOW);
      delay(500);
      digitalWrite(LedGiallo, HIGH);
      delay(500);
    }
  }

  Serial.println("GSM inizializzato");

  digitalWrite(LedRosso, LOW);
  digitalWrite(LedGiallo, LOW);
  digitalWrite(LedVerde, LOW);
  delay(500);
}

void loop()
{
  char c;

  //imposto il numero di risposta al default1
  for (byte i = 0; i < 21; i++) {
    remoteNumber[i] = checkNumber1[i];
  }

  //Lettura sensori
  memLuce = map(analogRead(LucePin), 0, 1023, 0, 100);
  TempUmd();
  
  if (sms.available())
  {
    digitalWrite(LedRosso,HIGH);

    Serial.println("Message received from:");

    // Get remote number
    sms.remoteNumber(remoteNumber, 20);
    Serial.println(remoteNumber);

    // This is just an example of message disposal    
    // Messages starting with # should be discarded
    if(sms.peek()=='#')
    {
      Serial.println("Discarded SMS");
      sms.flush();
    }

    // Read message bytes and print them
    while(c=sms.read())
      message += c;

    Serial.println("\nEND OF MESSAGE");

    // delete message from modem memory
    sms.flush();
    Serial.println("MESSAGE DELETED");
    digitalWrite(LedRosso, LOW);
  }

  delay(1000); 
  
  //Se il mittente è lo stesso arduino lo cambia nel default1
  if (String(remoteNumber) == numArduino) {
    for (byte i = 0; i < 21; i++) {
      remoteNumber[i] = checkNumber1[i];
    }
  }
  //Controlla se il mittente è uno dei due numeri autorizzati
  if ((String(remoteNumber) != String(checkNumber1)) && (String(remoteNumber) != String(checkNumber2))) {
    digitalWrite(LedRosso, HIGH);
    digitalWrite(LedGiallo, HIGH);

    sendSMS(checkNumber1, "Numero sconosciuto: " + String(remoteNumber));
    message = "";

    digitalWrite(LedRosso, LOW);
    digitalWrite(LedGiallo, LOW);
    delay(500);
  }

  // se c'è un nuovo sms
  if (message != "") {

    digitalWrite(LedGiallo, HIGH);

    // trasformo i caratteri del messaggio in minuscolo
    message.toLowerCase();

    byte i = 0;

    // definisco il comando e la periferica
    // le due stringhe sono separate da uno spazio
    while (message.charAt(i) != ' ') i++;
    
    commandID = message.substring(0, i);
    deviceID = message.substring(i + 1, message.length());
    
    //Serial.println(deviceID);
    //Serial.println(commandID);
    flgCMD = false;
  
    // verifica periferica
    if (deviceID == "gsm") {
      if (commandID == "invia") {
        flgCMD = true;
        flgGSM = false;
      }
    }
    if (deviceID == "parametri") {
      if (commandID == "invia") {
        flgCMD = true;
        flgSTS = false;
      }
    }
    if (deviceID == "rete") {
      if (commandID == "invia") {
        flgCMD = true;
        if (memRete == HIGH) {
          sendSMS(remoteNumber, "Rete 220: Assente");
        } else  {
          sendSMS(remoteNumber, "Rete 220: OK");
        }
      }
    }
    if (deviceID == "cancello") {
      if (commandID == "apri") {
        flgCMD = true;
        digitalWrite(CancelloPin, HIGH);
        delay(1000);
        digitalWrite(CancelloPin, LOW);
        sendSMS(remoteNumber, deviceID + " in apertura...");
      }
    }
    //if (deviceID == "video") {
    //  if (commandID == "accendi") {
    //    flgCMD = true;
    //    digitalWrite(Rele1Pin, LOW);
    //    sendFeedbackSMS(remoteNumber, deviceID + " ON");
    //  }
    //  if (commandID == "spegni") {
    //    flgCMD = true;
    //    digitalWrite(Rele1Pin, HIGH);
    //    sendFeedbackSMS(remoteNumber, deviceID + " OFF");
    //  }
    //}

    //se il comando non è riconosciuto risponde con un errore
    if (flgCMD == false) {
      sendSMS(remoteNumber, "'" + commandID + " " + deviceID + "' non valido!");
    }

    // pulizia sms appena elaborato
    message = "";

    delay(200);
    digitalWrite(LedGiallo, LOW);
    delay(200);
    digitalWrite(LedGiallo, HIGH);
    delay(3000);
    digitalWrite(LedGiallo, LOW);
    delay(200);
  }

  //invio stato GSM
  if (flgGSM == false) {
    flgGSM = true;
    sendSMS(remoteNumber, "Rete GSM OK");
  }

  //invio parametri sensori
  if ((abs(memTemp - DHT.temperature) > 1) || (abs(map(analogRead(LucePin), 0, 1023, 0, 100) - memLuce) > 25) || (flgSTS == false)) {
    flgSTS = true;
    memTemp = DHT.temperature;
    memUmid = DHT.humidity;
    memLuce = map(analogRead(LucePin), 0, 1023, 0, 100);
    delay(15);
    sendSMS(remoteNumber, "Temp.: " + String(memTemp) + " c Umid.: " + String(memUmid) + " % Luce: " + String(memLuce) + " %");
  }

  //invio stato rete elettrica
  if (digitalRead(RetePin) != memRete) {
    memRete = digitalRead(RetePin);
    if (memRete == HIGH) {
      sendSMS(remoteNumber, "Rete 220 Assente");
    } else  {
      sendSMS(remoteNumber, "Rete 220 Attiva");
    }
  }

  if (digitalRead(Test1Pin)== HIGH) {
    sendSMS(numArduino, "Apri cancello");
  }

  digitalWrite(LedVerde, HIGH);
  delay(200);
  digitalWrite(LedVerde, LOW);
  delay(200);
}

// questa funzione invia un sms
void sendSMS(char remoteNum[], String txtMsg) {
  Serial.print(remoteNum);
  Serial.println(" " + txtMsg);
  digitalWrite(LedVerde, HIGH);
  delay(200);
  
  sms.beginSMS(remoteNum);
  sms.print(txtMsg);
  sms.endSMS();

  delay(3000);
  digitalWrite(LedVerde, LOW);

}

// questa funzione legge i valori del sensore DHT11
void TempUmd() {
  int chk;
  chk = DHT.read(DHT11_PIN);    // READ DATA
  switch (chk) {
    case DHTLIB_OK:
      break;
    case DHTLIB_ERROR_CHECKSUM:
      //erial.print("Checksum error,\t");
      break;
    case DHTLIB_ERROR_TIMEOUT:
      //erial.print("Time out error,\t");
      break;
    default:
      //erial.print("Unknown error,\t");
      break;
  }
}

Come pensavo, "message" è di tipo String.
String è un oggetto che consuma un sacco di RAM, soprattutto se lo distruggi e ricrei molte volte a runtime come può accadere appunto quando si va a fare l'aggiunta di caratteri con il metodo "+".
Quando hai una stringa "a" e ci aggiungi "b", l'oggetto String distrugge il primo oggetto e ne ricrea uno nuovo lungo 1 carattere in più, dove aggiunge appunto il nuovo carattere. Con stringhe piccole non succede nulla ma se hai stringhe lunghe e fai l'operazione un sacco di volte, può capitare che tu esaurisca la RAM e quindi un overflow può mandare in crash la CPU, che causa il reset del microcontrollore.

A questo aggiungici che stai usando molte stringhe stampate sulla seriale, che causano un ulteriore consumo di RAM. Intanto metti tutte le Serial.print("...") nella forma Serial.print(F(".....")). Usa cioè la funzione F() per risparmiare RAM (mette le stringhe in Flash). Poi prova anche a dimensionare message all'inzio con una dimensione fissa che sia più grande del massimo quantitativo di caratteri che potrà mai contenere, in modo che il compilatore riservi già un quantitativo di RAM capace di accogliere tutte le future modifiche.

In realtà usando l'IDE 1.5.6-r2, che quando compili oltre al consumo in byte dell'occupazione del codice ti fornisce anche i byte utilizzati dalle variabili globali create, mi aveva segnalato che stavo esagerando con il consumo di memoria.

Avevo allora fatto un giro su internet per ottimizzare il consumo di codice e variabili e ho letto della funzione F() che elimina un passaggio da un tipo di memoria all'altra quando viene creata la variabile risparmiando un mare di memoria...

Comunque me li aspettavo questi tipi errori da parte mia, sono un programmatore in ambiente windows per i linguaggi che vanno da java, asp, php... a VB6, vb net, ABAP SAP... e fino ad ora non mi sono mai preoccupato (tranne in rari casi) del consumo di RAM del pc...

Una cosa: sappiamo che la funzione LOOP viene avviato a ciclo continuo da Arduino, se la variabile String message allora la dichiaro all'interno di questa funzione Arduino non dovrebbe distruggerla ogni volta ma liberare memoria?

andrea76:
Una cosa: sappiamo che la funzione LOOP viene avviato a ciclo continuo da Arduino, se la variabile String message allora la dichiaro all'interno di questa funzione Arduino non dovrebbe distruggerla ogni volta ma liberare memoria?

Dimentichi DOVE ti trovi ... non sei su un PC dove c'è un sistema operativo ... sei su una MCU dove l'unica cosa che gira è il tuo programma e ... NON c'è alcun "garbage-collector".

L'indicazione di memoria che ti da l'IDE è, in questo caso del tutto inutile ...
... la classe String alloca memoria dinamicamente con la malloc() e, ogni volta che cambi lunghezza alla String fa una dealloc() (o una realloc()) e rialloca la memoria necessaria. Ovviamente, piano piano, la cosa crea frammentazione e ... alla fine non c'è più memoria allocabile con conseguente blocco/malfunzionamento del programma.

Guglielmo

E se usassi un array di caratteri (char message) invece di un oggetto string???

Logicamente cambierei anche il loop creato dal while che aggiunge caratteri a message... (Dio come vorrei essere a casa invece che in ufficio a provare direttamente!!! :frowning: :frowning: :frowning: :frowning: )

byte i;
char message;
i=0;
while(c=sms.read()) {
i += 1;
message = c;
}

Io uso ESCLUSIVAMENTE stringhe di char ... solo che non puoi fare come hai scritto ... ma devi gestire un indice e lavorare elemento per elemento ... secondo la sintassi del C ... non del C++ o di altri linguaggi ... XD

char message[_massimo_numero_caratteri_più_uno_];
.......
message[i] = c;

e ricorda che le stringhe di char vanno terminate con 0x00 che è appunto il carattere che identifica il fine stringa (... per questo nella lunghezza da predisporre ti ho messo il massimo + 1 carattere ... il terminatore).

Guglielmo

Hai ragione con la fretta di inviare il posti me so scordato l’indice su message:

byte i;
char message[20];
i=0;
while(c=sms.read()) {
   i += 1;
   message[i] = c;
}

Ho messo 20, in realtà i messaggi che arriveranno ad Arduino saranno sempre molto piccoli max 2 parole come hai visto nel codice… Ma se per caso arrivasse un messaggio più lungo… posso troncarlo così:

byte i;
char message[20];
i=0;
while(c=sms.read()) {
   i += 1;
   if (i<21) {
      message[i] = c;
   }
}

Veramente il tuo secondo esempio, che, per inciso, è quello più corretto, controlla solo che NON usi più di 20 char :wink:

Non è importante la lunghezza dell’array che dichiari (purché sia sufficiente per il messaggio più lungo + 1 carattere), ma è importante che, alla fine dei caratteri ricevuti, in posizione quindi i+1, aggiungi un carattere di valore 0x00 che, nel C, indica la fine di una stringa.

Tutte le funzioni che operano su stringhe di char, sanno che quando incontrano 0x00 la stringa è finita … :wink:

Guglielmo

:astonished: :astonished: :astonished: :astonished:
quindi anche il metodo sms.read avrà come ultima lettura un char c =0x00 ???

Che ne dici di questo?

byte i;
char message[20];
i=0;
while(c=sms.read()) {
   i += 1;
   if (i<20) {
      message[i] = c;
   }
}
if (i>20) {
   message[20] = 0x00;
} else {
   message[i] = 0x00;
}

Non è detto che restituisca un carattere terminatore. Sono dati che viaggiano in seriale, arrivano un byte alla volta. Potrebbero arrivare senza terminatore, a quel punto sei tu che devi mettere lo \0 finale.

Allora, in realtà c’è ancora un errore …
… prima di chiamare il metodo read() devi verificare se ci sono caratteri disponibili con il metodo available() perché altrimenti, la read() ti restituisce una bella raffica di -1 :grin:

In pratica :

i = 0;
while (sms.available()) {
   c = sms.read();
   if  (i < 20)  message[i] = c;
   i++;
}

e ricorda che l’indice degli array parte da 0 quindi il primo che devi usare è l’elemento 0 e poi incrementare di 1 (… come vedi ho usato l’operatore di auto incremento).

Guglielmo

Ah ... se dovesse uscire dal while troppo presto (il ciclo potrebbe girare più veloce della disponibilità dei char :grin:) ... aggiungi un delay(10); alla fine del ciclo ... :wink:

Guglielmo

P.S. : Per me, quando leggo dati dalla seriale velocemente ... è quasi d'obbligo :wink:

Dalla dispensa ufficiale Arduino sulla libreria GSM
“available()
Description
Checks to see if there is a SMS messages on the SIM card to be read, and reports back the number of characters in the message.”

Sembra che tale metodo ritorni il numero di caratteri ancora da leggere nel messaggio!!!

byte nc=0;
nc= sms.available();

Giusto?

:relaxed:
Riflettendo è quello che in relatà già si fa con
while (sms.available())

Sarebbe, secondo voi, meglio leggere all’inizio il valore del numero di caratteri dell’SMS e riportarlo nella dichiarazione di message? Così:

i = 0;
byte nc=0;
nc= sms.available();
char message[nc];
while (sms.available()) {
   c = sms.read();
   if  (i < nc)  message[i] = c; //in realtà non so quanto abbia senso questa riga...
   i++;
   delay(10);
}

Riflessione :roll_eyes:
guardando al futuro (quindi a cosa faccio dopo con l’oggetto string message che ora è diventato char), di seguito uso i metodi
toLowerCase per riportare l’SMS tutto in minuscolo per il confronto di stringhe successivo
charAtper identificare ogni singolo carattere ricercando uno spazio che mi serve per dividere le due parole
substring per dividere le parole separate da uno spazio

Come sostituisco questi metodi su un oggetto char??? =(

Mah … se a priori sai quanto è la lunghezza massima del messaggio … alloca la variabile e non ci pensi più … ed è anche più veloce !

Relativeamnet alle funzioni che ti occorrono …
… ti viene in aiuto al AVR libc che è sempre disponibile (non devi includere nulla, il compilatore la conosce :wink: ) ed in particolare, guarda le funzioni che hai in <string.h> … ce ne è per tutti i gusti :wink:

Guglielmo

P.S.: Lo dico sempre quando segnalo la <string.h> … a suo tempo, pensando che fossero funzioni lente e pesanti, ho cercarto di riscrivermi io quelle che mi servivano con delle FOR e dei pointers … ma sbagliavo … AVR libc è altamente ottimizzata e sia l’occupazione che le performances sono migliori XD

Caro Guglielmo, grazie per le tue dritte...
finalmente a casa ho provato le tue soluzioni e sembrano funzionare...

Ora ho visionato anche le funzioni su String.h e ne ho trovata una che forse fa al caso mio

strcasestr

Il problema è che non ho capito come funziona!!! =( =( =( =( =(

   Serial.println(strcasestr(message,"apri cancello"));
    if (strcasestr(message,"apri cancello")==0) {
      flgCMD = true;
      digitalWrite(CancelloPin, HIGH);
      delay(1000);
      digitalWrite(CancelloPin, LOW);
      sendSMS(remoteNumber, "Cancello in apertura...");
    }

Usando il codice sopra per verificare l'uguaglianza dell'array message con la stringa "apri cancello" non ritorna vero (ne ==0 come nell'esempio) e quindi il codice all'interno dell'if non si esegue
Se provo a visualizzare nel monitor l'espressione mi ritorna "apri cancello" :astonished: :~
In realtà in rete ho trovato un'altra soluzione, ma ho paura di ricadere nel solito errore di memoria e poi non tiene conto dei caratteri minuscoli/maiuscoli (nota la A in "Apri cancello"!!!)

if (String(message)=="Apri cancello")

Mi puoi delucidare su strcasestr? L'inglese lo mastico ma nella guida che mi hai passato non ho proprio capito cosa vogliano intendere!

Allora …
prima di tutto prendi il tuo messaggio e trasformalo tutto in minuscolo … lo fai carattere a carattere …

for (i=0; i < strlen(message); i++) message[i] = tolower(message[i]);

… la funzione tolower() fa parte di <ctype.h>

E poi per fare la comparazione usa la strcmp() che è molto più semplice …

if (strcmp(message, "apri cancello") == 0) { ............ }

Guglielmo

P.S. : Do per scontato che “message” sia correttamente terminato da 0x00 … altrimenti non va nulla :grin:

Grazie Guglielmo ho finalmente risolto tutto (ieri sera fino a mezzanotte e mezza! :sweat_smile:).

Riposto il codice ottimizzato per conoscenza, ci sono tre etichette coperte da privacy ("+39numerocellulare", “+39numerocellularemoglie”, “+39numeroArduino”):

// Ardu-Does V1.1
//Codice by Andrea76

//28/02/2014 09.09
//Dimensione del file binario dello sketch: 21.312 bytes (su un massimo di 32.256 bytes)

// include la libreria GSM
#include <GSM.h>
//include libreria Temperatura e e umidità
#include <dht11.h>
dht11 DHT;

//definisci pin analogici usati
#define LucePin 0
//definisci pin digitali usati
//#define Pin 0 riservato trasmissione Rx
//#define Pin 1 riservato trasmissione Tx
//#define Pin 2 riservato comunicazione GSM SHIELD
//#define Pin 3 riservato comunicazione GSM SHIELD
#define CancelloPin 4
#define Rele1Pin 5
#define Rele2Pin 6
//#define Pin 7 // riservato GSM SHIELD
//#define Rele3Pin 8
#define RetePin 9
#define DHT11_PIN 10
#define LedRosso 11
#define LedGiallo 12
#define LedVerde 13

// istanza libreria
GSM gsmAccess;
GSM_SMS sms;

// array numero chiamate
char remoteNumber[20];
char checkNumber1[20] = "+39numerocellulare";
char checkNumber2[20] = "+39numerocellularemoglie"; // e si... anche le pretende di usare arduino  :astonished:

// Gestione sensori
boolean flgSTS = false;
boolean flgGSM = false;
boolean flgCMD = false;
byte memRete = LOW;
byte memLuce = 0;
byte memTemp = 0;
byte memUmid = 0;

char message[20];

void setup()
{
  // settaggio pin di uscita periferiche
  pinMode(CancelloPin, OUTPUT);
  pinMode(LucePin, INPUT);
  pinMode(RetePin, INPUT);
  pinMode(Rele1Pin, OUTPUT);
  pinMode(Rele2Pin, OUTPUT);
  //pinMode(Rele3Pin, OUTPUT);
  //pinMode(Rele4Pin, OUTPUT);
  pinMode(LedRosso, OUTPUT);
  pinMode(LedGiallo, OUTPUT);
  pinMode(LedVerde, OUTPUT);

  digitalWrite(LedRosso, HIGH);
  digitalWrite(LedGiallo, HIGH);
  digitalWrite(LedVerde, HIGH);

  // attiva comunicazione
  Serial.begin(9600);

  // Stato connessione
  boolean notConnected = true;
  Serial.println(F("Verifica GSM in corso..."));
  // Avvio connessione GSM
  while (notConnected)
  {
    if (gsmAccess.begin() == GSM_READY)
      notConnected = false;
    else
    {
      digitalWrite(LedGiallo, LOW);
      delay(500);
      digitalWrite(LedGiallo, HIGH);
      delay(500);
    }
  }

  Serial.println(F("GSM inizializzato"));

  digitalWrite(LedRosso, LOW);
  digitalWrite(LedGiallo, LOW);
  digitalWrite(LedVerde, LOW);
  delay(500);
}

void loop()
{
  byte i=0;
  char c;
  message[1]=-127;

  //imposto il numero di risposta al default1
  for (i = 0; i < 21; i++) remoteNumber[i] = checkNumber1[i];

  //Lettura sensori
  TempUmd();

  if (sms.available())
  {
    digitalWrite(LedRosso,HIGH);

    Serial.println(F("Message received from:"));

    // Get remote number
    sms.remoteNumber(remoteNumber, 20);
    Serial.println(remoteNumber);

    // This is just an example of message disposal    
    // Messages starting with # should be discarded
    if(sms.peek()=='#') {
      Serial.println(F("SMS Scartato"));
      sms.flush();
    }

    // Read message bytes and print them
    i=0;
    while (c=sms.read()) {
      if (i<21) message[i] = c;
      i++;
      delay(10);
    }
    message[i]=0x00; //byte  di conclusione stringa array
    Serial.println(message);

    // delete message from modem memory
    sms.flush();
    Serial.println(F("SMS Cancellato"));
    digitalWrite(LedRosso, LOW);
  }

  delay(500); 

  //Se il mittente è lo stesso arduino lo cambia nel default1
  if (String(remoteNumber) == "+39numeroArduino") {
    for (i = 0; i < 21; i++) remoteNumber[i] = checkNumber1[i];
  }

  //Controlla se il mittente è uno dei due numeri autorizzati
  if ((String(remoteNumber) != String(checkNumber1)) && (String(remoteNumber) != String(checkNumber2))) {
    digitalWrite(LedRosso, HIGH);
    digitalWrite(LedGiallo, HIGH);

    sendSMS(checkNumber1, "Numero sconosciuto: " + String(remoteNumber));

    message[1] = -127;

    digitalWrite(LedRosso, LOW);
    digitalWrite(LedGiallo, LOW);
    delay(500);
  }

  // se c'è un nuovo sms
  if (message[1] != -127) {

    digitalWrite(LedGiallo, HIGH);

    //trasformo tutto l'SMS ricevuto in minuscolo
    for (i=0; i < strlen(message); i++) message[i] = tolower(message[i]);

    flgCMD = false;

    // verifica periferica
    if (strcmp(message, "invia gsm") == 0) {
      flgCMD = true;
      flgGSM = false;
    }
    if (strcmp(message, "invia parametri") == 0) {
      flgCMD = true;
      flgSTS = false;
    }
    if (strcmp(message, "invia rete") == 0) {
      flgCMD = true;
      if (memRete == HIGH) {
        sendSMS(remoteNumber, "Rete 220: Assente");
      } 
      else  {
        sendSMS(remoteNumber, "Rete 220: OK");
      }
    }
    if (strcmp(message, "apri cancello") == 0) {
      flgCMD = true;
      digitalWrite(CancelloPin, HIGH);
      delay(1000);
      digitalWrite(CancelloPin, LOW);
      sendSMS(remoteNumber, "Cancello in apertura...");
    }
    if (strcmp(message, "accendi 1") == 0) {
      flgCMD = true;
      digitalWrite(Rele1Pin, LOW);
      sendSMS(remoteNumber, "Rele' 1 ON");
    }
    if (strcmp(message, "spegni 1") == 0) {
      flgCMD = true;
      digitalWrite(Rele1Pin, HIGH);
      sendSMS(remoteNumber, "Rele' 1 OFF");
    }
    if (strcmp(message, "accendi 2") == 0) {
      flgCMD = true;
      digitalWrite(Rele2Pin, LOW);
      sendSMS(remoteNumber, "Rele' 2 ON");
    }
    if (strcmp(message, "spegni 2") == 0) {
      flgCMD = true;
      digitalWrite(Rele2Pin, HIGH);
      sendSMS(remoteNumber, "Rele' 2 OFF");
    }

    //se il comando non è riconosciuto risponde con un errore
    if (flgCMD == false) {
      //Serial.println("Comando non valido!");
      sendSMS(remoteNumber, "'" + String(message) + "' non valido!");
    }

    // pulizia sms appena elaborato
    message[1] = -127;

    delay(200);
    digitalWrite(LedGiallo, LOW);
  }

  //invio stato GSM
  if (flgGSM == false) {
    flgGSM = true;
    sendSMS(remoteNumber, "Rete GSM OK");
  }

  //invio parametri sensori
  if ((abs(memTemp - DHT.temperature) > 1) || (abs(map(analogRead(LucePin), 0, 1023, 0, 100) - memLuce) > 25) || (flgSTS == false)) {
    flgSTS = true;
    memTemp = DHT.temperature;
    memUmid = DHT.humidity;
    memLuce = map(analogRead(LucePin), 0, 1023, 0, 100);
    delay(15);
    sendSMS(remoteNumber, "Temp.: " + String(memTemp) + " c Umid.: " + String(memUmid) + " % Luce: " + String(memLuce) + " %");
  }

  //invio stato rete elettrica
  if (digitalRead(RetePin) != memRete) {
    memRete = digitalRead(RetePin);
    if (memRete == HIGH) {
      sendSMS(remoteNumber, "Rete 220 Assente");
    } 
    else  {
      sendSMS(remoteNumber, "Rete 220 Attiva");
    }
  }

  //area test per i 4 pulsanti collegati in alalogico tramite resistenze varie
  int keyVal = analogRead(A5);
  if(keyVal >= 1000 && keyVal <= 1023){
    sendSMS("+39numeroArduino", "Invia gsm");
  }
  else if(keyVal >= 900 && keyVal <= 999){
    sendSMS("+39numeroArduino", "Apri cancello");
  }
  else if(keyVal >= 500 && keyVal <= 600){
    sendSMS("+39numeroArduino", "Accendi 1");
  }
  else if(keyVal >= 41 && keyVal <= 50){
    sendSMS("+39numeroArduino", "Spegni 1");
  }

  digitalWrite(LedVerde, HIGH);
  delay(200);
  digitalWrite(LedVerde, LOW);
  delay(200);
}

// questa funzione invia un sms
void sendSMS(char remoteNum[], String txtMsg) {
  digitalWrite(LedGiallo, LOW);
  Serial.print(F("Invio SMS "));
  Serial.print(remoteNum);
  Serial.println(" " + txtMsg);
  digitalWrite(LedVerde, HIGH);

  sms.beginSMS(remoteNum);
  sms.print(txtMsg);
  sms.endSMS();

  delay(200);
  digitalWrite(LedVerde, LOW);

}

// questa funzione legge i valori del sensore DHT11
void TempUmd() {
  int chk;
  chk = DHT.read(DHT11_PIN);    // READ DATA
  switch (chk) {
  case DHTLIB_OK:
    break;
  case DHTLIB_ERROR_CHECKSUM:
    //erial.print("Checksum error,\t");
    break;
  case DHTLIB_ERROR_TIMEOUT:
    //erial.print("Time out error,\t");
    break;
  default:
    //erial.print("Unknown error,\t");
    break;
  }
}

Grazie ancora della tua collaborazione… :slight_smile: :slight_smile: :slight_smile: