AVR based 16 Channel RC servo driver

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 snipped-for-privacy@hotmail.com

Reply to
Pang Fu
Loading thread data ...

search this page for "8-servo".....

formatting link

signals

C
Reply to
CWatters

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
Reply to
Rene Tschaggelar

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.

Reply to
Johnny

Is there any reason why you don't just use AVR I2C routines to drive this?

formatting link

-Shane

Reply to
Shane Bouslough

In comp.robotics.misc CWatters wrote: : search this page for "8-servo".....

:

formatting link

The link it references -

formatting link
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
 Click to see the full signature
Reply to
Christopher X. Candreva

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.

Reply to
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.

Reply to
Johnny

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

Reply to
Jan-Hinnerk Reichert

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 , Seattle, WA, USA. PGP keyID 27F772C1
Reply to
Wim Lewis

Somewhere around the time of 08/27/2003 03:51, the world stopped and listened as Rene Tschaggelar spoke these words of wisdom...:

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.
Reply to
Daniel Rudy

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.

Reply to
Dave VanHorn

The code as is, is here.

formatting link

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.

Reply to
Dave VanHorn

I have thought about servo control some time ago, but have never produced any code :-(

Jan-Hinnerk

Reply to
Jan-Hinnerk Reichert

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

Reply to
Jan-Hinnerk Reichert

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.

Reply to
Pang Fu

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.