UnDecima Audio Output from Arduino
I already have one project where arduino outputs audio signal to USB speakers via software 10-bits PWM. In first, I was not satisfied with quality of sound generated via PWM. There are just not enough speed in arduino engine to run PWM well. For example for 20.000 Hz audio, PWM has to be at least 2 – 3 times higher above normal frequency range, or 40 – 60 kHz. If we multiply this value with 10-bits resolution, we would get 40 – 60 MHz, that is too much for small arduino to drive.
In second, the idea to create multichannel audio system was boggling my mind for about a year now. This is how UNDECIMA project was born. 1 + 11, or 12 channel !!! audio system running on arduino UNO board with full 10-bits resolution – maximum available with internal ADC. Project gets its name because there is 1 Master channel, and 11 linearly delayed copy of the same audio stream, or Puppets channels, In its essence, this is acoustic Phase Array.
As you can see on posted drawings, the “heart” of the project is 10-bit multiplying (parallel) digital analog converter DAC1022. Output of the IC than buffered with OPA and “demultiplex’d” via two 74HC4051 8-channel analog switches. Outputs of the switches loaded by sampling and hold capacitors 0.01 uF, to filter out unwanted sampling frequency noise. DAC is configured for single supply power line. Usually, they recommend to buffer output with / high input impedance / high slew rate / rail – to – rail / OPA in such configuration. Which I don’t have, and it costs about half a price of DAC itself, So, this is why I implemented two variable voltage references based on NE5532 and couple of pots. Difference in voltages between two references forms a “span”. Lower voltage creates an off-set for cheap non rail-to-rail OPA LF351, with adequate slew rate 13 V/usecond. OPA is heavily loaded by sampling and hold capacitors, which it sees as connected in parallel at its output, 0.12 uF overall! To minimize distortion level due overloading of the OPA, span couldn’t be adjust too wide, and preset in current design 1.414 V, providing exactly 1V RMS output for pure sine wave. I know, that 12 buffers / filters inserted after switches would solve a problem, but idea to solder more than 100 electronics components on a breadboard doesn’t look attractive for me.
( *I will try to find another IC / circuits capable to drive big capacitive load later on. )
Software part of the project is straightforward ”sample-delay-output” function, completely wrapped inside interrupt subroutine. Main loop is empty. In setup 16 digital pins configured as outputs, 10 of them represent data bus, 5 are address bus and last one is check-point to measure performance with oscilloscope. Timer 2 defines a “heartbeat”, and fires interrupt every 25 usec, or at 40 kHz. ADC configured to take samples on analog input A5 (first 4 analog pins belong to data bus). Conversion prescaler: 1 MHz, allowing sampling to be completed with fast speed. I left two digital pins D0 and D1 free, as my initial attempts to use them in data bus failed.
Arduino periodically refuses to reload updates, I’m not sure if it’s Linux problem or on-board USB/RS232 converter. Each sample, received from the ADC, is shifted left on two bits to skip D0 and D1, and plus one bit more (3 bits left shift overall) to fix “imperfection” of input preamplifier stage, as NE5532 (again) “non rail-to-rail” OPA. Look for drawings in “Audio Input” blog. Measurements show that each channel is receiving a data for about 1 usec “window”, which is quite fast, nevertheless not fast enough to run 16 channels or to do something else with data before sending them out. In current hardware implementation the “bottle neck” is OPA, as DAC has settling time only 500 nanoseconds.
Link to arduino UNO sketch: UnDecima.
To be continue….
For more detail: UnDecima Audio Output from Arduino