SSC-32 syntax question

Hi again!

I’ve hit a bit of a speedbump. I had my tracked rover and arm working very well using a botboard 2 and PS2 control, running the standard rover_v1.2.
The next step involved slapping an SSC-32 on there. All wiring seems correct, I’ve got a power led that’s on normally and blinking fast when communicating.
I’ve only got the base servo connected so far, just to see if I can get it going. If all my servo’s suddenly decide to explode at thesame time, it’d create so much black smoke I wouldn’t be able to find the exit anymore :smiley:

I’ve ran a quick test and I can make the servo move according to the deviation of the PS2 stick using a very simple and crude…

BaseSSC = ((Dualshock(3)) * 2000 / 255 )+500 MIN 500 MAX 2500
serout SSC_OUT,i38400,"#0P",DEC BaseSSC, 13]
serout s_out, i9600, [SDEC BaseSSC,13]

Works like a charm, I figured the SSC needs a range of 500 to 2500.

However, how do I use the more complex values from the rover_v1.2 program? I can’t seem to figure out what’s being sent to the pins on the botboard there:

  ;Drive servos
   hservo [BasePin\		(BasePosition1*stepsperdegree1)/100 + Base_Offset\_mBaseSpeed, | 
           ShoulderPin\	(ShoulderPosition1*stepsperdegree1)/100 + Shoulder_Offset\_mShoulderSpeed, | 
           ElbowPin\	(ElbowPosition1*stepsperdegree1)/100 + Elbow_Offset\_mElbowSpeed, | 
           WristPin\	(WristPosition1*stepsperdegree1)/100 + Wrist_Offset\_mWristSpeed, | 
           GripperPin\	(GripperPosition1*stepsperdegree1)/100 + Gripper_Offset\_mGripperSpeed, | 
           WristRotatepin\(WristRotatePosition1*stepsperdegree1)/100 + WristRotate_Offset\_mWristRotateSpeed] 

This is the original. The range of BasePin appears to be -15842 to 15978 on the base pin. What’s that, and what would be the best way to get it into the SSC-32 syntax? I’m also still clueless on the speed factor (_mBaseSpeed) as the SSC-32 only accepts one global speed setting per group command. Will I need to adjust anything else aswell, such as offsets and the like, or will it all be sorted again as soon as the correct formula for the end command is set? Thanks in advance!

I seem to have gotten them to work to an extent, but I’m still in the dark about all the things I’ve cut out, such as that “stepsperdegree1 con 1666” and the entirety of “WaitForPrevMove” as you can’t use the command “hservoidle” through the SSC32. So what’s that stepsperdegree do, and won’t I need WaitforPrevmove? How about that speed limit? A bit clueless, does it show?

Here’s what is doing the trick:

; 	Drive servos Blocked, SSC-32 is installed
;   hservo [BasePin\		(BasePosition1*stepsperdegree1)/100 + Base_Offset\_mBaseSpeed, | 
;           ShoulderPin\	(ShoulderPosition1*stepsperdegree1)/100 + Shoulder_Offset\_mShoulderSpeed, | 
;           ElbowPin\	(ElbowPosition1*stepsperdegree1)/100 + Elbow_Offset\_mElbowSpeed, | 
;           WristPin\	(WristPosition1*stepsperdegree1)/100 + Wrist_Offset\_mWristSpeed, | 
;           GripperPin\	(GripperPosition1*stepsperdegree1)/100 + Gripper_Offset\_mGripperSpeed, | 
;           WristRotatepin\(WristRotatePosition1*stepsperdegree1)/100 + WristRotate_Offset\_mWristRotateSpeed] 


;SSC outputs

BaseSSC var sword
ShoulderSSC var sword
ElbowSSC var sword
WristSSC var sword
GripperSSC var sword
WristRotateSSC var sword

BaseSSC = BasePosition1 + 1500
ShoulderSSC = ShoulderPosition1 + 1500
ElbowSSC = ElbowPosition1 + 1500
WristSSC = WristPosition1 + 1500
GripperSSC = GripperPosition1 + 1500
WristRotateSSC = WristRotatePosition1 + 1500


serout SSC_OUT,i38400,"#0P",DEC BaseSSC, "#1P",DEC ShoulderSSC, "#2P",DEC ElbowSSC, "#3P",DEC WristSSC, "#4P",DEC GripperSSC, "#5P",DEC WristRotateSSC, 13]

So yes, it’s working, but I’d love to know why it is without all those extras, and how I SHOULD’ve done it :smiley:

I will try to explain a little what the differences are.

The HSERVO system uses a different value range/scale for the servos than the SSC-32. That is on the SSC-32 you tell it the pulse width in the number of microseconds where 1500 is the center point.

With HSERVO you tell it in the pulse width in CPU clock cycles. So the values are different if you are running on a BAP28 (16mhz) than they are on an Arc32 (20mhz). Also he set it such that 0 was the center point.

I described more about this up on the thread: viewtopic.php?f=4&t=3224&start=17
I believe the thread showed how to convert from one to the other ranges.

The steps per degree 1 variable, was a value that worked for most analog servos or about 166.6 steps per degree. As we were avoiding floating point, we put them in 10ths of degree. As the positions were also in 10ths of a degree when we multiplied the two we needed to divide by 100 to get the actual value.

