Okay, so I saw this fun little knock box about two years ago. I knew that I had to own one but it was so close to Halloween that I knew I wouldn’t get it done in time so I waited until next year. Well, fastword a year and I still forgot about the box until the last minute. This year is different. I remembered about it nearly two months before Halloween so I definately have enough time.
Its fairly easy to make with just a piezo element for the knock sensor and a motor to provide the knocking feedback. The microcontroller the original author used was a picaxe and its been nearly 7 years since I last used a PIC controller (I’m more of an AVR fan). Being that I have so many Attiny85′s laying around, I’ll just use one of them. Control is as simple as listening for knocks and after a few seconds of silence, repeat the pattern back. Input the secret number of knocks and it plays a tune.
The box is simply a craft store project box that I found for a dollar. There was some brass hardware on the front as well as two hinges on the back. Since the clasp in the front didn’t fit the theme of the box, I removed the screws securing it to the box and filled them in with wood putty. I sanded down the sides of the box until smooth then hit it with a few coats of stain. When that was dry (about 24 hours) I gave it a few coats of clear polyurethane, sanding between coats. For some reason, it too the box nearly 4 days to completely dry to the point that it wasn’t still tacky. Since I have long since retired my lego collection, I had to get creative. Luckily for me, several people on eBay are selling individual pieces like the chain and the skeleton guy. I attached the piezo speaker directly to the top of the box with some contact cement.
The motor I originally tried was a cheap radio shack 6v motor for $2 or $3. Unfortunately, it didn’t have enough torque to move the weighted end and it had several ‘dead’ spots where it wouldn’t engage. I had even taken careful measurements of the motor’s dimensions and transferred them to Sketch-Up where I created a motor mount and later printed it in ABS. In the end, I rummaged through my junk boxes and found a motor that seemed small enough to fit.
To make the knocking sound, I took a small section of 12 gauge wire (about 1.5″) and made two loops – one for the knocking end and the other to mount to the motor. I used a hammer to tap the loop end of the wire over the motor shaft and used some super strong double stick tape to adhere the motor to the box. I had problems with the motor not returning fast enough and the knocking sound being too quiet. To fix this I put a weight (in this case a bolt) on the end. This gave it more than enough momentum to move the box and allows the motor to return fast. To get rid of that annoying clunk sound when it returns to the resting position, I glued some foam to the back of the weight.
The electronics consist of a driver for the motor and an amplifier for the piezo element. The motor driver is just a simple 2n2222 transistor with a protection diode across the motor. I had planned on using a MOSFET for the motor driver but I somehow lost one of them to my desk and the other is already claimed for the amplifier circuit. The amplifier lets the circuit detect quieter knocks and gets away from having to use the ADC which seems to be a theme with piezo based knock sensors. The amplifier consists of a NTE490 MOSFET which was measured to have a threshold voltage of 1.7v. The gate is biased at just under 1.7v by a series of 7 diodes and a 11MΩ current limiting resistor. The current is so small that the diodes don’t fully conduct and as such, only drop about 230mV each.
This allows the gate voltage to remain fairly stable at just under the threshold voltage, yet allow the piezo element to influence this level ever so slightly which turns the MOSFET on. Since the gate voltage remains stable due to the diodes, a wide input voltage range can be used. I had tested from 4.5V down to 2.4V will success. This design allows the circuit to consume under 20μA while idle. I know someone will point out that zener diodes would allow better control of the gate voltage, however there are two problems with that: (1) its hard to find a zener at that low of a voltage and (2) zener diodes require a minimum current to maintain their reverse voltage – usually several mA.
Once I was happy with the operation of the circuit, I drew up a quick board in DipTrace and laid out the board in just under 1.5″x1.0″. This allowed it to nicely fit on the smaller side of the box. The board was etched and then populated. I continued to test the microcontroller on the breadboard since I left off the programming header on the circuit board. Once the software was complete, it was loaded to the Attiny45 (no sense in wasting an 85) and placed on the board This could fit in a ‘tiny25 but I don’t have any on hand.
On the software side of things, the microcontroller sleeps while waiting for a knock to trigger an interrupt. Once triggered, TIMER1 begins counting. When the next knock occurs, the current TIMER1 value is recorded in an array and TIMER1 cleared for the next knock. This repeats until either TIMER1 overflows or the array is filled. If the overflow event occurs, then the knock timed out and it begins repeating the pattern back with the motor. A special even occurs when either 13 or 20 knocks are registered. When the first occurs, the box plays the Addam’s Family theme song. When the latter occurs, then the box waits for 15 seconds, then randomly begins knocking at the box for 30 seconds.
Recording and playing back the knocks is pretty straight forward. The only difficulty I had was with playing the music. I spent about 3 days trying to figure out why the AVR wouldn’t play anything. Come to find out, the breadboard was bad and wasn’t making good contact with the wires. Once I moved everything to a different part of the breadboard, it began working. For the music, I relied on this RTTTL parser as well as the playback code. I of course had to modify it some for different registers, different timer (timer0), as well as some optimizations. I found an Addam’s Family theme song online in RTTTL format, which was piped into the parser. The parser took a lot of the guess work out of converting the individual notes into timer/counter compare values. This way, it produces a PWM signal on a pin that gets fed to the piezo element.
The random knocking was just as easy. Instead of using the rand() function built into the stdlib.h file, I used a different pesudo-random number generator using an xorshift method. This reduced the code size significantly (by almost 1K), allowing the program to fit on the Attiny25 if needed. The random number is conditioned to make it fit in the range of 250 to 900(ms). This is used as the delay between knocks and is subtracted from 30000 (well, 31000). When the 30 seconds is up (when the original 31000 becomes less than 1000) then the knocking stops and it resumes its idle mode.
Since this was going to be a decoration as well as something fun to play with, I wanted the batteries to last as long as possible. This is why I spent so much time carefully designing the circuit. Believe it or not, I came up with about half a dozen attempts to condition/amplify the piezo signal before feeding it into the microcontroller. This ranged from simple transistor amplifiers with current mirrors (one-sided op-amp), to the built-in ADC. I just found that every other attempt would drain the batteries way too much. The ADC was just out of the question because the sampling frequency needed would mean that the microcontroller would be awake too much of the time. In the end, the circuit draws less than 20μA sleeping (idle), 1.28mA waiting for the next knock, and 326mA when knocking. The program itself takes up only 1602 bytes and uses 32 bytes of RAM (plus stack) so it should fit on an Attiny25 or smaller microcontroller as well.
AVR Attiny45 Hex