ADC and DAC example
cgracey
Posts: 14,155
I did some experimentation yesterday to see how well (or if at all) the sigma-delta ADC concept works on the Propeller's CTR modules (each of the 8 COGs has two CTRs). At first, it was a disaster, like Peter had found by trying to do it on the breadboard. The trick was building the RC integrator VERY close to the pins. This circuit has an analog 'setup time' requirement that is on the order of nanoseconds. The breadboard implementation had enough parasitic C and L that this window got missed. Look what happens, though, when it's done in SMT near the pins. The picture below shows a 1kHz sine wave input on top, then the digitized and re-output version on the bottom. One COG is using its CTRA to do the sigma-delta ADC and its CTRB to do delta modulation for the DAC function. It's doing 11-bit conversions at 39k samples per second:
·
Here is the assembly code that makes it all happen:
I've inlcuded the Spin file for this, too. It actually does a little more than shown, as it outputs hex samples to a TV for viewing.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
Post Edited (Chip Gracey) : 3/15/2006 11:24:15 PM GMT
·
Here is the assembly code that makes it all happen:
I've inlcuded the Spin file for this, too. It actually does a little more than shown, as it outputs hex samples to a TV for viewing.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
Post Edited (Chip Gracey) : 3/15/2006 11:24:15 PM GMT
Comments
I'm still wondering about the issue with the breadboard that you and Peter observed.
-- 1) will it work on the breadboard with a slower clock, say pll4x, albeit with slower response?
-- 2) Still puzzled about the circuit model of why it doesn't work at 80mhz except with the SMT hack? I appreciate that inductance out from pin 8 and pin 9 (in series with every branch in fact) could make a "chaotic attractor" from multple resonances between the capacitors and the inductors. But it just doesn't add up.
The voltage at the capacitor junctions should be practally DC compared with 80mhz. The capacitance of the breadboard is effectively in parallel with the integration capacitors and would be swamped. The only really high speed signal is the one coming out at the sigma-delta feedback pin A8 on the righthand side of the resistor, pushing pulse of current through the resistor into the capacitor(s). Inductance in that trace and resistor lead would slow down the rise time of the current pulse, but it couldn't really resonate with the capacitor because of the low Q due to the 1k resistor, and the the inductive impedance of that inch of trace would certainly be much less than 1kohms, so it couldn't have too much effect on the current. What I am looking at as a possible culprit is the *mutual* inductance & capacitance between the traces to A8 and A9, which run parallel for one inch and then up through the breadboard circuitry. If that is the case, a fat pulse of voltage could be induced directly from A8 and cause A9 to ring and give false triggering on A9. If that is the case, one way (the best) to address it is the SMT approach right by the pins. Perhaps a workaround would be to use pins that are further apart on the chip, or to use a guard trace or EM shield in between the traces, or ??.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
I think you just explained what the 'breadboard' problem really is: inductive and/or capacitive coupling between the 'in' and 'out' signals. This explanation makes better·sense than what I was saying. I'm going to try far-away pins to see what happens on the breadboard...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
Indeed, adjacent pins on the breadboard behaved worse than far-apart pins. In any case, though, I·couldn't get things operating very well on the breadboard. It just introduces too much parasitic L and C. Adjacent pins are fine, though,·as long as you have a·tight layout.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
I still have more testing to do, but using the breadboard for the A/D seems to be OK now. I am running 12 bit and 16 bit versions in assembler cog, not using the CTR helpers (have not had time to learn/experiment with those yet), using a basic 2 uSec loop tick.
I have this running, using a second assembler cog to spit out the values serially in SPI form, that is data together with a 10 usec clock, so I can observe the values on a scope.
I also added a Spin (hooray, my first program), to calculate a 3/4 and 7/8 averaged filter values, and then also calculate the instantaneous difference from that average. All these three parameters are spit out via the "SPI" bits.
I get an instability of 3 counts in the instantaneous reading.
I would want to say, my Propeller ability is not extensive, but I AM learning, and I think I'm getting there...... the SX took a while too to become proficient.
For anyone who cares, the attached code is by no means deemed to be optimum..... more like barely working, and not very "clean". But at least there is progress.
Cheers,
Peter (pjv)
I'm excited that you've got this working. An instability of three counts is really good for 12-16 bits, I think.
Seeing your software made me realize that everything the CTRs do (with the exception of the PLLs) can just as well be·done in software, albeit at a slower rate. The CTRs are like 'helpers' that can perform simple, repetitive operations to free the COG for other processing. They would automate your ADCLoop and make it 160x faster. I wonder if any special performance can be realized by ganging two CTRs in delta-sigma mode onto the same input signal.
I noticed in your ADCLoop the following sequence:
············· mov······ Temp1,outa····················· 'read the output latches
······· if_z· or······· Temp1,#ADCOutPin··············· 'prep turn adc output on
······· if_nz and······ Temp1,#!ADCOutPin·············· 'prep turn adc output off
············· mov······ outa,Temp1····················· 'transfer to output
This could be reduced to a single 'muxz outa,#ADCOutPin' instruction.
I've been thinking about what can be done now that we have audio-bandwidth A/D conversion. We could execute Goertzel algorithms to make very narrow frequency sensors. Then we could output a DAC signal on one pin, send it through a transducer and through some mechanical medium, and then receive it back into another ADC circuit to check amplitude and phase differences. We could make a sweeper that finds resonances and anti-resonances. There have got to be some interesting applications. Maybe we could make something that would find the top three resonant·frequencies of a wine glass, and then output those frequencies in order to break it. Maybe we could make some wierd thing that creates standing wave patterns in water and then switches between them to form impossible-looking phenomena.
We could at least make audio spectrum analyzers and and musical instrument tuners. We could output video·for feedback.
At 8-bit sample quality using the CTRs, you can do 312k ADC conversions per second at 80 MHz. With that, we could make a 100kHz scope with a function generator and component tester built in. It could also have some kind of DMM function and a 5 MHz 16-channel logic analyzer. You could make a whole test instrument out of just the Propeller and some passives.
I was talking to Andre LaMothe for a while last night and he was telling me how they use multiple COGs to render video without a bitmap. They have one COG use its video generator, and 1, 2, or 4 other COGs buffer up scan lines to be output, as needed. They work off algorithms, not raw memory. He's demonstrated NES-level graphics so far and he said he could do 'Doom' on the Propeller. This algorithmic display stuff is really neat because it uses very little RAM. For example, say you want a vector display. The obvious thing to do is make a bitmap that you draw lines into. Then, you double-buffer it so that you have a workspace and a displayspace. Too much memory! If you just had a list of line endpoints, and COGs sifting through this list in real-time as scan lines were rendered, the only RAM required would be for the endpoint coordinates. This frees up ~98% of what would have been display memory. This is really exciting to me, because it means that graphics memory usage will be reduced dramatically, and at the same time, all sorts of wild rendering techniques can be used to generate full-screen motion, with every frame completely unique. This is cool, not to mention completely unanticipated during the chip development!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
Post Edited (Chip Gracey) : 3/16/2006 7:04:39 AM GMT
Thanks for the tip! I didn't realize we HAD a MUXZ....although I had aleady used the MUXC for similar purposes.
I also realized after posting that my filter has a flaw in it, and can be more easily done in the ADC assembler cog, and hence each reading will contribute to the average, rather than only those that are available when the Spin algorithm was done with the previous value.
Just for fun, I'm going to make the changes, and for comparison add a monitor bit to my old program to see how often the Spin averager had been taking a new value.
Also I found it useful to use the semaphores for "token passing" between the ADC cog and the SPI cog. This is not so easy to accomplish with I/O port bits. Ram bits is another option ablbeit slower.
I appreciate your comments and wonderful musings about weird applications........ I'm sure gonna have a go at 'em !
Cheers,
Peter (pjv)
It appears that all of the A/D you have discussed in you software implementations have been in the sub-megahertz range (most appears to be in the single digit kilohertz or sub-kilohertz range). So, how far up do you think it could be pushed?
Thanks,
Robert (rp)
I've been thinking of using the propeller in an SDR myself. The simplest I could come up with for a 0-30MHz radio consists of a 30MHz low pass filter (7 poles seems about right), followed by a diode mixer (eg SBL-1 or equiv) feeding a 40MHz diplexor. The signal is converted to baseband using a quradrature sampling detector (SD) at 40MHz. This could be implemented using a 74ac74 and a 74hc4066. The 74ac74 would be clocked by complementary 80MHz signals from the propeller - thus producing a 40MHz quadrature signal for the SD. A very low noise op-amp would follow the 4066.
To get the signals into the propeller assuming a 10Khz (or so) sampling rate you would need a LPF to eliminat the alias. An 8 pole butterworth at 3KHz in each of the I/Q channels would do the job. For tuning, the propeller would need to generate a 40MHz-70Mhz signal to drive the mixer. There have been discussions on how pure the signal is in this range but lets assume it's ok for a simple receiver. Anyway, with a bit of software intelligence perhaps the frequencies with the largest spurs can be avoided.
The propeller would then need to do the demodulation. I'm not sure if it could be done using an FFT, but i'm pretty sure it could be done using a Hilbert transform (to shift one of the channels 90 degrees, the other channel needs to be delayed by about half the poles used for the Hilbert - too easy). This would enable LSB/USB/CW. For AM you can take the square root of the sum of the squares of I and Q (this signal could also be used to generate a digital AGC signal). Finally you could have an FIR on the output to give you some bandwidth control. The D/A should be easy
Once the hardware is organise the fun part is the software!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Ian Mitchell
www.research.utas.edu.au
Post Edited (IanM) : 8/10/2006 3:21:34 AM GMT
I just think that's fantastic, when something you have created can suprises you. The propeller is so powerful it is just a matter of being able to see the things is can do, the counters are something that I am new to but you can bet I am going to learn a lot about them!
Graham
I am trying to use Chip's ADC.spin to generate a square wave from a second cog.
1) The square wave will be running at a fix frequency if the input sine wave is not available or out of a set frequency range.
2) The square wave will synchronize to the input sine wave only to a set frequency range
Thanks in advance
Ching Lin
You should start another thread with your question/comment since it's not really a continuation of the original subject.
Are you asking how to do what you want? If so, you're going to have to give much more information like frequency range, response time, signal levels, etc.
I have started another thread "Synchronized square wave output".
Thank you so much.
Ching Lin
what you've observed is absolutely normal for breadboards and microcontrollers
in DIP packages.
One example:
If you read the datasheet of an Atmel ATMega16, you'll notice that Atmel does not
guarantee 10 Bits performance of the ADC for the DIP version of the microcontroller.
Full 10 Bits are only guaranteed for the TQFP and MLF variants.
And it is clear why this is the case. The ADC input has a high impedance and the
trace from the pin to the silicon chip is just too far away from signal ground.
Therefore it is susceptible to all kinds of EMI. Either from the microcontroller itself
or from the outside.
This above mentioned microcontroller even has a special power down mode, that
stops the microcontroller core while the A to D conversion is running, to reduce
noice generated by the microcontroller itself.
As the cog that does the conversion is always running at full speed, you cannot
achieve the signal/noise ratio that you would expect from signal theory.
You should even see higher noise levels with the start of additional cogs.
Best regards
Karl