Difference between revisions of "Audio Modulator Circuit"

From Rebeldroids Wiki
(Created page with "I had a need for this circuit for my Hardware Wars Artie Deco build. However, I can see where people might want something similar in an actual Star Wars droid, so I thought I...")
 
(Sundry revisions for new, less stoopid wiring.)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
I had a need for this circuit for my Hardware Wars Artie Deco build.  However, I can see where people might want something similar in an actual Star Wars droid, so I thought I'd write up this document.
+
==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 [https://coub.com/view/1tvpu9cn 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 [http://www.da-share.com/misc/catalex-mp3-board-yx5300-chip/ 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==
 
==Overview==
  
For those who haven't seen Hardware Wars, Artie has a single blue eye light that [https://coub.com/view/1tvpu9cn flashes "in time" with his sound effects].  (As with everyone else's dialog in Hardware Wars, Artie's "lip syncing" is completely wrong, but I'm not reproducing that partIt could be accomplished with no circuit, merely by varying his light randomly for a few seconds after triggering a sound.)
+
The circuit consists of a few wires, two pairs of resistors, and one very common ceramic capacitorHere is the schematic:
  
To accomplish something similar with the Neopixel Jewel that I was using for his eye, I needed a simple way to feed the audio level of my MP3 board (a Catalex Serial MP3 player board) 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. As my convention deadline was rapidly approaching, I also needed to do it quickly.
+
http://i.imgur.com/yXfvKqgl.jpg
  
Essentially I had to build it with the parts I had on hand -- no special chips, op-amps, or other odd components.
+
On the schematic, the resistors are named R1, R2, R3, and R4 ... this is starting to sound like something meant for droids already! 
  
After some research, I came upon the idea of using a ''voltage divider''This consists of one very common ceramic capacitor (which I had already salvaged from some other circuit many years ago), some wires, and two pairs of resistors (named R1, R2, R3, and R4 ... this is starting to sound like something meant for droids already!).  You can see the resulting circuit on the bottom right corner of this image:
+
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.
  
http://i.imgur.com/vjOChIEl.jpg
 
  
 +
==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.
  
== Disclaimer==
+
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.
  
If you decide to build this yourself, you are at your own risk.  I seriously doubt the circuit poses much danger to you (except maybe the soldering iron), but be careful, and ask questions if something seems unclear.  Please don't blame me if you smoke your Arduino/neopixels, or catch your droid on fire, or whatever.  I'm no electronics expert, but I have built this and it worked.
 
  
  
 +
==Theory of Operation==
  
==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. 
  
If you just want to build the circuit, you can skip this sectionThis is just an explanation of what it is and how it works.
+
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 headerMaybe the Shifter's 5V and Ground as well if you intend to use the Arduino pins for those.)
  
To understand this circuit, you need to realize that audio, both in your computer/droid as a digital file, and as an analog electrical signal, is a [http://www.rebeldroids.net/gallery/displayimage.php?album=20&pid=68#top_display_media wave].    That means it has a center, and both positive peaks and negative peaks away from it.  The peaks of each wave represent amplitude, otherwise known as volume (tall = loud sound, short = quiet sound, at least when averaged together over time).
+
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).
  
(Note that I'm talking about monaural audio.  Stereo audio is just two separate waves -- aka channelsOne for each ear.  We don't need this for a single light, so we totally ignore one channelIf we wanted to react to both channels, say if we had two different "eyes", we can simply make a second circuit and connect it to a different arduino input.)
+
To understand this circuit, you'll need to realize that audio is a [http://www.rebeldroids.net/gallery/displayimage.php?album=20&pid=68#top_display_media wave]For our purposes, imagine a sine waveThat 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 the peaks of the wave are just numbers.  For the purposes of discussion, let's say the positive peaks are 127 and the negative peaks are -128 (the positive is one number shorter because the computer considers 0 to be a positive number.) When you play this file, these numbers will get converted to a positive or negative voltage, and that's what gets sent to your speakers or headphones or whatever.
+
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 ranges from about +1 V to -1 V.  For a headphone output, like the one on my MP3 board, the voltage range is even smaller (something below 0.2 V to -0.2 V)
+
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.
+
There are two problems with this signal.
  
  
 
===This Signal Is Not Used By The Alliance===
 
===This Signal Is Not Used By The Alliance===
  
First, either way is much weaker than we'd likeAn Arduino analog input wants a voltage between 0 and 5 V, which it converts to a number between 0 and 1023 in your codeIf it sees at most 1 volt, it can only give you a value of ~205 or less.
+
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) circuitIts 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 voltsIn 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.
  
If it sees at most 0.2 V, then things are even worse ... the highest value it can give you is ~41.  Instead of being able to distinguish between 1024 possible wave heights/voltages, you can only distinguish about 40It therefore takes a '''lot''' more change in the audio to produce any noticeable change in the brightness of the lights.  Ideally, we would ''amplify'' this signal (make the waves taller).  Since I didn't have any special electronic components, I couldn't do that.  I just had to scale the input in my code.
+
I didn't have the parts to build a rectifier, so I'm not going to tell you to do it eitherSo 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.
  
Second, think about the voltages a little further.  If they range from a positive voltage to a negative voltage, that means this is an AC (Alternating Current) signal.  Rather like the electrical wiring in your house, only much weaker.
 
  
However, an Arduino is a DC (direct current) circuit.  As I said before, the arduino's input wants a range of 0 v to 5 V (specifically, +5 V)  So the problem here is that the Arduino's analog input cannot understand negative voltages.  It's even possible that they could damage the Arduino input if strong enough.  We need a way to turn this AC signal into a DC signal.
+
===Voltage Dividers===
  
