Calculation with SX28
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
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
· 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
·
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
And if your goal is to read a sensor several times and get the average reading, you can do it like this:
The code above basically works like this routine, but without the extra accumulator variable:
Post Edited (JonnyMac) : 8/13/2007 12:29:46 AM GMT
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
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