Lampeggio led con intervalli diversi con millis

Ciao a tutti, sto provando a fare lampeggiare un led con la funzione millis ma non voglio che rimanga acceso e spento per lo stesso tempo, vorrei che il led rimanesse acceso, per esempio, per un secondo e rimanesse spento per due. Il problema è che non riesco, o si spegne e riaccende subito o il contrario. Vi lascio lo sketch che ho fatto. Spero che qualcuno di voi possa aiutarmi. Grazie in anticipo! ;)

const int led = 13;
unsigned long precedente1 = 0;
unsigned long intervallo1 = 1000;
unsigned long precedente2 = 0;
unsigned long intervallo2 = 2000;
unsigned long adesso = 0;
  
void setup() {
  pinMode(led, OUTPUT);
}

void loop() {
  adesso = millis();
  if (adesso - precedente1 > intervallo1) {
    precedente1 = adesso;
    digitalWrite(led, HIGH);
  }
  
  adesso = millis();
  
  if (adesso - precedente2 > intervallo2) {
    precedente2 = adesso;
    digitalWrite(led, LOW);
  }
}

... devi condizionare le if (ed i tempi) ... allo stato del LED (ON/OFF) ... prova a ragionarci ;)

Guglielmo

Ciao, grazie per la dritta, ho provato aggiungendo una variabile "stato" ed ho aggiunto la condizione nell'if però non mi funziona lo stesso :'( . Ho anche provato a fare uno schemino cartaceo per capire a quali millisecondi accende e a quali spegne ma non sono riuscito a farlo funzionare. Potresti spiegarmi cosa intendi per condizionare i tempi? Grazie

const int led = 13;
unsigned long precedente1 = 0;
unsigned long intervallo1 = 1000;
unsigned long precedente2 = 0;
unsigned long intervallo2 = 2000;
unsigned long adesso = 0;
int stato = 1;
void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}

void loop() {
  adesso = millis();
  if ((adesso - precedente1 > intervallo1)&&(stato==0)) {
    precedente1 = adesso;
    digitalWrite(led, HIGH);
    stato=1-stato;
    Serial.print("\nACCESO ");
    Serial.print(stato);
  }
  
  adesso = millis();
  
  if ((adesso - precedente2 > intervallo2)&&(stato==1)) {
    precedente2 = adesso;
    digitalWrite(led, LOW);
    stato=1-stato;
    Serial.print("\nSPENTO ");
    Serial.print(stato);
  }
}

... allora, se tu devi stare acceso X millisec e spento Y millisec, prima di tutto dovrai avere una variabile in cui memorizzi se sei acceso o spento, poi ... i tempi non possono essere confrontati in contemporanea, il tempo di partenza del ON inizia quando finisce il tempo dell'OFF e viceversa ... altrimenti è chiaro che ti si accavallano le condizioni di ON e di OFF ;)

Ti è più chiaro ? :)

Guglielmo

P.S. : Hai già avuto modo di studiare come si usa la millis()? Eventualmente guarda prima QUI, poi QUI ed infine leggi anche QUI e QUI ;)

#define LED 13
#define SPENTO 0
#define ACCESO 1

byte stato = SPENTO;
unsigned long starttime;
unsigned long timeon = 1000;
unsigned long timeoff = 2000;

void setup()
{
    pinMode(LED,OUTPUT);
    digitalWrite(LED,stato);
    starttime = millis();
}

void loop()
{
    if ( !stato && millis() >= starttime + timeoff)
    {
        digitalWrite(LED,++stato);
        starttime = millis();
    }
    else if ( stato && millis() >= starttime + timeon)
    {
        digitalWrite(LED,--stato);
        starttime = millis();
    }
}

... >:( ... VB ... pensi che non fossi capace anche io a dargli la "pappa fatta" ? E cosa avrà imparato secondo te ? ? ?

La cosa peggiore che si può fare è postare codice già bello che fatto, poiché poi, la tentazione, da parte di chi fa domande di fare copia/incolla, è sicuramente forte ma il risultato è di aver imparato poco.

E' bene invece cercare di spiegare la teoria così che, chi pone le domande, si sforza, capisca/studia e riesce a realizzare da solo quello che vuole ... con il risultato che IMPARA !

Guglielmo

Ciao, Guglielmo la penso anche io come te :) , nonostante avessi il codice già pronto ho provato ugualmente a sistemare il mio e grazie alle tue dritte ci sono riuscito!! ;) Eccolo: (Forse ci sono delle parti inutili, adesso lo controllo bene ;) )

const int led = 13;
unsigned long precedente1 = 0;
unsigned long intervallo1 = 5000;
unsigned long precedente2 = 0;
unsigned long intervallo2 = 10000;
unsigned long adesso = 0;
int stato = 1;
void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}

void loop() {
  adesso = millis();
  if ((adesso - precedente1 > intervallo1)&&(stato==0)) {
    precedente1 = adesso;
    digitalWrite(led, HIGH);
    stato=1-stato;
    Serial.print("\nACCESO ");
    Serial.print(stato);
    precedente2=adesso;
  }
  
  adesso = millis();
  
  if ((adesso - precedente2 > intervallo2)&&(stato==1)) {
    precedente2 = adesso;
    digitalWrite(led, LOW);
    stato=1-stato;
    Serial.print("\nSPENTO ");
    Serial.print(stato);
    precedente1=adesso;
  }
}

Idano98: Ciao, Guglielmo la penso anche io come te :)

