Shop OBEX P1 Docs P2 Docs Learn Events
Weid spin code behavior — Parallax Forums

Weid spin code behavior

bmentinkbmentink Posts: 107
edited 2008-08-25 01:11 in Propeller 1
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

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

  • TimmooreTimmoore Posts: 1,031
    edited 2008-08-22 06:01
    You need to post your modified adc as well, it could easily be a problem in that code
  • bmentinkbmentink Posts: 107
    edited 2008-08-22 06:38
    ok, here it is:

    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       1
    
    
  • TimmooreTimmoore Posts: 1,031
    edited 2008-08-22 07:20
    There are 2 issues I can see
    1. 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

    PRI GetPot (sdipin, sdfpin) : sample 
    
    sample := 0 
    adc.SigmaDelta(sdipin, sdfpin, @avg) 
    repeat 16 ' average 16 samples 
      avg := 0 
      repeat until avg <> 0 
      sample += avg 
    adc.stop 
    sample >>= 4 
    sample -= 5240
    

    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
  • bmentinkbmentink Posts: 107
    edited 2008-08-22 08:11
    Hi Timmoore,

    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 roll.gif

    I will try your code out ..

    Cheers,
  • bmentinkbmentink Posts: 107
    edited 2008-08-24 22:38
    O
    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 >>= 4
    
    
  • TimmooreTimmoore Posts: 1,031
    edited 2008-08-25 00:36
    Can you let it run for the 16 times but send to the uart the value of each avg. i.e. add a uart.dec(avg) before the sample += (avg - $C9D793f4) line.
    Looking 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
  • bmentinkbmentink Posts: 107
    edited 2008-08-25 01:04
    Yep, you nailed it Tim,

    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
  • TimmooreTimmoore Posts: 1,031
    edited 2008-08-25 01:11
    I would create a new thread, call it something like "intialization bug in adc.spin" and address the post to Beau who wrote adc.spin and describe the problem.
Sign In or Register to comment.