If the pedal notes were something like if A0 > threshold for > X milliseconds play note #42, if A0 > threshold for < X milliseconds play note #43?
But the splash, unlike the chick, is produced when transitioning from closed to open, correct?
And the chick is the sound you get when you close the pedal (which I assume has a short envelope as the closed cymbals dampen quickly)?
The logic is based on the close-point. If an open cymbol is closed it will 'chick' (unless done very slowly) and if an closed cymbal is opened 'quickly-enough' it will 'splash'
(Technically the notes are supressed if the absolute difference in raw readings is not greater than a threshold value.)
Both will have velocity values proportional to the change in (raw) signal values on either side of the relvenant transition.
For 'splash' we're looking for a drop below the closed point and a raw value difference at least as great as minSplash.
So increasing minSplash will make the splash less sensitive and you will be able to release it more quickly without firing it.
But the timing parameter will also impact the other parameters and not always in a linear and predicable way.
I know you think we were close before and somehow a minor tweak will give you want you want but it's not that simple.
What I need now is to be sure the code I share with you has workable zone-boundaries.
I can't recall the way you set up the FSR as a voltage divider so I can't guess the min and max readings possible.
What is the value of that resistor and are you pulling to ground while the FRS is tied to HIGH signal?
So here's the line by line on the configuration. This is where 95% of the work remaining lies... we need to figure out how to get a usable signal from the FSR that does both zone-mapping of MIDI notes for A1 and can trigger notes itself when it's signal moves across the close-point from zoneMap() if the reading across the transition is above a threshold value.
Code:
//********************************************************************************* SET PIN OPTIONS**************
const int PINS = 3; // number of piezo signals incoming (does not include HH signal pin)
const int analogPin[PINS] = {A1,A2,A3}; //array of analog PINs used for piezo readings
const int zonePin = A0; // high-hat pedal pin <- I NEED THIS AT 'A9' FOR TESTING AND MAY FORGET TO RETURN TO 'A0'
These lines set the pins. Note I need to set to A9 on my test rig so I may share code with zonePin set to that instead of A0 so watch for that!.
If you have 20 piezo senors then PINS = 20 and the analogPin[] array needs 20 elements with the analog pin numbers in the order you want to read them.
Code:
//********************************************************************************* SET HIGH HAT ZONE CONFIGURATION OPTIONS**************
const int ZONECOUNT = 5 ; // number of zones for FSR as modifier for HH
const int zoneMap[ZONECOUNT] = {300,500,700,850,1024}; //raw reading value boundaries between zones
This stuff is key to getting a usable signal for note selection as well as finding the close-point you want to use for triggering splash and chick.
1024 makes sure the 'while' condition fails when j = 4 but it's the element before (shown as 850 here) that is the critical close-point of the pedal. Above this point the splash is possible if you release fast enough and if you rise to this point from below quickly enough it will 'chick'. These zones can be set with the timing parameter (below) set very large to keep the number of prints small.
Code:
//********************************************************************************* SET MIDI CHANNEL AND NOTE VALUES *************************
const int channel = 10; // General MIDI: channel 10 = percussion sounds
const int note[PINS] = {-1,36,38}; // note values for each pin - negative value flags to read the HH array instead
const int hhNote[ZONECOUNT] = {46,2,3,4,42} ; // note values for flavours of HH from open to closed (no general MIDI for intermediaries so used low values as placeholders)
const int splashNote = 55; // note value for 'splash' note sent by HH pedal
const int chickNote = 42; // note value for 'chick' note sent by HH pedal (no general MIDI so set to 'closed hat' for now)
This is where you configure for MIDI values.
The ones I'm not sure about are the chickNote, which I've set to the same as the closed HH hit, and the intermediate values in the HHNote[] array which I've set to non-drum map (low) note values 2,3 and 4.
The array note[] holds the midi note values for the piezo triggers with -1 there to indicate which PIN is the HH piezo. As I have it in the first entry that corresponds with the A1 pin in the analogPin[] array.
The note values sent by that pin are modified by the current zone value by selecting from the nnNote[] array with the current zone value.
Code:
//********************************************************************************* SET TIMING AND THRESHOLD ADJUSTMENT OPTIONS**************
//****PIEZOS
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 thresholdMin = 60; // minimum reading before a note will be generated (too low = phantom notes)
These are the pieizo settings for how long to window readings looking for maxima, how long to wait for aftershocks to die down before allowing a repeat note on that sensor and the minimum value that will trigger a note event (of the maxima tracked during the window set by peakTrackMillis).
This algorithm is unchanged from the example file you started with. It will break if there is too much processing outside of the main loop which is one reason to keep the FRS logic light and on a limited updated.
Piezo signals are typically in the audio range while the trigger event we're extracting is on the human time-scale. The algorithm relies on the vast difference in these time scales to find a representative maximum value to map into a velocity. There are other more robust methods of tracking a percussive signal envelope from a piezo should this turn out to be unreliable reading only one piezo per code loop.
Code:
//****HIGH HAT PEDAL
const int zoneRefesh = 8; // mS between HH pedal updates - hat pedal is low freq. so we can check every few mS.
const int minSplash = 150; // raw value difference required to fire 'splash'
const int minChick = 90; // raw value difference required to fire 'chick'
const int deadBandLimit = 10; // raw value deadband to limit HH updates above noise threshold - can very large with small number of zones
These are the settings that control the HH pedal's behaviour.
The settings I've listed here a likely more usable than in the posted code.
The first, zoneRefresh, is the minimum time between scans of the HH-FSR's raw reading. Set this too high and you get latency before zones change or notes fire. For setting the zoneMap[] you may want to turn this way up (500 mS?) to limit the data being sent to the serial montor/plotter while you get these values tuned. Once you have that I think single digits should work but if your pedal is too touchy you might want to boost up to 10 or 12 and if it's working well you might want to creep the value downward as far as you can before note firing become difficult.
The values minSplash and minChick are the minimum difference between raw readings of the FSR after it transitions 'to' or 'from' zone 4 that will result in a note being generated.
I assume splash should be higher as you have to drop the pedal to get the sound and chick should still fire down into the delicate range. Note there are raw difference values and their optimum setting will depend on both the range of usable values you're getting from the FSR voltage divider and on how fast the zoneRefresh is set. If it's very fast (small value) then there is less time for the value to change and so a smaller value will represent the same speed of signal change when the FSR is polled more frequently. This makes these harder to tune and you should expect to have to come back to them each time you adjust the polling speed.