Weid spin code behavior
Hi All,
I have modified a version of ADC.spin that takes two pin arguments as well as the return value in order to use the object with multiple channels of sigma delta hardware.
That code works fine. I have also added a cog stop method so that I can re-use the cog.
However, my problem is with the following code that calls the ADC_brm.spin object. . The 1st call to GetPot() works fine and I can access both sets of hardware if I change the Pin arguments. However calling the second call to GetPot() after the 1st
(they have the pin asignments shown) produces the same result for each. i.e. the "y" result is the same as the "x" result, "y" is incorrect.
I have stared at this code forever and can not see what is wrong. Can someone please have a look and tell me what the problem is?
Thanks,
Bernie
I have modified a version of ADC.spin that takes two pin arguments as well as the return value in order to use the object with multiple channels of sigma delta hardware.
That code works fine. I have also added a cog stop method so that I can re-use the cog.
However, my problem is with the following code that calls the ADC_brm.spin object. . The 1st call to GetPot() works fine and I can access both sets of hardware if I change the Pin arguments. However calling the second call to GetPot() after the 1st
(they have the pin asignments shown) produces the same result for each. i.e. the "y" result is the same as the "x" result, "y" is incorrect.
I have stared at this code forever and can not see what is wrong. Can someone please have a look and tell me what the problem is?
Thanks,
Bernie
PUB go | x, y
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
txpin = 30
rxpin = 31
SDF_0 = 3 'sigma-delta feedback
SDI_0 = 7 'sigma-delta input
SDF_1 = 5 'sigma-delta feedback
SDI_1 = 0 'sigma-delta input
VAR
long avg
OBJ
adc : "ADC_brm"
uart : "FullDuplexSerial"
PUB go | x, y
uart.start(rxpin, txpin, 0, 115200)
repeat
x := GetPot(SDI_0, SDF_0)
uart.str(string(13,11,"Pot0 = "))
uart.dec(x)
y := GetPot(SDI_1, SDF_1)
uart.str(string(", Pot1 = "))
uart.dec(y)
PRI GetPot (sdipin, sdfpin) : sample
sample := 0
repeat 16 ' average 16 samples
adc.SigmaDelta(sdipin, sdfpin, @avg)
sample += avg
adc.stop
sample >>= 4
sample -= 5240

Comments
Please check the way I have passed the pin arguments to the assembly function ..
Thanks,
VAR long cog CON bits = 14 'try different values from table above here PUB SigmaDelta (sdipin, sdfpin, sample) : okay mask_value := |<sdfpin ' SDF pin an output sdi_value := sdipin sdf_value := sdfpin okay := cog := cognew(@asm_entry, sample) + 1 'launch assembly program in a COG PUB stop '' Stop adc driver - frees a cog if cog cogstop(cog~ - 1) DAT org asm_entry mov dira,mask_value movs ctra,sdi_value movd ctra,sdf_value movi ctra,#%01001_000 mov frqa,#1 mov asm_c,cnt 'prepare for WAITCNT loop add asm_c,asm_cycles :loop waitcnt asm_c,asm_cycles 'wait for next CNT value '(timing is determinant after WAITCNT) mov asm_new,phsa 'capture PHSA mov asm_sample,asm_new 'compute sample from 'new' - 'old' sub asm_sample,asm_old mov asm_old,asm_new wrlong asm_sample,par 'write sample back to Spin variable "sample" '(WRLONG introduces timing indeterminancy here..) '(..since it must sync to the HUB) jmp #:loop 'wait for next sample asm_cycles long |< bits - 1 'sample time mask_value long 0 sdi_value long 0 sdf_value long 0 asm_c res 1 'uninitialized variables follow emitted data asm_cnt res 1 asm_new res 1 asm_old res 1 asm_sample res 1 asm_temp res 11. The repeat 16 loop tries to start a cog each time round the loop which will fail and probably isn't what you want
2. The adc cog takes some time to run and output a result. The main cog doesn't wait for it to generate a result so the results could be anything, try
This starts the adc cog once per get pot and forces a delay until the adc cog has generated a result each time round the repeat 16 loop. It does have a problem if the possible output is 0, if so you could change avg := -1 and check for <> -1 instead
Post Edited (Timmoore) : 8/22/2008 7:25:20 AM GMT
Thanks. I should have seen that I was starting 16 cogs .... good pick up.
Waiting for the conversion to finish I didn't even think about, must get used to things running in parallel
I will try your code out ..
Cheers,
Hi Tim,
I have tried the code and am seeing the individual channels, but am still getting some weid results.
With the averaging loop commented out so that I can see the return value, I am getting a result, but I have to subtract a large
offset value (see code below) before I get my 0 .. $1024 result for 0 .. 3.3v in. ( A2D set for 12 bits.
Can anyone tell me why there is this offset?
'' Fetch averaged A2D value for a pot connected to the two nominated pins PRI GetPot (sdipin, sdfpin) : sample sample := 0 adc.SigmaDelta(sdipin, sdfpin, @avg) 'repeat 16 ' average 16 samples avg := 0 repeat until avg <> 0 ' wait till conversion finished sample += (avg - $C9D793F4) adc.stop 'sample >>= 4Looking at the adc code there looks to be a bug the first time, asm_old is not initialized so the 1st output value will be incorrect, if that is what to are getting this it will be wrong. The value of asm_old will be always the same, it will be loaded from the hub memory so depends on what follows in the code.
The original adc.spin looks to have hte same problem.
If the first value has the problem but the 2nd, etc dont, then add a mov asm_old,#0 after the mov frqa,#1 line
The problem was in the original adc.spin code. After initializing the asm_old variable at the start every thing works fine.
How do we report bugs for objects in the exchange?
Thanks,
Bernie