Pages: [1]   Go Down
Author Topic: Piezo MIDI Drums  (Read 1619 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everybody,

This piezo midi drums are my school project. For now I have just one "drum". My Arduino sends a signal to Serial to MIDI Coverter then via LoopBe1 to Native Instruments:Traktor.
I have one serious problem. When I hit the piezo I get multiply values, sometimes it's even 20 values smiley-eek . Program should search for maximum value
I hope you can help me.
here is my code:

int ledPin = 12;
int piezo = A0;
int threshold = 100; 
int sensorReading = 0;
int i=0,MAX=0;

void setup() {

  pinMode(ledPin, OUTPUT);
  pinMode(piezo, INPUT);
  Serial.begin(57600);     

}

void loop() {

 sensorReading = analogRead(piezo);   


  if (sensorReading > threshold) {

    while(sensorReading > threshold){

      if(sensorReading > MAX)

        MAX=sensorReading;
      else {   
        i++;

        /*analogWrite(ledPin,MAX);
        MidiTX(176, 0, 127);*/

        Serial.println(MAX);
        Serial.println(i);
        Serial.println("\t");
        Serial.println("TUC");
        break;
      }
    }

  }

  MAX = 0;
  digitalWrite(ledPin, LOW);
  delay(20);
 
/*void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val)
{
  Serial.write(StatusByte);
  Serial.write(Note);
  Serial.write(Val);
}
*/
Logged

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you have some protection at the input of the Arduino ?

Do you connect the piezo in such a way that a positive pulse is generated ? Or could it also be a negative pulse ?

You use a threshold, and if the input signal is above that, it is considered a valid pulse. Waiting for the maximum value seems not right to me.
But for each drum, you could add a variable called 'active'. That variable is 'true' while the pulse is still busy, and 'false' is the pulse is below the threshold again. That way just one midi TX is sent for each pulse, no matter how long the pulse is.

Another way to do this, is to use timing with the millis() function. You can use it to make a new pulse is only valid after about 100ms.

The best way is perhaps both. Use the variable 'active' together with the timing.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yop, I have parallel 1MOhm and serial diode to evade negative pulses
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34726
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

And what about pulses greater that 5V?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I measured it and max was something about 3.3V
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34726
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you use a scope to measure it. Meters can't see such narrow spikes.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nop. only multimeter
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks Krodal, I tried that timing, and it seems to work.

int ledPin = 12;
int piezo = A0;
int threshold = 200; 
int sensorReading = 0;
int val,oldtime,time;

void setup() {

  pinMode(ledPin, OUTPUT);
  pinMode(piezo, INPUT);
  Serial.begin(57600);     

}

void loop() {

////////////////////SNARE/////////////////////////////////////////////
  oldcas = millis()+10;
 
   sensorReading = analogRead(piezo);
  if( sensorReading > threshold ) {
   
   
    while(analogRead(piezo) > threshold) {
    time = millis();
      if(time==oldtime) val = map(analogRead(piezo), 0,1023, 0, 127);
       
    }
 
    MidiTX(144, 0, val);
    MidiTX(128, 0, val);
  }
      }
   

void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val)
{
  Serial.write(StatusByte);
  Serial.write(Note);
  Serial.write(Val);
}
Logged

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's not beautiful programming, but if you are happy then I'm happy.

For example the millis() function returns an unsigned long
http://arduino.cc/en/Reference/millis
You use integers to compare the time.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

now it works almost fine. there is one problem with latency. I hit the piezo, but sound is delayed by  500 milliseconds approx. do you think that problem is with converter or virtual midi interface or software that plays samples?

code:

int ledPin = 12;
int piezo = A0;
int threshold = 200; 
int sensorReading = 0;
int val,oldcas,cas;

void setup() {

  pinMode(ledPin, OUTPUT);
  pinMode(piezo, INPUT);
  Serial.begin(57600);     

}

void loop() {

  //    SNARE

  sensorReading = analogRead(piezo);

  if( sensorReading > threshold ) {
    oldcas = millis()+5;
    while(analogRead(piezo) > threshold)
    {
      if(millis()==oldcas)
      {
        val = analogRead(piezo) / 8;
      }
    }
    /*Serial.println(val);*/
    MidiTX(144, 0, val);
    MidiTX(128, 0, val);
  }
}

void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val)
{
  Serial.write(StatusByte);
  Serial.write(Note);
  Serial.write(Val);
}

Logged

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can try a fixed value for 'val', and send the MidiTX as soon as sensorReading > threshold.
Logged

Pages: [1]   Go Up
Jump to: