Too many variables???
Ghiamonster
Posts: 8
Using PBasic 2.5 with a BS2 (Boe Bot kit). Trying to run the following program and get 'Out of Variable Space' message!
From what I understand of the chipset's specs, there's 128 bytes of variable space? Not counting the CON definitions
(and not knowing how much space the PINs take up, there's only 58 bytes taken up by the WORD and WORD Arrays (2 bytes per WORD, correct?).
What am I missing??
' Servo Choreography - Test4Choro2.bs2
' Move 4 servos at the same time, different directions
'
' {$STAMP BS2}
' {$PBASIC 2.5}
S1················ PIN············ 12················· ' First Servo
S2················ PIN············ 13················· ' Second Servo
S3················ PIN············ 14················· ' Third Servo
S4················ PIN············ 15················· ' Fourth Servo
ServCenters······· VAR·········· Word(4)
ServLeftOff········ VAR·········· Word(4)
ServRightOff······· VAR·········· Word(4)
CurrPos············· VAR·········· Word(4)
ServTarget········ VAR·········· Word(4)
Srvs················· VAR·········· Word(4)
ServSpeed·········VAR·········· Byte(4)
BtwnPulses········ CON·········· 20·················· ' ms between servo pulses
counter··········· VAR·········· Word·················· ' Loop index
ServCenters(1)=750
ServCenters(2)=750
ServCenters(3)=750
ServCenters(4)=750
ServRightOff(1)=550
ServRightOff(2)=350
ServRightOff(3)=550
ServRightOff(4)=350
ServLeftOff(1)=450
ServLeftOff(2)=300
ServLeftOff(3)=450
ServLeftOff(4)=300
DEBUG "Centering Servos", CR
GOSUB CenterServos
Srvs(1)=CurrPos(1): Srvs(2)=CurrPos(2): Srvs(3)=CurrPos(3): Srvs(4)=CurrPos(4)
ServTarget(1)=CurrPos(1)-ServRightOff(1)
ServSpeed(1)=5
ServTarget(2)=CurrPos(2)+ServLeftOff(2)
ServSpeed(2)=5
ServTarget(3)=CurrPos(3)-ServRightOff(3)
ServSpeed(3)=5
ServTarget(4)=CurrPos(4)-ServLeftOff(4)
ServSpeed(4)=5
FOR Srvs(1)=Currpos(1) TO ServTarget(1) STEP ServSpeed(1)
·· PULSOUT S1, Srvs(1)
·· Currpos(1)=Srvs(1)
·· IF Srvs(2)<ServTarget(2) THEN
····· PULSOUT S2, Srvs(2)
····· Srvs(2)=Srvs(2)+ServSpeed(2)
····· Currpos(2)=Srvs(2)
·· ENDIF
·· IF Srvs(3)<ServTarget(3) THEN
····· PULSOUT S3, Srvs(3)
····· Srvs(3)=Srvs(3)+ServSpeed(3)
····· Currpos(3)=Srvs(3)
·· ENDIF
·· IF Srvs(4)<ServTarget(4) THEN
····· PULSOUT S4, Srvs(4)
····· Srvs(4)=Srvs(4)+ServSpeed(4)
····· Currpos(4)=Srvs(4)
·· ENDIF
·· PAUSE BtwnPulses
NEXT
END
CenterServos:
·· FOR counter = 1 TO 100
····· PULSOUT S1, ServCenters(1)
····· PULSOUT S2, ServCenters(2)
····· PULSOUT S3, ServCenters(3)
····· PULSOUT S4, ServCenters(4)
····· PAUSE BtwnPulses
·· NEXT
·· CurrPos(1)=ServCenters(1)
·· CurrPos(2)=ServCenters(2)
·· CurrPos(3)=ServCenters(3)
·· CurrPos(4)=ServCenters(4)
·· RETURN
Thanks,
Mike
From what I understand of the chipset's specs, there's 128 bytes of variable space? Not counting the CON definitions
(and not knowing how much space the PINs take up, there's only 58 bytes taken up by the WORD and WORD Arrays (2 bytes per WORD, correct?).
What am I missing??
' Servo Choreography - Test4Choro2.bs2
' Move 4 servos at the same time, different directions
'
' {$STAMP BS2}
' {$PBASIC 2.5}
S1················ PIN············ 12················· ' First Servo
S2················ PIN············ 13················· ' Second Servo
S3················ PIN············ 14················· ' Third Servo
S4················ PIN············ 15················· ' Fourth Servo
ServCenters······· VAR·········· Word(4)
ServLeftOff········ VAR·········· Word(4)
ServRightOff······· VAR·········· Word(4)
CurrPos············· VAR·········· Word(4)
ServTarget········ VAR·········· Word(4)
Srvs················· VAR·········· Word(4)
ServSpeed·········VAR·········· Byte(4)
BtwnPulses········ CON·········· 20·················· ' ms between servo pulses
counter··········· VAR·········· Word·················· ' Loop index
ServCenters(1)=750
ServCenters(2)=750
ServCenters(3)=750
ServCenters(4)=750
ServRightOff(1)=550
ServRightOff(2)=350
ServRightOff(3)=550
ServRightOff(4)=350
ServLeftOff(1)=450
ServLeftOff(2)=300
ServLeftOff(3)=450
ServLeftOff(4)=300
DEBUG "Centering Servos", CR
GOSUB CenterServos
Srvs(1)=CurrPos(1): Srvs(2)=CurrPos(2): Srvs(3)=CurrPos(3): Srvs(4)=CurrPos(4)
ServTarget(1)=CurrPos(1)-ServRightOff(1)
ServSpeed(1)=5
ServTarget(2)=CurrPos(2)+ServLeftOff(2)
ServSpeed(2)=5
ServTarget(3)=CurrPos(3)-ServRightOff(3)
ServSpeed(3)=5
ServTarget(4)=CurrPos(4)-ServLeftOff(4)
ServSpeed(4)=5
FOR Srvs(1)=Currpos(1) TO ServTarget(1) STEP ServSpeed(1)
·· PULSOUT S1, Srvs(1)
·· Currpos(1)=Srvs(1)
·· IF Srvs(2)<ServTarget(2) THEN
····· PULSOUT S2, Srvs(2)
····· Srvs(2)=Srvs(2)+ServSpeed(2)
····· Currpos(2)=Srvs(2)
·· ENDIF
·· IF Srvs(3)<ServTarget(3) THEN
····· PULSOUT S3, Srvs(3)
····· Srvs(3)=Srvs(3)+ServSpeed(3)
····· Currpos(3)=Srvs(3)
·· ENDIF
·· IF Srvs(4)<ServTarget(4) THEN
····· PULSOUT S4, Srvs(4)
····· Srvs(4)=Srvs(4)+ServSpeed(4)
····· Currpos(4)=Srvs(4)
·· ENDIF
·· PAUSE BtwnPulses
NEXT
END
CenterServos:
·· FOR counter = 1 TO 100
····· PULSOUT S1, ServCenters(1)
····· PULSOUT S2, ServCenters(2)
····· PULSOUT S3, ServCenters(3)
····· PULSOUT S4, ServCenters(4)
····· PAUSE BtwnPulses
·· NEXT
·· CurrPos(1)=ServCenters(1)
·· CurrPos(2)=ServCenters(2)
·· CurrPos(3)=ServCenters(3)
·· CurrPos(4)=ServCenters(4)
·· RETURN
Thanks,
Mike
Comments
The I/O pins are separate. They're accessible as three additional words (and bytes and bits) called INS / OUTS / DIRS.
You will have to find some way to get by with fewer variables.
Anyone know when the servo·controller board will be available for the Propeller? It looks like there USED to be one for the BS2
but it's discontinued...
Why do you use Words on static things like Servcenters?
Why use Word on a counter that counts only to 100?
Go through your program and you will find several examples of wasting variable spaces.
·http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/servo/List/0/SortField/4/ProductID/595/Default.aspx
Jim
so 250 would be 750, 249 would be 747 so you would lose some resolution but in just the 4 arrays you would save 12 bytes.
Not sure if 747 to 750 on a servo would be close enough though.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
At the time I wasn't sure if the CON wasn't taking up more space than a WORD would. Now that I understand that CON
doesn't take up Register space, I can change those back.
The Propeller would be for more complex tasks that I know are coming up. Given the limitations I've already run into here
with the BS2, I think it may be wise to consider it.
Metron, that's a good idea (at least to get me through this exercise)! I don't need precision as much as trying out logic.
I've made a 4 servo "arm" that I'm trying to articulate off the BOE. The code I posted is testing moving all the servos at
different rates and directions all at the same time. I'm using 4 simply because that's all the servo ports I've got (without
tearing apart cables and breadboarding. That's the reasoning behind the query for the servo controller.
Hover1 - that Propeller Servo Controller can be driven off the BS2, correct?
Thanks for all your replies! Although the original intent was to make this all variable driven so I can set variables, call the routine,
set them to different values, call the same routine, etc., since that's not happening, I DID get the concept to work with the CONs.
It's possible that using the servo controller will alleviate the necessity for this many variables.
Here's the code - it drives 4 servos, alternating right/left/right/left 90/45/90/45 degrees at about 1/2 speed:
' Servo Choreography - Test4Choro2.bs2
' Move 4 servos at the same time, different directions/rates
'
' {$STAMP BS2}
' {$PBASIC 2.5}
S1················ PIN············ 12················· ' First Servo
S2················ PIN············ 13················· ' Second Servo
S3················ PIN············ 14················· ' Third Servo
S4················ PIN············ 15················· ' Fourth Servo
ServCenter1······· CON·········· 750
ServCenter2······· CON·········· 750
ServCenter3······· CON·········· 750
ServCenter4······· CON·········· 750
ServRightOff1····· CON·········· 550
ServRightOff2····· CON·········· 350
ServRightOff3····· CON·········· 550
ServRightOff4····· CON·········· 350
ServLeftOff1······ CON·········· 450
ServLeftOff2······ CON·········· 300
ServLeftOff3······ CON·········· 450
ServLeftOff4······ CON·········· 300
CurrPos··········· VAR·········· Word(4)
ServTarget········ VAR·········· Word(4)
Srvs·············· VAR·········· Word(4)
ServSpeed········· CON·········· 5
BtwnPulses········ CON·········· 20·················· ' ms between servo pulses
counter··········· VAR·········· Byte·················· ' Loop index
DEBUG "Centering Servos", CR
GOSUB CenterServos
Srvs(1)=CurrPos(1): Srvs(2)=CurrPos(2): Srvs(3)=CurrPos(3): Srvs(4)=CurrPos(4)
ServTarget(1)=CurrPos(1)-ServRightOff1
'ServSpeed(1)=5
ServTarget(2)=CurrPos(2)+ServLeftOff2
'ServSpeed(2)=5
ServTarget(3)=CurrPos(3)-ServRightOff3
'ServSpeed(3)=5
ServTarget(4)=CurrPos(4)+ServLeftOff4
'ServSpeed(4)=5
FOR Srvs(1)=Currpos(1) TO ServTarget(1) STEP ServSpeed
·· PULSOUT S1, Srvs(1)
·· Currpos(1)=Srvs(1)
·· IF Srvs(2)<ServTarget(2) THEN
····· PULSOUT S2, Srvs(2)
····· Srvs(2)=Srvs(2)+ServSpeed
····· Currpos(2)=Srvs(2)
·· ENDIF
·· IF Srvs(3)>ServTarget(3) THEN
····· PULSOUT S3, Srvs(3)
····· Srvs(3)=Srvs(3)-ServSpeed
····· Currpos(3)=Srvs(3)
·· ENDIF
·· IF Srvs(4)<ServTarget(4) THEN
····· PULSOUT S4, Srvs(4)
····· Srvs(4)=Srvs(4)+ServSpeed
····· Currpos(4)=Srvs(4)
·· ENDIF
·· PAUSE BtwnPulses
NEXT
END
CenterServos:
·· FOR counter = 1 TO 100
····· PULSOUT S1, ServCenter1
····· PULSOUT S2, ServCenter2
····· PULSOUT S3, ServCenter3
····· PULSOUT S4, ServCenter4
····· PAUSE BtwnPulses
·· NEXT
·· CurrPos(1)=ServCenter1
·· CurrPos(2)=ServCenter2
·· CurrPos(3)=ServCenter3
·· CurrPos(4)=ServCenter4
·· RETURN
Assume you have a number you need 0 to 1500 (Is that the full rotation of a servo with 750 as the center?)
anyway lets say you need 4 servos and words would be 8 bytes to get full resolution using 0-1500 as your minimum and maximum
If you used 4 bytes so 0-255 range and then define one additional nibble as control bits. Bits 0..3 would represent Plus or minus
You would use if then logic to add or subtract the number or some other logic in the calculation.
Taking the center value of 750, servo1s variable (0-255) could represent adding 250 to 750 or subtracting 250 from 750 by setting or resetting bit 0 in the control mask nibble.
That gives you a range of 750-255 = 495 to 750+255= 1005. Giving you full resolution but a reduced range.
Increasing the range you could multiply the servos Byte (0-255 by a factor of 2 and get 750-(255*2) = 750-510 = 240 minimum up to 750 +510 = 1260 maximum, larger range at 1/2 resolution
Multiply by 3 and you have the same resolution as the original idea but you have added just one bit in a control mask to your overhead. Full range lower resolution.
Think of it this way, you are waisting 5 bits per variable if your range is 0-1500 and you use a word because they are not being used.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
Post Edited (metron9) : 5/8/2010 3:37:50 PM GMT
instead of
ServCenter1······· CON·········· 750
ServCenter2······· CON·········· 750
ServCenter3······· CON·········· 750
ServCenter4······· CON·········· 750
..you can use:
ServCenter CON 750
And change the subroutine to
····· PULSOUT S1, ServCenter
····· PULSOUT S2, ServCenter
····· PULSOUT S3, ServCenter
····· PULSOUT S4, ServCenter
·
The program is just a first pass/concept. My ultimate goal is to have a variable driven compact routine that will
allow me to "choreograph" a homemade "arm" consisting of 4 servos with all servos able to move at the same time with different
rates/directions. So far, the concept looks good.
I'm now running into a POSSIBLE bug that doesn't seem directly related to the program. From all I see, no matter what I do, it
LOOKS like one of the variables is getting corrupted.
I'm using metron9's idea of using numbers below 255 and multiplying to get the servo values I need (thanks!). In this way I
can get the variables I need within the 26 byte limitation.
Here's a code snippet, (first the variable definition):
S1················ PIN·············· 12················· ' First Servo
S2················ PIN·············· 13················· ' Second Servo
S3················ PIN·············· 14················· ' Third Servo
S4················ PIN·············· 15················· ' Fourth Servo
ServCenter········ CON············· 150·················· ' Servo centering constant
OffsetBit········· VAR········· Byte(4)·················· ' Will contain a 0 or 1 for each servo indicating which direction to move
ServOffset········ VAR········· Byte(4)·················· ' Will contain 1-500 to determine how far to move the servo
CurrPos··········· VAR········· Byte(4)·················· ' Servo's current position
ServTarget········ VAR········· Byte(4)·················· ' (Calculated CurrPos(n)+/-ServOffset(n) - plus or minus depending on OffsetBit(n)) Target position of the servo
Srvs·············· VAR········· Byte(4)·················· ' Contains the WORKING version of CurrPos - may be able to remove this and just use CurrPos...
ServSpeed········· VAR········· Byte(4)·················· ' Step factor to use in moving from CurrPos to ServTarget
BtwnPulses········ CON·············· 20·················· ' ms between servo pulses
AddData··········· VAR············ Word·················· ' Used to index through EEPROM
And the code pertaining to my problem:
' The DATA statements below describe the movements of the servos. There are groups of 12, subdivided
' into groups of 3 for each servo, in order from 1-4.
'Positions of the data statements are:
'·· 1··· Direction - 0 or 1, 0=Right, 1=Left
'·· 2··· Pulses - (divided by 5) How far to move the servo from it's CURRENT position
'·· 3··· Speed - How fast to move the servo - 1=slowest
'
Datain_1 DATA 1,100,3,0,100,3,1,100,3,0,100,2,
············· 0,100,1,1,100,2,0,100,5,1,100,1,
············· 0,0,0,0,0,0,0,0,0,0,0,0,0
FREQOUT 4,2000,2000
GOSUB CenterServos
AddData=0
DO
·· Srvs(2)=CurrPos(2)
·· Srvs(3)=CurrPos(3)
·· Srvs(4)=CurrPos(4)
·· 'READ Datain_1 + AddData, OffsetBit(1),ServOffset(1),ServSpeed(1),
·· '························ OffsetBit(2),ServOffset(2),ServSpeed(2),
·· '························ OffsetBit(3),ServOffset(3),ServSpeed(3),
·· '························ OffsetBit(4),ServOffset(4),ServSpeed(4)
·· READ Datain_1 + (AddData· + 0), OffsetBit(1)
·· READ Datain_1 + (AddData· + 1), ServOffset(1)
·· READ Datain_1 + (AddData· + 2), ServSpeed(1)
·· READ Datain_1 + (AddData· + 3), OffsetBit(2)
·· READ Datain_1 + (AddData· + 4), ServOffset(2)
·· READ Datain_1 + (AddData· + 5), ServSpeed(2)
·· READ Datain_1 + (AddData· + 6), OffsetBit(3)
·· READ Datain_1 + (AddData· + 7), ServOffset(3)
·· READ Datain_1 + (AddData· + 8), ServSpeed(3)
·· READ Datain_1 + (AddData· + 9), OffsetBit(4)
·· READ Datain_1 + (AddData· + 10), ServOffset(4)
·· READ Datain_1 + (AddData· + 11), ServSpeed(4)
·· IF ServOffset(1)=0 THEN GOTO Endit
When I run this (see screenshot) and the first READ occurs, it's looking like ServSpeed(4) - the last read - always gets 16. No matter what number is in
the data statement AND no matter where I put the read - I even swapped ServSpeed2 (along with the appropriate index) and ServSpeed(4) STILL
corrupted to 16. It's almost like when I use ALL available variable slots the 26th gets whacky.
Byte is 0-255
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
I don't even get to any calculations. The data (in the case of the first DATA line) for ServSpeed(4) should be 2, reading as 16. All other numbers look good.
Driving me nuts.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
I'll try getting rid of the Word (AddData) and using SRV(1) - it's used only in the DO loop below the READ loop...that'll free up 2 bytes.
BRB
Got it to work, but in a most weird way. Started out to multi-task a variable, but that didn't work out logically. Used Srv(1)
in place of AddDATA thinking it only got used in 1 DO (which it did)...but zeroed it out at the beginning of each READ loop..
then wondered why it kept looping and looping (duh).
So then added AddData back in (my READ Address offset), changing from Word to Byte just to get back 1 byte. I had it this way before and
was getting strange corruption (a different one). It should start with zero, usually would start with some random number. Each
time through the loop it would ALWAYS be somewhere between 12 and 15! Changed it to Word and all was good. I mention this because I thought
it was weird that a variable defined as Byte would do this with a number WELL BELOW 255.
Now, back to the original problem (that pesky 16 in the ServSpeed(4) variable). In the course of scratching my head on all this, I decided to
regroup a couple things in the variable section (being the good little programmer I am) and move the ServSpeed array from under Srvs
to under the ServOffset array (so the group would match the data coming from the READs).
Whan Bam! It works!
I'll have to put a bunch more DEBUG statements in to see what's being corrupted now because I'm sure SOMETHING's still corrupting.
Just don't know what...yet
I've attached the full program along with a screenshot of the memory map in case you want to take a look.
Thanks for your assistance!!!