Controllo Caldaia con SMS

Buonasera a tutti!
Volevo condividere un piccolo progetto che ho creato grazie all'aiuto di questo forum e di tutte le informazioni trovate in rete.
Avevo la necessità di comandare a distanza la caldaia di una seconda casa in montagna e così ho acquistato quasi per gioco una scheda Arduino Uno ed una Shield GPRS SIM900. Dopo innumerevoli prove, ed infiniti SMS, sono riuscito a creare (copiando parti di codice trovati in rete, ci tengo a precisarlo..) questo sketch che consente di accendere/spegnere la caldaia, inviare via sms la temperatura rilevata in casa ed avvisare in caso di fughe di gas e mancanza di corrente.
La batteria tampone utilizzata per l'invio dell'avviso di mancanza corrente, è una banale batteria per la ricarica d'emergenza dei cellulari dal costo di pochi euro.
Questo lo sketch:

/* -----------------------------------------------------------------------------------
 Accende e spegne un RELE a secondo dell'SMS inviato:
 ON  => Accende il RELE
 OFF => Spegne il RELE
 STATO => Comunica stato della caldaia/rele
 TEMP => Comunica la temperatura in casa
 Altro => Messaggio di errore sul Serial Monitor
 Fuga di Gas => invio sms con allarme
 Mancanza rete => invia sms con avviso (se collegata una batteria tampone su usb)
 ---------------------------------------------------------------------------------- */
#include "SIM900.h"
#include <SoftwareSerial.h> // necessaria alla libreria gsm.h richiamata in sms.h
#include "sms.h"            // Libreria per la gestione degli SMS
// temperatura con DS18B20 su pin digitale 4
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

SMSGSM sms;
int led = 13; // Il Pin 13 è quello connesso al rele
int numdata;
int rele=12;  // il Pin 12 legge il segnale di mancanza rete
int rel=0;
int sensore=2;  // sensore fughe di gas su pin digitale 2
int val=0;
int interrCount=0;

boolean started=false;
char smsbuffer[160];
char Mittente[20];
char Mittente1[20];
float tempC;
char tempB[6];
String tempA="";

void setup() 
{
  Serial.begin(9600);
  pinMode (sensore, INPUT);
  pinMode (rele, INPUT);
  //digitalWrite(rele, LOW);
  digitalWrite(sensore, HIGH);
  Serial.println("ESEMPIO INVIO/RICEZIONE SMS");
  pinMode(led, OUTPUT);   // imposta il pin 13 come pin di OUTPUT.
  digitalWrite(led, HIGH); // spegne inizialmente il led
  pinMode (sensore, INPUT);
  strcpy(Mittente1,"Mio numero");
  SIM900power();
  sensors.begin();
  // 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");
}

void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, HIGH);
  delay(2000);
  digitalWrite(9, LOW);
  delay(5000);
}

void loop() 
{
  interrCount++;                    // contatore dei cicli loop
  val=digitalRead(sensore);
  rel=digitalRead(rele);
  char inSerial[50];
  char position;
  Serial.println(interrCount);      // stampa il numero dei cicli su seral monitor
  if (started)
  {
    if ( interrCount == 30 )        // ogni 30 cicli
    {
      interrCount = 0;              // azzero il contatore
      gsm.CheckRegistration();      // controllo se la sim è connessa alla rete

      if  (gsm.IsRegistered()==0)    // se disconnessa, riavvia il modulo GSM
      {
        Serial.println("disconnesso, riavvio");    // messaggio su serial monitor

        digitalWrite(9, HIGH);
        delay(2000);
        digitalWrite(9, LOW);
        delay(5000);

        digitalWrite(9, HIGH);
        delay(2000);
        digitalWrite(9, LOW);
        delay(5000);

      }
    }

    if (rel==HIGH){              // se si diseccita il rele connesso ai 9v invia un sms
      sms.SendSMS(Mittente1, "Attenzione Manca la Corrente!"); // restituisce true se invia l'SMS
      Serial.println(" => Manca Corrente");
      delay(3600000);            // attende 1 ora prima di riprendere il loop
    }

    if(val==LOW) {              // se il sensore MQ-5 rileva una fuga di gpl, cambia stato ed invia un sms
      sms.SendSMS(Mittente1, "Attenzione fuga di GAS!"); // restituisce true se invia l'SMS
      Serial.println(" => Fuga di Gas");
      delay(1800000);            // attende 30 min prima di riprendere il loop
    }

    // 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)        // se riveve il messaggio ON via sms
      {
        digitalWrite(led, LOW);   // Accende il LED/rele impostando il voltaggio a HIGH
        Serial.println(" => Accendo la Caldaia");
      }
      else if (strcmp(smsbuffer,"OFF")==0)    // se riveve il messaggio OFF
      {
        digitalWrite(led, HIGH);    // Spengo il LED/rele impostando il voltaggio a LOW
        Serial.println(" => Spengo la caldaia");
      }
      else if (strcmp(smsbuffer,"TEMP")==0)    // se riceve il messaggio TEMP
      {

        sensors.requestTemperatures();          // legge il sensore/sonda DS18B20
        float tempC = sensors.getTempCByIndex(0)-1.5;    // sottraggo 1 grado per riscaldamento interno al contenitore
        dtostrf(tempC, 2, 2, tempB);
        Serial.print("tempB: ");
        for (int i = 0; i < sizeof(tempB); i++)
        {
          Serial.print(tempB[i]);
        }
        Serial.println();
        //convert chararray
        for (int i = 0; i < sizeof(tempB); i++)
        {
          tempA += tempB[i];
        }  
        sms.SendSMS(Mittente,  tempB); // invia sms con valore temperatura - restituisce true se invia l'SMS
        delay(5000);
      }

      else if (strcmp(smsbuffer,"STATO")==0)    // altrimenti se riceve il messaggio STATO
      {
        if (digitalRead(led)==LOW)              // se il rele è acceso (stato invertito..)
        {
          sms.SendSMS(Mittente, "STATO:  Caldaia Accesa"); // invia sms con caldaia accesa - restituisce true se invia l'SMS
          Serial.println(" => La Caldaia e' Accesa");
          delay(5000);
        }
        else                                    // altrimenti
        {
          sms.SendSMS(Mittente, "STATO:  Caldaia Spenta"); //  invia sms con caldaia spenta - restituisce true se invia l'SMS
          Serial.println(" => La Caldaia e' Spenta");
          delay(5000);
        }
      }
      else
        Serial.println(" => non riconosciuto!");
      sms.DeleteSMS(position); // Elimina l'SMS appena analizzato
    }
  }

  delay(1000);
}

