Go Down

Topic: primo esperimento con arduino e i piezo, consigli (Read 1 time) previous topic - next topic

mantissa00

Jul 26, 2010, 05:09 pm Last Edit: Jul 26, 2010, 05:11 pm by mantissa00 Reason: 1
ciao
questo è il mio primo post, spero di non dire cavolate
sto provando a fare una drum machine con arduino e i piezo

devo leggede dati da un sensore piezo e mandarli in seriale a puredata. su puredata vorrei leggere un valore che sarà l'insensità di un suono

ho trovato vari progetti simili
http://www.spikenzielabs.com/SpikenzieLabs/DrumKitKit.html
http://todbot.com/blog/2006/10/29/spooky-arduino-projects-4-and-musical-arduino/
http://drummaster.digitalcave.ca

ma un po' non sono riuscito a capire benissimo il codice, un po' vorrei cercare di fare un progetto da zero, un po' non mi sembrano tanto più precisi del metodo che ho trovato

è abbastanza empirico,
e funziona abbastanza bene, volevo sapere cosa ne pensate e se avete qualche consiglio da darmi.

come schematiche per il pizeo ho adottato lo schema di todbot:
piezo con resistenza da 1MOhm e un diodo
http://todbot.com/blog/wp-content/uploads/2006/10/arduino_midi_schematic.png

il problema dei piezo è che quando vengono colpiti danno vari valori,
che oscillano su e giù fino a stabilizzarsi sullo zero

non sono una cima in programmazione, e ho adottato questo metodo:
leggo i valori dal sensore e li metto dentro un array.
ogni loop prendo il valore più alto e controllo se l'array è pieno di zeri.
se l'array è pieno di zeri significa che il segnale del piezo si è stabilizzato, e la vibrazione è finita.
posso prendere il valore più alto e mandarlo in seriale.

questo è il codice:
Code: [Select]

#define MIN 20
#define NUMS 250
int vals[NUMS];
int maxVal = 0;
int index = 0;
boolean array_is_zero = true;

void setup() {
 Serial.begin(9600);
 Serial.println("Hello..");
 
 // array init to zero
 for(int i=0; i<NUMS; i++) {
   vals[i]=0;
 }
}

void loop() {
 // read piezo
 int val = analogRead(0);
 
 // update maxval
 if(val>maxVal){
   maxVal = val;
 }
 
 //fill vals
 vals[index]=val;
 if(index>=NUMS-1)index=0;
 else index++;

 // if oscillating is finished, print maxval
 if( checkZero(vals) && maxVal>MIN) {
   Serial.println( maxVal );
   maxVal=0;
   delay(10);
 }
}

boolean checkZero(int array[]) {
 for(int i=0; i<=NUMS-1; i++) {
   if(array[i]>=MIN)
     return false;
 }
 return true;
}


ora, il problema è che ogni tanto mi manda due numeri quando faccio un solo battito.
secondome il motivo è che la vibrazione del piezo ancora non è finita,
per cercare di ovviare ho:
- aumetato la grandezza dell'array (ma anche con valori molto alti tipo 400 a volte da ancora lo stesso problema. abbassando a 50 il problema si moltiplica e vengono stampati un sacco di numeri)
- messo un limite minimo (#define MIN 20) per fare il controllo sullo zero
- inserito delay(10)

delay(10) e aumentare la grandezza dell'array mi sembrano cose un po' quick and dirty, perchè se al posto di avere 1 piezo ne ho 4.. sono fregato. insomma non è scalabile.

so che al posto dei valori dell'array potrei usare un timer con i millis.. è meglio? che mi consigliate?

nel progetto http://drummaster.digitalcave.ca/design.jsp usa un filtro hardware con diodi e capacitori, ma non ho capito come funziona..

mantissa00

effettivamente la soluzione dell'array è poco scalabile,
ora ho implementato un counter con un index e un limite,
ogni MAXR secondi si legge il valore più alto, se è maggiore del threshold viene stampato via seriale.

il problema è che usando tuti e 6 gli ingressi analogici certe volte accumula del delay,
penso sia dovuto alla scarsa capacità computazionale?

ecco il codice aggiornato.
spero serva a qualcuno, e se c'è qualche palese errore qualcuno me lo faccia notare!
Code: [Select]


#define MIN 20
#define MAXR 500

int maxVal[6];
   /////////////////////////////////////////////int repetition[6];

int _repetition;

void setup() {
 Serial.begin(9600);
 Serial.println("Hello..");

 //inits arrays
 for(int i=0; i<6; i++) {
   maxVal[i]=0;
   /////////////////////////////////////////////repetition[i]=0;
 }
}

void loop() {
 _repetition++;
 for(int i=0; i<6;i++) {
   // read piezo
   int val = analogRead(i);

   // update maxval
   if(val>maxVal[i]){
     maxVal[i] = val;
   }

   /////////////////////////////////////////////repetition[i]++;

   // if oscillation is finished, print maxval
   /////////////////////////////////////////////if( repetition[i]>MAXR) {
   if( _repetition>MAXR) {
     if(maxVal[i]>MIN) {
       Serial.print(i);
       Serial.print(" ");
       Serial.println(maxVal[i]);

       //delay(10);
     }
   /////////////////////////////////////////////repetition[i]=0;
     _repetition=0;
     maxVal[i]=0;
   }
 }
}


il motivo dei commenti è che effettivamente non serve mantenere un counter di ogni sensore..

se qualcuno ha qualche consiglio su possibili ottimizzazioni...

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy