Added Part 2, on 26 August, 2012.
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….
After I expressed my concern about heavily loaded OPA, I was thinking, that it would be nice to run some measurements, in order to decide what part number would be better for this specific hardware realization (LF351 replacement), or if I have a few candidates, it would make sense to compare them based on measurements results, instead of what I can hear with my own ears. It didn’t take long to download and install JAAA application, which turn my laptop (Linux) into “home-brew” DSP laboratory. To cancel any distortion generated in ADC (plus another non rail-to-rail OPA*) on performance evaluation of the OUTPUT stage, I modified sketch adding sine-wave LUT table, basically turning it into Sine test generator. 20 – 20.000 Hz, sweeping along frequency axis by pot, connected to same pin A5, ground and +5V power rail.
First of all, I check if my “off-set” 2.000 V was set correctly, as according to data sheet 3V is a minimum.
Test confirmed, that 2V off-set was a mistake. The best results at 3V, with distortion level IMD-2 and IMD-3 less than 0.03%. And there is no surprise, that level goes up with a Span ( difference in V-1 and V-2), simply because OPA is loaded harder. All data were taken with phasor equals to 0. Look at the last line, where phasor was set to 11, approximately “worst case scenario” – when load of the OPA jumping up and down, in other words, when one channel is charging its capacitor, in less than 0.5 microseconds next channel connected to OPA output asking just opposite, to discharge a cap. It happens, when relation between phasor and test frequency forms 180 degree phase difference in neighboring channels. OPA just have no time to “settle” in between. Still not bad, for $0.60 “obsolete” OPA.
Second test, variation of the distortion level over frequency range. I’d not comment, just look at the pictures:
Summary: the results are quite remarkable. They show, that Arduino is capable to run 12 channels audio system with less than 0.03 % THD. Distortion level would be a little bit higher than 0.03 % if all 12 channel outputs not “in phase” melody, but not much than 0.05 % or so, as it’s quite unusual to have exactly 180 degree out-of-phase 100% magnitude ( what I highlighted in red line in posted table). Anyway, I will fix it replacing LF351.
Link to arduino UNO sketch: Generator
* Things to DO: I have to test INPUT for distortion level as well, more to come in part 3….