Centralina humidity temperatura suolo – lo sketch

Probabilmente hai già letto il primo articolo sulla Centralina humidity temperatura suolo è un progetto complesso che ho deciso di descrivere in più articoli per dedicare il giusto tempo ad ognuno.

centralina umidità e temperatura montata

Nella prima parte hai letto come è nata la centalina humidity temperatura suolo, quali sensori puoi utilizzare e come montarli sulla datalogger shield.

In questo articolo inizierai a comprendere lo sketch e la descrizione linea per linea per capire come modificarlo.

Lo sketch della centralina humidity temperatura suolo

/*
 * centralina humidity temperatura suolo con Arduino
 *
 * @author: Alfieri Mauro
 * Tw: @mauroalfieri
 * Web: www.mauroalfieri.it
*/

#include <Wire.h>
#include "RTClib.h"
#include <SdFat.h>
#include <dht11.h>
#include <SHT1x.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <LiquidCrystal.h>

#define CS 10
#define DHT11_PIN 15
#define SHT_dataPin  2
#define SHT_clockPin 3
#define BLAKLIGHT 16

#define BUTTON A0

int setModeTime=2000;
int setViewTime=2000;
unsigned long time=0;
unsigned long timeSet=0;

int SELECT[]  =  {720,760};
int LEFT[]    =  {480,520};
int RIGTH[]   =  {0,20};
int UP[]      =  {120,160};
int DOWN[]    =  {300,350};

RTC_DS1307 RTC;
dht11 DHT;
SHT1x sht1x(SHT_dataPin, SHT_clockPin);
LiquidCrystal lcd(8,9,4,5,6,7);
char buffer[50];
char lcdBuffer[16];

int  DHT_h;
int  DHT_t;
char BMP_p[10];
char SHT_t[10];
char SHT_h[10];

int current;

//File myFile;
SdFat sd;
SdFile myFile;
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);

void setup () {
    Serial.begin(9600);
    // Serial.print("Initializing SD card...");

    pinMode( CS,OUTPUT );
    pinMode( BUTTON,INPUT ); 
    pinMode( BLAKLIGHT,OUTPUT );

    blacklightOn();
    lcd.begin(16, 2);
    lcd.setCursor(0,0);
    lcd.print("Mandorleto v1.0");
    lcd.setCursor(0,1);
    lcd.print("mauroalfieri.it");

    delay( 3000 );

    lcd.clear();  
    lcd.setCursor(0,0);
    lcd.print("Init SD Card...");
    lcd.setCursor(0,1);

    //if (!SD.begin(CS)) {
    if (!sd.begin(CS, SPI_HALF_SPEED)) {
       sd.initErrorHalt();
      // Serial.println("initialization failed!");
      lcd.print("... Failed   ");
      while(1);
    }
    // Serial.println("initialization done.");
    lcd.print("... Ready    ");

    delay( 2000 );

    lcd.clear(); 
    Wire.begin();
    RTC.begin();
    RTC.sqw(0);		//0 Led off - 1 Freq 1Hz - 2 Freq 4096kHz - 3 Freq 8192kHz - 4 Freq 32768kHz

    lcd.setCursor(0,0);
    lcd.print("Init BMP085 ...");
    lcd.setCursor(0,1);

    delay( 200 );

    if(!bmp.begin()) {
      Serial.print("BMP085 Failed");
      lcd.print("... Failed   ");
      while(1);
    }
    lcd.print("... Ready    ");

    delay( 2000 );
    lcd.clear(); 
    blacklightOff();
}

void loop () {
    if ( ctrlButton( analogRead( BUTTON ) ) == 0 || ctrlButton( analogRead( BUTTON ) ) > 1 ) { time = millis(); }

    DateTime now = RTC.now();

    if (time > 0 && setModeTime < (millis() - time) ) { blacklightOn(); now = setMode( now ); lcd.clear(); }
    if (( now.minute() == 00 ||  now.minute() == 15 ||  now.minute() == 30 || now.minute() == 45 ) && (now.minute() != current)) { blacklightOn(); current=now.minute(); saveData( now ); lcd.clear(); }   
    if ( ctrlButton( analogRead( BUTTON ) ) > 1 ) {  blacklightOn(); viewSensor(); lcd.clear(); }

    sprintf(lcdBuffer, "%02d/%02d/%04d", now.day(), now.month(), now.year() );
    lcd.setCursor(0,0);
    lcd.print(lcdBuffer);
    sprintf(lcdBuffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second() );
    lcd.setCursor(0,1);
    lcd.print(lcdBuffer);

    delay( 1000 );
    blacklightOff();
}