In allegato lo schema.

Ora una richiesta di aiuto...
Come si nota dal programma, per leggere lo stato della caldaia, invio l'sms STATO, ed ottengo la risposta "Caldaia Accesa/Spenta" mentre per sapere la temperatura in casa invio TEMP, e ricevo i gradi. Ho tentato di accorpare le risposte, ma non ci sono mai riuscito ed infine ho installato il tutto. Se qualche buona anima mi indirizzasse, gliene sarei grato.... Ho provato ad unire le due stringhe char con i vari const char, ma alla fine ho rinunciato. Volendo poi inserire una seconda sonda per la temperatura esterna, la cosa sarebbe ancora più utile per risparmiare qualche sms.

Grazie in anticipo a tutti.
Emanuele

Se non riesci a fare il parsing della stringa ricevuta per dividere la parola TEMP dalla parola STATO prova usando una terza parola con cui spedisci entrambi i dati, ad esempio COND(izione) per sapere la caldaia, la temperatura ed eventuali allarmi. Idea stupida delle 8:50 :cold_sweat:

Se non ho capito male quello che lui chiede è unire le stringhe per mandare in un messaggio unico di max 140 caratteri tutto

da così

sms.SendSMS(Mittente, "STATO:  Caldaia Spenta")

a così

String str_ws = "STATO,"; 
  str_ws += String(temp1); str_ws += "," ; 
  str_ws += String(temp2); str_ws += "," ; 
  str_ws += String(temp3); str_ws += "," ; 
  str_ws += String(temp4); str_ws += ","; 
  str_ws += String(temp5); str_ws += "," ; 
  str_ws += String(temp6); 
 
sms.SendSMS(Mittente, str_ws)

una cosa simile

Esatto pablos, è proprio quello che intendevo....
Il problema è che sms.Send necessita di 2 stringhe char, il tuo esempio crea una string, cosa faccio converto alla fine str_ws in char?

Grazie!

Il Reference andrebbe letto e studiato, però :stuck_out_tongue:

Non mi sembra che nello schetch che hai bubblicato prima ci siano degli array di char da inviare

sms.SendSMS(Mittente1, "Attenzione fuga di GAS!");
sms.SendSMS(Mittente1, "Attenzione Manca la Corrente!"); 
sms.SendSMS(Mittente, "STATO:  Caldaia Accesa");
sms.SendSMS(Mittente, "STATO:  Caldaia Spenta");

Tutto ciò che invia SendSMS è tra " " quindi una stringa

però in un altro punto del programma vedo che invii anche

sms.SendSMS(Mittente,  tempB);

dove tempB è dichiarato come

char tempB[6];

Quindi a quanto pare sembra che li prenda entrambi, ma questo lo sai tu che usi quella libreria

ciao

No, la libreria prevede sms.SendSMS(char, char); almeno questo è quello che mi ha restituito innumerevoli volte durante le prove....
Per Leo72, ho provato anche a lavorare solo con string e poi convertirle in char, ma il risultato era lo stesso. Probabilmente l'errore è altrove.
Grazie comunque a tutti per l'interessamento, ormai il modulo è collegato (in montagna) e funzionante,
proverò la prossima primavera a fare qualche ottimizzazione. Ora il clima non lo consente....

Ciao
Emanuele