Project showcase
BLDC Brushless DC Motor and Slipring

BLDC Brushless DC Motor and Slipring © GPL3+

Code for driving a BLDC motor and adjusting its speed using a pot. This photo shows wires to a slipring in the hollow shaft of a BLDC motor.

  • 996 views
  • 1 comment
  • 6 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
L298N Stepper Motor Controller Module
×1
BLDC Brushless DC motor
×1
LiPO or NiMH battery, 2 cell (7.2V) or 3 cell (11.1V) tested
×1
Switch DPDT
×1
09939 01
Rotary potentiometer (generic)
×3

About this project

I ordered a motor with a hollow shaft because I wanted to use it with a slipring so I could drive a stepper motor, similar to that used in a commercial DSLR camera gimbal.

The motor turned out to be a BLDC motor with a 12N14P configuration. What did that even mean? Couldn't find any suitable Arduino code, so had to figure it out myself.

(Refer http://www.aerodesign.de/peter/2001/LRK350/index_eng.html and http://www.aerodesign.de/peter/2001/LRK350/Paper_from%20_Wroclaw.html) for how a BLDC motor works.

With regards to 12N14P: P denotes number of stator magnets, N denotes number of rotor poles. See https://en.wikipedia.org/wiki/Outrunner.

BLDC speed is controlled by a pot connected to A0.

The three wires from the BLDC can be connected to any of the four L298N output screw terminals labelled MOTOR A and MOTOR B. Unfortunately the LEDs on Jaycar's XC-4492 L298N stepper Motor Controller Module are reversed, so you'll need to test which screw terminal matches which LED.

The pot controls the speed of the BLDC motor by varying the length of the pulse to each coil; The higher the resistance of the pot the more time must pass before the next coil is energised.

The three wires of the BLDC can be held high or low. In binary this would be eight states:

000

001

010

011

100

101

110

111

In the first state (000) none of the coils are energised, so the BLDC is off.

In the last state (111) all of the coils are energised, which would lock the BLDC on with a wasteful drain of power. This state is not used.

The sequence of energising each coil was found through a process of elimination. The following sequence was found to work:

010 2

011 3

001 1

101 5

100 4

110 6

Not intuitive, but it works.

Code

BLDC Brushless DC motor code V2Arduino
This code is simply to drive a BLDC using an L298 driver board and an Arduino. The sketch after this sketch is for driving a stepper motor at the same time as the BLDC.

V1 code pulsed once and then waited for interval before sending next pulse, whereas this improved code keeps pulsing the same phase until the interval is past. Also, input from pot connected to A5, now varies BLDC motor speed. Removed 'step' variable by reversing order in which time interval is tested. Serial.print is commented out to improve smoothness of motion.
/*
  DC Brushless Motor (BLDC)
  Appears to be internally wired as though 3-phase stepper motor
  Tested with funtobuyonline GBM6324-180T

  Parts required:
  - Arduino (If using Chinese Nano then install CH340 driver and use ATmega328P (Old Bootloader)
  - L298N Stepper Motor Controller Module (Jaycar XC-4492)(Nb. LEDs L3 and L3 are reversed with respect to Motor B output pins)
  - 2 or 3 cell LiPO or NiMH battery
  - Switch in series with battery

  Michael Barr January 2019
*/

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;
unsigned long difference =0;
int potA5;  
// Define pins numbers
const int tri1 = 3;
const int tri2 = 4;
const int tri3 = 6;

void setup() {
  // initialize the serial port:
  Serial.begin(9600);
  
  // declare MOTOR A and MOTOR B pins as outputs
  pinMode(tri1, OUTPUT);
  pinMode(tri2, OUTPUT);
  pinMode(tri3, OUTPUT);
  
}

void loop() {
    potA5= analogRead(A5); //Read input from analog pin potA5 and store in potA5
    potA5= map(potA5, 0, 1023,30,100); //map potA5 to minimum and maximum
    // Serial.print("potA5:");
    // Serial.print(potA5);
    unsigned long currentMillis = millis(); 
    difference = currentMillis - previousMillis;
    // Serial.print(" difference = ");
    // Serial.print(difference);

    if (difference >= potA5 * 6) {
    previousMillis = currentMillis;
    // Serial.println(" 6");
    } 
      else if (difference >= potA5 * 5) {
      digitalWrite(tri1, HIGH);
      digitalWrite(tri2, HIGH);
      digitalWrite(tri3, LOW);
      // Serial.println(" 5");
      }
        else if (difference >= potA5 * 4) {
        digitalWrite(tri1, HIGH);
        digitalWrite(tri2, LOW);
        digitalWrite(tri3, LOW);
        // Serial.println(" 4");
        }
          else if (difference >= potA5 * 3) {
          digitalWrite(tri1, HIGH);
          digitalWrite(tri2, LOW);
          digitalWrite(tri3, HIGH);
          // Serial.println(" 3");
          }
            else if (difference >= potA5 * 2) {
            digitalWrite(tri1, LOW);
            digitalWrite(tri2, LOW);
            digitalWrite(tri3, HIGH);
            // Serial.println(" 2");
            }
              else if (difference >= potA5) {
              digitalWrite(tri1, LOW);
              digitalWrite(tri2, HIGH);
              digitalWrite(tri3, HIGH);
              // Serial.println(" 1");
              }
                else {
                digitalWrite(tri1, LOW);
                digitalWrite(tri2, HIGH);
                digitalWrite(tri3, LOW);
                // Serial.println(" 0");
                }
}
BLDC Brushless DC motor code V2 + stepper motor codeArduino
This code drives both a BLDC and a stepper motor at the same time. Three potentiometers are used to control the speed of both motors and the position of the stepper.

A Protoneer Arduino CNC Shield V3 with Pololu A4988 Stepper Motor Driver Carrier fitted, to drive the stepper motor.
An L298N Stepper Motor Controller Module is used to drive BLDC.
/*
  Derived from non-blocking mode Stepper Driver example by Laurentiu Badea
  
  Parts required:
  - Arduino Uno
  - L298N Stepper Motor Controller Module, to drive BLDC. (Jaycar XC-4492)(Nb. LEDs L3 and L3 are reversed with respect to Motor B output pins)
  - Protoneer Arduino CNC Shield V3 with Pololu A4988 Stepper Motor Driver Carrier fitted, to drive stepper motor.
  - DC Brushless Motor (BLDC) (funtobuyonline GBM6324-180T appears to be internally wired as though 3-phase stepper motor).
    (Refer http://www.aerodesign.de/peter/2001/LRK350/index_eng.html and http://www.aerodesign.de/peter/2001/LRK350/Paper_from%20_Wroclaw.html)
  - 4 wire stepper motor (eg 12V NEMA 17).
  - 2 or 3 cell LiPO or NiMH battery.
  - Switch in series with battery.
  - Pot delay on A5 because A0 is reserved by CNC Shield. Used for speed control of BLDC motor
  - Pot delay on A4 connected to pot mounted on stepper motor to provide position feedback.
    When the brush of the pot wipes past the extremes of the variable resistor the voltage will float, so values selected for this pot must be much higher than 0.
  - Pot delay on A3 controls speed of rotation of the stepper motor
  
  Michael Barr in January 2019
 */
 
#include <Arduino.h>      // Required to drive stepper motor

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 200
#define RPM 10
#define MICROSTEPS 1  // Microstepping mode. If you hardwired it to save pins, set to the same value here.
#define DIR 5
#define STEP 2
#define ENABLE 8 // optional (just delete ENABLE from everywhere if not used)

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillisA3 = 0;        // will store last time stepper motor was at extreme end of its arc
unsigned long previousMillisBLDC0 = 0;        // stores when BLDC moved to phase 0

int   potA5 = 50;
unsigned long difference =0;
const int highPotA5 = 100;
// Defines pins numbers. Wire BLDC to pins on CNC shield which are not used because not using Y and Z motors
const int BLDC1 = 3; // pin labelled Y STEP
const int BLDC2 = 4; // pin labelled Y DIR
const int BLDC3 = 6; // pin labelled Z STEP

int potA3; // Defines variables
int potA4,directionLinkage2; // Defines variables

/*
 * Choose one of the sections below that match your board
#include "DRV8834.h"
#define M0 10
#define M1 11
DRV8834 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1);
*/
#include "A4988.h"
#define MS1 10
#define MS2 11
#define MS3 12
A4988 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, MS1, MS2, MS3);

