programmazione timer arduino mega

salve a tutti, parto con le mie mille domande! ho un progetto in mente da realizzare che in seguito publicherò nella sezione adeguata e pongo la mia domanda, sono giorni che giro in rete ma non ho trovato nulla!!! allora la mia domanda è questa: ho bisogno che arduino mi accenda/spegne un led da un pin (esempio pin 20) tutti i giorni a una determinata ora e me lo deve spegnere in un'altra poi in un'altro pin (esempio pin 21 ) me lo accenda una volta a settimana in una determinata ora e me lo deve spegnere in un'altra al momento sono a questo punto, il display mi visualizza quanto segue

sereste così gentili da farmi un esempio su come impostare il programma

Qualche consiglio …
… per fare confronti ed altro senza impiccarti con il calcoli, usa il tempo in formato “Epoch” (Unix) così puoi fare direttamente somme, sottrazioni e confronti :wink:

Poi, per fare cicli NON bloccanti impara a usare la millis() … studia QUI e QUI

Infine NON fare confronti == ma sempre >= e <= … o il tempo giusto … è raro che lo imbrocchi :grin: :grin: :grin:

Guglielmo

premetto che mastico un po di informatica ma il linguaggio di ARDUINO è totalmente diverso dal mio
e faccio veramente fatica a farmi capire, dalla mia parte c’è il mio io che non molla, dall’altra c’è arduino che non nè vuole sapere!!! booooo vedremo chi la spunta
al momento sono arrivato a un buon punto ma ora viene il bello: accendere un led ( nel mio caso con il pin 13 ) a una determinata ora e visto che non riesco a capire dove sbaglio ho deciso di rendervi partecipi alla mia nuova avventura
magari tra voi c’è qualcuno che parla l’arduiniano, io ivece non parlo manco tanto bene l’italiano hahahahaahah
che dire aspetto le vostre risposte in merito e sotto ho fatto un copia incolla del programma a cui sto lavorando da settimane
spero che qualche buon uomo mi corregga il mio errore anche se l’errore non me lo da!

#include "Wire.h"
#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68

int ledPin = 13;
// 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) );
}

// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(0x80);
Wire.endTransmission();
}*/

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}


void setup()
{
pinMode(ledPin, OUTPUT);
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
Serial.begin(9600);

// Modificare i seguenti valori per impostare il vostro orologio ad ogni avvio del programma.
// Probabilmente si desidera impostare solo l'orologio una volta e quindi rimuovere
// la chiamata setDateDs1307 .
/*
second = 00;
minute = 59;
hour = 13;
dayOfWeek = 7;
dayOfMonth = 11;
month = 5;
year = 14;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);// chiamata per settare l'orologio
*/
}

void loop()

/*
{

byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
lcd.begin(16, 2);
lcd.print(hour, DEC);
lcd.print(":");
lcd.print(minute, DEC);
lcd.print(":");
lcd.print(second, DEC);
lcd.setCursor(0, 1);
lcd.print( dayOfMonth, DEC);
lcd.print("/");
lcd.print(month, DEC);
lcd.print("/");
lcd.print(year, DEC);
lcd.setCursor(10, 1);
lcd.print("CIAO");



delay(1000);

}
*/



{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
lcd.begin(16, 2);
lcd.clear(); // clear LCD screen
lcd.setCursor(3,0);
lcd.print(" ");
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)

if( hour >= 22 && minute >= 17);
{
digitalWrite(ledPin ,HIGH);
}
if( hour >= 22 && minute >= 18);
{
digitalWrite(ledPin ,LOW);
}


{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
lcd.setCursor(0,1);
lcd.print(" ");
switch(dayOfWeek){
case 1:
lcd.print("Lun");
break;
case 2:
lcd.print("Mar");
break;
case 3:
lcd.print("Mer");
break;
case 4:
lcd.print("Gio");
break;
case 5:
lcd.print("Ven");
break;
case 6:
lcd.print("Sab");
break;
case 7:
lcd.print("Dom");
break;
}
lcd.print(" ");
lcd.print(dayOfMonth, DEC);
lcd.print("/");
if (month<10)
{
lcd.print("0");
}
lcd.print(month, DEC);
lcd.print("/20");
lcd.print(year, DEC);
delay(1000);
}

