[RISOLTO] lampeggio led con funzione millis() con tempi On e OFF diversi

Salve a tutti, mi chiamo Michele.

Sono alle prime armi con arduino anche se è un po che ci traffico..ma non si finisce mai di imparare... e mi trovo in difficoltà con questo "semplice" (per voi) sketch e vi chiedo il vostro aiuto!

Come da titolo ho necessità di mettere in HIGH e LOW un'uscita di arduino con tempistiche indipendenti utilizzando la funzione millis().

Questo è lo sketch che ho provato a bozzare:

unsigned long pmillis1 = 0; // previusMillis1
unsigned long pmillis2 = 0; // previousMillis2
unsigned long time1 = 300; // time LED ON
unsigned long time2 = 300; // time LED OFF

void setup() {

pinMode(13, OUTPUT);
}

void loop()
{
if (millis() - pmillis1 >= time1) {
pmillis1=millis();
digitalWrite (13,HIGH);
}

if (millis() - pmillis2 >= time2) {
pmillis2=millis();
digitalWrite (13, LOW);
}
}

Il problema è che il led sulla pcb di arduino, lampeggia, ma in maniera instabile! Non riesco ad avere un lampeggio scandito..anzi, facendo diverse prove con tempi piu brevi o lunghi vedo che sfarfalla tra un lampeggio e l'altro..come mai secondo voi? :confused:

Questo sketch lo devo implementare poi in un altro programma piu complesso..e siccome in questo programma avrò tempi di ON dell'ordine di mS e di OFF anche di 1 minuto..durante il quale non posso bloccare il microprocessore, ho bisogno della funzione millis().

Ho provato a cercare su internet..ma anche altri sketch che ho trovato hanno lo stesso problema oppure hanno la stessa durata tra LED ON e LED OFF perchè viene usata un variabile boolean.

Spero qualcuno riesca a darmi la dritta giusta!!
Grazie
Michele

ah, aggiungo che vorrei raggirare l'overflow visto che la scheda rimarrà accesa finché non crepa..e vedendo per internet..questo sistema dell'if dovrebbe evitare questo problema in base a quello che ho trovato qui:

http://www.leonardomiliani.com/2012/come-gestire-loverflow-di-millis/

questo perchè appunto, questo schema lo devo implementare in un programma piu complesso..

Nel tuo sketch il led viene acceso e spento praticamente nello stesso momento. Ti propongo un approccio un po' diverso, in cui si aspetta un evento, quindi si calcola quando scatenare il prossimo:

unsigned long pmillis = 0;  // previusMillis1
const unsigned long timeOn = 300;  // time LED ON
const unsigned long timeOff = 700;  // time LED OFF

int led_level = LOW;
int nextEventTime = 0;

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  if (millis() - pmillis >= nextEventTime) {
    pmillis = millis ();
    
    if (led_level) {
      nextEventTime = timeOff;
    } else {
      nextEventTime = timeOn;
    }
    led_level = !led_level;
    
    digitalWrite (13, led_level);
  }
}

Una volta che hai capito la logica ci occuperemo di gestire l'overflow :).

PS: Usa i tag per il codice!

Grandissimo! :wink:

in pratica il mio primo if veniva sempre eseguito allo scadere del time on, giusto? e poi si ripeteva..accavallandosi con time off...

Ho modificato il nextEventTime con una unsigned long..per tempi di quakche minuto..posso chiederti perchè const unsigned long?

grazie!

Siccome sono nuovo..dove trovo la funzione tag?? :o non ho mai scritto nei forum..non sono esperto..

il tag code può essere l'icona </> oppure a seconda del forum usaro.
In alternativa si usa manualmente il tag bbcode corrispondente
[ c o d e]...[ / c o d e]
senza spazi

const indica al compilatore che quella variabile non cambierà mai nel corso del programma. Questo gli permetterà di segnalarti un errore nel caso tu provi a cambiarla e, in alcuni casi, gli permetterà di effettuare certe ottimizzazioni. Non è fondamentale, ma... perché no? :wink:

Ma il titolo l'hai scritto così per i non vedenti?

eh si..ero disperato pablos!! :grin:

invece..stavo rivedendo il codice..perchè è stato messo:

    if (led_level) {
      nextEventTime = timeOff;
    } else {
      nextEventTime = timeOn;
    }
    led_level = !led_level;

cioè..l'if cosa controlla??verifica se la variabile led_level è? :o

Controlla se è HIGH, ovvero se il led è acceso, nel qual caso il prossimo evento avverrà una volta passato il tempo di spegnimento.

ah ok..grazie!

chiedo un'altra info..senza aprire altro post..forse sbaglierò :confused:

ho cercato ma senza risultati..ovvero..l'argomento viene raggirato perchè meglio usare millis che delay..ma per me non è così..

in pratica quando lancio una funzione nel programma, quella funzione dev'essere eseguita tutta rispettando il tempo di delay che viene impostato nel menù anche se i segnali esterni dell'arduino cambiano.

Il problema è che se nel menù imposto un tempo x (byte x=0;) ..poi lo moltiplico per 1000 e la salvo nella variabile unsigned long time1=0, quando richiamo il delay(time1) tutto funziona bene se la variabile time1 sta sotto i 32000...invece se scrivo delay(40000) funziona bene..perchè secondo voi? :frowning:

Sei sicuro che sia unsigned long la variabile?

si..sicurissimo..

uso la byte per visualizzare nel display lcd (quindi da 0 a 255). Mi va bene anche per memorizzarla nella eprom.

però poi per avere le tempistiche da secondi, moltiplico la variabile time1 che l'ho messa apposta unsigned long.
Però se la variabile byte è 32..quindi time1=32000...il delay funziona bene..se metto 34 quindi 34000 il processore non risponde piu..

sembrerebbe un problema appunto di dichiarazione di variabile (32..32767 integer)..ma è unsigned long..

provo a stampare sull'lcd la variabile time1..vediamo come si comporta..

ricapitolando..
il codice semplificato è:

byte N=0;
unsigned long time1=0;
time1=N x 1000; //moltiplicazione per ottenere i secondi
lcd.print(time1);
delay(time1);

ecco..ho stampato la varibile time1 sull'lcd.

Se N vale 33..la variabile time1 vale (udite udite): 4294934760
Se N vale 32..la variabile time1 vale (udite udite): 32000

La variabile N la vedo sul display quindi di quella non ho dubbio..

Ho fatto la prova del nove saltando la variabile..ovvero:

delay(N*1000)...stesso problema...se metto N=32 funziona..se metto 33 non va..
ma se metto delay(33000) funziona benissimo!!

come si può spiegare sta cosa? :o

che abbia problemi la variabile byte?

Prova a mettere 1000UL al posti di 1000.

sei un grande!! :sunglasses: :sunglasses: :sunglasses:

mi spieghi per favore cos'è UL? mai sentito!!

comunque ho provato prima a mettere la variabile N integer perche pensavo fosse un conflitto moltiplicare byte..ma dava lo stesso problema..
con UL tutto risolto!! :wink:

Credo che il C/C++ interpreti le costanti numeriche come signed int, in mancanza di diverse indicazioni, il che sballa i tuoi calcoli, che necessitano di interi senza segno. Il suffisso UL forza il compilatore a interpretare il numero come unsigned long.

(Non sono sicuro che sia esattamente così, non ho mai memorizzato le varie interpretazioni/conversioni implicite, ma in ogni caso la realtà non può essere tanto distante 8))

grande!! Sei stato di grande aiuto!Grazie!

Spero di essere di aiuto pure io (quando aumenterò la mia esperienza) per altri del forum!!

Ciao raga!