lampeggio variabile

Buonasera a tutti! dopo lo spavento di aver fritto arduino stasera mi son cimentato in un codice un po piu complesso (per me ignorante in materia). Ho tre pulsanti, con relatice resistenze e collegamenti giusti, e tre led. Vorrei farli accendere uno fisso, l'altro un lampeggio normale e l'altro ancora un lampeggio un po piu veloce. il primo led tutto ok, il secondo e il terzo si accendono quando premo il pulsante e poi si spengono e non lampeggiano. Dove sbaglio? ecco il codice. copiando il codice dall'ide con la funzione apposita me ne metteva la metà così ho copiato normalmente. vi ringrazio per la pazienza.. :)

int puls1=53;
int puls2=52;
int puls3=50;
int led1=13;
int led2=12;
int led3=11;
int stato1;
int stato2;
int stato3;
int val1=0;
int val2=0;
int val3=0;

void setup(){
 pinMode(puls1,INPUT);
 pinMode(puls2,INPUT);
 pinMode(puls3,INPUT);
 pinMode(led1,OUTPUT);
 pinMode(led2,OUTPUT);
 pinMode(led3,OUTPUT);
 Serial.begin(9600);
}

void loop(){
 stato1=digitalRead(puls1);
 if ((stato1==HIGH) and (val1==0)){
   digitalWrite(led1,HIGH);
   Serial.println("led 1 acceso");
   val1=1;
   delay(300);
 }
 else if ((stato1==HIGH) and (val1==1)){
   digitalWrite(led1,LOW);
   Serial.println("led 1 spento");
   val1=0;
   delay(300);
 }
 stato2=digitalRead(puls2);
 if ((stato2==HIGH) and (val2==0)){
   Serial.println("led 2 lampeggia piano");
   digitalWrite(led2,HIGH);
   delay(1000);
   digitalWrite(led2,LOW);
   delay(1000);
   val2=1;
 }
 else if ((stato2==HIGH) and (val2==1)){
   digitalWrite(led2,LOW);
   Serial.println("led 2 spento");
   delay(300);
   val2=0;
 }
 stato3=digitalRead(puls3);
 if ((stato3==1) and (val3==0)){
   digitalWrite(led3,HIGH);
   delay(500);
   digitalWrite(led3,LOW);
   delay(500);
   Serial.println("led 3 lampeggia veloce");
   val3=1;
   delay(300);
   }

 else if ((stato3==HIGH) and (val3==1)){
   digitalWrite(led3,LOW);
   Serial.println("led 3 spento");
   val3=0;
   delay(300);
   }

}

Togli tutti i dalay() e fai il lampeggio temporizzati con millis() vedi esempio blink without delay.

Ciao Uwe

Come ti ha detto Uwe, con i delay() non ne esci e, come suggerito ...

... devi a studiarti come si usa la millis() prima QUI, poi QUI ed infine leggi anche QUI e QUI ... vedrai che ti sarà tutto più chiaro ;)

Guglielmo

A parte usare la funzione mills(), dovresti separare la lettura dei pulsanti e cambiamento dello stato, con l'esecuzione del lampeggio, tu in un unico blocco if() "accendi e spegni tramite pulsante" cioè se voalore=0 diventa valore=1, di conseguenza il blocco e il lampeggio verranno eseguiti un unica volta.

// TUO CODICE


stato2=digitalRead(puls2);
 if ((stato2==HIGH) and (val2==0)){  //Premi il pulsante il led si accende si spegne, e poi non viene 
   Serial.println("led 2 lampeggia piano"); //piu eseguito
   digitalWrite(led2,HIGH);
   delay(1000);
   digitalWrite(led2,LOW);
   delay(1000);
   val2=1;
 }
 else if ((stato2==HIGH) and (val2==1)){
   digitalWrite(led2,LOW);
   Serial.println("led 2 spento");
   delay(300);
   val2=0;
 }


// Codice logicamente corretto


 stato2=digitalRead(puls2);
 if ((stato2==HIGH) ){  
     if(val2==0){
         val2=1;
         Serial.println("led 2 lampeggia piano");
     }
     else{
           val2=0;
           Serial.println("led spento");

     }
   
 }
 if(val2==1){//Premi il pulsante e val2 diventa 1, il loop() eseguirà sempre il lampeggio
                  // Fino alla nuova pressione del pulsante che porterà val2 a valore 0

      digitalWrite(led2,HIGH);
      delay(1000);
      digitalWrite(led2,LOW);
      delay(1000);
   

  }
  else{
   
       digitalWrite(led2,LOW);
}

col codice che mi hai indicato il led lampeggia ma sul monitor non esce la scritta led spento e il led rimane sempre acceso

Ma come mai il codice dell accensione e mantenimento di stato del led1 funziona bene e invece per il secondo pulsante e led non funziona? non e lo stesso passaggio? cambia solo il lampeggio…

