January 02, 2016

Audio-In from Line-Out, Arduino Due DAC

Audio tracks can be a great source of widely varying and entertaining beat patterns for e-stim. All powerful boxes can generate e-stim pulses from a line-in port. I want to support this, too, and think about computing volume (VU) and frequency analysis (FFT) information as a source of time-varying information for e-stim programs.

The common way to interface a line-in port with an Arduino is the LM386 low-end audio amplifier chip. After all, we're not interested in high fidelity over a wide range of frequencies, but just in volume and beat pattern information. Sketches and circuits for LM386 are a dime a dozen on the interwebs, and most are based on the 20-gain minimum-parts circuit from the chip's datasheet [1]. Some examples and circuits can be found on [2,3,4].

To the left is my realization of that circuit, including a line-in connector with an audio cable coming from my notebook plugged in. Because the LM386 runs on 5V and the Due's ADC runs on 3.3V, I've added a simple 5V to 3.3V voltage divider using a 2.7k and a 5.6k resistor in series. You'll quickly fry the ADC channel if you don't. A number of alternative voltage conversion strategies can be found here [5]. The 10uF capacitor for a gain of 200 can still be seen soldered in, but is disconnected.
Two things didn't go too well in the first place. For one, it's paramount that the 5V supply is a good one. I had to realize that, when powering my Due from my notebook's USB, my power supply does not do too well because the LM2596 chip requires an input voltage of at least 8.5V. Powering from a 9V block fixed this. Second, the yellow cable runs to channel 0 of the Due's ADC, which is PIO A.2 pin number 85 [6]. It's stupidly labelled "A7" on the Due board, which helped a lot to eat into my spare time.

I'm running the ADC in free-running mode, meaning that it continuously converts incoming voltage in the 0V to 3.3V range to 12-bit integers in the range 0 to 4095. I've set up the Due DAC's direct memory access (DMA) to transfer the readings into a double-buffer in memory: An interrupt is triggered whenever a buffer is full, which happens every 2000/128 ~ 15 ms. The interrupt service routine (ISR) then switches buffers. Information on the Due's ADC and DMA controllers can be found in the SAM3X8E data sheet [7].

Now there's always a buffer being filled by DMA, while a full buffer holding ~15 ms worth of amplitude data could be processed inside loop(). I could be computing VU or FFT values from the amplitude information stored therein. But that's for another post.

Parts List

1x LM386 audio amplifier
1x 220uF capacitor, electrolytic
2x 10uF capacitor, electrolytic (3 for 200-gain)
1x 47nF capacitor
1x 10k resistor
1x 5.6k resistor (or similar)
1x 2.7k resistor (or similar at half the value)
1x 10 Ohms resistor
1x 3 pin header
1x mono audio socket

The total cost is about USD 5. Eagle files with scheme and board layout can be found in the project's GitHub repository.

References

[1] http://www.ti.com/lit/ds/symlink/lm386.pdf
[2] http://www.instructables.com/id/LM386-Audio-Amplifier/
[3] http://www.arduino-hacks.com/arduino-vu-meter-lm386electret-microphone-condenser/
[4] https://www.arduino.cc/en/Tutorial/SimpleAudioPlayer
[5] http://jamesreubenknowles.com/level-shifting-stragety-experments-1741
[6] http://forum.arduino.cc/index.php?topic=132130.0
[7] http://www.atmel.com/images/atmel-11057-32-bit-cortex-m3-microcontroller-sam3x-sam3a_datasheet.pdf

No comments:

Post a Comment