Pages: [1]   Go Down
Author Topic: primo esperimento con arduino e i piezo, consigli  (Read 1036 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 130
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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..
« Last Edit: July 26, 2010, 10:11:48 am by mantissa00 » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 130
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

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

Pages: [1]   Go Up
Jump to: