Shop OBEX P1 Docs P2 Docs Learn Events
Speed problem with "MCP3208 fast ADC 12 bit 8 channel" object — Parallax Forums

Speed problem with "MCP3208 fast ADC 12 bit 8 channel" object

MJHanaganMJHanagan Posts: 189
edited 2014-01-15 09:10 in Propeller 1
I am encountering a speed problem with a Microchip MCP3208 ADC and the “MCP3208 fast ADC 12 bit 8 channel“ object (see http://obex.parallax.com/objects/224/) . According the documentation the assembly written routine is capable of making ADC measurements at a rate of 50k Hz per channel. I need to measure two channels so this should half the rate to 25k Hz per channel. I am using a REPEAT loop to measure the first channel then the second storing the results in two arrays. I am using a zero crossing detector signal on an input pin to provide synchronized timing during the first half of a 60 Hz line cycle (i.e. a synchronized 8.33 msec data collection period). In the code below I am simulating the zero cross signal using a generated pulse on an output pin which is tied to the zero cross input pin via a 5k resistor (I measure a perfect 60.00 Hz on the input pin).

When I run the code I am only getting 45 data measurements during the zero cross high input to time. If the 50k Hz value is correct then I should be getting about 208 measurements per channel during this period. There is likely to be some processing time to assess the status of the zero cross input pin and increment the data counter but I think these operations should be relatively fast – even in SPIN.

Can anyone help explain why I am getting so few measurements?

Here is the code:
CON
  _clkmode        = xtal1 + pll16x
  _xinfreq        = 5_000_000
  
' serial terminal baud rate (default I/O pins are 30 and 31):
  PSTBaud = 115200
  
OBJ
        pst     : "Parallax Serial Terminal"
'        adc     : "MCP3208 ADC"
        adc     : "MCP3208 Fast"
VAR

  long DIOpin, CSpin, ClkPin, ZCinPin, ZCoutPin, BMode, nChannel, KbCmd, ADCcog, ZCPcog
  long Vdata [500], Idata[500], VChan, IChan
  long Stack1[50]
  
PUB Main | i, j, k, l, m, n, msec

  pst.Start( PSTBaud )
  pst.Clear
  pst.Beep
  pst.str(String("Initializing..."))

  DIOpin := 1   'MCP3208 data in/data out pin
  ClkPin := 0   'MCP3208 clock pin     
  CSPin := 3    'MCP3208 chip select pin

  BMode := %1   'MCP3208 mode (1=single ended, 0=differential)
  nChannel := 1  'Default ADC channel number
  VChan := 1     'Voltage channel
  IChan := 2     'Current channel
      
  ZCoutPin := 7 'Zero crossing simulator output pin     
  ZCinPin := 6  'Zero crossing simulator input pin 
  DIRA[ ZCinPin ]~
 
  ADCcog := adc.start( DIOpin, ClkPin, CSPin, BMode )  'Start the MCP3208 ADC routine
  
  pst.str(  String( pst#NL, "ADC runnning in cog: ")) 
  pst.dec( ADCcog )

  ZCPcog := cognew( HzPulse( ZCoutPin, 120 ), @Stack1 ) + 1       'Start the 60 Hz zero crossing pulse signal
  
  pst.str(  String( pst#NL, "ZC pulse running in cog: ")) 
  pst.dec( ZCPcog )
   
  REPEAT
      
    pst.str(String( pst#NL, "C=Channel select, M=measure, <ESC>=quit"))
    KbCmd := pst.CharIn      'Get command from keyboard

    if KbCmd == "c" OR KbCmd == "C"
      pst.str(  String( pst#NL, "Select channel: ")) 
      nChannel := pst.CharIn - "0"
     
    if KbCmd == "m" OR KbCmd == "M"
      pst.str(  String( pst#NL, "Measuring channel ")) 
      pst.dec( nChannel )
      pst.str(  String( "..."))
      j := adc.in( nChannel )
      pst.str(  String( "  Result="))
      pst.dec( j )

    if KbCmd == "s" OR KbCmd == "S"
    
      pst.str(  String( pst#NL, "Scanning channels..."))
      n := 0

      REPEAT UNTIL INA[ ZCinPin ] == 0   'Wait for ZC input to go low then high again
      REPEAT UNTIL INA[ ZCinPin ] == 1

'********* Measure V-I channels loop
      REPEAT UNTIL INA[ ZCinPin ] == 0   'Make as many measurements on channels 1 and 2 during the pulse high time (~8.33 msec)
          VData[n] := adc.in( VChan )
          IData[n] := adc.in( IChan )
          n++  
'*********
        
      pst.str(  String( " Done.  Results:"))
      m := n   'Save the number of measurements made.
      
      n := 0
      REPEAT m  'Display all the measuremnts made
      
        pst.str(  String( pst#NL, "VData["))
        pst.dec( n )
        pst.str(  String( "] = "))
        pst.dec( VData[n] )
        pst.str(  String( " = "))
        VData[n] := ( VData[n] * 3300 ) / 4096
        pst.dec( VData[n] )
        pst.str(  String( "mV  IData["))
        pst.dec( n )
        pst.str(  String( "] = "))
        pst.dec( IData[n] )
        pst.str(  String( " = "))
        IData[n] := ( IData[n] * 3300 ) / 4096
        pst.dec( IData[n] )
        pst.str(  String( "mV"))
        n++

      pst.str(  String( pst#NL, "Measurment in period: "))
      pst.dec( m )
         
    if KbCmd == 27
      cogstop( ADCcog )
      cogstop( ZCPcog )
      pst.str(String( pst#NL, pst#NL, "All done, good-bye.")) 
      ABORT

PUB HzPulse( _OutPin, _Freq )  | i, OutPin, HzCNT

  OutPin := _OutPin
  HzCNT := CLKFREQ / _Freq

  DIRA[ OutPin ]~~
  OUTA[ OutPin ]~

  i := CNT

  REPEAT    'Generate a pulsed output at the specified frequency
    !OUTA[ OutPin ]
    i := i + HzCNT
    WAITCNT( i )

And here is the ADC object code:
''MCP3208_fast.spin
''
''Copyright (c) 2007 Jim Kuhlman
''
'' See end of file for terms of use.
''
''*****************************************************
''*  MCP3208 12-bit/8-channel ADC Driver              *
''*  Works w/indiv channel on chip rather than all 8  *
''*  Provides single sample or average of n samples   *
''*  Provides single mode only, no differential mode  *
''*  Does not provide DAC output like original code   *
''*****************************************************

'' rev 1.0   09-16-07 Fixed bug in start routine for delay value.

CON
  #1, _setup, _single, _average, _delay, _div, _adcready
     ' cmds for assy routine: 1=setup, 2=single adc sample, 3=average of n adc samples, etc.

VAR

  long  cog, delay

  long  cmd, chnl, nsamples, data[4]          '7 longs (3 longs, 8 words)

PUB start(dpin, cpin, spin, mode) : okay

'' Start driver - starts a cog
'' returns false if no cog available
'' may be called again to change settings
''
''   dpin  = pin connected to both DIN and DOUT on MCP3208
''   cpin  = pin connected to CLK on MCP3208
''   spin  = pin connected to CS  on MCP3208
''   mode not used, included for compatability with older program

  stop                          ' stop cog if running from before
  
  cmd := 0                      ' tell adc_read to wait for next command
  cog := cognew(@adc_read, @cmd) + 1  ' store adc_read and shared mem address
  waitcnt(clkfreq/4 + cnt)      'wait 1/4 sec for cog to start

  chnl := dpin                  ' initialize for call to _setup
  nsamples := cpin
  data[0] := spin
  data[1] := 0
  
  do_cmd(_setup, @chnl)         ' initialize assy routine for dpin, cpin and spin pins on MCP3208

  if clkfreq => 80_000_000      ' make it work for prop2 also
    delay := clkfreq/2_000_000  ' time delay for half cycle of 50KHz sample rate
  else                          ' set for 1MHz clock rate to chip
    delay := 40                 ' if clkfreq < 80,000,000 then set to 40
    
  do_cmd(_delay, @delay)        ' pass time delay parameter to assy routine

  return cog


PUB stop

'' Stop driver - frees a cog

  if cog
    cogstop(cog~ - 1)

    
PUB in(channel)

'' Read the current sample from an ADC channel (0..7)

  chnl := channel

  do_cmd(_single, @chnl)        ' get single sample from channel

  return data.word[channel]


PUB average(channel, n)

'' Average n samples from an ADC channel (0..7), n <= 16

  chnl := channel               ' set channel number in xfr array

  nsamples := n <# 16           ' limit # of samples to 16 max
  nsamples #>= 1                ' must be greater than zero
  
  do_cmd(_average, @chnl)       ' get average of n samples from specified channel

  return data.word[channel]

PUB div(divisor, dividend) : quotient

'' Divide 16 bit dividend (in long)
'' by 16 bit divisor (in long)
'' Return 16 bit quotient (in long)

  chnl := divisor
  nsamples := dividend

  do_cmd(_div, @chnl)

  quotient := nsamples

  
PRI do_cmd(adc_command, argptr)

  cmd := adc_command << 16 + argptr                 'write command and pointer to shared memory loc
  repeat while cmd                                  'wait for command to be cleared, signifying completion

  
DAT
''
''************************************
''* Assembly language MCP3208 driver *
''************************************

                        org
'************************************
adc_read                rdlong  t1,par          wz      ' wait for command
        if_z            jmp     #adc_read

                        movd    :arg,#arg0              
                        mov     t2,t1
                        mov     t3,#4                   ' get 4 arguments
                        
:arg                    rdlong  arg0,t2                 ' store in arg0, arg1, arg2, arg3
                        add     :arg, hex200            ' update destination addr for next loop
                        add     t2,#4                   ' point to next input arg
                        djnz    t3,#:arg

                        ror     t1,#16+2                ' lookup command address
                        add     t1,#jmptable
                        movs    :tabloc,t1
                        rol     t1,#2
                        shl     t1,#3
:tabloc                 mov     t2,0
                        shr     t2,t1
                        and     t2,#$FF
                        jmp     t2                      ' jump to command

'************************************
jmptable                byte    0                       '0 not used
                        byte    setup_                  '1 setup adc routine
                        byte    single_                 '2 single adc value
                        byte    average_                '3 average adc values
                        byte    delay_                  '4 delay for adc clock
                        byte    div_                    '5 divide 16 x 16 bits
                        byte    adcready                '6 loop for next instruction

'************************************
setup_                  mov     t1, arg0
                        call    #param                  'setup DIN/DOUT pin
                        mov     dmask,t2

                        mov     t1, arg1
                        call    #param                  'setup CLK pin
                        mov     cmask,t2

                        mov     t1, arg2
                        call    #param                  'setup CS pin
                        mov     smask,t2
                        
                        jmp     #adcready

'************************************
param                   mov     t2,#1                   'make pin mask in t2
                        shl     t2,t1
param_ret               ret
                        
'************************************
delay_                  mov     t4, arg0                'set up delay time for chip clock
                        shr     t4, #3                  ' divide it by 8 clock cycles/ 2 instr
                        sub     t4, #4                  ' adj for 1/2 cycle
                        mov     delayval, t4            ' store in delayval for delay routines
                        jmp     #adcready
                        
'************************************
div_                    mov     t1, arg0                ' move divisor  to t1
                        mov     t2, arg1                ' move dividend to t2
                        
                        call    #divide
                        
                        mov     t3, par                 ' shared mem ref to t3
                        add     t3, #8                  ' point to output
                        wrlong  t2, t3                  ' write quotient to nsamples
                        jmp     #adcready
                        
'************************************
single_                 mov     arg1, #1                'initialize arg1, not supplied with single_ call

'************************************
average_                mov     t3, arg1                'set for n sample average (or 1 if single sample)
                        or      dira,cmask              'set CLK line to output
                        or      dira,smask              'set CS  line to output

                        mov     command,#$18            'init command to 011000, start/single
                        add     command, arg0           'add in channel number to command bits
                        
                        mov     t2, #0                  'initialize data[channel] accumulator
                        
:bloop                  mov     stream,command          'set up for new sample
                        or      outa,smask              ' CS high
                        or      dira,dmask              ' make DIN/DOUT output
                        andn    outa,cmask              ' CLK MUST be low before CS enabled!!!
                        andn    outa,smask              ' CS low
                        nop                             ' wait 8 clock cycles for TSUCS              
                        nop
                        
                        mov     bits,#5                 'ready 20 bits (cs+1+diff+ch[3]+0+0+data[12])
:cloop                  test    stream,#$10     wc      'update DIN/DOUT
                        muxc    outa,dmask
                        andn    outa,cmask              'CLK low
                        call    #delay1                 ' adjust clock cycle time                        
                        rcl     stream,#1               ' shift out next bit
                        or      outa,cmask              'CLK high                        
                        call    #delay2                 ' adjust clock cycle time                        
                        djnz    bits,#:cloop

                        andn    dira,dmask              ' make DIN/DOUT input to get data
                        mov     bits,#14                'get the data 2-null plus 12 data
:dloop                  andn    outa,cmask              'CLK low                        
                        call    #delay1                 ' adjust clock cycle time                        
                        or      outa,cmask              'CLK high
                        test    dmask,ina       wc      'sample DIN/DOUT
                        rcl     stream,#1               ' store bit for output         
                        call    #delay2                 ' adjust clock cycle time                        
                        djnz    bits, #:dloop           'next data bit

                        and     stream,mask12           'trim sample
                        add     t2, stream              'accumulate sum in t2
                        djnz    t3, #:bloop             'more samples for average?

                        cmp     arg1, #1        wz      ' see if n > 1
        if_nz           mov     t1, arg1                ' set up for divide if needed, arg1 = number of samples, n
        if_nz           call    #divide                 ' divide t2 by t1 or sum/n -> t2

                        mov     t3, arg0                'load channel number, 0..7
                        shl     t3, #1                  'mult by 2 for word offset in data[ ]
                        add     t3, #12                 'add 12 for 3 long offset (cmd + chnl + nsamples)
                        mov     t1,par                  'reset sample pointer
                        add     t1, t3                  'add offset, t1 now points to data[channel]
                        wrword  t2,t1                   'write sample to data[channel]
                                                        'fall through to adcready and exit
'************************************
adcready                wrlong  zero,par                'zero command to tell caller we're done
                        jmp     #adc_read               'back to wait for another command

'************************************
delay1                  mov     t4, delayval            ' load delayval, clock cycles
                        nop                             ' adj to half cycle
                        nop
:tloop1                 nop
                        djnz    t4, #:tloop1            ' delay 1/2 uSec = 1/2 MCP3208 clk cycle
delay1_ret              ret

'************************************
delay2                  mov     t4, delayval            ' load delayval, clock cycles
:tloop2                 nop
                        djnz    t4, #:tloop2            ' delay 1/2 uSec = 1/2 MCP3208 clk cycle
delay2_ret              ret

'************************************
' Divide
'   in:         t1 = 16-bit divisor  in long
'               t2 = 16-bit dividend in long

'   out:        t2 = 16-bit quotient (in long), truncated

'   temp:       t3 = loop counter

divide                  shl     t1,#15                  'get divisor into t1[30..15]
                        mov     t3,#16                  'loop counter for 16 bits
                        
:loop                   cmpsub  t2,t1 wc                'if t1 =< t2 subtract it, quotient bit -> c bit
                        rcl     t2,#1                   'rotate c into quotient and shift dividend
                        djnz    t3,#:loop               'loop until done
                        
                        and     t2, hexFFFF             'mask quotient, drop the remainder in [31..16]
divide_ret              ret                             

'************************************
' Initialized data
'
hex200                  long    $200                    'constants
hexFFFF                 long    $FFFF
mask12                  long    $FFF
zero                    long    0

'************************************
' Uninitialized data
'
arg0                    res     1                       ' arguments passed from high-level
arg1                    res     1
arg2                    res     1
arg3                    res     1

dmask                   res     1                       ' MCP3208 pin masks
cmask                   res     1
smask                   res     1

t1                      res     1                       ' temps
t2                      res     1
t3                      res     1
t4                      res     1

dx                      res     1                       ' for atn routine
dy                      res     1

command                 res     1                       ' for 3208 routine
stream                  res     1
bits                    res     1
delayval                res     1

{ Terms of use:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

}

Comments

  • SRLMSRLM Posts: 5,045
    edited 2012-09-07 08:43
    I think you're correct: Spin is very slow.

    Anyway, I get around that by writing a PASM loop around the assembly part. It speeds things right up.

    Attached is a version that automatically samples at full speed. It's based off the 3 ADC object, so you may need to trim it to one ADC. It should work, but it's been a while since I looked at that code.

    You should also move all of the PST statements out if you want maximum speed. It's sometimes surprising how slow those routines are. If you want something really fast, don't output anything except the number and characters such as space and CR.
  • lardomlardom Posts: 1,659
    edited 2012-09-07 09:04
    OBJ
            pst     : "Parallax Serial Terminal"
    '        adc     : "MCP3208 ADC"
            adc     : "MCP3208 Fast
    

    Maybe I'm missing something but it looks like you have three objects but two nicknames.
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-07 09:13
    lardom wrote: »
    OBJ
            pst     : "Parallax Serial Terminal"
    '        adc     : "MCP3208 ADC"
            adc     : "MCP3208 Fast
    

    Maybe I'm missing something but it looks like you have three objects but two nicknames.

    The first "adc" object is commented out so I am only using the "Parallax Serial Terminal" and the "MCP3208 Fast" objects. For some unknown reason I could not get the basic "MCP3208 ADC" object to work on anything but channel 0.
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-07 09:21
    SRLM wrote: »
    I think you're correct: Spin is very slow.

    Anyway, I get around that by writing a PASM loop around the assembly part. It speeds things right up.

    Attached is a version that automatically samples at full speed. It's based off the 3 ADC object, so you may need to trim it to one ADC. It should work, but it's been a while since I looked at that code.

    You should also move all of the PST statements out if you want maximum speed. It's sometimes surprising how slow those routines are. If you want something really fast, don't output anything except the number and characters such as space and CR.

    I don't think I have any PST statements inside the ADC measurement loop - only the adc.in(ch1), adc.in(ch2) and the n++ statements. I assume the PST's before and after have no impact on the speed.

    So you think the REPEAT UNTIL INA[ ZCinPin ] == 1 and n++ statements slow this down sufficiently to where I only get ~25% of the possible measurements? Wow - that is very surprizing.

    Unfortunately, I don't know PSAM and haven't touched assembly based code since 1977 (just after it was invented!!!). I may have to settle for 45 data points for now. :smile:
  • pedwardpedward Posts: 1,642
    edited 2012-09-07 09:32
    SPIN is supposed to be capable of 500k instructions per second. I would question whether the MCP3208 fast actually works properly. Have you tested the standard MCP3208 ADC object to see how many samples it gives you?

    Another way to speed things up is to not do what the fast object is doing, reading only 1 channel. You can read all 8 channels at once, saving you the overhead of the inter-COG communication and the second SPIN call.
  • SRLMSRLM Posts: 5,045
    edited 2012-09-07 12:14
    If you look at the call chain, it's

    adc.in->do_cmd-> "ASM Call"

    You could speed it up by directly going to the ASM call, without the Spin overhead (aka, do all the memory manipulation yourself in your end object).

    Additionally, you can unroll your loop for a bit more speed. It will probably be pretty minor, though.

    You should test the various pieces of code to see how long they take. Do something like:
    begin_cnt := cnt
    ... DO SOMETHING ...
    end_cnt := cnt
    delta_cnt := end_cnt - begin_cnt
    
  • kwinnkwinn Posts: 8,697
    edited 2012-09-07 18:51
    MJHanagan wrote: »
    .........

    Unfortunately, I don't know PSAM and haven't touched assembly based code since 1977 (just after it was invented!!!). I may have to settle for 45 data points for now. :smile:

    Just after it was invented????? I programmed in assembler quite a few years before that. Assembler was the first step up from programming in machine language. It was essentially machine language using mnemonics instead of binary/octal/hex numbers.
  • frank freedmanfrank freedman Posts: 1,983
    edited 2012-09-07 22:33
    On an earlier thread (last winter maybe) I put up my results of using spin and pasm to determine the max sample rate of a MCP3201. Spin could not give me the rated rate while I could quite exceed it in pasm using the counters my current avatar is the pasm result screen.

    FF
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-10 16:59
    I have been looking at the PASM code with the Propeller Manual open to the dreaded assembly language section. This will take a bit of time to work through but I think I am beginning to see how this works. For now I will have to suffer the scant 45 measurements so the project doesn't get unnecessarily delayed, but I think I will return to the PASM code and see if I can speed this process up.

    Thanks to all of you for your input!
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-09-10 18:08
    MJHanagan wrote: »
    I have been looking at the PASM code with the Propeller Manual open to the dreaded assembly language section. This will take a bit of time to work through but I think I am beginning to see how this works. For now I will have to suffer the scant 45 measurements so the project doesn't get unnecessarily delayed, but I think I will return to the PASM code and see if I can speed this process up.

    Thanks to all of you for your input!
    Just letting you know that as an exercise I started rewriting your code in Tachyon Forth as the MCP3208 interface runs at the full 100kHz sampling speed (2MHz clock) at 5V and slower if you need. Tachyon doesn't need to resort to having special cogs running PASM for speed and it's interactive via the terminal. The MCP3208 interface that I did is here.
  • frank freedmanfrank freedman Posts: 1,983
    edited 2012-09-10 19:24
    Just letting you know that as an exercise I started rewriting your code in Tachyon Forth as the MCP3208 interface runs at the full 100kHz sampling speed (2MHz clock) at 5V and slower if you need. Tachyon doesn't need to resort to having special cogs running PASM for speed and it's interactive via the terminal. The MCP3208 interface that I did is here.

    Thanks for the intro link Peter. Now I will go %@%@ crazy looking through my book archive because I just know I kept my copy of Starting Forth. Have not until this thread really considered playing with Forth again.........

    FF
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2012-09-11 08:21
    Depending on what you are doing, this object: http://obex.parallax.com/objects/488/ may work better. It does some analysis for you in it's pre-existing PASM.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-09-11 09:12
    The Spin code is slowing you down. I wrote a test program that executed similar code that you are running, and I got about 6,700 loops per second. This is about 25% of the 25,000 loops per second that you are expecting.

    I suggest that you create a new method that combines the "repeat until" loop with the in and do_cmd methods. This will eliminate the calling overhead within the loop. You should also pass @VData and @IData as pointers to the new method. This will give you higher speed.
  • r.daneelr.daneel Posts: 96
    edited 2014-01-15 03:24
    pedward wrote: »
    SPIN is supposed to be capable of 500k instructions per second. I would question whether the MCP3208 fast actually works properly. Have you tested the standard MCP3208 ADC object to see how many samples it gives you?

    Another way to speed things up is to not do what the fast object is doing, reading only 1 channel. You can read all 8 channels at once, saving you the overhead of the inter-COG communication and the second SPIN call.

    You can read 8 channels at once? Can you share some example code?
  • MJHanaganMJHanagan Posts: 189
    edited 2014-01-15 04:03
    r.daneel wrote: »
    You can read 8 channels at once? Can you share some example code?

    The MCP320x chips do not measure the inputs simultaneously - only one channel at a time. If you can get it to run at its top rated speed of 100 kHz then you can measure all 8 channels sequentially at an effective per channel rate of 100/8=12.5 kHz.

    If you truly need simultaneous measurements you would need to get a different chip, OR you could use 8 MCP3202's and tie their CS and CLK lines together so they measure in perfect timing sequence. You would need 8 dedicated DIO lines on the Propeller (or a fast bidiectional serial/parallel shift register). Wow, 8 ADC signal at 100 kHz speed - not bad!

    I wrote some code that got me to the full 100 kHz speed. Since I was only using a 2-channel MCP3202 I got 50 kHz per channel measurement rate. This code could be modified to scan all 8 channels on a MCP3208. My code is a bit of a WIP so not sure if it would be of value to you. Let me know if you still want to see it.
  • r.daneelr.daneel Posts: 96
    edited 2014-01-15 09:10
    MJHanagan wrote: »
    The MCP320x chips do not measure the inputs simultaneously - only one channel at a time.

    That's what I thought, hence the question - I thought I must be missing something.

    When your code's ready to be shared I wouldn't mind taking a look - thanks.
Sign In or Register to comment.