Buonasera a tutti,
ho eseguito l'esercizio 'clessidra digitale' (Libro dei Progetti - Progetto 8; da pagina 86 a 93) come indicato e, una volta ultimato l'esercizio, mi sono divertito ad aggiungere un piezo che mi avvertisse con un suono lo scadere del tempo. Ho inserito il piezo nel circuito ed una riga di codice: ho inserito la riga di codice proprio dove il libro lasciava solamente un if (led == 7){ //inserirecodice } specificando di lasciare l'istruzione 'if' vuota per decidere in seguito. Ho deciso che i sei led si devono accendere uno alla volta a distanza di un minuto dall'altro e ho notato che allo scoccare del quinto minuto, il piezo suonava in anticipo invece che suonare al sesto minuto. Ho risolto modificando la riga di codice proposta if (led == 7){ //codicedainserire } con la riga if (led == 8){ //codice da inserire }. Quindi la mia domanda è: sono io che sbagliavo a scrivere qualcosa nel codice oppure c'è stato un errore di trascrizione sul libro?
Inoltro il codice che ho scritto e la foto del circuito.
const int switchPin = 8;
unsigned long previousTime = 0;
int switchState = 0;
int prevSwitchState = 0;
int led = 2;
long interval = 60000;
void setup() {
// put your setup code here, to run once:
for(int x = 2;x<8;x++){
pinMode(x, OUTPUT);
}
pinMode(switchPin, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long currentTime = millis();
if(currentTime - previousTime > interval){
previousTime = currentTime;
digitalWrite(led, HIGH);
led++;
if (led == 8){
tone(12,1000,2000);
}
}
switchState = digitalRead(switchPin);
if(switchState != prevSwitchState){
for(int x = 2;x<8;x++){
digitalWrite(x, LOW);
}
led = 2;
previousTime = currentTime;
}
prevSwitchState = switchState;
}
Si c'è un errore nel pdf che hai allegato.
C'è altro che non mi torna.
La seguente condizione:
if(currentTime - previousTime > interval)
Risulta vera ogni minuto, dopo 6 minuti tutti i led sono accesi, ma dal settimo minuto in poi la variabile led cresce, sarà 8, poi 9, 10 ecc e con il tempo assumerà valori negativi poiché led è dichiarata int, fino al momento in cui giri la clessidra.
Comunque è possibile che nel libro questo venga spiegato in seguito.
Tornando all'errore, prova anche così:
if(currentTime - previousTime > interval){
previousTime = currentTime;
digitalWrite(led, HIGH);
// ora appena led è uguale a 7 suona
if (led == 7) {
tone(12,1000,2000);
}
led++; // valeva 7, dopo questa led assume il valore 7 + 1.
}
ciao a tutti, ho avuto anch'io lo stesso problema di marco-tornani e risolto cambiamo il valore da 7 a 8 il valore da verificare nella variabile "led" con la condizione "if (led == 8)"
Quello che pero´ ancora non mi torna e´ che, se non sbaglio, nel codice di questo progetto la variabile "led" identifica il pin digitale su cui e´ collegato il led da accendere.
Quindi quando si accende il led numero 5 collegato al piedino 6, la variante led dovrebbe contenere appunto il numero 6: allora perche´ attiva gia´ la condizione if e fa suonare il piezo se scriviamo "if (led == 7)" come da libro??
premetto che sono al mio terzo giorno di smanettamento con Arduino e programmazione C quindi non sono un esperto, ma sta cosa mi fa scervellare e se poteste spiegarmi il perche´ ve ne sarei grato
giusto grazie!
In effetti non avevo notato che "led++" la eseguiva subito dopo aver acceso il led e prima di iniziare un nuovo conteggio per cui ovviamente quando accende il penultimo led sul pin 6, incrementa la variabile a 7 e con quel valore di riferimento nella condizione "if (led == 7) " fa subito suonare il piezo prima di finire il conteggio dell'ultimo led...
Ho anche provato a far "bippare" il piezo per 5 secondi mentre il programma continua, cercando in rete un ciclo con "millis", ma non funziona, suona solo due volte come se ripetesse un solo ciclo della routine.
qui di seguito il codice:
digita o incolla il codice qui
const int switchPin = 8;
unsigned long previousTime = 0; // store the last time an LED was updated
unsigned long previousMillis = 0;
const long buzzInterval = 5000; // buzzer suona 5 secondi
int switchState = 0; // the current switch state
int prevSwitchState = 0; // the previous switch state
int led = 2; // a variable to refer to the LEDs
int notes [] = {330}; // variable for the single tone note
long interval = 20000; // interval at which to light the next LED
void setup() {
// set the LED pins as outputs
for (int x = 2; x < 8; x++) {
pinMode(x, OUTPUT);
}
// set the tilt switch pin as input
pinMode(switchPin, INPUT);
}
void loop() {
// store the time since the Arduino started running in a variable
unsigned long currentTime = millis();
unsigned long currentMillis = millis();
if (currentTime - previousTime > interval) {
previousTime = currentTime;
digitalWrite(led, HIGH);
led++;
if (led == 8 ) {
if (currentMillis - previousMillis >= buzzInterval) {
previousMillis = currentMillis;
tone(12, notes[0]);
delay(100);
noTone(12);
delay(60);
tone(12, notes[0]);
delay(100);
noTone(12);
delay(740);
}
else {
noTone(12);
}
}
}
// read the switch value
switchState = digitalRead(switchPin);
// if the switch has changed
if (switchState != prevSwitchState) {
// turn all the LEDs low
for (int x = 2; x < 8; x++) {
digitalWrite(x, LOW);
}
// reset the LED variable to the first one
led = 2;
//reset the timer
previousTime = currentTime;
}
// set the previous switch state to the current state
prevSwitchState = switchState;
}
diciamo che non ho ancora speso troppo tempo ad analizzare la funzione millis ed i relativi richiami/formule, magari ci arrivo poi da solo ma se avete tempo di correggermi prima, vi ringrazio!
Questo purtroppo è un problema comune a tutti i tutorial per principianti: per essere chiari e non sovraccaricare di concetti, finiscono con il dare un "imprinting" procedurale sbagliato sulla programmazione di microcontroller, e non sono affatto propedeutici a comprendere come scrivere programmi che "fanno qualcosa mentre il resto del programma continua". Questo arriva di consueto più tardi come un muro preso in faccia, chiamato programmazione a stati finiti, dove i beginners (ancora alle prese con difficoltà sulla sintassi e semantica delle istruzioni) svengono
Suona solo due volte perché quel frammento di codice è posto all'interno di due condizioni che si verificano solo in un preciso momento. Al successivo ciclo di esecuzione (della funzione loop) le condizioni non sono più vere.
Come si risolverebbe?
Spostando quel codice fuori dalle condizioni che ne determinano l'attivazione.
Usando come segnale di attivazione una variabile flag (bandierina) opportunamente settata quando le condizioni sono vere.
Variabile flag che viene poi resettata quando il codice bip bip è stato eseguito il numero di volte desiderato.
E che deve essere opportunamente inizializzata all'avvio (o riavvio) del programma in modo da non partire subito con bip-bip attivi.
E quindi servirà anche una variabile per contare i bip.
E anche questa sarà da (re)inizializzare all'avvio o riavvio.
Questo è il tipo di difficoltà concettuale sui processi da gestire, che un tutorial per principianti non affronta.
In effetti io ero abituato alla programmazione del PIC16C84 ad inizio anni 2000: le istruzioni in assembler a linguaggio macchina erano molto basiche, ma capivi esattamente che succedeva.
Ovviamente per programmazioni più complesse non eran l’ideale, ma all’epoca la mente era anche più fresca
Infatti qui il primo muro su cui mi son scontrato è che non esistono funzioni di “loop” da richiamare nel programma, ma ho inteso che bisogna usare “while” o “for” o altro che concettualmente mi sembra più complesso ma forse è solo questione di abituarsi al metodo.
In ogni caso con calma arriveró a comprendere meglio, anche grazie al vostro aiuto.
Ciao!