Non so quanto di quel codice è farina del tuo sacco, per cui mi concentro soltanto sul controllo condizione if.

if( (hour >= 22) && (minute >= 17) );     // <-- quel ; si deve togliere
{
     digitalWrite(ledPin ,HIGH);
}

Il codice sopra valuta se && (and) tra due espressioni (hour >= 22) e (minute >= 17) sia vero o falso.
Quando hour è >= 22, (hour >= 22) == true (vero)
if ( vero && (minute >= 17) ) {
;
}
Quando minute è >= 17, (minute >= 17) == true
if (vero && vero) {
// esegue il codice perché vero && vero == vero
// accendi il led
}

Per farla breve, rimuovi il ; nella condizione if ( condizione )
Questo >= quello mettili tra parentesi tonde di modo che prima viene risolto il valore di ogni sotto espressione
per finire alla ultima (vero && vero)

if (minute<10)
A che serve?
Secondo me è un refuso da compia incolla.

Dimenticavo c’è un modo per formattare il codice e postarlo direttamente nel forum, cerca tra le opzioni di Arduino IDE. Il codice formattato appare con i rientri e se non ricordo male ti verifica se manca qualche parentesi.

gpb01 ti consigliava di trasformare la data, l’orario ecc in un valore numerico a 32 bit in modo simile a ciò che avviene in Unix per rendere più semplici le espressioni condizionali if.
La semplicità sarebbe simile alla seguente:
if (currentTime >= TriggerTime ) {
accendi il led
}

Come dire: se il tempo attuale >= il tempo della sveglia, fai qualcosa.

Se non sai da dove cominciare per trasformare i dati di RTC in time stamp unix, procedi nel modo che hai intuito.

Se sistemi il codice che hai usato, sarà corretto formalmente ma non funzionerà comunque, perché (mi sento il Celeste):
( hour >= 22 && minute >= 17) vero se sono le ore 22:17, 22:18, 22:19 ecc
( hour >= 22 && minute >= 18) vero se sono le ore 22:18, 22:19 ecc
Il primo è vero e il secondo e falso, ma quando il secondo diventa vero lo è anche il primo e invece deve
essere mutualmente esclusivo.

Ciao.

mi accodo a quanto detto da @mautotec per dirti due cose.

1) Esistono anche librerie apposite, vedi ad esempio la TimeAlarms http://playground.arduino.cc/Code/Time che sono fatte per rendere la vita piu' semplice

2) Se vuoi continuare su quella strada, sposta il controllo dell'allarme in fondo allo sketch, prima del delay(1000), li' dove lo hai inserito ti fa' sballare la visulizzazione dei minuti sul display

voglio iniziare con il ringraziare coloro che mi hanno dato una mano e che me la daranno in futuro ho fatto delle variazioni e sembra funzionante ma ho un problema, e mi concentro su questa if, perchè altre ad eccitare i relè in quel determinato tempo qgni tanto arduino me lo accende anche da solo senza rispettare l'orario impostato

  if( (hour == 19)==true && (minute == 44)==true &&(second == 20)==true)
  if( true&&true&&true )
{
  digitalWrite(Relay_neon_sud_est, LOW);
}
  if( (hour == 19)==true && (minute == 45)==true &&(second == 53)==true)
  if( true&&true&&true ) 
{
  digitalWrite(Relay_neon_sud_est, HIGH);
}

secondo voi dove ho commesso l'errore

Forse è meglio scrivere if innestate.

Intanto il risultato delle if quale? accendere un pin o spegnerlo, quindi partiamo con il concetto seguente e vediamo dove ci porta.

Pseudo codice if ( il pin è acceso ) { fai altri controlli sul tempo e agisci per spegnere, altrimenti non fare nulla } else if (pin spento) { fai altri controlli sul tempo e agisci per accendere, altrimenti non fare nulla }

Controllo sul tempo: hour = 19, minute = 44, second = 20.

if (   (hour ==19) && (minutes == 44)   )  { // first if
       if (second >=20)  { // second if

                 digitalWrite(Relay_neon_sud_est, LOW);  // spegne
       
       } // second if
} // first if

hour = 19, minute = 45, second = 53

