This topic shows how to use a IR remote control to control DC motor rotation direction and speed using PIC16F877A microcontroller and L293D motor driver IC. The remote control used in this project is a TV remote control which uses RC-5 communication protocol.
Related topics:
To see how to interface DC motor with PIC16F877A microcontroller and L293D visit the following topic:
DC motor interfacing with PIC16F877A and L293D
And the following topic shows how to decode IR RC-5 remote control using PIC16F877A microcontroller:
RC-5 remote control protocol decoder using PIC16F877A and CCS C
The RC-5 has 14 bits per 1 code transmission, the 14 bits can be divided into 4 parts:
The first 2 bits are start bits and they are always logic 1.
The third bit called toggle bit, it can be logic 1 or logic 0.
The next 5 bits are address bits, each device type has its address number for example TV address number is 0, CD player address = 20 …………
And the last 6 bits are command bits, each button has its command number.
For the same device for example TV all the remote control buttons has the same address but each button has its command.
The toggle bit changes whenever a button is pressed.
The remote control used in this project is a TV remote control which has an address = 0.
In this project toggle bit is not used which means only address and command quantities are used. The following image shows the used buttons with the corresponding address and command numbers for each button.
Project circuit schematic is shown below.
The PIC16F877A MCU needs to be supplied with 5V on pins VDD and VSS.
LED2 indicates maximum speed.
PIC16F877A CCP1 and CCP2 modules are used as PWM which allows us to control motor speed as well as direction of rotation. PWM frequency is 500Hz.
Remote controlled DC motor using PIC16F877A CCS C code:
PIC16F877A Timer2 is configured to generate a PWM frequency of 488Hz and the microcontroller runs with 8MHz crystal oscillator.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | // Remote controlled DC motor with PIC16F877A CCS PIC C code // TV (RC-5 protocol) IR remote control is used #include <16F877A.h> #fuses HS,NOWDT,NOPROTECT,NOLVP #use delay(clock = 8000000) #use fast_io(B) #use fast_io(C) short toggle; unsigned int8 count, i, j, address, command; short remote_read(){ count = 0; // Check if the received signal uses RC5 protocol while((input(PIN_B0) == 0) && (count < 20)){ count++; delay_us(50);} if( (count > 20) || (count < 14)) // Signal doesn't use RC5 protocol return false; // Return count = 0; while((input(PIN_B0)) && (count < 20)){ count++; delay_us(50);} if( (count > 20) || (count < 14)) // Signal doesn't use RC5 protocol return false ; // Return count = 0; while((input(PIN_B0) == 0) && (count < 40)){ count++; delay_us(50);} if( (count > 40) || (count < 14)) // Signal doesn't use RC5 protocol return false ; // Return // End check (The received signal uses RC5 protocol) if(count > 30) delay_us(400); else delay_us(1300); output_high(PIN_B1); // Turn RB1 LED ON for(i = 0; i < 12; i++){ if(i == 0){ if(input(PIN_B0) == 1) toggle = 0; else toggle = 1; } else { if(i < 6){ //Read address bits if(input(PIN_B0) == 1) bit_clear(address, (5 - i)); //Clear bit (5-i) else bit_set(address, (5 - i)); //Set bit (5-i) } else { //Read command bits if(input(PIN_B0) == 1) bit_clear(command, (11 - i)); //Clear bit (11-i) else bit_set(command, (11 - i)); //Set bit (11-i) } } delay_us(1778); } address &= 0x1F; command &= 0x3F; return true; } void main(){ setup_adc_ports(NO_ANALOGS); // Configure AN pins as digital port_b_pullups(TRUE); // Enable PORTB pull-ups output_b(0); // PORTB initial state set_tris_b(1); // Configure RB0 pin as input output_c(0); // PORTC initial state set_tris_c(0); // Configure PORTC pins as outputs setup_timer_2(T2_DIV_BY_16, 250, 1); // Set PWM frequency to 500Hz delay_ms(100); // Wait 100ms while(TRUE){ output_low(PIN_B1); while(input(PIN_B0)); // Wait until RB0 pin falls if(remote_read()){ if((address == 0) && (command == 16) && (input(PIN_B3) == 0)){ output_b(0); // Both LEDs OFF setup_ccp1(CCP_OFF); // CCP1 OFF setup_ccp2(CCP_OFF); // CCP2 OFF output_c(0); // PORTC pins low delay_ms(100); // Wait 100ms setup_ccp1(CCP_PWM); // Configure CCP1 as PWM set_pwm1_duty(j); // Set pwm1 duty cycle output_high(PIN_B3); // RB3 LED ON if(j > 250) output_high(PIN_B2); // RB2 LED ON (speed is max) } if((address == 0) && (command == 17) && (input(PIN_B4) == 0)){ output_b(0); // Both LEDs OFF setup_ccp1(CCP_OFF); // CCP1 OFF setup_ccp2(CCP_OFF); // CCP2 OFF output_c(0); // PORTC pins low delay_ms(100); // Wait 100ms setup_ccp2(CCP_PWM); // Configure CCP2 as PWM set_pwm2_duty(j); // Set pwm1 duty cycle output_high(PIN_B4); // RB4 LED ON if(j > 250) output_high(PIN_B2); // RB2 LED ON (speed is max) } if((address == 0) && (command == 32) && (j < 251)){ j++; if(j > 250) output_high(PIN_B2); // RB2 LED ON if(input(PIN_B3)) set_pwm1_duty(j); // Set pwm1 duty cycle if(input(PIN_B4)) set_pwm2_duty(j); // Set pwm2 duty cycle } if((address == 0) && (command == 33) && (j > 0)){ j--; output_low(PIN_B2); // RB2 LED OFF if(input(PIN_B3)) set_pwm1_duty(j); // Set pwm1 duty cycle if(input(PIN_B4)) set_pwm2_duty(j); // Set pwm2 duty cycle } if((address == 0) && (command == 59)){ setup_ccp1(CCP_OFF); // CCP1 OFF setup_ccp2(CCP_OFF); // CCP2 OFF output_b(0); // Both LEDs OFF output_c(0); // PORTC pins low } } } } |
Remote controlled DC motor using PIC16F877A video:
The following video shows a hardware circuit of this project.
Discover more from Simple Circuit
Subscribe to get the latest posts sent to your email.