How is this possible? (adc read problem)
turbosupra
Posts: 1,088
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.
Something 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?
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