Shop OBEX P1 Docs P2 Docs Learn Events
Calculation with SX28 — Parallax Forums

Calculation with SX28

jmokiejmokie Posts: 13
edited 2007-08-18 21:29 in General Discussion
I have been fiddling with this problem for some time now without any success.· Please let me tap into your knowledge to help me out.

Problem:·
I have three optical sensors that I am trying to use for line following.· I have successfully connected them as a/d inputs to the SX28.· The outputs seem to have a reasonable relationship to the manufacture's curves.· I need to calculate max, min, and avg of each of the sensors in order to use their signals for PID control of the motors.

3 x 3 sensors = 9 variables.· Now when I use my method of noise reduction by taking the avg of 5 readings, I need 3 word variables(·X 5 bytes and then divide by 5.) so that takes another 6 bytes of variable space.· I have reached the limit of variable memory space (·in order to do this, what with needing a few other variables for PVerror, Pulse widths, timers, etc.

My variable list and the subroutine that I am using are listed below.· I am a basic programmer and fairly new to SX28.· Any suggestions?
Jerry
LMax·var·byte
LMin·var·byte
LAvg·var·byte································ ·· Left Sensor values
Lf·var·word·· [noparse][[/noparse]for calculating avg]
Lval·var·byte [noparse][[/noparse]raw value from sensor]
RMax·var·byte
RMin·var·byte
RAvg·var·byte································· Right sensor values
Rt·var·word·· [noparse][[/noparse]for calculating avg]
Rval·var·byte· [noparse][[/noparse]raw value from sensor]
Ctr·var·word··· [noparse][[/noparse]for calculating avg]
CVal·var·byte·· [noparse][[/noparse]raw value from sensor]
CMax·var·byte···································· Center sensor
CMin·var·byte
CAvg·var·byte
timer·var·byte


Snsrread:
· timer = 0
··
· For timer = 0 to 5
· ·ANALOGIN InCPin, OutCPin, Cval, 2
· ·ANALOGIN InRPin, OutRPin, Rval, 2
· ·ANALOGIN InLPin, OutLPin, Lval, 2
·Ctr = Ctr + Cval
······· Rt = Rt + Rval
·Lf = Lf + Lval
· next
· Ctr = Ctr/5···· [noparse][[/noparse]calculate avg]
'
Calculate Min, Max, Avg of Ctr
· \mov Cval, Ctr lsb··· [noparse][[/noparse]take the lsb·to conserve on memory]
· If Cval < Cmin then
·Cmin=Cval
· endif
· If Cval>CMax then
·CMax=Cval
· endif
· CAvg=CMax+CMin
· CAvg=Cavg/2
·
· Rt = Rt/5
· \mov Rval, Rt lsb··· [noparse][[/noparse]same routine on each input]
· If Rval < Rmin then
·Rmin=Rval
· endif
· If Rval>RMax then
·RMax=Rval
· endif
· RAvg=RMax+RMin
· Ravg=Ravg/2
· Lf = Lf/5
· \mov Lval, Lf lsb
· If Lval < Lmin then
·Lmin= Lval
· endif
· If Lval>LMax then
·LMax= Lval
· endif
· LAvg=LMax+LMin
· lAvg=Lavg/2
·· return

Comments

  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-08-12 00:41
    Put your sensor values into arrays to free up bank 0 (global) RAM space. And since you're using five samples, you can prevent rollover by dividing each sample by five and then accumulating -- the result will be very close to doing the other way and you can use all bytes.
  • BeanBean Posts: 8,129
    edited 2007-08-12 13:43
    Jerry,
    · A couple comments. You can just use "CVal = Ctr_LSB" without resorting to the assembly instruction "\MOV CVal,Ctr_LSB" .

    · The FOR loop is going from 0 to 5, that is 6 loops not five. So you should be dividing by 6 not 5. Actually it would generate less code if you could take 4 or 8 samples, then you just shift the value to do the divide.

    · Like Jon said, you arrays (even if just an array of 1 element). Arrays are stored in a different memory area and there is lots of room for arrays.
    In most cases you can use an array of 1 element with just the array name.

    myValue VAR BYTE(1)
    myValue = 100

    · When you post code, it's best to post the entire program. Even if it won't compile, then helpers can make modification and post back without having to guess and with less work.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Teacher: What is the difference between ignorance and apathy ?
    Student: I don't know and I don't care
    Teacher: Correct !
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    www.hittconsulting.com
    ·
  • jmokiejmokie Posts: 13
    edited 2007-08-12 22:21
    Thanks Johnnymac & Bean

    Being a novice SXB programmer I had stayed away from arrays, but I took a look and tried to do as you said. I finally got a test program to compile, but I can't seem to get values to show up in my WATCH list. Only the Ctrraw, the input from the a/d, shows up.

    Can the watch directive display array variables?
    My entire code is posted below.
    Jerry

    ' =========================================================================
    '
    ' File...... arraytest2.sxb
    ' Purpose... test sensor input array
    ' Author....
    ' E-mail....
    ' Started...
    ' Updated...
    '
    ' =========================================================================


    '
    ' Program Description
    '


    '
    ' Device Settings
    '

    DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
    FREQ 4_000_000


    '
    ' IO Pins
    '

    InCPin PIN Rb.2 INPUT CMOS
    OutCPin PIN Rb.3 OUTPUT


    '
    ' Constants
    '


    '
    ' Variables
    '
    timer var byte
    ctravg var word

    '
    Ctraray var byte(4) 'Array of variables for center sensor
    ctrval var ctraray(0) 'variable to hold the avg of 5 ctr readings
    ctrmin var ctraray(1) 'minimum value of ctrval
    ctrmax var ctraray(2) 'maximum value of ctrval
    ctrraw var ctraray(3) 'raw analog value from a/d

    watch ctrraw
    watch ctravg
    watch ctrmin
    watch ctrmax
    watch Ctrval


    '
    INTERRUPT
    '

    ISR_Start:
    ' ISR code here

    ISR_Exit:
    RETURNINT ' {cycles}


    ' =========================================================================
    PROGRAM Start
    ' =========================================================================

    Pgm_ID:
    DATA "SX/B Template", 0


    '
    ' Subroutines / Jump Table
    '


    '
    ' Program Code
    '

    Start:
    TRIS_C = %0000000 'Set C to outputs


    Main:
    Gosub ADCINPUT
    break

    GOTO Main


    '
    ' Page 1 Code
    '

    Page_1:
    ADDRESS $200

    P1_Start:
    GOTO P1_Start ' error if Pg0 overruns Pg1


    '
    ' Page 2 Code
    '

    Page_2:
    ADDRESS $400
    ADCINPUT:
    timer = 0
    Put ctrval, 0 'reset ctrval to zero each time you get ADC inputs

    for timer = 1 to 4
    ANALOGIN InCPin, OutCPin, Ctrraw, 2

    ctrraw=ctrraw/5 'divive ctrraw by 5
    Ctrval= Ctrval+Ctrraw 'accumulate ctrraw

    next
    '
    calculate min, max, avg of ctr input
    If Ctrval<Ctrmin then
    Put ctrval,ctrmin
    endif
    If Ctrval>ctrmax then
    Put ctrval, ctrmax
    endif
    ctravg=ctrmax+ctrmin
    ctravg=ctravg/2


    return

    P2_Start:
    GOTO P2_Start ' error if Pg1 overruns Pg2


    '
    ' Page 3 Code
    '

    'Page_3:
    'ADDRESS $600

    'P3_Start:
    ' GOTO P3_Start ' error if Pg3 overruns Pg4
  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-08-13 00:23
    I think you're working too hard. You should start with a newer template and use 1.51.03 features; things like declared subroutines.

    And if your goal is to read a sensor several times and get the average reading, you can do it like this:

    SUB ADC_IN
      ctrAvg = 0
      FOR idx = 1 TO 4
        ANALOGIN InCPin, OutCPin, ctrRaw, 2         ' get raw sensor value
        ctrRaw = ctrRaw >> 2                        ' divide by 4
        ctrAvg = ctrAvg + ctrRaw
      NEXT
      ENDSUB
    



    The code above basically works like this routine, but without the extra accumulator variable:

    SUB ADC_IN
      ctrAcc = 0                                    ' clear accumulator
      FOR idx = 1 TO 4
        ANALOGIN InCPin, OutCPin, ctrRaw, 2         ' get raw sensor value
        ctrAcc = ctrAcc + ctrRaw
      NEXT
      ctrAvg = ctrAcc / 4
      ENDSUB
    

    Post Edited (JonnyMac) : 8/13/2007 12:29:46 AM GMT
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-08-15 16:13
    As JonnyMac has indicated, make sure you are using the latest version of the compiler and also the updated help file.

    For help with watch variable syntax go to Help | Watch Format Help.

    You will probably want to use a format similar to “WATCH ctrraw, 8, UDEC” for your watch statements. You can watch array variables if you tell the debugger how many bit values to include and what display format to use.

    Continue to post further questions as they arise.

    - Sparks
  • jmokiejmokie Posts: 13
    edited 2007-08-18 21:29
    Thanks Johnny Mac & Sparks R fun

    Johnny's method of calculating the avg is great, works good

    I am using the latest rev. of the SXB compiler, and the latest helpfile. I haven't been able to find a more recent copy of a template than the one I have.

    I think with your help the avg & variable problem is solved.
    Thanks Again

    Now on to the PID!
    Jerry
Sign In or Register to comment.