Sto tentando di staccare un relè dopo un certo numero di impulsi generati da un apposito contatore.
Sono riuscito a commutare il relè dopo 2 impulsi (in questo esempio) e fin qui nessun problema.
Ora sto tentando di cambiare lo stato del relè di nuovo dopo essere passato un certo periodo di tempo ( 2000 millisecondi in questo esempio).
Purtroppo come al solito mi trovo in difficoltà a lavorare sulle funzioni temporali di Arduino ( Utilizzo un ArduinoMega2560) . Dopo molte prove prendendo spunti su siti, tutorial, manuali etc.. continuo a percorrere la via dell'insuccesso dell'esperimento. Questo è il codice che ne è uscito stamani ( ancora non funzionante).
Ho provato anche ad usare la sola differenza di tempo tra 2 variabili di cui una unsigned long .... = millis() dichiarata dopo il loop e chiedendo di ripristinare il pin 8 da 1 a 0 dopo che il valore della differenza superi i 2000 millisecondi
#define relepin 8
#define interval 2000
int value = LOW;
long previusMillis = 0;
int i;
bool stato;
void setup() {
pinMode (3, INPUT_PULLUP);
pinMode (relepin, OUTPUT);
Serial.begin (9600);
}
void loop() {
unsigned long tempo = millis();
if (digitalRead(3) == true && stato == true){
i ++;
stato = false;
}
else if (digitalRead(3) == false) {
stato = true;
}
if (i == 2){
digitalWrite (8, 1);
}
if (digitalRead (8) == HIGH){
previusMillis = tempo;
}
if (tempo - previusMillis > interval){
digitalWrite (8, 0);
}
}
Potreste per favore aiutarmi a capire dove sbaglio e indirizzarmi verso la retta via?
Grazie.
Beh, che dire..
nel tuo codice errori ve ne sono parecchi
mio fratello dice che hai fatto errori una riga si e una no
io sono meno drastico, alcuni li considero problemi di stile
partiamo dai più gravi
ricarichi il tempo previusmillis "ad ogni ciclo", dovresti farlo solo all'inserzione
previusmillis è del tipo sbagliato
non riporti mai a zero il contatore
non è chiaro cosa deve succedere se un impulso arrivasse nei due secondi di pausa
il resto sono di stile
mischi numeri e costanti simboliche (un pin 8 e uno relepin)
usi costanti simboliche minuscole
usi la elseif che "non è mai" più chiara che esplicitare i vari rami
ripeti la digitlaread invece di memorizzarne il valore
indenti pessimamente
da ultimo una domanda "hardware"
hai previsto un debounce?
No, non ho previsto nessun debounce.
Per quanto riguarda il punto numero 4 non ci sono impulsi nei secondi di pausa poiché questi impulsi vengono emessi da un contatore apposito quando viene erogata corrente. Quindi una volta che il relè commuta non vi è più passaggio di corrente e non c'è alcun impulso.
Il punto 3 invece credo sia proprio ciò di cui ho bisogno. Ho notato ora che quando voglio partire a contare una differenza di tempo tra 2 variabili non uso il codice corretto grazie a questi print sul monitor seriale.
long attesa = 0;
int i;
bool stato;
void setup() {
pinMode (3, INPUT_PULLUP);
pinMode (8, OUTPUT);
Serial.begin (9600);
}
void loop() {
unsigned long tempo = millis();
if (digitalRead(3) == true && stato == true){
i ++;
stato = false;
}
else if (digitalRead(3) == false) {
stato = true;
}
if (i == 2){
digitalWrite (8, HIGH);
}
if (digitalRead(8) == HIGH){
attesa = tempo;
}
Serial.print("Valore attesa ");
Serial.print ( attesa);
Serial.print ("Valore tempo");
Serial.println(tempo);
}
sapete dirmi come posso portare il valore attesa uguale a quello del tempo istantaneo di tempo senza che si incrementi in maniera tale da fare la differenza tra di essi e dichiarando che una volta raggiunto il valore di differenza di 2000 si può cambiare lo stato del pin da HIGH a LOW?
Trovo problemi anche nel riportare il valore di i a 0 dopo che si ricambia di stato per poter procedere nel loop.
Mi spiego meglio.
Una mappa schematica sarebbe questa:
Avvio il circuito (c'è assorbimento di corrente);
Conto gli impulsi ( so quanto watt sono stati erogati);
Stacco il relè ad un certo numero di impulsi;
Attendo un certo periodo di tempo;
Ricomincio il ciclo da capo.
Questo però dovrà essere abbinato ad un altro codice con un altra funzione quindi il delay o il break non vanno bene, almeno credo...
Ok, il problema è "agganciarti" agli istanti di tempo in cui avvengono le cose.
Hai giustamente scritto un "edge detect" per riconoscere i fronti di salita dell'impulso (per ora diamo per scontato che sia un impulso digitale pulito senza rimbalzi elettromeccanici, altrimenti serve anche un debounce, hardware o software).
Ad ogni fronte incrementi il contatore, ed è in questo stesso punto che va fatto il controllo sul raggiungimento della soglia, l'attivazione del relé, e la memorizzazione del tempo di partenza. Da questo istante inizia il conteggio. Per semplificare si potrebbe usare un'altra variabile stato per indicare questa nuova fase.
E solo quando questa fase è attiva si controlla se il tempo è trascorso, e, nel caso, si spegne il relé, si riazzera il contatore impulsi, e naturalmente si resetta la variabile di fase.
EDIT: anzi, non serve neppure un'altra variabile di fase, basta rileggere se il relé è attivo: