go_away

Author Topic: Input on how to use multiple servos on one MCU  (Read 3379 times)

0 Members and 1 Guest are viewing this topic.

Offline SixRingzTopic starter

  • Full Member
  • ***
  • Posts: 76
  • Helpful? 0
  • Bit's and pc's = Robot.
Input on how to use multiple servos on one MCU
« on: June 08, 2008, 02:09:19 PM »
I'm thinking about how many servos one might be able to control with one single MCU. Of course this depends on the amount of timers, PWM modules etc, but let's assume we will be working with only one 8 bit timer and one 16 bit timer. Number of output ports can be said to be infinite. How would you go about programming a control? Also, how many servos are your record controlled with a single MCU? (State which one also) I have some ideas myself but want others input also!  8)
Grounding things properly means burying them in the backyard...

Offline benji

  • Supreme Robot
  • *****
  • Posts: 832
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #1 on: June 08, 2008, 03:07:52 PM »
you can control as many servos as you have(I/O ports) with one timer  ;)
good ol' BeNNy

Offline SixRingzTopic starter

  • Full Member
  • ***
  • Posts: 76
  • Helpful? 0
  • Bit's and pc's = Robot.
Re: Input on how to use multiple servos on one MCU
« Reply #2 on: June 09, 2008, 05:29:27 AM »
Ok, maybe I should add: individually controlled servos. But maybe that is possible still Benji? I'm curious, how would you do that?  ::)
Grounding things properly means burying them in the backyard...

Offline dunk

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 1,086
  • Helpful? 21
Re: Input on how to use multiple servos on one MCU
« Reply #3 on: June 09, 2008, 07:25:23 AM »
i remember seeing an in depth discussion about this on http://www.avrfreaks.net/.
try searching their forum.

if you want to save some time programming there's also pre-written libraries as part of Procyon AVRlib here: http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/


dunk.

Offline benji

  • Supreme Robot
  • *****
  • Posts: 832
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #4 on: June 09, 2008, 12:27:35 PM »
yes it still  ;D

check this pseudo code:

Code: [Select]
1-make an array ,the number of the elements is the number of servos you have
2-set each element in the array as it is a number == how many microseconds is the high pulse - 1000
3-set all ports to logic high (here the high pulse starts)
4-delay for 1ms (this is the minimum pulse width, suppose servo range is 1ms>>2ms)
5-run the timer1 (make it run at 1MHZ,you can have it by using the timer prescaler,this way you have 1us each count)
6- while( timer1 <= 1000 )
{if ( x1 >= timer1 ){ turn off pin that goes to servo x1}
 if ( x2 >= timer1 ){ turn off pin that goes to servo x2}
 if ( x3 >= timer1 ){ turn off pin that goes to servo x3}
 .
 .
 .
 if ( xn >= timer1 ){ turn off pin that goes to servo xn}
}while loop ends here
7-turn off timer1
8-delay 20ms
now all the servos have got 1 pwm clock
just make a jump back to the step 3 to make the pwm continue
« Last Edit: June 12, 2008, 04:39:03 AM by benji »
good ol' BeNNy

Offline SixRingzTopic starter

  • Full Member
  • ***
  • Posts: 76
  • Helpful? 0
  • Bit's and pc's = Robot.
Re: Input on how to use multiple servos on one MCU
« Reply #5 on: June 09, 2008, 03:21:43 PM »
Benji, that looks like a beautiful solution I must say. Perhaps because it's alot like what I had in mind.  ;D  Still there's something in my heart against busy-wait loops in real time programming, but in this case I can't really think of a better and more straight forward solution than that. Nice work!  8)
Grounding things properly means burying them in the backyard...

Offline benji

  • Supreme Robot
  • *****
  • Posts: 832
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #6 on: June 10, 2008, 12:32:15 AM »
well i had to say that the problem with the loop is when its too long then there might be a little error,, i guess it would still be very acceptable
with servos
that error totally depends on how much time does the mcu spends doing the IFs
good ol' BeNNy

Offline ALZ

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
Re: Input on how to use multiple servos on one MCU
« Reply #7 on: June 11, 2008, 11:41:30 PM »
Hi SixRingz:

I see you are really looking to learn. I would like to put in my 2 cents.

"Still there's something in my heart against busy-wait loops in real time programming, "

That is why you don't use a "busy-wait loop" if you know how to program. You never have your MC just waiting! You should always have an idea of how long something should take. For ex. Are you waiting to see if a pulse is between 1 ms and 2 ms long. Well you know you have 1 ms before you have to check (the wait part of the loop) for that pulse. So jump into another loop that may check an encoder wheel. Then jump back.   Most of the programs I write have 3 "loops" for a lack of a better word. Main loop, subloop, interrupt. If you know the timing of your project, your MC will be jumping in and out of these loops without missing a beat.   

Offline dolinay

  • Contest Winner
  • Jr. Member
  • ****
  • Posts: 18
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #8 on: June 12, 2008, 12:37:33 AM »
Hi, I don't like busy loops either. Here is how you could do it "interrupt driven".

1) define variables which store how long the high pulse is for each servo (in "ticks" of counter)
   unsigned char servo1, servo2, servo3, etc.....
2) Define variable for "software counter":
   int counter;
3) Set timer to generate interrupt at e.g. 100 kHz - this will give you 2000 interrupts per one period of servo signal (20 ms): 100,000 ints
per second / period of servo signal (50 Hz) = 2000 interrupts per period.

4) In the interrupt handler do this:
ISR (TIMER0_COMPA_vect)
{
counter++;
if ( servo1 == counter )
   servo1_off();   // end pulse for servo 1
if ( servo2 == counter )
   servo2_off();   // end of pulse for
etc. for all servos

if ( counter == 2000 )    // end of period (20 ms), start new pulses
{
   servo1_on();
   servo2_on();
   ....
   counter = 0;
}
}
So the int. handler is executed 100,000 times per second. Each time you increment your software counter by one. When counter reaches desired length of any servo pulse, you set the output for this servo low. When counter reaches 2000, which means end of period, you set all servos high (start new pulses for all servos) and reset the counter.   

Difficult part here is to set up the timer. Use prescaler and modulo register. With Atmel AVR you would handle the "compare match" interrupt (CTC mode) and set up the timer like this (with 4 MHz CPU clock):

   TCCR0A = 0x02;   // CTC mode
   TCCR0B = 0x01;   //0x01;   // no prescaler
   OCR0A = 40;   // OC value to have 100000 interrupts per sec   

Valid length of servo pulse (stored in the variables servo1, servo2, etc.) is from 100 (1 ms) to 200 (2 ms). The resolution is then 100 units for servo travel, which should be ok for many aplications. If more precise control of the position is needed, you can generate the interrupt with higher frequency but remember to leave some processor time for the main loop. With 4 MHz clock and 100 KHz interrupt frequency there is only 40 cycles (roughly 40 CPU instructions executed) between each interrupt, minus what the interrupt handler takes, so it would need a higher clock (more powerful MCU or external crystal).

Offline benji

  • Supreme Robot
  • *****
  • Posts: 832
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #9 on: June 12, 2008, 04:37:44 AM »
well i dont urge the interupt driven program you mentioned above simply because there is no advantage of the interrupt over the busy loop,,or maybe its worse

1/because you actually keep interupting the main flow each 10us (0>>20ms) which is not enough to do anything in the main program so your mcu is mostly stuck in the interupt routine

2/when the IFs are too many you can have a debug problem as long as the interupts trigger faster than the ISR' execution time
(which will happen when you want accurate position control)

3/in the program i did mention you have a delay of 20ms (you can put a whole bunch of operations there,,imagine what u can do in 20ms)

« Last Edit: June 12, 2008, 04:44:59 AM by benji »
good ol' BeNNy

Offline dolinay

  • Contest Winner
  • Jr. Member
  • ****
  • Posts: 18
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #10 on: June 12, 2008, 08:03:13 AM »
There's "interrupt or not interrupt" discussion in another thread and it's really not a simple yes/no question.  ???
It's mostly about programming habits. Some people prefer to write one big loop in which everything is done and some tend to use interrupts.
I prefer the second way and I think when you write complex program it's just too complicated to put everything into one loop... That's why there are realtime operating systems with threads and processes - to separate tasks and let them execute (virtually) at the same time. You can think of an interrupt routine as a one thead of your programs execution and the main loop another thread...

