Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
Thread Tools Display Modes
Old 4th December 2007, 10:57 PM   (permalink)
Default 18 servo controller

Here is my problem:

I need to control 18 servos for a hexapod robot. I need to be able to control all 18 servos simultaneously. I have been looking at the PWM setup, but I am not sure if this would be best, since there are not many channels on each PIC.

Option 1:
*use 6 PICs with at least 3 PWM outputs (one for each leg)
*each leg PIC controlled by master PIC (brain, tells legs what coordinates to move to, also handles sensors (maybe another 10 pins))

Option 2
*use 18F master PIC as brain(sensor, decision handling, gives leg positions to slave PIC)
*use one slave PIC with 18 outputs and bit-bang the pins. (receives move direction, stop, body pitch/roll/yaw, etc. modes from master)

Option 3
*find a PIC with 18 PWM channels

I am hoping some of you have some experience with this, cause I cannot make up my mind as to what would be the better choice. I will be using an 18F series for the brain, since making a crude AI will be easier with C.
Ambient is offline  
Reply With Quote
Old 5th December 2007, 01:22 AM   (permalink)
Default

I don't know how useful this will be for you, but might get some ideas from what they did. I pick it up on AVRFreaks yesterday. It controls 20 servos, the source is in 'C', and uses 2 x 4017. I think they used a ATmega16, a 40 pin chip, but only 3 pins go to the 4017s. Just took a brief look, don't know 'C'.
Attached Files
File Type: zip servo_controller.zip (44.6 KB, 26 views)
HarveyH42 is online now  
Reply With Quote
Old 5th December 2007, 01:35 AM   (permalink)
Default

It looks like a much simpler design then I need to use. It looks like they are cascading the servos by using the decade counter? I need to be able to control each servo in real time.

Will a mux for the PWM signal work? Or does that signal need to be present on the servo input at all times?
Ambient is offline  
Reply With Quote
Old 5th December 2007, 01:52 AM   (permalink)
Default

You can do something similar on the PIC using the CCP module "compare" mode. The following example uses a single 74HC4017 IC and 2 PIC pins for 9 channels (on the 74HC4017 Q1..Q9 output pins). This could be expanded to 18 channels by adding another 74HC4017 driven by the CCP2 pin (and some additional interrupt code).

Code:
static unsigned char Qn = 0;
static unsigned int  Qarray [] = { 1500, 1500, 1500, 1500,
                                   1500, 1500, 1500, 1500,
                                   1500, 20000 };  // 800..2200 range

void isr_hi ()
{
 /****************************************************************
  *  K8LH Crazy-8 HiRez Hard 8-channel 74HC4017 Servo Algorithm  *
  ****************************************************************/
  if (PIR1bits.CCP1IF == 1)       // if CCP1 "compare" interrupt
  {
    CCPR1H++;                     // avoid update "match"
    CCPR1 += Qarray[Qn];          // update "compare" int value
    CCPR1H--;                     // fix CCPR1H
    LATCbits.LATC1 = 0;           // clear CCP1 "CLK" line
    PIR1bits.CCP1IF = 0;          // clear CCP1 interrupt flag

    Qarray[9] -= Qarray[Qn++];    // adjust end-of-period off time

    if (Qn = 10)                  // if end-of-period
    { Qn = 0;                     // reset Qn array index
      Qarray[9] = 21000;          // reset 20.0-msec period and
      LATAbits.LATA0 = 1;         // toggle 74HC4017 "CLR" line
      LATAbits.LATA0 = 0;         // to force Q0 output sync'
    }
  }
}

Last edited by Mike, K8LH; 5th December 2007 at 01:58 AM.
Mike, K8LH is online now  
Reply With Quote
Old 5th December 2007, 02:48 AM   (permalink)
Default

Code for 30 servos @ 256 resolution with a single PIC:

http://www.manhattancontrols.com/for...topic.php?t=68

Also, I have a board and superb PC software using a USB PIC to drive the servos:

http://www.circuit-ed.com/30-Servo-H...S-P117C10.aspx
wschroeder is offline  
Reply With Quote
Old 5th December 2007, 03:27 AM   (permalink)
Default

Quote:
Originally Posted by wschroeder
Code for 30 servos @ 256 resolution with a single PIC:
That's very clever and amazingly simple.

Mike.
Pommie is online now  
Reply With Quote
Old 5th December 2007, 11:29 AM   (permalink)
Default

Quote:
Originally Posted by wschroeder
Code for 30 servos @ 256 resolution with a single PIC:

http://www.manhattancontrols.com/for...topic.php?t=68

Also, I have a board and superb PC software using a USB PIC to drive the servos:

http://www.circuit-ed.com/30-Servo-H...S-P117C10.aspx
Ouch!!! That's almost a "standard" (isochronous) soft PWM routine but you destroy the Servo array values and rely on refreshing the array from the serial port for each 20 msec cycle. And it seems the same pulse width or PWM setting applied to all of the servos results in different timing (jitter) for the different servo port groups. I would not recommend this algorithm or method for anything more than a "learning exercise"!

Instead consider using a "standard" (isochronous) soft PWM routine which doesn't destroy the PWM array values. It'll continue to ouput pulses cycle after cycle and allows you to update one or more PWM array values at any time or interval (during your 17.5 msec 'window'). The soft PWM routine also correctly handles PWM array values of 0 (handy for LEDs) since it updates the output port from a shadow register.

Code:
        clrf    PWM             ;
        setf    Shadow          ; shadow bits all on