289Ciao, intanto ribadisco che dovresti usare la funzione mills() come ti hanno indicato, non ho il codice che usi effettivamente e non so come è fatto il circuito, e a me pare che lo spezzone di codice che ti ho postato non abbia problemi;) dovrebbe funzionare cosi, premi una volta il secondo pulsane e il led si mette a lampeggiare inviando la scritta "led lampeggia piano" sulla seriale, premi di nuovo il secondo pulsante e il led rimane spento, inviando la scritta "spento" sulla seriale.

Riguardo il primo pulsante che a te pare faccia il suo dovere, col primo pulsante devi solo accendere o spegnere un led, di conseguenza se viene eseguito un unica volta ottieni quello che vuoi, col secondo pulsante tu vuoi far lampeggiare un led, per farlo devi eseguire di continuo il codice nel loop(), non basta eseguirlo un unica volta come per accenderlo e spegnerlo, in pratica sono situazioni molto diverse quella del primo pulsante e quella del secondo...

@cmigoni, vuoi provare qualcosa di nuovo e semplice?
Bene, la funzione delay() ti blocca in quel punto fino a che non trascorre il tempo desiderato, l’unica soluzione che ha arduino è usare la funzione millis() e qui tutti gli utenti partono con tre o quattro milioni di domande, pertanto ho deciso di creare una funzione adatta a tutti, semplice come delay().
Questa funzione l’ho chiamata delayAsync() come si può intuire dal nome non blocca l’intero codice ma fa proseguire.
Praticamente la funzione ritorna 0 se non è trascorso il tempo, altrimenti ritorna 1.
Ad esempio il tuo codice può essere trasformato cosi:

/*********************************************/
/* Delay Async v. beta                       */
/* vbextreme <vbextreme@vbextreme.netai.net> */  
/*********************************************/

uint8_t _delayAsync(uint8_t id, uint32_t ms)
{
    struct ellapsed
    {
        uint8_t id;
        uint32_t Mst;
        uint32_t mst;
        struct ellapsed* next;
    };
    static struct ellapsed* at = NULL;
    struct ellapsed* t;
    
    uint32_t mst = micros();
    uint32_t Mst = millis();
    
    if ( at && at->id == id )
    {
        if ( millis() - at->Mst >= ms - 1)
        {
            mst = at->mst;
            t = at;
            at = at->next;
            free(t);

            while ( micros() - mst < ms * 1000 );
            return 1;
        }
        return 0;
    }

    for ( t = at; t->next; t = t->next )
    {
        if ( t->next->id == id )
        {
            if ( millis() - t->next->Mst >= ms - 1)
            {
                mst = t->next->mst;
                struct ellapsed* r = t->next;
                t->next = t->next->next;
                free(r);
                
                while ( micros() - mst < ms * 1000 );
                return 1;
            }
            return 0;
        }
    }

    t = (struct ellapsed*) malloc( sizeof(struct ellapsed) );
    t->id = id;
    t->mst = mst;
    t->Mst = Mst;
    
    t->next = at;
    at = t;
    
    return 0;
}

#define delayAsync(MS) _delayAsync(__COUNTER__, MS)

/********************************************************************/

int puls1=53;
int puls2=52;
int puls3=50;
int led1=13;
int led2=12;
int led3=11;
int stato1;
int stato2;
int stato3;
int val1=0;
int val2=0;
int val3=0;

void setup(){
 pinMode(puls1,INPUT);
 pinMode(puls2,INPUT);
 pinMode(puls3,INPUT);
 pinMode(led1,OUTPUT);
 pinMode(led2,OUTPUT);
 pinMode(led3,OUTPUT);
 Serial.begin(9600);
}

void loop(){
  
  if ( digitalRead(puls1) == HIGH )
  {
      if ( delayAsync(300) == 1 )
      {
          digitalWrite(led1,val1);
          val1 = !val1;
      }
  }

  if ( digitalRead(puls2) == HIGH )
  {
      if ( delayAsync(1000) == 1 )
      {
          digitalWrite(led2,val2);
          val2 = !val2;
      }
  }

  if ( digitalRead(puls3) == HIGH )
  {
      if ( delayAsync(500) == 1 )
      {
          digitalWrite(led3,val3);
          val3 = !val3;
      }
  }
}

In questo modo il led1 lampeggia fino a che viene premuto il pulsante1 e cosi via per gli altri led.
Ora prova a modificarlo per come vuoi farlo lavorare te, anche perchè non sono riuscito a comprendere molto bene il problema.

orse tra un paio di anni riusciro a decifrare qualcosa… :confused: vi ringrazio tutti ugualmente!

tutto il codice sopra a /**********************************************/ non lo devi guardare! guarda solo la parte sotto, cosa non ti è chiaro?