Quote
1/because you actually keep interupting the main flow each 10us (0>>20ms) which is not enough to do anything in the main program so your mcu is mostly stuck in the interupt routine

It depends on what you do in the main routine. For things like computing something or analyzing image data you need not worry about how often it is interrupted. What matters is if the main loop gets enough CPU time to provide results in time. If "in time" means e.g. in one second, 10 instructions between each interrupt may be more than enough. Sure you cant, for example, wait for short change on input pin there but in interrupt-driven program you won't do this - you will handle it with interrupt too. Such programs may actually do nothing in the main loop.

Anyway, you're right that 100 KHz interrupts is quite much here. Of course you have to make sure the ISR always finishes before next interrupt occurs. This would not be only debug problem but bad design  :-\ 

Debuging program with interrupt is always hard. I try to debug complicated code separately or rather use some kind of output to signal state of the program (such as turn on LED if some IF is true). There are things which you can hardly debug anyway - such as receiving IR signal from a remote control. And spending a minute or two looking at my code and thinking why it doesn't work is often more useful than trying to find a way to debug it.

Offline Asellith

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 648
  • Helpful? 9
  • "I'm a leaf on the wind. Watch how I soar"
Re: Input on how to use multiple servos on one MCU
« Reply #11 on: June 13, 2008, 08:40:59 AM »
I am currently working on a solution to run several servos from discrete electronics outside the MCU that can then hold "memory" and only need to be updated when the servo value changes. A clock signal at lets say 1.5ms to keep all the servos centered at startup and then something to clip or extend the Pulse width to the desired length in steps would work. My current ideas keep ending up being way to many gates and flip flops or counters per servo to be practical in large numbers. As a side note why not install a smaller MCU dedicated to servo control. I am working on an I2C based module for the SOR open source project that is having trouble getting off the ground. This will be a servo control board that will have a dedicated MCU. If the MCU is only controlling servos then only control interupts are needed to update variables based on communications. So each time a change is made all your main MCU does is tell the module servo 2 to 45 degrees or advance 1 degree. If I can find an easy way to control servos with limited amount of discrete electronics then I can expand the amount of servos my module can handle greatly if not I'll have to choose my MCU wisely.
Jonathan Bowen
CorSec Engineering
www.corseceng.com

Offline SixRingzTopic starter

  • Full Member
  • ***
  • Posts: 76
  • Helpful? 0
  • Bit's and pc's = Robot.
Re: Input on how to use multiple servos on one MCU
« Reply #12 on: June 15, 2008, 08:34:18 AM »
In this case I'm voting for benji's solution (in case of single mcu and no additional electronics). Scheduling is clean and although you might "waste" a whole ms worst case (if all servos are at 2ms) you still rather effectively use the cycles in average case and also give you a clean 20ms to use for other code. Like ALZ pointed out in another thread there's alot of pushing and popping the registers going on behind the scenes when calling interrupts.  This actually causes a call to an interrupt to take around 10 cycles if I remember him right? This would waste alot of cycles if we were calling the interrupts 100,000 times per second...  :-\

Grounding things properly means burying them in the backyard...

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: Input on how to use multiple servos on one MCU
« Reply #13 on: June 15, 2008, 10:34:10 AM »
I hate to tell you guys but this anti-interrupt thing you have going is not exactly a good idea.

My project at work makes use of PWM style sensors, and they run at a constant frequency and a vary their pulse width based on the input. Since our Frequency is constant, we can easily calculate what the time needed is, then we can use the interrupt hardware provide on our processors to take care of the measuring. Yes we have set up a global timer like John H. said in another post, but to using a polling technique would be a bigger waste of cycles.

E.G. if you have know you have a given number of servos, interrupt driven servos is probably your best option for maximizing your micro's processing time.

But you don't have to listen to me, I was just telling you what is typically done in the industry and that microcontrollers are designed with this in mind for better throughput, other wise there wouldn't be such a demand for it, and it wouldn't be on micros like the ATmega.

If you have the hardware, you should use it.

