PIC18F4520: PWM Motor Control

From Mech
Jump to navigationJump to search

Pulse Width Modulation, or PWM, is a technique used to vary the average magnitude of a signal by changing its duty cycle (the proportion of time that a signal is active or "high"). For a moe in-depth introduction to PWM motor control click here.

Available Pins

The PIC18F4520 is capable of outputing a Pulse Width Modulation signal on two separate channels: CCP1 and CCP2 (shown below). The red pins have the capability of outputing PWM, while the grey are usually committed to communication or power.

4520pindiagramPWM.jpg



Unidirectional Motor Control

This section will detail how to set up a simple program and circuit to control a motor using a PIC microcontroller and PWM.

Sample Code

Program to run a motor at different speeds using pulse width modulation (PWM), controlled by a push button.

First include header file with definitions for specific PIC. Set fuses. HS is type of external clock, low voltage protection (LVP) is off, and the watchdog timer (WDT) is off. External clock frequency of 20 MHz is specified.

  #include <18F4520.h>
  #fuses HS,NOWDT,NOPROTECT,NOLVP
  #use delay(clock=20000000)

Define pin names to be used in the main program. See header file for currently defined pin names.

  #define BUTTON PIN_A4

Begin main body of program.

  void main() {

Setup the CCP1 pin (PIN_C2 on the 18F4520 chip) to be a PWM output. Also set the timer to be used for PWM.

     setup_ccp1(CCP_PWM);
     setup_timer_2(T2_DIV_BY_1, 255, 1);

Setup an infinite loop, using a while statement.

     while( TRUE ) {

Check whether button is pressed or not, and vary duty cycle of PWM accordingly. Note that duty cycle is defined from 0-255 with 0 being 0% and 255 being 100% (8-bit number).

        if (input(BUTTON)){
           set_pwm1_duty(235);}
        else {
           set_pwm1_duty(135);}
    }
  }

Circuit Diagram

Pwmckt.jpg

Bidirectional Motor Control

This section will detail how to set up bidirectional motor control using a PIC microcontroller and PWM.

Sample Code

Program to run a motor bidirectionally at varying speeds depending on the position of a potentiometer.

First include header file with definitions for specific PIC. Set fuses. HS is type of external clock, low voltage protection (LVP) is off, and the watchdog timer (WDT) is off. External clock frequency of 20 MHz is specified.

  #include <18F4520.h>
  #fuses HS,NOWDT,NOPROTECT,NOLVP
  #use delay(clock=20000000)

Introduce the variables to be used in the main program.

  int read;
  int readlow;
  int readhigh;

Begin main body of program.

  void main() {

Setup the CCP1 and CCP2 to be PWM outputs. Also set the timer to be used for PWM.

     setup_ccp1(CCP_PWM);
     setup_ccp2(CCP_PWM);
     setup_timer_2(T2_DIV_BY_1, 255, 1);

Setup analog input, and which analog channel is active.

     setup_adc_ports(AN0_ANALOG);
     setup_adc(ADC_CLOCK_INTERNAL);
     set_adc_channel(0);

Setup an infinite loop, using a while statement.

     while(TRUE) {

Read the analog input and define "readhigh" and "readlow" as functions of "read". Note that the value of "readhigh" varies from 0 to 255 when the potentiometer is between 140 and 255, and "readlow" behaves similarly.

        read = read_adc();
        readlow = (120-read)*2.125;
        readhigh = (read-140)*2.217;

Check the value of "read", and set the duty cycle of each PWM output signal accordingly. The H-bridge circuit used requires two inputs (the two PWM outputs of the 18F4520) to control the direction and speed of the driven motor.

        if (read<120){
           set_pwm1_duty(readlow);
           set_pwm2_duty(0);}
        else if (read>140){
           set_pwm1_duty(0);
           set_pwm2_duty(readhigh);}
        else {
           set_pwm1_duty(0);
           set_pwm2_duty(0);}
    }
  }

Circuit Diagram

Bipwmckt.jpg