FSR pedal

Status
Not open for further replies.
I fixed the errors, The chick works ok but the splash is very hard to get. I couldn't get the monitor to copy, no big deal the first is the chick.
Capture 7.PNGCapture 8.PNG
 
Cool... if you mean you get chick notes when you try for splash then it's likely a longer peak-following period is needed to allow the user time to let off on the HH-pedal after the attack.

I guess I missed copying the top of the sketch when I posted 99. Did you copy the missing lines from the earlier post?

The setting for this is here in the second value for peakTrackMillis
Code:
//***************************************** SET MIDI NOTE VALUE CONFIGURATION OPTIONS**************
//** two value arrays are for normal piezo in index 0 and HH pedal in index 1 (use !i in as index during PINS loops)
const int thresholdMin[2] = {60,800}; // minimum reading, avoid noise and false starts
const int velocityScaleMax[2] = {1023,1023}; // used to scale velocity as effective maximum
const int peakTrackMillis[2] = {12,[B][COLOR="#FF0000"]25[/COLOR][/B]};
const int aftershockMillis[2] = {25,45}; // aftershocks & vibration reject

Note: all of the two-value arrays have the HH pedal value in the second entry (index = 1) so that !i (say 'not-eye') will index the second entry when the index value is zero.


Increasing this will make it easier to get the splash but it may begin to feel 'laggy' (high latency) as the chick/splash notes can only fire after this many mS after the peak is first detected.

velocityScaleMax can be adjusted downward if the top-end of the velocity range is difficult to reach (but it doesn't limit results yet so watch for 'stupid' velocity values on the current version.
Lowering the first value will make velocity readings from the piezo 'louder' in their velocity values while lowering the second will increase velocity for the HH notes only.

aftershockMillis (currently at 45 for HH) can be adjusted downward if you can't chick-chick quickly enough (especially if you've raised the track value already as the new total-time between two hits being read is the sum of the tracking and aftershock values).
 
Last edited:
Ok, I probably won't get to it till later this evening but if there's anything else that can be adjusted let me know, Other than that seams to work well. Haven't tried the pads yet though.
 
I bumped the (const int peakTrackMillis[2] = {12,25}; up to 55 and it feels pretty good, I see what you mean about latency though. The pedal works great at 65, has a very realistic response but the latency is too noticeable. All and all I think this will be fine for the pedal. The pad however needs some work, I changed these numbers (const int HHstickNote[ZONECOUNT] = {46,47,48,49,50} ; You had 2,3,4 and then 42. I wondered why I could only get 2 different notes, it's because 2,3/4 are way down in the almost inaudible range. I will work on it this weekend and try to fine tune some more but hay I think we might have it!
 
2,3,4 are midi notes not velocity... the values you've given are assigned to other percussion in general midi standard.... I chose those because they're not typically used in percussion maps..

You need to set up your instrument to have partially closed notes assigned outside the core percussion note range or just give up on general midi and use whatever values you want. But the values in that array give you five note numbers for the open/ closed range.
 
I forgot to mention I'm just using a piano roll for testing, I don't have anything mapped yet but that's next.
A few questions-
1 what is the #12 in this line? (const int peakTrackMillis[2] = {12,25};
2 what is the reason you have 4-55's in this line? (const int HHsplashNote[ZONECOUNT] = {55,55,55,55,44};
3 where can I assign notes to all the pads not affiliated with the pedal?
4 can I buy you a beer? I think this is going to work,
 
Last edited:
I started mapping the the notes in Ableton, the splash and chick work good and the open note on the pad, the closed note is there but I still get rapid fire when pedal is all the way down.
 
I forgot to mention I'm just using a piano roll for testing, I don't have anything mapped yet but that's next.
A few questions-
1 what is the #12 in this line? (const int peakTrackMillis[2] = {12,25};
1) peakTrackMillis is the amount of time we scan for peaks before sending the note based on the highest reading. The first entry is for the regular piezo and the other is for the HH pedal sensor.

The current value (12) is from the original example sketch and should be OK for the 3 pin version but it might be a parameter you could tweak if, when you have the full pin count running, you were to find it gives too many dud notes. But note that this is the intrinsic latency of the controller. The higher these numbers the more lagging the feel will become and so these should be as low as possible. That's why peak-detection hardware circuits for each piezo are sometimes suggested for multi-pad use (a circuit holds a voltage analog of the signal's envelope and so a very small number of readings --potentially one-- can provide an accurate analog of intensity).

