variazione delay con un pulsante

Ciao a tutti, sono un bel pò ignorante in tutto quello che riguarda l'elettronica e ho un problema con lo sketch del progettino che sto provando a portare a termine.
In sostanza vorrei fare accendere 32 led consecutivamente alla pressione di un tasto o comunque sia un input e poterne variare la durata. Per i 32 led da collegare ad arduino ho usato due integrati tlc5940 collegati in serie tra loro e modificando lo sketch basic della libreria per il tlc5940 riesco a comandarli alla pressione del tasto, in sostanza mi parte la sequenza dei 32 led. A parte che l'ultimo dei 32 led mi rimane acceso a fine sequenza e non capisco il perchè mi son reso conto che avevo la necessità di qualcos'altro per variare il delay tra l'accensione di un led e l'altro.
Allora ho optato per un secondo pulsante con un display 7 segmenti che mi dovrebbe far variare il tempo variando anche la numerazione sul 7 segmenti, solo che dopo aver scritto lo sketch che ora vi allego il risultato è che alla pressione del pulsante per variare il tempo sul display compare la numerazione ma parte automaticamente la sequenza, per fortuna variando i tempi come voluto, ma non capisco perchè non aspetti l'input per far partire la sequenza...
questo è lo sketch:

 #include "Tlc5940.h"
int pinbutton = 0;  //input partenza
int pintimer = 1;  //input regolazione timer
int counter = 0;  //variabile stato pulsante timer
int laststate = 0;  //stato pulsante timer
int timerstate = 0;  //stato del timer
int stato = 0;  //stato input partenza
int ultimo = 0;
int a = 4; //pin 7 segmenti
int b = 5;
int c = 7;
int d = 8;
int e = 12;
int f = 2;
int g = 6;
int timer;  //variabile per il delay


void setup()
{
  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(pinbutton, INPUT);
  pinMode(pintimer, INPUT);
  /* Call Tlc.init() to setup the tlc.
     You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
  Tlc.init();
  
}

/* This loop will create a Knight Rider-like effect if you have LEDs plugged
   into all the TLC outputs.  NUM_TLCS is defined in "tlc_config.h" in the
   library folder.  After editing tlc_config.h for your setup, delete the
   Tlc5940.o file to save the changes. */

void loop(){ 
  //lettura pulsante per timer
 timerstate =digitalRead(pintimer);
  delay(50);
  if(timerstate != laststate) {
    if(timerstate = HIGH) {
      
         if(counter<=9) counter++; //contatore da 0 a 9
        
         else {counter=0;}
         switch (counter){ //risultato alla pressione del tasto
         case 0:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, HIGH);
         break;
         case 1:
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(a, HIGH);
         digitalWrite(d, HIGH);
         digitalWrite(e, HIGH);
         digitalWrite(f, HIGH);
         digitalWrite(g, HIGH);
         timer = 100;
         break;

         case 2:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(g, LOW);
         digitalWrite(e, LOW);
         digitalWrite(d, LOW);
         digitalWrite(c, HIGH);
         digitalWrite(f, HIGH);
         timer = 200;
         break;

         case 3:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(g, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, HIGH);
         digitalWrite(f, HIGH);
         timer = 300;
         break;
         
         case 4:
         digitalWrite(a, HIGH);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, HIGH);
         digitalWrite(e, HIGH);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 400;
         break;

         case 5:
         digitalWrite(a, LOW);
         digitalWrite(b, HIGH);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, HIGH);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 500;
         break;
         
         case 6:
         digitalWrite(a, LOW);
         digitalWrite(b, HIGH);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 600;
         break;
         
         case 7:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, HIGH);
         digitalWrite(e, HIGH);
         digitalWrite(f, HIGH);
         digitalWrite(g, HIGH);
         timer = 700;
         break;
         
         case 8:
          digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 800;
         break;
         
         case 9:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, HIGH);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 900;
         break;
         
         case 10:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, HIGH);
         digitalWrite(d, HIGH);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         break;
         
         
         }
    }

 stato = digitalRead(pinbutton);{
 delay(200);
  if(stato != ultimo){
  if (stato==HIGH)
  {
    int direction = 1;
  for (int channel = 0; channel < NUM_TLCS * 16; channel ++) {

    /* Tlc.clear() sets all the grayscale values to zero, but does not send
       them to the TLCs.  To actually send the data, call Tlc.update() */
    Tlc.clear();

    /* Tlc.set(channel (0-15), value (0-4095)) sets the grayscale value for
       one channel (15 is OUT15 on the first TLC, if multiple TLCs are daisy-
       chained, then channel = 16 would be OUT0 of the second TLC, etc.).

       value goes from off (0) to always on (4095).

       Like Tlc.clear(), this function only sets up the data, Tlc.update()
       will send the data. */
     if (channel == 0) {
      direction = 1;
    } else {
      Tlc.set(channel - 1, 0);
    }
    Tlc.set(channel, 4095);
   

    /* Tlc.update() sends the data to the TLCs.  This is when the LEDs will
       actually change. */
    
Tlc.update();
    delay(timer);
  
  }}}}}}

