FSR pedal

Status
Not open for further replies.

edrummer

Well-known member
I want to be able to change the notes played on pin A1 by using a FSR connected to A0. Can this be done by adding another condition to the if statements?

HTML:
/* 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
      }
  }
}
 
Last edited:
I finally get what you're asking (in your earlier thread).

Two approaches come to mind.

1) Augmenting the note array to include a 'bank' dimension so that the FSR pin reading is selecting the bank from a zone of readings.

So the note[] array becomes a matrix based on bank and pin values:
Code:
const int note[][PINS] = {
{36,46,56},
{37,47,57},
{38,48,58}
};

And calling for it when sending midi becomes:

usbMIDI.sendNoteOn(note[zone], velocity, channel);

Where zone is a variable set by the most recent reading on the FSR pin mapped into (in this case) three zone regions: 0, 1 and 2.

2) Applying some arithmetical function to the note value based on the modifier's reading. E.g. If modifier is in zone 1 add 1 to the note value so instead of 36 being sent as it would in zone 0 it will sent midi note 37.

The latter is less flexible but doesn't require two-dimensional arrays.


The other side is extracting a usable signal from the FSR. Assuming you understand how to extract a reading by setting it up as a voltage divider the next step is to map the potential outputs into a usable variable (to select the bank/zone).

The library ResponsiveAnalogRead() is usually helpful in taming an analog signal. But given the very low resolution you need I recommend using a very simple 'dead-band hysteresis system'. That's a fancy way of saying 'don't change the current setting unless the new reading is different enough from the old to really warrant it'. Since the user will be trying to get the middle of the zones on the FSR a wide 'dead band' where you don't change the current bank would probably give very good results as we're only looking for two bits of resolution for up to four zones.

Code:
rawZone = analogRead(A0);
if (abs(rawZone-rawZoneLag)>deadBandLimit){
   zone = map(rawZone, minRead, maxRead, 0, 2);
}
rawZoneLag = rawZone



This code with the bank/zone changes compiles but is untested
Code:
const int channel = 10;  // General MIDI: channel 10 = percussion sounds
const int PINS = 3;     // number of signals incoming

const int note[][PINS] = {
{36,46,56},
{37,47,57},
{38,48,58}
};
const int zonePin = A0;
const int analogPin[PINS] = {A1,A2,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
const int deadBandLimit = 100; // huge deadband but can very large for three state output

const int maxRead = 992; //enter the FSR pin reading at full pressure
const int minRead = 123; //enter the FSR pin reading at zero pressure 

int zone;        // calculated zone
int rawZone;     // raw pin reading
int rawZoneLag;  // lagged raw reading

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(200);
    piezo[i] = analogRead(analogPin[i]);
    rawZone = analogRead(zonePin);
    if (abs(rawZone-rawZoneLag)>deadBandLimit){
      zone = map(rawZone, minRead, maxRead, 0, 2);
      //Serial.println(zone);
      rawZoneLag = rawZone;
    }
    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[zone][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.sendNoteOn(note[zone][i], 0, channel);
        state[i] = 0; // go back to idle when
      }
  }
}
 
Last edited:
Genius!! I get just 2 different notes so far but it's a great start! I have the FSR connected to +3v and then to pin A0, Should I have a pull down resistor on that? One last thing, the FSR pin (A0) has to trigger 2 notes, one when fully compressed and another just before. So probably something like > 900 and between >800 but < 900. I'll work on the that and the middle note of pin 1.
THANK YOU!!
 
Last edited:
I put a 10k pull down resistor on A0, I get a range between 20 and 900. I'm not sure how to extract the signal from the FSR or where to enter it . I wonder if you could highlight the places where I could experiment with the values?
 
Inside the conditional that fires when your FSR reading drifts far enough from your last update is a Serial.print commented out.

Un-comment the line and change the variable to the raw value.
Code:
    if (abs(rawZone-rawZoneLag)>deadBandLimit){
      zone = map(rawZone, minRead, maxRead, 0, 2);
      Serial.println([COLOR="#ff0000"]rawZone[/COLOR]); [COLOR="#00FF00"]// use this to print min/max readings to calibrate the code[/COLOR]
      rawZoneLag = rawZone;
    }

Then set the values here from observed readings at rest and at full pressure.
Code:
const int maxRead = 992; //enter the FSR pin reading at full pressure
const int minRead = 123; //enter the FSR pin reading at zero pressure

The FSR is half a voltage divider. It doesn't really matter which half but to get increasing voltage with increasing pressure I think you put it in the upper half of the voltage divider as it's less resistive under stress and so the middle voltage should increase.

Best to goggle for resistor value but I'd guess 5kOhm but i think it depends on the resting, and full stress resistances from the datasheet.
 
Last edited:
I put a 10k pull down resistor on A0, I get a range between 20 and 900. I'm not sure how to extract the signal from the FSR or where to enter it . I wonder if you could highlight the places where I could experiment with the values?

Lol... pecking on my tablet took a while and you had posted in between.

Still possible there's a bug in my additions.

Also: try moving that same conditional code fragment outside the inner loop to the beginning of the main loop. There's no need to update that with every piezo reading and recall we're trying to keep a light footprint so the peak detection remains accurate.
 
I hope you don't have me confused with somebody who actually knows what they're doing. I tried to move what I thought was the right fragment, but got more of those error messages from some foreign galaxy. When I change the 3 pins to A0 A1 A2 the FSR plays different notes depending on how hard I tap it. I think that's a good thing relative to the final goal but I can hear 3 different notes.
 
Last edited:
Code:
void loop() {
[COLOR="#0000FF"] rawZone = analogRead(zonePin);
 if (abs(rawZone-rawZoneLag)>deadBandLimit){
    zone = map(rawZone, minRead, maxRead, 0, 2);
    Serial.println(zone);
    rawZoneLag = rawZone;
  }[/COLOR]
[COLOR="#FF0000"]  for (int i=0;i<PINS;i++){
    piezo[i] = analogRead(analogPin[i]);
    peakDetect(i);
  }[/COLOR]
  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}
Sorry ...you need to move the read as well.
 
I guess you have to show me I moved it to setup but now no sound

Code:
const int channel = 10;  // General MIDI: channel 10 = percussion sounds
const int PINS = 3;     // number of signals incoming

const int note[][PINS] = {
{36,46,56},
{37,47,57},
{38,48,58}
};
const int zonePin = A0;
const int analogPin[PINS] = {A1,A2,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
const int deadBandLimit = 100; // huge deadband but can very large for three state output

const int maxRead = 992; //enter the FSR pin reading at full pressure
const int minRead = 123; //enter the FSR pin reading at zero pressure 

int zone;        // calculated zone
int rawZone;     // raw pin reading
int rawZoneLag;  // lagged raw reading

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");
    for (int i=0;i<PINS;i++){
    //delay(200);
    piezo[i] = analogRead(analogPin[i]);
    rawZone = analogRead(zonePin);
    if (abs(rawZone-rawZoneLag)>deadBandLimit){
      zone = map(rawZone, minRead, maxRead, 0, 2);
      //Serial.println(zone);
      rawZoneLag = rawZone;
    }
    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 loop() {
  for (int i=0;i<PINS;i++){
    //delay(200);
    piezo[i] = analogRead(analogPin[i]);
    rawZone = analogRead(zonePin);
    if (abs(rawZone-rawZoneLag)>deadBandLimit){
      zone = map(rawZone, minRead, maxRead, 0, 2);
      //Serial.println(zone);
      rawZoneLag = rawZone;
    }
    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[zone][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.sendNoteOn(note[zone][i], 0, channel);
        state[i] = 0; // go back to idle when
      }
  }
}
 
Last edited:
Close! However it changes the notes on pins 2 and 3 as well. should only change 1 pin. The middle note is hard to zero in on. If you could show me how to adjust that zone I'll probably have to do that myself.
 
Correction! I guess 2 pins, If it can be limited to just changing pins A0/A1 and be able to adjust the zones we'd pretty much have it. When I replace A3 with A0 I can trigger 3 notes with the pedal as well which is what I want except the pedal should only have 2 notes but I can make the middle note the same if I find where they are. I tried changing these but it didn't work
{36,46,56},
{37,47,57},
{38,48,58}
 
Last edited:
I guess the bank system solution is not really needed if you're modifying only the one switch.
So going back to the code in post 1 I've tried a re-write. Can you try this one.

The changes are significant enough that new bugs are likely.

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 and hi-hat alteration by oddson -- un(der)-tested*
*/

const int channel = 10;  // General MIDI: channel 10 = percussion sounds

const int PINS = 3;     // number of piezo signals incoming
const int note[PINS] = {36,39,40}; // set the note values for each pin
const int hHat = 0; // index of with pin is High Hat and therefore which gets modified by zone setting from zonePin (hat pedal)
const int analogPin[PINS] = {A1,A2,A3}; //array of analog PINs 

const int zonePin = A0; // high-hat pedal pin
const int zone1 = 300; // >half hat
const int zone2 = 700; // >closed hat
const int zoneRefesh = 10; // mS between pedal updates -  hat pedal is low freq. so we can check every few mS.

const int thresholdMin = 60;  // minimum reading before a note will be generated (too low = phantom notes)
const int peakTrackMillis = 12; // how long to keep reading looking for the peak to become velocity
const int aftershockMillis = 25; // aftershocks & vibration reject

const int maxRead = 850; //enter the FSR pin reading at full pressure
const int minRead = 20; //enter the FSR pin reading at zero pressure 
const int deadBandLimit = 100; // huge deadband but can very large for three state output

int zone;        // calculated zone
int rawZone;     // raw pin reading
int rawZoneLag;  // lagged raw reading used to judge change magnitude

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
elapsedMillis zonePoll ; // millseconds between rawZone readings


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


