Timer giornaliero senza RTC

Ciao a tutti, mi chiamo Claudio ed ho ricevuto appena questa mattina un SaintSmart Uno R3.
Non sono per nulla esperto nel campo della programmazione, quindi chiedo un vostro aiuto per la realizzazione di un progetto:
Vorrei realizzare tramite arduino un timer giornaliero che controlli dei relè.
In teoria risulta particolarmente facile (accenidi relè 1 alle 8:00, spegni relè 1 alle 20:00); (accenidi relè 2 alle 20:30, spegni relè 2 alle 22:00)
Ho già effettuato delle ricerche, sopratutto sulla funzione millis(), ma tutti gli esempi si complicano. Il mio è logicamente semplice.
Quello che sono riuscito sin qui a fare è questo:

unsigned long secondi;
unsigned long minuti;
unsigned long ore;

void setup()
{
Serial.begin(9600);
}

void loop()
{
secondi=(millis()/1000);
minuti=((millis()/1000)/60);
ore=(((millis()/1000)/60)/60);

Serial.print("Secondi: ");
Serial.println(secondi);
Serial.print("Minuti: ");
Serial.println(minuti);
Serial.print("Ore: ");
Serial.println(ore);
Serial.println(" ");
delay(1000);
}

vorrei che i secondi venissero contati fino a 60 così come i minuti e le ore fino a 24 ovviamente.
inoltre arrivando alle 23:59:59 il tutto dovrebbe resettarsi.
Grazie in anticipo per un qualsiasi aiuto.

Puoi usare questa ottima libreria di @leo72 (uno degli admin del forum) :
http://www.leonardomiliani.com/2011/swrtc-un-orologio-in-tempo-reale-via-software/