per favore aiutatemi a capire in cosa sbaglio o se ho bisogno di usare altre funzioni per avere due azioni distinte e separate

edit by mod: per favore includi il codice usando gli appositi tag

Il "case = 10" non imposta la variabile timer come nel caso di case 9 e gli altri, questo è voluto o no?

Dovresti usare delay() solo in caso di ritardi di tempo ridotti, perchè la chiamate delay impegna il microcontroller ad eseguire null'altro che il codice presente nell funzione delay, allo scadere del termnine la torna ad eseguire la riga successiva alla chiamata.

Per evitare questo spreco di risorse esiste la funzione millis() o micros(), questa ritorna un valore long che contiene il tempo espresso in millesimi di secondo conteggiato dal momento in cui la scheda viene alimentata al momento in cui avviene la chimata a funzione millis(). In sostanza ogni millesimo di secondo questa la variabile ritornata da millis() contiene una unità in più, se salvi il valore e poi fai dei confronti puoi stabilire se è o meno passato x millessimi.

Nell'ide c'è l'esempio blink senza delay dove viene mostrato il pattern comune di millis().

Ciao.

Ti ringrazio per la risposta. Per quel che attiene il case 10 in effetti non avevo ancora specificato niente, però al riguardo allo spreco di risorse non è che mi importi tanto al momento, per me l'importante è che con un pulsante faccio apparire il numero sul display che dovrebbe indicare un timer tra l'accensione di un led ed un altro, solo che come ho cercato di spiegare prima quando provo a variare il timer premendo il pulsante automaticamente parte la sequenza led e ciò non dovrebbe avvenire.
Intanto mi documenterò sull'uso di millis che in effetti non mi è chiaro, premetto che inizialmente ho fatto già un bello sforzo a legare la partenza della sequenza led con il tlc5940 alla pressione di un pulsante, ma ora che cerco di creare un'altra funzione solo per variare il delay delle sequenze mi sono impantanato daccapo.
Ciao e ancora grazie

Spesso si dice: prima di imparare a correre impara a camminare e ancora prima impara a stare in piedi.

Cosa significa?

Nel conteso, significa fai accendere e spegnere un led a tempo, es 1s accesso e 2s spento, e fai questo senza usare driver led. Questo è imparare a stare in piedi.

Introduci un led dopo l'altro e quindi prova a fare accendere 2 led con tempi di accensione e spegimento diversi, poi prova a fare accendere dei led in sequenza ecc. Questo è imparare a camminare.

Per correre devi sapere come funziona il driver led, come funziona il linguaggio C/C++, sapere che guando il microcontroller è impegnato a fare qualcosa non può contemporaneamente fare altro, es. durante un delay(20000) il microcontroller sarà impegnato a contare fino ad un tempo di 20s e non è possibile ad esempio intercettare la pressione di un pulsante esterno. La funzione millis() è fondamentale e chi sta in piedi deve conoscerla bene altrimenti non si spiega come stia in piedi, figuriamoci se poi vuole correre.

Ricordati che stai programmando un microcontroller idiota con ridotte risorse, che può fare una sola cosa per volta (non è sempre così) e che non hai i servizi di sistema che trovi sul PC perchè non c'è sistema operativo. Per dirla in termini automobilistici, non c'è AST, ABS, CTS e tutti gli altri sistemi che ti permettono di andare veloce senza uscire fuori strada, ecco immaginati una vecchia 500 fiat con il motore della Ferrari.

Segui il consiglio, così programmare sarà divertimento puro e non uno strazio.

Ciao.

Grazie ancora per la risposta, sapevo che prima o poi avrei ricevuto parole simili, ma devo ammettere che volevo scrivere già io quanto mi hai detto, ahimè sono così, inizio a stare male appena in piedi e già voglio correre.
Però a riguardo del microcontrollore, io non volevo che facesse più cose contemporaneamente, ad ogni pressione del pulsante timer doveva incrementare un numero sul display fino a 9 e stabilire il "timer" a seconda del case da collegarsi nel delay della sequenza led del tlc5940, ma purtroppo lo sketch così come compilato da me fa eseguire ad arduino più operazioni di quante io gliene abbia chieste.
Comunque proverò a seguire il tuo consiglio e ripartire da zero anche se è un pò complicato per me..
Ancora grazie

