Query Movement Status Trouble

Hi Kurt, all is programmed in C++ under Linux and compiled with Gcc; we have built several robots including one with 27 servos whose control appears to be satisfactory. Nevertheless (see the previous answer to Jim) I can’t explain why real time responses are so different (roughly factor 7). For example, if you want to build an inverted pendulum, you need your commands to respect a precise timing; we fail in that attempt…

As I mentioned, the phoenix code does it’s own timing.

That is the code issues a command, knowing how long the move is supposed to take, it does what is necessary to setup the next command, it calculates how much time the setup code took, subtract that from the time of the last command, wait that amount of time, and issue the next command… Sometimes you need to a little fudge to know how long it will take you to issue the next command and use that in your code estimate. In some versions of the phoenix code, I had the code output all of the next command up to the terminator (CR for ASCIIs, Time stuff for binary version). So all you have to output when the time is right is either 1 or 3 bytes…

Works well in the phoenix code.

Kurt

You are suggesting that the Q command is not working correctly. Which of the following do you suspect?

  1. The SSC32 sometimes takes much longer than 5ms to respond to the Q command.
  2. The SSC32 sometimes continues to return ‘+’ even after the move is complete.
  3. Something else.

It would be helpful to know some additional detail. Specifically

  • What is the move time and/or speed in the command sent to the SSC32? (And is it always the same?)
  • What is the sleep interval in the “usleep( foraWhile ) ;” statement?
  • Does the statement “receiveRS232( status, 1 ) ;” pend/spin until a byte is received, or does it return immediately? (I assume it pends, but it is always good to ask.)

As always, visibility into the code is valuable. If you have a way to monitor the serial data stream to/from the SSC32, that would be ideal. Then you can see exactly what is going on. The next best thing would be to instrument the code to send info the debug console. Look at the servo move command to make sure it is what you expect, and print the SSC32’s response to each Q command.

Mike

@jlp Mike designed the SSC-32 and wrote the firmware. If there’s anything wrong he will be able to help you figure it out. :wink:

That is probably the best thing to do. Querrying the movement command status is just adding useless churn to your setup. You already know the value you are going to use for the servo position. Remember that the ssc-32 knows nothing about the actual position of a connected servo.

Isnt it just to measure the the Voltage on the middle soilderpoint in the potentiometer on the servo in question ?

No, the “Q” command only checks to see if the ssc-32 has finished sending its commands to the servo.

I thing you misunderstood … or i didnt explain enough

If you carefully take the servo apart, solder a wire to the middle of the three solderpoints , i think its called “the brush”, and then put the servo together again. Now you have a absolute feedback exactly where the servoposition is, if you can decode it, and its quite simple: You just move the servo to one end, for example 500us, save the voltage, then move it to 1500us and save the voltage. Now if you have a reading of for example 3,26V you can easely calculatre the exact position where (in us) the servo is

hrmmm… was this explanation understandebal ?

Please observe, i have NOT done this IRL, but if you have spare analoge inputports it souldnt be a problem … i think …

Not the same.

Yes you can read the wiper of the pot, and calculate its position, but that has nothing to do with the Q command. The Q command will respond with + when the command has executed.

To use the voltage read from the R/C servo pot in a positioning system, you are essentially creating a ‘P’ (proportional) controller (simple closed loop).

Alan KM6VV

you are right

Been there, done that.

viewtopic.php?f=2&t=2748
viewtopic.php?f=31&t=3182

I just thoght it was an easy answer to jlp initial question, whithout solving the initial cause of the problem… because it was certanly way over my head…

@zoomkat
it was a very nice “Proof Of Concept”, did you use it for anything after that ?

No, I just did it to see how it could be done. It is more practical to query the last position sent to the servo when some event happens. Below is a test of that idea.

viewtopic.php?f=8&t=4658

The C++ code in attachment shows the trouble with the Query Movement Status :
If you compile the code as given (adding main and rs232 subroutines) you should find
the servo from time to time freezes for half a second. Now, if you comment the query
cycle, the servo performs at a higher rate and never freezes.

