Brushless DC motor control with PIC16F887 microcontroller

This post shows how to control a sensorless brushless DC (BLDC) motor using PIC16F887 8-bit microcontroller, or let’s say how to build a DIY ESC (Electronic speed controller using PIC16F887).

Basically there are two types of brushless motors: sensored and sensorless. Sensored BLDC motors come with three hall effect sensors which are used to detect (know) the position of the rotor (where it is located) at any moment, that’s why they called sensored.
The second type is: sensorless BLDC motors. Sensorless BLDC motor has no sensor to detect the rotor position, it has only 3 wires for power (3-phase). The commutation of sensorless BLDC motor is based on the BEMF (Back Electromotive Force) produced in the stator windings.

The main advantage of the sensorless BLDC motor control is lower system cost and the main disadvantage is the motor must be moving at minimum rate to produce sufficient BEMF to be sensed.

How it works:
When the BLDC motor rotates, each winding (3 windings) generates BEMF opposes the main voltage. The 3 generated BEMF signals are 120° out of phase which is the same as the hall effect sensor signals. The figure below shows the relationship between the hall effect signals and the BEMF signals:

bldc hall sensor and bemf signals

As shown in the figure above, the BEMF signals are not synchronized with the hall effect sensor signals (phase shift of 30°). In every energizing sequence, two windings are energized (one connected to positive and the other to negative) and the third winding is left open (floating). The floating winding is used to detect the zero crossing, thus, the combination of all 3 zero cross over point are used to generate the energizing sequence. Totally we’ve 6 events:
Phase A zero crossing: from high to low and from low to high
Phase B zero crossing: from high to low and from low to high
Phase C zero crossing: from high to low and from low to high

How to detect the zero crossing:
The easiest way to detect the zero crossing events is by using comparators. The comparator has 3 main terminals: 2 inputs (positive and negative) and an output. Comparator output is logic high if the positive voltage is greater than the negative voltage, and logic low if the positive voltage is lower than the negative voltage.
Basically 3 comparators are needed for this project, connections are done as shown in the figure below (example for phase B). Each phase requires a similar circuit:

bldc bemf signal detection

The virtual natural point is the same for all the 3 comparators, it is generated using 3 resistors. When the BEMF generated in the floating (open) winding crosses the zero point towards positive side, the comparator output makes a transition from low-to-high. When the BEMF generated in the floating winding crosses the zero point towards negative side, the comparator output makes a transition from high-to-low. By having three such comparator circuits, one on each of the phases gives three digital signals corresponding to the BEMF signal in the windings. The combination of these three signals is used to derive the commutation sequence.

The PIC16F887 has two analog comparators, one of them is enough for this project. The one will be used is comparator 1.

Components Required:

  • PIC16F887 microcontroller – datasheet
  • Brushless DC motor
  • 6 x 06N03LA N-type mosfet (or equivalent)  – datasheet
  • 3 x IR2101 (or IR2101S) gate driver IC  – datasheet
  • 6 x 33k ohm resistor
  • 3 x 10k ohm resistor
  • 6 x 10 ohm resistor
  • 3 x IN4148 diode
  • 3 x 10uF capacitor
  • 3 x 2.2uF capacitor
  • 20 MHz crystal oscillator
  • 2 x 22pF ceramic capacitor
  • 10k ohm potentiometer
  • 12V source
  • 5V source
  • Breadboard
  • Jumper wires

As an addition we need:

  • CCS C compiler to compile the C code below
  • PIC programmer such as PICkit 3, PICkit 2 ……
  • MPLAB IPE software

Brushless DC motor control with PIC16F887 microcontroller circuit:
Project circuit schematic diagram is shown below.

PIC16F887 Brushless dc motor controller DIY ESC circuit

Note that all grounded terminals are connected together.

As known the brushless motors are 3-phase motors. In the circuit diagram above the 3 phases are named: Phase A, Phase B and Phase C.

In this project we need two power sources, the first one with 5V and used to power the microcontroller. The other one with 12V which is used to power the three-phase bridge and therefore the BLDC motor.