Provo a commentare il codice, perchè vedi io non riesco a leggerlo, non è identato correttamente, i nomi delle variabili non mi tornano.

 #include "Tlc5940.h"

// int vale 16 bit ed è con il segno, se devi usare una variabile di stato 0 o 1, il tipo deve essere boolean, byte, o uint8_t
// comunque un tipo senza segno e di dimenzioni minime cioè 8 bit. 
// lascio così int perchè lungo il codice non so realmente come verranno usare queste variabili.
// Non dire ma me non importa l'efficenza, perchè a me importa leggerlo il codice e questo è illegibile
// Nomi di variabile, pinButton0, no pintimer perchè altrimenti io penso che ci hai connesso un timer a questo pin
// CamelCase in C++ è usato molto. I nomi di variabile cominciano con minuscolo e ogni parola che compone il nome inizia con la
// maiuscola come appunto 'lastState'
int pinbutton = 0;  //input partenza
int pintimer = 1;  //input regolazione timer
int counter = 0;  //variabile stato pulsante timer
int laststate = 0;  //stato pulsante timer
int timerstate = 0;  //stato del timer
int stato = 0;  //stato input partenza
int ultimo = 0;                                     // ultimo il film con raul bowa? ultimo cosa?
// Pin map seven segment to arduino
//      seven segment                             Arduino pin
byte  a                                             = 4; 
byte  b                                             = 5;
byte  c                                             = 7;
byte  d                                             = 8;
byte  e                                             = 12;
byte  f                                              = 2;
byte  g                                             = 6;
// Ho cambiato il tipo da int a byte. Non voglio essere pesante ma andrebbero messi tutte le variabili in una struct
// struct SevenSegment {
         byte aSegment;
         byte bSegment;
         // ecc
};

// poi crei variabile di tipo SevenSegment così:
// struct SevenSegment aSevenSegment;
// e accedi ad ogni membro con aSevenSegment.aSegment = 4
// ci sono varianti di uso di struct che sono più idonee quando hai un solo display, come nel tuo caso

int timer;  //variabile per il delay

void setup()
{
  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(pinbutton, INPUT);
  pinMode(pintimer, INPUT);
  /* Call Tlc.init() to setup the tlc.
     You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
  Tlc.init();
  
}

/* This loop will create a Knight Rider-like effect if you have LEDs plugged
   into all the TLC outputs.  NUM_TLCS is defined in "tlc_config.h" in the
   library folder.  After editing tlc_config.h for your setup, delete the
   Tlc5940.o file to save the changes. */

void loop(){ 
  //lettura pulsante per timer
 timerstate =digitalRead(pintimer);   // stato del timer, io per timer conosco quelli interni al microcontroller o quelli software
  delay(50);
  if(timerstate != laststate) {            // laststate sarà sempre zero, non aggiorni il valore in nessun posto del codice
    if(timerstate = HIGH) {                // verifica la condizione di assegnamento se è vera, cioè se l'assegnamento di timerstate = HIGH
                                                       // ha valore logico vero esegui il codice, si usa alle volte ma altre è un errore, forse volevi fare
                                                       // if ( timerState == HIGH )
      
         // così ora si può leggere e capire in 10ms
         if(counter<=9) 
             counter++; 
        else
             counter=0;
//  mi fermo qui perchè domani mi devo alzare alle 8 e sono le 3 di notte.
//  Riparti da zero, con i tutorial e scrivilo tu il codice da zero senza copiarlo, analizzalo e riscrivilo 
//  Capisci questo codice? spiegalo a parole tue.
//  if (!stato)
//       stato = HIGH;
//    else 
//       stato = LOW;  

         switch ( counter ) { //risultato alla pressione del tasto
         case 0:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, HIGH);
         break;
         case 1:
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(a, HIGH);
         digitalWrite(d, HIGH);
         digitalWrite(e, HIGH);
         digitalWrite(f, HIGH);
         digitalWrite(g, HIGH);
         timer = 100;
         break;

         case 2:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(g, LOW);
         digitalWrite(e, LOW);
         digitalWrite(d, LOW);
         digitalWrite(c, HIGH);
         digitalWrite(f, HIGH);
         timer = 200;
         break;

         case 3:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(g, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, HIGH);
         digitalWrite(f, HIGH);
         timer = 300;
         break;
         
         case 4:
         digitalWrite(a, HIGH);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, HIGH);
         digitalWrite(e, HIGH);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 400;
         break;

         case 5:
         digitalWrite(a, LOW);
         digitalWrite(b, HIGH);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, HIGH);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 500;
         break;
         
         case 6:
         digitalWrite(a, LOW);
         digitalWrite(b, HIGH);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 600;
         break;
         
         case 7:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, HIGH);
         digitalWrite(e, HIGH);
         digitalWrite(f, HIGH);
         digitalWrite(g, HIGH);
         timer = 700;
         break;
         
         case 8:
          digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 800;
         break;
         
         case 9:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, LOW);
         digitalWrite(d, LOW);
         digitalWrite(e, HIGH);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         timer = 900;
         break;
         
         case 10:
         digitalWrite(a, LOW);
         digitalWrite(b, LOW);
         digitalWrite(c, HIGH);
         digitalWrite(d, HIGH);
         digitalWrite(e, LOW);
         digitalWrite(f, LOW);
         digitalWrite(g, LOW);
         break;
         
         
         }
    }

 stato = digitalRead(pinbutton);{
 delay(200);
  if(stato != ultimo){
  if (stato==HIGH)
  {
    int direction = 1;
  for (int channel = 0; channel < NUM_TLCS * 16; channel ++) {

    /* Tlc.clear() sets all the grayscale values to zero, but does not send
       them to the TLCs.  To actually send the data, call Tlc.update() */
    Tlc.clear();

    /* Tlc.set(channel (0-15), value (0-4095)) sets the grayscale value for
       one channel (15 is OUT15 on the first TLC, if multiple TLCs are daisy-
       chained, then channel = 16 would be OUT0 of the second TLC, etc.).

       value goes from off (0) to always on (4095).

       Like Tlc.clear(), this function only sets up the data, Tlc.update()
       will send the data. */
     if (channel == 0) {
      direction = 1;
    } else {
      Tlc.set(channel - 1, 0);
    }
    Tlc.set(channel, 4095);
   

    /* Tlc.update() sends the data to the TLCs.  This is when the LEDs will
       actually change. */
    
Tlc.update();
    delay(timer);
  
  }}}}}}