Offline benji

  • Supreme Robot
  • *****
  • Posts: 832
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #14 on: June 15, 2008, 12:23:13 PM »
Quote
But you don't have to listen to me, I was just telling you what is typically done in the industry and that microcontrollers are designed with this in mind for better throughput, other wise there wouldn't be such a demand for it, and it wouldn't be on micros like the ATmega.
ye right, id support using the available hardware first, like the PWM channels
although these channels are made to be DACs for the industry but whynot use em if we can,
the problem comes in when we need more than the PWM channels available
so we prefer to use one timer to control all servos,so we can only use 1 interupt (this timer's interupt)
which can work on 1 value (1 servo) unless you dont want to spend much time in the ISR

if you can explain how to do it in short pseudo code ,or just the algorithm
it would be great
i d still support the code above untill i see an interupt based one thats more efficient
« Last Edit: June 15, 2008, 12:25:33 PM by benji »
good ol' BeNNy

Offline benji

  • Supreme Robot
  • *****
  • Posts: 832
  • Helpful? 0
Re: Input on how to use multiple servos on one MCU
« Reply #15 on: June 15, 2008, 12:29:29 PM »
Quote
you might "waste" a whole ms worst case (if all servos are at 2ms)
actually its not worse case, always you are going to loose that damn 1 ms  ;D
good ol' BeNNy

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: Input on how to use multiple servos on one MCU
« Reply #16 on: June 15, 2008, 11:35:18 PM »
The problem is you are making the assumption that all the servo's have to be sync'd so that they all roll over at the same point in time. Check out the avrlib implementation. It turns on and off the pins only using one timer and one output compare register only using N+2 interrupts where N is the number of servos.

I'm doing a small rewrite for a more Object Oriented solution specific to ATmegas with a Timer3, that run at 16MHz (e.g.  Robostix or Axon for example), but because of the way it works it can only handle about 9 servos using one output compare register. Using each additional output compare register would get you 9 more servos (I had done the math in another thread but my math started from the wrong assumptions...  :-\ )
« Last Edit: June 22, 2008, 05:34:14 PM by JesseWelling »

Offline SixRingzTopic starter

  • Full Member
  • ***
  • Posts: 76
  • Helpful? 0
  • Bit's and pc's = Robot.
Re: Input on how to use multiple servos on one MCU
« Reply #17 on: June 16, 2008, 04:35:04 AM »
Quote
The problem is you are making the assumption that all the servo's have to be sync'd so that they all roll over at the same point in time.
For me that's not the case. But if you are to control 20 servos, each with it's own interrupt, 40hz is going to mean 40x20= 800 interrupts per second. If you divide these evenly over that second it would mean 1/800 = 1,25 ms between interrupting your other algorithms. Maybe not that much when you're talking mcu:s, but still. And this is if you manage to have just a single interrupt per servo. You must also make sure none of these interrupts try to interrupt each other which also causes some concern. Just seems easier to know that during 1ms every 30ms or so, ALL the servos get served and the rest of the time is for other algorithms.
Well, I'm certainly not sure about this, and I'm no professional programmer either. But I sure want to be, and that is why this is such an interresting topic. Please more input!  8)

PS. I'm in no way anti-interrupt. My University real-time software teacher was very pro interrupt!
Grounding things properly means burying them in the backyard...

Offline ALZ

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
Re: Input on how to use multiple servos on one MCU
« Reply #18 on: June 17, 2008, 03:14:04 AM »
I am going to write a little tutorial on interrupts because most of the information coming from people on this site is wrong. No way is using interrupts to write this program is good programming.

Quote
The problem is you are making the assumption that all the servo's have to be sync'd so that they all roll over at the same point in time.
For me that's not the case. But if you are to control 20 servos, each with it's own interrupt, 40hz is going to mean 40x20= 800 interrupts per second. If you divide these evenly over that second it would mean 1/800 = 1,25 ms between interrupting your other algorithms. Maybe not that much when you're talking mcu:s, but still. And this is if you manage to have just a single interrupt per servo. You must also make sure none of these interrupts try to interrupt each other which also causes some concern. Just seems easier to know that during 1ms every 30ms or so, ALL the servos get served and the rest of the time is for other algorithms.
Well, I'm certainly not sure about this, and I'm no professional programmer either. But I sure want to be, and that is why this is such an interresting topic. Please more input!  8)

PS. I'm in no way anti-interrupt. My University real-time software teacher was very pro interrupt!


 


Get Your Ad Here

data_list