Bsera a tutti. Eccomi con il mio problemino cui vi chiedo di indicarmi la strada.
Devo fare un giochino di luci con i led pilotato da un Attiny e da comandare con un pulsante.
Stato iniziale spento;
Una prima pressione acceso modalità A;
Una seconda pressione acceso modalità B;
Una terza pressione spento.
Ho già scritto in passato un codice per la sola modalità acceso/spento e funziona, ora vi chiedo un suggerimento per come costruire il codice. Partendo dalla lettrua dello stato del bottomno, devo fare dei case oppure un if con le tre opzioni?
Grazie.
switch/case oppure if/else if sono solo scelte stilistiche/implementative, è la logica e il funzionamento che devono essere gli stessi.
Riguardo la logica ci sono due possibilità: in base alla lettura del pulsante scegliere cosa fare a seconda dello stato, oppure in base allo stato scegliere cosa fare a seconda della lettura del pulsante. Questa seconda forma è più intuitiva e generale: "se sono in questo stato e pulsante premuto allora faccio questo".
Formalizzando ogni cosa che vuoi fare in questa forma, la traduzione in codice diventa praticamente uno a uno con le frasi in italiano.
Per evitare effetti collaterali (in programmi più complessi) è importante che ad ogni ciclo di loop venga eseguito solo uno stato alla volta, quello attualmente attivo, se c'è un cambio di stato il nuovo stato va eseguito al prossimo loop.
Grazie provo a buttare giù il codice. Quindi praticamente si parte da:
tutto spento/settato nel setup per poi indicare varie azioni a seconda dello stato nel loop. Ovvero leggere continuamente lo stato del pulsante; memorizzarlo;...sono sulla giusta strada?
Pare ok, poi a combinare pasticci si fa sempre in tempo
E' già un risultato che Gug no nmi ha ancora cazziato.
... mi sto trattenendo ... voglio vedere fino a che punto arrivi ...
Guglielmo
Dai, ora spreca una variabile
No, seriamente ... se quelle azioni devono essere sempre eseguite in sequenza ...
variabile di stato (a 0 nel setup)
se pulsante premuto (controllando di eseguire il tutto una sola volta ad ogni pressione)
se variabile a 0, metti a 1
se a 1, metti a 2
se a 2, metti a 0
poi fai tutto quello che devi in base allo stato della variabile ...
Oltretutto in questo modo non sei limitato a 3 stati, puoi anche aggiungerne in seguito altri ...
Gug, Claudio...leggi, studia, copia, aggiusta...è venuto fuori questo. Che voto mi date?
[code]
const int buttonPin = 3;
const int ledPin = 11;
int counter = 0;
int brightness = 0;
int fadeAmount = 5;
void setup()
{
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop()
{
int buttonState;
buttonState = digitalRead(buttonPin);
if (buttonState == LOW)
{
counter++;
delay(150);
}
if (counter == 0)
{
digitalWrite(ledPin, LOW);
}
else if (counter == 1)
{
digitalWrite(ledPin, HIGH);
}
else if (counter == 2)
{
analogWrite(ledPin, brightness);
brightness = brightness + fadeAmount;
if (brightness <= 0 || brightness >= 255)
{
fadeAmount = -fadeAmount;
}
delay(30);
}
else if (counter == 3)
{
digitalWrite(ledPin, LOW);
}
else
{
counter = 0;
}
}
[/code]
Ciao Ete, ho visto solo ora dopo aver postato.
HO notato però che la sequenza a volte non è la stessa. Nel senso che pigiando il bottone. Non sempre parte allo stesso modo. DEvo resettare qualcos'altro?
Be', la variabile la dovresti resettare nel setup ... ma non e' che non hai debounce sul pulsante e ti legge i rimbalzi come pressioni multiple ? ...
Inoltre tu leggi il pulsante senza effettuare alcun controllo, il loop e' velocissimo e legge una pressione per ogni giro per tutto il tempo che rimane premuto ... si sta gia parlando degli stessi problemi proprio qui
Ho il debounce con r 10K sul positivo. Cmq comprendo la tua risposta.
Do un occhiata al thread da te indicato.
vince59:
Ho il debounce con r 10K sul positivo.
Ed un condensatore da 100n fra pin e massa, no ? ... senno non e' un debounce, e' solo un pullup
Vedo che nel momento in cui il pulsante viene riscontrato premuto si applica semplicemente un delay di 150ms.
Questo produce tre effetti:
- debounce alla pressione
- 6,66 pressioni rilevate al secondo se non si molla il pulsante entro 150ms
- nessun debounce sul rilascio (il rilascio può essere letto come un'ulteriore pressione)
Credo che gli ultimi due punti siano sufficienti a far vedere comportamenti strani, perché per il resto non mi sembra ci siano errori.
Per il debounce basta il condensatore.
Ma per non rilevare pressioni multiple serve l'edge detect (rilevamento delle variazioni e non dei livelli stabili).
...siete forti. Ete, hai ragione è solo un pull-up. Claudio: grazie della spiegazione....mi mancano solo i complimenti di Gug e chiudo quest'annata di me.. felice.
Mo me tocca studià l'edge detect...avevo fatto finta di non vederla.
vince59:
... mi mancano solo i complimenti di Gug e chiudo quest'annata di me.. felice.
... dopo tutti questi anni, dovevi venire qui e mostrare tutto il lavoro fatto da solo, non venire qui a ... chiedere come fare una banalità del genere !
Guglielmo
Che bello la cazziata è arrivata. Tanto lo so che in fondo mi vuoi bene e cmq hai ragione. Purtroppo è un attività cui mi dedico alla bisogna. Leggo sempre il forum e imparo ma, credimi, mi mancano le basi ed un adegiata conoscenza del linguaggio di programmazione per fare tutto da solo partendo dal foglio bianco. Riesco ad assemblare...ma solo cosette semplici
Bsera, ogni codice anche smeplice è per me spunto di studio. Ora sto giocando con questo smeplice codice. Ho provato ad inserire il debounce software con qualche difficoltà e quello hardware ovviamebte semplice.Il codice ha due "modlaità" corrispondenti al premere il bottone e funziona. Ho provato ad inserirne una quarta (come p otete vedere di seguito) il lampeggio funziona ma alla quarta pressione NON si spegne sempre al primo tocco e bisogna premere di nuovo...cosa succede?
const int btnPin = 3;
const int ledPin = 11;
int counter = 0;
int brightness = 0;
int fadeAmount = 5;
void setup()
{
pinMode(btnPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop()
{
int btnState;
btnState = digitalRead(btnPin);
if (btnState == LOW)
{
counter++;
delay(150);
}
if (counter == 0)
{
digitalWrite(ledPin, LOW);
}
else if (counter == 1)
{
digitalWrite(ledPin, HIGH);
}
else if (counter == 2)
{
analogWrite(ledPin, brightness);
brightness = brightness + fadeAmount;
if (brightness <= 0 || brightness >= 255)
{
fadeAmount = -fadeAmount;
}
delay(50);
}
else if (counter == 3)
{
digitalWrite(ledPin, HIGH);
delay(250);
digitalWrite(ledPin, LOW);
delay(250);
}
else if (counter == 4)
{
digitalWrite(ledPin, LOW);
}
else
{
counter = 0;
}
}
vince59:
alla quarta pressione NON si spegne sempre al primo tocco e bisogna premere di nuovo...cosa succede?
Il caso 3 dura mezzo secondo ad ogni ciclo. Se premi e rilasci all'interno di quel mezzo secondo che il programma è bloccato dai delay, il pulsante non può essere sentito.
Grazie Claudio, la risposta conferma quanto avevo "semplicemente" intuito. Ora volendo evitare il delay (in quanto blocca il codice) stavo provando ad inserire la pausa di accensione con millis. O meglio stavo cercando di sostituire i due delay con due millis...però il comportamento non mi convince, il primo millis sembra funzionare, quindi si è ridotto il tempo in cui il codice è fermo. Infatti ora sembra rispondere...evidentemente la finestra è più stretta ma non riesco ad inserire appropriatamente il secondo millis.