Ancora grazie MauroTec, sia per la risposta sia per l'aiuto che mi stai dando, sai non è semplice per un commercialista capire certe cose se non inizio da 0 nello studio.
Per quel che attiene la parte di codice che mi hai scritto

if (!stato)
stato = HIGH;
else
stato = LOW;

leggendo sul sito di arduino ho capito che stai confrontando se stato è vero o falso, se stato è falso, diventa HIGH se è vero diventa LOW, almeno questo ho capito.

Se non ho capito male quando assegno i pin da utilizzare all'inizio dello sketch, utilizzare int è uno spreco se si tratta di capire se un bottone è premuto o no e accendere dei led non in pwm, quindi sarebbe come assegnare uno 0 o un 1??? potrei usare byte come hai fatto per assegnare i pin del 7 segmenti??
Intanto ora vedo un pò come creare l'array per l'accensione del 7 segmenti, anche se credo che userò un 74HC595 per ridurre il numero dei pin, se no così non ci stà più niente su arduino.
Nel pomeriggio inizierò a riscrivere il codice con tutto il tag necessario anche se ancora non mi è ben chiaro l'uso della funzione struct, ho letto qualcosina ma non ho ancora capito bene come strutturarla. dopo faccio una prova e la allego qui e vediamo.

La struct non è necessaria, ma utile, quindi se ne può fare a meno quando non si ha padronanza del linguaggio.
Quindi ne farai a meno tu, perchè il primo obbiettivo è :fallo funzionare, come non importa.
Tuttavia il codice confuso è comprensibile solo a te e per un breve periodo di tempo, se non leggi il codice che tu hai creato per 2 mesi, inizialmente non ne capirai nulla e andrai in confusione, insomma è quasi come leggere il codice scritto da un'altro.

Quando il codice è scritto bene tutti quelli che conoscono il linguagio sono in grado di capire il codice come se leggessero un libro, un romanzo o altro. C'è un limite, quando i progetti diventano grandi come ad es il kernel linux, si barcolla con il rischio di cadere nella confusione. Nel tuo caso il codice è semplice. Divide et impera Divide et impera - Wikipedia

Lo sviluppo si esegue per passi, si testa e si procede per il prossimo passo, nel tuo caso dovresti evitare l'uso di una libreria di funzioni scritta da un altro di cui non hai garanzie, per questo ti consiglio di scrivere il programma ridotto con i led connessi ad arduino attraverso la resistenza di degenerazione per ogni led del valore di 330 ohm. Puoi usare fino ad 8 led per semplicità.

Il primo passo è fare in modo che i pulsanti funzionino entrambe e quindi devi scrivere il codice per un pulsante testi e poi passi all'altro. Quando apporti modifiche hardware o software introduci delle varianti, queste possono compromettere il funzionamento di quello che già è stato testato. Quando è il momento di introdurre l'accensione dei led ti accontenterai di accendere un led per volta o al massimo 2, questo ti aiuta ad avere meno codice davanti da scorrere e ti offre una migliore panoramica. Quando si scrive codice in un solo tab può capitare di avere codice che è in relazione stretta posto ad estremità opposte, questo è da evitare.

