Menu

all about electronic and microcontrollers

Sunday, October 17, 2010

Lesson nr.09-Using PWM to control DC Motor Speed

Hardware setup:
In this experiment we will work again with PWM, but this time, as a consumer, I will use a DC (Direct Current) motor. To avoid burning RB3 port, due to high consumption of the motor, consumption which can not be given by the port of the microcontroller, we will use an extension consisting of a transistor (our case, BC547/NPN) connected in switching mode (ON / OFF ). The current to drive the motor is provided by the collector current in the transistor. The diode is for EMF (ElectroMagnetic Field) protection. Protection provided to our transistor. I will use a small 5V DC motor from an old CD-Rom.



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.09:
'          Using PWM to control DC Motor Speed
'  Written by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will show how to work with module CCP1 as PWM mode.
'          The PORT RB3 is used for this experiment (as output, for DC Motor)
'          and RA4-RA6 (as imput, for buttons) which controls the pulse width.
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
// LCD module connections
sbit LCD_RS at RB5_bit;                 // LCD_RS assigned to PORT RB5;
sbit LCD_EN at RB6_bit;                 // LCD_EN assigned to PORT RB6;
sbit LCD_D4 at RB0_bit;                 // LCD_D4 assigned to PORT RB0;
sbit LCD_D5 at RB1_bit;                 // LCD_D5 assigned to PORT RB1;
sbit LCD_D6 at RB2_bit;                 // LCD_D6 assigned to PORT RB2;
sbit LCD_D7 at RB4_bit;                 // LCD_D7 assigned to PORT RB4;

sbit LCD_RS_Direction at TRISB5_bit;    // LCD_RS assigned to TRIS B5;
sbit LCD_EN_Direction at TRISB6_bit;    // LCD_EN assigned to TRIS B6;
sbit LCD_D4_Direction at TRISB0_bit;    // LCD_D4 assigned to TRIS B0;
sbit LCD_D5_Direction at TRISB1_bit;    // LCD_D5 assigned to TRIS B1;
sbit LCD_D6_Direction at TRISB2_bit;    // LCD_D6 assigned to TRIS B2;
sbit LCD_D7_Direction at TRISB4_bit;    // LCD_D7 assigned to TRIS B4;
// End LCD module connections

char message1[]="ON ";
char message2[]="OFF";

unsigned short Last_Duty, Current_Duty;
void main()                             // main;
{
 CMCON |= 7;                            // turn off analogue comparator and make PORTA to digital I/O;
 TRISA4_bit=1;
 TRISA6_bit=1;
 PORTA = 0;
 TRISB = 0;                             // make rb3 as output;
 PORTB = 0;                             // turn off LEDs on PORTB;
 Current_Duty = 0;                      // Initial value of variable current_duty;
 Last_Duty = 0;                         // Reset variable last_duty;
 
 Lcd_init();
 Lcd_cmd(_LCD_Clear);
 Lcd_cmd(_LCD_Cursor_Off);
 Lcd_out(1,6,"PWM and");
 Lcd_out(2,2,"DC Motor Speed");
 Delay_ms(3000);
 Lcd_cmd(_LCD_clear);
 Lcd_out(1,1,"switch1:");
 Lcd_out(2,1,"switch2:");

 Pwm1_Init(5000);                       // PWM module initialization (5KHz);
 Pwm1_Start();                          // Start PWM1 module;
 Pwm1_Set_Duty(Last_Duty);
 do {
     while(Last_Duty >= 0 <= 255)
     {
      if (Button(&PORTA, 4,1,0))
      {
       Last_Duty = Last_Duty + 5;       // If the button connected to RA4 is pressed
       Pwm1_Set_Duty(Last_Duty);
       Lcd_out(1,9,message1);
       }
      else
      Lcd_out(1,9,message2);
      Delay_ms(100);

      if (Button(&PORTA, 6,1,0))
      {
       Last_Duty = Last_Duty - 5;       // If the button connected to RA6 is pressed
       Pwm1_Set_Duty(Last_Duty);
       Lcd_out(2,9,message1);
       }
      else
      Lcd_out(2,9,message2);
      Delay_ms(100);
      }
     Delay_ms(200);                     // 200mS delay
     } while(1);                        // Do forever;
}                                       // End.

6 comments:

  1. Hello! First I want to thank you for helping us sharing your knowledge :)
    This program saved my life (my school life, at least) but there's one thing I had to change:

    You put S3 (Switch 3) at the same pin where the cristal oscillator is (RA6). When I did this physically, the lcd always displayed ON for button 2. I fixed this by just changing the port for that switch (I believe I used RB0, but I can't remember well).
    Anyway, thanks! You're great!

    ReplyDelete
  2. Please update the circuit diagram for LCD connections.Also explain what type of LCD is used.

    ReplyDelete
  3. Hi ! Could some one to help me, I am learning about ASM using MPLAP IDE. This lesson may I have code on ASM, my email : trinlt@yahoo.com.hk. Thanks for all.
    Tri Lee

    ReplyDelete
  4. Please send me the ASM code of my e-mail: subee19@gmail.com.
    Sub-ee

    ReplyDelete
    Replies
    1. Itt a forráskód mikroc-vel semeddig se tart lefordítani..

      Delete
  5. Dear sir,
    i am interested to build this circuit, could you pl mail me the .ASM file or the HEX file to my e-mail: systemelectrocontrol@yahoo.co.in please.
    regards
    padmanabhan.k

    ReplyDelete

If you do not understand something, or if you make some aplication helped by this blog, let me know.