Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC 16F877 > Timers > 2 servos

Status
Not open for further replies.
Servos are serviced sequentially. Each using 2.5-msecs. Each servo has a 20-msec period but they're staggered by 2.5-msec intervals.

Happy Holidays. Cheerful regards, Mike, K8LH

Code:
unsigned int servo[] = { 1500, 1500, 1500, 1500,
                         1500, 1500, 1500, 1500 };
Code:
void interrupt isr()               //
{ static unsigned char mask = 0;   // servo output pin mask
  static unsigned char n = 0;      // servo array index, 0..7

  if(CCP1IF)                       // if "special event" interrupt
  { CCP1IF = 0;                    // clear the interrupt flag
    if(LATB ^= mask)               // toggle the servo output pin
    { CCPR1 = servo[n];            // servo "on" time, 1000..2000 usecs
    }                              //
    else
    { CCPR1 = 2500 - servo[n];     // servo "off" time, 500..1500 usecs
      mask <<= 1; n++;             // setup for next servo
    }                              //
    if(mask == 0)                  // if last servo (20-msecs)
    { mask = 1; n = 0;             // reset mask and index
    }
  }
}

soft servo.png
 
Last edited:
Please note that unlike the other "compare" modes, the special event trigger mode resets the CCPR1 register pair on a compare match.
This made me remember something, The compare match clears timer1 and so the above code is wrong. The lines setting CCP1 shouldn't be += just =. I.E CCP1 = servoPos[n] etc. The Special Events Trigger mode has (unfortunately) been removed from the newer chips.

Mike.
Edit, I see Mike has it correct above.
 
Oops! I said it wrong, too, Mike. As you said, it's the timer that's cleared on the special event trigger match, not the CCPR1 register pair...
 
The Special Events Trigger mode has (unfortunately) been removed from the newer chips.
Some of the newer chips have PWM "pulse steering" which works quite nicely for servos. Unlike the "soft" servo methods, it's a hardware solution (no jitter) and since the PWM module is buffered you have plenty of time to service the PWM driver interrupt (you can turn off interrupts for short periods of time, if necessary, without affecting the servos). It's really a pretty nice hi-rez low-overhead servo solution...

Happy Holidays... Mike, K8LH

servo steering 2.png
 

Attachments

  • 16F1823 Servo Steering.asm
    15.2 KB · Views: 184
Last edited:
Please note that unlike the other "compare" modes, the special event trigger mode resets the CCPR1 register pair on a compare match.
In my 18F2321 (I know we are talking of a 16F) the compare function allows to reset the timer not the ECCP.
 
As per! I was wrong, thinking PWM.... Servos use PCM … It make sense to me now... I remember a couple of years back working on JPanhault's aero endeavours… We had all sorts of servo driving software... Believe it or not, this was the one we went with..

PWM was in my head because recently we've been messing with Arduino PWM outputs....

Thanks Mike... Oh and Mike....
 
With PICs, to use PWM for servos, the "secret" so to speak, is to have an additional prescaler allowing to output a frequency, low enough, as required by them.

That is common (not sure if with all PICs) with ECCP modules. In some of the manuals (if not all) the example on how to reach 50 Hz is detailed with numerical values.

IIRC, 18F4431 is one.
 
We seem to have lost the Thread starter...
kawauso
I have made several "non" interrupt servo drivers, but it's difficult to maintain perfect timing (especially in C)

Interrupts are really the only way...

You need to just grab Mikes code and load it into a pic16f877a... It should work fine..
 
With PICs, to use PWM for servos, the "secret" so to speak, is to have an additional prescaler allowing to output a frequency, low enough, as required by them.

That is common (not sure if with all PICs) with ECCP modules. In some of the manuals (if not all) the example on how to reach 50 Hz is detailed with numerical values.

IIRC, 18F4431 is one.


As I said in a very early post, you cannot get the prescalers to slow to 50Hz pwm. You also need to slow the CPU clock speed from 4MHz to 500kHz. That allows hardware to control the update.

Alternatively, a servo sets with a couple 50Hz pulses and holds x
For some time if you want to set other servos and then loop to check and update each servo
 
As I said in a very early post, you cannot get the prescalers to slow to 50Hz pwm. You also need to slow the CPU clock speed from 4MHz to 500kHz. That allows hardware to control the update.

Alternatively, a servo sets with a couple 50Hz pulses and holds x
For some time if you want to set other servos and then loop to check and update each servo
That is not how you use the PWM module to drive servos. Did you even bother to read this thread?

Mike.
 
As I said in a very early post, you cannot get the prescalers to slow to 50Hz pwm. You also need to slow the CPU clock speed from 4MHz to 500kHz. That allows hardware to control the update.

Alternatively, a servo sets with a couple 50Hz pulses and holds x
For some time if you want to set other servos and then loop to check and update each servo

Here you have it. As I said, at 40 MHz; nothing less.

Sorry it is the Power Control Module.
For Gophert.png
 
Any chance you or Gophert can provide an example? Does the method provide a usable pulse width resolution?

TIA... Mike
 
Any chance you or Gophert can provide an example? Does the method provide a usable pulse width resolution?

TIA... Mike

As I understand hobby servos, the duty cycle doesn't matter as much as the on time so any frequency from 25 to 100Hz has worked ok for me (with some trimming).

Anyhow, 1 mSec is generally one extreme and 2 mSec is the other extreme with 1.5 mSec being neutral (midpoint).

To do this with PWM on a pic, specifically an 18F877, set parameters as follows to get 62Hz updates and 12% duty cycle (2 mSec) at 1MHz F(osc).

/*
* PWM registers configuration
* Fosc = 1000000 Hz
* Fpwm = 62.00 Hz
* Duty Cycle is about 12.2 % (2 mSec)
* Prescaler is 16
* Config pwm pin as output
*/
PR2 = 0b11111011 ;
T2CON = 0b00000111 ;
CCPR1L = 0b00011110 ;
CCP1CON = 0b00101100 ;


// If you want 1 mSec for other extreme, set...
CPR1L = 0b00001111 ;
CCP1CON = 0b00011100
This technique yields about 31 steps of resolution which is good enough for most flying/driving RC applications or the little gadgets people have asked me to make. Your milage may vary.

NOTE: you may have to adjust (trim) a bit to tune for your specific servo (add/subtract a few bits on the duty cycle). Also, remember that the two least significant bits for duty cycle are bits 5&4 of CCP1CON.

Using PWM allows the microcontrol hardware to maintain position and code can be used for monitoring sensors and other overhead.

If you are a purist and want 50Hz update frequency, you'll have to drop clock F(osc) to 500kHz and you'll have to settle for 16 steps of resolution.

If you have a non-hobby servo, check the datasheet for range of high/low times and adjust PWM as needed of this level of resolution fits your needs.
 
Last edited:
Thank you for the explanation. Unfortunately, I don't think I can do much with only sixteen 64-usec steps across that 1000-us range.
 
Last edited:
Last edited by a moderator:
Mike... Remember this thread...
 
Do you constantly need some kind of validation? If you think everything in life is a competition, professional help is available and happiness is possible. Keep your local suicide prevention hotline number available - the holidays are difficult for people with your symptoms.
Let's not start a war!! Christmas an all!! There are some places where 16 levels would be fine... All's good..
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top