void blacklightOn()  {  digitalWrite( BLAKLIGHT,HIGH ); }
void blacklightOff() {  digitalWrite( BLAKLIGHT,LOW ); }

DateTime setMode( DateTime now ) {
    boolean setModeVal = true;
    int setModeLevel = 0;

    int _day = now.day();
    int _month = now.month();
    int _year = now.year();
    int _hour = now.hour();
    int _min = now.minute();
    int _sec = now.second();

    lcd.clear();
    lcd.setCursor(0,0);
    sprintf(lcdBuffer,  "%s: %02d", "Giorno", _day);
    delay( 1000 );
    timeSet = millis();

    while ( setModeVal ) {
      //if ( ctrlButton( analogRead( BUTTON ) ) == 1 || ctrlButton( analogRead( BUTTON ) ) == 2 || ctrlButton( analogRead( BUTTON ) ) == 3 ) { timeSet = millis(); }
      if ( ctrlButton( analogRead( BUTTON ) ) >= 1 ) { timeSet = millis(); } 
      lcd.setCursor(0,0);

      // Set Day
      if ( setModeLevel == 0 ) {
        if ( ctrlButton( analogRead( BUTTON ) ) == 3 && _day < 31) { _day++; }
        if ( ctrlButton( analogRead( BUTTON ) ) == 2 && _day > 1) { _day--; }

        sprintf(buffer,  "%s: %02d", "Giorno", _day);
      }
      // Set Month
      if ( setModeLevel == 1 ) {
        if ( ctrlButton( analogRead( BUTTON ) ) == 3 && _month < 12) { _month++; }
        if ( ctrlButton( analogRead( BUTTON ) ) == 2 && _month > 1) { _month--; }

        sprintf(buffer,  "%s: %02d", "Mese", _month);
      }
      // Set Year
      if ( setModeLevel == 2 ) {
        if ( ctrlButton( analogRead( BUTTON ) ) == 3 && _year < 9999) { _year++; }
        if ( ctrlButton( analogRead( BUTTON ) ) == 2 && _year > 1900) { _year--; }

        sprintf(buffer,  "%s: %02d", "Anno", _year);
      }
      // Set Hour
      if ( setModeLevel == 3 ) {
        if ( ctrlButton( analogRead( BUTTON ) ) == 3 && _hour < 24) { _hour++; }
        if ( ctrlButton( analogRead( BUTTON ) ) == 2 && _hour > 1) { _hour--; }

        sprintf(buffer,  "%s: %02d", "Ora", _hour);
      }
      // Set Minute
      if ( setModeLevel == 4 ) {
        if ( ctrlButton( analogRead( BUTTON ) ) == 3 && _min < 60) { _min++; }
        if ( ctrlButton( analogRead( BUTTON ) ) == 2 && _min > 1) { _min--; }

        sprintf(buffer,  "%s: %02d", "Minuti", _min);
      }
      // Set Second
      if ( setModeLevel == 5 ) {
        if ( ctrlButton( analogRead( BUTTON ) ) == 3 && _sec < 60) { _sec++; }
        if ( ctrlButton( analogRead( BUTTON ) ) == 2 && _sec > 0) { _sec--; }

        sprintf(buffer,  "%s: %02d", "Secondi", _sec);
      }

      lcd.print( buffer );
      if ( ctrlButton( analogRead( BUTTON ) ) == 4 && setModeLevel > 0) { lcd.clear(); setModeLevel--;  }
      if ( ctrlButton( analogRead( BUTTON ) ) == 5 && setModeLevel < 5 ) { lcd.clear(); setModeLevel++;  }
      // if ( setModeLevel > 5 ) { setModeLevel=0; }

      if ((timeSet > 0 && (setModeTime*2) < (millis() - timeSet)) || ( ctrlButton( analogRead( BUTTON ) ) == 1) ) {
         RTC.adjust(DateTime(_year, _month, _day, _hour, _min, _sec));
         setModeVal = false;
      }
      delay(200);
    }

    return RTC.now();
}