void loop() {
  checkZone();   // checkZone polls the hi-hat modifer signal
  for (int i=0;i<PINS;i++){ // loop through piezo readings
    piezo[i] = analogRead(analogPin[i]); // piezo[] holds raw readings
    peakDetect(i); // check for peaks events and send note events
  }
  while (usbMIDI.read()) { 
    // MIDI Controllers should discard incoming MIDI messages.
  }
}


void peakDetect(int i) {
  int playNote;
  playNote = note[i];
  if (i==0){
    playNote = note[0] + zone;
  }
  switch (state[i]) {
    case 0:
      if (piezo[i] > thresholdMin) {
        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) {
        int velocity = map(peak[i], thresholdMin, 1023, 1, 127);
        usbMIDI.sendNoteOn(playNote, 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.sendNoteOn(playNote, 0, channel);
        state[i] = 0; // go back to idle when
      }
  }
}

void checkZone() {
  if (zonePoll>zoneRefesh) { // modifiying pedal is low Freq. so limit reads
    rawZone = analogRead(zonePin);
    if (abs(rawZone-rawZoneLag)>deadBandLimit){ //also limit by change size
      if (rawZone < zone1) { // below first zone edge must be zone=0
        zone = 0;
      }else if (rawZone>zone2) { 
        zone = 2;
      }else  {
        zone = 1;
      }
      rawZoneLag = rawZone;
    }
    zonePoll = 0;
    //Serial.println(zone);
  }
}
 
please test the code and report specifics.

(there's no way this code is doing that... maybe you didn't actually upload the new code?)
 
The pedal needs to trigger notes also, which it does If I replace A3 with A0 , so in the array there is now (A0,A1,A2) both the pedal and the pad on A1 work ok. The problem is it will also change the notes on A2, and I assume all other pins that would be included in the array. If A0/A1 can be somehow separated so that only the notes on those 2 pins are changed by the pedal and the rest are unaffected. I think we'd have it.



Code:
const int channel = 10;  // General MIDI: channel 10 = percussion sounds
const int PINS = 3;     // number of signals incoming

const int note[][PINS] = {
{36,46,56},
{37,47,57},
{38,48,58}
};
const int zonePin = A0;
const int analogPin[PINS] = {A0,A1,A2,}; //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
const int deadBandLimit = 100; // huge deadband but can very large for three state output

const int maxRead = 900; //enter the FSR pin reading at full pressure
const int minRead = 100; //enter the FSR pin reading at zero pressure 

int zone;        // calculated zone
int rawZone;     // raw pin reading
int rawZoneLag;  // lagged raw reading

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");
    for (int i=0;i<PINS;i++){
    //delay(200);
    piezo[i] = analogRead(analogPin[i]);
    rawZone = analogRead(zonePin);
    if (abs(rawZone-rawZoneLag)>deadBandLimit){
      zone = map(rawZone, minRead, maxRead, 0, 2);
      //Serial.println(zone);
      rawZoneLag = rawZone;
    }
    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 loop() {
 rawZone = analogRead(zonePin);
 if (abs(rawZone-rawZoneLag)>deadBandLimit){
    zone = map(rawZone, minRead, maxRead, 0, 2);
    Serial.println(zone);
    rawZoneLag = rawZone;
  }
  for (int i=0;i<PINS;i++){
    piezo[i] = analogRead(analogPin[i]);
    peakDetect(i);
  }
  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[zone][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.sendNoteOn(note[zone][i], 0, channel);
        state[i] = 0; // go back to idle when
      }
  }
}
 
Now the sketch in#13 changes just the notes on A1 but not A0. I just checked the sketch in #16 again, it does indeed trigger 3 notes with the pedal as well as pins A1/A2
 
Why wouldn't it ? The pedal would be almost the same as a piezo when connected to +3v Is there a way to add A0 to A1 in sketch 13?
 
Last edited:
...The pedal would be almost the same as a piezo when connected to +3v ...
FSR does not equal piezo.. and may need different signal processing to generate reliable MIDI messages.

Now the sketch in#13 changes just the notes on A1 but not A0. I just checked the sketch in #16 again, it does indeed trigger 3 notes with the pedal as well as pins A1/A2
I did not, and still do not fully understand what your intended behaviour from the HH pedal is supposed to be. It now appears to me that it is meant to generate notes on its own and it alters the notes of one (possibly two?) piezos by altering the note played but i'm not sure of exactly on the details on how this should work.



I think I've wasted enough time not understanding what the heck you're trying to do and not being able to test it on hardware.

So, before even trying to resurrect any of this code (or the dormant branches along the way) I need to be certain I understand the hardware and the intended note value scheme on the receiving end.

Pin values and Note values are both arbitrary but I think you prefer to use them as short-hand.

1) A0 I have assumed is a high-hat pedal. Is it an all electronic sensor or is it an FSR attached in some way to an acoustic HH's pedal?
2a) A1 is an identical sensor all the remaining piezos but, because it is the high-hat sensor, it needs to be modified by the pedal's current output value. How many positions did you want this to be sensitive to?
2b) Is there a second pin like this (other disc form HH)? Some of your comments made me wonder but most seem to indicate A0 modulates only A1 and no others.

