Driving more than 4 servos

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Driving more than 4 servos

Post by fma » Wed Jun 18, 2014 2:20 pm

Hi!

I plan to build a little hexapod, first using cheap 9G servos for the prototype, before switching to the new Dynamixel XL-320 servos (chained serial connection).

Is there a way to drive more than 4 servos (using Servo class)? A 3DOF hexapod will need 24 servos...

Thanks.
Frédéric

rambo
Posts: 11
Joined: Fri Jun 06, 2014 9:36 pm
Location: Finland
Contact:

Re: Driving more than 4 servos

Post by rambo » Wed Jun 18, 2014 6:55 pm

I just realized I wasn't thinking properly when I first read your message. Short version: as such most likely not, however one could try using 595s over SPI (choose some high-speed version and you can run the SPI clock at several MHz) and timer trickery to send out new data every time a pulse needs to end (they can all start at the same time), or put smd-attiny (or similar cheap&small mcu) next to each servo to generate the analog signals and use I2C as the bus. Openservo looks way too sophisticated (and expensive) for this.

Below what I first wrote, just in case someone else needs a bit of background info:

I'm fairly sure the Servo class is for "analog" servos which need 1000us to 2000us pulse every 20ms. To complicate matters there are "digital" servos which take this same analog pulse at up to 200Hz, and some that take shorter pulses at even higher rate. Then there are the Dynamixels and their kind (every name-brand traditional RC-servo maker has their own proprietary bus as well) which use addressable serial bus.

For the serial bus you're not limited by the amount of timers that can be dedicated to generating the pulses, so write your own DynamixelServo class and you're basically limited by RAM if you want an instance for each servo. On the other extreme just change the address on a single instance as needed.

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: Driving more than 4 servos

Post by fma » Wed Jun 18, 2014 7:54 pm

Yes, I mean analog servos. I would like to make a low cost prototype, before switching to Dynamixel.

Do you think it is possible to drive 24 servos using simple GPIO, set in an interrupt routine? The idea is to register a function within a timer interrupt, and there, turn on/off each pin to emulate the Servo class...
Frédéric

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Driving more than 4 servos

Post by dhylands » Thu Jun 19, 2014 5:27 am

I think that you should be able to drive about 12 servos using a single timer. So provided you have the GPIOs, driving 24 servos should just require 2 timers. The teensy code uses a single timer to drive upto 12 servos.

If you add external shift registers then you can dramatically reduce the number of GPIOs required.

Using external shift registers, you should be able to drive 12-16 servos using 2 GPIO lines.

If you're interested, I have C libraries for talking to Dynamexils and a Python one (although it was coded for full python and uses pyserial). You can find my python code here:
https://github.com/dhylands/Bioloid
This includes a command line utility for talking to the servos as well.

The code also implements a command line interface on top of the lower level libraries for talking to the dynamexils. It's buried in a few places in this repository:
The command line stuff is here:
https://github.com/dhylands/projects/tr ... ioloid/cli
and if you look in the Makefile you'll see the names of all of the source files needed, some of which are elsewhere in the same repository.

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: Driving more than 4 servos

Post by fma » Thu Jun 19, 2014 5:38 am

Thanks for the tips!
Frédéric

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: Driving more than 4 servos

Post by fma » Mon Jun 23, 2014 11:48 am

dhylands wrote:I think that you should be able to drive about 12 servos using a single timer. So provided you have the GPIOs, driving 24 servos should just require 2 timers. The teensy code uses a single timer to drive upto 12 servos.
Could you explain a little bit how it is possible to drive 12 servos with only 1 timer? Do you mean using timer outputs (don't they have only 4 outputs each?), or using a software way?
Frédéric

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Driving more than 4 servos

Post by dhylands » Mon Jun 23, 2014 4:13 pm

Basically, you need to know the required pulse with for each servo.

You use GPIOs to drive the servos, and the timer to drive your code.

Basically, you have a state machine that is either processing a pulse for a particular servo, or you're processing the refresh interval.

So lets say, you have 3 servos, with pulse widths of 1.3, 2.0, and 1.8 msec each. And that the refresh interval is 20 msec.

So you would start things off by bringing servo 1's gpio high, and setting the timer for 1.3 msec.
When the timer expires, you set servo 1's gpio low, set servo 2's gpio high, and set the timer for 2.0 msec
When the timer expires, you set servo 2's gpio low, set servo 3's gpio high and set the timer for 1.8 msec
When the timer expires, you set servo 3's gpio low, and you've finished processing the servos, so now you calculate the refresh interval.
1.3 + 2.0 + 1.8 = 5.1 msec. We've got a refresh interval of 20 msec, and only 5.1 msec has gone by, so we now wait for 14.9 msec.

And then repeat.

By sequencing the servos (and not trying to process them all at once) you get consistent pulse widths.

The big thing is being able to program the timer to go off some time in the future and generate an interrupt when that happens. This interrupt handler is what drives the whole thing. In the teensy code, that ISR is here: https://github.com/dhylands/micropython ... rvo.c#L224 but its using totally different hardware from the pyboard.

However, the logic should be mostly the same.

If you were to use an external shift register, you basically just shift a 1 though the shift register, generating a rising and falling clock edge on each timer interrupt.

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: Driving more than 4 servos

Post by fma » Mon Jun 23, 2014 8:49 pm

Nice idea! I'll try that...
Frédéric

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: Driving more than 4 servos

Post by fma » Thu Jun 26, 2014 6:44 am

I have another question related to servos...

Do you think it is possible to drive a micropython board using radio control (RC) servo pulses signal? The idea would be to plug pyboard inputs to standard RC receiver outputs...

I was thinking to use the ExtInt class, to register a callback, and, in the same time, use a Timer as precise counter (µs) to measure the pulses. But I don't know if it will be fast enough.

All this in // with the software servos control as described above...

Thanks.
Frédéric

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Driving more than 4 servos

Post by dhylands » Thu Jun 26, 2014 7:51 am

fma wrote:I have another question related to servos...

Do you think it is possible to drive a micropython board using radio control (RC) servo pulses signal? The idea would be to plug pyboard inputs to standard RC receiver outputs...

I was thinking to use the ExtInt class, to register a callback, and, in the same time, use a Timer as precise counter (µs) to measure the pulses. But I don't know if it will be fast enough.

All this in // with the software servos control as described above...

Thanks.
oh yeah - that should definitely be possible, and is on my todo list. I've done it on a 16 MHz AVR. See: http://docwiki.gumstix.org/index.php?ti ... x_RC_input using pin change interrupts.

I did a mod to my RC receiver to get all the channels on a single line. The VEX receiver also presents a single signal line. Capturing individual channels should also be possible.

You could use EXTINT, but I wanted to use the HW to capture timestamps on the edges. That makes it more accurate and less susceptible to jitter caused by the EXTINT irq handler being delayed by some other irq. I like using the HW whenever I can.

Post Reply