piezo velocity

Status
Not open for further replies.

edrummer

Well-known member
I'm building a drum pad using a piezo connected to (A0), I found this code that works well with the T3.6 but is not velocity sensitive. Is there any way to modify it so it reads the value of the piezo hit and sends it as midi velocity?

HTML:
/*
   MIDIUSB_test.ino

   Created: 4/6/2015 10:47:08 AM
   Author: gurbrinder grewal
   Modified by Arduino LLC (2015) & Grumpy Mike
*/

#include "MIDIUSB.h"

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void loop() {
  int val;
  val = analogRead(A0);
  if (val > 600) { // if it is greater than the threshold
    noteOn(0, 50, 127); // send a note on message the 68 is the pitch of the note 
    MidiUSB.flush(); // send the MIDI message
    while (analogRead(A0) > 600) { } // wait here until the signal has dropped
    noteOff(0, 50, 127); // send the note off message
  }
  MidiUSB.flush(); // send the MIDI message

  
  }
 
is this what you mean? I added #include "MIDIUSB.h" and got it to compile but all it does is play a note for ever until I hit the piezo again then it starts over with after some delay

include "MIDIUSB.h"

const int channel = 10; // General MIDI: channel 10 = percussion sounds
const int note = 38; // General MIDI: note 38 = acoustic snare

const int analogPin = A0;
const int thresholdMin = 60; // minimum reading, avoid noise and false starts
const int peakTrackMillis = 12;
const int aftershockMillis = 25; // aftershocks & vibration reject


void setup() {
Serial.begin(115200);
while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
Serial.println("Piezo Peak Capture");
}


void loop() {
int piezo = analogRead(analogPin);
peakDetect(piezo);
// 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 voltage) {
// "static" variables keep their numbers between each run of this function
static int state; // 0=idle, 1=looking for peak, 2=ignore aftershocks
static int peak; // remember the highest reading
static elapsedMillis msec; // timer to end states 1 and 2

switch (state) {
// 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 (voltage > thresholdMin) {
//Serial.print("begin peak track ");
//Serial.println(voltage);
peak = voltage;
msec = 0;
state = 1;
}
return;

// Peak Tracking state: capture largest reading
case 1:
if (voltage > peak) {
peak = voltage;
}
if (msec >= peakTrackMillis) {
//Serial.print("peak = ");
//Serial.println(peak);
int velocity = map(peak, thresholdMin, 1023, 1, 127);
usbMIDI.sendNoteOn(note, velocity, channel);
msec = 0;
state = 2;
}
return;

// Ignore Aftershock state: wait for things to be quiet again.
default:
if (voltage > thresholdMin) {
msec = 0; // keep resetting timer if above threshold
} else if (msec > aftershockMillis) {
usbMIDI.sendNoteOff(note, 0, channel);
state = 0; // go back to idle when
}
}
}[/CODE]
 
Maybe your piezo is different? Or maybe you have a different load resistor? Blind guessing, since I can't see your setup.

Perhaps try adjusting the 3 configuration parameters? Or maybe uncomment the Serial.print() lines to get more info about what's actually happening?
 
is this what you mean? I added #include "MIDIUSB.h" and got it to compile ....
You don't need to use this library with Teensy.

But it also should not effect whether it compiles or not...

Instead you select "MIDI" from the Tools->USB Type menu but I think you must have done that to get it to compile with those USBMidi.sendNoteOn messages.

Are you saying it plays a note at startup and it sticks until played again and then another fires and sticks?

FYI it's much easier to troubleshoot MIDI sketches if you have software that can tell you exactly what midi your computer is receiving from Teensy. Search for a 'midi monitor' - MIDIOX is often used for this.

Also, are you voltage limiting the signal before it gets to your Teensy? Piezo discs can generate voltages well in excess of what is safe for Teensy.
 
FYI it's much easier to troubleshoot MIDI sketches if you have software that can tell you exactly what midi your computer is receiving from Teensy.
Paul's point about using serial print may be more helpful as your problem may stem from the signal peak issues. Is it possible you are reading a DC offset voltage that is above the threshold all the time?

Some details on your hardware might be in order
 
