Go Down

Topic: RTC DS3231 impostare allarmi (Read 1 time) previous topic - next topic

ziopippo

May 05, 2018, 06:45 pm Last Edit: May 08, 2018, 11:09 am by ziopippo
Salve,
ho bisogno di programmare alcuni relè ad orari diversi ed ho pensato di utilizzare un RTC DS3231.

So che il DS3231 gestisce solo due allarmi ed ho provato diverse librerie ma non ancora ne vengo a capo.
Ho bisogno che i relè si accendano ad una determinata ora del giorno spegnendosi ad una certa ora della notte.
In realtà i relè sono quattro ma hanno più o meno le stesse funzioni ed uno in particolare funziona al contrario dell'altro; Qui non è un problema perchè una volta eccitato l'uno metto su LOW l'altro e vice versa.
Due devono accendersi di mattina e due di notte.
Chi mi aiuta con un consiglio su dove indirizzarmi per gestire al meglio l'RTC?
Grazie.

ziopippo

#1
May 08, 2018, 06:29 pm Last Edit: May 08, 2018, 07:32 pm by ziopippo
Per ora sono riuscito ad arrivare a questo punto:

Code: [Select]

/*
   Esempio per accensione ed spegnimento relè temporizzati
*/
#include <TimeLib.h>
#include <TimeAlarms.h>
#include <LiquidCrystal_I2C.h>
#include <DS3232RTC.h>
#include <Wire.h>

AlarmId id;

// lcd object
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

//================================= DEFINISCO LE VARIABILI DEI RELE' ====================================
const int releCO2 = 8;         //relè CO2                   R1 NC
const int releAereatore = 9; //relè Aereatore           R2 NA
const int releTermo = 10;    //relè Temoriscaldatore R3 NA
const int relePlafo = 12;     //relè Plafoniera            R4 NA


void setup() {
  Serial.begin(57600);
  while (!Serial) ; // wait for Arduino Serial Monitor


  setSyncProvider(RTC.get);  // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");

  //setTime(8, 29, 40, 1, 1, 11); // set time to Saturday 8:29:00am Jan 1 2011

  lcd.init();
  lcd.clear();
  lcd.backlight();

  pinMode(releCO2 , OUTPUT);
  digitalWrite(releCO2 , HIGH);
  pinMode(releAereatore , OUTPUT);
  digitalWrite(releAereatore , HIGH);
  pinMode(releTermo , OUTPUT);
  digitalWrite(releTermo , HIGH);
  pinMode(relePlafo , OUTPUT);
  digitalWrite(relePlafo , HIGH);

  // create the alarms, to trigger at specific times
  Alarm.alarmRepeat(17, 00, 00, CO2); // 17:00:00 every day
  Alarm.alarmRepeat(18, 00, 00, Aereatore); // 18:00:00 every day

  digitalClockDisplay();
}