2 what is the reason you have 4-55's in this line? (const int HHsplashNote[ZONECOUNT] = {55,55,55,55,44};
2) To give you five zones for the hit-close-open range you inherit the same zones for the pedal notes. If you don't want to use it then the repeated 55 values say to use the same MIDI note for any open position.

If you wanted splash notes that rang-out differently based on how open the pedal is when triggered you could map intermediate samples {55,15,16,17,44} or you could require the zone to be below zone four by doubling 44 in the last two places. But I suspect the given config is all you'd need.

3 where can I assign notes to all the pads not affiliated with the pedal?
3) const int note[PINS] = {0,0,36};//,38,40,41,47,50,49,51}; // array of MIDI note values for read signals (0 placeholders for HH)
As it says, first two zeros are placeholders, the code doesn't even look at them so they could be anything; the code uses the values from the other two arrays for the HH settings. The rest are the midi note values played for all the remaining piezo but currently limited to one note from the A2 pin.

Recall this is one of a very few settings that changes when the PINS count changes. Removing '};//' will put the remaining 7 values back for PINS=10.

4 can I buy you a beer? I think this is going to work,

4) absolutely - I haven't touched a hi-hat pedal in 30 years and never played drums so I've never given the pedal a lot of thought. I'm not 100% convinced the sensitivity will be there for the pedal where volume-as-impact playing is wanted but it's reading volume-as-pressure. That's why I spent so much time working on an intensity reading that was based on the rate of change instead of raw peak. But it looks like pursuing that would require interrupt programming where you respond to interrupt signals instead of polling for values and I'm not up for that quite yet.

I started mapping the the notes in Ableton, the splash and chick work good and the open note on the pad, the closed note is there but I still get rapid fire when pedal is all the way down.
There must be a problem with the code that's supposed to suppress re-triggering chick notes. I'll have another look but I might need you to post details.

Can you post the cofig portion of the code you are running to make sure I don't alter any parameters?
 
This is the code I'm using now, it seams to be working now could be a hardware issue. I have to get it out of the breadboard and solder everything permanently. I have a lot to do today but I'll be in and out and try to work on it when I can. The pad not connected to the pedal seams to be clipping, it cuts off when I hit it hard, I think the plotter shows that.

Code:
//***************************************** SET PIN ASSIGNMENT CONFIGURATION OPTIONS**************
const int PINS = 3; // number of signals incoming
const int analogPin[PINS] = {A0,A1,A2};//A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20,A21,}; //array of analog PINs 

//***************************************** SET HIGH HAT ZONE CONFIGURATION OPTIONS**************
const int ZONECOUNT = 5 ; // number of zones for FSR as modifier for HH
const int zoneMap[ZONECOUNT] = {40,150,450,800,1024};
const int zoneClose = 800;

//***************************************** SET MIDI NOTE VALUE CONFIGURATION OPTIONS**************
//** two value arrays are for normal piezo in index 0 and HH pedal in index 1 (use !i in as index during PINS loops)
const int thresholdMin[2] = {60,800}; // minimum reading, avoid noise and false starts
const int velocityScaleMax[2] = {1023,1023}; // used to scale velocity as effective maximum
const int peakTrackMillis[2] = {12,55};
const int aftershockMillis[2] = {25,45}; // aftershocks & vibration reject


//***************************************** SET MIDI NOTE VALUE CONFIGURATION OPTIONS**************
const int channel = 10; // General MIDI: channel 10 = percussion sounds
const int note[PINS] = {0,0,36};//37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55}; // array of MIDI note values for read signals (0 placeholders for HH)
const int HHstickNote[ZONECOUNT] = {46,47,48,49,50} ; // note values for flavours of HH from open to closed (no general MIDI for intermediaries so used low values as placeholders)
const int HHsplashNote[ZONECOUNT] = {55,55,55,55,44}; // note values for splash/chick 


int zone; // calculated zone
int zoneLag; // zone during last note on event
int state[PINS]; // 0=idle, 1=looking for peak, 2=ignore aftershocks
int peak[PINS]; // remember the highest reading
int piezo[PINS];
elapsedMillis displayLimiter;
elapsedMillis msec[PINS]; // timers to end states 1 and 2
int zoneNote[ZONECOUNT][PINS]; // matrix of note values with zone alterations for HH and it's piezo calc'd during setup

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
  Serial.println("Piezo Peak Capture w/ HH pedal");
  //*****build matrix to hold zone options (different only for HH and it's piezo)
  for (int i=0;i<PINS;i++){
    for (int j=0;j<ZONECOUNT;j++){ 
      if (i==0){
        zoneNote[j][i] = HHsplashNote[j];  // HH pedal notes 
      }else if(i==1){ 
        zoneNote[j][i] = HHstickNote[j];   // HH piezo notes
      }else{
        zoneNote[j][i] = note[i] ;         // other piezo - same for all j
      }
    } 
  }
}