I am still not sure where the problem came from; eventually a cause may be our own
RS232 send/receive methods…
checkServo.cpp (2.25 KB)

So it occasionally takes 500 ms instead of 200 ms for the Q command?

Maybe your RS-232 receive function is getting blocked by something else in the PC?

Just a thought.

Alan KM6VV

  1. Yes, from time to time, the servo get stuck and the difference factor may be higher than the
    mentioned one, apparently as much as 200ms and 1 sec
  2. Effectively, as mentioned, the RS232 send/receive methods we wrote may be the cause of the
    unexpected behavior nevertheless these same methods perform without trouble when we shunt
    the Query cycle. This is not a full proof because there is much more communications when the
    Query cycle is present.
  3. If someone may use its on RS232 library to communicate with the SSC-32 with one servo connected
    on port 0; we could confirm (or not) these results.

I went back and re-read the thread. You never mentioned what sort of hardware you are using. Is it RS232, or USB to serial? If it’s USB to serial what adapter are you using? If it’s FTDI based, change the latency to the minimum. This will help. The SSC-32 as stated before can have delays (50uS to 5mS), but nothing like 500mS or more. The most likely culprit is the serial system on the PC / embedded PC…

Also as stated before. You can achieve great results by defining the time, send the commands, then waiting precisely for that time to elapse, then issue the next command. You can even subtract the time required to send the command from the equation. This will be more precise than relying on the PC’s serial system to pass data, although RIOS uses it quite effectively. :stuck_out_tongue: Good luck…

Hi Mike,
the previous posted CCP code should answer most of your questions; I have not monitored the stream.
Thanks.

  1. You are right, I use USB to serial; tomorrow I will repeat the test with another converter and/or on a PC with a RS232 output… (my converter label is unreadable)
  2. “send the commands, then waiting precisely for that time to elapse, then issue the next command” is what I am doing in the test code; I also agree that I could avoid the query command and programmed my own to bypass RS232 but… anyway I’d like to understand…

Below is the code I used with my foot contact test. It worked with out issues using a noname USB to serial adapter.

'ssc-32 (SSC32-V2.01XE) servo control using Just Basic.
'6 second timed move, stopped when "VC" analog input is
'grounded and reads less than "228" (foot switch, etc.).
'22k resistor connected between +5v and "C" input
'to keep "C" high at +5v (~"255" value) until grounded.

oncomerror [handleIt]
'set comport value to the one you use
open "Com8:9600,n,8,1,ds0,cs0,rs" for random as #comm
Print #comm, "#0P2200T1000" 'put servo to initial position
y=1 'outside loop counter set to 0
[loop]
print "step ";y
print "starting 2 second start delay"
timer 2000, [delay2] 'iniial delay before timed move
wait
[delay2]
timer 0
x=0   'inside loop counter set to 0
Print #comm, "#0P700T6000" 'start timed servo 0 move to 700
[loop1] 'inside loop
x=x+1
y$ = "VC" 'used for analog input
Print #comm, y$ 'request digital input value from ssc-32
timer 20, [delay] 'read return delay
wait
[delay]
timer 0
dataRead$ = input$(#comm, lof(#comm))
num = ASC(dataRead$)'used for analog data
if num < 228 then Print #comm, "STOP 0"
if num < 228 then [jump]
if x < 160 then [loop1] 'set for number of samples during move
[jump]
Print #comm, "QP0" 'get last position sent to servo
timer 50, [delay3] 'delay to allow data to be returned
wait
[delay3]
timer 0
dataRead$ = input$(#comm, lof(#comm)) 'get returned data
print "voltage byte is "; num 'print out raw servo position
print "position byte is "; dataRead$ 'print out raw servo position
print "servo position is "; ASC(dataRead$)*10 'convert position into ms
timer 500, [delay4] 'delay to allow data to be returned
wait
[delay4]
timer 0
Print #comm, "#0 P2200T1000" 'send servo to start position
print ""
y=y+1
if y < 11 then [loop] 'set for number of loops
print "done"
Close #comm
end
[handleIt]
print "Comport error! Check settings and status."