Servo32V7: Multiple servo move synchronized
KurtE
Posts: 4
Hi,
I am in the process of porting some code for some of my robots to the propeller. So far I do have my Hexapod walking and the like, but I am still using an external servo controller board to actually drive the 18 servos. I have organized my code, such that the servo driving stuff is in its own class (.spin file) and am working on a version to have the propeller do the servo driving itself.
So I started off with Servo32V7 and my first experiments were to figure out how the ramp works. My goal is to issue a set of servo calls for each of these 18 servos and have them all complete this at the same time, even though they are all moving a different amount. My understanding from reading the code and experiments is that the delay specified in the set ramp call is the time it would take to move a delta of 2000us. So to make this work the way that I want it to work, I would need to calculate the delta for each of the servos and than generate a delay as a ratio of the delta to 2000. To do this implies that I need to know where the servos are. I could keep a set of values myself, but why duplicate the memory space. Also at times I would like to stop a servo moving, such as if I have a sensor and detect that the foot hit the ground.
So I started mucking a little with the servo32v7 code. So far I have added a couple of simple functions:
PUB Get(Pin)
'' Added by KurtEck - Ability to Retrieve the current pulse width for a servo
return ServoData[Pin]
PUB RampDone(Pin)
'' Added by KurtEck - Ability to check to see if a ramp operation is done or not...
return ServoTarget[Pin] == ServoData[Pin]
PUB RampAbort(Pin)
'' Added by KurtEck - Ability to tell the ramp system to stop updating the location
'' May be needed when we detect that a leg has made contact.
ServoTarget[Pin] := ServoData[Pin]
In my code that will commit the move, I do the following:
pub Commit (SSCTime) | LegIndex
' I believe that the timing in this process is in 100th of a second
' But the ramping stuff is sortof screwy, The timing is based on
' moving a full 2000us so we need to scale each of them.
SSCTime *= 200 ' prescale here for all of the calculations
repeat LegIndex from 0 to 5
SDRIVER.SetRamp(cCoxaPin[LegIndex], awCoxaSSCV[LegIndex], SSCTime/||(awCoxaSSCV[LegIndex]-SDRIVER.Get(cCoxaPin[LegIndex])))
SDRIVER.SetRamp(cFemurPin[LegIndex], awFemurSSCV[LegIndex], SSCTime/||(awFemurSSCV[LegIndex]-SDRIVER.Get(cFemurPin[LegIndex])))
SDRIVER.SetRamp(cTibiaPin[LegIndex], awTibiaSSCV[LegIndex], SSCTime/||(awTibiaSSCV[LegIndex]-SDRIVER.Get(cTibiaPin[LegIndex])))
I have not started to debug this part yet as I need to tear apart the robot to get to all 18 servo wires... But hopefully in the next few days.
My question is: Is it advised to make changes like this to these OBEX library files, or should I try to find a different way, like writing my own.
As a follow on to this, if I get this to work reasonably, one of the next steps would be to somehow emulate the servo zero offsets that are part of my current servo controller. That is, you wish to have the code output a standard pulse width like 1500 but on some servos this may turn out to be 1498 or 1526, so you can either change the code on each robot or, maybe store away a delta in the EEPROM and use that. What I will than have to decide is where to put this. Probably the best place would be in the servo driver itself. Would need to update the Init code, the Set, SetRamp (and if I leave it the Get) to take this into effect.
Thoughts?
Kurt
I am in the process of porting some code for some of my robots to the propeller. So far I do have my Hexapod walking and the like, but I am still using an external servo controller board to actually drive the 18 servos. I have organized my code, such that the servo driving stuff is in its own class (.spin file) and am working on a version to have the propeller do the servo driving itself.
So I started off with Servo32V7 and my first experiments were to figure out how the ramp works. My goal is to issue a set of servo calls for each of these 18 servos and have them all complete this at the same time, even though they are all moving a different amount. My understanding from reading the code and experiments is that the delay specified in the set ramp call is the time it would take to move a delta of 2000us. So to make this work the way that I want it to work, I would need to calculate the delta for each of the servos and than generate a delay as a ratio of the delta to 2000. To do this implies that I need to know where the servos are. I could keep a set of values myself, but why duplicate the memory space. Also at times I would like to stop a servo moving, such as if I have a sensor and detect that the foot hit the ground.
So I started mucking a little with the servo32v7 code. So far I have added a couple of simple functions:
PUB Get(Pin)
'' Added by KurtEck - Ability to Retrieve the current pulse width for a servo
return ServoData[Pin]
PUB RampDone(Pin)
'' Added by KurtEck - Ability to check to see if a ramp operation is done or not...
return ServoTarget[Pin] == ServoData[Pin]
PUB RampAbort(Pin)
'' Added by KurtEck - Ability to tell the ramp system to stop updating the location
'' May be needed when we detect that a leg has made contact.
ServoTarget[Pin] := ServoData[Pin]
In my code that will commit the move, I do the following:
pub Commit (SSCTime) | LegIndex
' I believe that the timing in this process is in 100th of a second
' But the ramping stuff is sortof screwy, The timing is based on
' moving a full 2000us so we need to scale each of them.
SSCTime *= 200 ' prescale here for all of the calculations
repeat LegIndex from 0 to 5
SDRIVER.SetRamp(cCoxaPin[LegIndex], awCoxaSSCV[LegIndex], SSCTime/||(awCoxaSSCV[LegIndex]-SDRIVER.Get(cCoxaPin[LegIndex])))
SDRIVER.SetRamp(cFemurPin[LegIndex], awFemurSSCV[LegIndex], SSCTime/||(awFemurSSCV[LegIndex]-SDRIVER.Get(cFemurPin[LegIndex])))
SDRIVER.SetRamp(cTibiaPin[LegIndex], awTibiaSSCV[LegIndex], SSCTime/||(awTibiaSSCV[LegIndex]-SDRIVER.Get(cTibiaPin[LegIndex])))
I have not started to debug this part yet as I need to tear apart the robot to get to all 18 servo wires... But hopefully in the next few days.
My question is: Is it advised to make changes like this to these OBEX library files, or should I try to find a different way, like writing my own.
As a follow on to this, if I get this to work reasonably, one of the next steps would be to somehow emulate the servo zero offsets that are part of my current servo controller. That is, you wish to have the code output a standard pulse width like 1500 but on some servos this may turn out to be 1498 or 1526, so you can either change the code on each robot or, maybe store away a delta in the EEPROM and use that. What I will than have to decide is where to put this. Probably the best place would be in the servo driver itself. Would need to update the Init code, the Set, SetRamp (and if I leave it the Get) to take this into effect.
Thoughts?
Kurt