Audio Modulator Circuit

From Rebeldroids Wiki

Opening Crawl

A long time ago in a house far, far away ...

... I had a need for a particular circuit for my Hardware Wars Artie Deco build. It has occurred to me that folks here might want something similar in an actual Star Wars droid, so I thought I'd describe what I'd done.

First, a little background. For those who haven't seen Hardware Wars, Artie Deco (the films parody of R2-D2) has a single blue eye light that flashes "in time with" his sound effects. Of course the "lip syncing" is completely wrong, like everyone else's in Hardware Wars, but I'm not reproducing that. If I wanted no synchronization, it could be done with no circuit at all, merely by varying his light randomly while a sound was being played.

I wanted Artie's neopixels to actually be flashing in sync with his audio. To accomplish this, I needed a simple and cheap way to feed the audio level from my MP3 board (a Catalex Serial MP3 player) back into one of the Arduino Uno's analog inputs, where it could be read and then used to scale the brightness of the neopixels.

Essentially I needed something I could build with the parts I had on hand -- no chips, op-amps, diodes, or other specialized components.

After some research, I came upon the suggestion of using a voltage divider to take a mono signal into the arduino. I combined this circuit with a stereo-to-mono circuit (really just another voltage divider), stuck most of it in Artie's wiring plan, and proceeded to ignore it while I worked on other things that needed to be done.


Overview

The circuit consists of a few wires, two pairs of resistors, and one very common ceramic capacitor. Here is the schematic:

yXfvKqgl.jpg

On the schematic, the resistors are named R1, R2, R3, and R4 ... this is starting to sound like something meant for droids already!

The capacitor is C1. Capacitors like this are usually disc or pill shaped, brown, and have 104 printed on them, often with a letter at the end to specify tolerance. I salvaged mine from some random circuit years and years ago.


Disclaimer

I'm no electronics expert (as will be obvious to anyone that saw the way I wired and described this circuit originally). I have built this and it worked, but if you decide to build one yourself, you are doing so at your own risk. Please don't blame me if you smoke your Arduino/neopixels, catch your droid on fire, create a great disturbance in the Force, start a Galactic Civil War, or whatever.

I seriously doubt the circuit poses any inherent danger to anyone, but safety first. As always with electricity, be careful, take your time, and ask questions if something seems unclear.


Theory of Operation

If you just want to build the circuit, you can skip to the Circuit Construction section. This is mainly an explanation of how it works and why it is needed.

For that matter, if you already know how to turn schematics into actual electronics, then you can probably skip the entire rest of this article (the only thing of note is that the Output wire should probably end in a male breadboard pin, to plug into the Arduino's female header. Maybe the Shifter's 5V and Ground as well if you intend to use the Arduino pins for those.)

For the rest, it may seem like I'm explaining this a bit backwards, but that's because I'm starting with the primary function of the circuit (get a signal into the Arduino).

To understand this circuit, you'll need to realize that audio is a wave. For our purposes, imagine a sine wave. That wave has a center, and there are peaks both above and below the center line (for this simple wave, they are generally at an equal distance). The distance of the peaks from center is the amplitude of the wave.

Inside the computer, every point on the wave is represented as a positive or negative number (or zero). The number changes over time, but it can only be one value at any given instant. When you play the file, the numbers will get converted to a positive or negative (or zero for silence) electrical voltage. That voltage gets sent out the wire to your speakers or headphones or whatever.

For a "line level" output, the voltage usually varies by a maximum of around ±1 V from center. Other outputs can differ from this, either stronger or weaker. For some non-line level outputs like a microphone, it is often weaker ... on the order of ±0.2 V. For other outputs, like those for speakers or headphones, the signal can be stronger than line level.

There are two problems with this signal.


This Signal Is Not Used By The Alliance

Think about the basic shape of the sine wave: Like the Force, it has two parts. In this case, up and down. The electrical signal mimics this, but the center of the wave is at 0 V, so "up" and "down" become "positive voltage" and "negative voltage". That means that an audio signal is AC (Alternating Current). It's rather like the electricity supplying your house, only much weaker.

So the first problem we face is that an Arduino is a DC (Direct Current) circuit. Its analog inputs cannot understand negative voltages at all. At best, it will clip them at 0 V, ignoring everything below that, which kills half of the information in the wave (it would be like turning your speaker off and on very very rapidly). At worst, a strong negative voltage could even damage the Arduino. So we'll need a way to turn this AC signal into a DC signal before we can really think about reading it.

Well, what is a DC signal? It's just a voltage that doesn't go from positive to negative, right? It exists all on one side or the other of 0 volts. In our case, we want the voltage to be all positive.

But we can't just strip off the negative half of the wave, for the same reason we can't let the Arduino clip it.

I didn't have the parts to build a rectifier, so I'm not going to tell you to do it either. So to make the AC signal into DC, we need a way to SHIFT the voltage in one direction (positive). And part of this circuit does just that.


Voltage Dividers

