Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 24 of 24

Thread: Latency on piezo + teensy (drums)

  1. #1

    Latency on piezo + teensy (drums)

    Hello,

    I'm building an electronic drum kit with Teensy + piezo + Ableton live. It's quite working well, but the main problem is latency (enough to disturb the play) ..

    Here is my code

    Code:
    /*
      MIDI Toy Piano Hack Code
    */
    
    #include <MIDI.h>
    MIDI_CREATE_DEFAULT_INSTANCE();
    
    //========================================================================================
    //Values you may need to change
    
    //Set this value to the number of keys/piezos you are using
    const int NUM_OF_KEYS = 16;
    //Adjust this value to change the sensitivity of the piezos
    const int THRESHOLD = 10;
    //Set this value to the number of microseconds you want each MIDI note to last for
    const int NOTE_LENGTH = 3;
    //Adjust this value to set the range of MIDI note velocity values
    const int VEL_SENSE_VAL = 2;
    
    //Change this number to set what MIDI channel the MIDI notes are set to
    const int midiChan = 1;
    //Change these numbers to set what MIDI note number each key/piezo will send.
    //Also make sure that the total number of numbers here matches the value of NUM_OF_KEYS
    const int midiNote[NUM_OF_KEYS] = {86};
    
    //Change these values to set which analog input pins you are using
    //Also make sure that the total number of values here matches the value of NUM_OF_KEYS
    const int triggerSensor[NUM_OF_KEYS] = {A0};
    
    //=======================================================================================
    
    //Variables for storing certain values
    int triggerVal[NUM_OF_KEYS] = {0};
    bool noteIsOn[NUM_OF_KEYS] = {false};
    int midiNoteTime[NUM_OF_KEYS] = {0};
    int midiVelocityVal[NUM_OF_KEYS] = {0};
    
    void setup()
    {
      MIDI.begin(MIDI_CHANNEL_OMNI);
      Serial.begin(9600); //REMOVE THIS LINE IF USING HIDUINO INSTEAD OF HAIRLESS
    }
    
    void loop()
    {
      //repeat the below code for each anaolog input/piezo sensor
      for (int count; count < NUM_OF_KEYS; count++)
      {
        //read the piezo value
        triggerVal[count] = analogRead(triggerSensor[count]);
    
        //if the value is over the threshold and there isn't currently a note on for this piezo
        if (triggerVal[count] > THRESHOLD && noteIsOn[count] == false)
        {
          //get a velocity value based on the value
          midiVelocityVal[count] = triggerVal[count] * (127.0 / 1023.0);
    
          //increase sensitivity
          midiVelocityVal[count] *= VEL_SENSE_VAL;
    
          //make sure we don't go out of range
          if (midiVelocityVal[count] > 127)
            midiVelocityVal[count] = 127;
    
          //send a MIDI note-on message
          MIDI.sendNoteOn (midiNote[count], midiVelocityVal[count], midiChan);
    
          //flag that the note is on
          noteIsOn[count] = true;
    
          //start a timer for the note to be on for
          midiNoteTime[count] = NOTE_LENGTH;
        }
    
        //if the note is currently on
        if (noteIsOn[count] == true)
        {
          //reduce the time value by 1
          midiNoteTime[count]--;
    
          //if time value equals 0
          if (midiNoteTime[count] == 0)
          {
            //turn off the note
            MIDI.sendNoteOff (midiNote[count], 0, midiChan);
            noteIsOn[count] = false;
          }
    
        }
    
      }
    
      //pause the loop
      delay(1);
    }
    What do you think ? Do you have a solution ? I'm on a Macbook pro.

    Thanks
    Florent

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,977
    Which board are you using?

  3. #3
    Junior Member
    Join Date
    Dec 2017
    Posts
    7
    teensy 3.6 and i also have a LC

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,977
    This part looks like a problem.

    Code:
    //Change these values to set which analog input pins you are using
    //Also make sure that the total number of values here matches the value of NUM_OF_KEYS
    const int triggerSensor[NUM_OF_KEYS] = {A0};
    The array is 16 elements, but only the first is initialized. Likewise for the other arrays...

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,977
    I ran it just now on a Teensy 3.6. I connected a 10K resistor from 14/A0 to GND.

    First, the threshold is too low. It transmits a continuous stream of data.

    With the threshold increased to 50, here is what I see on pin 1 (Serial1 TX) when I touch a wire between 14/A0 and 3.3V.

    Click image for larger version. 