// #include "DRV8825.h"
// #define MODE0 10
// #define MODE1 11
// #define MODE2 12
// DRV8825 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, MODE0, MODE1, MODE2);

// #include "DRV8880.h"
// #define M0 10
// #define M1 11
// #define TRQ0 6
// #define TRQ1 7
// DRV8880 stepper(MOTORS_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);

void setup() {
    Serial.begin(115200);
    // declare the BLDC pins as outputs
    pinMode(BLDC1, OUTPUT);
    pinMode(BLDC2, OUTPUT);
    pinMode(BLDC3, OUTPUT);

    stepper.begin(RPM, MICROSTEPS);
    stepper.enable();
    // set current level (for DRV8880 only). Valid percent values are 25, 50, 75 or 100.
    // stepper.setCurrent(100);
    // Serial.println("START");
}

void loop() {
    rotateStepper();  // Rotate 4 wire stepper motor
    rotateBLDC();     // Rotate 3 wire BLDC motor
    // Serial.println();
  }

// Function for rotating stepper motor
void  rotateStepper(){
    // Linkage 2 stepper motor speed
    int potA3 = analogRead(A3); // Reads the potentiometer
    potA3 = map(potA3,0,1023,5,360); // Converts the read values of the potentiometer from 0 to 1023 into an angle (0 to 360 degrees )
    unsigned long currentMillisA3 = millis(); // Get current time

    // Rotate stepper motor until pot is rotated 70 degrees and then rotate back to 0 degrees
    int potA4 = analogRead(A4); // Reads the potentiometer
    potA4 = map(potA4,0,1023,0,360); // Converts the read values of the potentiometer from 0 to 1023 into an angle (0 to 360 degrees )

    // The value selected here must be substantially above zero, as immediately less than zero is 360, which confuses the motor and me
    if (potA4 <=80) {
      // Serial.print(" potA4 <=80"); // Pot angled to side
      directionLinkage2 = 0;     
      }
        else if (potA4 >=185) { // Pot angled to other side
          // Serial.print(" potA4 >=185");
          directionLinkage2 = 1;
        }
                
    if (directionLinkage2 == 0 && currentMillisA3 - previousMillisA3 >= potA3)  {
        // Serial.print(" rotating out");
        stepper.rotate(2);
        previousMillisA3 = currentMillisA3;
       }
        else if (directionLinkage2 == 1 && currentMillisA3 - previousMillisA3 >= potA3)  {
           // Serial.print(" rotating back");
           stepper.rotate(-2);
           previousMillisA3 = currentMillisA3;
          }
}