To get this out of the way, I believe the capacitor mainly serves to smooth out the incoming AC signal a bit (the waves become smoother, less jagged), ultimately helping to make our lights a bit less flickery. It may also relate to impedance. Either way, the output of the capacitor feeds into a voltage divider.

A voltage divider is merely a simple circuit that creates a new voltage. This Modulator contains two of them. In the schematic above, the first voltage divider I want to look at is the part of the schematic that forms a vertical line below the word "Shifter" ... +5 V at top, the ground symbol at the bottom, with R3 and R4. That's the basic structure of a voltage divider: two resistors are connected to reference voltages, and an output lies between the resistors.

+5 V and 0 V (ground) are our reference voltages. Since R3 and R4 are equal in value (10 k ohms), the divider splits the difference between these exactly in half. If you built just this part of the circuit, and then measured the voltage at the point between R3 and R4, you'd get a constant +2.5 V (more or less)

If you are wondering what the point of creating 2.5 V is, think about what happens if we simply added it to our AC voltage.

The wave moves upward, right? If our signal, at any given instant, lies somewhere within ±1 V, and we add 2.5 V to that, then we'll end up with a signal that ranges from +1.5 V to +3.5 V. Both minimum and maximum are now positive values, so this is now a DC signal, which the Arduino can understand.


Now, there's actually another voltage divider in this circuit. It works in exactly the same way, but rather than creating a constant voltage, we're connecting it straight to our audio, which changes over time.


In Stereo, Where Available

I've mainly been talking about monaural audio. But let's think about stereo sound, because we need to decide what to do if our sound effects are all in stereo.

Stereo audio is really just two separate waves -- one for each ear. They are often called the left and right channels.

(If we wanted to represent this left/right channel thing with left/right eye lights, we'd essentially need two copies of our circuit so far, one for each channel. Most likely, you could connect the capacitor for the left circuit straight to the signal from the audio source, and eliminate R1 and R2. But only a monster could possibly want to eliminate R2.)

More to the point, Artie Deco only has one eye light, so I just had the one circuit. I did add something to cope with stereo, however.

The two waves of a stereo sound are usually very similar, but not identical. The more something moves to one side, the louder it gets in that ear, and the quieter it gets in the other ear, right?

That means the voltage increases on the left, and decreases on the right. So, for example, the left ear at some particular instant could be at +0.9 V, while the right ear at the same instant is at +0.7 V, even though they are otherwise the same wave.

We simply average those two voltages. That's what the stereo-to-mono section of this circuit does. The left and right signals are fed into the two inputs, and since R1 and R2 are equal, the divider outputs a voltage halfway in between. Halfway between +0.9 and +0.7 is +0.8.


Strong Am I In The (Electrical) Force ... But Not That Strong

About three sections ago, I said there were two issues caused by the way the electrical signals work. The second issue (finally) is that the line level signal is weaker than we'd like. As previously mentioned, the Arduino's analog input wants a voltage between 0 and +5 V, which it converts to a number between 0 and 1023 in your code.

We've taken the signal's voltage and shifted it upward. If silence was represented by 0 V before (no audio) then silence is now represented by 2.5 V. +2.5 V at the Arduino's analog input will be read as roughly 512.

If the signal varies by at most ± 1 volt, then the Arduino can only "see" a value of roughly 512 ± 205. That's about 40% of the range it could have.

A microphone signal is even worse. If the Arduino sees at most ± 0.2 V, the best range it can read in is about 512 ± 41. With this signal, it therefore takes a lot more change in the audio level to produce any change in the brightness of the lights.

Ideally, we would amplify the audio signal (make the waves taller) by the exact amount needed to turn our audio source's signal into exactly 2.5 V ± 2.5 V, so we end up with a peak-to-peak range of 0 to 5 V. Since I don't have any special electronic components, I couldn't do this amplification electronically. I have to live with scaling up the value after I read it from the analog input.


Circuit Construction

"If any of my circuits or gears will help, I'll gladly donate them" -- C-3PO


To build the circuit, we'll need a headphone (TRS) connector that still has a short length of its wires attached. I cut mine off of an old pair of dead earbuds, but you can buy them new if you want (in which case I'd buy a mono TS connector rather than stereo TRS).

My connector is stereo, so it has two obvious wires, one for each channel/ear.


Stereo-to-mono Converter

Strip a bit of the insulation off of one of the wires, and you'll see that inside is probably a bit of white thread-like padding that you can just ignore, and two thinner wires. These two are the Signal wire (usually colored green or blue for the left channel, and red for the right channel) and the Ground wire (copper).

You will probably have difficulty soldering anything to either wire until you strip off the acrylic coating that serves to keep the wires from shorting against each other. That's because it also serves to repel solder. In my case, I removed it with a tool purchased especially for the purpose (I burned it off with a cigarette lighter from dollar tree). Just use the briefest flame you can, otherwise you'll melt away the end of the wire.

Each Signal wire gets a 4700 ohm resistor soldered to it (those are R1 and R2). Once there's a resistor soldered to each wire, take the unattached ends of those resistors, and twist them together. Then twist that together with one of the leads from the ceramic capacitor. Solder these three leads together.


