Problema sketch per far funzionare rele con rtc ***RISOLTO***

Buongiorno a tutti,

Sto cercando di controllare 2 rele con un RTC, voglio che il primo di accenda ad una certa ora (il secondo vediamo più avanti voglio impostare un timer che dopo x minuti dall'avvio del primo si deve accendere il secondo per x tempo).

Per ora, mi funzionano i rele, il sensore funziona, lo schermo funziona e l'RTC funziona.

MA, se mi stampa l'ora in Serial, non riesco a stampare sullo schermo, ne a utilizzare "hour" "minute" "second" "dayOfMonth" ecc altrove che li.

Ad esempio, nella riga evidenziata di giallo, mi sembra non aver sbagliato il codice ma evidentemente lo è perché mi dice che " 'hour' was not declared in this scope"
Perché?!

Grazie a chi vorrà aiutarmi.
(il mio sketch è fatto da più sketch trovati in internet e adattati al mio caso, non sono bravo abbastanza da scrivere da 0)

#include "Wire.h"
#include <LiquidCrystal_I2C.h>


//inizio RTC                *****************************
#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}
unsigned long previousMillisRTC = 0;        // will store last time RTC was updated
const long interval = 1000;              // interval at which to check RTC (milliseconds)

void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(
byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  switch(dayOfWeek){
  case 1:
    Serial.print("Domenica ");
    break;
  case 2:
    Serial.print("Lunedi ");
    break;
  case 3:
    Serial.print("Martedi ");
    break;
  case 4:
    Serial.print("Mercoledi ");
    break;
  case 5:
    Serial.print("Giovedi ");
    break;
  case 6:
    Serial.print("Venerdi ");
    break;
  case 7:
    Serial.print("Sabato ");
    break;
  }
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.println(year, DEC);
  
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.println(" ");    
}
//fine RTC                *****************************



//Pompa
int pompa = 7;                            // Pump connected to digital pin 7
//unsigned long previousMillisPompa = 0;        // will store last time POMPA was updated
//const long intervalPompa = 5000;              // interval at which to check POMPA (milliseconds)

//Elettrovalvola
int valvola = 4;                            // Pump connected to digital pin 4


//millis per sensore orizzontale
unsigned long previousMillisSensore = 0;        // will store last time Sensore was updated
//const long interval = 1000;                   // Uguale per RTC e Sensore
int lightPin = 0;              // Analog Input LED Sensore
int threshold = 500;           // 0 chiuso - 1023 aperto

//lcd2004
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
unsigned long previousMillisLCD = 0;        // will store last time Sensore was updated


void setup()
{
  lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.setCursor(3,0);     //Start at character 4 on line 0
  
  Wire.begin();
  Serial.begin(9600);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
  //setDS3231time(40,12,16,3,25,04,17);

  //Pompa
  pinMode(pompa, OUTPUT);      // sets the digital pin as output
  
  //Elettrovalvola
  pinMode(valvola, OUTPUT);      // sets the digital pin as output

  //LED Sensore orizzontale
  pinMode(13, OUTPUT);
}




void loop()
{
  //RTC
unsigned long currentMillisRTC = millis();
if (currentMillisRTC - previousMillisRTC >= interval) {
    // save the last time you blinked the LED
    previousMillisRTC = currentMillisRTC;

  displayTime(); // display the real-time clock data on the Serial Monitor,
}

{
//lcd2004
unsigned long currentMillisLCD = millis();
if (currentMillisLCD - previousMillisLCD >= interval) {
    // save the last time you controlled
    previousMillisLCD = currentMillisLCD;
    lcd.setCursor(3,0); //Start at character 4 on line 0
    lcd.print("HELLO, WORLD!");
}
}

{
//Elettrovalvola
[color=yellow]while(hour == 7 && minute >= 00 && minute <= 02){[/color]   <<------
 digitalWrite(valvola, HIGH);   // sets the elettrovalvola on
}
}

unsigned long currentMillisSensore = millis();
if (currentMillisSensore - previousMillisSensore >= interval) {
    // save the last time you blinked the LED
    previousMillisSensore = currentMillisSensore;
  
//Serial.println(analogRead(lightPin)); 
 
    if(analogRead(lightPin) > threshold ) {         
        digitalWrite(13, HIGH);       //LED pin 13
        digitalWrite(pompa, HIGH);   // sets the pump on   
        Serial.println("high");
        lcd.setCursor(0,2);
        lcd.print("Pompa aperta");
    } else {
        digitalWrite(13, LOW);        //LED pin 13
        digitalWrite(pompa, LOW);    // sets the pump off
        Serial.println("low");
        lcd.setCursor(0,2);
        lcd.print("Pompa chiusa");  
    }
}

}

in effetti, visto dove sono dichiarate, le variabili hour e minute non sono accessibili dal loop...

>Wado: ... ti consiglio di prendere un buon testo di 'C' e di ripassare i concetti di 'variabili locali' e 'variabili globali' e della loro 'visibilità' :wink:

Guglielmo

guarda anche io l' anno scorso mi sono imbattuto su questo problema di accendere un relè per l' orto a una determinata ora per innaffiare le piante e ci sono riuscito. E' molto semplice: ho utilizzato la libreria RTClib per programmare arduino con un ds1307, poi scrivendo sul codice

  lcd.print(now.hour(), DEC);

stampavo l' ora sul mio lcd. Infine per accendere il relè scrivevo

  if(now.hour() == 21){
    digitalWrite(rele, HIGH);
 }
 else{
   digitalWrite(rele, LOW);
 }

e così è andato avanti tutta l' estate e anche questa che verrà.
Ovviamente questo non è tutto il codice. Ti ho scritto solo quelle tre righe che ho usato per accendere il relè. Se vuoi ti mostro il codice per intero appena ho terminato di migliorarlo, cioè tra pochi giorni.

fratt:
in effetti, visto dove sono dichiarate, le variabili hour e minute non sono accessibili dal loop...

Ho provato a spostare tutto il blocco nel setup ma non funziona lo stesso

gpb01:
>Wado: ... ti consiglio di prendere un buon testo di 'C' e di ripassare i concetti di 'variabili locali' e 'variabili globali' e della loro 'visibilità' :wink:

Guglielmo

Ah questa delle variabili locali mi mancava... grazie!

C'è un modo per rimediare? Posso trasformare le variabili locali spostandole o non è cosi semplice?
Perché difatti queste variabili mi serviranno per entrambi i rele e lo schermo.

Grazie in tanto!!

Se dichiari le variabili in testa al programma (... dopo le varie #include per capirci) e al di fuori di qualsiasi funzione, esse saranno 'globali' e le vedrai dovunque, se le dichiari dentro una qualsiasi funzione (setup(), loop(), tuaFunzione(), ecc.) esse saranno 'locali' e le vedrai SOLO dentro quella funzione.

Non solo, se dentro una funzione dichiari una 'locale' che ha lo stesso nome di una 'globale', la 'locale' ti nasconde la 'globale' che, li dentro, non viene più vista, quindi ... evitare di usare gli stessi nomi per variabli 'locali' e 'globali'. :wink:

Nota che, se non c'è lo scopo di accederci da più funzioni, è sempre meglio dichiarare le variabili 'locali'. Ovviamente, se invece ci si deve accedere da più funzioni, la strada più semplice è dichiarale 'globali'

Guglielmo

Ho risolto parzialmente utilizzando un altro sketch per DS3231 che non usa variabili locali.
Riesco a stampare su lcd.
Grazie a voi che avete preso il tempo di aiutarmi e specialmente gpb01 che è stato più che chiaro!!

Se avete ancora la pazienza di aiutarmi vorrei capire come potrei fare per decidere di attivare un rele ad un orario fisso ad esempio alle 07 ogni giorno?

Grazie a chi vorrà aiutarmi!

#include <DS3231.h> 
#include "Wire.h"
#include <LiquidCrystal_I2C.h>

DS3231 rtc(SDA, SCL);

//millis RTC
unsigned long previousMillisRTC = 0;        // will store last time RTC was updated
const long interval = 1000;              // interval at which to check RTC (milliseconds)

//Pompa
int pompa = 7;                            // Pump connected to digital pin 7
//unsigned long previousMillisPompa = 0;        // will store last time POMPA was updated
//const long intervalPompa = 5000;              // interval at which to check POMPA (milliseconds)

//Elettrovalvola
int valvola = 4;                            // Pump connected to digital pin 4


//millis per sensore orizzontale
unsigned long previousMillisSensore = 0;        // will store last time Sensore was updated
//const long interval = 1000;                   // Uguale per RTC e Sensore
int lightPin = 0;              // Analog Input LED Sensore
int threshold = 500;           // 0 chiuso - 1023 aperto

//lcd2004
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
unsigned long previousMillisLCD = 0;        // will store last time Sensore was updated


void setup()
{
  lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.setCursor(3,0);     //Start at character 4 on line 0
  
  //RTC
  rtc.begin();
  // The following lines can be uncommented to set the date and time
  //rtc.setDOW(SUNDAY);     // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 22, 30);     // Set the time to 12:22:30 (24hr format)
  //rtc.setDate(30, 4, 2017);   // Set the date to 30 aprile 2017
  
  Wire.begin();
  Serial.begin(9600);


  //Pompa
  pinMode(pompa, OUTPUT);      // sets the digital pin as output
  
  //Elettrovalvola
  pinMode(valvola, OUTPUT);      // sets the digital pin as output

  //LED Sensore orizzontale
  pinMode(13, OUTPUT);
}




void loop()
{
  
 //RTC
 unsigned long currentMillisRTC = millis();
if (currentMillisRTC - previousMillisRTC >= interval) 
{
  // save the last time you blinked the LED
  previousMillisRTC = currentMillisRTC;
  // Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");
  
  // Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");

  // Send time
  Serial.println(rtc.getTimeStr());
  lcd.setCursor(0,1); //Start at character 4 on line 0
  lcd.print(rtc.getTimeStr());
  }


{
//lcd2004
unsigned long currentMillisLCD = millis();
if (currentMillisLCD - previousMillisLCD >= interval) {
    // save the last time you controlled
    previousMillisLCD = currentMillisLCD;
    lcd.setCursor(3,0); //Start at character 4 on line 0
    lcd.print("HELLO, WORLD!");
}
}

{
//Elettrovalvola
  digitalWrite(valvola, HIGH);   // sets the elettrovalvola on
//}
}

unsigned long currentMillisSensore = millis();
if (currentMillisSensore - previousMillisSensore >= interval) {
    // save the last time you blinked the LED
    previousMillisSensore = currentMillisSensore;
  
//Serial.println(analogRead(lightPin)); 
 
    if(analogRead(lightPin) > threshold ) {         
        digitalWrite(13, HIGH);       //LED pin 13
        digitalWrite(pompa, HIGH);   // sets the pump on   
        Serial.println("high");
        lcd.setCursor(0,2);
        lcd.print("Pompa aperta");
    } else {
        digitalWrite(13, LOW);        //LED pin 13
        digitalWrite(pompa, LOW);    // sets the pump off
        Serial.println("low");
        lcd.setCursor(0,2);
        lcd.print("Pompa chiusa");  
    }
}

}

Inoltre non capisco perché se tolgo l'alimentazione ad arduino poi non riparte correttamente lo sketch?
Sul serial o sul LCD non viene fuori niente devo ricaricare lo sketch ogni volta, il che è un problema perche una volta montato se salta la corrente poi non funziona più! come mai?

non uso la tua stessa libreria, ma con un minimo di pazienza dovresti riuscire a trovare le istruzioni compatibili col mio esempio
in pratica prendi l'orario corrente e confronti ore e minuti con il valore che ti serve...

    DateTime now = rtc.now();
    
    if ((now.hour() == 7) && (now.minute() == 0)) {
      // sono le 7.00... fai quello che devi fare

    }

per il secondo problema... se togli e ridai l'alimentazione ad arduino lo sketch dovrebbe ripartire dall'inizio... con me funziona così

fratt:
non uso la tua stessa libreria, ma con un minimo di pazienza dovresti riuscire a trovare le istruzioni compatibili col mio esempio
in pratica prendi l'orario corrente e confronti ore e minuti con il valore che ti serve...

    DateTime now = rtc.now();

if ((now.hour() == 7) && (now.minute() == 0)) {
      // sono le 7.00... fai quello che devi fare

}




per il secondo problema... se togli e ridai l'alimentazione ad arduino lo sketch dovrebbe ripartire dall'inizio... con me funziona così

Ma sai che mi sei stato d'aiuto?! :smiley:

Ho cercato un'altro esempio con il "DateTime now..." per il DS3231 e ho trovato uno sketch, domani con calma lo provo ma mi sembra che faccia al caso mio!

Per il secondo problema invece ti confermo che se tolgo la corrente quando lo ricollego mi da quadratini sullo schermo e niente sul Serial, a meno che non ricarichi lo sketch.
Appena ricarico lo sketch funziona nuovamente.

I quadratini sul display sono normali. È lo "schermo" di acensione del dislay. Se li vedi vuol dire che non é stato inizializzato.

Prova a schiacciare il pulsante reset dopo averli dato alimentazione.
Parte cosí?

Ciao Uwe

Ciao Uwe,

Grazie per il suggerimento, si avevo provato a schiacciare reset, a fare reset dal pin reset, e ad usare il watchdog ma non c'era niente da fare, era come se il i2c non si resettava e bloccava il tutto.

Fortunatamente mi è venuto in mente di provare con un'altro Atmega328 che fortunatamente avevo e adesso funziona bene.

Chissà cosa avrà avuto questo per non funzionare? boh!

Comunque ragazzi vi ringrazio tantissimo per il vostro interesse e il vostro aiuto.

Adesso il mio sketch è cosi

#include "Wire.h"
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
#include <avr/wdt.h>             // includo la libreria per utilizzare il watchdog


//millis RTC
unsigned long previousMillisRTC = 0;        // will store last time RTC was updated
const long interval = 1000;              // interval at which to check RTC (milliseconds)
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Domenica", "Lunedi", "Martedi", "Mercoledi", "Giovedi", "Venerdi", "Sabato"};


//lcd2004
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
unsigned long previousMillisLCD = 0;        // will store last time Sensore was updated


//Elettrovalvola
int valvola = 4;                                       // Pump connected to digital pin 4
int oraAccenzioneValvolaMattina = 6;                  // Ora accenzione Valvola Mattina
int oraAccenzioneValvolaPomeriggio = 17;               // Ora accenzione Valvola Pomeriggio
int minAccenzioneValvola = 36;                         // Minute accenzione Valvola


//Pompa
int pompa = 7;                            // Pump connected to digital pin 7
unsigned long previousMillisPompa = 0;        // will store last time POMPA was updated
//const long intervalPompa = 10000;              // interval at which to check POMPA (milliseconds)
int minAccenzionePompa = (minAccenzioneValvola + 1);   // Intervallo per accenzione pompa
// dopo accenzione Valvola

//millis per sensore orizzontale
unsigned long previousMillisSensore = 0;        // will store last time Sensore was updated
//const long interval = 1000;                   // Uguale per RTC e Sensore
int lightPin = 0;              // Analog Input LED Sensore
int threshold = 500;           // 0 chiuso - 1023 aperto



void setup()
{
  wdt_enable(WDTO_1S);         // abilita la funzione watchdog con un tempo di intervento di 1 secondo

  Wire.begin();
  Serial.begin(9600);
  lcd.begin(20, 4);        // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.setCursor(3, 0);    //Start at character 3 on line 0

  //RTC
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    //rtc.adjust(DateTime(2017, 5, 1, 18, 17, 30));
  }

  //Pompa
  pinMode(pompa, OUTPUT);      // sets the digital pin as output

  //Elettrovalvola
  pinMode(valvola, OUTPUT);      // sets the digital pin as output

  //LED Sensore orizzontale
  pinMode(13, OUTPUT);
}



void loop()
{

  //***RTC
  DateTime now = rtc.now();

  unsigned long currentMillisRTC = millis();
  if (currentMillisRTC - previousMillisRTC >= interval) {
    previousMillisRTC = currentMillisRTC;

    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(" ");
    Serial.print(now.day(), DEC);
    Serial.print("/");
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.year(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    Serial.println();

    lcd.setCursor(0, 1);              //Start at character 0 on line 2
    //lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
    //lcd.print(" ");
    lcd.print(now.day(), DEC);
    lcd.print("/");
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.year(), DEC);
    lcd.print(' ');
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    lcd.print(now.second(), DEC);
    lcd.println("      ");
  }


  {
    //***lcd2004
    //unsigned long currentMillisLCD = millis();
    //if (currentMillisLCD - previousMillisLCD >= interval) {
    // save the last time you controlled
    //previousMillisLCD = currentMillisLCD;
    lcd.setCursor(3, 0); //Start at character 4 on line 0
    lcd.print("HELLO, WORLD!");
    //}
  }

  {
    //***Elettrovalvola
    lcd.setCursor(0, 2);
    lcd.print("Valvola ");

    unsigned long currentMillisSensore = millis();
    //unsigned long currentMillisValvola = millis();
    if (currentMillisSensore - previousMillisSensore >= interval) {
      // save the last time you blinked the LED
      previousMillisSensore = currentMillisSensore;

      if (now.hour() == oraAccenzioneValvolaMattina && (now.minute() == minAccenzioneValvola )) {
        digitalWrite(valvola, HIGH);   // sets the pump on
        lcd.setCursor(8, 2);
        lcd.print("aperta");
        Serial.print("Valvola ");
        Serial.println("high");
      } else {
        digitalWrite(valvola, LOW);    // sets the pump off
        lcd.setCursor(8, 2);
        lcd.print("chiusa");
        Serial.print("Valvola ");
        Serial.println("low");
      }
    }
  }//***Fine Elettrovalvola


  {
    //***POMPA
    lcd.setCursor(0, 3);
    lcd.print("Pompa ");

    unsigned long currentMillisPompa = millis();
    if (currentMillisPompa - previousMillisPompa >= interval) {
      // save the last time you blinked the LED
      previousMillisPompa = currentMillisPompa;

      if ((analogRead(lightPin) > threshold ) && (now.minute() == minAccenzionePompa) ) {
        digitalWrite(13, HIGH);       //LED pin 13
        digitalWrite(pompa, HIGH);   // sets the pump on
        Serial.print("Pompa ");
        Serial.println("high");
        lcd.setCursor(7, 3);
        lcd.print(" aperta");
      }
      else {
        digitalWrite(13, LOW);        //LED pin 13
        digitalWrite(pompa, LOW);    // sets the pump off
        Serial.print("Pompa ");
        Serial.println("low");
        lcd.setCursor(7, 3);
        lcd.print(" chiusa");
      }
    }

  }//***Fine Pompa

  wdt_reset();                  // resetta il conteggio del watchdog, se prima di arrivare a questo punto sarà passato più di 1 secondo allora la scheda si resetterà, altrimenti il loop continuerà ad essere eseguito senza problemi

}//***Fine LOOP

Non è finito e non è certo perfetto, ma funziona! :slight_smile:

Tu hai un Arduino originale?
Ciao Uwe

Sì sì originale.
Arduino uno R3