SPIN code problem reading MCP3202
MJHanagan
Posts: 189
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?
Typical results when running the code above:
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
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).
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.
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.
FF
Ehhhh,never mind, just saw the dira for input.