Voltage Shifter

Now we need to make the voltage divider. Take two wires. I used breadboard jumpers -- one red wire, one black -- that were cut in half with male connectors on the end, and the other end stripped to bare wire. Solder a 10k ohm resistor to the bare end of the red wire. If you are looking at the schematic, that's resistor R3.

You do pretty much the same with the black wire and R4, but there's an addition. The two ground wires from the earbuds can be soldered to one another, or not, as you choose. Electrically, they are already pretty much the same wire, because they are joined at the stereo plug. But you will need a wire to connect at least one of them to same black wire that R4 connects to (on the same side of the resistor). This provides a common ground between the audio source, the modulator, and the Arduino.


Putting It All Together

Another male breadboard jumper cut in half (in my case white) will serve as the output connector. It will plug into the Arduino's analog input. Take the bare end of this wire, the currently non-soldered ends of R3 and R4, and the non-soldered lead from the capacitor. Twist all four together. Then solder them.

To insulate the circuit, I used a liberal coating of liquid electrical tape on all of the exposed wires and leads. You could use regular solid electrical tape instead, or even heat shrink tubing if you can make it fit. (You probably should have put it on before soldering anything.)

I made a small 3D printed case to house the modulator circuit after I took the picture at the start of this page. It is just a thin plastic box with one hole on one end and three holes on the other, for the input and output wires respectively.


Interfacing

Now the circuit is complete. All that remains is to plug it up.

I need to not only have the Arduino react to the audio, I also need to be able to hear it. My MP3 board only has one headphone jack, so I used a standard headphone Y splitter. The input to the modulator circuit (that is, the 3.5 mm earbud connector) that I just described above is connected to one output of the Y. Artie's "audio system" -- just a simple pair of USB powered speakers -- is connected to the other output.

The red jumper (if you wired yours like mine) connects to +5 V. The black jumper connects to Ground. You can just use the appropriate pins on the Arduino if they are free.

The white jumper plugs into whichever one of the Arduino analog inputs you like. I used the first pin, Analog 0.


Coding

Now that the circuit is built and connected, we need to decide how to process the values the Arduino picks up from it.

The way this setup works in Artie (if I'm in audio modulator "mode") is that every time I go to update the neopixels, I read the current value of the analog input. That gives me the current strength of the audio signal. I use this value to scale the brightness of the neopixels when I update them. This happens over and over, constantly, even if no audio is playing (in which case, I hopefully read something below my noise threshold, and the light stays dark.)

From the previous discussion, you may have realized that we'll need to scale these values up. That's so the tiny voltage range our audio signal gives us doesn't give us dim light. In audio terms, we are normalizing. Arduino programmers probably are thinking of the map() function right now. Your instincts serve you well.

We also need to deal with the formerly negative half of the signal. Our analog input came from a voltage centered at 2.5 V, which the arduino interprets as a value of ~512, and it goes up and down from there. We want it to start at 0 and only go up. So we'll need some rectification (changing the negative values of the wave to make them positive). Through the Force, many visions you will see ... the past, the future ... math classes long gone. I suspect that if you slowly reread the bit of this paragraph that's in parentheses, many of you will sense the phrase absolute value.

This audio signal is also invariably going to have some electrical noise due to interference from other components in the circuit, nearby brushed DC motors, etc. And since our voltage range is tiny, noise tends to be more obvious. We'll need to ignore values below a certain threshold, otherwise our light will constantly flicker on and off, even when no audio is playing.


Data Smoothing

Audio waves -- even with the capacitor for filtering -- are complex and inherently jagged. Because I'm unlikely to be sampling the analog pin at a rate even close to the frequency of my mp3 files, I skip over a lot of the detail of the waves (which reduces their complexity and thus makes them smoother), but I also lose most of the continuity and smooth transitions between values (which makes the result more jagged). Since that's a wash, we still end up "inherently jagged".

The upshot is that the lights will probably end up very flickery if we just use the raw analog input on the neopixels. We can improve their behavior by taking the current value at the analog input and averaging it with the previous running average value. This will smooth out the waves further.

For simplicity, I'll back up and describe the result of doing this in terms of line level voltages, rather than the numbers from reading the input in code. If the audio jumps from 0 to 1 volt in one sample and then stays at 1 v for the next ten samples, the effect is as if we'd read 0 v for the first sample, 0.5 v for the second one ((0v + 1v)/2), 0.75 for the third ((0.5+1)/2), and so forth. Rather than immediately jumping, it gradually approaches 1. It falls off the same way ... gradually.

We probably want sudden spikes and drops to matter a bit more than this, so we need to treat the current value as a bit more important than the running average. That means we need a weighted average. In my case, I just take previous average and add the current input value twice, then divide the result by three. (previous+current+current)/3. In our imaginary scenario, this would be like reading ((0+0+0)/3) = 0 V, ((0+1+1)/3) = 0.667 v, ((0.667+1+1)/3) = 0.889 V, etc. This makes the lights a bit quicker to react, but still not as jittery as using the raw analog input.

(To be continued)