Go Down

Topic: Pianola con Arduino (Read 3613 times) previous topic - next topic

dab77



mi sa che l'errore è l'utilizzo di = per comparare. devi usare ==.

E' vero, non ci avevo fatto caso neanch'io  ;)

Quote

a questo punto, visto che Do e tutte le altre sono dei valori boolean (o Vero o Falso), è uno spreco usare le 'int'. dichiarali come boolean (

Oppure un byte, tanto anche il boolean occupa comunque 1 byte in memoria.

ma dai! questa non la sapevo, pensavo stupidamente che potesse occupare solo un bit.. quindi è così perchè non si può indirizzare un solo bit, o perchè insieme al bit del valore viene registrato dell'altro?

leo72



Oppure un byte, tanto anche il boolean occupa comunque 1 byte in memoria.

ma dai! questa non la sapevo, pensavo stupidamente che potesse occupare solo un bit.. quindi è così perchè non si può indirizzare un solo bit, o perchè insieme al bit del valore viene registrato dell'altro?

Il resto del byte è inutilizzato. Per questo spesso si consiglia di utilizzare gli operatori sui bit se si devono memorizzare più flag che devono avere solo il valore 1 o 0.

dab77




Oppure un byte, tanto anche il boolean occupa comunque 1 byte in memoria.

ma dai! questa non la sapevo, pensavo stupidamente che potesse occupare solo un bit.. quindi è così perchè non si può indirizzare un solo bit, o perchè insieme al bit del valore viene registrato dell'altro?

Il resto del byte è inutilizzato. Per questo spesso si consiglia di utilizzare gli operatori sui bit se si devono memorizzare più flag che devono avere solo il valore 1 o 0.

Giusto, così non si spreca spazio..
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.

IngHooch

Interessante lo sviluppo che ha preso la discussione.
Bravo dab77 per aver beccato l'errore sul while!
The brightest flame burns quickest

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:
Code: [Select]
else
{
   noTone(Buzzer);
}

...ma peggio che prima. Ho ottenuto delle frequenze altissime senza spiegarmi il perchè.

Per quanto riguarda quello che ha detto dab77, come faccio a registrare le note come bit?

leo72


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  :D
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.

leo72


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:
Code: [Select]
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.

dab77



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:
Code: [Select]
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ì?

leo72

Esistono 2 modi per intendere il "finché è vero deve suonare":
1) finché non stacca il pulsante, deve suonare
2) 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.

IngHooch


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:
Code: [Select]
else
{
   noTone(Buzzer);
}

...ma peggio che prima. Ho ottenuto delle frequenze altissime senza spiegarmi il perchè.


hai provato a mettere una roba del genere?
Code: [Select]

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]
The brightest flame burns quickest

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...

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.

IngHooch


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ì

Code: [Select]

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
The brightest flame burns quickest

francescobonassi

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?

francescobonassi

Funziona facendo così!!!

Code: [Select]
if(ValueDo==HIGH)
{   tone(Buzzer,262);
delay(10);
noTone(Buzzer);
}


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.

IngHooch

No l'istruzione
Code: [Select]

if(digitalRead(Do) == HIGH){
tone(Buzer, 262, duration);
delay(duration);
noTone(Buzer);
}

if(digitalRead(La) == HIGH){
//codice LA
}

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)
The brightest flame burns quickest

Go Up