When I replace A3 with A0 I can trigger 3 notes with the pedal as well which is what I want except the pedal should only have 2 notes but I can make the middle note the same if I find where they are.
This baffles me what your saying except that something has only two levels of sensitivity to something else.

3a) Please confirm: Is the HH pedal signal meant to generate notes on its own?
3b) if so, Is the HH pedal changing note value based on its peak value?
3c) Does it also need to be velocity sensitive and how would that work as each note value would get only half the velocity range unless you remap?

4) Are all sensors 'non-acoustic' in that they are not connected to resonating bodies but instead give a quick 'thud' peak value and then dampen very quickly?

There are a number of other issues around the FSR signal but I'll leave them for now.

A full description of the mechanism and/or the its signal characteristics when played on it's own and in conjunction with it's afflieated piezo(s) may be required.
 
I added a few more pins to the array and they all work, that is they all stay the same while pin 1 changes with the pedal. Now if I could just find out how make the FSR trigger notes on this sketch like it did in the other one. I don't see where you made A1 different than the other pins in the array so that it would be the only pin to change notes. Maybe you could point that out to me and include A0. Other than that I think it will work.
 
1) A0 is the hi hat pedal which is nothing more than a FSR and a 10k pull down resistor. It is compressed by a mechanical pedal.

2a) A1 is just another piezo like the other 20 pads. It needs to be modulated by A0 It should have at least 3 positions, 5 would be great!