Name:	file.png 
Views:	72 
Size:	34.5 KB 
ID:	13977

    The latency from the moment the voltage at A0/14 goes high until the first start bit of the MIDI message looks like about 400 us (not quite a 1 division). Looks very fast to me on Teensy 3.6. Even if it becomes 16X slower when using all 16 inputs, the speed is very good.

    However, there's another possible problem. This code (did you write it?) appears to continue sending messages repeated if the signal stays above the threashold. Here's what I see on the scope if I zoom out to view 0.2 seconds.

    Click image for larger version. 

Name:	file.png 
Views:	93 
Size:	38.7 KB 
ID:	13978

    Here's how I tested...

    Click image for larger version. 

Name:	DSC_0128_web.jpg 
Views:	116 
Size:	163.0 KB 
ID:	13979

  6. #6
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    There is plenty wrong with this code... apart from you not understanding the array assignments.

    It doesn't use Teensy's built in MIDI but from the comments looks like it's meant to work as a USB MIDI device using Arduinio kludgeware.

    Ok that's unfair but Paul's USB MIDI is the way to go on Teensy if you're not building a 5-pin DIN interface.

    With that you don't need to include the MIDI.h and you can use serial for printing to the serial monitor while debugging.


    I'm surprised latency is the problem though as the code itself slows down on whatever it's run on.

    This code delays every pass... that means it's like running on a 1000 Hz clocked computer. So even though your T3.6 is relative supercomputer to what this code would usually run on, its speed is all wasted.

    Paul's example code for a single Piezo trigger (File-Examples-Teensy-USB_MIDI-Piezo_Drum) is a good place to start for a single trigger.

    There's a thread here somewhere on someone trying to generalize it to multiple triggers... I can't recall how far they got... I'll post the link when I locate it...

    (@ Paul... did you remove the delay(1) to get that... the code relies on the delay for timing.)

  7. #7
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    I found the thread but it goes on for pages about other issues...

    My post HERE does have some code that might be a better starting place. It is essentially a multi-pin extension of Paul's Piezo trigger code.

    Code:
    /* Use a Piezo sensor (percussion / drum) to send USB MIDI note on
       messages, where the "velocity" represents how hard the Piezo was
       tapped.
    
       Connect a Pieze sensor to analog pin A0.  This example was tested
       with Murata 7BB-27-4L0.  Almost any piezo sensor (not a buzzer with
       built-in oscillator electronics) may be used.  However, Piezo
       sensors are easily damaged by excessive heat if soldering.  It
       is highly recommended to buy a Piezo with wires already attached!
    
       Use a 100K resistor between A0 to GND, to give the sensor a "load".
       The value of this resistor determines how "sensitive" the circuit is.
    
       A pair of 1N4148 diodes are recommended to protect the analog pin.
       The first diode connects to A0 with its stripe (cathode) and the other
       side to GND.  The other diode connects its non-stripe (anode) side to
       A0, and its stripe (cathode) side to 3.3V.
    
       Sensitivity may also be tuned with the map() function.  Uncomment
       the Serial.print lines to see the actual analog measurements in the
       Arduino Serial Monitor.
    
       You must select MIDI from the "Tools > USB Type" menu
    
       This example code is in the public domain.
       *multi-pad extension by oddson (under-tested)*
    */
    
    const int channel = 10;  // General MIDI: channel 10 = percussion sounds
    const int PINS = 3;     // number of signals incoming
    
    const int note[PINS] = {36,37,38};     // array of MIDI note values for read signals
    
    const int analogPin[PINS] = {A0,A1,A3}; //array of analog PINs 
    const int thresholdMin = 60;  // minimum reading, avoid noise and false starts
    const int peakTrackMillis = 12;
    const int aftershockMillis = 25; // aftershocks & vibration reject
    
    int state[PINS];  // 0=idle, 1=looking for peak, 2=ignore aftershocks
    int peak[PINS];   // remember the highest reading
    int piezo[PINS];
    elapsedMillis msec[PINS]; // timers to end states 1 and 2
    
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
      Serial.println("Piezo Peak Capture");
    }
    
    
    void loop() {
      for (int i=0;i<PINS;i++){
        //delay(20);
        piezo[i] = analogRead(analogPin[i]);
     
      peakDetect(i);
      // Add other tasks to loop, but avoid using delay() or waiting.
      // You need loop() to keep running rapidly to detect Piezo peaks!
    
    }
      // MIDI Controllers should discard incoming MIDI messages.
      // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
      while (usbMIDI.read()) {
        // ignore incoming messages
      }
    }
    
    
    void peakDetect(int i) {
    
            //Serial.println(state[i]);
    
      switch (state[i]) {
        // IDLE state: wait for any reading is above threshold.  Do not set
        // the threshold too low.  You don't want to be too sensitive to slight
        // vibration.
        case 0:
          if (piezo[i] > thresholdMin) {
            //Serial.print("begin peak track ");
            //Serial.println(piezo[i]);
            peak[i] = piezo[i];
            msec[i] = 0;
            state[i] = 1;
          }
          return;
    
        // Peak Tracking state: capture largest reading
        case 1:
          if (piezo[i] > peak[i]) {
            peak[i] = piezo[i];     
          }
          if (msec[i] >= peakTrackMillis) {
            //Serial.print("peak = ");
            //Serial.println(peak);
            int velocity = map(peak[i], thresholdMin, 1023, 1, 127);
            usbMIDI.sendNoteOn(note[i], velocity, channel);
            msec[i] = 0;
            state[i] = 2;
          }
          return;
    
        // Ignore Aftershock state: wait for things to be quiet again.
        default:
          if (piezo[i] > thresholdMin) {
            msec[i] = 0; // keep resetting timer if above threshold
          } else if (msec[i] > aftershockMillis) {
            usbMIDI.sendNoteOff(note[i], 0, channel);
            state[i] = 0; // go back to idle when
          }
      }
    }

  8. #8
    Hello

    Thanks for the answers. I did'nt write this code, I took it from someone and then change it. I'm really newbie.. @paul thanks for testing it so quickly ! @oddson thanks for the code I'll try it !!

  9. #9
    @oddson with that code, will my teensy will be recognize in Music programs as a midi instrument ?

  10. #10
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    When you choose MIDI as the USB type to compile code it will appear as a class compliant MIDI device.

    There is example code that shows one way to capture piezo signals and output MIDI note events with a velocity value proportional to the signal peak.

    This code attempts to extend that code for multiple sensors. It appears to work but I have not tested it personally.

    Make sure you protect Teensy from voltage spikes. Read the comment at te top carried over from the example code.

  11. #11
    Thanks a lot

    There is example code that shows one way to capture piezo signals and output MIDI note events with a velocity value proportional to the signal peak.
    I can't find it, is it in the Teensy exemples library ?

  12. #12
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    Paul's example code for a single Piezo trigger (File-Examples-Teensy-USB_MIDI-Piezo_Drum) is a good place to start for a single trigger.
    that's the path in paranthesthes

  13. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,977
    Quote Originally Posted by oddson View Post
    that's the path in paranthesthes
    That means in Arduino, you click File > Examples > Teensy > USB_MIDI > Piezo_Drum

  14. #14
    I don't have it in my exemples. Maybe I need an update of exemples ? How to proceed ? Thanks

  15. #15
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400

  16. #16
    thanks a lot !

  17. #17
    hi everybody, I come to midi with piezo for the first time, I just tried the code that odds-on gave my teensy 4.0 seems to always send 127 for velocity, I wired my piezo to A0 and A1 with 1M resistor and also tried with 100k and it s the same, I don t have the diode here, may this be my problem or can I check something else please?


    I use this piezo https://fr.farnell.com/multicomp/abt...-bf9f-00001000


    Code:
    /* Use a Piezo sensor (percussion / drum) to send USB MIDI note on
       messages, where the "velocity" represents how hard the Piezo was
       tapped.
    
       Connect a Pieze sensor to analog pin A0.  This example was tested
       with Murata 7BB-27-4L0.  Almost any piezo sensor (not a buzzer with
       built-in oscillator electronics) may be used.  However, Piezo
       sensors are easily damaged by excessive heat if soldering.  It
       is highly recommended to buy a Piezo with wires already attached!
    
       Use a 100K resistor between A0 to GND, to give the sensor a "load".
       The value of this resistor determines how "sensitive" the circuit is.
    
       A pair of 1N4148 diodes are recommended to protect the analog pin.
       The first diode connects to A0 with its stripe (cathode) and the other
       side to GND.  The other diode connects its non-stripe (anode) side to
       A0, and its stripe (cathode) side to 3.3V.
    
       Sensitivity may also be tuned with the map() function.  Uncomment
       the Serial.print lines to see the actual analog measurements in the
       Arduino Serial Monitor.
    
       You must select MIDI from the "Tools > USB Type" menu
    
       This example code is in the public domain.
       *multi-pad extension by oddson (under-tested)*
    */
    
    const int channel = 10;  // General MIDI: channel 10 = percussion sounds
    const int PINS = 2;     // number of signals incoming
    
    const int note[PINS] = {36,37};     // array of MIDI note values for read signals
    
    const int analogPin[PINS] = {A0,A1}; //array of analog PINs 
    const int thresholdMin = 60;  // minimum reading, avoid noise and false starts
    const int peakTrackMillis = 12;
    const int aftershockMillis = 25; // aftershocks & vibration reject
    
    int state[PINS];  // 0=idle, 1=looking for peak, 2=ignore aftershocks
    int peak[PINS];   // remember the highest reading
    int piezo[PINS];
    elapsedMillis msec[PINS]; // timers to end states 1 and 2
    
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
      Serial.println("Piezo Peak Capture");
    }
    
    
    void loop() {
      for (int i=0;i<PINS;i++){
        //delay(20);
        piezo[i] = analogRead(analogPin[i]);
     
      peakDetect(i);
      // Add other tasks to loop, but avoid using delay() or waiting.
      // You need loop() to keep running rapidly to detect Piezo peaks!
    
    }
      // MIDI Controllers should discard incoming MIDI messages.
      // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
      while (usbMIDI.read()) {
        // ignore incoming messages
      }
    }
    
    
    void peakDetect(int i) {
    
            //Serial.println(state[i]);
    
      switch (state[i]) {
        // IDLE state: wait for any reading is above threshold.  Do not set
        // the threshold too low.  You don't want to be too sensitive to slight
        // vibration.
        case 0:
          if (piezo[i] > thresholdMin) {
            //Serial.print("begin peak track ");
            //Serial.println(piezo[i]);
            peak[i] = piezo[i];
            msec[i] = 0;
            state[i] = 1;
          }
          return;
    
        // Peak Tracking state: capture largest reading
        case 1:
          if (piezo[i] > peak[i]) {
            peak[i] = piezo[i];     
          }
          if (msec[i] >= peakTrackMillis) {
            //Serial.print("peak = ");
            //Serial.println(peak);
            int velocity = map(peak[i], thresholdMin, 1023, 1, 127);
            Serial.println (velocity);
            usbMIDI.sendNoteOn(note[i], velocity, channel);
            msec[i] = 0;
            state[i] = 2;
          }
          return;
    
        // Ignore Aftershock state: wait for things to be quiet again.
        default:
          if (piezo[i] > thresholdMin) {
            msec[i] = 0; // keep resetting timer if above threshold
          } else if (msec[i] > aftershockMillis) {
            usbMIDI.sendNoteOff(note[i], 0, channel);
            state[i] = 0; // go back to idle when
          }
      }
    }

  18. #18
    Quote Originally Posted by PaulStoffregen View Post
    That means in Arduino, you click File > Examples > Teensy > USB_MIDI > Piezo_Drum
    hi, now I can get values of 354 or 738 or 1023 in serial monitor but the velocity sent is always at 127
    anyone got idea how I could make this drummed working with velocity please?

  19. #19
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    Quote Originally Posted by benwadub View Post
    hi, now I can get values of 354 or 738 or 1023 in serial monitor but the velocity sent is always at 127
    anyone got idea how I could make this drummed working with velocity please?
    Code:
            int velocity = map(peak[i], thresholdMin, 1023, 1, 127);
            Serial.println (velocity);
            usbMIDI.sendNoteOn(note[i], velocity, channel);
    Yeah, how can you be getting those values at all? If you are then the MIDI likely would max out at 127 (I've never tried to overload it or ever bothered to remember the result when I did). But how can println(velocity) give numbers that haven't been mapped from the raw values?

    I've NEVER run this code on anything resembling piezo hardware. I only extended it to arrays for multiple signals so my 'expertise' is suspect but the behaviour as you describe it doesn't seem consistent with the above posted code.

    Can you confirm you're referring to that code?

  20. #20
    hi, thanks for answering! the values I got are voltage not velocity, I was able to receive 354 or 738 or 1023 as voltage but the values sent always the max velocity, what I d like to achieve is using 2 piezo for the moment that send different velocity over usb I m a beginner in coding I can t make work the code you gave I m experimenting around it but can t find why I always receive the same voltage
    with that code my piezo always print 1023 on the serial monitor


    Code:
    /* Use a Piezo sensor (percussion / drum) to send USB MIDI note on
       messages, where the "velocity" represents how hard the Piezo was
       tapped.
    
       Connect a Pieze sensor to analog pin A0.  This example was tested
       with Murata 7BB-27-4L0.  Almost any piezo sensor (not a buzzer with
       built-in oscillator electronics) may be used.  However, Piezo
       sensors are easily damaged by excessive heat if soldering.  It
       is highly recommended to buy a Piezo with wires already attached!
    
       Use a 100K resistor between A0 to GND, to give the sensor a "load".
       The value of this resistor determines how "sensitive" the circuit is.
    
       A pair of 1N4148 diodes are recommended to protect the analog pin.
       The first diode connects to A0 with its stripe (cathode) and the other
       side to GND.  The other diode connects its non-stripe (anode) side to
       A0, and its stripe (cathode) side to 3.3V.
    
       Sensitivity may also be tuned with the map() function.  Uncomment
       the Serial.print lines to see the actual analog measurements in the
       Arduino Serial Monitor.
    
       You must select MIDI from the "Tools > USB Type" menu
    
       This example code is in the public domain.
       *multi-pad extension by oddson (under-tested)*
    */
    
    const int channel = 10;  // General MIDI: channel 10 = percussion sounds
    const int PINS = 2;     // number of signals incoming
    
    const int note[PINS] = {36,37};     // array of MIDI note values for read signals
    
    const int analogPin[PINS] = {A0,A1}; //array of analog PINs 
    const int thresholdMin = 1;  // minimum reading, avoid noise and false starts
    const int peakTrackMillis = 200;
    const int aftershockMillis = 60; // aftershocks & vibration reject
    
    int state[PINS];  // 0=idle, 1=looking for peak, 2=ignore aftershocks
    int peak[PINS];   // remember the highest reading
    int piezo[PINS];
    elapsedMillis msec[PINS]; // timers to end states 1 and 2
    
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
      Serial.println("Piezo Peak Capture");
    }
    
    
    void loop() {
      for (int i=0;i<PINS;i++){
        delay(5);
        piezo[i] = analogRead(analogPin[i]);
     
      peakDetect(i);
      // Add other tasks to loop, but avoid using delay() or waiting.
      // You need loop() to keep running rapidly to detect Piezo peaks!
    
    }
      // MIDI Controllers should discard incoming MIDI messages.
      // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
      while (usbMIDI.read()) {
        // ignore incoming messages
      }
    }
    
    
    void peakDetect(int i) {
    
            //Serial.println(state[i]);
    
      switch (state[i]) {
        // IDLE state: wait for any reading is above threshold.  Do not set
        // the threshold too low.  You don't want to be too sensitive to slight
        // vibration.
        case 0:
          if (piezo[i] > thresholdMin) {
            Serial.print("begin peak track ");
            Serial.println(piezo[i]);
            peak[i] = piezo[i];
            msec[i] = 0;
            state[i] = 1;
          }
          return;
    
        // Peak Tracking state: capture largest reading
        case 1:
          if (piezo[i] > peak[i]) {
            peak[i] = piezo[i];     
          }
          if (msec[i] >= peakTrackMillis) {
            Serial.print("peak = ");
            Serial.println(peak[i]);
            int velocity = map(piezo[i], thresholdMin, 1023, 80, 127);
            usbMIDI.sendNoteOn(note[i], velocity, channel);
            msec[i] = 0;
            state[i] = 2;
          }
          return;
    
        // Ignore Aftershock state: wait for things to be quiet again.
        default:
          if (piezo[i] > thresholdMin) {
            msec[i] = 0; // keep resetting timer if above threshold
          } else if (msec[i] > aftershockMillis) {
            usbMIDI.sendNoteOff(note[i], 0, channel);
            state[i] = 0; // go back to idle when
          }
      }
    }

  21. #21
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    int velocity = map(piezo[i], thresholdMin, 1023, 80, 127);
    You want peak[i] not piezo[i] here.

    You're taking the last reading instead of the maximum reading... as it's likely below the threshold min and map doesn't deal with out of range inputs well (I recall but that might not be true for Teensy currently) it's possible that's the source of the velocity problem but I don't think that's likely the only problem or even necessarily involved but it will prevent you from getting a meaningful velocity so you need to change it.

    You mention "354 or 738 or 1023" twice as if these are the ONLY values you are seeing... which would be very strange.

    Can you post the actual serial output from playing it? (Maybe add a print for the calculated velocity too!)

  22. #22
    thanks for help!!
    with this code I get in serial monitor even if I strike the piezo quite slowly or very hard


    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023
    begin peak track 1023
    peak = 1023


    Code:
    /* Use a Piezo sensor (percussion / drum) to send USB MIDI note on
       messages, where the "velocity" represents how hard the Piezo was
       tapped.
    
       Connect a Pieze sensor to analog pin A0.  This example was tested
       with Murata 7BB-27-4L0.  Almost any piezo sensor (not a buzzer with
       built-in oscillator electronics) may be used.  However, Piezo
       sensors are easily damaged by excessive heat if soldering.  It
       is highly recommended to buy a Piezo with wires already attached!
    
       Use a 100K resistor between A0 to GND, to give the sensor a "load".
       The value of this resistor determines how "sensitive" the circuit is.
    
       A pair of 1N4148 diodes are recommended to protect the analog pin.
       The first diode connects to A0 with its stripe (cathode) and the other
       side to GND.  The other diode connects its non-stripe (anode) side to
       A0, and its stripe (cathode) side to 3.3V.
    
       Sensitivity may also be tuned with the map() function.  Uncomment
       the Serial.print lines to see the actual analog measurements in the
       Arduino Serial Monitor.
    
       You must select MIDI from the "Tools > USB Type" menu
    
       This example code is in the public domain.
       *multi-pad extension by oddson (under-tested)*
    */
    
    const int channel = 10;  // General MIDI: channel 10 = percussion sounds
    const int PINS = 2;     // number of signals incoming
    
    const int note[PINS] = {36,37};     // array of MIDI note values for read signals
    
    const int analogPin[PINS] = {A0,A1}; //array of analog PINs 
    const int thresholdMin = 1;  // minimum reading, avoid noise and false starts
    const int peakTrackMillis = 12;
    const int aftershockMillis = 17; // aftershocks & vibration reject
    
    int state[PINS];  // 0=idle, 1=looking for peak, 2=ignore aftershocks
    int peak[PINS];   // remember the highest reading
    int piezo[PINS];
    elapsedMillis msec[PINS]; // timers to end states 1 and 2
    
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
      Serial.println("Piezo Peak Capture");
    }
    
    
    void loop() {
      for (int i=0;i<PINS;i++){
        delay(5);
        piezo[i] = analogRead(analogPin[i]);
     
      peakDetect(i);
      // Add other tasks to loop, but avoid using delay() or waiting.
      // You need loop() to keep running rapidly to detect Piezo peaks!
    
    }
      // MIDI Controllers should discard incoming MIDI messages.
      // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
      while (usbMIDI.read()) {
        // ignore incoming messages
      }
    }
    
    
    void peakDetect(int i) {
    
            //Serial.println(state[i]);
    
      switch (state[i]) {
        // IDLE state: wait for any reading is above threshold.  Do not set
        // the threshold too low.  You don't want to be too sensitive to slight
        // vibration.
        case 0:
          if (piezo[i] > thresholdMin) {
            Serial.print("begin peak track ");
            Serial.println(piezo[i]);
            peak[i] = piezo[i];
            msec[i] = 0;
            state[i] = 1;
          }
          return;
    
        // Peak Tracking state: capture largest reading
        case 1:
          if (piezo[i] > peak[i]) {
            peak[i] = piezo[i];     
          }
          if (msec[i] >= peakTrackMillis) {
            Serial.print("peak = ");
            Serial.println(peak[i]);
            int velocity = map(peak[i], thresholdMin, 1023, 1, 127);
            usbMIDI.sendNoteOn(note[i], velocity, channel);
            msec[i] = 0;
            state[i] = 2;
          }
          return;
    
        // Ignore Aftershock state: wait for things to be quiet again.
        default:
          if (piezo[i] > thresholdMin) {
            msec[i] = 0; // keep resetting timer if above threshold
          } else if (msec[i] > aftershockMillis) {
            usbMIDI.sendNoteOff(note[i], 0, channel);
            state[i] = 0; // go back to idle when
          }
      }
    }

  23. #23
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,400
    So what are you saying about values other than 1023... it sounds like you have hardware problems.

  24. #24
    i made change in the code when I was able to get others values but can t remember what did I changed... I m lost with these piezo :-)
    maybe my piezo are not the good ones?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •