The project on a protoboard with a practice pad.
I needed a way to record drum tracks to go along with guitar, bass, and keyboards without the hassles of a real drum set (size, cost, volume). I went to Guitar Center and saw they had electronic drum sets. These use trigger pads and a trigger box/synthesizer and amp to simulate real drums. Many of the pads looked an awful lot like something else I’d seen… practice pads! While a real trigger pad costs around $100, I bought a practice pad for $12. They are round, plastic enclosures filled with foam and covered with a skin on the top. You can stick a piezo-electric sensor inside the foam of the pad, drill a hole in the bottom of the pad and wire the peizo to an RCA jack. Having already played with MIDI on the AVR 8535, I figured it would be trivial to filter the input from the piezo and generate MIDI events. This set up would lack a synthesizer but as I use a computer to record music I could just plug the drums into the sound card of the computer and use a software synthesizer (Cakewalk and Cubase work nicely and can be used to record the audio tracks as well).
The first step was to get the AVR to generate MIDI events. I chose to have it play a bass drum every second.
The wiring for the MIDI ports. Note that you only need the MIDI out for this project. I used an 74LS04N for the inverters (the things that look like triangles with a circle on the end) but they are not necessary if you haven’t got any on hand.
|Specifies the type of message (NOTE_ON for example) and the MIDI channel||The value of the note (E3 or G1 etc)||How hard the note is pressed|
|The 4 MSB are the message type
The 4 LSB are the channel
NOTE_ON is 1001 or 0×9
|0×00 to 0x7f||From 0×00 to 0x7f|
MIDI uses 3 byte words for each note. The drums are on channel 10 (0×9 in hex, since the first channel is 0). Each note plays a different drum. The velocity is how hard the drum is hit (determined by the AVR’s ADC). Only Status Bytes can have a 1 in the MSB so the range for the note and velocity are from 0 to 127. A velocity of 0 is used to turn a note off.
After this, the next step was to use the ADC to sample the input from the piezo to generate NOTE_ON events with different velocities. This was actually the most time consuming part of the project because I forgot to turn the pullup resistors off in the AVR (when I wasn’t hitting the “drum” and the piezo voltage was low, the AVR would source current from the input pin and the software would get wacky). After that, however, the development was straight forward.
Simply attaching the piezo to an input pin does not work. First, the voltage can get quite a bit higher than the maximum 5V. Since the piezo can be described as an AC voltage source, the voltage also goes negative (which makes the AVR misbehave). The latter problem is easily solved by placing a diode after the piezo. A potentiometer placed after the diode can be used to keep the voltage from exceeding 5V. This pot can also be adjusted for different sensitivity. Also the change in voltage on the input pin is so brief that the ADC will not often read it. The value on the pin must be held somehow, so I added a 100uF capacitor. However, without some way to leak current around the capacitor it will stay charged for a few seconds and trigger too many events. If you know how often the ADC samples each pin, you can find the right value of resistor by finding the time constant of the circuit. One last detail is that the AVR would generate events when I didn’t touch the piezo at all. I added a 1uF capacitor to filter out noise. All was good.
The circuit for each trigger input. The diode is need because the voltage between the piezo and the port is negative half of the time and we don’t want the input pins to source current. The potentiometer adjusts the sensitivity of the input. The 1uF capacitor is used to remove high frequency noise. The 100uF capacitor “holds” the input from the piezo long enough for the ADC to sample it. The 1M Ohm resistor leaks current to ground around the capacitor so that this value is not held too long. Other values can be substituted as long as the time constant remains the same. Replacing the 1M Ohm resistor with a higher value will result in multiple triggers for each event (without changes to the software) and lowering it may result in incorrect velocity values or missed events.
Connections for the ADC
Connecting a crystal to the AVR
The software is simple in concept. Just sample each of the 8 ADC inputs, one after the other. If the value exceeds a threshold, queue the appropriate MIDI bytes. The AVR has interrupts for ADC conversion finished and finished sending serial data. The program just needs to start one sample of the ADC, then the ISR for when the conversion finishes saves the value in a matrix and then goes on to the next pin and samples that. A loop in main() waits for the value in the matrix for each pin to exceed the threshold then queues the appropriate bytes. It also turns that channel off for however long you wish (I set it to 1/8 of a second). The queue code pops bytes off the queue and throws them into the serial data register, which automatically sends the byte. When it finishes, it triggers and ISR which I have coded to try and pop more data off the queue into the data register. After the 1/8th of a second expires, the main loop queues a NOTE_ON event with a value of 0×00 (you could use NOTE_OFF too). This it to keep the drum from play forever.
Further improvements would be to have an LCD display and buttons so that the user can adjust which drum each of the inputs is tied to, rather than having to reprogram the AVR. Settings and drum names can be saved in the AVR’s eeprom (quite a tight fit actually!). Since building this project I have gone ahead and planned these improvements out. They are described in “drum data.rtf” in the code zip file.
(Note, I can’t find this zip file anymore after moving hosting… sorry)