AVR based 16 Channel RC servo driver

P

Pang Fu

Guest
I would like to generate 16 channel R/C (radio control) servo motor signals
(1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is there any C
(AVRgcc or CodeVisionAVR) code to realize this?

Pang Fu

nospam_pangfu@hotmail.com
 
search this page for "8-servo".....

http://www.omegav.ntnu.no/avr/resources.php3


"Pang Fu" <pangfu@hotmail.com> wrote in message
news:3f4b77d0_1@news.iprimus.com.au...
I would like to generate 16 channel R/C (radio control) servo motor
signals
(1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is there any
C
(AVRgcc or CodeVisionAVR) code to realize this?

Pang Fu

nospam_pangfu@hotmail.com
 
Pang Fu wrote:
I would like to generate 16 channel R/C (radio control) servo motor signals
(1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is there any C
(AVRgcc or CodeVisionAVR) code to realize this?
A rather simple approach uses a small FPGA for the couters.

Rene
--
Ing.Buero R.Tschaggelar - http://www.ibrtses.com
& commercial newsgroups - http://www.talkto.net
 
On Wed, 27 Aug 2003 10:51:17 GMT, Rene Tschaggelar
<tschaggelar@dplanet.ch> wrote:

Pang Fu wrote:
I would like to generate 16 channel R/C (radio control) servo motor signals
(1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is there any C
(AVRgcc or CodeVisionAVR) code to realize this?

A rather simple approach uses a small FPGA for the couters.

FPGA is not necessary. The AVR has 16 bit timer with two 16bit
compare registers and interrupts. I suggest this application can be
implemented by sorting the array of 16 channels into sequence of pulse
width, and then just reloading the same compare register. The second
16bit comapare register can be used to reload or clear the timer, and
thus determine the timebase. The AVR is plenty fast enough to make
this work, especially the new mega series that process 16MIP/s @
16MHz, but codevision compiler is a bit of a handicap. Imagecraft
make a much more efficient one. Never tried any gcc though.

regards,
Johnny.
 
"Pang Fu" <pangfu@hotmail.com> wrote in message news:<3f4b77d0_1@news.iprimus.com.au>...
I would like to generate 16 channel R/C (radio control) servo motor signals
(1ms-2ms) with 9 or 10 bits accuracy. These signals will drive an 16 R/C
motors on a walking robot.
Is there any reason why you don't just use AVR I2C routines
to drive this?

http://www.robot-electronics.co.uk/htm/sd20tech.htm

-Shane
 
In comp.robotics.misc CWatters <colin.watters@pandora.be> wrote:
: search this page for "8-servo".....

: http://www.omegav.ntnu.no/avr/resources.php3

The link it references - http://members.home.net/daniel.herrington/ no
longer exists. Anyone mirror this ?

Herky Jerky's Pages - Robotics-related information. Includes schematics,
source code, mechanical photos, printed circuit boards for robot. Uses Atmel
AVR microcontrollers for infrared remote decoder, infrared obstacle
detection, sonar rangefinder, 8-servo controller. Also includes linux C
source code for onboard PC.



--
==========================================================
Chris Candreva -- chris@westnet.com -- (914) 967-7816
WestNet Internet Services of Westchester
http://www.westnet.com/
 
In article <3f4cae13.433766@news.optusnet.com.au>,
john_wr@NOSPAM.hotmail.com says...
thus determine the timebase. The AVR is plenty fast enough to make
this work, especially the new mega series that process 16MIP/s @
16MHz, but codevision compiler is a bit of a handicap. Imagecraft
make a much more efficient one. Never tried any gcc though.
Can you be specific on why you feel Imagecraft is more efficient
compared to the Codevision compiler? I'm thinking about buying
Codevision and I'd like to hear plus/minuses.

-- Jay.
 
On Wed, 27 Aug 2003 10:47:39 -0500, Jay <se10110@yahoo.com> wrote:

In article <3f4cae13.433766@news.optusnet.com.au>,
john_wr@NOSPAM.hotmail.com says...
thus determine the timebase. The AVR is plenty fast enough to make
this work, especially the new mega series that process 16MIP/s @
16MHz, but codevision compiler is a bit of a handicap. Imagecraft
make a much more efficient one. Never tried any gcc though.

Can you be specific on why you feel Imagecraft is more efficient
compared to the Codevision compiler? I'm thinking about buying
Codevision and I'd like to hear plus/minuses.

-- Jay.

Write some code and try the demo versions. Using AvrStudio to
simulate the code operation, its easy to time the code execution using
the timer in the 'processor' window. When I tried this, with my
sample code I found the Imagecraft compiled code was smaller and
executed about twice as fast as the some code compiled with
codevision. Imagecraft have 45 day evaulation version, and I think
codevision offer something similar.

AVR studio compatibility is something you should also investigate. I
have heard that Imagecraft is better than the others in this regard,
but only used codevision with Version 3 of avr sudio. Avr Studio
4.07 is not 100% stable though (can say the same for V3.56 also), so
it is difficult to tell if the problem is with the compiler listing
file compatilibility, or some bug in avr studio.

regards,
Johnny.
 
Johnny wrote:

On Wed, 27 Aug 2003 10:51:17 GMT, Rene Tschaggelar
tschaggelar@dplanet.ch> wrote:

Pang Fu wrote:
I would like to generate 16 channel R/C (radio control) servo
motor signals (1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is
there any C (AVRgcc or CodeVisionAVR) code to realize this?

A rather simple approach uses a small FPGA for the couters.


FPGA is not necessary. The AVR has 16 bit timer with two 16bit
compare registers and interrupts. I suggest this application can be
implemented by sorting the array of 16 channels into sequence of
pulse
width, and then just reloading the same compare register. The
second 16bit comapare register can be used to reload or clear the
timer, and
thus determine the timebase. The AVR is plenty fast enough to make
this work, especially the new mega series that process 16MIP/s @
16MHz, but codevision compiler is a bit of a handicap. Imagecraft
make a much more efficient one. Never tried any gcc though.
IMO it is not that simple ;-(

If you start all pulses at ones, you get trouble if some servos have
(almost) equal pulse lengths.

The classic way to avoid this would be to send one pulse after the
other. However, a servo requires a pulse every 20ms. So you can do at
most 10 servos in sequence, no matter how hard you optimize the code.

I would suggest one of the following:

1) One interrupt every 20ms that starts all pulses. Another interrupt
1ms later, here you do a hand-timed loop that stops the pulses one by
one. The drawback is that you are in a loop (with disabled
interrupts) for 1ms, i.e. that you shouldn't use 19.2kBaud or higher
for UART (or SPI).

2) Start pulses in turn every 1ms. Problem here is, that you don't get
pulse lengths near 1ms and near 2ms.

The choice depends on the application.

BTW: Every interrupt (other than pulse generation) has to be
interruptable to achieve the desired accuracy.

Jan-Hinnerk
 
"Jan-Hinnerk Reichert" <hinni@despammed.com> wrote in message
news:bilsbo$ap331$1@news.hansenet.net...
Johnny wrote:

On Wed, 27 Aug 2003 10:51:17 GMT, Rene Tschaggelar
tschaggelar@dplanet.ch> wrote:

Pang Fu wrote:
I would like to generate 16 channel R/C (radio control) servo
motor signals (1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is
there any C (AVRgcc or CodeVisionAVR) code to realize this?

A rather simple approach uses a small FPGA for the couters.


FPGA is not necessary. The AVR has 16 bit timer with two 16bit
compare registers and interrupts. I suggest this application can be
implemented by sorting the array of 16 channels into sequence of
pulse
width, and then just reloading the same compare register. The
second 16bit comapare register can be used to reload or clear the
timer, and
thus determine the timebase. The AVR is plenty fast enough to make
this work, especially the new mega series that process 16MIP/s @
16MHz, but codevision compiler is a bit of a handicap. Imagecraft
make a much more efficient one. Never tried any gcc though.

IMO it is not that simple ;-(

If you start all pulses at ones, you get trouble if some servos have
(almost) equal pulse lengths.

The classic way to avoid this would be to send one pulse after the
other. However, a servo requires a pulse every 20ms. So you can do at
most 10 servos in sequence, no matter how hard you optimize the code.

I would suggest one of the following:

1) One interrupt every 20ms that starts all pulses. Another interrupt
1ms later, here you do a hand-timed loop that stops the pulses one by
one. The drawback is that you are in a loop (with disabled
interrupts) for 1ms, i.e. that you shouldn't use 19.2kBaud or higher
for UART (or SPI).

2) Start pulses in turn every 1ms. Problem here is, that you don't get
pulse lengths near 1ms and near 2ms.

The choice depends on the application.

BTW: Every interrupt (other than pulse generation) has to be
interruptable to achieve the desired accuracy.

Jan-Hinnerk

Why not? The AVR running at 10MHz will execute instructions in 100nS.
Turning on or off 16 port pins should be easy to do with at least
a few uS of accuracy. That should be close enough for a servo signal. I've
done it with 4 servos seems simple enough to do with 16.

Randy Ott
 
On Fri, 29 Aug 2003 17:04:19 GMT, "Randy Ott" <randy@iscdata.com>
wrote:

"Jan-Hinnerk Reichert" <hinni@despammed.com> wrote in message
news:bilsbo$ap331$1@news.hansenet.net...
Johnny wrote:

On Wed, 27 Aug 2003 10:51:17 GMT, Rene Tschaggelar
tschaggelar@dplanet.ch> wrote:

Pang Fu wrote:
I would like to generate 16 channel R/C (radio control) servo
motor signals (1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is
there any C (AVRgcc or CodeVisionAVR) code to realize this?

A rather simple approach uses a small FPGA for the couters.


FPGA is not necessary. The AVR has 16 bit timer with two 16bit
compare registers and interrupts. I suggest this application can be
implemented by sorting the array of 16 channels into sequence of
pulse
width, and then just reloading the same compare register. The
second 16bit comapare register can be used to reload or clear the
timer, and
thus determine the timebase. The AVR is plenty fast enough to make
this work, especially the new mega series that process 16MIP/s @
16MHz, but codevision compiler is a bit of a handicap. Imagecraft
make a much more efficient one. Never tried any gcc though.

IMO it is not that simple ;-(

If you start all pulses at ones, you get trouble if some servos have
(almost) equal pulse lengths.

The classic way to avoid this would be to send one pulse after the
other. However, a servo requires a pulse every 20ms. So you can do at
most 10 servos in sequence, no matter how hard you optimize the code.

I would suggest one of the following:

1) One interrupt every 20ms that starts all pulses. Another interrupt
1ms later, here you do a hand-timed loop that stops the pulses one by
one. The drawback is that you are in a loop (with disabled
interrupts) for 1ms, i.e. that you shouldn't use 19.2kBaud or higher
for UART (or SPI).

2) Start pulses in turn every 1ms. Problem here is, that you don't get
pulse lengths near 1ms and near 2ms.

The choice depends on the application.

BTW: Every interrupt (other than pulse generation) has to be
interruptable to achieve the desired accuracy.

Jan-Hinnerk

Why not? The AVR running at 10MHz will execute instructions in 100nS.
Turning on or off 16 port pins should be easy to do with at least
a few uS of accuracy. That should be close enough for a servo signal. I've
done it with 4 servos seems simple enough to do with 16.

Randy Ott

From memory I think that the servos can accept pulse widths of 1000uS
+/-500us. With AVR running at 8 or 10MHz, you will get an error of
about 2us when different channels cross over if coding in C. You
could do much better that this if you use assembly language for the
ISR, or maybe by using different compiler directives and smart use of
C language.

regards,
Johnny.
 
In article <bilsbo$ap331$1@news.hansenet.net>,
Jan-Hinnerk Reichert <hinni@despammed.com> wrote:
Johnny wrote:
FPGA is not necessary. The AVR has 16 bit timer with two 16bit
compare registers and interrupts. [....]

IMO it is not that simple ;-(

If you start all pulses at ones, you get trouble if some servos have
(almost) equal pulse lengths.

The classic way to avoid this would be to send one pulse after the
other. However, a servo requires a pulse every 20ms. So you can do at
most 10 servos in sequence, no matter how hard you optimize the code.
On the other hand, if you have two timer compare registers, you can
be sending two pulses at a time; this lets you run two sets of up
to 10 servos each in the allotted 20ms, which is is enough to do
what the original poster wanted.

10-bit accuracy corresponds to about 1us of pulse-length accuracy,
or about 16 instructions at 16MIPS. As long as the interrupt latency
has less jitter than that, it should be ok.

--
Wim Lewis <wiml@hhhh.org>, Seattle, WA, USA. PGP keyID 27F772C1
 
Somewhere around the time of 08/27/2003 03:51, the world stopped and
listened as Rene Tschaggelar spoke these words of wisdom...:

Pang Fu wrote:
I would like to generate 16 channel R/C (radio control) servo motor signals
(1ms-2ms) with 9 or 10 bits accuracy.
These signals will drive an 16 R/C motors on a walking robot. Is there any C
(AVRgcc or CodeVisionAVR) code to realize this?

A rather simple approach uses a small FPGA for the couters.

Rene
You can also do this in software. Below is some pascal psudo code that
I wrote awhile ago while brainstorming this idea. You'll need 2-16 bit
timers and a VERY FAST controller to pull this off.



timer0 - interval (This sets how many pulses per second to send. Most
servoes need at least 60Hz.)
timer1 - dwell (This counts the pulsewidth slice or minimum width of the
servo pulse. So, at 6KHz that would be .000166666 seconds.)






constants
number_of_outputs = 16; Total number of outputs to control.
interval = 20; Number of pulses to send to each output before we
check for new data.

variables
zeroflag: array [0..number_of_outputs - 1] of boolean;
zerocount, intcount, X: byte;


begin {Start of servo control program}
set all i/os to output.
write 0 to all outputs.
set timer0 to freq-div mode for 60-80Hz output.
set timer1 to freq-div mode for 4KHz-6KHz output.

loop0:
intcount := interval;
get servo pulsewidth counts - load counts into temp resgister space from
count source (This could be a serial port, pre-programmed, network line,
etc...)


repeat {loop1}
{init variables}
zerocount := 0;
for x := 0 to number_of_outputs - 1 do zeroflag[x] := false;
load working registers with counts from temp registers.
write 0 to all outputs.
wait for timer0 to fire.


repeat {loop2}
wait for timer1 to fire.
for X := 0 to number_of_outputs - 1 do
begin
if (zeroflag[X] = false) then
if (reg[X] > 0) then dec(reg[X])
else
begin
output[X] := 0;
zeroflag[X] := true;
inc(zerocount);
end;
end;
until zerocount = number_of_outputs; {loop2}

dec(intcount};
until intcount = 0; {loop1}

goto loop0;

You'll need a VERY FAST controller to run this as the performance of
loop2 and and loop1 are directly dependent on the performance of the
processor. The best way to litterally wring maximum performance out of
this is hand optimized assembly code as most compiled languages do not
produce tight enough code, C and pascal included.

If you use a pulse slice of 6KHz or 6000 time a second (.00016666666
seconds) and do this 80 times a second that's 6000x80 on the inner loop
for 480000 max illiterations in 1 second!!! So, any little thing that
you can shave off loop2 and anything that it calls (like output[X] := 0)
will amplify the performance loop1 times.

HTH
--
Daniel Rudy

Remove nospam, invalid, and 0123456789 to reply.
 
You can also do this in software. Below is some pascal psudo code that
I wrote awhile ago while brainstorming this idea. You'll need 2-16 bit
timers and a VERY FAST controller to pull this off.
I have assembler freeware that does this, and a bunch of other bot related
tasks.
I set it up for eight servo outputs, but it could easily be 16.
 
"Pang Fu" <nospam_pangfu@yahoo.com> wrote in message
news:3f518137_1@news.iprimus.com.au...
Is it possible to read servo positions from a serial port (19200 or
115200kbps) and drive the servo motors in your 8 channel asm. code? Would
you share your code (preferebly 16 channel upgrraded version) with all of
us?
The code as is, is here.
http://groups.yahoo.com/group/AVR-Chat/files/

Interrupt driven serial I/O is in place, as well as the core of a language
interpreter that runs out of EEPROM. You have to define the commands, other
than the basics supplied. One of the basic commands is "set servo".

I think if you look at it, it won't be too hard to make it into what you
want.
Making it sixteen outputs instead of eight would mean using another port for
output, adding eight more positions for step position in ram, and slight
changes in the T1 ISR, and the sequencing.

Trim out the stepper, LCD, and VFD code, morse output, random number
generator, etc.
It's written for the 8515.
 
Pang Fu wrote:

Did you do it within C ? If so yould you share your code with us?
I have thought about servo control some time ago, but have never
produced any code :-(

Jan-Hinnerk
 
Wim Lewis wrote:

In article <bilsbo$ap331$1@news.hansenet.net>,
Jan-Hinnerk Reichert <hinni@despammed.com> wrote:
[...]
The classic way to avoid this would be to send one pulse after the
other. However, a servo requires a pulse every 20ms. So you can do
at most 10 servos in sequence, no matter how hard you optimize the
code.

On the other hand, if you have two timer compare registers, you can
be sending two pulses at a time; this lets you run two sets of up
to 10 servos each in the allotted 20ms, which is is enough to do
what the original poster wanted.

10-bit accuracy corresponds to about 1us of pulse-length accuracy,
or about 16 instructions at 16MIPS. As long as the interrupt latency
has less jitter than that, it should be ok.
You will get problems when both interrupts overlap, because you can
only execute one ISR at a time. However, I'm not sure that 10-bit
accuracy is needed (is the servo really able to act that accurate???)

@Pang Fu: Do you really mean 10-bit accuracy on the output variation,
i.e. 1024 different servo positions?

Jan-Hinnerk
 
You will get problems when both interrupts overlap, because you can
only execute one ISR at a time. However, I'm not sure that 10-bit
accuracy is needed (is the servo really able to act that accurate???)
When I did mine, I tried 7 bit, and 6 bit. 6 bit just started to show some
granularity.
The ISR on mine just turns off the pulse, and it turns all outputs off at
the same time, so it's pretty fast. :)
 
Dear Jan-Hinnerk,

Yes, I did mean 9 bit for 512 and 10 bit for 1024 different servo
positions. There are servo motors and other RC controlled gadgets working
with this high accuracy.

@Pang Fu: Do you really mean 10-bit accuracy on the output variation,
i.e. 1024 different servo positions?

Jan-Hinnerk
 

Welcome to EDABoard.com

Sponsor

Back
Top