// Function for rotating BLDC motor
void rotateBLDC() {
    potA5= analogRead(A5); //Read input from analog pin potA5 and store in potA5
    potA5= map(potA5, 0, 1023,30,110); //map potA5 to minimum and maximum
    // Serial.print("potA5:");
    // Serial.print(potA5);
    unsigned long currentMillis = millis(); 
    difference = currentMillis - previousMillisBLDC0;
    // Serial.print(" difference = ");
    // Serial.print(difference);

    if (potA5 >= highPotA5) { // Turn off BLDC when BLDC pot is near zero resistance          
    digitalWrite(BLDC1, LOW);
    digitalWrite(BLDC2, LOW);
    digitalWrite(BLDC3, LOW); 
    // Serial.println(" off");
    }
      else if (difference >= potA5 * 6) {
      previousMillisBLDC0 = currentMillis;
      // Serial.println(" 6");
      } 
        else if (difference >= potA5 * 5) {
        digitalWrite(BLDC1, HIGH);
        digitalWrite(BLDC2, HIGH);
        digitalWrite(BLDC3, LOW);
        // Serial.println(" 5");
        }
          else if (difference >= potA5 * 4) {
          digitalWrite(BLDC1, HIGH);
          digitalWrite(BLDC2, LOW);
          digitalWrite(BLDC3, LOW);
          // Serial.println(" 4");
          }
            else if (difference >= potA5 * 3) {
            digitalWrite(BLDC1, HIGH);
            digitalWrite(BLDC2, LOW);
            digitalWrite(BLDC3, HIGH);
            // Serial.println(" 3");
            }
              else if (difference >= potA5 * 2) {
              digitalWrite(BLDC1, LOW);
              digitalWrite(BLDC2, LOW);
              digitalWrite(BLDC3, HIGH);
              // Serial.println(" 2");
              }
                else if (difference >= potA5) {
                digitalWrite(BLDC1, LOW);
                digitalWrite(BLDC2, HIGH);
                digitalWrite(BLDC3, HIGH);
                // Serial.println(" 1");
                }
                  else {
                  digitalWrite(BLDC1, LOW);
                  digitalWrite(BLDC2, HIGH);
                  digitalWrite(BLDC3, LOW);
                  // Serial.println(" 0");
                  } 
}

Schematics

BLDC and L293
This layout is approximately right. I used a L298N Stepper Motor Controller Module (Jaycar XC-4492) instead of the genuine Arduino shield (which would have been easier, as it mounts directly on the Uno).
bldc_and_l293_TwUsQApivy.fzz

Comments

Author

Default
mbarraus
  • 1 project
  • 0 followers

Additional contributors

  • Non-blocking mode stepper driver example by Laurentiu Badea

Published on

December 22, 2018

Members who respect this project

DefaultDefaultPhoto

and 3 others

See similar projects
you might like

Similar projects you might like

Control the Speed of Brushless DC Motor Using Bluetooth

Project tutorial by mohitmehlawat

  • 3,986 views
  • 0 comments
  • 13 respects

DC Motor Controlling Library

Project tutorial by ambhatt

  • 4,588 views
  • 12 comments
  • 33 respects

Brushless Motor Wireless Control Using Arduino

Project showcase by Team Rootsaid

  • 4,235 views
  • 1 comment
  • 14 respects

Outboard Motor Throttle Controller

Project tutorial by Terry Towle

  • 5,532 views
  • 2 comments
  • 13 respects

Motor Controlled with Arduino

by Benjamin Larralde

  • 19,130 views
  • 20 comments
  • 52 respects
Add projectSign up / Login