2b) A0 modulates only A1 and no others.

3a) yes

3b) yes

3c) this I'm not sure of but it worked very well before. The 2 notes that the pedal triggers will be the chick sound (sound of the cymbals brought together and remain closed) and the other is the splash sound, with a mechanical hi hat you tap your foot down and quickly release it so the cymbals ring. I don't know if it was because of velocity or just the note triggering at that pressure but it worked so if possible keep it the same.

4) The pads are all the same they are just piezos mounted on plastic with rubber on top insulated from each other with foam. they do not resonate.
 
Last edited:
I'll try to explain what I'm trying to do, I've played drums professionally off and on for over 40 yrs. I bought a sample pad and built the 2 pedals to use in small venues instead of cramming a drum set in the corner of some restaurant. This works quite well but there are limitations to the one I bought. It has only 6 pads and there are other issues with it so I decided to build this one. That was over a year ago, I got frustrated and put it on the shelf for a while. Now I'm very close to completing and using it. There are 20 pads a bass drum and hi hat pedal. They all just send midi messages that trigger samples in the software program so it can be used for other instruments as well. I new the HH pedal was going to be tricky so I tried to do it in 2 parts, first change the notes on one of the pads, then worry about how to trigger the 2 notes with the pedal, maybe not the right approach. I wasn't sure how to create the splash note which is the hardest to recreate. and one of the limitations with the unit I have. It's very sporadic and unreliable. The bottom note or chick sound is easy but the splash was more responsive using the sketch in#16.
I am truly grateful for the help
 
Ok... great. As long as you're not in too much of a hurry I'm sure I can help you get there.

I'm away on business this week and will have only a tablet and no compiler but I'll have some time to try some blind code... since I can't test anyway without a complex test rig this might be ok if I'm careful and look up syntax and watch for missing semicolons.

I'll review your posts above in more detail tomorrow and will likelyhave some followup.

If you could enumerate the various samples that the hh would need to support and what the sticks and pedals are doing to make them that would be great.

Have you looked into velocity mapping in your sample player to avoid having to output two or more different midi note values from the fsr signal? It's not terribly complicated to do it with the Teensy if there's some benefit.
 
Just reading up on hh splash.

Looks like a quick transiton transition from high to mid level pressures tiggers.

Is the other sound I assume is them slamming shut? Low or mid to high.
 
Some hi hats use as many as 9 different samples to go from closed to open, I don't think the pedal is accurate enough to take advantage of all those. The one I have now only has 3. If it's not to hard 5 would be great because it will be used for other sounds as well. With the software program I use, I can build different drum kits for different kinds of music like a jazz kit a Latin kit and so on. So the pedal will have different samples depending on the kit. That is why I like to use just pin and note #. So when used for a hi hat, the pad that is controlled by the pedal is hit with a stick and will play a note with the open cymbal sound unless the pedal changes it. As the pedal is compressed the notes will change 4 more times each with the sound of the cymbals closer together until the last when they are together. The software has a choke group where you can place notes that kill each other. so when the open cymbal is hit it will ring until you hit the closed cymbal which kills it.
I'm not sure I follow you about the velocity from the fsr signal. It may be that just having the splash note in a zone just before the chick note is good enough. If I had a way to test the pedal with 2 notes I could tell. The pedal worked well in sketch #16 though. I would like to see and understand where some things are in the code so for example if I wanted to map the pedal to be used as a pitch bend if that's possible.
 
Last edited:
Status
Not open for further replies.
Back
Top