The doorbell has a boring sound. We can fix it.

ATmega328 + JQ6500 MP3 tutorial


Fellow Xin Che Jian member LuFeng came in with a good project and a stack of microchips: Microduino modules that can be programmed to play music off a memory card and a wireless doorbell that made a boring old doorbell sound. He’s new to arduino and the tutorials for these modules are fairly vague, so I thought this would be a good opportunity to write up a tutorial on using an Atmega328 and a JQ6500 to trigger sounds with a really simple program.

From left to right: UART serial programmer, ATMEGA328P, JQ6500 MP3 module, microSD module, and 2 channel amplifier

Here’s the tools we had, a really neat set of stackable modules called Microduino programmable with the standard Arduino IDE (though you might not know that by reading their website — for this ATmega328 at 5V and 16Mhz clock, you can tell the IDE that it’s an UNO, no extra hardware files are requried.)

While I used these modules to get this project to work, if you get these parts in a different format (maybe an Arduino UNO and a JQ6500 on a breakout board) the following instructions should be relevant to you, too.


So we’ll deal with two stacks separately first: the audio module with the usb port stacked on top of the memory card module and the ATmega328 stacked on the UART.

When you plug in the audio + memory card stack, two drives will show up on your PC: one is the internal storage on the MP3 decoder, you probably don’t want to touch that one. But the drive that shows up called “SD” is where we can drop our MP3s. Microduino’s wiki has some information on the necessary naming scheme: Our file will be called “001.mp3” and be placed in a folder simply named “01”


Audacity makes it easy to grab a short clip of our chosen sound: a nice piano arpeggio from a longer song. If you’ve never used Audacity, no problem, you can visit their website for a Mac or Windows executable, or if you’re on debian (ubuntu / kubuntu / mint etc) you can just open a shell and type “sudo apt-get install audacity” and it will magically be installed on your OS. File → Open your song, click and drag across its sound wave to select a portion of it, and hit play to listen to your selection. Once you’ve selected the few seconds you want to play, you can hit File → Export Selected Audio and choose your file type as MP3, save it with the filename ‘001.mp3’

With your mp3 moved to the ‘01’ directory of the SD card, we can unplug that module and start programming our ATmega328. The microduino wiki was really vague on how to write code to control the MP3 module, but thankfully it gives the model number of the IC it uses: JQ6500. So I searched for a “JQ6500 arduino library” and found something really well documented here. So download that library and add it to the arduino IDE in the usual way (Sketch →Import Library →Add Library… or unzipping into your sketchbook, whatever works for you.) Check out the example sketches, “Full Demo” and “HelloWorld”, but here’s my code to simply play the first file on bootup. (01/001.mp3)

https://gist.github.com/jazzyjackson/de8f905636a6a3a05fb5

The only part that may be different based on your hardware is line 5, the object declaration that defines what Arduino pins will communicate via software serial to the JQ6500 chip. Looking close on the underside of this particular breakout board, the default TX and RX serial pins (the ones not in parentheses) are labeled next to D2 and D3, which in Arduino IDE language corresponds simply to 2 and 3.


So I declared my object as mp3(2,3) but if you’re using a different breakout board for the JQ6500 you will have to determine which 2 pins are wired to JQ6500’s RX and TX and use those pin numbers in your “JQ6500_Serial mp3(tx, rx)” declaration. By the way, ‘mp3’ is a user definable name, it can be called whatever you want.

Once you’ve got that figured out, you can load the code to the little stack of UART + ATmega. Unplug it once it uploads, and join the two stacks together, and add the amplifier module on that, so you have a whole tower of modules. Oh, important thing to know at this point: if you try to power the stack via the audio module’s USB, it won’t work, it will try to boot into file transfer mode, so power it with the UART module or otherwise.


If everything has gone right so far, you can plug a little speaker (the aluminum 3W style pictured at the top is perfect and easy to get a hold of) into the amplifier and give it power you’ll hear your sample. Did it work for you? I hope so.

To get the sound to play only when our original doorbell rings, we have to add a conditional to our program: instead of just mp3.play() in the setup, we use an if statement in our loop so that the ATMega328 is constantly checking for an input, it’ll look something like this:

