Society of Robots - Robot Forum

Software => Software => Topic started by: galannthegreat on April 30, 2009, 09:15:47 PM

Title: Emulating PWM on non-PWM port on a PIC
Post by: galannthegreat on April 30, 2009, 09:15:47 PM
I am having a little trouble with getting PWM working on my PIC. I am using a non-hardware PWM (CCP) and from what I've been told, it can be emulated via software. My first question would be, how would I go about this?

P.S. even a simple example in pseudo code would be of great help here.

With thanks, Kurt.
Title: Re: Emulating PWM on non-PWM port on a PIC
Post by: LunchBox! on April 30, 2009, 10:22:19 PM
are you using the pwm for servo control?

enable a pin as output

loop
set pin high
delay for 1.5ms
set pin low
delay 20ms
goto loop

you can use a timer and interrupts to make your program more efficient too.
Title: Re: Emulating PWM on non-PWM port on a PIC
Post by: hazzer123 on May 01, 2009, 01:39:00 AM
You can use either a straight forward routine with delays, or a more complex interrupt based algorithm.

Here is the easy one.

Code: [Select]
int duty_cycle = 60; //Duty cycle varies between 0 and 100.
while (1) {
  SetPinHigh();
  delay(duty_cycle);
  SetPinLow();
  delay(100-duty_cycle);
}

The delay function here would determine your PWM frequency.

It's not a nice way of doing it... but it achieves what you want :)
Title: Re: Emulating PWM on non-PWM port on a PIC
Post by: galannthegreat on May 01, 2009, 10:56:27 AM
Thank you very much, this will be of help, but I'm curious, how would the interupt based code go?
Title: Re: Emulating PWM on non-PWM port on a PIC
Post by: hazzer123 on May 01, 2009, 11:25:13 AM
Code: [Select]
boolean PWM_state; //global
int duty_cycle;
ISR () { //Interrupt service routine
  if(PWM_state) {
    setPinLow();
    PWM_state = false;
    setTimer(100-duty_cycle); //Set timer to interrupt in this many units of time
  } else {
    setPinHigh();
    PWM_state = true;
    setTimer(duty_cycle); //Set timer to interrupt in this many units of time
  }
}

int main() {
  configure_MCU(); //Configure pin modes and timer interrupts (and possible other things)
  PWM_state = false;
  duty_cycle = 60;
  do_other_things();
}

This enables you to do other things while the PWM works. You could also use scheduling to have multiple PWM (you can see this in the arduino SoftwareServo library).
Title: Re: Emulating PWM on non-PWM port on a PIC
Post by: galannthegreat on May 01, 2009, 11:51:43 AM
Thank you this is really helpful, and this will be an even more useful method for my purposes.