void readSensor() {
   int chk = DHT.read(DHT11_PIN);
   if ( chk != DHTLIB_OK ) {
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print("DHT11 (Aria)");
     lcd.setCursor(0,1);
     switch (chk){
         case DHTLIB_OK:  
                 lcd.print("SUCCESS");
                 break;
         case DHTLIB_ERROR_CHECKSUM: 
                 lcd.print("Checksum error");
                 break;
         case DHTLIB_ERROR_TIMEOUT: 
                 lcd.print("Time out error");
                 break;
         default: 
                 lcd.print("Unknown error");
                 break;
      }
      delay( setViewTime );
    }
    DHT_h=DHT.humidity;
    DHT_t=DHT.temperature;
    // -----------------------------------------------------------------------
    sensors_event_t event;
    bmp.getEvent(&event);
    if (event.pressure) { dtostrf(event.pressure, 5, 2, BMP_p); }    
    // -----------------------------------------------------------------------
    dtostrf(sht1x.readHumidity(), 5, 2, SHT_h);
    dtostrf(sht1x.readTemperatureC(), 5, 2, SHT_t);
}

void viewSensor() {
  lcd.clear(); readSensor();

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("DHT11 (Aria)");
  lcd.setCursor(0,1);
  sprintf(lcdBuffer,  "%s %02d", "Humidty", DHT_h);
  lcd.print(lcdBuffer);

  delay( setViewTime );

  lcd.clear(); 
  lcd.setCursor(0,0);
  lcd.print("DHT11 (Aria)");
  lcd.setCursor(0,1);
  sprintf(lcdBuffer,  "%s %02d", "Temp.", DHT_t);
  lcd.print(lcdBuffer);

  delay( setViewTime );

  lcd.clear(); 
  lcd.setCursor(0,0);
  lcd.print("BMP085 Pressione");
  lcd.setCursor(0,1);
  sprintf(lcdBuffer,  "%s %s", "Pressione", BMP_p);
  lcd.print(lcdBuffer);

  delay( setViewTime );

  lcd.clear(); 
  lcd.setCursor(0,0);
  lcd.print("SHT (Suolo)");
  lcd.setCursor(0,1);
  sprintf(lcdBuffer,  "%s %s", "Humidity", SHT_h);
  lcd.print(lcdBuffer);

  delay( setViewTime );

  lcd.clear(); 
  lcd.setCursor(0,0);
  lcd.print("SHT (Suolo)");
  lcd.setCursor(0,1);
  sprintf(lcdBuffer,  "%s %s", "Temp.", SHT_t);
  lcd.print(lcdBuffer);

  delay( setViewTime ); 
  lcd.clear();   
}

void saveData( DateTime now ) {
    readSensor();
    sprintf(buffer,  "%02d/%02d/%d %02d:%02d:%02d %02d %02d %s %s %s", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), DHT_h, DHT_t, BMP_p, SHT_h, SHT_t );

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Salvataggio dati");
    if (myFile.open("dati.log", O_RDWR | O_CREAT | O_AT_END)) {
      myFile.println(buffer);
      myFile.close();      
      lcd.setCursor(0,1);
      lcd.print("SD Write Success");
    } else {
      sd.errorHalt("opening dati.log for write failed");       
      lcd.setCursor(0,1);
      lcd.print("SD Write Error");
    }
    delay(1000);
}

int ctrlButton( int button ) {

  if ( SELECT[0] <= button && button <= SELECT[1] ) { return 1; }
  if ( LEFT[0] <= button && button <= LEFT[1] )     { return 2; }
  if ( RIGTH[0] <= button && button <= RIGTH[1] )   { return 3; }
  if ( UP[0] <= button && button <= UP[1] )         { return 4; }
  if ( DOWN[0] <= button && button <= DOWN[1] )     { return 5; }

  return 0;
}

