SSC-32 fast binary communication test firmware

I am playing around with the switches on my CHR-3 and I was wondering if it would make sense to add a selective binary stop servo command, that is very much like the selective query command. That is if I have my hex robot walking and one of the legs steps on something, I may wish to stop that leg, not necessarily all of the legs.

I am not sure if I will need it in the end, I am going to try a couple of approaches.

  1. Stop that leg, do a query for the servos on that leg and maybe make a few adjustments… Or just leave it stopped.
  2. Guess where I think the leg should be and issue a new command for those servos to go there.

Kurt

Not sure about the "binary’ command concept, but according to the below, you already have the individual leg stop capability. If one was stepping three legs at once, when the legs are given a “down” command the three switches could be individually monitored for contact and individually stopped when contact is detected. If “canned” group steps are used, then some provision would be needed to not start monitoring the switches for contact until the switches are known to be off the ground in the start of the step.

STOP 0-31 Immediately stops the specified servo at its current position. A space is optional before the servo number. STOP0
STOP 31

If the servo is part of a timed move, the other servos will continue moving and a query command will indicate that the move continues until the total time for the original move has elapsed. This is true even if all of the servos in the original move are stopped.

Thanks Zoomkat,

I knew about the stop command. I know that he also added that if you simply do stop it will stop all servos or you can specify a specific servo as you mentioned.
With the binary mode you can also send a single byte: 0xA2 to stop all of the servos. I was just wondering if there was a binary command equivalent to the Query command where the command is 5 bytes long and you specify which servo you wish to query or potentially stop…

As I mentioned I may not need this, I am playing with the idea of simply telling the servos to go to where I think they should be…

Kurt

The only logical place to tell the servo to go is to the full down position. The assumed physics of the leg movement is that some where between the leg full up position and full down position, the leg will hit something solid and need to be stopped at that point. Could be the top of a rock just below the full up position, or the bottom of a trench just above the full down position.

Hi.
This is my first post som please forgive any mistake or misconceptions re the SSC-32

Is this Binary mode in the current firmware or must it be loaded?
After the Binary commands are send is there a simple way to know if the comands have been processed.

I am working on a project where command sequences are stored in a SD card and then passed to an SCC-32. The command sequences for multiple servos are read every 500ms and
passed to the SSC-32 in a group format.

It would be handy if I could store the commands in a fixed record length format to make it easier the jump forward or back X number of steps, hence my interest in a Binary format where I can fill the record padding with 0X00’s

Many thanks
Dave

The binary firmware is not the default firmware. You must load it. Note: the current binary firmware version does not support offsets. We are making a new release that fixes this. With any version of the firmware it is easy to ask if the SSC-32 is working or finished. From the manual…

Example: "Q "
This will return a “.” if the previous move is complete, or a “+” if it is still in progress.

I’m sorry but the binary firmware was written to speed up the exchange of data between the host and the SSC-32. It has nothing to do with how the data is formatted on the host. I may not be getting something here.

Is there any reason why what you store on the SD card needs to be in the format that is sent to the SSC-32?

If not you could easily setup what you store on the card in any format you wish and simply format it to either the normal or the binary format when you need to. Example: If you need full resolution for each servo, you could store a word (2 bytes) for each servo and if moves take different times, a time value. If you can live with lesser resolution, you could easily store this as one byte for servo. That is if your servo range is from 500-2500, you could store the values as:
(Time - 500)/8. When you are ready to use it you would simply need to do the reverse: Value*8 + 500

Kurt

ASCII and binary commands can be padded at beginning or end with spaces (0x20) or escape characters (0x1B). Space is just padding; escape has the often-beneficial side effect of canceling any command in progress.

In ASCII mode, extra spaces before, after, or within a command are ignored. Thus

"#0P1500T1000<cr>"
"#0 P1500 T1000<cr>"
"#0    P1500   T1000    <cr>"
"           #0P1500T1000<cr>"
"#0P1500T1000<cr>           "

are all the same command.