I cicli while for, le if annidate o no, ecc devono essere non più grandi di una schermata, il motivo è che guardando il ciclo, dove inizia il blocco { e dove finisce } in un solo colpo si comprende il funzionamento. Se si va di fretta, si può estendere inizio e fine } oltre la schermata, con la promessa a se stessi di trovare una soluzione più in là, perchè prima il codice devo farlo funzionare.

Sono tutti consiglio da applicare, ma non tutti insieme nello stesso momento, andrebbe fatto uno studio passo passo. Sono sicuro che più in là ti ricorderai quello che hai letto qui e troverai il modo di applicarlo.

Un ritardo di accensione tra due led può essere inserito tra le istruzioni digitalWrite():

1: digitalWrite(LED0, HIGH)
2: delay(1000);      // il microcontroller resta fermo qui per un secondo terminato il quale passa ad eseguire quello che c'è scritto dopo
                             // il delay. Se usi 10 led prima che il codice a riga 1: venga eseguito passeranno 10 secondi
                             // se devi nel frattempo intercettare la pressione del pulsante il codice necessario verra eseguito ogni 10 secondi.
                             // millis() risolve il problema.
3: digitalWrite(LED1, HIGH)

Ciao.

Allora, al momento sono partito con la creazione di uno sketch da 0, con gli 8 led e 2 pulsanti, solo che al momento c'è l'utilizzo di un solo pulsante. ecco lo sketch:

//devo far accendere 8 led in sequenza

//definisco il bottone 1
int pinButton1 = 2; //indico che il bottone 1 che servità da input per la partenza della sequenza è sul pin 2 di arduino
int buttonState1 = 0; //stato attuale del bottone 1
int lastState1 = 0; //vecchio stato del bottone 1

//definisco il bottone 2
int pinButton2 = 3; //indico che il bottone 2  che mi servirà per variare il delay e' sul pin 3 di arduino
int buttonState2 = 0; //stato attuale del bottone 2
int lastState2 = 0; //vecchio stato del bottone 2

//definisco gli 8 led
int led1 = 4;
int led2 = 5;
int led3 = 6;
int led4 = 7;
int led5 = 8;
int led6 = 9;
int led7 = 10;
int led8 = 11;

void setup(){
  //inizializzo i pin di input
  pinMode(pinButton1, INPUT);
  pinMode(pinButton2, INPUT);
  //inizializzo i pin di output
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  pinMode(led7, OUTPUT);
  pinMode(led8, OUTPUT);
}

void loo(){
  buttonState1 = digitalRead(pinButton1); //legge la pressione del tasto 1
  delay(50);  // antirimbalzo per lettura pulsante
  //compare lo stato attuale con lo stato iniziale
  if(buttonState1 != lastState1){
    
    if(buttonState1 == HIGH){  //se il bottone 1 è alto
    
    digitalWrite(led1, HIGH); //accende il led 1 
    
    delay(100); //pausa di 0,100 secondi
    
    digitalWrite(led1, LOW); //spegne il led 1
    digitalWrite(led2, HIGH); //accende il led 2
    
    delay(100); //pausa di 0,100
    
    digitalWrite(led2, LOW);  //spegne il led 2
    digitalWrite(led3, HIGH);  //accende il led3
    
    delay(100); //pausa
    
    digitalWrite(led3, LOW);
    digitalWrite(led4, HIGH);
    
    delay(100);
    
    digitalWrite(led4, LOW);
    digitalWrite(led5, HIGH);
    
    delay(100);
    
    digitalWrite(led5, LOW);
    digitalWrite(led6, HIGH);
    
    delay(100);
    
    digitalWrite(led6, LOW);
    digitalWrite(led7, HIGH);
    
    delay(100);
    
    digitalWrite(led7, LOW);
    digitalWrite(led8, HIGH);
    
    delay(100);
    }
    
   else 
   digitalWrite(led8, LOW);//spengo il led 8
   }
  }

edit by mod: per favore includere il codice usando gli appositi tag

sinceramente non l'ho ancora provato sulla board ma l'ide non mi dà errore.
stasera lo proverò per vedere se gli 8 led si accendono come dovrebbero.
ciao a dopo

Ho realizzato i collegamenti e provato lo sketch che ho allegato prima, solo che mancava la lettera p al loop e rimaneva acceso comunque il led 8 anche se avevo messo la else, allora ho modificato togliendo l'else e inserendo un altro digitalRead(led8, LOW) ed ora alla pressione del tasto i led si accendono in sequenza con un ritardo di 0,10 secondi.
Ora per la legge del Divide et Impera dovrei passare al secondo punto del problema.
Stabilire dei delay da 0,100 a 0,900 che dovrebbero cambiare in base alla pressione del tasto 2.
Giusto?