come vedi lo sketch non è semplicissimo, iniziamo dalle prime linee:

linee 009-016: includi tutte le librerie necessarie alla lettura dei dati dai sensori ed a scrivere sulla SD card;

linee 018-022: definisci le costanti dei pin a cui sono collegati i sensori;

linea 024: definisci la costante a cui sono collegati i pulsanti della Keypad LCD;

linee 026-027: definisci le variabili in cui imposti i tempi per la modalità di impostazioni della data e dell’ora ( setModeTime ) e il tempo di attesa della visualizzazione ( setViewTime );

linee 028-029: definisci le variabili in cui memorizzerai i valori di tempo trascorsi, vedrai nelle linee successive a cosa servono;

linee 031-035: definisci 5 array di due valori ciascuno, ogni coppia rappresenta un range, primo=valore minimo, secondo=valore massimo, da confrontare con il valore letto sul pin A0 per capire quale pulsante è stato premuto;

linee 037-040: inizializza la classe RTC, DHT, SHT1x e Lcd;

linee 041-042: definisci due buffer in cui memorizzerai messaggi da visualizzare sul display LCD o la linea da scrivere sulla SD Card;

linee 044-048: definisci le variabili di tipo integer e char in cui memorizzerai i valori letti sui 3 sensori;

linea 50: definisci una variabile di tipo integer in cui memorizzerai il valore del minuto corrente, vedrai nelle righe successive il suo utilizzo;

linee 053-055: inizializza l’oggetto sd per scrivere sulla card e l’oggetto bmp per leggere il sensore BMP085;

nella funzione setup() trovi molte parti dedicate all’inizializzazione dei pin ed alla gestione del display LCD per cui ti invito a leggere gli articoli specifici, le parti importanti per questo progetto sono:

if (!sd.begin(CS, SPI_HALF_SPEED)) {
  sd.initErrorHalt();
  // Serial.println("initialization failed!");
  lcd.print("... Failed   ");
  while(1);
}

linea 80: controlla che sia possibile inizializzare la SD card, se fallisce l’inizializzazione della SD Card esegui le istruzioni successive;

linea 81: leggi eventuali errori;

linea 83: scrivi sul display LCD della centralina humidity temperatura suolo la frase: “… Failed   “;

linea 84: inizia un ciclo infinito, in quanto 1 non permette al while di fermarsi, che non fa nulla, serve solo a fermare il programma a questa linea;

if(!bmp.begin()) {
  Serial.print("BMP085 Failed");
  lcd.print("... Failed   ");
  while(1);
}

linea 103: tenta di inizializzare la comunicazione con il sensore BMP085 della centalina humidity temperatura suolo ;

linea 104: in caso di fallimento ottenuto alla linea 103 scrive sul monitor Seriale la frase “BMP085 Failed”;

linea 105: scrivi sul display LCD la frase “… Failed    ”

linea 106: inizia un ciclo infinito come descritto alla linea 84;

blacklightOff();

linea 112: spegni la retro illuminazione del display LCD per risparmiare la batteria con cui alimenti la centralina humidity temperatura suolo;

In un prossimo articolo descriverò la funzione loop() e a seguire tutte le funzioni che sono definite nel progetto.

Buona sperimentazione !!!

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/centralina-humidity-temperatura-suolo-lo-sketch.html

8 commenti

3 ping