The other differences have to do with timings of these commands. That is in the HSERVO version we took the desired time to complete the command and had to convert it to how many HSERVO units should the command update per 20ms servo cycle, which he had to calculate for each servo. With the SSC-32 we can simply pass the desired time off on the group move command with the “T” argument.

As you mentioned, on the SSC-32, when we wish to wait for the previous command to wait, we simply do the HSERVOIDLE command for all of the servos… On the SSC-32 we have a couple of options:
a) We hook up the SSC-32 such that we have bidirectional communications and use the Q command (lynxmotion.com/images/html/b … tm#qmovest)
b) Set up a timer and right after we issue a command to move, we get the current time and then when we are ready to issue the next command we loop until the timer tells us enough time as has elapsed and then we issue the next command.

I have used both methods. For the Hex Software (phoenix) we went with the timing version.

Hope I answered some of the questions.
Kurt

Kurte,

I’m very grateful for your explanation, it’s been most helpful and I’ve learnt a great deal on how these things work.

So to wrap things up on conversion, I’ve done this before I’ve read your explanation:
Instead of the original
BasePosition1*stepsperdegree1/100 + Base_Offset
I now do
BasePosition1 + 1500 + Base_Offset
and that seems to do the trick, plus allowing most other values to remain thesame.

As for the timing, I’m still a bit confused. I think my confusion comes from my lack of knowledge of the basic principles of servo’s and the program in general.
After your explanation, some study of the thread you linked and looking deeper into the program, I’ve gathered enough courage to start fiddling around.

I am now doing this: (you might have to open up rover_v1.2 to follow my ranting)

Movement is handled my the “GOTO Movement” subprogram. There, the “MAXSPEED” value is used to calculate the final individual maximum speeds for every servo controlled by the botboard.

For the SSC conversion, I simply took the MAXSPEED value, processed all the values to match time value of the SSC ( /600 * 1000) and fed that straight into the SSC output. So that gives us:

serout SSC_OUT,i38400,"#0P",DEC BaseSSC, "#1P",DEC ShoulderSSC, "#2P",DEC ElbowSSC, "#3P",DEC WristSSC, "#4P",DEC GripperSSC, "#5P",DEC WristRotateSSC, "T",DEC MaxSpeed, 13]

So when hitting the start button (and thus doing an INIT) the arm moves to init position in one second as the MAXSPEED value is 1000. (600 / 600 *1000)
When moving normally, the MAXSPEED value is now (50 /600 * 1000) or 83, or 50ms. (I think)
So the servos will try to do the full move in 50ms, which is thesame as it was using the botboard, I think.

This seems to be doing the trick, is there any reason why I can’t do it like this? What is the advantage of using the (b) timer you mentioned?

Thanks for the feedback, I’m absolutely loving all of this to bits :smiley:

Glad you are having fun!

Couple of things: (50 /600 * 1000): Could easily = 0. That is since / * are same priority operators, the compiler could easily choose to go left to right. So 50/600 = 0 * 1000 = 0

There are many different was to do things. If you simply want your servos to move as quick as possible to new position, then you don’t need anything additional. But to keep the discussion simple suppose you had one servo that you wish to move back and forth from 750 to 2250 with each move taking 1 second. At the simplest form, the code may look like:

loop:
    serout SSC_OUT,i38400,"#0P750T1000", 13]
    serout SSC_OUT,i38400,"#0P2250T1000", 13]
    goto loop

Problem, the SSC-32 when it receives a new command will immediately start executing it on the mentioned servos, so instead of moving the whole range it will probably just wiggle a little. To do full range you could do something like:

loop:
    serout SSC_OUT,i38400,"#0P750T1000", 13]
    pause 1000
    serout SSC_OUT,i38400,"#0P2250T1000", 13]
    pause 1000
    goto loop

For something this simple this would probably be close enough. You may find a slight delay at both ends as there is some overhead in basic, plus it takes time to send out the next command string. In a simple case like the above could probably fix by slightly decreasing the pause. But if your code is more complicated and checks joysticks and … then you may have less predictable pause of the servos

To solve this you can use the methods I mentioned in the previous post. The A) method is to ask the SSC-32 if it has completed the previous command or not. You simply loop waiting until it says it is done. Works well, but gives you an inherent delay between commands as it takes a little time for SSC to respond and for the serial data to be sent. Or you can do B) which simply keeps timer and computes how much time is left on previous command and either pauses, loops or… until the right time.

Kurt

Kurt, Please forgive me for interloping on your conversation, but you have me mightily confused. :confused: Not difficult. :blush:

  1. Why does 50/600 = 0 instead of 50/600 = .08333? Does the compiler reject fractional numbers?
  2. If so, Why does the direction the compiler chooses matter in this case since 50/600,000 would still equal 0 if fractions are rejected?

It’s been 55 years since I dealt with mathematical priorities of operators, the single transistor radios we built were huge because all components were discrete, micro circuits were still in the future, and compilers??? :unamused:

Thanks for indulging me. :slight_smile:

We are doing integer math here so only numbers are 0, 1, 2, 3… You can use floating point as well, but lots slower…

Yep my school years are a few years back as well…

I use () a lot to make sure there is no doubt. Also depending on platform have to be careful about overflows, in case of BM basic all calculations are done in 32 bit math. But when using C for example, it often defaults to the size of one of the used variables, so may need to cast to larger sizes. But that is a different subject…

Kurt