It did stick on 1 note the first time I tried it, I tweeked the parameters and got it to kind of work but it's so slow it I don't think it's going to work for me. The sketch in #1 works fine with all my soft ware, with very little latency. I had success with this sketch on a different board but I had to use Hairless which caused problems with the ports.

Code:
#include "MIDIUSB.h"

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

  
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}
#include "MIDIUSB.h"

//Piezo defines
#define NUM_PIEZOS 6
#define SNARE_THRESHOLD 30     //anything < TRIGGER_THRESHOLD is treated as 0
#define LTOM_THRESHOLD 30
#define RTOM_THRESHOLD 30
#define LCYM_THRESHOLD 100
#define RCYM_THRESHOLD 100
#define KICK_THRESHOLD 50
#define START_SLOT 0     //first analog slot of piezos

//MIDI note defines for each trigger
#define SNARE_NOTE 70
#define LTOM_NOTE 71
#define RTOM_NOTE 72
#define LCYM_NOTE 73
#define RCYM_NOTE 74
#define KICK_NOTE 75

//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127

//MIDI baud rate
#define SERIAL_RATE 31250

//Program defines
//ALL TIME MEASURED IN MILLISECONDS
#define SIGNAL_BUFFER_SIZE 100
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 20
#define MIN_TIME_BETWEEN_NOTES 50

//map that holds the mux slots of the piezos
unsigned short slotMap[NUM_PIEZOS];

//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];

//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];

//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];

boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];

unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];

void setup()
{
  Serial.begin(SERIAL_RATE);
  
  //initialize globals
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    currentSignalIndex[i] = 0;
    currentPeakIndex[i] = 0;
    memset(signalBuffer[i],0,sizeof(signalBuffer[i]));
    memset(peakBuffer[i],0,sizeof(peakBuffer[i]));
    noteReady[i] = false;
    noteReadyVelocity[i] = 0;
    isLastPeakZeroed[i] = true;
    lastPeakTime[i] = 0;
    lastNoteTime[i] = 0;    
    slotMap[i] = START_SLOT + i;
  }
  
  thresholdMap[0] = KICK_THRESHOLD;
  thresholdMap[1] = RTOM_THRESHOLD;
  thresholdMap[2] = RCYM_THRESHOLD;
  thresholdMap[3] = LCYM_THRESHOLD;
  thresholdMap[4] = SNARE_THRESHOLD;
  thresholdMap[5] = LTOM_THRESHOLD;  
  
  noteMap[0] = KICK_NOTE;
  noteMap[1] = RTOM_NOTE;
  noteMap[2] = RCYM_NOTE;
  noteMap[3] = LCYM_NOTE;
  noteMap[4] = SNARE_NOTE;
  noteMap[5] = LTOM_NOTE;  
}

void loop()
{
  unsigned long currentTime = millis();
  
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    //get a new signal from analog read
    unsigned short newSignal = analogRead(slotMap[i]);
    signalBuffer[i][currentSignalIndex[i]] = newSignal;
    
    //if new signal is 0
    if(newSignal < thresholdMap[i])
    {
      if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
      {
        recordNewPeak(i,0);
      }
      else
      {
        //get previous signal
        short prevSignalIndex = currentSignalIndex[i]-1;
        if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;        
        unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
        
        unsigned short newPeak = 0;
        
        //find the wave peak if previous signal was not 0 by going
        //through previous signal values until another 0 is reached
        while(prevSignal >= thresholdMap[i])
        {
          if(signalBuffer[i][prevSignalIndex] > newPeak)
          {
            newPeak = signalBuffer[i][prevSignalIndex];        
          }
          
          //decrement previous signal index, and get previous signal
          prevSignalIndex--;
          if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
          prevSignal = signalBuffer[i][prevSignalIndex];
        }
        
        if(newPeak > 0)
        {
          recordNewPeak(i, newPeak);
        }
      }
  
    }
        
    currentSignalIndex[i]++;
    if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
  }
}