void loop() {
  for (int i=0;i<PINS;i++){
    piezo[i] = analogRead(analogPin[i]);
    if (i==0){ // calc zone if pin index = 0
      int j = 0;
      while ( piezo[0]>zoneMap[j] ) {
        j++;
      }
      zone = j;
    }
    peakDetect(i);
  }
  // MIDI Controllers should discard incoming MIDI messages.
  // http://forum.pjrc.com/threads/24179-...ses-midi-crash
  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}


void peakDetect(int i) {
  switch (state[i]) {
    // IDLE state: wait for any reading is above threshold. Do not set threshold too low. 
  case 0:      
    if (piezo[i] > thresholdMin[!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[!i]) {
      int velocity = map(peak[i], thresholdMin[!i], velocityScaleMax[!i], 1, 127);
      usbMIDI.sendNoteOn(zoneNote[zone][i], velocity, channel);
      zoneLag = zone;
      printMIDI(true, zoneNote[zone][i], velocity, zone, peak[i]);
      msec[i] = 0;
      state[i] = 2;
    }
    return;
    
    // Ignore Aftershock state: wait for things to be quiet again.
  default:
    if (piezo[i] > thresholdMin[i]) {
      msec[i] = 0; // keep resetting timer if above threshold
    } else if (msec[i] > aftershockMillis[!i]) {
      usbMIDI.sendNoteOff(zoneNote[zoneLag][i], 0, channel);
      printMIDI(false, zoneNote[zoneLag][i], 0, zone, peak[i]);
      state[i] = 0; // go back to idle when
    }
  }
}



void printMIDI(boolean on, int noteID, int vel, int zone, int peak){
  Serial.print("NoteOn: ");
  Serial.print(on);
  Serial.print(" NoteID: ");
  Serial.print(noteID);
  Serial.print(" Velocity: ");
  Serial.print(vel);
  Serial.print(" Zone: ");
  Serial.print(zone);
  Serial.print(" Peak: ");
  Serial.println(peak);
}

Capture 3.PNG
 
Maxing out on the raw reading is not a problem unless it happens a too light of a touch which would mean you don't have enough attenuation in the voltages coming from the piezo.

The real problem is if you haven't got your spike protection correct and the pins are actually seeing voltages above 3.3 v which could result in damage.

If you are getting max readings easily there's no point lowering the remap upper limit (velocityScaleMax[1]) as you will get 127 velocity note messages easily without lowering it.

I added that feature as you were previously suggesting you never saw full readings (or so I thought you said somewhere).
 
I haven't had a chance to do anything the last few days, I have a busy week and have to play tomorrow but I'll try to work on it this weekend. I do have 2 diodes on each pin, it may be adjustable in Ableton I just don't have time right now.
 
...it may be adjustable in Ableton I just don't have time right now.
It's adjustable only in hardware because if you are getting maximum signal levels with weak hits you're never going to get the range without lowering the signal voltage at the pin.

I'm not qualified to give signal conditioning advice beyond saying voltage dividers are typically used to lower a signal voltage. I'm not sure where in the diode protection that would go. I would think on the signal side or the part of the signal we're looking to (re)capture will have already been clipped off.

If you're too aggressive with the voltage divider and you can no longer get the maximum reading easily then the range can be remapped by lowering its scaling parameter:

const int velocityScaleMax[2] = {900,1023}; // first one is for piezo


But it's only a problem if you think it's one. If the force required to pin the voltage to the 3.3 v rail and result in 127 velocity feels ok to you then it's ok.

It's funny, a lot of references to piezo discs as data sources suggest amplification rather than attenuation of the signal is required.

No worries on if/when you get back to this... it's your project.
 
Turns out it was a volume issue in Ableton. All I had to do was lower the volume of the sample, problem solved! Hope to start putting it all together next week. I still have to finish the controller part, just 5 pots and 6 button switches for cc messages. I could get a separate board for that what do you think? Is there any reason it would have to receive midi messages or can it just send? The pots would control things like volume, reverb, delay etc. and the buttons on/off for scenes and loops or whatever you map them to. I can control these on the keyboard for now.
 
Status
Not open for further replies.
Back
Top