Friday, August 4, 2017

Sensorless brushless DC motor drive with an ESC and PIC16F887


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 an ESC and 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:
Pulses for servo motor and ESC
Hardware Required:
  • PIC16F887 microcontroller
  • ESC (Electronic Speed Controller) __ I used 30A ESC
  • Brushless DC motor __ I used 2210 - 1000KV BLDC motor
  • 10K ohm potentiometer
  • Breadboard
  • Battery (or high power 12V source)
  • Jumper wires
Sensorless brushless DC motor drive with an ESC and PIC16F887 circuit:
Brushless DC motor control using 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
   http://ccspicc.blogspot.com/
   electronnote@gmail.com
*/

#include <16F887.h>
#device ADC = 10
#fuses NOMCLR, NOBROWNOUT, NOLVP, INTRC_IO
#use delay(clock = 8MHz)
#use fast_io(D)

int16 i;
void main(){
  setup_oscillator(OSC_8MHZ);                    // Set internal oscillator to 8MHz
  output_d(0);
  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
  set_adc_channel(0);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_2);      // Setup Timer1 module: internal source + 2 prescaler
  while(TRUE){
    set_timer1(0);                               // Set Timer1 value to 0
    output_high(PIN_D0);
    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);
    output_low(PIN_D0);
    while(get_timer1() < 19999);
  }
}
Example video: