Shop OBEX P1 Docs P2 Docs Learn Events
SPIN code problem reading MCP3202 — Parallax Forums

SPIN code problem reading MCP3202

MJHanaganMJHanagan Posts: 189
edited 2013-03-07 12:21 in Propeller 1
Wow, I am banging my head against the wall looking for the error in my SPIN code. I am trying to write the basic code to communicate with an MCP3202 and while the hardware setup works fine with downloaded MCP32xx objects I cannot seem to get my simple code to work. I have compared my code with Harprit's simple MCP3202 SPIN code and I cannot identify where I'm going wrong.

My hardware setup has a constant 2.505 V signal on channel 0 and a small AC voltage offset by +0.2V on channel 1. The "ZCPin" changes state each time the AC voltage passes through zero (excluding the +0.2 VDC offset). When I run any of the downloaded MCP32xx objects I get the correct measurements but when I run my code I get output as shown below the code.

Can anyone spot my error?
CON

    _clkmode = xtal1 + pll16x                           
    _xinfreq = 5_000_000

    ZCPin = 11      ' Zero cross signal input pin
    TransformerPin = 18  ' Output pin which turns on the ZC TRIAC relay sending 120 VAC to the power transformer.

    ADCCS = 26    'MCP3202 Chip Select pin.
    ADCClk = 25   'MCP3202 serial clock pin
    ADCDIO = 24   'MCP3202 Data in and data out pin

    High = 1
    Low = 0
    Output = 1
    Input = 0


OBJ

        pst     : "Parallax Serial Terminal"

Var

  long ADCData[ 100 ], ADCtime, nChan
  
Pub Main |  i, j, k


    pst.Start( 115_200 )             'Start the serial terminal interface running at a baud rate of 115,200
    waitcnt (cnt + clkfreq/2 )
    pst.Beep
    pst.clear

    pst.str(string(pst#NL,"Operating clock frequency: "))
    pst.dec( clkfreq/1000000 )
    pst.str(string(" MHz"))
     
    dira[ ZCPin ] := Input  ' Set ZC pin as input

    DIRA[ TransformerPin ] := Output   ' Set transformer pin as output.
    outa[ TransformerPin ] := High   ' Turn on power to transformer.

    waitcnt (cnt + clkfreq )
    
    pst.str(string(pst#NL,pst#NL,"Power is now on.")) 


   pst.Beep

   nChan := 0
   
      j := ADCRead( nChan )
      pst.str(string(pst#NL, pst#NL,"ADCReads: "))
      pst.dec( j )
      pst.str( string(" on channel: "))
      pst.dec( nChan )
      pst.str( string(" Single read CNT: "))
      pst.dec( ADCtime )
      pst.str(string(" Data follows:", pst#NL))      
      IF j > 0
        i := 0
        REPEAT j
          pst.str(string(pst#NL,"n="))
          pst.dec( i )
          pst.str(string("  "))
          pst.dec( ADCData[i] )
          pst.str(string(", %"))
          pst.bin( ADCData[i++], 16 )


   nChan := 1
   
      j := ADCRead( nChan )
      pst.str(string(pst#NL, pst#NL,"ADCReads: "))
      pst.dec( j )
      pst.str( string(" on channel: "))
      pst.dec( nChan )
      pst.str( string(" Single read CNT: "))
      pst.dec( ADCtime )
      pst.str(string(" Data follows:", pst#NL))      
      IF j > 0
        i := 0
        REPEAT j
          pst.str(string(pst#NL,"n="))
          pst.dec( i )
          pst.str(string("  "))
          pst.dec( ADCData[i] )
          pst.str(string(", %"))
          pst.bin( ADCData[i++], 16 )

  outa[TransformerPin] := Low 'Turn off main track transformer.

   pst.str(string(pst#NL,"  Transformer power is now off."))
   pst.Beep
   pst.str(string(pst#NL, pst#NL, "Program run terminated, good-bye."))
   pst.Beep

PUB ADCRead( Chan ) | i, j, k, StartCNT, EndCNT


    DIRA[ ADCClk ] := Output    ' Set clock pin for output
    OUTA[ ADCClk ] := Low       ' Set clock pin low

    DIRA[ ADCCS ] := Output      ' Set chip select pin for output
    OUTA[ ADCCS ] := High        ' Set chip select pin high

    WAITPEQ( %0, |<ZCPin, 0 )    'Wait for ZC pin to go low

    j := 0

    WAITPEQ( |<ZCPin, |<ZCPin, 0 )    ' Wait for ZC pin to go high to initiate measurement loop

REPEAT UNTIL INA[ ZCPin ] == 0  ' Make repeated ADC measurements until the zero cross pin goes low

    StartCNT := CNT

    DIRA[ ADCDIO ] := Output    ' Set DIO pin as output
    OUTA[ ADCDIO ] := Low        ' Set data pin low
    
    OUTA[ ADCCS ] := Low        ' Set chip select pin low to initiate ADC communication/conversion process
    
    OUTA[ ADCDIO ] := High      ' Set DIO pin high (start bit)
    OUTA[ ADCClk ] := High      ' Set clock pin high.  The MCP3202 reads the data on the rising edge of the clock.

    OUTA[ ADCClk ] := Low       ' Set clock pin low

    OUTA[ ADCDIO ] := High      ' Set DIO pin high for single ended measurements (which it is already!)
    OUTA[ ADCClk ] := High      ' Set clock pin high.  The MCP3202 reads the data on the rising edge of the clock.   

    OUTA[ ADCClk ] := Low       ' Set clock pin low

    OUTA[ ADCDIO ] := Chan      ' Set DIO pin low for Ch0 or high for Ch1
    OUTA[ ADCClk ] := High      ' Set clock pin high.  The MCP3202 reads the data on the rising edge of the clock.   
                                ' The MCP3202 begins the sampling of the voltage at this moment.

    OUTA[ ADCClk ] := Low       ' Set clock pin low

    OUTA[ ADCDIO ] := High      ' Set DIO pin high for MSB data mode (MCP3202 send result MSB first)
    OUTA[ ADCClk ] := High      ' Set clock pin high.  The MCP3202 reads the data on the rising edge of the clock.   

    OUTA[ ADCClk ] := Low       ' Set clock pin low
                                ' The MCP3202 ends the sampling of the voltage at this moment.

    OUTA[ ADCDIO ] := Low
    DIRA[ ADCDIO ] := Input      ' Set DIO pin for input

    OUTA[ ADCClk ] := High       ' Set clock pin high
    OUTA[ ADCClk ] := Low        ' The MCP3202 outputs a low null bit on the falling edge of the clock pin.
    OUTA[ ADCClk ] := High       ' Set clock pin high
    
    i := %0       ' Clear the result variable

    REPEAT 12               ' Read the the subsequent 12 data bits (MSB to LSB order)
      OUTA[ ADCClk ] := Low ' Set clock pin low. The MCP3202 outputs the next data bit on the falling edge of the clock pin.
      i <<= 1               ' Shift already read data bits left one position to make room for the next data bit.
      i := i + INA[ ADCDIO ]' Add the read data bit into the LSB position
      OUTA[ ADCClk ] := High' Set clock pin high

    ADCData[ j++ ] := i     ' Copy the ADC data into the data storage array
    OUTA[ ADCClk ] := Low   ' Set clock pin low
    OUTA[ ADCCS ] := High   ' Set chip select pin high to end communications.
    
    EndCNT := CNT

    ADCtime := EndCNT - StartCNT

RETURN j-1       ' Return the number of measurements made.

Typical results when running the code above:
Operating clock frequency: 80 MHz

Power is now on.

ADCReads: 12 on channel: 0 Single read CNT: 49424 Data follows:

n=0  2, %0000000000000010
n=1  7, %0000000000000111
n=2  2, %0000000000000010
n=3  0, %0000000000000000
n=4  0, %0000000000000000
n=5  0, %0000000000000000
n=6  4090, %0000111111111010
n=7  4095, %0000111111111111
n=8  4095, %0000111111111111
n=9  0, %0000000000000000
n=10  5, %0000000000000101
n=11  5, %0000000000000101

ADCReads: 12 on channel: 1 Single read CNT: 49424 Data follows:

n=0  264, %0000000100001000
n=1  0, %0000000000000000
n=2  0, %0000000000000000
n=3  0, %0000000000000000
n=4  0, %0000000000000000
n=5  0, %0000000000000000
n=6  0, %0000000000000000
n=7  0, %0000000000000000
n=8  0, %0000000000000000
n=9  0, %0000000000000000
n=10  0, %0000000000000000
n=11  0, %0000000000000000
  Transformer power is now off.

Program run terminated, good-bye.

Comments

  • Mark_TMark_T Posts: 1,981
    edited 2013-03-03 16:13
    I don't understand your indentation with the REPEAT UNTIL
  • MJHanaganMJHanagan Posts: 189
    edited 2013-03-03 16:50
    Mark_T wrote: »
    I don't understand your indentation with the REPEAT UNTIL

    I am trying to measure the voltage as many times as possible during the positive phase of the AC voltage. I wait for the voltage to pass through zero before starting then measure as many times as possible until it passes through zero again. In SPIN I only get 10-15 measurements depending on the lines of code. Once I get the SPIN working I want to go into PASM so I can get many more samples measured (the ultimate goal being ~100+ samples per 60 Hz line cycle of V and I data so I can calculate the real power being dissipated).
  • JLockeJLocke Posts: 354
    edited 2013-03-04 00:39
    MJHanagan wrote: »
        j := 0
    
        WAITPEQ( |<ZCPin, |<ZCPin, 0 )    ' Wait for ZC pin to go high to initiate measurement loop
    
    REPEAT UNTIL INA[ ZCPin ] == 0  ' Make repeated ADC measurements until the zero cross pin goes low
    
        StartCNT := CNT
    
        DIRA[ ADCDIO ] := Output    ' Set DIO pin as output
        OUTA[ ADCDIO ] := Low        ' Set data pin low
        
    

    I believe the reference was to the REPEAT being aligned with the left margin (same as your function declaration). Is this intentional; does your code indent like that, or was that an artifact of posting your code to the forum?
  • MJHanaganMJHanagan Posts: 189
    edited 2013-03-06 03:44
    JLocke wrote: »
    I believe the reference was to the REPEAT being aligned with the left margin (same as your function declaration). Is this intentional; does your code indent like that, or was that an artifact of posting your code to the forum?

    Yes, the REPEAT is supposed to be at theeftmost position. All the ADC measurement is repeated until the next zero crossing event. In SPIN I get roughly 10 to 15 measurements in this REPEAT loop. The error is somewhere below this line.
  • Mike GMike G Posts: 2,702
    edited 2013-03-06 06:11
    Are you sure the SPIN code within the REPEAT UNTIL INA[ ZCPin ] == 0 block is always executing within the positive swing of the signal? I believe this is right, ~0.8 * (2 * 1/freq).

    I would spin up another COG to process zero crossing state.
  • MJHanaganMJHanagan Posts: 189
    edited 2013-03-07 07:35
    Mike G wrote: »
    Are you sure the SPIN code within the REPEAT UNTIL INA[ ZCPin ] == 0 block is always executing within the positive swing of the signal? I believe this is right, ~0.8 * (2 * 1/freq).

    I would spin up another COG to process zero crossing state.

    Yes, the ZCPin is high when the AC voltage is high. The SPIN code within the REPEAT loop runs 10-15X during each positive phase of the AC voltage. The problem I'm having has something to do with the communication code to the MCP3202. When I substitute code from one of the downloaded objects I get the correct data from the MCP3202 but when I substitute my code it get back garbage from the MCP3202.
  • frank freedmanfrank freedman Posts: 1,983
    edited 2013-03-07 12:21
    I could be wrong about this, and was.........

    FF

    Ehhhh,never mind, just saw the dira for input.
Sign In or Register to comment.