void recordNewPeak(short slot, short newPeak)
{
  isLastPeakZeroed[slot] = (newPeak == 0);
  
  unsigned long currentTime = millis();
  lastPeakTime[slot] = currentTime;
  
  //new peak recorded (newPeak)
  peakBuffer[slot][currentPeakIndex[slot]] = newPeak;
  
  //1 of 3 cases can happen:
  // 1) note ready - if new peak >= previous peak
  // 2) note fire - if new peak < previous peak and previous peak was a note ready
  // 3) no note - if new peak < previous peak and previous peak was NOT note ready
  
  //get previous peak
  short prevPeakIndex = currentPeakIndex[slot]-1;
  if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;        
  unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
   
  if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
  {
    noteReady[slot] = true;
    if(newPeak > noteReadyVelocity[slot])
      noteReadyVelocity[slot] = newPeak;
  }
  else if(newPeak < prevPeak && noteReady[slot])
  {
    noteFire(noteMap[slot], noteReadyVelocity[slot]);
    noteReady[slot] = false;
    noteReadyVelocity[slot] = 0;
    lastNoteTime[slot] = currentTime;
  }
  
  currentPeakIndex[slot]++;
  if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;  
}

void noteFire(unsigned short note, unsigned short velocity)
{
  if(velocity > MAX_MIDI_VELOCITY)
    velocity = MAX_MIDI_VELOCITY;
  
  midiNoteOn(note, velocity);
  midiNoteOff(note, velocity);
}