La funzione millis() è un contatore di millisecondi che si resetta dopo 49,7 giorni, rendendo in pratica il tuo metodo inutilizzabile sulle "lunghe distanze", a prescindere dai problemi di precisione che la millis si porta dietro (essendo la fonte di clock del microcontrollore un risuonatore ceramico, ha una certa imprecisione, anche di diversi punti percentuale, per cui in un giorno puoi accumare ritardi nell'ordine dei minuti, o anche di più).

Detto questo, il controllo sull'accensione/spengimento di un dispositivo diventa un controllo su una tripletta di valori (ore:minuti:secondi): all'accensione, l'orario deve essere uguale o superiore a quello di partenza, allo spengimento deve essere uguale o maggiore a quello di fine.

Ti consiglio una ricerca sul forum perché l'argomento è stato trattato diverse altre volte, e ci sono alcune problematiche che non ho affrontato in questo post per semplicità di spiegazione.

PS:
se vuoi avere un orario "corretto", non puoi avere i secondi fino a 60 perché ogni minuto sarebbe così lungo 61 secondi (da 0 a 60) e non 60 (da 0 a 59).

Grazie per le info, sono riuscito ad utilizzare la libreria swRTC impostando un intervallo di tempo in cui attivare un pin.
Inoltre ho aggiunto un comando per mettere in HIGH lo stesso pin tramite pulsante:

#include <swRTC.h>
swRTC rtc; //create a new istance of the lib
const byte WITHOUT_SECONDS = 0;
const byte WITH_SECONDS = 1;
int minuti;
int ora;
int secondi;
int button;
int stato=0;

void setup() {
  Serial.begin(9600); //choose the serial speed here
	rtc.stopRTC(); //stop the RTC
	rtc.setTime(17,59,50); //set the time here
	rtc.setDate(16,9,2013); //set the date here
	rtc.startRTC(); //start the RTC
pinMode(7,INPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
	
}

void loop(){
  secondi=(rtc.getSeconds());
  minuti=(rtc.getMinutes());
  ora=(rtc.getHours());
  button= digitalRead(7);

Serial.print("Ora attuale     ");
Serial.print(ora);
Serial.print(" : ");
Serial.print(minuti);
Serial.print(" : ");
Serial.println(secondi);
Serial.print("Stato:   ");
Serial.println(stato);
delay(1000);

if((ora >= 8 && ora <= 17) || (button==HIGH)){ 
digitalWrite(3,HIGH);
stato=1;}
else
{
digitalWrite(3,LOW);
stato=0;
}
}

l'unico problema è che dopo aver pigiato il pulsante il pin resta in HIGH per pochi secondi e poi torna in LOW.
Avete qualche consiglio?

Mi sembra corretto. Tu inizializzi l'ora alle 17:59:50.
Dopo 10 secondi l'ora diventa 18:00:00 e perciò nell'if, ora <= 17 non è più vero

Giusto, e deve essere così. Ma essendo inserito dell' if il comando " ||(oppure) (button==HIGH) " dopo le 18 ad una pressione del pulsante il pin va in HIGH, anche qui giusto. Il problema è che dopo pochi secondi torna in LOW da solo, mentre io vorrei che ci andasse premendo nuovamente il pulsante.
Ho anche provato ad aggiungere un delay al pin in HIGH, ma questo arresta anche swRTC, rendendolo inutilizzabile.

Non vorrei scriverti la soluzione, sarebbe preferibile arrivarci da solo.
Ho scritto: "Dopo 10 secondi l'ora diventa 18:00:00 e perciò nell'if, ora <= 17 non è più vero"
Se non è vero, allora esegue quello che c'e' nell'else e quindi spegne
Il tutto indipendentemente dallo stato del pulsante. Perchè è un OR (oppure)

Il led è high se orario tra le 8 e le 17 OPPURE tasto high. Ma il tasto tu mica lo tieni premuto all'infinito. Lo hai premuto e poi rilasciato, giusto?

Dopo un pomeriggio di scervellamento e grazie a i vostri stimoli sono riuscito a fare funzionare il tutto, introducendo una variabile "stato", nel modo seguente:

#include <swRTC.h>
swRTC rtc; //create a new istance of the lib
const byte WITHOUT_SECONDS = 0;
const byte WITH_SECONDS = 1;
int minuti;
int ora;
int secondi;
int button_on;
int button_off;
int stato;

void setup() {
  Serial.begin(9600); //choose the serial speed here
	rtc.stopRTC(); //stop the RTC
	rtc.setTime(17,59,40); //set the time here
	rtc.setDate(16,9,2013); //set the date here
	rtc.startRTC(); //start the RTC
pinMode(7,INPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(6,INPUT);
stato=0;

	
}

void loop(){
  secondi=(rtc.getSeconds());
  minuti=(rtc.getMinutes());
  ora=(rtc.getHours());
  button_on= digitalRead(7);
  button_off= digitalRead(6);
 
 
  


Serial.print("Ora attuale     ");
Serial.print(ora);
Serial.print(" : ");
Serial.print(minuti);
Serial.print(" : ");
Serial.println(secondi);
Serial.print("Stato:   ");
Serial.println(stato);
delay(1000);

if(ora >= 8 && ora <= 17 && (stato==0 || stato==2)){ 
digitalWrite(3,HIGH);
digitalWrite(4,HIGH);
delay(70);
digitalWrite(4,LOW);
stato=1;
}
else if((ora < 8 || ora > 17) && (stato==1)){
  digitalWrite(3,LOW);
  digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
delay(50);
digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
  stato=2;
}
if(button_on==HIGH && (stato==2 || stato==0)){
digitalWrite(3,HIGH);
digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
stato=3;

}
if(button_off==HIGH && stato==3){
 digitalWrite(3,LOW);
  digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
delay(50);
digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
stato=2; 
}
}

Il sistema dovrà gestire una pompa da laghetto (attraverso relay) che si accenderà automaticamente nell'intervallo di tempo impostato, ma potrà essere azionata manualmente tramite i due pulsanti "button_on" e "button_off" al di fuori dell'intervallo di tempo precedente.
I due pulsanti saranno poi sostituiti da input provenienti da un kit IR (che non ho ancora a disposizione).
In fine altri comandi gestiranno due strisce di led da esterni per l'illuminazione.
Accetto ulteriori consigli e critiche.

Ps: il pin4 in output è un segnale sonoro tramite buzzer (so che il delay ad esso associato provoca un ritardo del sistema, ma lo reputo accettabile).

Un'altra soluzione, molto spesso citata nel forum, è quella di usare i timestamp. Un timestamp altro non è che il numero di secondi trascorsi da una certa data. Qualunque orario puoi trasformarlo in timestamp ed usando i timestamp i confronti si traducono in un paio di if perché devi fare un check su un solo valore invece che sulla tripletta ore:minuti:secondi.
La lib swRTC ha già integrati i metodi per gestire i timestamp per cui sei facilitato nel compito. :wink:

Ho giocherellato col tuo sketch. :grin:

#include <swRTC.h>

const byte BUTTON_ON = 7;
const byte BUTTON_OFF = 6;
const byte RELEUNO = 3;
const byte BUZZER = 4;

const byte  STARTTIME = 8;
const byte  ENDTIME = 17;

swRTC rtc; //create a new istance of the lib
const byte WITHOUT_SECONDS = 0;
const byte WITH_SECONDS = 1;

byte minuti;
byte ora;
byte secondi;
byte button_on;
byte button_off;
byte stato;

void setup() {
  Serial.begin(9600); //choose the serial speed here
  rtc.stopRTC(); //stop the RTC
  rtc.setTime(17,59,40); //set the time here
  rtc.setDate(16,9,2013); //set the date here
  rtc.startRTC(); //start the RTC
  pinMode(BUTTON_ON, INPUT);
  pinMode(BUTTON_OFF, INPUT);
  pinMode(RELEUNO, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  stato = 0;
}

void loop(){
  secondi = rtc.getSeconds();
  minuti = rtc.getMinutes();
  ora = rtc.getHours();
  button_on = digitalRead(BUTTON_ON);
  button_off = digitalRead(BUTTON_OFF);

  Serial.print(F("Ora attuale     "));
  Serial.print(ora);
  Serial.print(F(" : "));
  Serial.print(minuti);
  Serial.print(F(" : "));
  Serial.println(secondi);
  Serial.print(F("Stato:   "));
  Serial.println(stato);
  delay(1000);

  if(ora >= STARTTIME && ora <= ENDTIME && (stato==0 || stato==2)){ 
    digitalWrite(RELEUNO, HIGH);    
    buzz(3);
    stato=1;
  }
  else
    if((ora < STARTTIME || ora > ENDTIME) && (stato==1)){
      digitalWrite(RELEUNO, LOW);
      buzz(1);
      stato=2;
    }

  if(button_on==HIGH && (stato==2 || stato==0)){
    digitalWrite(RELEUNO, HIGH);
    buzz(2);
    stato=3;
  }

  if(button_off==HIGH && stato==3){
    digitalWrite(RELEUNO, LOW);
    buzz(1);
    stato=2; 
  }

} // End Loop


void buzz(byte type){
  switch(type) {
  case 1:
    digitalWrite(BUZZER, HIGH);
    delay(50);
    digitalWrite(BUZZER, LOW);
    delay(50);
    digitalWrite(BUZZER, HIGH);
    delay(50);
    digitalWrite(BUZZER, LOW);
    break;

  case 2:
    digitalWrite(BUZZER, HIGH);
    delay(50);
    digitalWrite(BUZZER, LOW);
    break;

  case 3:
    digitalWrite(BUZZER, HIGH);
    delay(70);
    digitalWrite(BUZZER, LOW);
    break;

  default:;
  }
}

wow... di alcuni comandi non conoscevo neanche l'esistenza :fearful:
Appena ho un attimo lo studio e lo provo un pò.
Oggi ho provato i relay con la striscia led e funge tutto alla perfezione, poi sono passato all'inserimento dei componenti in un scatola di derivazione, anche se manca sempre il kit IR.
Appena arriva avrò sicuramente bisogno di consigli.

Potresti iniziale a dare una lettura qui --> C (linguaggio): tutorial per imparare programmare | Guida HTML.it dal capitolo 11 in poi.
Anche se non tralascerei i primi capitoli.

E poi qui --> http://arduino.cc/en/Reference/HomePage