drums with teensy - a keyboard emulation problem

Status
Not open for further replies.

dirtdiver

Member
Hi,
i have been making a drums for use with the pc but im having trouble with the code - when i trigger the pieso it writes the letter 10-15 times



int ledPin = 13;

byte val = 0;
int statePin = LOW;
int THRESHOLD = 50; // if it's too sensitive then change this value

void setup()
{
pinMode(ledPin, OUTPUT);
}

void loop()
{
val = analogRead(A0);
if (val >= THRESHOLD) { // check the piezo
Keyboard.println("A");
}
delay (10 );


}

I am guessing i have to limit the time in which it reads that "val" is above the THRESHOLD , or maybe somehow implement the fallingEdge function.
Any ideas are highly appreciated!! Thanks
 
A lot of info here http://www.sparkfun.com/tutorials/330 , but based on your sample code, you have already been there :) There are a couple of challenges. the Piezo signal will has a waweform and will delute overtime. The first problem with your code is you are only delay(10) before you test the value again and it is still HIGH and you get another "A". The best way to understand this is if you print val instead of "A" if it is above THRESHOLD. You can put a resistor in parallel with the piezo to deplete the charge faster or increase the delay - which will create latency... In general you should not use Delay at all for something like a drum trigger but rather test if enough time have lapsed before taking a new sample to avoid double triggering. Your other drum triggers may be sending you data while you are waiting :). Assuming you want velocity triggering the next challenge is to capture the wave while it is at is top. Best way to do this is to take multiple measurements for 5ms or what ever value that works for your setup and consider the highest as the trigger value.
 
hmm..if i can use the fallingEdge function here it would be perfect, but i have to use digitalRead and not Analog im guessing? And how to digitalRead a piezo ?
 
First of all, do not connect the piezo directly to a Teensy pin. Use a resistor between the pin and the piezo. A value like 10K is probably good. The piezo can actually create quite a bit more than 5 volts. It also creates negative voltage. These are harm the Teensy. Connecting a 10K resistor right at the pin will limit the current to a (hopefully) safe value. The piezo might also limit how much current it can produce, but a 10K resistor is very cheap and easy, so do this first to minimize risk to your hardware.

Also use a resistor in parallel with the piezo. If you're not getting enough voltage, you can try increasing the resistance. Or instead of a fixed resistor, you can connect a pot and use the center pin as the output. Then you can easily adjust how much voltage you get out.
 
hmm..if i can use the fallingEdge function here it would be perfect, but i have to use digitalRead and not Analog im guessing? And how to digitalRead a piezo ?

I am assuming you want velocity sensing since you are using piezos, so the digital read is no good as it is...digital eg on/off. if you don't want velocity sensing you can use a push button and a digital pin which is MUCH easier, but not as fun/realistic.
This is what I would do:
1) put your circuit together as Paul suggests
2) Build a simple pad from memory foam, a foam mouse pad and some masonite or whatever fits your design. It is better to put together now, so you don't have to re-calibrate your thresholds etc afterwards
3) Change your test program so it prints ms since start and the analog pin value when ever the value exceeds the threshold.
4) use your test program to determine what your threshold and scan time should be. Scan time being the time from the hardest hit to the value is below your threshold
5) start programming. if you are using delay even once, you are doing something wrong ;-)
The below code is completely untested ( I put it together in 5 min) and is only meant as a concept to explain the concepts of the code without the delays. if you get into this and planning on building a complete drum kit, I will be happy to assist

Code:
 int     PiezoPin       = 1;
int     triggervalue;
int     higesttriggervalue;
boolean triggeractive;
int     scantime       = 5;
int     threshold      = 40;
int     instrument     = 38;
int     MIDIChannel    = 11;
int     notevelocity;
unsigned long        Time;
unsigned long       triggertime;


void setup() 
{
  pinMode(PiezoPin, INPUT);
}

