Difference between revisions of "DIY electronic drumkit notes"

From Helpful
Jump to: navigation, search
m
m (Two-sensor logic)
 
(79 intermediate revisions by the same user not shown)
Line 1: Line 1:
  
  
 +
[[File:Drumkit test.jpg|thumb|300px|right|Listen. I was focusing on the electronics.]]
 +
''The idea: build a cheap electronic, velocity-sensitive, MIDI-output drumkit.''
  
=DIY electronic drumkit=
 
[[File:Drumkit test.jpg|thumb|300px|right|look, I was focusing on the electronics, okay?]]
 
The idea: build a cheap electronic, velocity-sensitive, MIDI-output drumkit.
 
  
There are many simple and cheap DIY ideas out there.  Check the usual video sites.
+
There are many simple and cheap DIY drumkit ideas out there.  Check the usual video sites.
  
 +
The most basic version of this is
 +
: sense a large impact on input pin
 +
: send according MIDI note on serial
 +
And most of them do that quite well, actually.
  
This is neat DIY project,
+
 
 +
I wanted to see if I could refine the idea a little,
 +
evaluating what you can improve, both electronically, and physically.
 +
 
 +
It's a neat DIY project,
 
in that it has analog and digital and physical things to figure out,
 
in that it has analog and digital and physical things to figure out,
all manageable but some quite educational.
+
manageable and educational,
Also satisfying result of something that makes sounds.
+
and it's pretty satisfying to have it not only work but make loud sounds.
  
  
Line 45: Line 52:
 
==Physical design==
 
==Physical design==
  
[[Image:padbounce.jpg|thumb|200px|right|pad bounce experiment: liquid latex formed in a piece of tupperware. The left one looks cruddy because I was impatient and took it out before it dried. The bounce works surprisingly well.]]
 
A few of those can be solved largely in '''physical design''', making your life easier once you get to the electronics and code.
 
  
 +
===Sensor related===
  
if you only want finger drumming, then life is much easier because the forces are much smaller, and so barely carry to neighbouring ones. I'd recommend your first version be this.
+
Many designs (even most of the fancier ones - see e.g. V-drum fixing videos) use a '''piezo sensor''' because not only are they cheap, they are great vibration sensors.
  
  
Beyond that, the question is how much you want it to be practice for real movement - in which case you need positioning makes sense and doesn't fall apart, a hihat pedal, etc.
+
For finger drumming the constuction can be small.
The cheapest nearly-toy e-drums are not ''that'' much more expensive than what you'ld spend making them. Particularly second had
+
+
  
 +
For harder drumming, you probably want decent-sized pads for aiming reasons, and the implied large surface is nice for a consistent amount of energy and resonance for you to measure, which also makes it a little easier to get a more ''predictable'' amount of energy.
  
[[Image:woodkick1.jpg|thumb|100px|right|This is a kickdrum (a.k.a. a piece of wood)]] [[Image:woodkick2.jpg|thumb|200px|right|...which is nothing more than a piezo (needs better attachment) and a socket]]
 
  
If you want to play as hard as regular drums this is a little harder to design well.
+
Keep in mind that on a solid board, the main resonant node is typically in the middle, so that's where you get best response.
  
Say, you probably do still want thing to stay in place,  
+
Also keep in mind that you want to attach a piezo in a way that transmits vibrations well, doesn't fall apart immediately, or preferably at all.  
but a solid construction will also be better at hard-coupling energy to the other sensors, so the more sensitivity you want (and the more velocity sensitivity you want) the more this becomes a design tradeoff you have to deal with.
+
  
If you don't care about the physical loudness of hitting pads, or the physical bounce,
+
A dollop of wood glue works well enough for testing, but likely to fail sooner rather than later.
then it's enough to put a piezo on the back of a piece of wood
+
Something solid holding it in might, if it's ''too'' solid, locally stress and damage the piezo over time.
  
 +
A holder with something soft may dampen the response, for better or worse. You at least want to know/control that.
 +
{{comment|(I plan on modifying something like [https://www.thingiverse.com/thing:2446460] with space for rubber (to connect) and foam (to isolate))}}
  
If you do care about the bounce and loudness, and about crosstalk and the false triggers that may cause on closeby pads, then the materials above and below the pad matter.
 
  
Good physical isolation is a little more work than you'ld think, if you want an otherwise quite solid thing. {{comment|(For example, I at one point had a MIDI guitar, which has piezos detecting the picking of each stringalike, which if you pick them hard enough will trigger the next one over even though they're mounted in rubber. Could be lessened with filtering by velocity at MIDI level, but that a commercial product has this issue is an indication of the problem)}}
 
  
These materials also change the strength of the signal and the resonance of the pad, so means your code shouldn't assume too much about the design, and means you may want at least basic calibration in the velocity detection part.
+
Also keep in mind that the wires on the piezo also carry shock directly to the piezo, so you probably want to isolate at least the last part of wire (Bit of foam, hot snot, or whatnot) from the part of the wire that may get touched or moved.
  
  
  
Many designs use a '''piezo sensor''' because they're cheap and work pretty well. For finger drumming the constuction can be small, for harder drumming you probably want decent-sized pads for aiming reasons, and the implied large surface is nice for a consistent amount of energy and resonance to measure, which also makes it a little easier to get a more ''predictable'' amount of energy. 
 
  
Keep in mind that on a solid board, the main resonant node is typically in the middle, so that's where you get best response.
 
  
Also keep in mind that you want to attach a piezo in a way that transmits vibrations well, doesn't fall apart immediately, or preferably at all.
+
===The bit you hit===
A dollop of wood glue works well enough for testing, but likely to fail sooner rather than later.
+
Something entirely solid holding it in might damage the piezo over time.
+
A holder with something soft may dampening the response a little, for better or worse.
+
  
I plan on modifying something like [https://www.thingiverse.com/thing:2446460] with space for rubber (to connect) and foam (to isolate).
+
Some of the mentioned issues can be solved largely in '''physical design''', making your life easier once you get to the electronics and code. [[Image:woodkick1.jpg|thumb|100px|right|This is a kickdrum, or rather, a piece of wood]] [[Image:woodkick2.jpg|thumb|200px|right|...which is nothing more than a piezo (needs better attachment) and a socket]]
  
 +
 +
'''If you only want finger drumming''', then life is actually fairly easy, because the forces are much smaller, and it's easy enough to design in a way where vibrations barely carry to neighbouring pads.
 +
 +
I'd recommend your first version be this, if only for the satisfaction.
 +
 +
 +
 +
'''If you want it larger and just want it to work at all''' - 
 +
 +
If you don't care about the physical loudness of hitting pads,
 +
or the physical bounce, or training for real playing (also e.g. hihat pedal and bass drum pedal feeling real),
 +
then it's ''basically'' enough to put a piezo on the back of a piece of wood with maybe a piece of rubber on it.
 +
 +
It'll work.
 +
 +
That test kickdrum 'pedal' in the image is made of a piece of hardish wood, a piezo disc, some glue.
 +
 +
 +
 +
'''If you want practice for drumming on a real drumkit''',
 +
then you want it to not only have velocity sensitivity,
 +
you also want a similar layout, a similar feel, bounce, and such.
 +
 +
Doing all of that is a ''lot'' harder,
 +
and having played on both a fifty dollar kit and one with meshes and rim sensors, yeah, the meshes feel a lot better.
 +
 +
 +
It's not even the sensitivity - I've played on both the cheapest and more expensive drumkits, and while the sensitivity of expressiveness is similar, the feel of playing different ways is more varied.
 +
 +
That difference may not be important in a "I'm making this because I'm trying out whether drumming is a hobby for me", but it does become important once you've decided that it ''is''.
 +
 +
 +
 +
For most other things, it can matter
 +
: to have something you can hit with a bunch of force, have it stay in place, and not break
 +
: to get a sensible bounce
 +
: to get a hihat pedal
 +
: to get sensors to detect edge hits
 +
: to get sensors to detect bell hits on cymbals
 +
: to get sensors to mute cymbals
 +
...and whatever else you can think of.
 +
 +
 +
Mesh heads turn out to be one way of imitating a real drum feel, because it basically ''is'' a drum,
 +
just with a quiet skin and no need for acoustic resonance.
 +
 +
It's a lot harder to try to DIY something similar.
 +
 +
 +
 +
Also, an large setup solid enough not to break is also hard-couple energy well,
 +
so unless you deal with mounting details, different sensors will easily get some of the energy from adjacent hits.
 +
 +
The more you want sensitivity, the more that matters.
 +
 +
It's not hard, but it's going to take iterations.
 +
Unless you really enjoy the DIY, at some point a cheap mesh kit is just worth buying.
 +
 +
 +
 +
[[Image:padbounce.jpg|thumb|200px|right|pad bounce experiment: liquid latex formed in tupperware. The left one looks cruddy because I was impatient and took it out before it fully dried. The bounce is surprisingly okay for something so basic.]]
 +
 +
If you do care about the bounce and loudness, and about crosstalk and the false triggers that may cause on closeby pads, then the materials above and below the pad matter.
 +
 +
Good physical isolation is a little more work than you'ld think, if you want an otherwise solid thing. {{comment|(For example, I at one point had a MIDI guitar, which has piezos detecting the picking of each stringalike, which if you pick them hard enough will trigger the next one over even though they're mounted in rubber. Could be lessened with filtering by velocity at MIDI level, but that a commercial product has this issue is an indication of the problem)}}
 +
 +
These materials also change the strength of the signal and the resonance of the pad, so means your code shouldn't assume too much about the design, and means you may want at least basic calibration in the velocity detection part.
  
  
Also keep in mind that the wires on the piezo also carry shock directly to the piezo, so you probably want to isolate at least the last part of wire (Bit of foam, hot snot, or whatnot) from the part that might move.
 
  
 
<br style="clear:both">
 
<br style="clear:both">
  
 
==Electronics==
 
==Electronics==
 +
 +
<!--
 +
===What kind of sensor?===
 +
 +
If you primarily care about triggers (and not velocity) there are a ''lot'' of different things that can do,
 +
from keyboard buttons to reflection sensors
 +
(e.g. [https://www.youtube.com/watch?v=OInd2ybB2uA this] uses a CMY70 as a distance sensor for trigger and velocity)
 +
 +
-->
  
 
===The piezo in a circuit===
 
===The piezo in a circuit===
  
Piezos are essentially stress sensors, so respond well to weight, impact, and vibration including that caused by impact.
+
Piezos are essentially stress sensors, so respond well to force/weight, impact, and vibration including that caused by impact.
 +
 
 +
 
 +
Due to their design, they can be seen as stress-to-voltage sensors, but also have a decent amount of capacitance, on the order of nanoFarads capacitor. 
 +
 
 +
 
 +
You can model a piezo as three things in parallel:
 +
* a stress sensor with voltage output
 +
* a few-nF capacitor
 +
* a GOhm-scale{{verify}} resistor{{verify}}
 +
 
  
Due to their design, they can be seen as stress-to-voltage sensors, but also have a decent amount of capacitance, on the order of nanoFarads capacitor.  {{comment|(You can model a piezo as a stress sensor in parallel with a capacitor, and a GOhm-cale resistor{{verify}}))}}.  
+
This combination means that, without any further components, it will hold the stress-generated voltage for a relatively long time, to the point that if you hook up a piezo directly to an ADC, you get what looks like a fairly steady voltage after each hit, that is at a different level each time.
  
 +
Resting a weight on the pad will give a proportional high value (falls off eventually).
  
That combination means it will hold the stress-generated voltage for a relatively long time, to the point that if you hook up a piezo directly to an ADC, you get what looks like a varying resting voltage between hits. Resting a weight on the pad will give a proportional high value.
 
 
You may even get small changes over time and with temperature as the piezo and/or the thing it's attached to expands or shifts.
 
You may even get small changes over time and with temperature as the piezo and/or the thing it's attached to expands or shifts.
  
You ''can'' write code to deal with such shifty input values, but it's messy, and there's more edge cases where you can get wild triggering, e.g. the voltage going out of range, which you can't really control.
 
  
 +
You ''can'' write code to deal with such shifty input values (largely by subtracting a recent average), but it's messy, and there's more edge cases where you can still get wild triggering, or e.g. the voltage going out of range, which you can't really control.
  
  
 
So many designs add a '''resistor across''' the piezo.
 
So many designs add a '''resistor across''' the piezo.
  
This is essentially a discharge resistor for the capacitance, which means the voltage output is now primarily the ''changes'' in stress, and will go to 0V the rest of the time.
+
This is essentially a discharge resistor for the piezo's capacitance, which means the voltage output is now primarily the ''changes'' in stress, and will go to 0V the rest of the time. {{comment|(it also means a ground-referenced ADC will only see half the wafeform, but that's probably acceptable)}}
  
You can quantify its impulse response, because the setup resembles an RC lowpass filter. Since a piezo disc's capacitance will probably be in the ballpark of 500pF to few dozen nF, and you probably want dropoff within a few dozen milliseconds, a resistance on the order of 100k&#x2126; makes sense.
 
  
More widely something in the range of 10k to 1M can make sense, varying with further component and design choices. {{comment|(If you wanted to make just the interface, and make it a more flexible "plug in any sort of piezo" design you could to add a ~1M trimpot, in series with ~10k as a minimum, so you can easily calibrate this later)}}
+
This setup resembles an RC lowpass filter, so you can quantify its impulse response.
  
 +
Since a piezo disc's capacitance will probably be in the ballpark of 500pF to few dozen nF (depending on its size), and you probably want dropoff within a few dozen milliseconds, you want a resistance on the order of 100k&#x2126;.
  
 +
{{comment|(More widely, something in the range of 10k to 1M can make sense, varying with specific components and further design choices. If you wanted to make a drum interface separate from the impact sensors and make it "plug in any sort of piezo", you could to add a ~1M trimpot, in series with ~10k as a minimum, so you can easily calibrate this later)}}
  
'''If you are multiplexing a single ADC''' {{comment|(example being an Arduino)}} you are likely to find the signal is cross-bleeding between the channels, giving responses on channels you're not hitting.
 
  
This is not because of muxing or sampling speed. It's because ADCs like the Arduino's are designed to sense things with lowish output impedance {{comment|(&lt;10kOhm for AVRs, see section "Analog Input Circuitry" in the datasheet)}}, and the mulitplexing counts on this. If the impedance of what you're measuring is higher than that, then the ADC's sample-and-hold capacitor starts interacting enough to become part of the sampling.
 
  
One thing you could do is lower the discharge resistor.  While lowering it to ~10kOhm lessens this crossbleed, it doesn't solve it, and comes at the cost of having a weaker signal as well as faster dampening, which both make it harder to be sensitive to velocity, and sensitive in general.
+
'''If you are multiplexing a single ADC and find the signal is bleeding between the channels'''.
  
[[File:Drumkit circuit.jpg|thumb|420px|right|Looks messy but is a simple circuit:<br/>Arduino Nano (muxes 8 analog pins),<br/>two LM324s for eight buffers,<br/>resistors to set the gains,<br/>and a serial MIDI socket (out of frame)]]
+
This is probably ''not'' because of flaws in muxing, or sampling too fast.
A better fix is presenting a low impedance to the ADC, via a buffer (which also implies the discharge resistor now only affects the dropoff), such as with a FET or an op amp.
+
 
 +
It's probably because ADCs like the Arduino's, and its muxing, are designed to sense things with lowish output impedance {{comment|(&lt;10kOhm for AVRs, see the "Analog Input Circuitry" section in the datasheet)}}.
 +
 
 +
If the impedance of what you're measuring is higher than that, then the interaction with the ADC's sample-and-hold capacitor starts to noticeably become part of the sampling.
 +
 
 +
 
 +
One thing you could try is lower the discharge resistor.  While lowering it to ~10kOhm lessens this crossbleed, it comes at the cost of having a weaker signal (making it less sensitive) as well as changing the RC circuit with the piezo to dampen faster (which makes velocity sensitity harder), and it only lessens the issue, and doesn't solve it.
 +
 
 +
 
 +
[[File:Drumkit circuit.jpg|thumb|450px|right|Looks messy but is mostly just wires, and everything for eight channels:<br/>- Arduino Nano (muxes 8 analog pins),<br/>- two LM324s (quad op-amps) for eight buffers,<br/>- discharge resistors,<br/>- eight 3.5mm sockets  and a a serial MIDI socket (out of frame).<br/><br/>
 +
Those op amps are configured as [[voltage followers]] (unity gain), because the large piezos I have happened to peak at a reasonable voltage as-is, but in general you want to control the gain e.g. with a [[non-inverting amplifier]].<br/><br/>
 +
Yes, I omitted the diodes in this.<br/>
 +
And yes, those are different-valued discharge resistors, I was experimenting.
 +
]]
 +
A better fix is presenting a low impedance to the ADC, via a buffer (which also implies the discharge resistor now only affects the dropoff), such as a FET or op amp.
 +
 
 +
 
 +
My personal preference is op amps, mostly because those will ''also'' easily let you control the gain {{comment|(and it's a little easier to breadboard, with quad op amp ICs)}}.
  
My personal preference is op amps, mostly because it's easier to tweak the gain {{comment|(and it's slightly easier to breadboard, with two or three quad op amps for 8 to 12 channels)}}.
 
 
That said, op amps come with further considerations, like that the output voltage swing is usually lower than the rail, so try to keep under that effective clipping level.
 
That said, op amps come with further considerations, like that the output voltage swing is usually lower than the rail, so try to keep under that effective clipping level.
  
{{comment|(You could do dedicated ADCs, or even MCUs per channel, but that makes communication a little harder.)}}
+
 
 +
<!--
 +
<br style="clear:both">
 +
 
 +
[[File:Drumkit opamp.png|thumb|300px|right|Note to self: add the diode]]
 +
 
 +
 
 +
{{comment|(You could do dedicated ADCs, or even MCUs per drum channel, but that makes communication a little harder instead)}}
 +
-->
  
  
Line 137: Line 243:
 
* If you care to build a buffer that also filters, take a look at e.g. {{search|AN4708 Signal conditioning for shock sensors pdf|AN4708 Signal conditioning for shock sensors}}.
 
* If you care to build a buffer that also filters, take a look at e.g. {{search|AN4708 Signal conditioning for shock sensors pdf|AN4708 Signal conditioning for shock sensors}}.
  
* Note also that you can only multiplex so much before you can't sample fast enough to get well defined oscillations per drum channel, start aliasing, and velocity starts being less robust. You may want to run the ADC faster, as the time resolution is more important than the noise.
+
* You can only multiplex so much before you can't sample fast enough to get well defined oscillations per drum channel, start aliasing, which would mean velocity starts being less robust.
 +
: You may want to run the ADC faster, as the time resolution is more important than the amplitude resolution or noise.
  
  
Line 160: Line 267:
  
 
How necessary this is depends on a ''little'' the choice of piezo and resistor, and specs of ADC/buffer,
 
How necessary this is depends on a ''little'' the choice of piezo and resistor, and specs of ADC/buffer,
: ...but it's a good idea in that it can help lifetime, and costs cents. They should be in my circuit.
+
 
 +
In a generalized design it's a good idea that it can help lifetime, and costs cents.
 +
They should be in my circuit.
  
 
===Detecting empty sockets===
 
===Detecting empty sockets===
 
<!--
 
<!--
The discharge resistor would probably be internal to your setup,
+
In theory, your code may do velocity a little more precisely if you sampling only sockets that are actually used.
which means you'll get near-0 values on all pins regardless of
+
whether something is connected or not.  
+
  
Which means you ''don't'' need to worry about [[floating inputs]] on unconnected pins causing false triggers.
+
Usually the difference will be tiny, so the easiest solution is to just ignore the problem entirely.
  
 +
But if you care:
  
In theory, depending on your code you may get slightly faster response if you are muxing to fewer channels that you have. Usually the difference will be tiny, so the easiest solution is to just ignore the problem entirely.
 
  
  
If you do want to do this, consider getting a type of socket that, when nothing is plugged in, connects to an extra pin on the socket (I'd recommend 3.5mm mono, because a bunch of them are without it being a special feature).
+
The discharge resistor would probably be internal to your setup (not the sensor you plug in),
 +
which means you'll get near-0 values on all pins ''regardless'' of
 +
whether something is connected or not.  
 +
 
 +
Which means you ''don't'' need to worry about [[floating inputs]] on unconnected pins causing false triggers,
 +
but also means you can't tell which is plugged in.
  
This lets you pull up to Vcc via a resistor.
 
It'll be a voltage divider and you'll get a pretty-constant not-near-0, which is easily distinguised at startup (or maybe just every so often).
 
  
 +
If you do want this, consider getting a type of socket that, when nothing is plugged in, connects to an extra pin on the socket (I'd recommend 3.5mm mono).
  
 +
If that extra pin is a pullup to Vcc (note: high value so that the voltage dividing effect when something is plugged is small), this is an easy to detect, should-never-happen-on-an-actual-sensor thing easily distinguised at startup (or maybe just every so often, to allow hotplugging).
  
 
-->
 
-->
Line 200: Line 312:
  
  
In a version that doesn't care about velocity, the loss of energy on the way may help, in that it may not cross the threshold for other pads.  
+
If you don't care about velocity, then the energy loss along the way may let you choose a threshold that is fine.  
A little threshold tweaking can help.
+
A little threshold tweaking can help (and you can make it adaptive).
  
  
Still, ideally your physical design avoids or at least reduces this.
+
Still, your probably want you physical design to lessens this a bunch.
  
Particularly when you ''do'' care about velocity, because the better the physical isolation is, the lower the 'played at all?' threshold can be, so the more we can support softer playing even while you're hitting something nearby harder.
+
Particularly when you ''do'' care about velocity, because the better the physical isolation is, the lower the 'played at all?' threshold can be, and the better we support softer playing without false triggering, even while you're hitting something nearby harder.
  
  
 
+
Yes, you also have the option of 'if two pads seem to hit less than a few ms apart, and one has rather lower intensity, then then maybe just trigger the strongest' - but
Yes, you also have the option of 'if two pads seem to hit less than a few ms apart, and one with rather lower intensity, then then maybe just trigger the strongest'.
+
* that means you have to delay all hits a few ms.
 
+
* this will sometimes ignore actual playing, and may punish good timing
This will sometimes ignore actual playing, and punish good timing, so ideally you improve the isolation instead.
+
...so improving physical isolation is the better solution.
  
 
===Velocity===
 
===Velocity===
  
Velocity makes things more interesting.  
+
Velocity isn't hard to do ''at all'', but doing it ''well'' makes things more interesting, and introduces some tradeoffs.  
  
 
There are various methods.  
 
There are various methods.  
Line 225: Line 337:
  
  
For example, we could watch channels for the initial hit. Once we decide it has been triggered, we keep sampling it as long as the values keep increasing, trigger once it starts falling, with the peak value as the velocity
+
For example, we could watch channels for the initial hit.  
 +
Once we decide it has been triggered, we '''keep sampling it as long as the values keep increasing''', trigger once it starts falling, with the peak value as the velocity.
  
 
This is probably the lowest-latency you can get, and it's simple code in that it doesn't need to store much.
 
This is probably the lowest-latency you can get, and it's simple code in that it doesn't need to store much.
However, high frequency content makes this sometimes stop too early/low, and using just the first peak may be a little less robust between similar hits depending e.g. on the resonance of your design. If/when (just) that first peak clips, it will always report the same value
+
However, high frequency content makes this sometimes stop too early/low.
 +
Also, using just the first peak may be a little less robust between similar hits, depending e.g. on physical resonance.
 +
Also, if the signal is so strong that it clips, it will always report the same (maximum) value.
  
  
Another way is to, once we decide to trigger, keep sampling for another 2-15 milliseconds, and average the values (or e.g. over-threshold time), and use that as the velocity.  
+
Another way is to, once we decide to trigger, '''keep sampling for a fixed time''' (perhaps 2-15 milliseconds), and average the values (or e.g. over-threshold time), and use that as the velocity.  
This fairly robust to any clipping of the initial peak.  
+
This is more robust to high frequency content, and to that potential initial clipping.
  
Because tiny peaks that were only just enough to trigger the "could this be a hit?" threshold, but the average would be very low, it's a little easier to reject it as probably-crosstalk or noise, while still allowing soft hits.
+
It may also be a ''little''' easier to tell the difference between soft hits on us, and physical crosstalk from other pads, because the latter will in most designs arrives more damped{{verify}}
: has a fundamental tradeoff between longer (more consistent velocity) and shorter sampling time (lower latency)
+
: can be done without storing samples in RAM (keep adding magnitudes to a large-typed counter, and divide by sampling time)
+
  
 +
It can be done without storing samples in RAM (keep adding magnitudes to a large-int counter, and divide by sampling time)
  
 +
However, it does come at the cost of higher, fixed latency.
  
Apparently there's some that try to find the envelope of the signal.
+
It also has a fundamental tradeoff between longer sampling time (more consistent velocity) and shorter sampling time (lower latency).
Probably more accurate, but slower, and harder to do
+
  
  
  
Since you don't have direct control over what pad voltage should correspond to the softest hardest hits (depends on the size of the piezo and the size of the pad), you may want to calibrate.  
+
Apparently there's some that try to '''find the envelope of the signal'''.
: A 'play a few sample hits on everything, and store that into EEPROM' is a simple and effective idea.
+
 
: This also makes it more a lot more modular/portable around varying physical designs.
+
This is potentially more accurate, but is harder to do,
 +
and to have this be lower latency may take even more care,
 +
and specificity to particular piezos.
 +
 
 +
 
 +
 
 +
 
 +
 
 +
Since you don't have direct control over what pad voltage should correspond to the softest hardest hits (depends on the size of the piezo and the size of the pad), you may need to trial-and-error those values.
 +
 
 +
Or, in a more practical/serious setup, let you calibrate that.
 +
: it's fairly simple to implement a 'play a few sample hits on everything
 +
:: and store that into EEPROM
 +
: This also makes it more a lot more modular/portable around varying physical designs/piezos.
  
 
That also makes it easier to change the curve away from linear by applying a function (e.g. a power).
 
That also makes it easier to change the curve away from linear by applying a function (e.g. a power).
Line 256: Line 383:
 
====Fast playing (flams, drumrolls), hard playing, and false re-triggers====
 
====Fast playing (flams, drumrolls), hard playing, and false re-triggers====
  
Playing harder means the signal is stronger, but also a slightly longer time it takes for the physical vibrations to taper off - may be up to 40ms or so.
+
Playing harder means the signal is stronger (nice in that it makes velocity easier), but also a slightly longer time it takes for the physical vibrations to taper off - may be up to 40ms or so.
  
So if you're reading fast enough, then you may see the tail end of one hit's peak, and it might still be high enough to trigger again.
+
So if you're reading fast enough, and your logic was "collect 8ms and decide hit or not; repeat",
 +
then the next collection may see the tail of the same hit's peak, which may still be high enough to cause that logic to trigger again.
  
  
A conceptually simple fix is to add the condition "AND did I not trigger in the last 100ms?" in your note-triggering code. {{comment|(100ms backoff on a channel is enough for basic playing, because that's 10beats/second = 600bpm and most playing is far slower)}}
+
A conceptually simple fix is to add the condition "AND did I not trigger in the last 100ms?" in your note-triggering code.  
  
 +
A 100ms backoff on a channel is enough for basic playing, because that's 10beats/second, = 600bpm, and most playing is ''far'' slower.
  
That said, things like flams and drumrolls are hits on the order of milliseconds apart, so if you care about these, you now ''do'' want to detect new hits before the last one has fallen off, so e.g. tell whether a half-waves was falloff from the last hit or a new one.
+
...except for flams and drumrolls, which are hits on the order of milliseconds apart, so if you care about these, you now ''do'' want to distinguish between a falloff and a new hit.
  
This is harder to get right. It's certainly possible, but involves some tradeoffs.  
+
This is harder to get right. It's possible, but involves some informed tradeoffs.
  
  
 
One decent approach is to  
 
One decent approach is to  
* '''normally''': leave a low threshold for triggers, because they come up from nothing
+
* '''normally''': leave a low threshold for triggers, because
:: a lower threshold can help lower latency a little
+
: they come up from nothing  
 +
: a lower threshold can help velocity sentitivity (a little)
 +
: a lower threshold can help lower latency (a little)
  
* '''for some time after a note trigger''': temporarily set a higher threshold, base it on the last emitted's strength.
+
* '''for some time after a note trigger''': temporarily set a higher threshold
:: one issue is determining that new threshold reliably - you probably want it lower than the first peak, but higher than the average.
+
: ...based on the last triggered note's actual strength if possible
 +
: one issue is determining that new threshold reliably
 +
:: you probably want it lower than the first peak
 +
:: but higher than the average or you risk retriggers
  
  
This creates a (potentially configurable) balance between
+
This means a balance between
 
: general threshold low for lower-latency triggers,
 
: general threshold low for lower-latency triggers,
 
: evade most dampened peaks from the same hit,
 
: evade most dampened peaks from the same hit,
 
: still catch most similar-velocity hits.
 
: still catch most similar-velocity hits.
 
  
 
If you do velocities, then you may like the ability to tweak the curve on the fly.
 
If you do velocities, then you may like the ability to tweak the curve on the fly.
 +
 +
You may want some parameters to bias this towards one behaviour or the other.
  
  
Line 297: Line 432:
 
===Hihat logic===
 
===Hihat logic===
  
If you care to practice for real hihats, you want to include the pedal.
+
If you care to have practice for hihats, you want to include the pedal.
  
 +
It should emit
 +
: pedal-hihat when pedal closes, note number 44 in GM {{comment|(name: G#1)}}
 +
: open-hihat when hit while open, note number 46 in GM {{comment|(name: A#1)}}
 +
: closed hihat when hit while closed, note number 42 in GM {{comment|(name: F#1)}}
 +
{{comment|(Those notes are from the [https://en.wikipedia.org/wiki/General_MIDI#Percussion General MIDI percussion] set, and some drumkits are known to deviate somewhat. Also, when setting these by name, remember the octave numbering is not well established within MIDI so may be off by one or maybe two)}}
  
Since the pedal should allow staying closed, a piezo isn't enough.
 
  
A basic footswitch works well enough, though making a sturdy one that feels something like a real one is a project of its own. I used a cheap sustain pedal for now.
+
Since the pedal should allow ''staying'' closed, you can't do that via a piezo, and will need one channel to read off a simple switch instead.
  
  
{{comment|In theory you could combine it with a piezo to also get velocity of the hihat close, but that's probably overkill, and I'm not sure a lot of drumkits even use that{{verify}}}}
+
Any basic footswitch should work (you can find them as e.g. sustain pedals for keyboards). This is one area where buying probably gives you something sturdier than making, unless you're a bit of a mechanical engineer already, because you learn to ''stomp'' on these things. 
 +
There are also sustain pedals that try to imitate piano-like resistance which might be closer to real practice (though check whether you can stomp on them).
 +
There are other options, like DIYing a swith onto a bass drum pedal.
  
  
It should emit
+
{{comment|In theory you could combine it with a piezo to also get velocity of the hihat close, but that's probably overkill, more work, and I'm not sure a lot of drumkits even use that information{{verify}}}}
: open-hihat when hihat is hit while open, note number 46 {{comment|(name: A#1)}}
+
: pedal-hihat when pedal closes, note number 44 {{comment|(name: G#1)}}
+
: closed hihat (42 in GM) when the hihat is hit while closed, note number 42 {{comment|(name: F#1)}}
+
 
+
(those notes are from the [https://en.wikipedia.org/wiki/General_MIDI#Percussion GM percussion] set, it might vary somewhat. And remember the octave numbering is not well set within midi, it may be +- 1{{verify}})
+
  
 
===Two-sensor logic===
 
===Two-sensor logic===
 
<!--
 
<!--
  
rimshot is used to refer to one of three things
+
More professional drumkits tend to have two sensors in some element.
 +
 
 +
The reason depends a little on the element. For the snare, it's usually to separately sense hits on the rim.
 +
For cymbal elements, it may be sensing hits on their bell separately.
 +
 
 +
 
 +
Rimshot is used to refer to one of three things
 
* head+rim simultaneous,  
 
* head+rim simultaneous,  
:: a few techniques, including hitting a stick you laid down
+
:: a few distinct techniques, including hitting a stick you laid down
  
 
* rim-only (or -mostly) for clave-like sound (a.k.a. side stick)
 
* rim-only (or -mostly) for clave-like sound (a.k.a. side stick)
 
:: e.g. by laying your hand on the middle of the snare, hinging it hinging it from the middle
 
:: e.g. by laying your hand on the middle of the snare, hinging it hinging it from the middle
  
* the after-a-joke ba-dum-tss thing (snare, snare, cymbals (optional basedrum on the last))
+
* the after-a-joke ba-dum-tss thing  
 +
: snare, snare, cymbals  
 +
:: often using the head+rim on the snare{{verify}}
 +
:: optional basedrum with the cymbals
 +
 
 +
...and usually on the snare, though sometimes on toms
 +
 
  
  
Line 337: Line 485:
  
  
 +
'''Other things that drummers do, that may be hard to impossible to detect'''
 +
 +
 +
rim click, a.k.a. cross stick
 +
: sounds like a wooden click, not entirely unlike a clave
 +
: hold the stick (somewhat loosely) in the center of the snare, lift the outer end (the part over the rim) and land it on the rim
 +
: many reverse the stick (hold by head, land the handle), the difference is more of a taste thing (the argument seems to often be dynamics. This is a relatively small sound, which is often the point, but this may be a little louder than the other way so more balanced)
 +
 +
 +
 +
 +
 +
 +
https://www.youtube.com/watch?v=FstCw876T9M
 
-->
 
-->
  
 
===Muting logic===
 
===Muting logic===
  
Cymbals could be muted. I've seen kits with a strategically placed pushbutton,
+
Cymbals could be muted.  
but I'd suggest something capacitive, even if that's more work.
+
I've seen cheaper kits with a strategically placed pushbutton, and fancier ones with a capacitive strip (on the underside).
  
  
Probably via a NoteOff.  
+
Probably via a NoteOff (or NoteOn with 0 velocity).  
  
I think I've seen aftertouch for this use, but whether that works seems to depend on whether your drum software listens for this at all.
+
I think I've also seen [[aftertouch]] for this use, but whether that works seems to depend on your specific drum software.
  
 
===MIDI practicalities===
 
===MIDI practicalities===
Line 354: Line 516:
  
  
In my code I delayed sending NoteOff for ~10ms (unless the next trigger is sooner), mostly for debug reasons - it makes it easier for to see hits when something (physical/DAW) chooses to visualise it.
+
Most drum related sound makers only care for the NoteOn, but DAWs that visualize notes will get confused if NoteOffs never come, so my code sends a NoteOff ~10ms later (unless the next trigger is sooner than that).
  
  
Line 361: Line 523:
 
'''MIDI Velocity'''
 
'''MIDI Velocity'''
  
You may find that compared to the sound you get at velocity 100ish, velocities under 30 or so are barely heard - even [[ghost notes]] would probably be at 40-60.  
+
MIDI velocity works a little differently for drums than for other things,  
 +
because of the dynamics of typical playing.
  
Much lower and it'd sound like you're playing part of your kit from the next room.
+
Regular playing may be around 100, and compared to that, velocities under 30 or so are barely heard (and some software may not emit sound at all, or it'd sound like a kit played in the next room).  Even [[ghost notes]] would probably be at 40-60.
  
{{comment|(I spent a day trying to figure out why hits went missing when it was just that I'd spread them over the MIDI range, and velocity ~15 doesn't actually trigger a lot of drumkits)}}
+
{{comment|(I spent a day trying to figure out debug my electronics because hits went missing, when it was just that I'd spread them over the MIDI range, and velocities around 15 doesn't actually trigger any sound on the software I was feeding it into)}}
  
  
  
As such, you should think about tradeoffs, between more expressiveness (sounds more natural), better repeatability, and and allow ghost notes.
+
As such, you should think about tradeoffs, between more expressiveness (sounds more natural), better repeatability, and how much you care about ghost notes.
  
 
It helps to have
 
It helps to have
: good physical isolation (lets you do softer hits without triggering from neighbouring pads)
+
: good physical isolation between heads (you can't allow softer hits if you can't distinguish them from hits on neighbouring pads)
 
: calibration
 
: calibration
 
: habit in playing
 
: habit in playing
Line 386: Line 549:
  
 
If you want to get decent sounds for free, try options like
 
If you want to get decent sounds for free, try options like
* [http://hydrogen-music.org/ Hydrogen], which is cross-platform.
+
* a decent free drum VST
 +
: like [https://www.powerdrumkit.com/ MT-PowerDrumkit] - has fairly natural drumkit sounds, velocity senitivity {{comment|(and is free though has a click-once-at-startup annoyance, that you can disappear by contributing something once)}}
 +
 
 +
* ...in a VST host
 +
: e.g. a free one like [https://www.cantabilesoftware.com/ Cantabile]
 +
:: if you don't have ASIO hardware, tell cantabile to use the WASAPI output, 48kHz (or higher) if you can, exclusive mode if you can, and you may be able to get away with 384-sample buffer on generic modern hardware, for ~6ms latency which is decent for drumming.
 +
: or a DAW if you have one anyway
 +
 
  
* a decent free drum VST (like [https://www.powerdrumkit.com/ MT-PowerDrumkit]) in a free VST host (like [https://www.cantabilesoftware.com/ Cantabile]) or a fuller DAW if you have one.
+
* [http://hydrogen-music.org/ Hydrogen], which is standalone and cross-platform
: that VST has velocity senitivity so sounds pretty decent, and is free (though has a click-once-at-startup annoyance, that you can disappear by contribute something once)
+
: tell cantabile to use the WASAPI output, 48kHz (or higher) if you can, and you can usually get away with 384-sample buffer on generic modern hardware, for ~6ms latency which is pretty decent for drumming.
+
  
  
 
Linux has a steeper learning curve when it comes to MIDI routing, and low latency audio output.
 
Linux has a steeper learning curve when it comes to MIDI routing, and low latency audio output.
It's on my list of things to figure out -- later.
+
It's on my list of things to figure out and summarize.
  
 
[[Category:Audio]] [[Category:Hardware]] [[Category:DIY projects]]
 
[[Category:Audio]] [[Category:Hardware]] [[Category:DIY projects]]

Latest revision as of 14:42, 7 July 2022


Listen. I was focusing on the electronics.

The idea: build a cheap electronic, velocity-sensitive, MIDI-output drumkit.


There are many simple and cheap DIY drumkit ideas out there. Check the usual video sites.

The most basic version of this is

sense a large impact on input pin
send according MIDI note on serial

And most of them do that quite well, actually.


I wanted to see if I could refine the idea a little, evaluating what you can improve, both electronically, and physically.

It's a neat DIY project, in that it has analog and digital and physical things to figure out, manageable and educational, and it's pretty satisfying to have it not only work but make loud sounds.


Wishes

You may care about a few different things

getting enough energy to the sensor, and consistent amount of energy to it
more makes it easier to reliably measure impact and its velocity
detecting velocity
and getting it reproducably
getting minimal energy to neigbouring pads - i.e. physical isolation from others
avoid false triggers (without having to hard-ignore pads, which would be bad for real drumming)
allows us to be more sensitive
allows some choice between finger drumming and stick drumming (there's a large energy difference)
allowing fast drumming, without false triggers
we'll discuss why this is a thing later


having it be useful for practice
pads that aren't loud
half the reason is fewer complaining neighbours
relevant for stick drumming, not finger drumming
getting the pads to physically bounce roughly like their real-world counterpart
do hihat pedal properly
and potentially things like muting


Physical design

Sensor related

Many designs (even most of the fancier ones - see e.g. V-drum fixing videos) use a piezo sensor because not only are they cheap, they are great vibration sensors.


For finger drumming the constuction can be small.

For harder drumming, you probably want decent-sized pads for aiming reasons, and the implied large surface is nice for a consistent amount of energy and resonance for you to measure, which also makes it a little easier to get a more predictable amount of energy.


Keep in mind that on a solid board, the main resonant node is typically in the middle, so that's where you get best response.

Also keep in mind that you want to attach a piezo in a way that transmits vibrations well, doesn't fall apart immediately, or preferably at all.

A dollop of wood glue works well enough for testing, but likely to fail sooner rather than later. Something solid holding it in might, if it's too solid, locally stress and damage the piezo over time.

A holder with something soft may dampen the response, for better or worse. You at least want to know/control that. (I plan on modifying something like [1] with space for rubber (to connect) and foam (to isolate))


Also keep in mind that the wires on the piezo also carry shock directly to the piezo, so you probably want to isolate at least the last part of wire (Bit of foam, hot snot, or whatnot) from the part of the wire that may get touched or moved.



The bit you hit

Some of the mentioned issues can be solved largely in physical design, making your life easier once you get to the electronics and code.
This is a kickdrum, or rather, a piece of wood
...which is nothing more than a piezo (needs better attachment) and a socket


If you only want finger drumming, then life is actually fairly easy, because the forces are much smaller, and it's easy enough to design in a way where vibrations barely carry to neighbouring pads.

I'd recommend your first version be this, if only for the satisfaction.


If you want it larger and just want it to work at all -

If you don't care about the physical loudness of hitting pads, or the physical bounce, or training for real playing (also e.g. hihat pedal and bass drum pedal feeling real), then it's basically enough to put a piezo on the back of a piece of wood with maybe a piece of rubber on it.

It'll work.

That test kickdrum 'pedal' in the image is made of a piece of hardish wood, a piezo disc, some glue.


If you want practice for drumming on a real drumkit, then you want it to not only have velocity sensitivity, you also want a similar layout, a similar feel, bounce, and such.

Doing all of that is a lot harder, and having played on both a fifty dollar kit and one with meshes and rim sensors, yeah, the meshes feel a lot better.


It's not even the sensitivity - I've played on both the cheapest and more expensive drumkits, and while the sensitivity of expressiveness is similar, the feel of playing different ways is more varied.

That difference may not be important in a "I'm making this because I'm trying out whether drumming is a hobby for me", but it does become important once you've decided that it is.


For most other things, it can matter

to have something you can hit with a bunch of force, have it stay in place, and not break
to get a sensible bounce
to get a hihat pedal
to get sensors to detect edge hits
to get sensors to detect bell hits on cymbals
to get sensors to mute cymbals

...and whatever else you can think of.


Mesh heads turn out to be one way of imitating a real drum feel, because it basically is a drum, just with a quiet skin and no need for acoustic resonance.

It's a lot harder to try to DIY something similar.


Also, an large setup solid enough not to break is also hard-couple energy well, so unless you deal with mounting details, different sensors will easily get some of the energy from adjacent hits.

The more you want sensitivity, the more that matters.

It's not hard, but it's going to take iterations. Unless you really enjoy the DIY, at some point a cheap mesh kit is just worth buying.


pad bounce experiment: liquid latex formed in tupperware. The left one looks cruddy because I was impatient and took it out before it fully dried. The bounce is surprisingly okay for something so basic.

If you do care about the bounce and loudness, and about crosstalk and the false triggers that may cause on closeby pads, then the materials above and below the pad matter.

Good physical isolation is a little more work than you'ld think, if you want an otherwise solid thing. (For example, I at one point had a MIDI guitar, which has piezos detecting the picking of each stringalike, which if you pick them hard enough will trigger the next one over even though they're mounted in rubber. Could be lessened with filtering by velocity at MIDI level, but that a commercial product has this issue is an indication of the problem)

These materials also change the strength of the signal and the resonance of the pad, so means your code shouldn't assume too much about the design, and means you may want at least basic calibration in the velocity detection part.



Electronics

The piezo in a circuit

Piezos are essentially stress sensors, so respond well to force/weight, impact, and vibration including that caused by impact.


Due to their design, they can be seen as stress-to-voltage sensors, but also have a decent amount of capacitance, on the order of nanoFarads capacitor.


You can model a piezo as three things in parallel:

  • a stress sensor with voltage output
  • a few-nF capacitor
  • a GOhm-scale(verify) resistor(verify)


This combination means that, without any further components, it will hold the stress-generated voltage for a relatively long time, to the point that if you hook up a piezo directly to an ADC, you get what looks like a fairly steady voltage after each hit, that is at a different level each time.

Resting a weight on the pad will give a proportional high value (falls off eventually).

You may even get small changes over time and with temperature as the piezo and/or the thing it's attached to expands or shifts.


You can write code to deal with such shifty input values (largely by subtracting a recent average), but it's messy, and there's more edge cases where you can still get wild triggering, or e.g. the voltage going out of range, which you can't really control.


So many designs add a resistor across the piezo.

This is essentially a discharge resistor for the piezo's capacitance, which means the voltage output is now primarily the changes in stress, and will go to 0V the rest of the time. (it also means a ground-referenced ADC will only see half the wafeform, but that's probably acceptable)


This setup resembles an RC lowpass filter, so you can quantify its impulse response.

Since a piezo disc's capacitance will probably be in the ballpark of 500pF to few dozen nF (depending on its size), and you probably want dropoff within a few dozen milliseconds, you want a resistance on the order of 100kΩ.

(More widely, something in the range of 10k to 1M can make sense, varying with specific components and further design choices. If you wanted to make a drum interface separate from the impact sensors and make it "plug in any sort of piezo", you could to add a ~1M trimpot, in series with ~10k as a minimum, so you can easily calibrate this later)


If you are multiplexing a single ADC and find the signal is bleeding between the channels.

This is probably not because of flaws in muxing, or sampling too fast.

It's probably because ADCs like the Arduino's, and its muxing, are designed to sense things with lowish output impedance (<10kOhm for AVRs, see the "Analog Input Circuitry" section in the datasheet).

If the impedance of what you're measuring is higher than that, then the interaction with the ADC's sample-and-hold capacitor starts to noticeably become part of the sampling.


One thing you could try is lower the discharge resistor. While lowering it to ~10kOhm lessens this crossbleed, it comes at the cost of having a weaker signal (making it less sensitive) as well as changing the RC circuit with the piezo to dampen faster (which makes velocity sensitity harder), and it only lessens the issue, and doesn't solve it.


Looks messy but is mostly just wires, and everything for eight channels:
- Arduino Nano (muxes 8 analog pins),
- two LM324s (quad op-amps) for eight buffers,
- discharge resistors,
- eight 3.5mm sockets and a a serial MIDI socket (out of frame).

Those op amps are configured as voltage followers (unity gain), because the large piezos I have happened to peak at a reasonable voltage as-is, but in general you want to control the gain e.g. with a non-inverting amplifier.

Yes, I omitted the diodes in this.
And yes, those are different-valued discharge resistors, I was experimenting.

A better fix is presenting a low impedance to the ADC, via a buffer (which also implies the discharge resistor now only affects the dropoff), such as a FET or op amp.


My personal preference is op amps, mostly because those will also easily let you control the gain (and it's a little easier to breadboard, with quad op amp ICs).

That said, op amps come with further considerations, like that the output voltage swing is usually lower than the rail, so try to keep under that effective clipping level.



Relatedly:

  • You can only multiplex so much before you can't sample fast enough to get well defined oscillations per drum channel, start aliasing, which would mean velocity starts being less robust.
You may want to run the ADC faster, as the time resolution is more important than the amplitude resolution or noise.



Protecting your input

Diodes you see in a bunch of circuits seem to typically be ~5V zeners from ground to the input socket's signal, to clip peaks and protecting the ADC/buffer from larger piezo voltages, which could be a few dozen volts if hard-coupled and hit hard enough.


How necessary this is depends on a little the choice of piezo and resistor, and specs of ADC/buffer,

In a generalized design it's a good idea that it can help lifetime, and costs cents. They should be in my circuit.

Detecting empty sockets

Code

As the above electronic construction means self-dampening, the voltage output is amount of recent change.

That makes basic velocity-less code easy to write. Do analogRead, Is it above threshold, and have we not triggered this in the last 100ms or so? Then trigger MIDI note" goes a long way.


When you want velocity, and smartness to help isolation, then things become a little more interesting.


Physical isolation and sensitivity

If the physical part of isolation wasn't perfect, you'll still see a little of the force from neigbouring pads.


If you don't care about velocity, then the energy loss along the way may let you choose a threshold that is fine. A little threshold tweaking can help (and you can make it adaptive).


Still, your probably want you physical design to lessens this a bunch.

Particularly when you do care about velocity, because the better the physical isolation is, the lower the 'played at all?' threshold can be, and the better we support softer playing without false triggering, even while you're hitting something nearby harder.


Yes, you also have the option of 'if two pads seem to hit less than a few ms apart, and one has rather lower intensity, then then maybe just trigger the strongest' - but

  • that means you have to delay all hits a few ms.
  • this will sometimes ignore actual playing, and may punish good timing

...so improving physical isolation is the better solution.

Velocity

Velocity isn't hard to do at all, but doing it well makes things more interesting, and introduces some tradeoffs.

There are various methods. Some are simple, some are complex, some are slightly faster (latencywise), some are more consistent, some are handier for softer playing, etc.


For example, we could watch channels for the initial hit. Once we decide it has been triggered, we keep sampling it as long as the values keep increasing, trigger once it starts falling, with the peak value as the velocity.

This is probably the lowest-latency you can get, and it's simple code in that it doesn't need to store much. However, high frequency content makes this sometimes stop too early/low. Also, using just the first peak may be a little less robust between similar hits, depending e.g. on physical resonance. Also, if the signal is so strong that it clips, it will always report the same (maximum) value.


Another way is to, once we decide to trigger, keep sampling for a fixed time (perhaps 2-15 milliseconds), and average the values (or e.g. over-threshold time), and use that as the velocity. This is more robust to high frequency content, and to that potential initial clipping.

It may also be a little' easier to tell the difference between soft hits on us, and physical crosstalk from other pads, because the latter will in most designs arrives more damped(verify)

It can be done without storing samples in RAM (keep adding magnitudes to a large-int counter, and divide by sampling time)

However, it does come at the cost of higher, fixed latency.

It also has a fundamental tradeoff between longer sampling time (more consistent velocity) and shorter sampling time (lower latency).


Apparently there's some that try to find the envelope of the signal.

This is potentially more accurate, but is harder to do, and to have this be lower latency may take even more care, and specificity to particular piezos.



Since you don't have direct control over what pad voltage should correspond to the softest hardest hits (depends on the size of the piezo and the size of the pad), you may need to trial-and-error those values.

Or, in a more practical/serious setup, let you calibrate that.

it's fairly simple to implement a 'play a few sample hits on everything
and store that into EEPROM
This also makes it more a lot more modular/portable around varying physical designs/piezos.

That also makes it easier to change the curve away from linear by applying a function (e.g. a power).



Fast playing (flams, drumrolls), hard playing, and false re-triggers

Playing harder means the signal is stronger (nice in that it makes velocity easier), but also a slightly longer time it takes for the physical vibrations to taper off - may be up to 40ms or so.

So if you're reading fast enough, and your logic was "collect 8ms and decide hit or not; repeat", then the next collection may see the tail of the same hit's peak, which may still be high enough to cause that logic to trigger again.


A conceptually simple fix is to add the condition "AND did I not trigger in the last 100ms?" in your note-triggering code.

A 100ms backoff on a channel is enough for basic playing, because that's 10beats/second, = 600bpm, and most playing is far slower.

...except for flams and drumrolls, which are hits on the order of milliseconds apart, so if you care about these, you now do want to distinguish between a falloff and a new hit.

This is harder to get right. It's possible, but involves some informed tradeoffs.


One decent approach is to

  • normally: leave a low threshold for triggers, because
they come up from nothing
a lower threshold can help velocity sentitivity (a little)
a lower threshold can help lower latency (a little)
  • for some time after a note trigger: temporarily set a higher threshold
...based on the last triggered note's actual strength if possible
one issue is determining that new threshold reliably
you probably want it lower than the first peak
but higher than the average or you risk retriggers


This means a balance between

general threshold low for lower-latency triggers,
evade most dampened peaks from the same hit,
still catch most similar-velocity hits.

If you do velocities, then you may like the ability to tweak the curve on the fly.

You may want some parameters to bias this towards one behaviour or the other.


Consider also that some channels have their own logic

You're not going to do few-ms drumrolls on a kickdrum, so can reject this harder
fast playing on a crash cymbal amounts to a sustain so the speed doesn't matter as much - while on a ride drum or tom this is more important.

And it's generally useful to have distinct inputs be specific drumkit parts anyway, though, if only because then you don't have to think about configurable MIDI mapping.


If you vary trigger designs, e.g. have kickdrum just be a block of wood, consider physical design having a some way to tweak thresholds and curves per channel.

Hihat logic

If you care to have practice for hihats, you want to include the pedal.

It should emit

pedal-hihat when pedal closes, note number 44 in GM (name: G#1)
open-hihat when hit while open, note number 46 in GM (name: A#1)
closed hihat when hit while closed, note number 42 in GM (name: F#1)

(Those notes are from the General MIDI percussion set, and some drumkits are known to deviate somewhat. Also, when setting these by name, remember the octave numbering is not well established within MIDI so may be off by one or maybe two)


Since the pedal should allow staying closed, you can't do that via a piezo, and will need one channel to read off a simple switch instead.


Any basic footswitch should work (you can find them as e.g. sustain pedals for keyboards). This is one area where buying probably gives you something sturdier than making, unless you're a bit of a mechanical engineer already, because you learn to stomp on these things. There are also sustain pedals that try to imitate piano-like resistance which might be closer to real practice (though check whether you can stomp on them). There are other options, like DIYing a swith onto a bass drum pedal.


In theory you could combine it with a piezo to also get velocity of the hihat close, but that's probably overkill, more work, and I'm not sure a lot of drumkits even use that information(verify)

Two-sensor logic

Muting logic

Cymbals could be muted. I've seen cheaper kits with a strategically placed pushbutton, and fancier ones with a capacitive strip (on the underside).


Probably via a NoteOff (or NoteOn with 0 velocity).

I think I've also seen aftertouch for this use, but whether that works seems to depend on your specific drum software.

MIDI practicalities

(see also MIDI_notes#Percussion)


Most drum related sound makers only care for the NoteOn, but DAWs that visualize notes will get confused if NoteOffs never come, so my code sends a NoteOff ~10ms later (unless the next trigger is sooner than that).



MIDI Velocity

MIDI velocity works a little differently for drums than for other things, because of the dynamics of typical playing.

Regular playing may be around 100, and compared to that, velocities under 30 or so are barely heard (and some software may not emit sound at all, or it'd sound like a kit played in the next room). Even ghost notes would probably be at 40-60.

(I spent a day trying to figure out debug my electronics because hits went missing, when it was just that I'd spread them over the MIDI range, and velocities around 15 doesn't actually trigger any sound on the software I was feeding it into)


As such, you should think about tradeoffs, between more expressiveness (sounds more natural), better repeatability, and how much you care about ghost notes.

It helps to have

good physical isolation between heads (you can't allow softer hits if you can't distinguish them from hits on neighbouring pads)
calibration
habit in playing
may help to put a transform that makes the mapping from physical to MIDI velocities nonlinear.


A little tweakability to that can't hurt.

PC side

Drum sounds

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, or tell me)

If you want to get decent sounds for free, try options like

  • a decent free drum VST
like MT-PowerDrumkit - has fairly natural drumkit sounds, velocity senitivity (and is free though has a click-once-at-startup annoyance, that you can disappear by contributing something once)
  • ...in a VST host
e.g. a free one like Cantabile
if you don't have ASIO hardware, tell cantabile to use the WASAPI output, 48kHz (or higher) if you can, exclusive mode if you can, and you may be able to get away with 384-sample buffer on generic modern hardware, for ~6ms latency which is decent for drumming.
or a DAW if you have one anyway


  • Hydrogen, which is standalone and cross-platform


Linux has a steeper learning curve when it comes to MIDI routing, and low latency audio output. It's on my list of things to figure out and summarize.