Centralina humidity temperatura suolo – lo sketch – parte III

In questa terza parte dedicata allo sketch della centralina humidity temperatura suolo analizerai le funzioni di raccolta dati, visualizzazione e salvatagglio dei log.

Centralina humidity temperatura suolo umidita sht11

Dedicherò poi un articolo finale, a conclusione del progetto per descrivere come funziona la centralina e come analizzare i dati creando grafici con Excel.

Lo sketch della centralina humidity temperatura suolo

lo sketch della centralina humidity temperatura suolo è sempre lo stesso presentato nei precedenti articoli:

In questo articolo analizzi le ultime funzioni:

  • readSensor()
  • viewSensor()
  • saveData()
  • ctrlButton()
/*
 * 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 ) { 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;
}

Funzione readSensor()

La funzione readSensor() della centralina humidity temperatura suolo è incaricata di interrogare i 3 sensori presenti sulla centralina e popolare 5 variabili che userai sia in fase di visualizzazione ( viewSensor ) sia in fase di salvataggio ( saveData )

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

linea 232: interroga il sensore DHT usando il metodo read() dell’istanza DHT e salva il valore restituito nella variabile chk;

linea 233: se il valore di chk è identico a quello della costante DHTLOB_OK definita nella libreria DHT vuol dire che la la lettura del sensore DHT della centralina humidity temperatura suolo è avvenuta con successo ed hai letto i valori di temperatura ed umiità dal sensore;

linee 234-237: scrivi sulla prima linea dell’LCD la stringa “DHT11 (Aria)” e posiziona il cursore sulla seconda linea;

linee 238-251: scrive sulla seconda riga del display un meggassio relativo all’esito della lettura del sensore DHT11;

linea 252: attendi un tempo pari a quello definito in setViewTime();

linee 254-255: assegna i valori di temperatura ed umidità alle relative variabili DHT_t e DHT_h che userai per la visualizzazione;

linee 257-258: leggi il valore di pressione dal sensore BMP085;

linea 259: assegna il valore letto dal BMP085 alla variabile BMP_p dopo aver convertito il valore float restituito dalla libreria BMP in un valore di tipo char formato da 5 cifre di cui 2 decimali;

linee 261-262: interroga il sensore SHT1x ed elabora i risultati come alla riga 259;

Funzione viewSensor()

la funzione viewSensor() della centralina humidity temperatura suolo ha il compito di visualizzare sul monitor LCD i dati raccolti dai sensori attraverso la funzione readSesor().

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

la linea 266: pulisci il display LCD e richiama la funzione readSensor();

linee 268-273: scrivi sul display LCD la prima riga “DHT11 (Aria)” e sulla seconda riga il valore di umidità in % rilevato dallo stesso DHT11;

linea 275: attendi il tempo specificato nella variabile setViewTime prima di procedere oltre;

linee 277-282: pulisci il display e scrivi sempre sulla prima riga il tipo di sensore letto e il mezzo in cui lo hai letto, in questo caso ancora Aria per distinguerlo dal Suolo che visualizzerai in seguito. Sulla seconda riga scrivi il valore di temperatura rilvata;

linea 283: identica alla linea 275;

linee 286-291: Scrivi sul display il sensore che stai leggendo “BMP085 Pressione” ed il valore rilevato per la pressione;

linea 293: identica alla 275;

linee 295-311: compie le medesime operazioni delle linee precedenti per il sensore SHT1x;

linea 312: pulisci il display LCD;

Funzione saveData()

la saveData() è la funzione che si occupa del vero e proprio salvataggio dei dati sulla scheda SD.

Scopo della centralina humidity temperatura suolo è rilevare i dati di temperatura e umidità dell’aria e del suolo e salvarli come datalog su una scheda SD da 2Gb.

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

linea 316: richiami la funzione readSensor() per aggiornare i valori dei sensori da scrivere sulla SD Card;

linee 317-319: prepari la linea da scrivere nel file di log, la sequenza di scrittura dei dati è:

dd/mm/aaa hh:mm:ss temp_aria umidità_aria pressione temp_suolo umidità_suolo

tutti i valori sono separati da spazio e questa informazione ti servirà in fase di importazione dati su excel;

linee 321-323: pulisci il display da precedenti messaggi e scrivi sulla prima linea il messaggio “Salvataggio dati”;

linee 324-329: se riesci ad aprire il dile DATI.LOG in scrittura aggiungi una nuova linea con i dati predisposti alle linee 317-319, chiudi il file e scrivi sulla seconda linea “SD Write Success”;

linee 319-333: scrivi sul display il messaggio “SD Write Error” sulla seconda riga del display;

linea 334: aspetta un secondo prima di uscire dalla funzione, questo tempo è necessario a leggere il messaggio di Success o Error verificatosi durante la scrittura su SD.

Cosa leggi sul display della centralina datalogger

Ho realizzato qualche foto durante la visualizzazione dei valori rilevati dalla centralina humidity temperatura suolo dopo il montaggio:

Centralina humidity temperatura suolo montaggio

premendo un pulsante visualizzi data ed ora con la retroilluminazione dell’LCD

Centralina humidity temperatura suolo data ed ora

premendo il pulsante DOWN iniziano a scorrere in automatico i valori rilevati dai sensori:

Centralina humidity temperatura suolo umidita aria dht11

temperatura dell’aria:

Centralina humidity temperatura suolo temperatura aria dht11

pressione atmosferica:

Centralina humidity temperatura suolo pressione bmp085

umidità del suolo o terreno in cui hai inserito la sonda SHT1x:

Centralina humidity temperatura suolo umidita sht11

temperatura del suolo attraverso la sonda SHT1x:

Centralina humidity temperatura suolo temperatura sht11

Nel prossimo articolo vedrai come organizzare i dati raccolti in Excel e come creare dei grafici.

Buona rilevazione della temperatura ed umidità con la tua centralina arduino.

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: https://www.mauroalfieri.it/elettronica/centralina-humidity-temperatura-suolo-lo-sketch-parte-iii.html

Lascia un commento

Your email address will not be published.

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