Shop OBEX P1 Docs P2 Docs Learn Events
reading multiple analog Inputs — Parallax Forums

reading multiple analog Inputs

CodingChimpCodingChimp Posts: 15
edited 2022-08-16 01:06 in Propeller 2

I wrote the attached code to read multiple analog inputs ( a max of 32 ) . Each is sampled eight times and then averaged then stored for calculation. Then the endpoints for each sensor are used to calculate the full scale reading. My problem is that one analog input works fine, two work fine, but the third reads a abnormally high number in the middle of the range. I have moved the inputs so that the sensor I am reading functions fine when only two sensors are read. I have even run two cogs with the same code and two inputs works on one cog while the third is on a different cog and it works fine. Am I going crazy or what?

Comments

  • JonnyMacJonnyMac Posts: 9,003
    edited 2022-08-16 02:06

    I just drove home from DEF CON, so my mind is a little mushy -- fair warning to take these suggestions as potentially questionable.

    These lines:

      start_pin := s_pin
      n_sensors := n_sens
      zero_val := val_z
      max_val := val_mx
    

    ...can be replaced with:

      longmove(@start_pin, @s_pin, 4)                               ' copy pins 
    

    I'm pretty sure you could change this:

                            mov     ptr_out,        ptra
                            add     ptr_out,        #20
    

    ...to:

                            mov     ptr_out         ptra[5] 
    

    I don't know if this has anything to do with your problem, but you have this line

                            jmp     #end_prog 
    

    ...that jumps to the end -- it doesn't loop back to the top. I assume your PASM constants and vars are being treated as code. If your goal is to stop the code in it's tracks, you could do this:

                            jmp     #$ 
    
  • Jon,
    Thanks for your reply, I apologize for the length of the code but it didn't feel right to leave anything out. I am a big fan of your work with Parallax. I tried the ptra[5] syntax but the propeller tool gave me an error. I will look at the ending that could be the issue.

  • evanhevanh Posts: 15,423
    edited 2022-08-16 03:27

    The jmp #end_prog is a big no-no. It falls off the end into data. If you don't need this to loop then may as well just have it as a called subroutine of the main spin program instead of starting a cog. Or at the very least issue a COGSTOP. As is, that cog is crashing.

  • I changed the ending to loop endlessly after setting cmd to 0. I am still having the issue it is like the pin is not configured correctly, I am recieving changing values but they don't match the voltage at the pin. I put debug statements all over this routine to see what it happening, but I came up with no smoking gun.

  • JonnyMacJonnyMac Posts: 9,003
    edited 2022-08-16 18:06

    Is this a run-once cog? Or is it the start of something bigger that will need to run in a loop to handle other commands? If the latter, you might consider a simple structure like this at the top of your pasm code.

                            org       0
    
    entry                   setq      #5-1                          ' get 5 parameter from hub
                            rdlong    cmd, ptra
                            jmp       #check_cmd1
    
    get_cmd                 rdlong    cmd, ptra
                            tjz       cmd, #get_cmd
    
    check_cmd1              cmp       cmd, #CMD_1            wcz
            if_e            jmp       #do_cmd1
    
    check_cmd2              cmp       cmd, #CMD_2            wcz
            if_e            jmp       #do_cmd2
    
    check_cmd3              cmp       cmd, #CMD_3            wcz                  
            if_e            jmp       #do_cmd3                     
    
    bad_cmd                 wrlong    #0, ptra
                            jmp       #get_cmd
    
  • This code should really be running all the time endlessly. Your code definitely looks more readable and I will be sure to add it, but I think I found it. I have yet to test this out but my counting variables j and k are added to pin each cycle. that means the pin would be added with 0 the first cycle, 1 the second cycle, then 2 the third cycle. That would be one pin over from where I wanted to read hence my bogus reading.

  • Is the process:
    -- wait for read command
    -- iterate through pins
    -- calibrate and read each pin
    -- return average for each pin to hub
    -- back to top

    ?

  • BTW, if you have a lot of commands, and they are contiguous, 1 to n, you can do a structure like this:

    entry                   setq      #5-1                          ' get 5 parameter from hub
                            rdlong    cmd, ptra
                            jmp       #check_cmd 
    
    get_cmd                 rdlong    cmd, ptra                     ' check for command
                            tjz       cmd, #get_cmd
    
    check_cmd               fge       cmd, #0                       ' limit range
                            fle       cmd, #4                       ' commands + 1
                            add       cmd, #jmp_table               ' prep for jump
                            jmp       cmd                           ' do it
    
    jmp_table               jmp       #done                         ' 0          
                            jmp       #do_cmd1                            
                            jmp       #do_cmd2                            
                            jmp       #do_cmd3
    '                       jmp       #done                         ' 4          
    
    done                    wrlong    #0, ptra
                            jmp       #get_cmd
    
  • Jon,

    Thanks for the help. I will definitely put your suggestions into practice. Whatever makes this easier to read will help next time I have to touch it. It was designed to read some contiguous pins analog inputs average each of them to clean them up then scale them to a full scale value and zero of my choice.

  • Do you want to read them on demand or automatically (once the cog is started). I have used both approaches, usually with JonyJib camera controls where we have lots of analog inputs (joysticks, etc).

  • Automatically

  • JonnyMacJonnyMac Posts: 9,003
    edited 2022-08-17 19:29

    You want to start a cog that you give a base pin, # of pins, low and high scaled values, and pointer to a buffer to drop the results. Then you want to have that cog take eight samples for every pin, average and scale them, and then write to the assigned hub location? I'm asking because I've done this with a physical ADC chip on the P1, and this would be a good mental exercise. If this is all about automatic reading, it doesn't seem like the command value is needed. Or am I missing something?

    While on a break I put this together. It's simple (simplistic?) and, perhaps, overwrought, but I think it does the job. It does compile, but I don't have time to test right now which is why I didn't attach a file (after testing, I will).

    dat
    
                            org       0
    
    entry                   setq      #5-1                          ' get 5 parameter from hub
                            rdlong    basepin, ptra
    
                            mov       ch, #0
    an8_loop                mov       chpin, basepin
                            add       chpin, ch
    
    read_ch                 mov       rdnum, #0   
                            mov       rawacc, #0
    .loop                   call      #get_cal_lo
                            call      #get_cal_hi
                            call      #get_raw
                            add       rawacc, rawval
                            incmod    rdnum, #7                     ' do 8 samples
                            tjnz      rdnum, #.loop
    
                            shr       rawacc, #3                    ' average
                            call      #get_scaled
    
                            mov       t1, ch
                            shl       t1, #2
                            add       t1, hub
                            wrlong    scaledval, t1
    
                            mov       t1, npins
                            sub       t1, #1
                            incmod    ch, t1
                            jmp       #an8_loop
    
    
    get_cal_lo              fltl      chpin                            
                            wrpin     ##(P_ADC | P_ADC_GIO), chpin   
                            wxpin     #%00_1101, chpin
                            wypin     #0, chpin
                            dirh      chpin                            
                            waitx     ##(8192 << 2)                
                            rdpin     callo, chpin
                            ret
    
    
    get_cal_hi              fltl      chpin                            
                            wrpin     ##(P_ADC | P_ADC_GIO), chpin   
                            wxpin     #%00_1101, chpin
                            wypin     #0, chpin
                            dirh      chpin                            
                            waitx     ##(8192 << 2)                
                            rdpin     calhi, chpin
                            ret
    
    
    get_raw                 fltl      chpin                            
                            wrpin     ##(P_ADC | P_ADC_1X), chpin   
                            wxpin     #%00_1101, chpin
                            wypin     #0, chpin
                            dirh      chpin                            
                            waitx     ##(8192 << 2)                
                            rdpin     rawval, chpin
                            ret              
    
    
    get_scaled              mov       t1, rawacc
                            sub       t1, callo
                            mov       t2, uhi
                            sub       t2, ulo
                            qmul      t1, t2
                            getqx     t1
                            mov       t2, calhi
                            sub       t2, callo
                            qdiv      t1, t2
                            getqx     scaledval
                            add       scaledval, ulo
                            fge       scaledval, ulo
                            fle       scaledval, uhi
                            ret
    
    ' --------------------------------------------------------------------------------------------------
    
    basepin                 res       1                             ' first pin in group
    npins                   res       1                             ' number of pins in group
    ulo                     res       1                             ' user value for 0.0v
    uhi                     res       1                             ' user value for 3.3v
    hub                     res       1                             ' pointer to user output array
    
    ch                      res       1                             ' active channel
    chpin                   res       1                             ' active pin
    rdnum                   res       1                             ' active reading   
    
    callo                   res       1                             ' analog level at ground
    calhi                   res       1                             ' analog level at 3.3v
    rawval                  res       1                             ' raw reading
    rawacc                  res       1                             ' raw accumulator
    scaledval               res       1                             ' scaled to user range
    
    t1                      res       1                             ' work vars
    t2                      res       1
    t3                      res       1
    
                            fit       496
    
  • Jon,

    Thank you for going through this trouble. I figured the calibrate portion should be done only once then readings forever after that. I guess I see your point now that I could just loop forever over the read portion after the cal is done and continuously update the readings.

  • Jon,

    I noticed you used some P2 commands that I am not used to yet, as well as a better use of memory in total. I am still learning how to write efficient P2 code. I had not written too much in the way of assembly using the P1, but I knew I wanted to use the new capabilities of the P2 once it came out. I am waiting for a good book on using the P2 and a Propeller Live Forum youtube video(s) on P2 assembly language programming. I am building a simple roverbot with IR sensors for avoidance probably way overkill to use a P2 Edge board, but I am certainly having a lot of fun. Especially using the debug windows in Propeller Tool for inspecting values in my assembly code.

  • I try to make code very modular. You could do one cal (low and high) per read cycle -- that would be an easy mod with the way the code is laid out. To me, code should be like Legos: build small, useful "bricks" and then assemble them as required. This style lends itself to debugging as well. I have had a busy week after being out of town at DEF CON; perhaps tonight I can run my code on a JonnyMac to see if it's working.

Sign In or Register to comment.