Essendo peggio di un principiante non riesco a capire il procedimento. Forse sto correndo troppo o forse non son portato.. booh! cmq il codice l ho provato e mi restituisce questo messaggio di errore..

Arduino:1.6.7 (Linux), Scheda:"Arduino Mega ADK"

/tmp/arduino_f8f2b91a44c1223bca43d1373530fe42/sketch_dec27a.ino: In function 'void loop()': sketch_dec27a:28: error: 'delayAsync' was not declared in this scope if ( delayAsync(300) == 1 ) ^ sketch_dec27a:37: error: 'delayAsync' was not declared in this scope if ( delayAsync(1000) == 1 ) ^ sketch_dec27a:46: error: 'delayAsync' was not declared in this scope if ( delayAsync(500) == 1 ) ^ exit status 1 'delayAsync' was not declared in this scope

copia tutto il codice che ti ho postato, TUTTO, ma non fare caso a tutto il codice contenuto prima di /***************************/

fatto.. si accendono tutti e tre e restano fissi.. mi potresti spiegare passo passo cosa dici ad arduino? sempre se ti va e non sono invadente

cmigoni, se ti riferisci a quella funzione è programmazione avanzata, non ho capito bene come funziona, ma salva il tempo di ogni chiamata in una lista "particolare struttura dati", diciamo che molti studenti universitari al secondo anno in informatica farebbero fatica a capirla, e l' 80% di chi usa arduino anche :)

Visto che sono un autodidatta anche io, e penso che ti piacerebbe imparare a programmare, era più saggio usare la funzione mills() come mostrato dagli esempi che ti hanno linkato, http://www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/

Perché, con un po di pazienza avresti capito benissimo il suo funzionamento e quindi imparato qualcosa, ottenendo il risultato voluto, usare codice scritto da altri solo quando non se ne può fare a meno, altrimenti non potrai mai migliorare ;)

@cmigoni, vediamo di semplificarti la vita:
fase 1: scarica il file .zip in allegato e scompattalo nella directory “Arduino/libraries” o installalo cliccando nell’ide “sketch->inclusione librerie->aggiungi libreria da file zip”
ora hai insallato la delayAsync(), in questo modo hai il tuo codice pulito.

Nella precedente prova devi aver sbagliato qualcosa, il codice che ti ho passato era testato e collaudato, quindi assicurati di avere il pulsante e il led nei pin giusti, per sicurezza ho semplificato e rafforzato il codice.
Torniamo al tuo progetto, prima cosa lo semplfichiamo e gestiamo solo un led, faremo in modo che il led inizi a lampeggiare dopo la pressione di un tasto e smetta solo dopo la pressione sempre dello stesso pulsante.
vediamo il codice:

//includo la libreria di vbextreme
#include <delayAsync.h>

//pin dei pulsanti
int puls1 = 53;

//pin dei ped
int led1 = 13;

//stato indica se un led sta lampeggiando oppure no
int stato1 = 0;

//val indica se led è HIGH o LOW
int val1 = 0;

//funzione per gestire un pulsante
//il primo argomento è il pin dove è collegato il pulsante
//il secondo argomento HIGH se quando si preme il pulsante entra 5v in arduino
//                     LOW se quando si preme il pulsante non entra corrente in arduino
byte buttonPress(byte pin, byte ispress)
{
    if ( digitalRead(pin) != ispress ) return 0;
    delay(80);
    if ( digitalRead(pin) != ispress ) return 0;
    while(digitalRead(pin) == ispress );
    return 1;
}

//inizializzo tutto, pulsanti in input, led in output e seriale
void setup(){
    pinMode(puls1,INPUT);
    
    pinMode(led1,OUTPUT);
    
    Serial.begin(9600);
}


void loop(){
    //controllo il primo stato
    if ( stato1 == 0 )
    {
        //non lampeggio,
        //mi assicuro che il led sia spento:
        val1 = 0;
        digitalWrite(led1,val1);
        //controllo se il pulsante è stato premuto con la funzione buttonPress()
        //tale funzione ritorna 1 se premuto e 0 in caso contrario
        //quindi posso assegnarlo direttamente alla variabile di stato.
        stato1 = buttonPress(puls1, HIGH);        
    }
    else
    {
        //sto lampeggiando 
        if ( delayAsync(300) == 1 )
        {
            //è trascorso il tempo di 300ms cambio lo stato del led
            val1 = !val1;
            digitalWrite(led1,val1);
        }

        //controllo che non sia stato premuto il pulsante, in questo caso se viene premuto
        stato1 = buttonPress(puls1, HIGH);
        //ma dato che vogliamo disattivarlo alla pressione invertiamo lo stato
        stato1 = !stato1;
    }
}

ora prova a compilare, inviare e raccontaci cosa ti è difficile e cosa accade.

delayAsync.zip (1.25 KB)

grazie a tutti, appena ho un attimo ci provo!! :)