I am code blind - MCP3208 continous reading into global LONGs - no longer works
Erlend
Posts: 612
I am re-building my project to move from birds nest style to a more robust build. The rebuildt ADC board works fine when I test it with MCP3208_DEMO, but when I run the code that continously reads all channels (jm_mcp3208_auto) and put the values into a set of 8 consecutive LONGS that I have passed the pointer of, the values passed are 0 - 4095 - 0 - 4095 - 0 - 4095 - 0 - 4095, no matter what the adc inputs are. The drives-me-crazy factor is that I finished debugging this a year ago, and it worked perfect. I have stripped my code of everything not to do with the adc values, and this looks like this:
-and JonnyMac's (very nice) code looks like this:
thanks for any guidance,
Erlend
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
'pin assignments:
PinADCdata = 7 'DAT pin 11&12
PinADCclk = 8 'CLK pin 13
PinADCcs = 9 'CS pin 10
'parameters
LCD_BAUD = 19_200
VAR
'Variables to hold I/O values
'============================
'ADC analogue input values - obeying the requirement for declaring 8 consecutive LONGs
LONG gAnLevelWater
LONG gAnTempWater
LONG gAnPressWater
LONG gAnPanic
LONG gAnWeightCup
LONG gAnVoltageSupply
LONG gAnUVflame
LONG gAnAmperage
OBJ
lcd : "Parallax Serial Terminal"
adc : "ADCreader"
PUB Main
'Startup procedures
'==================
lcd.start(LCD_BAUD) 'not lcd, but pst here
'start ad converter reader
adc.startx(PinADCcs, PinADCclk, pinADCdata, 8, @gAnLevelWater) 'gAnLevelWater is the first in the block of 8 LONGs
waitcnt(clkfreq + cnt)
'Testing:
lcd.str(STRING("ADC reading starts:", 13))
waitcnt(clkfreq + cnt)
Repeat
lcd.dec(adc.read(0)) 'just to check if reading a channel direct works better
lcd.str(STRING(" read direct", 13))
lcd.dec(gAnLevelWater)
lcd.str(STRING(" ADC", 13))
lcd.dec(gAnTempWater)
lcd.str(STRING(" degC,", 13))
lcd.dec(gAnPressWater)
lcd.str(STRING(" Bar,", 13))
lcd.dec(gAnPanic)
lcd.str(STRING(" mSec,", 13))
lcd.dec(gAnWeightCup)
lcd.str(STRING(" gram,", 13))
lcd.dec(gAnVoltageSupply)
lcd.str(STRING(" Volt,", 13))
lcd.dec(gAnUVflame)
lcd.str(STRING(" UV%,", 13))
lcd.dec(gAnAmperage)
lcd.str(STRING(" mA,", 13))
waitcnt(clkfreq + cnt)
lcd.clear
DAT
-and JonnyMac's (very nice) code looks like this:
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
'' =================================================================================================
''
'' File....... jm_mcp3208_auto.spin
'' Purpose.... S/E auto/continuous reader for MCP3208/MCP3204 ADCs
'' Author..... Jon "JonnyMac" McPhalen
'' Copyright (c) 2010-2013 Jon McPhalen
'' -- see below for terms of use
'' E-mail..... jon@jonmcphalen.com
'' Started.... 03 JUL 2010
'' Updated.... 19 JAN 2013
''
'' =================================================================================================
{{
Auto-reader for MCP3208 (use .start or .startx) and MCP3204 (use .startx method) ADCs.
3v3-5v0
MCP3208 
┌─────────────────┐ │
ch0 ────┤1 CH0 VDD 16├──┫
ch1 ────┤2 CH1 VREF 15├──┘
ch2 ────┤3 CH2 AGND 14├──┐
ch3 ────┤4 CH3 CLK 13├──│──────── clk
ch4 ────┤5 CH4 DOUT 12├──│──┐ 3k3
ch5 ────┤6 CH5 DIN 11├──│────┻── dio
ch6 ────┤7 CH6 /CS 10├──│──────── cs
ch7 ────┤8 CH7 DGND 9├──┫
└─────────────────┘ │

3v3-5v0
MCP3204 
┌─────────────────┐ │
ch0 ────┤1 CH0 VDD 14├──┫
ch1 ────┤2 CH1 VREF 13├──┘
ch2 ────┤3 CH2 AGND 12├──┐
ch3 ────┤4 CH3 CLK 11├──│──────── clk
─┤5 NC DOUT 10├──│──┐ 3k3
─┤6 NC DIN 9├──│────┻── dio
┌──┤7 DGND /CS 8├──│──────── cs
│ └─────────────────┘ │
 
}}
var
long cog ' cog running reader
long cs ' pins used
long clk
long dio
long channels
long p_adcvals ' pointer to adc readings
long adc[8] ' adc readings
long stack[32] ' memory for reader cog
pub start(cspin, clkpin, diopin)
'' Start free-running MCP3204/8 reader
'' -- store readings in object var space
'' -- assumes 8-channel MCP3208
return startx(cspin, clkpin, diopin, 8, -1)
pub startx(cspin, clkpin, diopin, nchans, p_analog)
'' Start free-running MCP3204/8 reader
'' -- store readings at user-specified location (parent var space)
'' -- nchans is number of channels, 1..8
'' -- p_analog is a pointer to a block of eight longs
'' * use -1 for local storage
stop ' kill if already running
longmove(@cs, @cspin, 3) ' copy pins
channels := 1 #> nchans <# 8 ' keep channel count legal
if (p_analog < 0)
p_adcvals := @adc ' use internal array
else
p_adcvals := p_analog ' use specified array
cog := cognew(mcp3208, @stack) + 1 ' start reader cog
return cog
pub stop
'' Unload MCP3204/8 reader cog
if (cog) ' if running
cogstop(cog - 1) ' stop
cog := 0
longfill(p_adcvals, 0, channels)
pub read(ch)
'' Get last read channel value
if ((ch => 0) and (ch < channels)) ' valid?
return long[p_adcvals][ch] ' return channel value
else
return 0
pub address
'' Returns address of adc results storage
return p_adcvals
pri mcp3208 | ch, mux, level ' call with cognew()
outa[cs] := 1 ' output high
dira[cs] := 1
outa[clk] := 0 ' output low
dira[clk] := 1
repeat
repeat ch from 0 to (channels-1) ' loop through channels
outa[cs] := 0 ' activate adc
' output mux bits, MSBFIRST
dira[dio] := 1 ' dio is output
mux := (%11000 + ch) << (32-5) ' single-ended mode
repeat 5 ' send mux bits
outa[dio] := (mux <-= 1) & 1 ' output a bit
outa[clk] := 1 ' clock the bit
outa[clk] := 0
' input data bits, MSBPOST
dira[dio] := 0 ' dio is input
level := 0 ' clear work var
repeat 13 ' null + 12 data bits
outa[clk] := 1 ' clock a bit
outa[clk] := 0
level := (level << 1) | ina[dio] ' input data bit
outa[cs] := 1 ' de-activate adc
long[p_adcvals][ch] := level & $FFF ' update results array
dat
{{
Terms of Use: MIT License
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 NON-INFRINGEMENT. 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.
}}
thanks for any guidance,
Erlend

Comments
doing that mod in the code results in this output:
0 read direct
0 ADC
1 degC,
2 Bar,
3 mSec,
4 gram,
5 Volt,
6 UV%,
7 mA,
Which proves that writing back to the global vars works fine. Now that's sorted: my code is not faulty, and JonnyMac's code simply is not wrong, so. ...waitaminute...(.....connecting scope, checking signals, compare with when running code that works, eureka...).... I go over the pin assignments and wiring one more time: it appears I have swapped CLK and CS. I was fooled by that the communication seemed to work, as well as when something doesn't work I instinctively blame my own code.
Thanks for the guidance : )
Erlend
Erlend
Jim