Buonasera a tutti,
vi espongo un mio problema:
Sono in possesso di un arduino uno rev 3,da qualche giorno mi ballena in testa l'idea di fare un gioco molto semplice,si accendono uno dietro l'altro dei led,il giocatore non dovrà far altro che ricordare in che seguenza si sono accesi i led e premere un pulsantino ad esso corrispondente.
Adesso ho un problemino,per leggere lo stato dei pulsantini uno digitalread(),il problema è che è possibile che mentre arduino esegue il comando digitalread,il giocatore ancora non abbiamo premuto nessun pulsante,non esiste un modo per far si che arduino aspetti prima di eseguire quel comando?
NO, sei tu che lo devi gestire nel loop() leggendo in continuazione i vari pin e capendo quando un pulsante è stato premuto. Ad esempio puoi attivare le resistenze di PULL-UP sugli input e quando uno preme il pulsante collega quell'input a massa.
In questo modo normalmente digitalRead() ti ritornerà HIGH (ovvero pulsante NON premuto), metre ti ritornerà LOW per pulsante premuto.
Guglielmo
gpb01:
NO, sei tu che lo devi gestire nel loop() leggendo in continuazione i vari pin e capendo quando un pulsante è stato premuto. Ad esempio puoi attivare le resistenze di PULL-UP sugli input e quando uno preme il pulsante collega quell'input a massa.
In questo modo normalmente digitalRead() ti ritornerà HIGH (ovvero pulsante NON premuto), metre ti ritornerà LOW per pulsante premuto.Guglielmo
Grazie della risposta!
Allora non capisco cosa possa cambiare,non sapevo delle resiste di PULL-UP,e sono andato a ricerca,ho letto che si attivano con il digitalWrite (pin,HIGH),però la cosa non cambia,potrebbe capitare che si prema il pulsante mentre arduino ha gia processato l'istruzione e non legge l'eventuale presione del bottone...o sto sbagliando?
Io pensavo di usare un do while,mettendo all'interno la lettura dei pin,e come condizione verificare se un bottone (un altro) sia stato premuto per andare avanti,ma il ripetere del ciclo potrebbe mettere a 0 (o a 1 se uso il tuo metodo) una variabile (che mi indica lo stato dei pin) che prima era stato messo a 1 (o a 0),potrei mettere una condizione che se un pin viene messo a 1 non può essere più modificato...che ne pensi? esistono altri modi?
razielmitico:
Allora non capisco cosa possa cambiare,non sapevo delle resiste di PULL-UP,e sono andato a ricerca,ho letto che si attivano con il digitalWrite (pin,HIGH)
No, no, sbagliato ... il pin a te serve in ingresso quindi ... nessuna digitalWrite() ... le attivi quando dichiari in che modalità lavora il pin : pinMode(numeroPin, INPUT_PULLUP); ... ovvero dichiari il pin in input con la resistenza di pull-up attiva ... quindi, in queste condizioni, se effettui poi una digitalRead() trovi quel pin a HIGH salvo che qualcuno non lo metta a LOW (il pulsante).
razielmitico:
però la cosa non cambia,potrebbe capitare che si prema il pulsante mentre arduino ha gia processato l'istruzione e non legge l'eventuale presione del bottone...o sto sbagliando?
Se tu sei all'interno di un ciclo come il loop() e non fai perdere troppo tempo al processore, allora la pressione a mano di un pulsante non ha alcuna possibilità di non essere rilevata, anzi, dovrai anche implementare una tecnica di debouncing, altrimenti ... di pressioni e rilasci del pulsante ... te ne trovi una sfilza (una per ogni rimbalzo che hanno i contatti).
Per casi più estremi invece, si usano gli interrupt, ma ... per il momento, non so, ma non mi sembra che tu sia già ad un livello da "gestione degli interrupt" (senza offesa naturalmente) ![]()
razielmitico:
Io pensavo di usare un do while,mettendo all'interno la lettura dei pin,e come condizione verificare se un bottone (un altro) sia stato premuto per andare avanti,ma il ripetere del ciclo potrebbe mettere a 0 (o a 1 se uso il tuo metodo) una variabile (che mi indica lo stato dei pin) che prima era stato messo a 1 (o a 0),potrei mettere una condizione che se un pin viene messo a 1 non può essere più modificato...che ne pensi? esistono altri modi?
Sei già all'interno di un ciclo, il loop() ... non so se è il caso /utile crearne un altro ... dipende da come si imposta il programma ... prova a vedere di impostarlo usando il loop() e comincia a scrivere un po' di codice ... che mano mano lo sistemiamo ![]()
Guglielmo
Innanzitutto ti ringrazio da morire per l'aiuto!
Allora spiego meglio il mio progetto,consiste in 5 led (per ora,volevo apliarlo a 10,ma meglio iniziare facilmente) e 5 pulsanti,il gioco è diviso in 5 livelli,e ogni livello in altri 3 sottolivelli,ad ogni livello si accendono un tot di led con questo ordine:
livello 0-1:
si accende un led con velocità lenta
livello 0-2
si accende un led con velocità lenta
livello 0-3
si accende un led con velocità lenta
livello 1-1
si accendono due led con velocità media
ecc ecc,fino a
liveloo 5-3
si accendono 5 led rapidamente.
Adesso,i led sono collegati dal pin 0 al 4 analogici,i pulsanti sono dal pin 8 al 12 analogici e poi ai pin 5,6,7 ci sono dei led,al pin 5 un led rosso che indica quando si sta passando da un livello all'altro (dal livello 1 al livello 2) al pin 6 un led verde che indica quando si sta passando da un sottolivello all'altro (in questo caso il led rosso sta acceso,es: dal livello 1-2 al livello 1-3),al pin 7 un led che lampeggia quando si sbaglia la combinazione.
Ho fatto un breve codice solo per i livelli 0-1,0-2,0-3,facendo scegliere alla funzione random quali led accendere in combinazione (e mettendo questi valori su un array che ho chiamato led[5]):
[quelli ingrassetto sono le righe degli errori]
boolean input[5],led[5],comodo;
int indice;
void setup(){
pinMode(0,OUTPUT);
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,INPUT_PULLUP);
pinMode(9,INPUT_PULLUP);
pinMode(10,INPUT_PULLUP);
pinMode(11,INPUT_PULLUP);
pinMode(12,INPUT_PULLUP);
pinMode(13,INPUT_PULLUP);
//VERIFICA FUNZIONAMENTO LED
for (int i=0;i<8;i++){
digitalWrite(i,HIGH);
}
for (int i=0;i<8;i++){
digitalWrite(i,LOW);
}
//VERIFICA FUNZIONAMENTO LED
}
void loop(){
livello_0();
}
void livello_0 (){
for (int i=0;i<4;i++)
led[i]=random(0,4);
indice=1;
//livello 0-1,2,3
for (int j=0;j<3;j++){
accensione_led(indice);
//lettura pulsanti
[b] for (int i=0;i<5;i++)[/b]
[b] input[i]=digitalRead[i];[/b]
[b] comodo=led[i];[/b]
if(input[comodo]==1){
digitalWrite(6,HIGH);
delay(3000);
digitalWrite(6,LOW);
indice++;
}
}
}
void accensione_led (int indice){
digitalWrite(led[indice],HIGH);
delay(5000);
}
il problema è che mi da questi errori:
simon.ino: In function 'void livello_0()':
simon:52: error: pointer to a function used in arithmetic
simon:52: error: invalid conversion from 'int (*)(uint8_t)' to 'boolean'
simon:54: error: name lookup of 'i' changed for new ISO 'for' scoping
simon:51: error: using obsolete binding at 'i'
razielmitico:
input[i]=digitalRead[i];
Errore di copiatura? digitalRead devi usare le tonde:
input[i]=digitalRead (i);
Se poi il compilatore ti dice errore o avvisa che non può convertire da int (digitalRead ritorna int) a boolean, fai un cast (forzi conversione)
input[i]=(boolean)digitalRead (i);
nid69ita:
razielmitico:
input[i]=digitalRead[i];Errore di copiatura? digitalRead devi usare le tonde:
input[i]=digitalRead (i);
ops,errore di svista,a forza di mettere parentesi quadre mi sono confuso,comunque non mi da errore di conversione!
Però mi da questi errori:
simon.ino: In function 'void livello_0()':
simon:54: error: name lookup of 'i' changed for new ISO 'for' scoping
simon:51: error: using obsolete binding at 'i'
e le righe sono
for (int i=0;i<5;i++) (51)
comodo=led*;[/b] (54)*
come mai questo errore su "i",non capisco...non dovrebberò esserci errori nel codice,passo la parola a voi!
grazie
Pubblica il codice che hai provato a compilare.
leo72:
Pubblica il codice che hai provato a compilare.
è stato pubblicato qualche post più in sù...comunque rieccolo:
boolean input[5],led[5],comodo;
int indice;
void setup(){
pinMode(0,OUTPUT);
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,INPUT_PULLUP);
pinMode(9,INPUT_PULLUP);
pinMode(10,INPUT_PULLUP);
pinMode(11,INPUT_PULLUP);
pinMode(12,INPUT_PULLUP);
pinMode(13,INPUT_PULLUP);
//VERIFICA FUNZIONAMENTO LED
for (int i=0;i<8;i++){
digitalWrite(i,HIGH);
}
for (int i=0;i<8;i++){
digitalWrite(i,LOW);
}
//VERIFICA FUNZIONAMENTO LED
}
void loop(){
livello_0();
}
void livello_0 (){
for (int i=0;i<4;i++)
led[i]=random(0,4);
indice=1;
//livello 0-1,2,3
for (int j=0;j<3;j++){
accensione_led(indice);
//lettura pulsanti
for (int i=0;i<5;i++)
input[i]=digitalRead(i);
comodo=led[i];
if(input[comodo]==1){
digitalWrite(6,HIGH);
delay(3000);
digitalWrite(6,LOW);
indice++;
}
}
}
void accensione_led (int indice){
digitalWrite(led[indice],HIGH);
delay(5000);
}
Fa una bella cosa ...
... le variabili dei for, invece che dichiararle nei for stessi, dichiarale all'inizio della funzione dove le usi con la classica istruzione "int i,j;" e nei for lasci solo "for(i=0; .......);" perché ... mi sembra che, all'interno di "void livello_0", ci siano delle definizioni multiple della stessa variabile (i) e magari il compilatore non gradisce.
Guglielmo
Edit : Mmmm . NO, ho appena provato e a me il compilatore accetta tranquillamente multiple definizioni della variabile di for rispettandone la visibilità. Quindi è un'altra cosa ... ![]()
Mancano le parentesi {}:
void livello_0 (){
for (int i=0;i<4;i++)
led[i]=random(0,4);
eccetera eccetera
dopo for (int i=0;i<4;i++) devi aprire la { e chiuderla alla fine delle istruzione che vuoi inserire:
void livello_0 (){
for (int i=0;i<4;i++) {
led[i]=random(0,4);
eccetera eccetera }
Forse si incasina per questo.
P.S. ma se led[] lo hai creato boolean, come mai vai ad assegnare un random(0,4) ????
Si, esatto, l'errore è la mancanza delle parentesi, per cui l'istruzione
comodo=led[i]; usa la variabile "i" al di fuori del suo "scope" ( = della sua visibilità).
Se metti le graffe tutto va a posto ...
Guglielmo
razielmitico:
leo72:
Pubblica il codice che hai provato a compilare.è stato pubblicato qualche post più in sù...comunque rieccolo:
Quello NON era compilabile. C'erano cose in più, vedi i tag "[ b ]". Mica possiamo metterci a ripulirlo per fare dei test. ![]()
ho risolto dichiarando le variabili del for fuori da essi,adesso il codice è questo:
boolean input[5],comodo;
int indice,led[5];
void setup(){
pinMode(0,OUTPUT);
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,INPUT_PULLUP);
pinMode(9,INPUT_PULLUP);
pinMode(10,INPUT_PULLUP);
pinMode(11,INPUT_PULLUP);
pinMode(12,INPUT_PULLUP);
pinMode(13,INPUT_PULLUP);
//VERIFICA FUNZIONAMENTO LED
for (int i=0;i<8;i++){
digitalWrite(i,HIGH);
}
for (int i=0;i<8;i++){
digitalWrite(i,LOW);
}
//VERIFICA FUNZIONAMENTO LED
}
void loop(){
livello_0();
}
void livello_0 (){
int i;
for (i=0;i<4;i++)
led[i]=random(0,4);
indice=1;
//livello 0-1,2,3
int j;
for (j=0;j<3;j++){
accensione_led(indice);
//lettura pulsanti
for (int i=0;i<5;i++)
input[i]=digitalRead(i);
comodo=led[i];
if(input[comodo]==0){
digitalWrite(6,HIGH);
delay(3000);
digitalWrite(6,LOW);
indice++;
}
}
}
void accensione_led (int indice){
digitalWrite(led[indice],HIGH);
delay(5000);
}
adesso lo continuo a scrivere fino al 5 livello...poi lo pubblico per sapere qualche vostra opinione...vi ringrazio dell'aiuto sono i primi sketch che scrivo per arduino
raziel, il post precedente, quello sbagliato (con i codici controllo colore all'interno del sorgente), eliminalo con il bottone "Remove", così il thread resta pulito ... ![]()
Guglielmo
razielmitico:
ho risolto dichiarando le variabili del for fuori da essi
Hai semplicemente spostato la definizione della variabile al di fuori del blocco di codice introdotto dal for.
Adesso la variabile ha uno spazio di visibilità maggiore rispetto a quello che aveva definendola nel for.
Inoltre se non indenti bene il codice, errori come quelli commessi in precedenza continuerai a farli.
Così sintatticamente va bene ma puoi confonderti perché le 4 istruzioni che seguono l'if sembrano non appartenere al blocco di codice introdotto dall'if stesso:
if(input[comodo]==0){
digitalWrite(6,HIGH);
delay(3000);
digitalWrite(6,LOW);
indice++;
}
Così è più leggibile:
if(input[comodo]==0){
digitalWrite(6,HIGH);
delay(3000);
digitalWrite(6,LOW);
indice++;
}
E' per questo motivo che avevi fatto diversi errori nei precedenti sketch, con le graffe messe tutte allo stesso livello che ti confondevano le idee ![]()
Non hai risolto, hai semplicemente eliminato la segnalazione dell'errore ma non funzionerà.
Devi usare le {} per includere quello che deve andare dentro il ciclo FOR.
A parte altri errori logici che si notano qua e là sparsi per il codice.
Oltre all'indentazione, che sicuramente rende più facile individuare i blocchi, puoi aiutarti con l'evidenziazione delle parentesi dell'editor. Se ti metti a fianco di una parentesi aperta (di qualsiasi genere), l'editor ti evidenzia la corrispondente parentesi chiusa. Funziona anche il viceversa, ti metti accanto alla parentesi chiusa e vedi dove si apre.
Dichiarare fuori dal FOR le variabili che usi nel FOR a mio avviso è inopportuno, rischi di usare le suddetta variabili fuori dal ciclo e creare confusione. Ti conviene usare per i FOR delle variabili (di solito uso i, j, k per tre possibili livelli di nidificazione) ed usare sempre quelle, tanto ad ogni ciclo il programma "dimentica" l'uso precedente che hai fatto di queste variabili negli altri cicli FOR.
Fare confusione con i diversi livelli di una variabile è un errore molto comune quando si programma.
Tanto vale eliminare alla base questa possibilità di errore.
E io che avevo detto? ![]()