PWM256  movf    PWM,W           ; PWM counter 0..255
        cpfsgt  Servo+0         ; servo 0 (0..255) match?
        bcf     Shadow,0        ; yes, turn off output bit
        cpfsgt  Servo+1         ;
        bcf     Shadow,1        ;
        cpfsgt  Servo+2         ;
        bcf     Shadow,2        ;
        cpfsgt  Servo+3         ;
        bcf     Shadow,3        ;
        cpfsgt  Servo+4         ;
        bcf     Shadow,4        ;
        cpfsgt  Servo+5         ;
        bcf     Shadow,5        ;
        cpfsgt  Servo+6         ;
        bcf     Shadow,6        ;
        cpfsgt  Servo+7         ;
        bcf     Shadow,7        ;
        movff   Shadow,LATB     ; update output port
        incfsz  PWM,F           ; bump PWM counter
        bra     PWM256          ; do it again

Last edited by Mike, K8LH; 5th December 2007 at 01:01 PM.
Mike, K8LH is online now  
Reply With Quote
Old 5th December 2007, 01:54 PM   (permalink)
Default

Mike,

It doesn't need to make a copy as each servo value is decremented 256 times.

I also don't understand why you think the original code would jitter? There would be a slight discrepancy between the first and last servo but it could be easily fixed (have a similar line of code to set the bits initially) and wouldn't cause jitter anyway.

Mike.
Pommie is online now  
Reply With Quote
Old 5th December 2007, 02:04 PM   (permalink)
Default

Oops, I missed that (each array element decremented 256 times). Sorry.

But as far as jitter, he's turning on all of the port LAT bits at the same time at the beginning of the code but turning off the bits one group at a time with many cycles difference between groups. I don't see the "easy fix" you mention without using shadow registers. Please enlighten me some more? Thanks.

Last edited by Mike, K8LH; 5th December 2007 at 02:18 PM.
Mike, K8LH is online now  
Reply With Quote
Old 5th December 2007, 02:26 PM   (permalink)
Default

The easy fix is to turn the bits on with similar code to in the PWM loop but with just a bsf followed by a nop for each output. This would be placed before the 500uS delay.

Mike.
Pommie is online now  
Reply With Quote
Old 5th December 2007, 02:43 PM   (permalink)
Default

I don't understand. Can you show me?

Also, that code doesn't seem capable of handling Servo PWM values of 0 for the minimum 500 msec timing.
Mike, K8LH is online now  
Reply With Quote
Old 5th December 2007, 03:01 PM   (permalink)
Default

Worst case is if the last servo pin in the decfsz array is 0 movement and nearly 1/256 resolution time has passed in the On state. Since 500us of delay at the beginning is an arbitrary value for this example, there is room for adjustment at this point to fine tune out any real physical servo movement for a 0 servo at the beginning of the routine. Maybe I should more accurately say that the resolution is 255 with a spare do nothing loop at the beginning.
wschroeder is offline  
Reply With Quote
Old 5th December 2007, 03:05 PM   (permalink)
Default

The code to turn on the outputs would be,
Code:
	bsf	 PORTA.0
	nop
	bsf	 PORTA.1
	nop
	bsf	 PORTA.2
	nop
	bsf	 PORTA.3
	nop
	bsf	 PORTA.5
	nop
	bsf	 PORTB.0
	nop
This would be repeated for all outputs in the same order as the pwm loop.

Then would come the 500uS delay.

Then would come the loop that consist of,
Code:
             decfsz    _servo+0, 1,0 
             iorlw     1 
             decfsz    _servo+1, 1,0 
             iorlw     2 
             decfsz    _servo+2, 1,0 
             iorlw     4 
             decfsz    _servo+3, 1,0
The value of zero is the maximum value. The valid values being 1 to 256. You can of course shorten the 500uS delay.

Mike.
Pommie is online now  
Reply With Quote
Old 5th December 2007, 03:20 PM   (permalink)
Default

I do have other code where I incremented all the servo values to make 0 = 0:

Code:
i = 30
FSR0ptr = @servo
Do
   inc(POSTINC0)
   dec(i)
Loop Until i = 0
wschroeder is offline  
Reply With Quote
Old 5th December 2007, 03:26 PM   (permalink)
Default

Warren;

I apologize.

There really is no jitter other than the normal plus or minus 1 cycle jitter associated with interrupt entry. All of the servo pulses maintain the same timing from 20 msec cycle to 20 msec cycle.

It's just pulse width timing that's off a bit;

Servo 00 (LATA) = 1 ---> 501.2 usecs
Servo 05 (LATB) = 1 ---> 503.0 usecs
Servo 13 (LATC) = 1 ---> 504.4 usecs
Servo 19 (LATD) = 1 ---> 506.2 usecs

No jitter...

Mike,

Yes, of course. Now that's a simple and elegant and (embarrassingly) intuitive solution. Of course you'd need some extra 'nops' to account for those instructions writing the the LATx registers too.

Then modify that delay_us(500) statement to take into account the 12 cycles that occur before writing LATA and you've eliminated the pulse width timing problems...

Last edited by Mike, K8LH; 7th December 2007 at 10:33 AM.
Mike, K8LH is online now  
Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Latest
555 servo controller? can get them working lompa General Electronics Chat 9 31st May 2007 06:24 AM
Help required with servo motor controller mayhem Robotics Chat 3 26th May 2006 04:21 PM
Auto servo controller, need help with the 555 linuxglobal General Electronics Chat 2 20th April 2006 03:52 PM
looking for servo controller circuit diagram using switch ? calico Micro Controllers 49 27th February 2006 01:35 AM
Help me start, making a servo controller for motorcycle use. motoracer General Electronics Chat 4 11th November 2003 10:29 PM



All times are GMT. The time now is 01:44 PM.


Electronic Circuits  |  Electronics Wiki
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.