How is this possible? (adc read problem)
I'm basing a 2.3hz pwm signal off of an ADC read. The signal is inconsistent randomly and will flatline at times for a few seconds. In troubleshooting this I discovered that a lot of times when I read an ADC value, the value is being returned as zero, when I know that I am feeding the mcp3208 pin a constant analog voltage for testing. Is there some sort of read write lock issue going on here? As you can see, within the same loop it will read 2 different values and the only thing I can think of is that I'm being locked out from a read operation, during a write operation? In the top screen capture I set the value for adcTHW to a hard coded 1000 (bypassing the ADC read function entirely) and the behavior still continued? In the bottom I let it read from adc, but tried to have it consistently update a temp variable, and then let me assign it to the comparison variable right before entering the case statement. If this is a problem with a lock, does anyone have a work around for this coding wise? Flags? I do not need a high speed read, a 2hz or 1hz update cycle would be fine.
Thanks

Thanks
pub main
repeat
adcTHWTemp := adc.read(4, adc#SE)
pub pwmOut
adcTHW := adcTHWTemp
if (adcTHW <> 0)
[b]debug.str(string("adcTHW is "))
debug.dec(adcTHW)
debug.tx(13)[/b]
case -1
(adcTHW => 3482) : ' 20C or 68F = 4.25vDc or 3482 ADC value (this is a guess at vDc and ADC)
onTime := f.fmul(c_20CelsiusOn, pwmOutputHertzToClkCycles)
onTime := f.fround(onTime)
offTime := f.fmul(c_20CelsiusOff, pwmOutputHertzToClkCycles)
offTime := f.fround(offTime)
'onTime := 32863070 ' 99% was 35200000
'offTime := 331950 ' 1% was 355556
if (coolantPwmDebug == true) AND ((cnt - coolantPwmDebugPause) > 0)
coolantPwmDebugPause := (coolantPwmDebugPauseTime + cnt)
coolantPwmDebugLoopOverride := true
debug.dec(adcTHW)
debug.Tx(13)
if (coolantPwmStateHigh == false) AND ((cnt - coolantPwmOffTime) > 0)
coolantPwmStateHigh := true
outa[O_TempGauge] := 1
coolantPwmOnTime := (onTime + cnt)
if (coolantPwmDebug == true) AND (((cnt - coolantPwmDebugPause) > 0) OR (coolantPwmDebugLoopOverride == true))
debug.str(string("20C On"))
debug.tx(13)
if (coolantPwmStateHigh == true) AND ((cnt - coolantPwmOnTime) > 0)
coolantPwmStateHigh := false
outa[O_TempGauge] := 0
coolantPwmOffTime := (offTime + cnt)
if (coolantPwmDebug == true) AND (((cnt - coolantPwmDebugPause) > 0) OR (coolantPwmDebugLoopOverride == true))
coolantPwmDebugLoopOverride := false
debug.str(string("20C Off"))
debug.tx(13)
...
[many other case statements]
...
(adcTHW < 82) AND (adcTHW => 0) : ' AND (adcTHW => 82) :
[b] debug.str(string("<<<<< 82"))
debug.tx(13)
debug.dec(adcTHW)
debug.tx(13)
debug.dec(adcTHW)
debug.tx(13) [/b]


Comments
The zeros are less common, but still occur.
if (adcTHW <> 0) debug.str(string("adcTHW is ")) [b]debug.dec(adc.read(4, adc#SE)) [/b] debug.tx(13) (adc.read(4, adc#SE) < 82) AND (adc.read(4, adc#SE) => 0) : ' AND (adcTHW => 82) : debug.str(string("<<<<< 82")) debug.tx(13) [b]debug.dec(adc.read(4, adc#SE))[/b] debug.tx(13) [b]debug.dec(adc.read(4, adc#SE))[/b] debug.tx(13)VAR long OKtoRead pub main repeat repeat until OKtoRead = 1 OKtoRead := 0; adcTHWTemp := adc.read(4, adc#SE) OKtoRead := 1; pause 50 pub pwmOut repeat until OKtoRead = 1 OKtoRead:=0 adcTHW := adcTHWTemp OKtoRead:=1Something like the above pseudocode has worked for me previously when I experienced a similar problem.
You could also use locks I suppose...
Discalimer: The syntax of the code fragment above is way, way wrong - I don't do much Spin - but the logic is hopefully apparent.
Thanks for the reply. So if I understand correctly, you've had a similar adc read issue and you used flags to allow the cogs to avoid a read issue?
var long adccog long adcstack[32] long pot[8] ' averaged pots long accidx long acc[32] ' 4 readings for 8 pots pri start_adc if (adccog) ' stop if already running cogstop(adccog-1) adccog := cognew(scan_pots, @adcstack) + 1 pri scan_pots | t, ofs, ch, sum '' Scans and averages adc inputs '' -- averages adc inputs over four readings adc.start(ADC_CS, ADC_CLK, ADC_DIO) ' mcp3208 (Spin) t := cnt repeat ofs := accidx << 3 ' offset into accumulator array repeat ch from 0 to 7 acc[ch + ofs] := adc.read(ch, adc#SE) ' read channels sum := acc[ch] ' rolling average sum += acc[ch + 08] sum += acc[ch + 16] sum += acc[ch + 24] pot[ch] := sum >> 2 if (++accidx == 4) accidx := 0 waitcnt(t += (10 * MS_001))I don't have a spare cog, but I can have a spare cog with some movement ... my one spare cog is being used to simulate something for testing but I can disable it and replace it with that function if that is the best way.
Right now it was running inside of the main cog, I have tried the flag suggestion and it is working on the bench right now, I do not know if it will work out in the "field" yet. I had considered doing averaging but had not gotten that far yet, so thank you for that example as well. I will test tonight/tomorrow and report back.
I only had one cog (pub main) reading the adc object and then set a global variable value to the read adc value. I was getting a 0 value when reading the global variable from the second cog and was trying to troubleshoot why thinking that it may have been an issue that when the second cog was trying to read the global variable, the first cog (pub main) was writing to it and there was a lock issue.
All that being said, I wrote the code for the flags and I also found a typo in my code. When I came home and tested the code, it worked. I'm not sure if the flags or the corrected typo fixed it. I am also going to implement your suggestion of a rolling average, as I think that is a great idea. If I run into problems again, I will attach all of my code and objects if the size is not discouraging ... if the size is, I'll move the failing parts to a new smaller project, verify the behavior is still there and attach that.
Yes, that is correct. I also use Jon's approach as well especially if I have multichannel ADC acquiring multiple channels. A separate cog reading (and optionally averaging) the ADC values then writing the processed values to a global hub variable works nicely. You can then read the global variable by any other cog without fear of getting an anomalous value. I almost certainly learned these techniques from Jon and others, a tip of the hat to all who have unknowingly helped me!
-Mike