void loop() 
{
  Time = millis();
  triggervalue = analogRead(PiezoPin);
  if (triggervalue > threshold)
  {
    if (triggeractive = false) 
    {
      triggeractive = true;
      triggertime = Time;    
    }
    higesttriggervalue = triggervalue > higesttriggervalue ? triggervalue :  higesttriggervalue;
  }  
  if (triggeractive && (triggervalue < threshold || Time >= triggertime + scantime )) // if you get too many double hits remove the triggervalue < threshold. it is there to minimize latency for soft hits
  {
      notevelocity = triggervalue > 127 ? 127 : triggervalue; // replace this with a formula that makes sense for your situation. basically you need to step down a 0-1023 value to 0-127
      usbMIDI.sendNoteOn(instrument, notevelocity, MIDIChannel);  
      triggeractive = false;
      higesttriggervalue = 0;
      triggertime = 0;  
  }
}
 
Last edited:
Paul, i have the piezos connected to the teensy with a 1M ohm resistor in paralel ,I will connect the 10K right away!

I dont need the velocity sensing (im building guitar hero drums) i only need the piezo to act like a button.As far as i can understand CheapB's code , it measires the velocity too.I just need the simpler version that is like a button - on or off. Obviously i cant use a button for the drums so it has to be a piezo.But how do i calibrate the piezo to work with a digital read, or still use an analog read but limit the "noice" (the unwanted detection)
 
Paul, i have the piezos connected to the teensy with a 1M ohm resistor in paralel ,I will connect the 10K right away!

I dont need the velocity sensing (im building guitar hero drums) i only need the piezo to act like a button.As far as i can understand CheapB's code , it measires the velocity too.I just need the simpler version that is like a button - on or off. Obviously i cant use a button for the drums so it has to be a piezo.But how do i calibrate the piezo to work with a digital read, or still use an analog read but limit the "noice" (the unwanted detection)

Actually the original Guitar hero drums does have velocity sensing, which you would need in the higher levels of the game. Even if you don't need that it will be very difficult to accept very fast convective triggers without the risk of double triggering if you ignore the level of the signal and only consider it on or off (which likely is why the Guitar Hero Bass pedal is not a piezo)
Think about this: if the piezo will be above your threshold for 30ms, you will either not accept another trigger for 30ms or if you do, it will be impossible to distinguish the ringout from the previous note to a new note being hit without comparing the level of the two readings (the above code actually doesn't take care of that problem either..) but it is still a sound framework. A lot of this will be taken care of by adjusting the threshold and potentially change the value of the pull-down resistor.
to ignore velocity change notevelocity = triggervalue > 127 ? 127 : triggervalue; to notevelocity = 127;
the code should still work as a framework for you.

That being said I am sure you can find buttons in a format that could work for drumpads if velocity is truly not needed.
 
buttons wont be really practical for drums, but i guess i can make the piezo trigger a relay that will be the "button" connected to the arduino or teensy

But when i think about it, 30ms is not a time i which i can psychically hit the drum pad two times so i dont think that would be a problem, so how do I ignore that 30 ms , with a 30 ms delay?Cause ive tried a delay up to 100ms and it still sends the letter alot of times(cause im using the keyboard emulation)
 
buttons wont be really practical for drums, but i guess i can make the piezo trigger a relay that will be the "button" connected to the arduino or teensy

But when i think about it, 30ms is not a time i which i can psychically hit the drum pad two times so i dont think that would be a problem, so how do I ignore that 30 ms , with a 30 ms delay?Cause ive tried a delay up to 100ms and it still sends the letter alot of times(cause im using the keyboard emulation)

30ms is just an example. you need to check your specific situation to see what the scan time should be. You cannot have delays in our code if you want to use more than one trigger. You will often want to hit two triggers at the same time and if you use delays, it would only pick up one.

if you are tapping the "raw" piezo you will have to do all your calibration all over again when you are building you pad. The steps 1-5 and the code example above should get you there. You may have to change the resistor to deplete the piezo faster or if that is not fast enough for you you can consider building this: http://leucos.lstilde.org/wp/wp-content/uploads/2009/05/piezo_circuit.png , but it should not be required for what you are trying to do.
 
the code from the first link is going to be very useful , so now i just need to play with it for a while to set it up for my case
 
Status
Not open for further replies.
Back
Top