Problema compilazione sketch con funzione Alarm.AlarmRepeat

Ciao a tutti!! nonostante diverse ricerche fatte online, sono di nuovo qui a chiedervi un aiuto: devo realizzare un semplice progetto con Arduino UNO, un RTC DS3231, display I2C che deve mostrare ora e data sul display e poi ad una certa ora (alle 3.00 di notte di tutti i giorni) deve mettere in stato "HIGH" 5 pin che a loro volta (tramite appositi bjt e relè) dovranno accendere in successione 5 elettrovalvole per 40 minuti l'una (quindi si accende elettrovalvola 1 per 40 min. poi si spegne e si accende la 2 per 40 min. e così via...fino alla 5 poi tutto spento fine alle 3.00 del giorno successivo); in fase di Verifica dello sketch non riesco a capire perchè ottengo questi errori:

C:\Users\lorenzo\Desktop\display_e_time_giusto\display_e_time_giusto.ino: In function 'void StartProg()':

display_e_time_giusto:116:18: error: 'eleval_1' was not declared in this scope

digitalWrite(eleval_1, HIGH); //accensione elettro-valvola 1

^

display_e_time_giusto:119:18: error: 'eleval_2' was not declared in this scope

digitalWrite(eleval_2, HIGH);

^

display_e_time_giusto:122:18: error: 'eleval_3' was not declared in this scope

digitalWrite(eleval_3, HIGH);

^

display_e_time_giusto:125:18: error: 'eleval_4' was not declared in this scope

digitalWrite(eleval_4, HIGH);

^

display_e_time_giusto:128:18: error: 'eleval_5' was not declared in this scope

digitalWrite(eleval_5, HIGH);

^

exit status 1
'eleval_1' was not declared in this scope

Dove sbaglio??
Ringrazio tutti in anticipo...

Allego lo sketch completo

irrigazione.txt (3.71 KB)

Ops...scusate.....credo di aver risolto il problema: la definizione delle variabili va prima del "void setup" ...giusto?
Perchè ora sembra tutto ok e senza errori....in allegato il nuovo sketch....
Comunque visto che ormai ci sono vediamo se concettualmente potrebbe funzionare o se ci sono consigli per migliorarlo...
GRAZIE!!!!

irrigazione.txt (3.64 KB)

Ora però c'è un nuovo problema....skecth caricato...per ora ho montato dei led con resistenze da 220 ohm per simulare l'attivazone dei pin delle elettrovalvole, ma....quando arriva l'orario impostato per l'allarme....non succe nulla, ne sul display ne si accende alcun led! secondo voi come mai?

Il problema è che hai messo l'impostazione dell'allarme

Alarm.alarmRepeat(3, 00, 0, StartProg);

dentro l'if