Vai al modulo dei commenti

    • Luca Ferrando il 30 Gennaio 2016 alle 00:11
    • Rispondi

    Buonasera Mauro, sono Luca. Hai fatto un ottimo sito che aiuta molto quelle persone che si sono avvicinate da poco ad arduino. Sto cercando di realizzare il tuo progetto della Centralina humidity temperatura suolo . Ho un piccolo problema nello sketch : mi compare questo errore quando lo verifico. Potresti aiutarmi
    Attendo una tua risposta
    Grazie

    Arduino:1.7.8 (Windows XP), Scheda:”Arduino Uno”

    centralina.ino: In function ‘void setup()’:

    centralina.ino:94:9: error: ‘class RTC_DS1307’ has no member named ‘sqw’

    Errore durante la compilazione

    1. Ciao Luca,
      puoi commentare la riga 094 in quanto la tua libreria non supporta quella funzione.
      Leggerai nel blog, cercando l’errore “class RTC_DS1307’ has no member named ‘sqw’” che è ricorrente a causa dell’uso di librerie incomplete.
      In questo progetto non serve.

        • Luca Ferrando il 3 Febbraio 2016 alle 20:53
        • Rispondi

        Ciao Mauro, grazie per il suggerimento. Ora non da piu’ errori. Ma purtroppo ho un problema nel settare l’ora e la data. Dopo l’inizializzazione dei sensori dovrei premere il pulsante select per almeno tre secondi e mi permette d’impostare data e ora. Io pur premendo il tasto non succede nulla e la data e l’ora che mi compare e molto strana (data 35/08/2095 – ora 43:01:29). i pulsanti funzionano xche li ho testati con l’apposito sketch.Mi sorge il dubbio che rtc non funzioni o che ci siano problemi con le librerie. Le schede che utilizzo sono esattamente quelle che hai usato tu. Mi potresti dare qualche dritta. Grazie nuovamente in attesa di una tua risposta.

        1. Ciao Luca,
          i problemi sono due distinti:
          1. i pulsanti mi dici che ti funzionano ma non riesci a entrare nella modalità di impostazione potrebbe dipendere dalla versione della shield originale DFRobot è stata prodotta in due versioni: v.1.0 e v.1.1 in cui i valori restituiti dai pulsanti sono differenti per cui se nel test fai i controlli per un valore errato ottieni che lo sketch non reagisce;

          2. i valori di data ed ora che sono certamente errati in quanto non mi risulta il giorno 35 e l’ora 43 in una giornata, anche se a me servirebbe sia l’una che l’altra :-), per cui ipotizzo una incompatibilità con la libreria, sei certo di aver usata quella del produttore?

            • Luca il 22 Dicembre 2018 alle 16:30

            Ciao mauro. Il programma funziona molto bene con il sensore DHT11. Volevo sostituirlo con uno piu preciso come il dht22 ma lo sketch mi da numerosi errori pur cambiando la libreria e alcunediciture da dht11 a dht22. Il sensore funziona con uno sketch di prova in seriale. Ma a me interessa visualizzare i valori e memorizzarli. Grazie x il tuo aiuto e buon natale

          1. Ciao Luca,
            tra il DHT11 ed DHT22 varia non solo la precisione ma anche la libreria ed i metodi che essa utilizza.
            Dovrai adattare lo sketch, comprendendolo grazie alla descrizione, alle tue esigenze con il DHT22.

    • domenico il 7 Agosto 2014 alle 23:40
    • Rispondi

    io ho assemblato i pin sulla scheda data logging lo schema che tu hai pubblicato, cioè quello in cui vengono rappresentati i collegamenti dei sensori sulla scheda arduino, ma che invece vanno eseguiti sulla scheda data logging
    siccome non vedo una foto di come sono stati effetuati i collegamenti, vorrei capire bene prima di procedere,. come è stata effettuata la saldature della resistenza 10 khom quindi se ho capito bene prima vengono assemblati i sensori e poi si carica lo sketch oppure il contrario? il quale tu hai riportato dopo di che dovrebbe funzionare giusto, scusami ma non sono tanto esperto ma mi piace tanto e con il saldatore ci so fare realizzo molti kit elettronici mi sto avvicinando ad arduino. ho bisogno di questo progetto per un impiego quindi ti chiedo di aiutarmi grazie.

  1. Ciao Domenico,
    non ho capito tutta la tua richiesta, provo a risponderti per quello che mi è chiaro.
    Trovi lo schema di come saldare la resistenza da 10K:
    – nel link della prima frase;
    – sul sito del venditore del sensore
    – sul sito del produttore del sensore

    Per i dubbi su arduino e su come funziona come caricare lo sketch, ecc.. ti consiglio di leggere il mio corso on-line gratuito.

  1. […] « Centalina humidity temperatura suolo – lo sketch […]

  2. […] « Centralina humidity temperatura suolo – lo sketch […]

  3. […] centralina humidity temperatura suolo – lo sketch […]

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.