void midiNoteOn(byte note, byte midiVelocity)
{
  Serial.write(NOTE_ON_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

void midiNoteOff(byte note, byte midiVelocity)
{
  Serial.write(NOTE_OFF_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

midi m.PNG is this midi?
 
is this midi?

Yes, it is indeed MIDI, but you're sending the MIDI bytes to the Arduino Serial Monitor.

You almost certainly meant to use Serial1 rather than Serial in these places:

Code:
  Serial.begin(SERIAL_RATE);

Code:
void midiNoteOn(byte note, byte midiVelocity)
{
  Serial.write(NOTE_ON_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

void midiNoteOff(byte note, byte midiVelocity)
{
  Serial.write(NOTE_OFF_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

Or if you intended to send MIDI messages to your PC, you must use usbMIDI.setNoteOn() and usbMIDI.setNoteOff().
 
From your questions and code, my guess is you're reading quite a lot of info which was written for regular Arduino boards. Most is good, but Teensy has far more capability than boards like Arduino Uno. On Uno, there is only one Serial.

On Teensy, you get Serial which talks to the Arduino Serial Monitor, and you get 6 more Serial1, Serial2, etc which are the hardware serial pins. You ALSO get usbMIDI which can talk MIDI over USB to your PC. All of these can work simultaneously on Teensy 3.6. That's a massive step up in capability compared to Uno where you basically get just one Serial. Usually this makes things easier, because you can always use the Arduino Serial Monitor even while you're sending and receiving MIDI.

But having 7 different Serial and also MIDI at the same time is a lot more than Arduino Uno. If you read other websites where people write info for Uno, please keep in mind you're using a far more powerful board. Usually that power makes things easier, but it's also not as simple as everything being only one "Serial".
 
I get this error when I try to change it, 'class usb_midi_class' has no member named 'setNoteOn', I don't know enough about code to make a lot of corrections.
 
The code in#7 I thought that was what you meant in post#8. I was trying to get the code in 7 to work with the T3.6
 
I copied the code from #7 into Arduino and clicked Verify. No errors. Nothing like "I get this error when I try to change it, 'class usb_midi_class' has no member named 'setNoteOn'"
 
Does it work with a teensy? The code will compile with no changes but it doesn't work, Doesn't play a note. thought you that what you meant by ''Or if you intended to send MIDI messages to your PC, you must use usbMIDI.setNoteOn() and usbMIDI.setNoteOff().''
 
Does it work with a teensy?

No, the code in #7 is written for Arduino Uno, not Teensy.

As written you are sending bytes to the Arduino Serial Monitor. I tried to explain this in message #9. Those 2 functions near the end are sending 3 bytes to "Serial", which always talks *only* to the Arduino Serial Monitor when using Teensy. The data you meant to be MIDI messages appears as weird characters in the Arduino Serial Monitor!

Moreover, you are including MIDIUSB.h, which is not harmful but also not very helpful when using Teensy. I suggest removing MIDIUSB.h. On Teensy, the USB MIDI is selected from Arduino's Tools > USB Type menu. You do *NOT* need to include anything else. Just select it from that menu. Stop trying to include the stuff that's used for non-Teensy boards! Doing that is only making everything harder for you...

On Teensy, use usbMIDI.sendNoteOn(note, velocity, channel) to send USB MIDI to your computer. Details here:

https://www.pjrc.com/teensy/td_midi.html

If you are unsure how this works, I highly recommend starting with the examples from File > Examples > Teensy > USB_MIDI. The Buttons example is a good place to start. That will give you *working* code for sending note on/off messages. Copy that code into your program.
 
So I was able to get this to work by changing the resistor, Can the sketch be modified for multiple pads?
 
Can the sketch be modified for multiple pads?
Typically the way to move to multiple controls is to change variables and constants to arrays where needed and add a for( i=0,i<N,i++) type loop to read through each with the index variable.

That way you run the same code N times.

Alternatively you can just add more variables and copy the functional part of your sketch N times and make all those variable name changes manually. If N is small enough or if the controls are used very differently within the sketch this isn't a bad option for code readability. But if you're making an tuned-percussion controller then you definitely need to use arrays.

Knowing what your current sketch is would help (there's a bunch of code in this thread and I'm not 100% sure I know which one you mean).
 
Thanks, it's this one, I just want to make 22 pins with piezos to fire notes 36-58 the same way it does now. If one way would be better as far as not adding latency then that would be best. Other than that they can all be the same,I can adjust velocity in the software.

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.
*/

const int channel = 10;  // General MIDI: channel 10 = percussion sounds
const int note = 38;     // General MIDI: note 38 = acoustic snare

const int analogPin = A0;
const int thresholdMin = 60;  // minimum reading, avoid noise and false starts
const int peakTrackMillis = 12;
const int aftershockMillis = 25; // aftershocks & vibration reject


void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
  Serial.println("Piezo Peak Capture");
}


void loop() {
  int piezo = analogRead(analogPin);
  peakDetect(piezo);
  // 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 voltage) {
  // "static" variables keep their numbers between each run of this function
  static int state;  // 0=idle, 1=looking for peak, 2=ignore aftershocks
  static int peak;   // remember the highest reading
  static elapsedMillis msec; // timer to end states 1 and 2

  switch (state) {
    // 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 (voltage > thresholdMin) {
        //Serial.print("begin peak track ");
        //Serial.println(voltage);
        peak = voltage;
        msec = 0;
        state = 1;
      }
      return;

    // Peak Tracking state: capture largest reading
    case 1:
      if (voltage > peak) {
        peak = voltage;     
      }
      if (msec >= peakTrackMillis) {
        //Serial.print("peak = ");
        //Serial.println(peak);
        int velocity = map(peak, thresholdMin, 1023, 1, 127);
        usbMIDI.sendNoteOn(note, velocity, channel);
        msec = 0;
        state = 2;
      }
      return;

    // Ignore Aftershock state: wait for things to be quiet again.
    default:
      if (voltage > thresholdMin) {
        msec = 0; // keep resetting timer if above threshold
      } else if (msec > aftershockMillis) {
        usbMIDI.sendNoteOff(note, 0, channel);
        state = 0; // go back to idle when
      }
  }
}
 
I've highlighted in red the variables/constants that would need to be arrays to hold different values for different signals.

Code:
const int channel = 10;  // General MIDI: channel 10 = percussion sounds
const int [COLOR="#FF0000"]note[/COLOR]= 35 ;   

const int [COLOR="#FF0000"]analogPin [/COLOR]= A0;
const int thresholdMin = 60;  // minimum reading, avoid noise and false starts
const int peakTrackMillis = 12;
const int aftershockMillis = 25; // aftershocks & vibration reject


void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
  Serial.println("Piezo Peak Capture");
}


void loop() {
  int [COLOR="#FF0000"]piezo [/COLOR]= analogRead([COLOR="#FF0000"]analogPin[/COLOR]);
  peakDetect([COLOR="#FF0000"]piezo[/COLOR]);
  // 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 voltage) {
  // "static" variables keep their numbers between each run of this function
  static int [COLOR="#FF0000"]state[/COLOR];  // 0=idle, 1=looking for peak, 2=ignore aftershocks
  static int [COLOR="#FF0000"]peak[/COLOR];   // remember the highest reading
  static elapsedMillis [COLOR="#FF0000"]msec[/COLOR]; // timer to end states 1 and 2

  switch (state) {
    // 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 (voltage > thresholdMin) {
        //Serial.print("begin peak track ");
        //Serial.println(voltage);
        [COLOR="#FF0000"]peak [/COLOR]= voltage;
        [COLOR="#FF0000"]msec [/COLOR]= 0;
        [COLOR="#FF0000"]state [/COLOR]= 1;
      }
      return;

    // Peak Tracking state: capture largest reading
    case 1:
      if (voltage > [COLOR="#FF0000"]peak[/COLOR]) {
        [COLOR="#FF0000"]peak [/COLOR]= voltage;     
      }
      if ([COLOR="#FF0000"]msec [/COLOR]>= peakTrackMillis) {
        //Serial.print("[COLOR="#FF0000"]peak [/COLOR]= ");
        //Serial.println([COLOR="#FF0000"]peak[/COLOR]);
        int velocity = map([COLOR="#FF0000"]peak[/COLOR], thresholdMin, 1023, [COLOR="#00FF00"]1[/COLOR], 127); // [COLOR="#00FF00"]do you really want velocity = 1 at threshold?[/COLOR]
        usbMIDI.sendNoteOn([COLOR="#FF0000"]note[/COLOR], velocity, channel);
        [COLOR="#FF0000"]msec [/COLOR]= 0;
        [COLOR="#FF0000"]state [/COLOR]= 2;
      }
      return;

    // Ignore Aftershock state: wait for things to be quiet again.
    default:
      if (voltage > thresholdMin) {
        [COLOR="#FF0000"]msec [/COLOR]= 0; // keep resetting timer if above threshold
      } else if ([COLOR="#FF0000"]msec [/COLOR]> aftershockMillis) {
        usbMIDI.sendNoteOff([COLOR="#FF0000"]note[/COLOR], 0, channel);
        [COLOR="#FF0000"]state [/COLOR]= 0; // go back to idle when
      }
  }
}


To keep things simple for now I'd move the peak-detection code and analogread() call into the same programing structure to make accessing the arrays a bit simpler.

The main loop is tiny so I'd likely just pull the peak detect code back into the main loop.

I could try my hand at making the required changes but I'm not in a position to build a test rig with even one piezo at present so it would be a casual testing at best.
 
Oh.... since this code requires 3.3 volts at the pin to give 127 velocity I hope you have some signal conditioning to limit the possibility of damage to Teensy?

Piezo transients can damage uC pins if not limited with at least an in-series resistor but some schemes are much more robust with external clamping diodes.

Not an EE so I'm not sure how safe you need to be but if you're bashing a piezo with a stick I'm thinking you want to be protected from plausible spike voltages.
 
Thanks very much! I'll work on this a little later. I don't know about the velocity at 1 threshold, I just copied the code as is. What do you suggest?
 
You can tweak the velocity mapping based on the actual readings you see when you're pounding on it...

My point was more about making sure you read up a bit in signal protection from piezo discs and microcontroller inputs.

I'm also not sure you want linear mapping all the way to 1 when the threshold is met as it usually is inaudible if it's mapped to volume. But like I say you can tweak the map line later but not if your Teensy's analog pins are fried.
 
Yes I do have the pins protected with 3.3 diodes. I'm just not sure how to do this, the code is like a foreign language to me. For example do I replace const int note= 35 ; with int [22] note={36,37,38,39, and so on?};
 
Last edited:
I'll write some code but you'll have to understand it to debug it.

You're close... it's more like this:

const int note[22] = {35,36,37,....,54};
 
IS THIS CORRECT?

const int note [22] = {36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58};

const int pin [22] = {A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20,A21,A22};
 
Status
Not open for further replies.
Back
Top