PWM Speed Control of DC Motor with PIC16F887
Control de velocidad pwm de un motor dc usando PIC16f887, PWM Speed Control of DC Motor with PIC16F887, calculo frecuencia pwm para motor dc
Objetives:
Use a pic16f887 to control in open loop speed an dc motor using a pwm signal controlled by a potentiometer.
Material:
- Motor DC
- LCD
- Potenciometro
- PIC16f887
- ld293 ( Driver puente H )
Theory:
PWM Control
It is a technique to modulate the power that is delivered to a motor by modulating the supply voltage. The voltage applied to the motor is a PWM signal, which is a periodic signal to which the pulse width is changed, the larger the pulse the greater the delivered power.

ADC module for Pic16f887
A pic of medium range like the pic16f887 incorporates a digital analog converter that can be configured of 8 or 10 bits.
folio 150946
Frecuencia de la señal PWM
La frecuencia de la señal PWM debe estar en un rango de 500 – 20K Hz, se recomienda una frecuencia alta para que la dinámica del motor la vea como si fuera una señal constante. Lo ideal es que se una frecuencia de 20k para que no produsca un ruido audible al ser humano.
Por ejemplo si queremos que nuestra señal PWM una frecuencia de 2kHz usando el oscilador interno del pic que es 8 M Hz se calcula con la siguiente formula
F_pwm = F_osc / [4 x PRE x (PR2+1)]
Donde:
F_osc: Frecuencia del oscilación del PIC
PRE : Es el preescaler ( Un prescaler es un circuito que reduce la frecuencia que ingresa a un temporizador-contador dividiéndola para un determinado valor . Por ejemplo, si la relación es 1:8, el prescaler entrega una frecuencia igual a la octava parte de la frecuencia del oscilador)
PR2 es el valor de 8 bits del registro TMR0
Si escogemos
F_osc = 8MHz
PRE = 4
F_PWM=4K Hz
Entonces el parámetro a despejar es PR2
PR2 = ( F_osc / [4 x PRE x F_pwm ] )-1 = ( 8 M Hz / 4 * 4 * 2k)-1 = 249
En este casa la función para configurar la frecuencia de la señal pwm es
setup_timer_2 (mode, period, postscale)
Mode puedes T2_DISABLED, T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16 ( es el preescaler)
Period is a int 0-255 that determines when the clock value is reset ( es el PR2)
Postscale is a number 1-16 that determines how many timer overflows
PWM Module for pic
The pic has a module to generate a pwm signal which can be modulated the pulse width with a value of 8 bits
0 would be a zero pulse guess, a zero power
255 would be a complete pulse choke, the maximum power delivered
Functioning
The microcontroller reads the output voltage of the potentiometer using the ADC module converts it into a digital value, and depending on that value, the PIC generates a PWM signal with a given pulse width, this signal is connected to the ENABLE of a bridge driver H (LD293D) which in turn is connected to the DC motor.
Proteus Diagram

Dowloand PWM control DC motor
https://mega.nz/#!zpwnGIqY!RubugwkGmlAUkZNd0c3VeeC6x_Ni3SHW_-2X3_uz9tE
Code in pic16f887
For compiler this code i use PIC C Compiler
#INCLUDE <16F887.H> #DEVICE ADC=8 // resolucion del ADC de 8bits #USE DELAY(CLOCK=8000000) #FUSES NOWDT //No Watch Dog Timer #FUSES INTRC_IO //Internal RC Osc, no CLKOUT #FUSES NOPUT //No Power Up Timer #FUSES NOMCLR //Master Clear pin used for I/O #FUSES NOPROTECT //Code not protected from reading #FUSES NOCPD //No EE protection #FUSES NOBROWNOUT //No brownout reset #FUSES NOIESO //Internal External Switch Over mode disabled #FUSES NOFCMEN //Fail-safe clock monitor disabled #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NODEBUG //No Debug mode for ICD #FUSES NOWRT //Program memory not write protected #FUSES BORV40 //Brownout reset at 4.0V #include "lcd.c" // libreria para el control de LCD void main(){ FLOAT pwmanalogica; INT16 pwmdigital; //Variables para lectura de ADC y señal de Control a modulo CCP lcd_init(); // Turn LCD ON, along with other initialization commands lcd_gotoxy(1,1); lcd_putc("PWM:"); // periodo reloj = 1/f ; periodo de ciclo maquina = 4/f ; preescaler 2,4, 8, 16 4/f / prescaler; // F_pwm = F_osc / [4 x PRE x (PR2+1)] setup_timer_2(t2_div_by_4,249,1); setup_ccp1(ccp_pwm); //Configurar modulo CCP1 en modo PWM setup_adc(adc_clock_internal); //Configurar ADC setup_adc_ports(sAN0|VSS_VDD); // AN0 como entrada analogica while(true){ set_adc_channel(0); //Seleccionar Canal 0 delay_ms(1); pwmdigital=read_adc(); //Leer ADC delay_ms(1); pwmanalogica=pwmdigital; lcd_gotoxy(5,1); // point LCD cursor to col5 row1 printf(lcd_putc,"%2.1f",pwmanalogica); set_pwm1_duty(pwmanalogica); // } }
Download source code and machine file .hex
https://mega.nz/#!zpwnGIqY!RubugwkGmlAUkZNd0c3VeeC6x_Ni3SHW_-2X3_uz9tE
