Chiedo consigli per completare il mio sketch per realizzare un treno di impulsi

Buongiorno, sono alle primissime armi (e ore) con arduino e la programmazione in wiring, scrivo per chiedere qualche consiglio per completare la sequenza di impulsi come da sketch (che parte dopo che si è premuto il pulsante).
Vorrei che dopo 15 minuti di questa sequenza ( 5 impulsi uguali e un periodo di pausa di 280 msec) il pin 13 vada HIGH e ci rimanga 15 minuti poi ancora 15 minuti di sequenza e 15 minuti di pin 13 high. al termine dopo 1 ora ( le 4 sequenze da 15 minuti) e cioè da quando si è premuto il pulsante si deve fermare tutto e il pin 13 deve rimanere sempre basso. poi eventualmente il ciclo riprende se ripremiamo il pulsante
Poi il passo successivo sarà implemetare un display che conta i minuti da quando si preme il pulsante ma per quello proverò a studiarmi qualcosa prima. mi accontenterei per il momento di accendere un led quando si preme il pulsante di start e un led ogni 15 minuti. poi dopo un ora i 4 led si spengono.

questo lo sketch che ho fatto e che vorrei implementare come ho scritto sopra.

ringrazio per eventuai suggerimenti magari con qualche dettaglio visto la mia inesperienza

Daniele

const byte LED = 13 ;
const byte PULSANTE = 2 ;

void setup() {
pinMode (LED, OUTPUT);
pinMode (PULSANTE, INPUT) ;
while ( digitalRead (PULSANTE) ==LOW) {}

}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite (LED, HIGH) ;
delay (25) ;
digitalWrite (LED, LOW) ;
delay (25) ;
digitalWrite (LED, HIGH) ;
delay (25) ;
digitalWrite (LED, LOW) ;
delay (25) ;
digitalWrite (LED, HIGH) ;
delay (25) ;
digitalWrite (LED, LOW) ;
delay (25) ;
digitalWrite (LED, HIGH) ;
delay (25) ;
digitalWrite (LED, LOW) ;
delay (25) ;
digitalWrite (LED, HIGH) ;
delay (25) ;
digitalWrite (LED, LOW) ;
delay (280) ;
}

>supermago: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More → Modify che si trova in basso a destra del tuo post) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

Domanda: conosci i cicli for?
Se si puoi mettere quello che ti dico in un for che giri due volte
Inoltre puoi mettere in un for che ne giri abbastanza (non ho fatto il calcolo, ma immagino tu sappia quanti impulsi vuoi), ed in questo secondo for dentro nel primo ci metti un impulso, che verrà generato tante volte quante gira il for.
Dopo il secondo for ma nel primo accendi il pin 13 e lo lasci acceso per quanto ti serve.

Ricorda che delay misura in millisecondi.

So che verrebbe meglio con millis(), ma per la prima fase non é necessaria, e sembra che non tutti la capiscano

Io invece trovo che si risolverebbe ottimamente con la funzione millis() e variabili falg;

Sul forum o in rete, trovi esempi di come creare un contatore di tempo con la funzione millis().

E una variabile flag, è una variabile che assume due valori vero o falso, uno o zero.

Se tu metti la sequenza di impulsi dentro un if(flag), gli impulsi saranno eseguiti solo quando la variabile vale 1, e non eseguiti quando vale zero.

Poi crei un contatore di tempo con millis(), che ogni 15 minuti inverte il valore della variabile flag, quindi per 15 minuti esegue gli impulsi, per quindi minuti non esegue.

Poi un secondo contatore e una seconda variabile flag, che conta un ora, eseguo tutto dopo un ora cesso dei eseguire.

Ti posso aiutare, ma prima perché tu possa imparare, e perché tu possa avere soddisfazione del tuo lavoro, è meglio se provi a realizzarlo da solo :slight_smile:

... aggiungo solo ... per capire le basi con cui si usa millis() consiglio prima la lettura di QUESTO post esplicativo, dopo di che lo studio di come si usa la funzione millis(), prima QUI, poi QUI e QUI e QUI e tutti gli articoli che sono in QUESTA pagina ... alla fine il tutto dovrebbe essere più chiaro :slight_smile:

Guglielmo