Divide et Impera, è un dogma, le leggi le puoi trasgredire le religioni no, cioè significa non essere religiosi e la mia religione è divide et impera.

Questa è la fase "fallo funzionare, non importa come", questo non vuol dire scrivere codice che poi per leggerlo mette in difficoltà anche te.

Divide et impera in questo contesto significa, tutti i problemi di qualunque dimensioni possono essere risolti dividendo il problema principale in sotto-problemi più piccoli e gestibile. Ad ogni divisione si deve definire il sotto-problema. Il sotto-problema a sua volta potrebbe essere divisibile, se lo è non è il momento di risolverlo e quindi bisogna reiterare il processo di divisione.

Sembra una lezione di ingegneria del software, purtroppo non lo è e non può esserlo perchè anche un corso richiede la divisione del problema principale in sotto-problemi che poi è la singola lezione ed è tale perchè si è deciso superfluo sottoporla ad un nuovo processo di divisione.

Tu ora il programma lo devi studiare, perfezionare, renderlo più compatto, più flessibile, mantenendo la leggibilità del codice, scontrandoti con i vincoli programmatici quali ad es i vincoli temporali (quella cosa deve essere compiuta in non più di 10ms), che alle volte costringono a sacrificare la leggibilità e/o la flessibilità. Per semplificare, ogni programma è frutto di compromessi.