Mike

Hi.
Ok I’ll explain what I am doing a little better.

I am making a self-contained animatronic system for costumes. Think Underworld werewolf or a Predator costume… but without needing all of the additional operators off screen.
A person will use a program first to move the servo’s arounds then then run a processs that will capture the positions of the servo’s every 500ms (or 250ms depending of experimentaion). The information captures is a sequence number, the servo num, position, and the time to move everything in. This will be set up as a group command.
These sequences are then stored on the SD card.

The SD card is inserted into the costume controller which can do several things.

  1. open up the file and read in the commands
  2. check is there is any special function to do (jump back to previous sequence line in the file)
  3. send the servo processing string to the SSC-32.

Because there will be other things going on like On-Screen-Displays, voltage checks etc I want to have as much pre-processed as possible…

Also - if I have each record as a fixed length it makes it a lot easier to say “jump to seq no 132” to repeat a set of movements

Take Care
Dave

Hi Kurt,

Did you by any chance had some time to build a binary version of the ServoDriver function from V2.0? It would be silly to invent the wheel twice :wink:

Thanks, Xan

Hi Xan,

I did this awhile ago in the thread: viewtopic.php?f=8&t=5962 Also a version of it is in the Arc32 port of it as well.

I can upload another version if you would like.

Kurt

Hi Kurt,

I quickly read trough the post but could not find a code snippet of the servo driver. Do you have a binary version of it? I would love to check it :smiley:

Thanks!

Xan

It’s in the zip-File in the Post from 19.2.2010 at 0:38.

Greetings
Daniel

Hi Guys,

I’m not sure if there is any and if so, I couldn’t find it. So I made my own. :smiley:

Here is the binary version of the ServoDriver subroute used in the Phoenix code V2.0. It is tested with Mikes new firmware.
Version : SSC32-V2.05Alpha4A-EGP

[code];--------------------------------------------------------------------
;[SERVO DRIVER] Updates the positions of the servos
;Binary version
;**********************************************************************
;Extended binary commands.
;
;Commands 0x80-0x9F are group move servo number 0-31. The next 2 bytes
;must be pulse width for the servo:
; 0x80+servoNum, pwHigh, pwLow
;
;Command 0xA0 is the group move servo speed, which must immediately
;follow the pulse width:
; 0xA0, spdHigh, spdLow
;
;Command 0xA1 is the group move time, which must follow all of the
;pulse widths and speeds:
; 0xA1, timeHigh, timeLow
;
;Command 0xA2 is the stop all command, 1 byte
; 0xA2
;**********************************************************************
CoxaPWM var word
FemurPWM var word
TibiaPWM var word
ServoDrivernew:
for LegIndex = 0 to 5

;Update Right Legs
if LegIndex <= 2 then
  CoxaPWM =  (-CoxaAngle1(LegIndex) +900)*1000/1059+650
  FemurPWM = (-FemurAngle1(LegIndex)+900)*1000/1059+650
  TibiaPWM = (-TibiaAngle1(LegIndex)+900)*1000/1059+650
else
  ;Update Left Legs
  CoxaPWM =  (CoxaAngle1(LegIndex) +900)*1000/1059+650
  FemurPWM = (FemurAngle1(LegIndex)+900)*1000/1059+650
  TibiaPWM = (TibiaAngle1(LegIndex)+900)*1000/1059+650
endif  

serout cSSC_OUT, cSSC_BAUD, [0x80+cCoxaPin(LegIndex) ,CoxaPWM.highbyte,  CoxaPWM.lowbyte]
serout cSSC_OUT, cSSC_BAUD, [0x80+cFemurPin(LegIndex),FemurPWM.highbyte, FemurPWM.lowbyte]
serout cSSC_OUT, cSSC_BAUD, [0x80+cTibiaPin(LegIndex),TibiaPWM.highbyte, TibiaPWM.lowbyte]    

next

;Send speed and
serout cSSC_OUT, cSSC_BAUD, [0xA1,SSCTime.highbyte,SSCTime.lowbyte,13]