void loop(){
if(AnalogRead(A0) > 400){
mp3.play();
}
}

Our input will be the two wires that use to be the doorbell’s speaker. For this, I cut off the original speaker and soldered new wires into its place. One of these wires should just be grounded, and the other wire can be stuck into A0 for measuring.

To make a sound, the speaker is pushed and pulled by changes in voltage. ATmegas have a 10-bit analog-to-digital converter that is super useful for measuring changes in voltage. Instead of measuring if something is turned on or off (like a button, which is strictly on or off, digital, 1 or 0) the A0-A7 pins let you measure subtler changes like a speaker buzzing around in between high and low voltage (between 1 and 0 😉

The readAnalog function performs this measurement for us, and if you want to experiment with this you should try the File → Examples → Basics → AnalogReadSerial program, which lets you open the serial monitor and see what voltage the ATmega328 is measuring. When you have what-use-to-be-a-speaker wired to GND and A0, and watching your serial monitor when you ring the doorbell, you’ll see a number jump around and settle back to 0 once the doorbell stops ringing. So in the code snippet, our mp3 will be triggered whenever the voltage jumps above 0V. (the 400 is a number we pick. In arduino-land, zero volts reads as 0, and 5 volts reads as 1023. That’s just because the hardware on the chip has 10bit precision, which is to say, it can distinguish between 2¹⁰ different voltages. 2 to the tenth power equals 1024, and if you have 1024 numbers and want to start at 0, you get the range 0–1023. So any voltage it measures is returned as some number between 0 and 1023.)

However, this simple way of waiting for change in voltage is susceptible to a electronic hobbyist’s worse nightmare: noise. Even if things are wired correctly (but especially if they’re wired loosely) little spikes in charge from humans handling things or other more mysterious sources can cause a spike in measurement, thereby triggering our doorbell when no one is at the door.

A slightly more reliable way to wait for changes in voltage, then, is to use a handy feature of ATmegas called an ‘internal pullup resistor.’ This phrase didn’t make sense to me for a long time so I’ll elaborate a little: if there’s a signal that may naturally fluctuate and you want to prevent it from fluctuating, you can wire a resistor in between that signal and a power source (thereby “pulling the signal high”, making it a “pull up resistor”) or wire a resistor in between the signal and a ground source (thereby “pulling the signal down to ground” making it a “pull down resistor”). If I didn’t explain it well enough, search for more articles about it, it’s a super useful thing to understand.

ATmegas have one of these resistors built in inside the chip and it can be programmed to be connected to a power source or not (this is the magic of programmable computers…they are machines that re-wire themselves). It can keep the analogRead measurement pinned to 1023 until some other active component, like our speaker signal, interferes and pulls the voltage low (remember how the speaker gets voltage pushed and pulled? That’s why this can work by measuring from 0V or from 5V, we just want to wait for a change in voltage, doesn’t matter what direction.) So to set that internal pullup resistor and wait for a change away from 5V, our code will look like this:

https://gist.github.com/jazzyjackson/8996d6519b7cd0cbf965

Oh, and the pinMode(6, OUTPUT) and digitalWrite(6, LOW) is kind of silly, I’m giving myself an extra place on my tiny MicroDuino modules to ground the speaker. Arduino UNOs have 3 different places to GND things, but if you ever need more, you can set a pin low and it will work just the same as a GND pin. Just don’t ground something that uses lots of power, because this forces current to go through the chip.

But that’s the final program, and the final necessary wiring: old speaker pins plugged into GND and A0, JQ6500 connected to pins 2 and 3, and I’m using the 5V pin to power the doorbell. It use to be powered by 220V mains, but that part exploded for reasons I don’t need to go into detail about here. Did you ever see Wayne’s World? Fireworks. Suffice to say, this almost become a blog about how to build a replacement full wave rectifier out of diodes until it occurred to me that the parts that I want to use can be powered off 5V.

Now when the doorbell makes a sound, it triggers the arduino to command the JQ6500 to play its mp3 and we hear a nice piano arpeggio instead of a boring old simulation of a doorbell.

Leave a Reply

Your email address will not be published. Required fields are marked *