Ottimo :)

Si, credo che qualche cosetta potrai ottimizzare e magari anche ... rendere più elegante ;)

Ad esempio ricorda che puoi definire una variabile byte che può essere true o false ... molto comoda negli IF (... è già un valore logico) e che trasformi da true a false e viceversa con un semplice not booleano ( miaVar = !miaVar; ) ;)

Guglielmo

@guglielmo sono ormai 20 anni che cerco di aiutare sui forum! In questo caso specifico il codice è più che lecito dato che sta semplicemente studiando il linguaggio. Infine il FREE SOFTWARE si basa su questo! Non si impara solo sui libri, cosa che consigliere di fare all'utente, ma anche vedendo codice scritto da altri.

@Idano98 avresti potuto almeno leggere il codice e farti delle domande! infatti questa forma

adesso - precedente1 > intervallo1

è sbagliata!

C'è una canzone che recita: "Se non chiedi non ti sarà dato...."

vbextreme: @Idano98 avresti potuto almeno leggere il codice e farti delle domande! infatti questa forma

adesso - precedente1 > intervallo1

è sbagliata!

... a si VB ? e cosa ci sarebbe di sbagliato ? ? ?

Guglielmo

come ad esempio eliminare queste 3 var long pubbliche unsigned long precedente2 = 0; unsigned long intervallo2 = 10000; unsigned long adesso = 0;

la var "adesso" è inutile ed essendo 10000 un multiplo di 5000 puoi usare un ciclo millis solo

pablos: come ad esempio eliminare queste 3 var pubbliche unsigned long precedente2 = 0; unsigned long intervallo2 = 10000; unsigned long adesso = 0;

la var "adesso" è inutile ed essendo 10000 un multiplo di 5000 puoi usare un ciclo millis solo

... cos'è la serata dei "saputelli" ? ? ? :astonished:

... e la mia frase :

gpb01: Si, credo che qualche cosetta potrai ottimizzare e magari anche ... rendere più elegante ;)

... cosa pensate che stessa ad indicare a Idano98 ? ? ? :smiling_imp: :smiling_imp: :smiling_imp:

Vogliamo lasciare che gli utenti USINO la materia grigia invece che dirgli sempre cosa fare ?

Poi, se non ci riescono, li aiutiamo ... :)

Guglielmo

la millis() va da 0 a 4294967296 per poi tornare a 0 ora se lasciasse sempre accesa la scheda arriva magari a precedente = 4294967200 ora dopo 96 millisecondi passa a 0 e dunque 0 - 4294967200 da 3204008036 e quindi essendo maggiore di intervallo 1 scatta anche se sono passati solo 96 millisecondi, per quello va usata la forma adesso >= precedente + intervallo1 così facendo l'overflow ottenuto con la somma torna ad allinearsi con il tempo voluto. @gbp01 pertanto forse è meglio un pò di codice che tante piccole cose dette poco e male, è anche doveroso ricordare che i forum non sostituiscono i libri di testo sui quali va studiato il linguaggio.

vbextreme: dunque 0 - 4294967200 da 3204008036

Direi proprio di no visto che sono unsigned long, il risultato è 96.

@astro a mente mi sono sbagliato dovrebbe dare 3865470576.

prova:

void loop()
{
    unsigned long v = 0;
    unsigned long k = 429496720L;
    v -= k;
    Serial.println(v);
    delay(1000);
}

Almeno quello che sto affermando è quello che avviene nei mainstream poi magari in questi chipettini le cose cambiano, ma dubito fortemente.

quasi dimenticato:

    unsigned long v = 0;
    unsigned long k = ~0L;
    v -= k;

Questo secondo te quanto stampa? 00000000 00000000 00000000 00000000 - 11111111 11111111 11111111 11111111 = ? secondo te dovrebbe dare 0 e io invece dico che da 1, chi prova? non sono a casa.

VB ... vai a studiare bene come funzionano le MCU prima di "correggere" gli altri !

Sarai sicuramente un genio di Linux, non lo metto in dubbio, ... ma qui hai molto da imparare !!!

Comincia con il leggere QUESTO ... ;)

Guglielmo

Che giornata .... è il mese dei saputelli!!! :) :) Però gpb ultimamente gli utenti li stai caziando di brutto ... basta che poi non dite a me che sono scortese :)

pablos: Che giornata .... è il mese dei saputelli!!! :) :)

Guglielmo

pablos:
Però gpb ultimamente gli utenti li stai caziando di brutto … basta che poi non dite a me che sono scortese :slight_smile:

… no, solo quelli che agiscono d’impulso … senza considerare cosa è veramente utile per chi sta imparando :smiley: :smiley: :smiley:

Guglielmo

P.S. : Pablos, seriamente, credo di averlo scritto un’infinità di volte, ed anche qua sopra … quello che ricordo sempre ai più “navigati” (come te) è di NON postare codice già bello che fatto, poiché poi la tentazione, da parte di chi fa domande, di fare copia/incolla, è sicuramente forte ma il risultato è di aver imparato poco.

E’ bene invece cercare di spiegare la teoria così che, chi pone le domande, si sforza, capisca/studia e riesce a realizzare da solo quello che vuole … con il risultato che IMPARA :slight_smile:

Ritengo infatti che lo scopo del forum e della comunità sia “far crescere” le persone, non fornirgli “pappa fatta” per cui, alla prossima difficoltà … sono da capo a dodici ! :wink: