The Netduino is Microsoft’s answer to the Arduino. It runs using the .NET Micro Framework (.NETMF) which means you can program it using C# within Visual Studio and with whole bunch of useful .NET standard libraries at your disposal. It is a breeze to setup and get started.
The goal of this project is to construct a robotic drummer using a microcontroller as the robot brain and a few solenoids as actuators that make drum sounds. I had a Netduino lying around and it was the perfect choice for this project since multi-threading is supported natively. This helps to simplify the code base, since when I want to activate a solenoid, I can simply spawn a thread which turns on the solenoid, waits a moment and then turns off the solenoid, and I don’t have to worry about this delay effecting the timing of subsequent drum hits. I can even trigger a drum roll or complicated riff if I want. Accomplishing the same task on an Arduino without the help of multi-threading is not too difficult either, but would take some extra effort, so this was a good excuse to try out the Netduino and it’s capabilities.
I eventually was able to leverage the .NETMF Threading and Timer classes for even more. Here is a great reference on the basics of multithreading on .NETMF. I have each Beat in a BeatPattern running on a separate “Timer” thread. The KnockDetector also runs on a separate thread so the (relatively) heavy number crunching doesn’t interfere with the timing of the drums.
Playing a Beat Pattern
I wanted to use solenoids to produce drum sounds by banging on things. One of the most frustrating things about the 12V push solenoids i had was that they had no frame and return spring. To make them usable, I had to construct custom frames out of metal and find some really weak springs to spring them back to their starting position after they’ve struck a beat. I purchased a variety pack of 100’s of springs but none of them were weak enough! I finally found some that were sold individually at a local hardware store, but i had to “weaken” them further. The strength of a spring depends on the thickness of the wound metal and also the radius of the winding, so stretching them out to increase that radius works. Lacking a frame also made mounting your solenoids a challenge. It is much easier to just purchase solenoids that include a frame and return spring. You also end up with something less rusted and ugly (good thing they’ll be out of sight eventually)
The circuit for each solenoid resembled the following diagram, which comes courtesy of this Bildr page.
There are a few differences in my circuit. My power source comes out of the netduino 5V pin, so its weaker than the 12V used in this diagram. I also used a schottky diode instead of the zener diode pictured and a 1kΩ resistor instead of a 2.2kΩ resistor. If anyone has any insight on whether I’d be better off modifying my circuit, I would love to hear your suggestions, please do post a comment.
On the software side, I created a BeatPattern class which, among other things, consists of an array of Beats. Each beat has its own thread which I set up using the .NETMF Timer library. At the beginning of a measure, the main program calls BeatPattern.update() which tells each Beat in the pattern to get ready to play it’s corresponding solenoid at the right moment, depending on the tempo.
Here is an early version of the beat making portion of the project:
Hardware-wise, knock detection was quite simple. A piezoelectric buzzer can easily be used as a sort of knock or vibration or movement sensor if it’s correctly hooked up to an input pin on the microcontroller. Below is a diagram for the arduino.cc tutorial on this topic.
The software side of knock detection was more tricky. I set up a new thread to just listen for values coming from the knock sensor every 10 ms. Since this is an analog sensor, it has to be hooked up to an analog pin on the Netduino and will give you a continuous value (as opposed to a discrete 1 or 0). This means you end up getting a string of numbers for each hit. For example a single knock may give you the following values:
0 - 0 - 0 - 55 - 127 - 358 - 82 - 0 - 0 - 0
It looks like you can just take the highest numbers between 0’s to get your knock’s timing. This is true in some cases, however, a couple of knocks in quick succession may give you something like:
0 - 0 - 55 - 127 - 358 - 82 - 20 - 101 - 530 - 222 - 71 - 0 - 0
So to get both distinct knocks, I keep track of whether the current reading is on a “rising edge” or a “falling edge”. If rising and current value is starting to fall, the last reading was the peak. As always, see the code which is linked below for more details.
Finally I made a custom class called Knock with members “interval” and “volume”. Volume is simply the peak number from above, and to calculate the interval I used a Stopwatch class (copy it into a code file and include it in your project). Now I can store all my peaks in an array of Knocks for interpretation later.
Here are all the parts of this project prototype. The 3 solenoids, the breadboard circuit, the microcontroller, and of course the box which will house everything and has the piezoelectric buzzer installed on top. I also added a button because I’m considering using it as a very simple user interface to tell the drums when to start and stop.
Unless your knocks are in a steady “4 on the floor” pattern (think techno), determining the user’s tempo is a difficult task. Sometimes called “Beat Detection”, Tempo Extraction is a complicated process which is the subject of many scientific papers. It involves a lot of number crunching and can bring your microcontroller, which lacks a powerful processor, to a grinding halt, so to speak.
Drawing clues from research papers I found online, I wrote a very simplified version of a Tempo Extraction algorithm which performs well and yields a fairly reliable beat interval reading. It only works for the 4/4 meter which simplifies the task quite a bit. Keep in mind, this means there are 4 beats in a measure. A beat interval is the time between 2 consecutive beats. The beat interval value is computed in milliseconds and can easily be converted to a BPM (beats per minute) by dividing 60K by it. To convert back, again, divide 60K by your BPM value.
BPM = 60000 / BeatInterval
The rational behind the Tempo Extraction algorithm is that beats in a 4/4 pattern usually fall on a whole, half, quarter, or eighth note. So consecutive beats should generally have one of these intervals between them. I compare each beat to it’s previous beat, two beats ago, and three beats ago, then “normalize” the intervals by either dividing by 2 or multiplying by 2 since all the intervals should be multiples by this theory.
Then I perform the following steps on the array:
1. Sort the array of intervals
2. Find the median
3. Throw out the outliers
4. Take the average of what’s left
This gives me a pretty decent beat interval value. See the code linked below for the nitty gritty, though keep in mind its a work in progress. I would love to hear from anyone who has experience with any of the techniques described above and can suggest an improvements or alternative methods!
On a side note, I noticed one shortcoming of .NETMF is that it lacks support for generics, which means a lot of nice built in functions – like Sort() on an ArrayList – are just missing. I used extension methods to make my own algorithms on an ArrayList of integers. But extension methods don’t work out of the box, there’s a little trick I learned thanks to this guy to get them working.