handling ADC MCP3208 with Propeller
gio_rome
Posts: 48
Hello,
I'm using the MCP3208_fast library and so far I've managed to measure the RMS Voltage with channel 0 of the ADC (read max & min over a 5 cicle period, use experimental constants to tranform the value into an effective RMS value verifiable w/ that one of a voltmeter). I'm now trying to make the machine measure currents (...).
Anyway I've found two methods to initialize the ADC.
adc.start(na,nb,nc,%1111_1111)
or
adc.start(na,nb,nc,%1111_1111)
The first three numbers are the pins, but the last parameter, according to http://www.gadgetgangster.com/tutorials/382
actually "turns on channel". %1111_1111 evidently turns on all 8 channels.
BUT
MCP3208_fast documentation says
last parameter "not used, included for compatability with older program "
AND
in another version of the code I'm rewriting (of the old one I'm not responsible) this is the way it is initialized, i.e. with the last parameter=0.
Then which one is true/what's the exact way of initializing the ADC?
Why all this? Because I need certainties :-) I'm so unsure of the tracks and pins that I want there to be solid ground on which to build a new paradigm.
Tnx all!
Giovanni
I'm using the MCP3208_fast library and so far I've managed to measure the RMS Voltage with channel 0 of the ADC (read max & min over a 5 cicle period, use experimental constants to tranform the value into an effective RMS value verifiable w/ that one of a voltmeter). I'm now trying to make the machine measure currents (...).
Anyway I've found two methods to initialize the ADC.
adc.start(na,nb,nc,%1111_1111)
or
adc.start(na,nb,nc,%1111_1111)
The first three numbers are the pins, but the last parameter, according to http://www.gadgetgangster.com/tutorials/382
actually "turns on channel". %1111_1111 evidently turns on all 8 channels.
BUT
MCP3208_fast documentation says
last parameter "not used, included for compatability with older program "
AND
in another version of the code I'm rewriting (of the old one I'm not responsible) this is the way it is initialized, i.e. with the last parameter=0.
Then which one is true/what's the exact way of initializing the ADC?
Why all this? Because I need certainties :-) I'm so unsure of the tracks and pins that I want there to be solid ground on which to build a new paradigm.
Tnx all!
Giovanni
Comments
-Mike
The MCP3208 will only return a reading on a single channel at a time. Any of the 8 channels can be read from "In" or "Average" methods. You don't need to set the number of channels with start.
The MCP3208 has trouble reading quickly from high impedance sources. I've had some trouble getting good readings from 10K pots used as a voltage divider.
I don't think the mode parameter in Chip's original code was used to initialize the ADC - the mode parameter indicated which channels to read. There is no initialization really - each command to the ADC is self-contained (see the Serial Communication section of the datasheet). As far as I can tell the start function in the fast code just sets up the pin assignments, then each channel is read using the in function. I wrote my own code in assembler which works just fine, but you have to get the timing right (read the datasheet).
As Duane said, the 3208 samples each channel separately, so you need a separate command to the chip to read each channel.
Does anybody know of a relatively inexpensive 4 or 8 channel ADC in DIP form (I can't see SMDs let alone solder them) that samples simultaneously? I want to sample 4 channels simultaneously, and my solution at the moment is to use 4xMCP3201s and tie their CS and CLK pins together - that way I get almost simultaneous sampling, but I'd prefer a single chip (one that I can see...).
PASM is very friendly, and there are times when an off-the-shelf object/library is just not enough.
[Edit] Proving once again that search engines are our friends, I found this:
-- http://www.analog.com/en/analog-to-digital-converters/ad-converters/ad7606/products/product.html
So, these beasts exist -- now it's down to finding one that works for your project and writing some code for it.
I'll keep looking.
http://www.digikey.com/product-detail/en/LTC1408IUH-12%23PBF/LTC1408IUH-12%23PBF-ND/1468456
The MCP320x chips are capable of measuring up to 100,000 Hz, so if you measure all 8 channels the effective rate is 12,500 Hz per channel. If you are writing the code in PASM you could also track the CNT value at the beginning of each measurement and therefore know the exact time offset between measurements and do a software correction.
What is the delay/delta time that begins to cause problems?
A few more important details on the MCP320x ADCs if you are working at fast measurement rates:
Sampling of the selected channel begins with on the rising edge of the 5th clock signal after the CS is set low (just after sending the last bit of the input channel number). Sampling continues until the falling edge of the 6th clock tick. The charging capacitor in the MCP320x chip is 20 pF with a nominal 1000 ohm resistor in series. Pay particular attention to the charging time required as described in the datasheet (specifically Figures 4-1 and 4-2). Be sure you are not current limiting the ability of the sampling capacitor to achieve a full charge if your clocking speed is maxed out (that leaves you with only 750 ns to fully charge the 20 pF sampling capacitor). I ran into this charging problem trying to sample the voltage downstream from a 20 kohm resistor.
If you are writing your SPI communication code in PASM then you need to heed the clock speed requirements - i.e. the clock signal must remain high for 250 ns and low for 250 ns so the chip has time to properly respond (maximum clock speed is 2 MHz). Pay particular attention to the Timing Parameters outlined in the specification table on page 3 of the datasheet. Failure to adhere to these parameters might lead to inaccurate measurements.
There is also a minimum clock speed of about 10,000 Hz which is described in Section 6.2 of the datasheet (any slower than this and the sampling capacitor leaks charge which then results in a low voltage measurement error).
Not sure how many chips you could parallel like that but I bet it's way more than two.
Sandy
Yes, the 3202,3204, and 3208's will let you do that. I did that very thing to read a resolver SIN/COS on a CNC machine using an MCP3204.
gio_rome,
I could probably find that code if you are interested. As I recall, programming for the MCP3204 and the 3208 is the same, the MCP3202 is a little different.
That's precisely what I'm doing, but I'm using 4 x MCP3201s. The coding is a little different because there's no command sent to the chip (no channel or mode select - they are a single differential channel), but it's basically the same as all the 320x ADCs. As long as I can pick the peak on each ADC I can calculate the time difference. It would just be easier (I think) and use fewer pins if I had an ADC that samples 4 (or more) inputs simultaneously. I know kwinn pointed one out (thanks), but I can hardly see those tiny QFN things, much less solder them.
MJHanagan: All good advice, and I actually started down that track (using 4 channels on a 3208). My code is PASM and you are absolutely right that timing is really important. In the end though it was just cleaner code to use an extra few pins and 4 x 3201s (which I just happened to have around). This is just a proof of concept at the moment - if I get it working then I may see if I can find a DIP multi-channel simultaneous sample ADC (or find someone to solder the QFN version for me...).
I do have an object in OBEX that was done for the purpose of multiple parallel cogs/ADCs (and learning PASM) using one master control cog, one timing generator cog, and up to 6 ADC cogs/ADCs... have not had time to refine it for a while, but it should be able to also run additional prop chips with at least 7 cogs each paralleled and controlled by the first one. If only for more time to play and less for work.....
Frank
"The MCP3201 A/D Converter employs a conventional SAR architecture. With this architecture, a sample is acquired on an internal sample/hold capacitor for 1.5 clock cycles starting on the first rising edge of the serial clock after CS has been pulled low. Following this sample time, the input switch of the converter opens and the device uses the collected charge on the internal sample and hold capacitor to produce a serial 12-bit digital output code."
So my theory is that if I tie the CS and CLK pins of 4x3201s together they'll all acquire a sample at the same time because they're all clocked from the same source. All I need to do is make sure I get the bits out of all four ADCs before the charge dissipates - or am I being too simplistic?
Here's a snippet from my code:
Without the peak detection code I should get a sample rate of somewhere bewteen 65 and 70k samples per second. I could probably tweak it a bit and get closer to 312ns for the clock transitions instead of 400ns. The peak detection code (which I've left out for brevity) isn't that many instructions, so should reduce the sample rate to no less than 50k samples per second.
Anything I'm missing?
I should add that this code seems to work - I get numbers that look right and look consistent. I've put a scope on one of the mics I'm using, and the number I get out of the 3201 for that mic looks right. If my theory about the sample time for all four ADCs being the same is right then I think I'm good. I think.
That's a very good point - I just re-read your post and that jumped out at me. So maybe a 3204 (or 3208 if I go with more than 4 mics) is actually viable. Thanks.
Consider most my parallel ADC object. Like probably (nearly) all of the others, it clocks one bit in at a time, shifts the bit and goes back for more. Now, What if I wanted to get the input from say 24 MCP3201s but rather than with multiple cogs as my object does, I have just now thought of a way to do the same thing with only one cog. Rather than using multiple cogs to acquire one value, let us say we need more than 6 single channels and use a minimal number of cogs. Clock the ADCs as before, one pin per ADC input. So far no changes. Now, lets set up a stack of 12 registers in cog memory space (yep, no free lunch here either, the trade off for this trick is to eat 12 registers of space plus some additional code). read the input of the acquisition cog and mask for the ADC data. Your code should be smart enough to ignore the first three clock times after CS. After the prep pulses are passed, then start taking the masked data bits and store them into the first register for bit2^12 and repeat until all 12 bits are clocked in. You would be left with an array of bits with the words turned sideways so to speak. The final part of the trick would be to rotate this array so that the ADC values are each in a data word of their own. Have not quite figured out how to do that fast yet. Have to think of. a way to that efficiently with out loosing to much sample speed. My parallel ADC object uses one cog per ADC channel. max six channels on the first prop chip; but no real delays. This method would go many ADC channels into one cog, but an amount of delay would be introduced to reformat the input data into individual channel data.......
Oh , for only a couple more hours a day.......
I only need one internal sample line if I'm using 4x3201s. If I use a 3204 (or 3208) then, as MJHanagan pointed out, the time difference is very small. I'm using TDOA to locate direction to the sound, and my microphones are 160mm apart. The time difference between microphones is then about 400-500µs, so a delay of 10-11µs isn't so bad.
Usually in a situation like this you need to collect the data quickly then have lots of time to do the analysis once all the data is accounted for. If that is the case here then you could simply read all 8 data bits and save them as a single byte in an array in main RAM (a single byte write costs no more than 23 clock ticks, or about 1.15 µs at 80 MHz). Once the data has been collected each byte could be deconstructed and put in separate arrays for each channel.
If you had two cogs you could have the second cog watch the common clock pin and read the all the output pins and parse the bits into the 4/8 results and after the 12th bit transfer the data up to main RAM in word sized arrays. Four WRWORD commands will no doubt cost you the good part of 4x23 clock cycles so about 4.6 µs. That leaves you with a similar amount of time to parse the measured bits before the next measurement is ready and time to read the new inputs. If you were doing all 8 channels then the WRWORD would consume 9.2 µs leaving very time to do the parsing. In that case you might need to slow the data collection speed down to something like 80,000 Hz (with the speed of sound at 340 m/s that makes the uncertainty in the distance measurement roughly 1 mm).