if (rtc.lostPower()) {

che entra se e solo se l'RTC è da inizializzare.
Non sono pratico della libreria che stai usando ma secondo me spostando fuori dall'if la riga che ti ho indicato funzionerà a dovere

A parte quello che ti ha detto @fabpolli per far funzionare il tuo codice, ma ....

... onestamente rivedrei tutto il codice, senza bloccare il loop principale per ore!!!!

Federico

In generale è un programma scritto senza una visione generale
Cominciamo a vedere se lo OP arriva in fondo
Scommettiamo che il prossimo problema è che durante l'erogazione l'orologio non aggiorna?

OK ....grazie a tutti x i consigli...è quello che mi serviva...
Ora faccio tutte le prove e poi vi aggiorno...
intanto però non capisco una cosa: perchè il loop si dovrebbe bloccare per ore? anche negli esempi della libreria il programma è impostato in quel modo...

In una sola parola (o meglio un solo link) delay

Più in esteso, gli esempio sono appunto... esempi per far comprendere il funzionamento base della libreria. Come usarla al meglio diepende dal contesto in cui va usata.
Esempio classico, il programma deve attivare un uscita per cinque secondi e il programma in quel frangente non deve fare null'altro, ma proprio nulla nulla nulla e anzi se fa qualcosa probabilmente causerebbe danni? benissimo il delay(5000).
Il programma deve irrigare per un ora ma nel frattempo deve aggiornare lo schermo, accettare che l'utente prema pulsanti, invii un messaggio SMS, ecc. ecc. ecc., che è il 99.99% dei casi ovvero il programma fa qualcosa ma deve fare anche altro nel frattempo (e non contemporaneamente) il delay è il tuo nemico giurato devi temporizzare il tutto o a mezzo RTC (differenza di orari) o con l'uso di millis.
Se cerchi millis sul forum troverai millemila topic a riguardo

fabpolli:
Se cerchi millis sul forum troverai millemila topic a riguardo

Aiutiamolo ... mettiamogli la solita frase standard dai :smiley: ...

... devi studiarti come si usa la funzione millis(), prima QUI, poi QUI e QUI e QUI e tutti gli articoli che sono in QUESTA pagina ... vedrai che ti sarà tutto più chiaro.

Guglielmo

Resta valido quello che ti ha detto @fabpolli, anzi, visto che sei all'inizio, è meglio che ti studi il millis che è sempre utile, ma in questo caso specifico, imho, si riesce a gestire il tutto senza il millis.

Non conosco quelle librerie, quindi non so se si possa fare o meno, quindi ti consiglio di guadare quella che ho usato io, questa.
Va utilizzata in sostituzione di:

  • RTClib.h
  • Time.h (viene richiamata direttamente da DS3232RTC.h)
  • TimeAlarms.h

DS3232RTC.h usa direttamente i due allarmi presenti sul RTC e hai la possibilità di verificare se è scattato, quindi potresti fare più o meno in questo modo:

Nel setup imposti l'allarme all'ora iniziale e nel loop controlli se è scattato;
ogni volta che scatta, reimposti l'allarme a più 40 min dal precedente e vai avanti fino ad accendere l'ultima elettrovalvola.
Quando scatta l'ultimo allarme (fine ciclo), spegni l'ultima elettrovalvola e imposti l'allarme di nuovo all'ora iniziale.

In questo modo non devi gestire il tempo, ma solo gli allarmi.
Naturalmente avrai bisogno di almeno una variabile di stato per sapere dove ti trovi (se e quale elettrovalvola è accesa), quindi per capire cosa devi fare (aggiungere i 40 min di attività alla prossima elettrovalvola).

  //cosi imposti l'allarme
   RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 3, 0);

  // cosi verifichi se è l'ora x
  if (RTC.alarm(ALARM_1)) {
    // scatta l'allarme
    // fai quello che devi fare
  }

La mia è solo un'idea, prova a ragionare su quale strada seguire.
Resta valido l'invito a studiare il millis, serve sempre :slight_smile:

Federico

Insomma...
Basterebbe fare una manciatina di alarm.repeat

Standardoil:
Insomma...
Basterebbe fare una manciatina di alarm.repeat

Probabilmente si, ma se uso un RTC, preferisco l'altra libreria e quindi bisogna adattarsi :slight_smile:

Federico

Grazie veramente a tutti!!! mi avete dato un sacco di idee, consigli e materiale da vedere/studiare quindi......ci sentiamo fra un pò di giorni e vi aggiorno!!
Sempre disponibili e veloci!!

Ma domanda: e leggere direttamente l'ora, e i minuti, dall'RTC e fare una roba tipo (codice scritto direttamente qui, e non mi prendo la briga di formattarlo)

if (ora()==3)
{
byte lastminute=0;
for (byte i=0;i<5;i++)
{
digitalWrite (pin[i], 1);
while (minuti()< ((lastminute+40)%60));
digitalWrite (pin [i], 0);
lastminute=minuti();
}
}

Potrebbe funzionare? (dato di avere un array di pin (5), e un modo per conoscere ore e minuti)

P. S. È bloccante, certo, -ma non ha detto di dover far altro in quel tempo-. Nel caso in arrivo a breve la versione non bloccante
P. P. S. Mi sono appena accorto che lo aveva detto

A livello teorico credo funzioni

static byte inlavoro = 0;
  if (Ora() == 3)
    inlavoro = 1;
  if (inlavoro)
  {
    static byte i=0;
    static byte lastminute=0;
    if (i<5)
    {
      byte a=Minuti()<((lastminute+40)%60);
      digitalWrite (pin [i], a);
      if (!a)
      {
        i++;
        lastminute=Minuti();
      }
    }
    if (i==5)
    {
      i=inlavoro=0;
    }
  }

