dab77:
Francesco, potrebbe essere l'occasione per imparare una cosa nuova! registri le 7 note come sette bit di un byte, e controlli i singoli valori dei byte. non cambia niente come risultato, ma utilizzi un metodo molto più elegante. io ci proverei.
Un passo alla volta. Per ora non gli serve questo, gli serve come imparare a gestire i pulsanti
Anche perché ha già dei byte che contengono i livelli logici dei pin accessibili a singoli bit, sono i registri del microcontrollore. Le porte sono infatti mappate in alcuni registri e leggere un registro equivale a leggere un gruppo di 8 porte tutte insieme. http://www.arduino.cc/en/Reference/PortManipulation
Ma qui si entra in un livello più elevato di programmazione, mentre ora deve imparare a programmare correttamente.
francescobonassi:
Allora... Ho sostituito gli = con == e adesso suona :% Però la nota non torna mai bassa. Se premo il Do questo suona finchè non premo un'altra nota che a sua volta farà lo stesso. Ho prova a mettere dopo ogni nota:
else
{
noTone(Buzzer);
}
...ma peggio che prima. Ho ottenuto delle frequenze altissime senza spiegarmi il perchè.
Forse perché si sommano più frequenze insieme. Oppure perché fai un'alternanza superveloce fra nota/no nota....
Un altro problema che nessuno ha sollevato è il debounce dei pulsanti. Ogni pulsante dà dei "rimbalzi" elettrici, che possono essere letti come false pressioni. Anche questo tema è da sviluppare.
Poi secondo me dovresti provare un altro approccio. Semplifica il programma e fai suonare una singola nota per un determinato lasso di tempo, metti cioè un flag per verificare che non sia già in esecuzione la riproduzione di una nota.
Poi il secondo passo potrebbe essere quello di far suonare una nota finché il tasto è premuto.
francescobonassi:
Allora... Ho sostituito gli = con == e adesso suona :% Però la nota non torna mai bassa. Se premo il Do questo suona finchè non premo un'altra nota che a sua volta farà lo stesso. Ho prova a mettere dopo ogni nota:
else
{
noTone(Buzzer);
}
...ma peggio che prima. Ho ottenuto delle frequenze altissime senza spiegarmi il perchè.
Forse perché si sommano più frequenze insieme. Oppure perché fai un'alternanza superveloce fra nota/no nota....
Un altro problema che nessuno ha sollevato è il debounce dei pulsanti. Ogni pulsante dà dei "rimbalzi" elettrici, che possono essere letti come false pressioni. Anche questo tema è da sviluppare.
Poi secondo me dovresti provare un altro approccio. Semplifica il programma e fai suonare una singola nota per un determinato lasso di tempo, metti cioè un flag per verificare che non sia già in esecuzione la riproduzione di una nota.
Poi il secondo passo potrebbe essere quello di far suonare una nota finché il tasto è premuto.
Si, si hai perfettamente ragione, lo suggerivo solo per dopo, cioè quando hai fatto funzionare tutto e vuoi migliorare.
Secondo me però aveva colto il punto col 'while', e non capisco perchè non si può usare. in fondo finchè è 'Vero' deve suonare, poi manca la condizione di uscita, ovvero quando il pin è falso. Non è così?
Esistono 2 modi per intendere il "finché è vero deve suonare":
finché non stacca il pulsante, deve suonare
finché non viene premuto un altro tasto, deve suonare
Nel 1° caso può usare il while (e va messo appunto il controllo del cambio di stato del pin per l'uscita), nel secondo caso, non può usare il while ma deve usare un ciclo per cambiare nota solo quando viene premuto un altro pulsante.
francescobonassi:
Allora... Ho sostituito gli = con == e adesso suona :% Però la nota non torna mai bassa. Se premo il Do questo suona finchè non premo un'altra nota che a sua volta farà lo stesso. Ho prova a mettere dopo ogni nota:
else
{
noTone(Buzzer);
}
...ma peggio che prima. Ho ottenuto delle frequenze altissime senza spiegarmi il perchè.
hai provato a mettere una roba del genere?
if(digitalRead(Do) == HIGH){
tone(Buzer, 262, duration); // suona il DO per duration ms (duration lo dichiari come const int )
delay(duration); //attende che il do abbia finito di suonare
noTone(Buzer); //smette di far suonare il Buzer
}
[\code]
x IngHooch
Se ho capito bene però "duration" ha valore fisso e la nota rimane attiva per un lasso di tempo predefinito, nel caso volessi prolungare la nota tenendo premuto il pulsante non posso farlo...
x leo72
Da quello che dici capisco che è più corretto usare i while... Usando gli if ottengo appunto quello che ho ottenuto; ogni nota suona finchè non ne premo un'altra.
francescobonassi:
x IngHooch
Se ho capito bene però "duration" ha valore fisso e la nota rimane attiva per un lasso di tempo predefinito, nel caso volessi prolungare la nota tenendo premuto il pulsante non posso farlo...
Nì, perché se il codice è fatto così
void loop(){
if(digitalRead(Do) == HIGH){
tone(Buzer, 262, duration); // suona il DO per duration ms (duration lo dichiari come const int )
delay(duration); //attende che il do abbia finito di suonare
noTone(Buzer); //smette di far suonare il Buzer
}
}
Se tu tiene premuto il bottone ogni volete che passa dall'if trova i bottone premuto e continua a suonare la stessa nota, nel momento in cui lo lasci questo continua a suonare per duration e poi smette
mmm... qualcosa non mi torna... tutto quello che dici però accade se il tasto è premuto. Supponiamo che imposto il delay a 10ms... Appena premo il tasto suona il do per 20ms (10ms per la funzione tone + 10ms per il delay successivo) e poi si spegne... Indipendentemente che io rilascio o meno il pulsante... Corretto?
IngHooch come dici tu però senza impostare il tempo alla funzione tone.
Però ora si tratta solo di trovare il delay giusto perchè a 10 è troppo basso e distorce... Però a 100 si sente il buzzer staccare e attaccare velocemente.
da il via al Buzer per duration, ma non aspetta che finisce! Passa subito all'istruzione successiva, che nel nostro caso è un delay di duration.
Quindi le due righe di codice forzano il programma ad aspettare che il do abbia finito di suonare prima di procedere ad altri controlli (nel nostro caso controllare se il La è premuto ed eventualmente farlo suonare)
IngHooch come dici tu però senza impostare il tempo alla funzione tone.
Però ora si tratta solo di trovare il delay giusto perchè a 10 è troppo basso e distorce... Però a 100 si sente il buzzer staccare e attaccare velocemente.
Qui devi fare un po' di prove. Leggi il post precedente e guarda di capire bene la logica del duration + delay :%
Non riesco a capire...
if(digitalRead(Do) == HIGH){
tone(Buzer, 262, duration);
delay(duration);
noTone(Buzer);
}
Inizia a suona Do per duration, aspetta duration e poi spegne... Poi ricomincia... Non capisco l'utilità di impostare duration anche a tone.
io pero' ritornerei ai while, l'unica cosa che devi fare e' che all'interno del while ci deve essere anche il controllo per vedere se il tasto e' ancora premuto o no.
Perche' quando entri nel while sei in un loop chiuso, fai solo quello che c'e' nel while, non altro.
Il loop stesso di arduino e' un while (l'ho imparato da leo :))
Testato:
io pero' ritornerei ai while, l'unica cosa che devi fare e' che all'interno del while ci deve essere anche il controllo per vedere se il tasto e' ancora premuto o no.
Perche' quando entri nel while sei in un loop chiuso, fai solo quello che c'e' nel while, non altro.
Il loop stesso di arduino e' un while (l'ho imparato da leo :))
E' un ciclo for. Cmq è un ciclo infinito da cui non se ne esce. E' un "raggiro" fatto per imbrogliare il compilatore perché in un programma in C che gira sul computer esiste il caso che, al termine del programma, il controllo sia reso al sistema operativo. Ma su un micro non esiste tale ambiente superiore, una "cosa" cioè a cui rendere il controllo, per cui nel core dell'Arduino all'interno del file main.c è stato inserito lo spezzone di codice contenuto in loop() all'interno di un ciclo infinito.
@Francesco:
esistono infinite combinazioni di casi che portano ad uno stesso risultato, ti sono state suggerite molte di esse. A questo punto prendi ed inizia a studiarti le varie casistiche altrimenti passi più tempo qui sul forum a chiedere questo o quello piuttosto che ad imparare a programmare per conto tuo
int Buzzer=13; //Collego il Buzzer al pin D13
int Do=12; //Collego il pulsante Do al pin D12
int Re=11; //Collego il pulsante Re al pin D11
int Mi=10; //Collego il pulsante Mi al pin D10
int Fa=9; //Collego il pulsante Fa al pin D9
int Sol=8; //Collego il pulsante Sol al pin D8
int La=7; //Collego il pulsante La al pin D7
int Si=6; //Collego il pulsante Si al pin D6
int ValueDo; //Valore del pulsante Do
int ValueRe; //Valore del pulsante Re
int ValueMi; //Valore del pulsante Mi
int ValueFa; //Valore del pulsante Fa
int ValueSol; //Valore del pulsante Sol
int ValueLa; //Valore del pulsante La
int ValueSi; //Valore del pulsante Si
void setup() //Azioni da eseguire solo all'avvio
{
pinMode(Buzzer,OUTPUT); //Imposto in uscita il pin D13
pinMode(Do,INPUT); //Imposto in ingresso il pin D12
pinMode(Re,INPUT); //Imposto in ingresso il pin D11
pinMode(Mi,INPUT); //Imposto in ingresso il pin D10
pinMode(Fa,INPUT); //Imposto in ingresso il pin D9
pinMode(Sol,INPUT); //Imposto in ingresso il pin D8
pinMode(La,INPUT); //Imposto in ingresso il pin D7
pinMode(Si,INPUT); //Imposto in ingresso il pin D6
}
void loop() //Azioni da ripetere all'infinito
{
ValueDo=digitalRead(Do); //Associo al valore del pulsante Do la lettura al pin D12
delayMicroseconds(10); //Aspetta 10us
ValueRe=digitalRead(Re); //Associo al valore del pulsante Re la lettura al pin D11
delayMicroseconds(10); //Aspetta 10us
ValueMi=digitalRead(Mi); //Associo al valore del pulsante Mi la lettura al pin D10
delayMicroseconds(10); //Aspetta 10us
ValueFa=digitalRead(Fa); //Associo al valore del pulsante Fa la lettura al pin D9
delayMicroseconds(10); //Aspetta 10us
ValueSol=digitalRead(Sol); //Associo al valore del pulsante Sol la lettura al pin D8
delayMicroseconds(10); //Aspetta 10us
ValueLa=digitalRead(La); //Associo al valore del pulsante La la lettura al pin D7
delayMicroseconds(10); //Aspetta 10us
ValueSi=digitalRead(Si); //Associo al valore del pulsante Si la lettura al pin D6
delayMicroseconds(10); //Aspetta 10us
if(ValueDo==HIGH) //Se il valore del pulsante Do è alto...
{
tone(Buzzer,262); //...fai suonare il Buzzer a 262Hz...
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
if(ValueRe==HIGH) //Se il valore del pulsante Re è alto...
{
tone(Buzzer,294); //...fai suonare il Buzzer a 294Hz
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
if(ValueMi==HIGH) //Se il valore del pulsante Mi è alto...
{
tone(Buzzer,330); //...fai suonare il Buzzer a 330Hz
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
if(ValueFa==HIGH) //Se il valore del pulsante Fa è alto...
{
tone(Buzzer,349); //...fai suonare il Buzzer a 349Hz
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
if(ValueSol==HIGH) //Se il valore del pulsante Sol è alto...
{
tone(Buzzer,392); //...fai suonare il Buzzer a 392Hz
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
if(ValueLa==HIGH) //Se il valore del pulsante La è alto...
{
tone(Buzzer,440); //...fai suonare il Buzzers a 440Hz
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
if(ValueSi==HIGH) //Se il valore del pulsante Si è alto...
{
tone(Buzzer,494); //...fai suonare il Buzzers a 349Hz
delay(10); //...aspetta 10ms...
noTone(Buzzer); //...e poi spegni il Buzzer
}
}
Funziona... Solamente che il tempo di delay impostato a 10ms (la miglior soluzione a mio parere comprata alle altre) crea un leggero disturbo in uscita sul buzzer.
francescobonassi:
Funziona... Solamente che il tempo di delay impostato a 10ms (la miglior soluzione a mio parere comprata alle altre) crea un leggero disturbo in uscita sul buzzer.
Ringrazio tutti quanti per la collaborazione
L'importante è che tu sia soddisfatto del risultato, sono sicuro che con un po' d'impegni riuscirai a risolvere anche il disturbo che hai adesso.
@Francesco:
io nutro dei dubbi.... a ripensarci, vedendo il tuo sketch, tu manderesti in riproduzione per 10 millisecondi il tono di una nota, poi lo stacco ecc....Quindi sarebbe un continuo suona per 10 ms/stacca/suona per 10 ms/stacca/suona per 10 ms ecc... se io tengo premuto un pulsante. E' giusto?
Uhm, non mi sembra il modo corretto, però. Tu devi attivare la riproduzione di un tono in base al tasto premuto e poi disattivarlo al rilascio del pulsante, non continuare a fare suona/stacca/suona/stacca mentre vedi il tasto premuto