Centralina humidity temperatura suolo – lo sketch – parte II

Questo articolo segue il precedente articolo in cui hai iniziato l’analisi dello sketch Centralina humidity temperatura suolo – lo sketch.

Centralina humidity temperatura suolo pressione bmp085

In questo articolo analizzi la funzione loop() che a sua volta andrà a chiamare le altre funzioni necessarie al corretto funzionamento della tua centralina humidity temperatura suolo.

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 ) { 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 sai la prima parte dello sketch puoi leggerlo nell’articolo di introduzione allo sketch, oggi analizzerai le funzioni loop(), blacklightOn(), blacklightOff(), setMode() lasciando per un prossimo articolo le funzioni di raccolta dati e salvataggio su SD Card.

Inizia dalla loop() alla linea 115: definisci la funzione loop();

linee 116-117: controlla la pressione dei pulsanti richiamando la funzione ctrlButton(), già utilizzata in precednti articoli dedicati alla key pad LCD il cui valore di ritorno è un numero da 0 ( nessun pulsante premuto ) a 5 ( pressione del pulsante DOWN ). In queste righe verifichi che il pulsante premuto sia diverso da 1 e in tal caso assegni il tempo corrente al alla variabile time.

linea 119: imposta la data e l’ora nell’istanza now di tipo DateTime;

linee 121-122: trascorso un tempo superiore a quello che hai impostato nella variabile setModeTime accendi il display richiamando la funzione blacklightOn() e richiama la funzione setMode() il cui scopo è consentirti di impostare data ed ora corrente senza collegare Arduino al Pc. Il risultato dell’impostazione di data ed ora viene riassegnato all’istanza now e procedi a pulire il display LCD;

linee 123-125: controlla il trascorrere dei minuti della RTC ed ogni 15 minuti se il valore di now.minute() è differente dal valore contenuto nella variabile current :

  • accende il display LCD ( BlaklightOn() )
  • assegna il minuto corrente alla variabile current
  • richiama saveData() per il salvataggio dei dati rilevati dalle sonde
  • pulisce il display LCD

L’epsediente della variabile current impedisce che se il salvataggio duri meno di un minuto la centralina humidity temperatura suolo salvi più righe per il medesimo minuto;

linee 126-127: se premi un pulsante di quelli che riportano valori superiori ad 1 ( LEFT,RIGHT,UP,DOWN ) accendi il display, richiami la funzione di visualizzazione dei dati rilevati dalla centralina humidity temperatura suolo attraverso i suoi sensori e pulisci il display LCD;

linee 129-135: componi le due righe con la data e l’ora corrente e le visualizzi sul display LCD;

linee 137-138: attendi un tempo pari ad un secondo e spegni il display LCD richiamando la funzione blacklightOff().

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

le due funzioni blacklightOn e blacklightOff hanno il compito di accendere e spegnere la retro illuminazione del display LCD in modo da rendere tale operazione del tutto indipendente dal tipo di display utilizzato e dal pin a cui è connessa la retro illuminazione.

linea 141: accende la retro illuminazione portando a livello HIGH il pin BLAKLIGHT;

linea 142: spegne la retro illuminazione portando a livello LOW il pin BLAKLIGHT;

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

la funzione setMode( DateTime now ) accetta come valore in ingresso l’istanza now e restituisce un’istanza di tipo DateTime dopo l’impostazione della data e dell’ora corrente.

Trovi le descrizione della funzione setMode() in altri articoli dedicati all’RTC

In pratiica il risultato che otterrai è che alla pressione del pulsante SELECT per un tempo maggiore a quello impostato nella variabile setModeTime lo sketch richiama questa funzione.

La pressione dei pulsanti UP e DOWN ti sposta tra i menu nella sequenza: GIORNO -> MESE -> ANNO -> ORA -> MINUTI -> SECONDI mentre i pulsanti LEFT e RIGHT servono ad incrementare e decrementare il valore da impostare per ogni voce del sottomenu.

Per salvare i valori impostati è necessario non toccare alcun pulsante per un tempo doppio del valore impostato nella variabile setModeTime o premere il pulsante SELCT in modo che il controllo alla linea 220 provveda a salvare i valori impostati nella RTC Shield ed uscire dalla modalità di impostazione della data e dell’ora.

In questo video puoi vedere come si imposta la data e l’ora per la centralina humidity temperatura suolo.

Buon monitoraggio !!!

  • 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-parte-ii.html

4 commenti

Vai al modulo dei commenti

    • Eliseo il 19 Settembre 2014 alle 12:16
    • Rispondi

    Buongiorno,
    Seguo molto le sue lezioni ed i suoi esempi riguardo Arduino, e la ringrazio molto per questo aiuto.
    Avrei però bisogno di un consiglio.
    Devo fare un programma simile a questo, cioè gestire lcd e pulsanti. Volevo sapere se esiste un metodo più semplice per la gestione del menù e l’interazione con esso attraverso i pulsanti.
    GRAZIE

    1. Ciao Eliseo,
      grazie per i complimenti.
      L’unico modo che conosco è questo, non escludo ne esistano altri, tuttavia avessi avuto a disposizione un metodo più semplice lo avrei di certo usato.
      Se trovi un metodo più semplice e ti va di condividerlo gli posso dedicare un progetto.

    • Eliseo il 20 Settembre 2014 alle 11:03
    • Rispondi

    Ho trovato la libreria menwiz, però nonostante gli esempi faccio fatica a capire come funziona e soprattutto se mi permette o meno di risparmiare memoria. Mi servirebbe un menu con 5 pagine totali, 3 di programmazione e 2 di visualizzazione….

    1. Ciao Eliseo,
      non la conoscevo, se ho tempo la guardo, intanto se approfondisci il suo funzionamento sono a disposizione per condividerlo con altri appassionati.

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.