PrevSSCTime = SSCTime
return
;--------------------------------------------------------------------[/code]
The only thing you should do is to replace the old version with this one and make sure you’ve got the right SSC firmware uploaded.

Don’t forget to update this little line

;Wait for previous commands to be completed while walking pause (PrevSSCTime - CycleTime - 18) MIN 1 ; Min 1 ensures that there alway is a value in the pause command
This line ensures that the previous command is finished before sending a new one. The pause length is SSC speed time - cycleTime used to do IK - time it takes to send the new command. As you will see in the old version the value to send the new command is 45. This is also involves a bit of testing. You don’t want a new command before the previous is finished since not all legs will be on the right position yet. But you also don’t want the move to be already finished for some time since the walking part will be pretty shockey and bumpy.

You have to play a bit with this value to get it right. I couldn’t do it since the battery of the hybrid died while testing this…

Now the good part. I hooked up my logic analyzer to see the differences between the 2 commands. A full update of all 18 servos takes:

  • with the original sub: 52ms
  • with the binary sub: 18ms 8)

Thats what I call: a good win of some serous processing time! Thanks for the new set of SSC commands Mike!

Xan

Awesome!!! That is a massive improvement! 8) I have the file here and we will get it on the website immediately. 8)

Sounds great.

Note: the previous version I posted up here (viewtopic.php?t=5962&p=60028#p60028 ) in February also had some additional changes. That included splitting up the servo driver into two parts, the first output the servo commands and the commit part that output the end of the command. This allowed the timing to be very accurate in timing as you only needed to output the final 3 bytes (I don’t think you need the CR here…)

I also found the speedup here to be significant. Yours is a little more than I would have expected as my earlier calculations were that with the ASCII version you output about 8 characters per servo (#10P1500), where with the binary you output 3 so expect about a 2.67 time speedup here, so if the old way was 52ms I would have expected the new time to be about 19.5… I still wish we could get the SSC-32 and Bap to talk to each other at full speed 115200 as this would give us a 3 times speedup. The version I I mentioned in the other thread has my own serout functions to allow me to do that, but it would be a lot cleaner if you could simply do this using serout.

Kurt

Hi Kurt,

Yes indeed, I thought, or even wrote, about this before as well. This makes it easier to calculate the length of the pause needed to sync the BAP and SSC. Good change!

You’re right about this one. It’s a bit odd. When calculating the time with the current baud and number of bytes to send you will end up with something like 19.5 indeed. When looking at my code you will see that I convert the angles to PWM lengths in the for loop. This means that it takes even a bit longer.

I measured the time with the same logic analyzer as you got. The signal also shows the little “holes” in the signal where the bap is converting the angles to PWM signals. So I’m not quite sure where it +1,5ms stays. Maybe the “bits” flow a bit harder on dutch ground? :wink:

Xan

Sounds great. Yep the other bit of speed up is probably caused by savings in the serout functions to go in and out to do the calculations. I wonder if you would get a little more speedup, if you changed the 3 serouts into 1, like:

serout cSSC_OUT, cSSC_BAUD, [0x80+cCoxaPin(LegIndex) ,CoxaPWM.highbyte, CoxaPWM.lowbyte, | 0x80+cFemurPin(LegIndex),FemurPWM.highbyte, FemurPWM.lowbyte, | 0x80+cTibiaPin(LegIndex),TibiaPWM.highbyte, TibiaPWM.lowbyte]
Kurt

I hope this doesn’t give much of a difference. This is only a function jump which should not take much time. But it sure is worth a try. It should really surprise me if I could see the difference on the logic analyzer though.

I’ll get back on this :mrgreen:

Xan

Hi Kurt,

As promised an update;
You are right, it gives a small time win.
With the 3 separate serout commands an full update takes 18.14075ms.
With a single serout command the full update takes 17.99105ms
The difference is another 230uS. :stuck_out_tongue:

Xan