The first three 33k (connected to motor phases) and the three 10k resistors are used as voltage dividers, because we can not supply the microcontroller with 12V, the other three 33k resistors generate the virtual natural point. The virtual natural point is connected to pin RA3 (#5) which is comparator 1 positive input.

PIC16F887 microcontroller has two analog comparators, one of them is enough for this project, so I chose comparator 1. The positive input of this comparator is C1IN+ (pin #5) and the negative input can be C12IN0- (pin #2), C12IN1- (pin #3), C12IN2- (pin #36) or C12IN3- (pin #34). Therefore, I connected the virtual natural point to the positive pin of the analog comparator C1IN+ (pin #5), phase A BEMF to C12IN0- (pin #2), C12IN1- (pin #3) and phase C BEMF to C12IN2- (pin #36). Each time the comparator compares the virtual point with the BEMF of one phase (done in the software). This minimizes the hardware needed and simplifies the circuit.

The IR2101 chips are used to control high side and low side mosfets of each phase. The switching between the high side and the low side is done according to the control lines HIN and LIN. The figure below shows input and output timing diagram:

IR2101 input output timing diagram

The HIN lines of the three IR2101 are connected to pins: P1D (RD7), P1C (RD6) and P1B (RD5) respectively for phase A, phase B and phase C, whereas the LIN lines are connected to pins: RD4, RD3 and RD2.
The PIC16F887 has one CCP module (Capture/Compare/PWM module) and one ECCP module (Enhanced CCP module). With the ECCP module we can generate 4 PWM signals with the same frequency and controlled by one duty cycle (we need 3 PWM signals). In this project I applied 3 PWM signals to high side mosfets only (one PWM active at a time).

The speed of the BLDC motor is controlled by a potentiometer connected to analog channel AN4 (pin #7).

The PIC16F887 runs with 20MHz crystal oscillator (5 MIPS), MCLR pin function is disabled.

Brushless DC motor control with PIC16F887 microcontroller C code:
The C code was tested with CCS C compiler version 5.051. The compiler may give a warning, it is not a problem at all, just ignore it!

Timer2 module is configured to give a PWM signal with frequency of 19.53 KHz and resolution of 10 bits. The configuration line is:
setup_timer_2(T2_DIV_BY_1, 255, 1);
where Timer2 prescaler = 1, preload (PR2) = 255
PWM frequency and resolution can be calculated using the functions below (Fosc = 20 MHz):
PWM_freqency = Fosc/{[(PR2) + 1] * 4 * (TMR2 Prescaler Value)} = 19.53 KHz
Resolution = log[4(PR2 + 1)]/log(2) = 10 bits

Full CCS C code is below.

Finally this video shows a simple hardware circuit of the project:

Related Projects:
Sensorless BLDC motor control with PIC microcontroller and mikroC
Brushless DC motor controller using Arduino and IR2101

References:
Microchip AN970 document
https://www.microchip.com/

21 thoughts on “Brushless DC motor control with PIC16F887 microcontroller”

  1. Hi I’ve working this for weeks. Completed the hardware part, but I get the following error while executing the CCS code.

    Error 128 “C:\Program Files (x86)\PICC\Drivers\stdint.h” Line 19(9,15): A #DEVICE required before this line.

    These are the starting few lines of the stdint.h file that got opened.

    ///////////////////////////////////////////////////////////////////////////
    //// ////
    //// stdint.h ////
    //// ////
    //// Standard integer definitions. ////
    //// ////
    ///////////////////////////////////////////////////////////////////////////
    //// (C) Copyright 1996,2008 Custom Computer Services ////
    //// This source code may only be used by licensed users of the CCS C ////
    //// compiler. This source code may only be distributed to other ////
    //// licensed users of the CCS C compiler. No other use, reproduction ////
    //// or distribution is permitted without written permission. ////
    //// Derivative programs created using this software in object code ////
    //// form are not restricted in any way. ////
    ///////////////////////////////////////////////////////////////////////////

    #ifndef _STDINT

    #define _STDINT

    //////////// exact width

    typedef signed int8 int8_t;
    typedef unsigned int8 uint8_t;
    typedef signed int16 int16_t;
    typedef unsigned int16 uint16_t;
    typedef signed int32 int32_t;
    typedef unsigned int32 uint32_t;

    Kindly help on this issue. I’m really in need of ot

  2. what might be the reason for the motor not to be running even though the circuit is connected correctly? I gave changed the MOSFETs to IRFZ44N. with 5V for MCU and 12V for the MOSFETs.

  3. Prof. Radha Rman Pal

    Please give the required C program if we want to use the MCU PIC16F877A, instead of PIC16F887. This is because PIC16F887 is not available in the market, but PIC16F877F is readily available.

  4. Thank you for your prompt response, much appreciated!

    I have indeed experimented with different values with no good results.
    Your circuit voltage devider values are: R1(33K), R2(10K).
    I have been attempting the followings values R1(22K), R2(1K, 2.7K, or 10K).
    Can you please advise/recommend/confirm the accurate voltage divider values I can use with motor voltage at 20V, 42V and 400V?

  5. Greeting, I have followed your desing and it runs well when supplying both the uC 5V, the driver circuit with 12V nad Motorvolatage with 12V, but if I only increase the Motor voltage to 20V or more then the motor does not run well, no speed change, andit it stops running after few seconds, please advise (is the problem with ground/earth?).

      1. Thank you for your prompt response, much appreciated!

        I have indeed experimented with different values with no good results.
        Your circuit voltage devider values are: R1(33K), R2(10K).
        I have been attempting the followings values R1(22K), R2(1K, 2.7K, or 10K).
        Can you please advise/recommend/confirm the accurate voltage divider values I can use with motor voltage at 20V, 42V and 400V?

    1. el sistema no funciona porque el divisor de las resistencias está pensado para 12 V. deberías modificar los divisores (33k-10k)

  6. I want to use hall sensors in this circuit for that we need to change the as well can you guide us in this ?
    I’m looking forward to hearing from you

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top