Well, what is a DC signal? It's just a voltage that ''doesn't'' go positive to negative, right?It's all one or the other.
+
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 impedanceEither way, the output of the capacitor feeds into a voltage divider.
  
We can't just strip off half of the wave, because both halves contain information. We need a way to SHIFT the voltage in one direction or the otherAnd that's what this circuit does.
+
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 R4That's the basic structure of a voltage divider: two resistors are connected to reference voltages, and an output lies between the resistors.
  
http://i.imgur.com/OQc3zLYl.jpg
+
+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.
  
In the schematic, the voltage divider is just the part of the circuit that's forms a vertical line between 5V at top and the ground symbol at the bottom, with R3 and R4 in between.  A voltage divider is merely a circuit that creates a new voltage somewhere in-between two reference voltages. We've connected it to 0 V (ground) and +5 V.  As R3 and R4 are equal in value (10 k ohms), the divider splits the difference between these reference voltages evenly, so if you measure the voltage at the point between the two resistors, you get +2.5 V.
+
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.
  
How can we use this?  Well if we take a signal that at any given instant is somewhere between -1 V and +1 V, and we add 2.5 more volts to it, then we end up with a signal that ranges from +1.5 V to +3.5 V.  Voila, we have an all-positive DC signal, which the Arduino can understand.  (Those numbers are just 2.5 - 1 and 2.5 + 1.  The same idea applies to a signal that ranges from -0.2 V and +0.2 V.  Instead of +1.5 V to +3.5 V, we'll get +2.3 V to +2.7 V, but it's still DC.)
 
  
And that's what the rest of the circuit does.  The two wires for our audio are connected, one to each inputThese go through resistors to the capacitor.  The capacitor smooths out the AC signal a bit (the waves become less jagged), ultimately making our lights a bit less flickery.  The capacitor is connected to the voltage divider, which adds its +2.5V to whatever is coming from the capacitorThen the output is connected to one of the Arduino's analog input pins.
+
 
 +
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 voltagesThat'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 ± 41With 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.
  
  
Line 68: Line 117:
  
  
You 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).
+
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.
 +
 
  
My connector is stereo, so it has two obvious wires, one for each channel/ear.  One of these earbud wires will be ignored because I only have one "eye" (if I had two, the second copy of the circuit would be connected to this other wire).
+
===Stereo-to-mono Converter===
  
===Input Side===
+
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).
  
Strip a bit of the insulation off of the wire we are using, and you'll see that inside is probably a bit of white thread-like padding, and two more wires: a positive and a negativeIt doesn't really matter which wire is which, but the positive is usually colored red or green and the negative is usually copper.  Each wire gets a 4700 ohm resistor soldered to it (those are R1 and R2).
+
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.
  
You will probably have difficulty soldering either wire unless you strip the acrylic coatingIt acts like invisible insulation and also repels solderIn my case, I removed it with a tool purchased especially for the purpose: I burned it off with a cigarette lighter from dollar treeJust use the briefest flame, otherwise you'll melt away the end of the wire that you are wanting to solder.
+
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 togetherThen twist ''that'' together with one of the leads from the ceramic capacitorSolder these three leads together.
  
Once there's a resistor on each wire, take both of the resistor leads that you haven't soldered anything to, and twist them together.  Then twist ''that'' together with one of the leads from the ceramic capacitor.  Solder these three leads together. 
 
  
 +
===Voltage Shifter===
  
===Voltage Divider===
+
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.
  
Now we need to make the voltage dividerTake 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 wire end of each one.  If you are looking at the schematic, that's R3 on the red wire and R4 on the black wire.
+
You do pretty much the same with the black wire and R4, but there's an additionThe 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.
  
  
Line 90: Line 142:
 
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.
 
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.  However, it will be somewhat difficult to use the tubing if you didn't realize that you needed to put it on before soldering things together.
+
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.
 
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.
 
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 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 splitter.  Artie's "audio system" -- just a simple pair of USB powered speakers -- is connected to the other.  Using a splitter probably lowers the voltage of the audio signal even more, but this setup does work.
+
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 +5V.  The black jumper connects to ground.  You can just use the appropriate pins on the arduino.
+
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 whichever one of the Arduino analog inputs you like.  I used the first, analog pin 0.
+
The white jumper plugs into whichever one of the Arduino analog inputs you like.  I used the first pin, Analog 0.
  
  
 +
==Coding==
  
==Coding==
+
Now that the circuit is built and connected, we need to decide how to process the values the Arduino picks up from it.
  
Now that the circuit is built and connected, we need to decide how to process the value 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 above discussion, you may have realized that we'll need to scale them up.  That's so the tiny voltage range our audio signal gives us doesn't equal a dim light.  In audio terms, we are ''normalizing''.  Arduino programmers probably are thinking of the map() function right now.  Your instincts serve you well.
+
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 reread the bit of this paragraph that's in parentheses, many of you will sense the phrase ''absolute value''.
+
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.
 
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.
Line 117: Line 173:
 
===Data Smoothing===
 
===Data Smoothing===
  
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 neopixel brightness 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.)
+
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".
 
 
However, 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 averaging the current value at the analog input with the previous ''average'' value.  This will smooth out the waves further.   
+
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 in terms of line level voltages rather than the numbers in our code: If the audio jumps from 0 to 1 volt in one sample and then stay 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 ((0+1)/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.
+
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 codeIf 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 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.  A bit quicker to react, but still not as jittery as the raw analog input.
+
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)
 
(To be continued)

Latest revision as of 11:25, 21 September 2016

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)