The easiest way to control a sensorless BLDC motor is through an ESC (Electronic Speed Controller). This topic shows how to drive a BLDC motor using ESC and Microchip PIC16F887 microcontroller.
Topics related to this post:
PIC16F887 Timers and Interrupts
The basic components of the ESC is a microcontroller and at least 6 mosfets. It also consists of other components such as voltage regulator, capacitors, resistors ….. The controlling of the ESC is similar to the controlling of servo motor, the ESC controls the speed of the BLDC motor while the servo motor controller controls the position (moving angle) of a DC motor.
To drive the ESC or servo motor we’ve to provide a repeated 50Hz PWM signal (20 ms period) with a duty cycle between 5 and 10% (1 ms to 2 ms pulse). The following figure shows the PWM signal needed by the ESC:
- PIC16F887 microcontroller
- ESC (Electronic Speed Controller) __ I used 30A ESC
- Brushless DC motor __ I used 2210 – 1000KV BLDC motor
- 10K ohm potentiometer
- Battery (or high power 12V source)
- Jumper wires
Sensorless brushless DC motor drive with an ESC and PIC16F887 circuit:
The two thick wires black and red are the ESC input power which normally comes from a battery (11.1V, 14.8V ….). There are also 3 thick wires which are black, red and brown (in my ESC white). The black and red are 5V voltage source which can be used to supply the microcontroller circuit as what I have done, or the microcontroller circuit can be supplied from an other source and in this case the red wire will not be used. The brown wire is the PWM signal wire and this wire is used to send PWM pulses from the microcontroller to the ESC through pin RD0.
In my hardware circuit I replaced the battery with 12V 10A DC voltage source.
The potentiometer which is connected to RA0 is used to control the speed of the BLDC motor.
In this example the PIC16F887 uses its internal oscillator and MCLR pin function is disabled.
Sensorless brushless DC motor drive with an ESC and PIC16F887 CCS C code:
Timer1 module is used to measure pulses width, it’s configured to increment every 1 us.
/* Sensorless brushless DC motor drive with an ESC and PIC16F887 CCS PIC C code
PIC16F887 runs with 8MHz internal oscillator
#device ADC = 10
#fuses NOMCLR, NOBROWNOUT, NOLVP, INTRC_IO
#use delay(clock = 8MHz)
setup_oscillator(OSC_8MHZ); // Set internal oscillator to 8MHz
set_tris_d(0); // Configure PORTD pins as outputs
setup_adc(ADC_CLOCK_INTERNAL); // ADC module uses its internal oscillator
setup_adc_ports(sAN0); // Configure AN0 as analog input pin
setup_timer_1(T1_INTERNAL | T1_DIV_BY_2); // Setup Timer1 module: internal source + 2 prescaler
set_timer1(0); // Set Timer1 value to 0
i = read_adc(); // Read analog value from channel 0 and store it in 'i'
if(i > 1000)
i = 1000;
i = i + 1000;
while(get_timer1() < i);
while(get_timer1() < 19999);