if ( (hour ==19) && (minutes == 45) ) { // first if if (second >=53) { // second if

digitalWrite(Relay_neon_sud_est, HIGH); // accende

} // second if } // first if

Come vedi c'è duplicazione di codice e inoltre hour, minute, second e action (cioè accendi o spegni) sono i dati che cambiano per cui si potrebbe pensare di creare una funzione a cui passare gli argomenti che cambiano e scrivere il controllo così:

if ( il pin è acceso ) { chiama funzione di controllo azione( hour, minute, second, SwitchOffAction ) } else if (pin spento) { chiama funzione di controllo azione( hour, minute, second, SwitchOnAction ) }

if ( il pin è acceso ) { chiama funzione di controllo azione( 19, 44, 20, SwitchOffAction ) } else if (pin spento) { chiama funzione di controllo azione( 19, 45, 53, SwitchOnAction ) }

La funzione (dagli il nome che ti pare): updateNeonOutSE( byte h, byte m, byte s, bool action) { if ( (hour == s) && (minute == m ) ) { // first if if (second >=s) { // second if

digitalWrite(Relay_neon_sud_est, action); // accende

} // second if } // first if }

Devi trovare il modo per completare la seguente porzione di codice: if ( il pin è acceso ) { chiama funzione di controllo azione( 19, 44, 20, SwitchOffAction ) } else if (pin spento) { chiama funzione di controllo azione( 19, 45, 53, SwitchOnAction ) }

Non so se funzione digitalRead() per leggere lo stato di un pin di output, se funziona il codice seguente dovrebbe funzionare:

if (digitalRead(Relay_neon_sud_est) == HIGH )  {
    updateNeonOutSE( 19, 44, 20, LOW );  // spegne
} else if (digitalRead(Relay_neon_sud_est) == LOW )  {
    updateNeonOutSE( 19, 45, 53, HIGH );  // accende
}

Il codice che hai scritto non ha senso:

if( true&&true&&true )

Il risultato è sempre vero.

(hour == 19)==true

Non è necessario esplicitarlo anzi crea confusione. ( questo == quello ) sarà valutato come true o false l'importante che quando si uniscono insieme delle espressioni con && ogni sotto espressione sia racchiusa in (). Come nel codice di sopra che riporto qui in versione modificata:

 if (   (hour == s) && 
         (minute == m )  && 
         (second >=s)   ) 
{
                digitalWrite(Relay_neon_sud_est, action);  // accende
      
}

Come ogni subespressione è tra parantesi e tutta è contenuta tra parentesi della if

Ciao.

ho dato una risistemata al codice seguendo i vostri consigli potreste verificare se ora va bene?

  if( (hour == 17) && (minute == 15) &&(second == 00)==true)  
{
  digitalWrite(Relay_HQI_sud, LOW);
}
  else if( (hour == 18) && (minute == 15) &&(second == 30)==true)  
{
  digitalWrite(Relay_HQI_sud, HIGH);
}

altra cosa che ho notato e che l'orologio del RTC scappa un po avanti (tipo 10 secondi al giorno) rispetto a quello del pc mi sapete dire perchè?

E' dato dalla qualità del quarzo usato e dello stesso RTC. Se vuoi qualcosa di più preciso devi comprare uno di quei chip RTC termocompensati dove l'integrato controlla anche la temperatura (che influisce sull'oscillazione del quarzo) ed applica una correzione per tenere la frequenza esattamente precisa. Solo che costano 10 volte tanto un normale RTC. Dipende se spendere 20 euri valgono quei 10 secondi al giorno ;)

Vedo che quello che ho scritto non ti è stato utile, peccato.

&&(second == 30)==true)

perché uguale a true, comunque e solo una questione di forma alla fine funziona sempre allo stesso modo.

Se per coincidenza il codice viene eseguito quando second == 29 e per 2 secondi non viene eseguito, il match e l’azione la perdi.

Infine NON fare confronti == ma sempre >= e <= … o il tempo giusto … è raro che lo imbrocchi smiley-mr-green smiley-mr-green smiley-mr-green

Ciao.

intanto grazie per le risposte......e vi pongo un altra domanda: ho impostato delle ore in maniera casuale per fare accendere dei ralay, esempoi

//********************************* TIMER GIORNALIERO *********************************

//---------------------------------- NEON SUD OVEST ----------------------------------- if( (hour == 20) && (minute == 54) &&(second == 00)==true) { digitalWrite(Relay_neon_sud_ovest, LOW); } else if( (hour == 20) && (minute == 59) &&(second == 30)==true) { digitalWrite(Relay_neon_sud_ovest, HIGH); }

se notate mi accende alle 20:54:00 e mi spegne alle 20:59:30 e fin qui tutto ok, se non fosse che in qualche caso arduino mi ignora l'ora e mi fa accendere il relay anche per esempio alle 21:54:00 e mi spegne 21:29:30 secondo voi come mai? allego l'intero progetto, magari ci capite dove sbaglio!!!! grazie in anticipo.

sbagli qui

if( (hour == 20) && (minute == 54) &&(second == 00)==true)

Anche se non è un vero e proprio errore, considera che il programma ha uno svolgimento veloce ma a volte non sufficiente a intercettare tutto, nell'orario hai inserito anche i secondi ... sono davvero importanti nel tuo timer?

Ti dico questo perchè?? ipotizziamo che il tuo ON sia alle ore 23:10:30 e per qualche motivo il tuo programma non passa a leggere 30 (secondi) ma legge il 31 .... salta tutto, sei nei limiti troppo ristretti

Quindi le cose sono 2: elimini i secondi e lavori su ore e minuti o utilizzi il > di n (ma non sulle ore altrimenti sarà attivo anche nelle ore successive)

quando le letture sui tempi sono molto brevi come i secondi dovrebbero essere fatte non su == ma su > di Ridurrai di molto la possibilità di errore

ciao

diciamo che per quanto riguarda l’accensione delle lampade, i secondi sono irrilevanti !!! ma preferirei che ci fossero…
il problema sorge quando mi si deve attivare una pompa dosatrice perche in base ai secondi mi pompa un X di ml e di sicuro non può essere una cosa forfettaria, con la dosatrice diciamo che sto sui 3-4 ml al dì ed è pari ad una accensione di 3-4 secondi
che alla fine della storia se una volta arduino non leggesse i secondi non farebbe nemmeno nulla per un giorno
ma se la cosa è ripetitiva?

quindi ricapitolando se non ho capito male mi consigliate di modificare in questo modo:

//********************************* TIMER GIORNALIERO *********************************

//---------------------------------- NEON SUD OVEST -----------------------------------
if( (hour == 20) && (minute == 54) &&(second >= 00)==true)
{
digitalWrite(Relay_neon_sud_ovest, LOW);
}
else if( (hour == 20) && (minute == 59) &&(second >= 30)==true)
{
digitalWrite(Relay_neon_sud_ovest, HIGH);
}

ragazi mi sono accorto che il mio RTC corre troppo, cioè un minuto la fa in 50 secondi reali anche se li segna tutti e 60 però sono piu veloci ora la domanda è : esiste un metodo per rallentare il quarzo di 10 secondi?

Ni, cioè il mio RTCC mcp79410 può essere tarato, il tuo ? dipende da qual’è il chip usato e la scheda su cui è montato. 10 secondi ogni minuto sono davvero eccessivi per un RTCC, comunque ad occhio se riscaldi il quarzo il clock diminuisce e se lo raffreddi aumenta.

Posta un link alla tua scheda RTCC, così posso documentarmi.

Ciao.

questo è RTC che ho usato http://www.ebay.it/itm/230993139734?ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1423.l2649 ma il quarzo lo riscaldo come? basta farlo una sola volta?

E' un semplice DS1307, non può essere tarato. Potresti provare a dissaldare il quarzino ed a cambiarlo. E' probabile che la causa dell'imprecisione sia lui.

questo secondo voi è meglio? http://www.ebay.it/itm/MCP-RTC-Microchip-MCP79410-PIC-AVR-Arduino-Real-Time-Clock-module-from-EU-/171178593877 si puo tarare?

Va calibrato, ma manualmente. A te servirebbe più un RTC termocompensato, dove l'aggiustamento della frequenza la fa lo stesso RTC. Tipo il DS3231 o simili. Però costano un botto. Non fai prima a provare a cambiare il quarzo al tuo modulo?