How SSC 32 controls the servo speed?

Hi, i´m trying to control the servo speed using PWM on the VCC in.
I´m having problems with that, so i start to search on internet and i found the SSC 32 board that control the servo speed without use an PWM in the VCC input.
So i want to know if anybody here knows how to control the servo speed just with microcontroler software.
I´m using ATMEGA16 and i tried to do some rotines to increment the pulse width, so as faster i increment the pulse width, faster the servo goes to the position.
For example, i want to move the servo from position A (1ms) to position B (2ms), so i created a rotine that goes like 1.1ms, 1.2ms, 1.3ms…,2ms, because if i pulse 2ms the servo goes with total speed to the desired position. This way i make the servo goes in “steps”, but unfortunately it´s not working properly.
Somebody can help me? What method SSC 32 uses to control the servo speed?
Thanks for now!

please don’t cross-post a question to multiple threads. this board is active enough that all posts get read by the regulars and the lynxmotion customer service employees several times a day.

first off just reading your post it really sounds like you are trying to modulate the VCC of a servo to control its rotational velocity. just forget this idea and move on… a servo is not just a motor but an entire closed loop system with a controller running a PID to drive the output to a commanded position. even if you reduce the supply voltage you might make some effect simply because you starve the dc motor inside of current but the results will be both very non linear and highly erratic when you have a load on the motor.

so connect the servo vcc to a nice beefy 6V and modulate the position command signal to accomplish the desired rotational velocity.

to demonstrate concept let’s start off with the basic signal for a servo at 0 degrees is a 1.5ms pulse every 20ms. you probably knew that of course. if you want to move the servo to say -45 degrees the pulse changes to 1.0ms every 20ms. to make that move occur smoothly over say 1 second (=1000ms) you need 1000ms / 20ms = 50 steps, each step being (1.0ms - 1.5 ms) / 50 = -.01ms shorter in duration without changing the 20ms pulse rate.

In your atmega probably the easiest way to do this is to set one timer to create an interrupt every 20ms and in the service routine trigger a second timer to make the control pulse. what I would do is to have a position variable with the next control pulse duration all setup before the interrupt occurs such that all it needs to do is jam that value into the timer register and set a flag that the pulse has occurred. now in your foreground loop you can wait for that flag and when it goes active you update the position variable and clear the flag before the next 20ms interrupt occurs. when the commanded position == desired position and the flag is set… the move is done. assuming you are coding in C, don’t forget to make any variables accessed by both the foreground loop and the interrupt service routine volatile so you don’t get messed with by any compiler optimizations.

this is a very over generalized description of what the ssc-32 does for 32 servo channels all at the same time. the ssc-32 has some hardware latches that drive the servo outputs to allow a simple atmega168 to do this very effectively and very cleverly. if you have an ssc-32 it is much much simpler to use a serial port (UART) just send it position commands with a ‘T’ parameter to accomplish the same thing as above.

Hello Eddie, thanks for your explanation and sorry for the cross-post.

Actually i´m using BASIC language to programm my ATMEGA16, i think that i understand your
example and i tried to write it.
In BASIC i used a command called PULSE that generates a pulse with the specified time duration
in the specified pin, and the PAUSE command to make the 20 ms interrupt. I will try it as
soon i get in home and i´ll post the result later.
It looked like this:

\Steps = number of steps to reach the destination
\TimeMov = Duration of the Movement in ms
\ActPos = Actual servo position
\FutPos = Future servo position
\delta = increment/decrement constant of Actual position pulse

Steps=TimeMov/20

ActPos=1,5
FutPost=1

delta=(FutPos-ActPos)/Steps

for i=1 to Steps
pulse B,0,ActPos
ActPos=ActPos+delta
pause 20
next


It looked right to you? Thanks again!

here’s the problem… the 20ms includes the time from the pulse, which varies.

the 20ms is from pulse leading edge to pulse leading edge. by using a 20ms pause plus the servo pulse you increase the frame time to 21 to 22ms total. with an analog servo you’ll still get movement but it won’t be linear with your pulse width. with a digital servo it “might” stop accepting pulses if the time becomes too long… depends on the servo.

you can still experiment with this of course, so long as you are prepared for the results. I would recommend using a pause of 19 rather than 20 just so the frame time varies from 20 to 21 which is closer to the standard. you may also want to put conditional around your pulse duration to restrict it to the range of 0.7ms to 2.3ms so any math type error can’t send the servo screaming into an end stop and possibly damage it.

good luck.

Ow i see, so i´ll try to use pause like this:

pause (20-ActPos)

Then the interrupt time will be no longer then 20ms, if it didn´t work i´ll try pause 19.

It´s a good idea to limited the max and min values of the ActPos, i´ll try it too.
Later i´ll post the results, i appreciate your help!

My previous tests didn´t work, but i think that it´s a problem with the compiler commands. I can´t use the PULSE and PAUSE command with variables, maybe it´s a bug on the compiler, because he compile the file but the MC don´t execute this instructions correctly if i´m using variables with that, it works fine just with a static number, like: PAUSE 100.
If i put:

time=100
pause time

didn´t work.

So i´m trying to make the pulse in another way, setting the bit high and low in the right times, but to do that i need to know what is the minimum valeu of the PAUSE command, then i make a routine to execute this “unit” time for “n” times.
Somebody knows whats the maximum PAUSE resolution ? Because i will need a very precise small value to do this as i´m thinking, like: PAUSE 0.004 (4us).
Thanks !

This depends entirely upon the specifics of the BASIC compiler you are using and the oscillator frequency of the ATmega16, and possibly the optimization level of the compiler if it has one.

Ok, so i´ll try another compiler.
Actually i´m already trying with CodeVision AVR, i wrote the code but i don´t know how i have to wire the ATMEGA32 with the serial port to record the chip.
I see the CodeVision manual and it say´s that i need a board to do that.
There is any other way to upload the program to the chip without the use of this boards?
I have wired my protoboard to connect the ATMEGA32 to the serial port to use PonyProg and it works, actually it´s the datasheet wiring, but isn´t working with CodeVision.
What i need to do to interface my ATMEGA32 with CodeVision without this boards???
Thanks!

as I recall PonyProg can be made to work with a couple different programming interfaces.

when you say “I have wired my protoboard to connect the ATMEGA32 to the serial port to use PonyProg and it works, actually it´s the datasheet wiring, but isn´t working with CodeVision” what exactly do you mean? What is actually working, PonyProg recognizing you have an ATmega32 attached? Please provide a link to what you have wired up.

It is quite possible you just need to configure CodeVision to output a specific file format, although PonyProg should take a number of the standard ones. You may not be able to use the hardware wiring that works with PonyProg with the CodeVision environment, but you should certainly be able to generate an output file (like a .hex file) from CodeVision that PonyProg can program to your ATmega32.