Usa byte o int o float quando necessario, non a sproposito.
if spazio (cond) spazio {, su questa riga niente commenti
Accorpa in un blocco delimitato da ritorno carrello quelle istruzioni correlate
Ritorno carrello (enter)
Accendi LED0
ritarda 100 ms
Spegni LED0
Ritorno carrello (enter)
Accendi LED1
ritarda 100 ms
Spegni LED1

Traforma quel codice in un
for ( byte n_led = 0; byte < n_max_led + 1; n_led++ ) {
Accendi led0 + 4;
ritardo;
Spegni led0+4;
}

Ciao.

Perdonami ma non riesco a trasformarlo in un ciclo for, sto cercando esempi ma mi sono bloccato...
byte n_led=0;??? n_led cosa intendi? il led1 led2 esempio?? il numero dei led dovrei indicare 9..
ma dopo come lo richiamo nel digitalWrite?
Ciao

Che credevi che ti scrivessi il codice preciso e funzionante. :wink:

Devi fare da te, ha tutte le carte in regola per riuscire a scrivere un ciclo for.

ps: guarda che è già scritto il ciclo for, devi solo capire come funziona.
La seguente parte io la chiamo pseudo code. Si tratta di singole operazioni nel linguaggio misto tra quello umano e quello di programmazione. Visto che per accendere un bit (digitalWrite() si può fare in tanti modi, scrivo l'operazione in linguaggio misto, poi
la vera codifica di linguaggio la si realizza secondo necessità, in un modo o nell'altro.

     Accendi led0 + 4;
     ritardo;
     Spegni led0+4;

n_led cosa vuol dire?
ho preso n cose, n sta per numero e led sta per led.

Nel ciclo for n_led, sarà 0 la 1° volta 1 la 2° volta e così via
se sommo 0 + 4 = 4
1 + 4 = 5

Guarda caso i led sono messi a partire dal piedino 4 in poi.

Per cui digitalWrite(0+4, HIGH) accende il primo led.

Sta a te usare le varibili per creare il for funzionante, e dovrebbe apparire ormai banale.

Ciao.

Ciao, scusa la mia assenza ma sono partito in fretta e furia per il week end, sto provando a compilare lo sketch sempre per quel che riguarda il ciclo for, ma l'ide mi restituisce come errore che byte non è un template, non capisco cosa voglia dire.. scusami

Ah, lo so che non mi avresti dato il codice bello e fatto e ciò mi fa piacere, perchè mi stai aiutando ad imparare cercando di farmi capire e non limitandoti a scrivere delle righe per te facilissime...ma a volte capita che lo sconforto prenda il sopravvento...soprattutto quando uno fa il commercialista e non sa un fico secco di elettronica e programmazione..ciaooooo e ancora grazie

Posta il codice che ti da errore.

Non devi cercare esempi, devi trovare un libro o risorsa internet che ti possa guidare durante la sperimentazione.
Ti servono i rudimenti, in mancanza di questi programmare per alcuni è un traguardo irrangiungibile, alcuni forse più portati di altri
si accontentano di una spiegazione banale e capiscono il ciclo for dopo 2 minuti e ci sperimentano da soli fino a capirlo a fondo.

Con arduino la sperimentazione di codice è resa difficoltosa perchè si è costretti a scrivere il programma dentro il microcontroller, mentre con il PC la sperimentazione di programmi in C/C++ è quasi diretta, quasi perchè il compilatore si prende il suo tempo, che per piccoli programmi è equiparabile alla immediatezza, quindi io consiglio sempre di sperimentare il codice C/C++ sul PC, usando un IDE e il compilatore C/C++ gcc o altro.

Il ciclo for:

for(byte idx = 0; idx < 100; idx++) {

}

Il codice dentro il blocco {} viene ripetuto 99 volte.
per byte idx = 0; continua a ciclare se idx < 100; idx viene incrementato di una unità ad ogni ciclo
quindi idx è un indice che parte da 0 e termina a 100.
Il ciclo for termina quando idx non è più minore di 99, appunto quando diventa 100.
Chi lo fa diventare 100? Il contatore unario ++ postfisso, perchè c'è anche quello prefisso ++idx.

Ciao.

Speravo nella solita risposta notturna...e così è stato...ancora grazie
Mi dava errore il codice perchè inserivo daccapo byte quando dovevo dirgli che n_led era 9
for (byte n_led=0; byte n_led<9; n_led++)
ma dopo aver visto il tuo esempio ho riprovato e adesso funziona con gli 8 led che si accendono in sequenza e il codice è diventato questo:

//devo far accendere 8 led in sequenza

//definisco il bottone 1
int pinButton1 = 2; //indico che il bottone 1 che servità da input per la partenza della sequenza è sul pin 2 di arduino
int buttonState1 = 0; //stato attuale del bottone 1
int lastState1 = 0; //vecchio stato del bottone 1

//definisco il bottone 2
int pinButton2 = 3; //indico che il bottone 2  che mi servirà per variare il delay e' sul pin 3 di arduino
int buttonState2 = 0; //stato attuale del bottone 2
int lastState2 = 0; //vecchio stato del bottone 2

//definisco gli 8 led
byte led1 = 4;
byte led2 = 5;
byte led3 = 6;
byte led4 = 7;
byte led5 = 8;
byte led6 = 9;
byte led7 = 10;
byte led8 = 11;

void setup(){
  //inizializzo i pin di input
  pinMode(pinButton1, INPUT);
  pinMode(pinButton2, INPUT);
  //inizializzo i pin di output
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  pinMode(led7, OUTPUT);
  pinMode(led8, OUTPUT);
}

void loop(){
  buttonState1 = digitalRead(pinButton1); //legge la pressione del tasto 1
  delay(50);  // antirimbalzo per lettura pulsante
  //compare lo stato attuale con lo stato iniziale
  if(buttonState1 != lastState1){
    
    if(buttonState1 == HIGH){  //se il bottone 1 è alto
    
    for (byte n_led=0; n_led <9; n_led++){
      digitalWrite(n_led+4, HIGH);
      delay(100); //pausa di 0,100 secondi
      digitalWrite(n_led+4, LOW);
    }
  }
}
}

edit by mod: per favore includi il codice usando gli appositi tag

Sembra che ora inizi a diventare più snello.
In effetti hai ragione, per quel che riguarda la programmazione del micro, sono alle prime armi, non conosco i linguaggi e vorrei correre..Attualmente come altro progettino sto cercando di realizzare un contagiri per la mia barca con lettura della tensione delle batterie e lettura del galleggiante del carburante..dovrei integrare anche un altro bel pò di cose :slight_smile:
ancora grazie
Ciao e buona giornata

Le variabili contengono un valore, questo può essere modificato durante il funzionamento del programma o essere invece una costante, il compilatore e il programmatore che leggono il codice non sanno sempre se questa è o meno una costante.
Il compilatore si accorge se la variabili non viene modificata e quindi sembrerebbe superfluo comunicare in qualche modo la volonta del programmatore di rendere una variabile una costante, ma così non è, alle volte si alle volte no.

Il programmatore gradirebbe sapere che la variabile che sta osservando è o meno una costante, pertanto tutte le dichiarazioni di variabili che devono essere delle costanti useranno il qualificatore "const" anteposto al tipo.

Es la dichiarazione di byte led1 = 4; poiche non viene modificata durante il programma è a tutti gli effetti una costante, e per farlo sapere a tutti in modo non equivoco lo specifico dichiarando la varibile così: const byte led1 = 4;

Metti caso il tuo programma fosse lungo 2000 linee, potresti finire per dimenticare che led1 è una variabile già usata e che il suo valore non deve essere cambiato, e quindi ci cambi il valore, durante la compilazione il compilatore ti avverte che led1 è const e che non può cambiare il valore.

Considera che led1 è una variabile globale e dovrebbe avere un nome che lo lasci intendere, es g_Led1, o gLED1, o _LED1
il nome deriva da convenzioni di uso comune o anche linee guida da te scritte nel codice.
Cioè nel codice scrivi dei commenti dove spieghi le linee guida per la codifica, dicendo che le variabili globali
iniziano sempre _ e tutti i caratteri devono essere maiuscoli tranne la parte finale che può essere minuscola.

Le regole o linee guida si dettano quando si ha una certa esperienza, diversamente viene difficile scriverele e osservarle, ma
è comunque un buon esercizio tentare di scrivere delle linee guida e cercare di osservarlo, anche se si finirià inizialmente per
dimenticarsi osservarle oppure notare ambiguità e finire col dire che le linee guida devono essere modificate, si ma come?
Come non si sa, in qualunque modo che possa tornare utile chiaro e non ambiguo.

Mi dava errore il codice perchè inserivo daccapo byte quando dovevo dirgli che n_led era 9

Le variabili si dichiarano una sola volta e si usano tutte le volte che vuoi.
Il for (tipo var = 0;
dichiara var di tipo e la inizializza con un valore, questa è la dichiarazione definizione contemporanea di una variabile.
Il codice tipo var = 0; viene eseguito solo la prima volta, perchè altrimenti 'var' sarebbe sempre 0 (zero).
La variabile 'var' è visibile solo nel blocco di codice appartenente al for che ha dichiarato la variabile, per cui fuori da {} var non esiste, anzi al termine di } 'var' viene distrutta, e non è possibile pertanto fargli rifermento.

In effetti hai ragione, per quel che riguarda la programmazione del micro, sono alle prime armi, non conosco i linguaggi e vorrei correre..Attualmente come altro progettino sto cercando di realizzare un contagiri per la mia barca con lettura della tensione delle batterie e lettura del galleggiante del carburante..dovrei integrare anche un altro bel pò di cose smiley

Io sono sicuro che le nozioni di programmazione che hai al momento non ti permettono di scrivere programmi divertendoti, cioè sarò un lavoro stressante e per niente divertente. Il divertimento viene quando hai una certa padronanza del linguaggio e una esperienza di base che ti permette di non commettere errori banali. Insomma concentrati sul codice che funziona e modificalo e studialo.

Es la funzione loop() e il for sono concettualmente simili, o meglio hanno qualcosa in comune, entrambe eseguono del codice ciclicamente, il for ha una condizione di uscita dal ciclo la funzione loop() no.

In virtù di quanto detto sopra potresti pensare di usare la funzione loop() al posto del for. La cosa è fattibile modifcando il codice, con l'aiuto di 'if ( condizione... e alcune variabili di stato da te create con il fine di conservare memoria circa uno stato avvenuto o corrente o da verificarsi.

loop() {
variabile currentState

tasto = leggi tasto
if (tasto == 1)
entra in stato accendi currenteState = accendi;
else
entra in stato spegni currentState = spegni;

if (currentState)
accendi // accendi esegue l'azione
else
spegni // spegni esegue l'azione

}

Le variabili di stato conservano un valore a cui attribuiamo un significato di stato situazione corrente.

Quando sei ubriaco non devi guidare.
Controlla stato corrente: stato corrente = ubricaco

if (!stato corrente == ubriaco)
pui guidare
else
non guidare

Ma anche quando stai male non devi guidare, allora possiamo attribuire a stato corrente un altro valore numerico
a cui noi diamo un significato reale.

Imparare a programmare richiede una analisi dei nostri comportamenti. Noi eseguiamo delle azioni in base ad una serie di variabili,
analizzare le azioni e le variabili che hanno comportato quella/e azioni ci permette di capire che noi svolgiamo calcoli in modo inconsapevole. Es descrivimi tutte le azioni da compiere per bere un bicchiare di acqua.
Prendo la bottiglia la apro e verso l'acqua nel bicchiere, semplice no.

Sempre se il bicchiere può contenere l'acqua, magari e già pieno. Ma hai controllato che nella bottiglia ci sia l'acqua, no perchè magari e vuota. Allora se (if) bottiglia piena ... && se bicchiere vuoto ... esegui azione, si ma fino a quando devo eseguire l'azione, fintanto (while bicchiere != pieno) che il bicchiere non è pieno. while ( bicchiere != pieno) { cicla } cicla fintantoché la condizione bicchiere è diverso (!=) da pieno. Peccato che il while così blocca l'esecuzione di altro codice fintanto che il bicchiere si è riempito.

Ciao.

Ragazzi complimenti per lo sketch mi ha salvato la vita peccato solo che non riesco a tenere tutto in condizioni di riposo e all'avvenuta pressione del pulsante si accendano come adesso uno alla volta