fabpolli:
Il problema è che hai messo l'impostazione dell'allarme

Alarm.alarmRepeat(3, 00, 0, StartProg);

dentro l'if

if (rtc.lostPower()) {

che entra se e solo se l'RTC è da inizializzare.
Non sono pratico della libreria che stai usando ma secondo me spostando fuori dall'if la riga che ti ho indicato funzionerà a dovere

Anche così non funziona...

Federico66:
Resta valido quello che ti ha detto @fabpolli, anzi, visto che sei all'inizio, è meglio che ti studi il millis che è sempre utile, ma in questo caso specifico, imho, si riesce a gestire il tutto senza il millis ...

con questa libreria tutto ok....l'allarme si attiva! grazie!

Millis Non credo sia la soluzione da usare, ma per un altro motivo: A quanto ho capito fai attualmente uso di un RTC, ovvero di un sistema per misurare il tempo con una precisione elevata, e mi sembra concettualmente stupido dotarsi di un sistema del genere e continuare a usare millis che ha una precisione Inferiore

Silente:
Millis Non credo sia la soluzione da usare, ma per un altro motivo: A quanto ho capito fai attualmente uso di un RTC, ovvero di un sistema per misurare il tempo con una precisione elevata, e mi sembra concettualmente stupido dotarsi di un sistema del genere e continuare a usare millis che ha una precisione Inferiore

Condivido...ma infine non devo realizzare un progetto ultrapreciso, mi basta che mi faccia accendere le elettrovalvole una alla volta ad una certa ora...ed avevo pensato all'RTC perchè ha un orologio con batteria ed una sveglia...

con la funzione millis ho modificato lo sketch come in allegato facendo finta di accendere solo la elettrovalv 1 per due secondi...ma non si accende...viene eseguito solo illampeggio della scritta "ON 1" e basta.

#include <DS3232RTC.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <TimeAlarms.h>
#include "RTClib.h"
#include <Time.h>
#include <TimeLib.h>

// OLED display TWI address
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib

RTC_DS3231 rtc;

const int eleval_1 = 2;
const int eleval_2 = 3;
const int eleval_3 = 4;
const int eleval_4 = 5;
const int eleval_5 = 6;

unsigned long time;
unsigned long lampeggio_time = 0;

void setup () {
  pinMode(eleval_1, OUTPUT);
  digitalWrite(eleval_1, LOW);
  pinMode(eleval_2, OUTPUT);
  digitalWrite(eleval_2, LOW);
  pinMode(eleval_3, OUTPUT);
  digitalWrite(eleval_3, LOW);
  pinMode(eleval_4, OUTPUT);
  digitalWrite(eleval_4, LOW);
  pinMode(eleval_5, OUTPUT);
  digitalWrite(eleval_5, LOW);

  // initialize and clear display
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  display.display();

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(9600);

  delay(1000); // wait for console opening

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power !");
    // 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(2014, 1, 21, 3, 0, 0));
  }

  //cosi imposti l'allarme
  RTC.setAlarm(ALM1_MATCH_HOURS, 0, 39, 23, 0);

}

void loop () {
  // cosi verifichi se è l'ora x
  if (RTC.alarm(ALARM_1)) {
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(90, 5);
    display.println("ON 1");
    
    time=millis();
   if(time>lampeggio_time+1000)
  {
    digitalWrite(eleval_1, HIGH);
  }
   if(time>lampeggio_time+2000)
  {
    digitalWrite(eleval_1, LOW);
    lampeggio_time=millis();
  }
 }
  DateTime now = rtc.now();
  Serial.print(now.day(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.year(), DEC);
  Serial.println();
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  Serial.print("T: ");
  Serial.print(rtc.getTemperature());
  Serial.println(" C");
  Serial.println();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(now.day(), DEC);
  display.print('.');
  display.print(now.month(), DEC);
  display.print('.');
  display.print(now.year(), DEC);
  display.setCursor(0, 10);
  display.print("T: ");
  display.print(rtc.getTemperature());
  display.print(" C");
  display.setCursor(45, 22);
  display.print(now.hour(), DEC);
  display.print(':');
  display.print(now.minute(), DEC);
  display.print(':');
  display.print(now.second(), DEC);
  display.display();
  display.clearDisplay();
  delay(1000);
}