Campanello (2011)¶
Overview¶
Our current house came with a doorbell based on the wonderful technology of the 1980s. Rather than something old fashioned like solenoids and chimes, it was solid state complete with a terrible recording of real chimes. I imagine it also allowed you to select from some other horrible recordings, although they were unlikely to be more bearable than a simple two note chime. The other truly bizarre thing about this doorbell was that it was wireless and hence battery powered. This despite the fact that both the button and the ringer were covering up live wires. From the time we moved in, this proved to be much more trouble than it was worth, since the doorbell rarely rang when you pressed the button. Having previously lived in a house with an extremely simple and pleasant sounding doorbell, we set out looking for a better alternative.
Uninspired by any of the options we could find locally, the doorbell sat semi-broken for many years. At some point our daughter came home with a simple resonator bell from a music class she took at preschool. Like most of our kids' toys, I probably played with it more than she did, and thought it would make an excellent doorbell. My idea was to emphasize the fact that it was made from kids toys, making the mechanism completely obvious to a three year old.
Bells¶
Starting with the inspiration of kids toys, I found a cheap set of eight resonator bells for about $25. At the time, I was worried that this was kind of expensive, since the bells by themselves cost about as much as a simple doorbell. On the other hand, with eight bells, I figured I could make something a lot cooler than a simple two tone chime, so I wasn't too worried about it.
Parts¶
- Kids Resonator Bells. Rhythm Band RB2130.
Mallets¶
The cheap bell set I bought came with two plastic mallets. They produced a very loud and pleasant tone. Unfortunately I wan't able to buy the same mallets independent of the bells. I even went so far as to call the retailer and the manufacturer and while they both thought they knew which mallets would match, neither set did. I ended up making my own mallets out of wood. They are a little less bright sounding than the stock mallets, but they're easy to make and much better than any of the other options I found.
Parts¶
Wooden ball ¾". I found some at a local craft store, but they can be found in bulk online, including a hole already drilled for the dowel. Woodworks RB4000.
¼" wooden dowels, about 12" each. Again, these are easy to find locally. Woodworks BD9250.
Actuators¶
The most complicated part of the whole project was figuring out how to get the mallets to strike the bells. I originally bought some cheap surplus solenoids. They had a couple of problems. First they were pull based solenoids, so they would require a lever based design. They also didn't have any built in springs, so I would need to engineer some mechanism to return them to their rest position. More critically, the solenoid made a large clacking sound every time it was triggered. I spent some time trying to mitigate all these problems, but in the end the solenoids were too hard for me to use. Any small variance in the spacing of the components would drastically change the timing of the mallet striking the bell.
In the end, I was inspired by the Solar Xylophone in Make Volume 12. The Solar Xylophone uses geared pager motors in almost exactly the same application I was trying to produce. These motors had several things going for them. First, they were small and clearly didn't require a lot of power. They also included an arm with a spring that returns the arm back to a neutral position after they're turned off. The biggest thing I was concerned about was how hard it would be to adjust them to be consistent across all the bells. In the Solar Xylophone application, there is lots of hand tuning to get the balace of the mallets just right. In the end, the motors worked out perfectly. I was able to find a configuration that was relatively easy to replicate without hand tuning. The variance I did end up with was easy to fix in software, and would be easy to eliminate with better manufacturing techniques.
Parts¶
- Geared pager motors, one for each bell (8). Solarbotics GM10.
Mounting¶
Going back to the original goal, I wanted to find a mounting strategy that made the entire mechanism easy to see, while sounding nice. Since I wanted to mount this to a wall, I figured I would mount everything on a piece of plywood. I built several prototypes to test out the placement of all the components. The first big decision was to mount the bells upside down. This made it easy for the kids to see the mallets hitting the bells even when the whole thing was mounted above their heads. It also made it a lot easier to get the mallet to hit the bell without damping the tone. With the mallets moving down, the motors would need to let the mallets fall and then pick them up fast enough to prevent the heads from sitting on the bar. With the mallets moving up, the motor only has to turn on long enough to launch the mallet and then get out of the way. In this case only the amount of time the motor is on needs to be adjusted. This works out because the motors move extremely fast, and the spring is powerful enough to get the arm out of the way.
The only problem with the motors was that at $10 a piece, they were going to propel this project way past the point of being comparable to a doorbell I could buy commercially. Given how well they worked, I was clearly going to have to get over the cost and see this project as a fun project, rather than a simple, functional object!
Hinges¶
The one remaining issue was how to attach the mallets to the plywood. One option was to just drill a hole through the mallet and drive a nail into the board. My biggest concern with this idea was that the nail would loosen up over time. The other problem was that thin, long nails were all finish nails, with a head just barely larger than the rest of the nail. I didn't think this would do a very good job of keeping the mallet positioned correctly. It seemed like I needed some way to mount a screw perpendicular to the board and hinge the mallet to the screw.
I tried lots of different pieces of hardware to act as a hinge, from pieces of wire to cable hangers. Nothing I could find would both keep the mallet straight and not bind up with the screw. I had a basic design in mind, but I couldn't find any commercial solution that matched that design. Given that I had given up trying to make this a cheap project, it seemed like the perfect opportunity to play with 3D printing.
I designed a simple hinge in OpenSCAD and had it printed by Shapeways. For about $25 I got 10 copies of a simple hinge made that worked exactly the way I wanted (shipped from the Netherlands, no less).
Electronics¶
When I first started working on this project, I was mostly concerned about how to do the electronics. The most relevant thing I found was a project by Andrew Kilpatrick with almost the same inspiration: creating a doorbell that actually sounded pleasant. A short description of the project can be found under Door Chimes, although there used to be a longer description available as well. The key insight was to use a Darlington transistor array.
Another problem I had was dealing with motor noise. To reduce power, I put the microcontroller to sleep when not playing and wake up using a pin change interrupt on the doorbell pin. When the motors are running off the same power supply as the micro, this causes a lot of spurious interrupts as the doorbell is playing a song. The simple solution was to use completely separate power sources for the motors and the microcontroller. The BEAM Robotics Wiki has a good page on reducing motor noise which lists some alternative solutions.
The orignal design was prototyped using a Diavolino and a breadboard which was balanced on top of the mounting board. Since I had already made an effort to put the mechanical side of the doorbell on display, I decided the electronics needed a nicer finish as well. In the end I had two prototype boards manufactured using Laen's PCB Order. The first board is hidden downstairs in the basement and basically takes a serial input as well as a 5V power supply and converts it into a RJ45 plug. This is then connected to a Cat 5 cable which runs upstairs to the actual doorbell. The upstairs board is basically an Arduino clone, derived from the Diavolino schematics. The serial link is connected to a Linux server which allows me to update the doorbell software from my laptop, and to trigger songs using a very simple web server.
Software¶
The main feature of the software is playing the songs. Songs are stored as a list of two byte tuples. The first byte is a bitmask of which notes to play. Since there are exactly eight chimes, there is one bit per chime. The second byte indiciates the delay before the next note, in milliseconds. For delays longer than 255 milliseconds, another pair with an empty note bitmask can be used to add additional delay. The list of pairs is terminated with a pair of 0 values.
The following is an example of a scale.
const unsigned char scale_song[] PROGMEM =
{128, 255,
0, 245,
64, 255,
0, 245,
32, 255,
0, 245,
16, 255,
0, 245,
8, 255,
0, 245,
4, 255,
0, 245,
2, 255,
0, 245,
1, 0,
0, 0};
The PROGMEM
directive keeps the data in ROM and prevents it from being loaded into RAM.
Songs are decoded and played using the play_song
function.
void
play_song(const unsigned char *s) {
unsigned char notes;
unsigned char pause;
while (1) {
notes = pgm_read_byte(s);
s++;
pause = pgm_read_byte(s);
s++;
//Serial.println(notes, BIN);
//Serial.println(pause, DEC);
if (notes == 0 && pause == 0) {
Serial.println("All done!");
break;
}
play_note(notes, pause);
}
}
The main point here is that the pgm_read_byte
function takes care of reading the data from program memory, rather than reading from RAM.
The main work is carried out by the play_note
code:
// Masks to specify which pins we're controlling on which ports.
// Conveniently we can just mask the song bits without any math.
const unsigned char portc_mask = 0x3F;
const unsigned char portd_mask = 0xC0;
void
play_note(unsigned char notes, unsigned char pause) {
unsigned char portc;
unsigned char portd;
unsigned long wait;
portc = notes & portc_mask;
portd = notes & portd_mask;
PORTC |= portc;
PORTD |= portd;
// Mechanical spacing isn't constant, adjust motor on times.
// XXX Abstract this out.
delay(20);
bitClear(PORTC, 5);
delay(20);
PORTC &= ~portc_mask;
PORTD &= ~portd_mask;
// XXX wait = next - millis();
if (pause > 40) {
wait = pause - 40; // XXX
//Serial.print("Waiting: ");
//Serial.println(wait);
delay(wait);
}
}
There are a couple of things going on here. The first is that the output pins are mapped such that we're using the first six pins from the ATMega328P Port C, which corresponds to analog inputs 0-5 on an Arduino. The other two pins are the last two pins from Port D, which correspond to digital pins 6 and 7 on the Arduino. What this means in practice is that the note bitmask just needs to be split into two parts and then written directly to the port registers.
The other issue is a software fix to the fact that one of the mallets is significantly closer to the chime than the others. The solution is to turn off the motor for this one chime earlier than the others. This prevents the mallet from being pressed into the chime and damping it. This fix is currently hard coded into the code rather than being abstracted as a more general purpose solution.
Source¶
All the source files for this project including the circuit board designs, the Arduino source code as well as the simple web interface are available on GitHub.