Servo deadband code
jcferguson
Posts: 86
I am trying to streamline my dead band code (for continuous rotation servo - so it won't creep) for faster operation - I would like to find a better way of doing the following:
I need to first check to see if the pot value for the servo is in the dead range - say my servo center is 750 and deadvalue is 50. I want the servo to stay still from 700 to 800. To do this I just check for this range and then reset the servo output value to center so that there is no movement on the servo.
When the servo value gets to the edges of this dead range though - like a servo value of 802, there would be a jump from the re-setting the center range (750) to the tracking the actual value range (802) - to correct this I need set the servo closer to center by deadbandvalue units. This means that the servo actually goes from 750 to 752 when the servo value changes from 800 to 802.
this is the "elseif" part of the code below.
IF ABS (servodrivevalue - servocentervalue) <= deadbandval THEN 'check to see if servodrivevalue is in deadband range
servodrivevalue = servocentervalue 'if it is, set it to center value so it won't creep
ElSEIF servodrivevalue > servocentervalue THEN 'if servo is outside dead range then subtract deadvalue so
servodrivevalue = servodrivevalue - deadbandval 'there won't be a jump in servo drive
ElSE:servodrivevalue = servodrivevalue + deadbandval
ENDIF
My question: is there a better way of doing the second half?
basically I just want to take a variable that may be higher or lower than a constant and make it closer in value to that constant... is there a trick for this or should I just check like I do above?
Thanks! !
Carlos
Post Edited (jcferguson) : 3/17/2007 6:37:18 PM GMT
I need to first check to see if the pot value for the servo is in the dead range - say my servo center is 750 and deadvalue is 50. I want the servo to stay still from 700 to 800. To do this I just check for this range and then reset the servo output value to center so that there is no movement on the servo.
When the servo value gets to the edges of this dead range though - like a servo value of 802, there would be a jump from the re-setting the center range (750) to the tracking the actual value range (802) - to correct this I need set the servo closer to center by deadbandvalue units. This means that the servo actually goes from 750 to 752 when the servo value changes from 800 to 802.
this is the "elseif" part of the code below.
IF ABS (servodrivevalue - servocentervalue) <= deadbandval THEN 'check to see if servodrivevalue is in deadband range
servodrivevalue = servocentervalue 'if it is, set it to center value so it won't creep
ElSEIF servodrivevalue > servocentervalue THEN 'if servo is outside dead range then subtract deadvalue so
servodrivevalue = servodrivevalue - deadbandval 'there won't be a jump in servo drive
ElSE:servodrivevalue = servodrivevalue + deadbandval
ENDIF
My question: is there a better way of doing the second half?
basically I just want to take a variable that may be higher or lower than a constant and make it closer in value to that constant... is there a trick for this or should I just check like I do above?
Thanks! !
Carlos
Post Edited (jcferguson) : 3/17/2007 6:37:18 PM GMT
Comments
can you explain what you mean by dead band code?
Do you intend to create artifically a dead band of 50 in your example so that a program output to the servo
can vary within the dead band before the servo starts moving ?
I use parallax PM servos and they have no dead band at all.
One is "still" at 759, the other at 760 and that's it! Even changing the value by one results in rotation of the motor.
I can see on second reading that my post above is pretty opaque!
thanks,
Carlos
I use the SELECT - CASE construction when doing joystick work. It may not be too much shorter, but it is easy to troubleshoot and runs quickly.
It does a good job both when directly reading the joystick or over RF.
Here is a brief piece of code from the research boat I was involved with. This one used RF so it used PULSIN, but it works the same with RCTIME.
Notice how the deadbands are adjusted in the CASE statements and that several (ch3 and ch4) channels of stick can be interlaced.
Note that this isn't all the code, it carries on for a couple hundred lines in order to control two drive motors F-R and also steer by differential speed control.
Regards,
Tom
mainLOOP:
PULSIN 8,0,ch1 ' winch 1 control stick
PULSIN 9,0,ch2 ' winch 2 control stick
PULSIN 10,0,ch3 ' forward/reverse main motors;including trolling motor
PULSIN 11,0,ch4 ' left/right on fans; y-connection to steering servo
'DEBUG DEC3 ch1," ",DEC3 ch2," ",DEC3 ch3," ",DEC3 ch4," ",DEC1 IN12,HOME
GOSUB motspd
'PAUSE 250
GOTO mainLOOP
motspd: 'determine whether direction is forward or reverse
SELECT ch3
CASE < 300
GOTO nolink
CASE 700 TO 800 ' check F/R neutral position
GOSUB allstop
GOSUB runwin
'GOSUB turninplace
' ######################## Low Speed Forward ########################
CASE 825 TO 875 ' lowest forward speed
IF IN12=0 THEN ' check to see if trolling servo selected
GOSUB trolslofwd
GOTO bypass1
ENDIF
SELECT ch4
CASE 700 TO 800 ' steering centred,both motors slow fwd
x=0
y=0
u=0
v=0
IF lmotstat = 1 THEN 'see if left mot was running in rev
GOSUB timr3
IF z<del3 THEN
GOSUB bak2fwdlft
GOTO decel2
ELSEIF z > del3 THEN
lmotstat=0 ' reset left mot rev status
ENDIF
ENDIF
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tom Sisk
http://www.siskconsult.com
·
The creep occurs when the "center point" value changes. You need to detect when this change occurs, and then you need to determine the new center point. The deadzone is only telling you over what range of values you do not wish to move the servo, but it will not tell you where "center" is (i.e., has move to)·at the current time.
The trick is to figure out how to detect the creep (when does it occur, and where is the new center?).
PAR
PAR - right, I am just making a big blank area in the middle of the joystick range so that when temperature shift happens it will be encompassed by the dead zone... it would be better to just find the new center point when the temperature changes and then need no deadband at all - I have been thinking of how to do this - the joysticks are part of an interactive sculpture that is only used some of the time. Maybe I can identify through code when the joystick has not been touched for a long enough period and re-set the center to this value?
something like:
check joystick
if joystick is active, send data to servos, reset inactivity counter
if joystick isn't active add one to inactivity counter
check counter - if it is high enough then reset center value
if not high enough, go back to check joystick
Does that seem like what you were thinking? I could probably get rid of all my deadband code so that there would be a net savings in time to execute. I was trying a while ago to find a way of setting up another rc circuit to compare and reset centers accordingly but never really got it working in a good fashion...
Thanks,
Carlos
How are they connected (circuit)?· Are you suggesting that you re-"center" (bias) the joystick pots rather than re-centering the servos?
You will still have to determine whether/how much·the servo's center has drifted, regardless of whether you adjust the servo or the joystick pot to stop the creep.
When you state "...joystick is active...", what do you mean? Does the joystick move on its own (e.g., it is connected to a servo that moves (controls movement of)·the joystick), or are people moving the joystick? (This question is related to the earlier one about how your circuit components are wired to each other.)
PAR
Does that make sense? Are you saying that the value that the servo centers to is changing as well? I hadn't thought of that. I was thinking I would just check my rctime values when the joysticks aren't being touched and reset the scaling so that the center value that is pulsout-ed to the servo stays the same. Any other solution?
Thanks,
Carlos
In the case of servo drift, you'd have to know where the "new" center is (i.e., where the old center drifted to), in order to correct for it (whether that is by programmatically resetting the "center" point value of the servo, or by physically resetting the servo's pot; if you go with the program reset, you'll have to know how much to reset it by.
In the case of joystick drift (from its "home" or center position), and assuming that the servo's center hasn't drifted also, you could use your "deadband" approach, or you could figure out the new (drifted-to) center/home on the joystick and correct programmatically for that bias (i.e., change the value of "joystick-center").
It seems to me that in either case, you need to know first whether your servo is moving when it isn't supposed to be moving so that you can bias your calculated "center" position accordingly. Once you know how your servo is behaving ("creeping", not creeping, given a particular "centering" value), you can do away with (or significantly narrow) your deadband and deal directly with a current, correct center value.
PAR