void loop() {
  printTime();
  Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:
void CO2() {
  Serial.println("Alarm: accendo CO2");
  lcd.setCursor(0, 0);
  lcd.print("CO2:ON Aereatore:OFF");
  digitalWrite(releCO2 , LOW);
}

void Aereatore() {
  lcd.setCursor(0, 0);
  lcd.print("CO2:OFF Aereatore:OFF");
  Serial.println("Alarm: spengo CO2");
  digitalWrite(releCO2 , HIGH);
  delay(2000);

  lcd.setCursor(0, 0);
  lcd.print("CO2:OFF Aereatore:ON");
  Serial.println("Alarm: accedo aereatore");
  digitalWrite(releAereatore , LOW);
}

void p2dig(uint8_t v)
// Print 2 digits with leading zero
{
  if (v < 10) lcd.print("0");
  lcd.print(v);
}

void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

const char *dow2String(uint8_t code)
// Day of week to string. DOW 1=Sunday, 0 is undefined
{
  static const char *str[] = {"---", "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"};

  if (code > 7) code = 0;
  return (str[code]);
}

void printTime(void)
// Display the current time on the display
{
  // display the current time
  lcd.setCursor(0, 1);
  lcd.print (hour());
  lcd.print(":");
  p2dig(minute());
  lcd.print(":");
  p2dig(second());
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print('/');
  Serial.print(month());
  Serial.print('/');
  Serial.print(year());
  Serial.println();
  Alarm.delay(1000); // wait one second between clock display
}



I problema però è che se va via la luce o carico lo sketch dopo gli allarmi questi, non si attivano.
Mi spiego meglio; Se carico lo sketch alle 16:00 tutto funziona correttamente; Se invece lo carico alle 17:30 il relè CO2 non si eccita per (alle 18:00 tutto funzionerà correttamente); Se lo carico alle 18:01 non accadrà nulla.
La domanda è: come faccio a far "leggere" l'allarme in qualunque momento?[/code]

Standardoil

semplice, non fai
non è che "legge" l'allarme, esegue un comando (OK OK una funzione passata come indirizzo)
dicevo esegue una funzione a quell'ora, e non ad altre
se vuoi che un certo coso stia acceso tra un'ora e un'altra  "anche"  se all'inizio del periodo arduino è spento devi fare differente
Consiglio
se ora è piu' di inizio e meno di fine
traducilo prima in inglese e poi in 'C' vedrai che è meno complicato di quanto si puo' pensare   
Seconda legge di Nelson, che sono io:
Un programma ben pensato è già mezzo realizzato

ziopippo

#3
May 08, 2018, 07:40 pm Last Edit: May 08, 2018, 07:41 pm by ziopippo
semplice, non fai
non è che "legge" l'allarme, esegue un comando (OK OK una funzione passata come indirizzo)
dicevo esegue una funzione a quell'ora, e non ad altre
se vuoi che un certo coso stia acceso tra un'ora e un'altra  "anche"  se all'inizio del periodo arduino è spento devi fare differente
Consiglio
se ora è piu' di inizio e meno di fine
traducilo prima in inglese e poi in 'C' vedrai che è meno complicato di quanto si puo' pensare   
Così facendo ovviamente credo sia inutile utilizzare la funzione Alarm.alarmRepeat della libreria TimeAlarms.
Inizia però il problema di come memorizzare  inizio e fine, entrando in una bolgia di clcoli con i secondi o con Unix Time.
In realtà cercavo un modo meno complicato per non uscire matto.

ziopippo

Provando così funziona:

Code: [Select]
/*
   Esempio per accensione ed spegnimento relè temporizzati
*/
#include <TimeLib.h>
#include <TimeAlarms.h>
#include <LiquidCrystal_I2C.h>
#include <DS3232RTC.h>
#include <Wire.h>

AlarmId id;

// lcd object
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

//================================= DEFINISCO LE VARIABILI DEI RELE' ====================================
const int releCO2 = 8;       //relè CO2              R1 NC
const int releAereatore = 9; //relè Aereatore        R2 NA
const int releTermo = 10;    //relè Temoriscaldatore R3 NA
const int relePlafo = 12;    //relè Plafoniera       R4 NA




void setup() {
  Serial.begin(57600);
  while (!Serial) ; // wait for Arduino Serial Monitor


  setSyncProvider(RTC.get);  // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");

  //setTime(8, 29, 40, 1, 1, 11); // set time to Saturday 8:29:00am Jan 1 2011

  lcd.init();
  lcd.clear();
  lcd.backlight();

  pinMode(releCO2 , OUTPUT);
  digitalWrite(releCO2 , HIGH);
  pinMode(releAereatore , OUTPUT);
  digitalWrite(releAereatore , HIGH);
  pinMode(releTermo , OUTPUT);
  digitalWrite(releTermo , HIGH);
  pinMode(relePlafo , OUTPUT);
  digitalWrite(relePlafo , HIGH);

  // create the alarms, to trigger at specific times
  Alarm.alarmRepeat(18, 43, 0, CO2); // 18:430 every day
  Alarm.alarmRepeat(21, 43, 30, Aereatore); // 21:43:00 every day

  digitalClockDisplay();
}

void loop() {
  printTime();
  Alarm.delay(0); // wait one second between clock display
  CO2();
}

// functions to be called when an alarm triggers:
void CO2() {
    if ( (hour() >= 20) || (hour() <= 2) ) {
    Serial.println("Alarm: accendo CO2");
    lcd.setCursor(0, 0);
    lcd.print("CO2:ON AIR:OFF");
    digitalWrite(releCO2 , LOW);
  }
  else {
    Serial.println("Alarm: spengo CO2");
    lcd.setCursor(0, 0);
    lcd.print("CO2:OF AIR:OFF");
    digitalWrite(releCO2 , HIGH);
  }
  /*
    Serial.println("Alarm: accendo CO2");
    lcd.setCursor(0, 0);
    lcd.print("CO2:ON AIR:OFF");
    digitalWrite(releCO2 , LOW);*/
}

void Aereatore() {
  lcd.setCursor(0, 0);
  lcd.print("CO2:OFF AIR:OFF");
  Serial.println("Alarm: spengo CO2");
  digitalWrite(releCO2 , HIGH);
  delay(2000);

  lcd.setCursor(0, 0);
  lcd.print("CO2:OFF AIR:ON ");
  Serial.println("Alarm: accedo aereatore");
  digitalWrite(releAereatore , LOW);
}

void p2dig(uint8_t v)
// Print 2 digits with leading zero
{
  if (v < 10) lcd.print("0");
  lcd.print(v);
}

void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

const char *dow2String(uint8_t code)
// Day of week to string. DOW 1=Sunday, 0 is undefined
{
  static const char *str[] = {"---", "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"};

  if (code > 7) code = 0;
  return (str[code]);
}

void printTime(void)
// Display the current time on the display
{
  // display the current time
  lcd.setCursor(0, 1);
  lcd.print (hour());
  lcd.print(":");
  p2dig(minute());
  lcd.print(":");
  p2dig(second());
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print('/');
  Serial.print(month());
  Serial.print('/');
  Serial.print(year());
  Serial.println();
  Alarm.delay(1000); // wait one second between clock display
}



però non gestisce i minuti :(

Standardoil

Scriviti in italiano la condizione con ore e minuti
Oppure ragiona in minuti moltiplicando per 60 le ore e sommando i minuti
Oppure ragiona in ore e frazioni digitando per 60 i minuti e sommando le ore
Insomma si può fare....
Seconda legge di Nelson, che sono io:
Un programma ben pensato è già mezzo realizzato

ziopippo

Scriviti in italiano la condizione con ore e minuti
Oppure ragiona in minuti moltiplicando per 60 le ore e sommando i minuti
Oppure ragiona in ore e frazioni digitando per 60 i minuti e sommando le ore
Insomma si può fare....
Qualcosa non mi torna però con il tuo ragionamento, e quel qualcosa è se imposto la fine dell'allarme  ad un orario dopo la mezza notte.
Seguendo il tuo consiglio tutto fila fino alle 23.59 poi tutto sballa.
Faccio un esempio:

T1 - Inizio allarme 14:30 =    860 m
T2 - Fine allarme   21:00 = 1.260 m.
Il controllo da fare sarebbe: IF NOW => T1 AND NOW <= T2 ELSE relè ON

Invece se si imposta la fine dell'allarme dopo la mezza notte ad esempio alle 3:00 = 180m la formula non funziona più perchè se NOW = 23:00 =1.380 m in questo caso NOW non è più piccolo di T2.

Standardoil

Purtroppo è vero
Soluzioni semplici non ne ho
Seconda legge di Nelson, che sono io:
Un programma ben pensato è già mezzo realizzato

ziopippo

Sarebbe da convertire tutto in Unix Time Stamp però al contrario di NOW non saprei come fare per convertire T1 e T2

Patrick_M

invece di consicerare solo ora
T1 - Inizio allarme 14:30 =    860 m
T2 - Fine allarme   21:00 = 1.260 m.
considerare anche data...
T1 - Inizio allarme 2018-05-10-14:30 = ...
T2 - Fine allarme   2018-05-11-03:00 = ...
per inserire lo sketch da IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

ziopippo

invece di consicerare solo ora
T1 - Inizio allarme 14:30 =    860 m
T2 - Fine allarme   21:00 = 1.260 m.
considerare anche data...
T1 - Inizio allarme 2018-05-10-14:30 = ...
T2 - Fine allarme   2018-05-11-03:00 = ...
In che modo? T1 e T2 vengono impostai una tantum e modificati con un encoder e display molto di rado. Come faccio a capire la data dei due T?

Patrick_M

probabilmente bisognerebbe stravolgere un po il codice....

e se allo start dell'allarme imposti una variabile con i minuti mancanti per la fine del periodo? ovvio che se l'orario finale è minore bisogna aggiungere i minuti mancanti alle 00:00 e il tutto vale solo per intervalli inferiori alle 24 ore
per inserire lo sketch da IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

ziopippo

probabilmente bisognerebbe stravolgere un po il codice....

e se allo start dell'allarme imposti una variabile con i minuti mancanti per la fine del periodo? ovvio che se l'orario finale è minore bisogna aggiungere i minuti mancanti alle 00:00 e il tutto vale solo per intervalli inferiori alle 24 ore
Grazie per la risposta.
In realtà quello scritto è una "bozza" che poi andrà inclusa in un codice più complesso che prevede l'utilizzo di più relè, sonda ds18b20, ed un menù su lcd i2c comandato da encoder rotativo.
Sto scrivendo piccoli pezzi di codice per semplificare il tutto per poi riassemblarli insieme alla fine.
Se ne hai voglia puoi tranquillamente provare la tua teoria e postarmi le modifiche, ne sarei  più che onorato. ;)
P.S: in giornata vedo di condividere anche tutta la parte hardware che, senza presunzione, penso sia venuta molto bella.

ziopippo

#13
May 11, 2018, 11:18 am Last Edit: May 11, 2018, 12:13 pm by ziopippo
Ecco le foto del porgetto.
Per il display volevo utilizzare le custom char per inserire simboli in modo di dare più spazio alle informazioni utili variabili (tipo ora, allarmi e temperature)  ma purtoppo non so perchè ma utilizzando la libreria LCDMenuLib.h di Nils Feldkämper non risco a visualizzarli; Questo però è ripagato dal fatto che è una liberia davvero completa che permette di gestire tantissimi display e tante possibilità per comandarli tramite tasti, pulsanti, encoder ed altro che semplifica non poco la vita.
































Patrick_M

#14
May 11, 2018, 01:02 pm Last Edit: May 11, 2018, 01:04 pm by Patrick_M
ho dato un'occhiata al readme.txt della libreria degli allarmi e ho trovato questo:

Alarm.timerOnce(Hour, Minute, Second, TimerFunction);
  Description:  As timerOnce above, but period is the number of seconds in the given Hour, Minute and Second parameters

quindi puoi impostare l'allarme all'orario che vuoi come gia facevi e impostare la durata per l'intervento con la timerOnce che accetta ore, minuti e secondi
quindi seguendo l'esempio
Code: [Select]

#include <Time.h>
#include <TimeAlarms.h>

void setup()
{
  Serial.begin(9600);
  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
  // create the alarms
  Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
  Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day
 
//
// nel caso di mancanza corrente
// qui ci va il controllo se siamo in un orario successivo al previsto per l'allarme
//per l'attivazione/disattivazione dei relè
// qualche cosa tipo
// if (oraAdesso > oraPrimoAllarme && oraAdesso < oraFineAllarme)
//    attiva/disattiva relè;


}
void  loop(){ 
  digitalClockDisplay();    //fai quello che serve
  Alarm.delay(1000);     // wait one second between clock display
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - accendi relè 1");
// esegui le varie istruzioni
Alarm.timerOnce(Hour, Minute, Second, EndFunction); // tra quanto tempo in ore, minuti, secondi intervenire
}

void EndFunction() {
   serial.println("Spengo relè 1");
// esegui le varie istruzioni

}

per inserire lo sketch da IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

Go Up