Aggiungo, che il conteggio del tempo tramite funzione millis() non è precisissimo, se in un conteggio di 15 minuti avremmo un errore di secondi, nel conteggio di 1 ora, avremo un errore di qualche minuto.

In molti progetti può andare bene un conteggio del tempo approssimato, ma dove occorre molta precisione bisogna usare un rtc.

Aggiungo che sapere se quei valori di tempo sono stringenti o meno può indirizzare verso una soluzione o l'altra. Ad esempio in 15 minuti non c'è un numero intero di quelle trame, quindi:

  • Le trame possono/devono interrompersi esattamente allo scadere dei 15 minuti?
  • La trama in corso può terminare anche se sono trascorsi i 15 minuti?
  • Il tutto deve durare esattamente un'ora oppure qualche secondo in più o in meno non fa differenza?

Ringrazio tutti per i consigli. il prox post metterò il codice nella modalità come da regolamento. avevo letto (velocemente) come bisogna fare ma sinceramente non ho ancora capito bene...tornerò a riprovarci
Per Claudio _FF: qualche secondo di sbaglio su un ora di tempo totale non è un problema. sono sequenze di impulsi che adeguatamente amplificati, vorrei applicare ad un solenoide per una specie di magnetoterapia pertanto non è richiesta una precisione assoluta sulla durata della "terapia" ( i 15 minuti per ciclo) ma deve essere molto precisa invece la durata dei singoli impulsi ( 5 impulsi di 25 msec con duty cycle del 50% seguiti da 280 msec di pausa e via di questo passo per 15 minuti.) . potrei anche sapere quante sequenze di impulsi ci sono in un quarto d'ora ed usare un contatore che si incrementa visto che so che la durata della singola sequenza ciclo che è di 250+280 msec. Al raggiungimento del numero di impulsi prefissato l'uscita va HIGHT per starci 15 min con un delay appropriato (900.000 msec) poi ricomincia il ciclo. forse in questa maniera si rende più preciso il tutto ma ripeto non importa che spacchiamo il secondo.. Ho una idea a blocchi del come fare ma poi devo ancora capire nello specifico come fare.

Ok, allora un treno sono 250+280 ms (e non 225+280 come sembrava dal primo sketch).

1698 treni durano 899.94 s (15 minuti con un errore di 0.06 s)

Ma qui arriva l’imprecisione dell’oscillatore non quarzato che si riflette sui risultati delle funzioni delay, millis, micros.

Sul mio ArduinoProMini ad esempio i tempi risultano alterati dello 0.12%, circa quattro secondi e mezzo all’ora.

Questo credo sia il meglio che si può ottenere se la struttura del programma, per come viene scritto, non va ad introdurre ulteriori ritardi (che possono invece influire di parecchi punti percentuali, ad esempio usare delay per produrre piccoli tempi periodici porta ad almeno 10 minuti di errore all’ora).

La misura di tempo più precisa è fornita dalla funzione micros (che funziona come millis ma riporta i microsecondi (con un jitter di ±4µs) invece che i millisecondi, per cui ha una risoluzione almeno 250 volte migliore, cioè gli impulsi alla fine avranno complessivamente circa 50 µs di errore).

Un’idea può essere quella di creare una base tempi costante per il programma usando micros, ad esempio di 5 millisecondi (solo perché è un sottomultiplo di 25):

//*********************************************************
void elabora()  // funzione chiamata 200 volte al secondo
{
    digitalWrite(13, !digitalRead(13));
}
//*********************************************************
void setup()
{
    pinMode(13, OUTPUT);
}
//*********************************************************
void loop()
{
    static unsigned long t = 0;
    if(micros() - t >= 5000) 
    { 
        elabora(); 
        t += 5000; 
    }
}
//*********************************************************

L’unico vincolo con questa soluzione è che la funzione elabora non duri MAI più di 5 ms, naturalmente sono possibili altre soluzioni, ma sempre usando la funzione micros per contare il tempo con la maggior precisione possibile.

Per il resto nella elabora si possono usare variabili contatore, variabili stato ecc. per ottenere i tempi voluti e modificare comportamento al raggiungimento di specifici timeout.

Così a occhio mi sembra che la soluzione più semplice sia una sezione che legge il pulsante e genera i quattro tempi da 15 minuti, e un’altra, comandata dalla prima, che genera i treni.