Engineering Blog — TutorialWhatsApp: +86 18268661068
Maker Tutorial

How to Control a BLDC Motor with Arduino — Step-by-Step Tutorial.

A BLDC motor cannot be driven directly from an Arduino — the windings need a six-MOSFET inverter to switch tens of amps. The right approach is to use a dedicated BLDC controller (like Shenghe's BLD22010) and have Arduino send a speed setpoint over 0–5V analog or PWM. This tutorial walks through the wiring, code, and the upgrade path to RS485 / Modbus when the project moves from prototype to production.

What You'll Need

  • Arduino Uno or Nano (any 5V Arduino board works)
  • BLDC motor — 12V or 24V for benchtop testing (Shenghe 57BL or 80BL frame is a good starting point)
  • BLDC motor controller — Shenghe BLD22010 covers 24V/36V/48V and accepts 0–5V analog and PWM directly
  • Bench DC power supply matching motor voltage (with adjustable current limit)
  • Jumper wires, 10kΩ potentiometer (optional, for variable throttle)
  • Multimeter (always good to have)

Step 1 — Pick a Controller That Accepts Arduino-Friendly Inputs

Don't try to drive a BLDC motor's three phases directly from Arduino — Arduino's I/O can't switch the tens of amps the windings draw, and there's no Hall-sensor decoding logic on Arduino either. Instead, use a dedicated BLDC controller. Shenghe's BLD22010 covers 24V / 36V / 48V battery and PSU systems, accepts 0–5V analog speed (the easiest case for Arduino), and exposes FR (forward/reverse) and EN (enable) digital pins that map directly to Arduino digital outputs.

Step 2 — Wire the Motor to the Controller

  • Motor U / V / W phases → Controller U / V / W terminals
  • Motor Hall +5V → Controller Hall +5V
  • Motor Hall GND → Controller Hall GND
  • Motor HU / HV / HW → Controller HU / HV / HW
  • Bench DC supply (+) → Controller V+
  • Bench DC supply (–) → Controller GND

If U / V / W phases are reversed (motor turns wrong way), swap any two of the three motor wires and any two corresponding Hall wires — both have to match.

Step 3 — Wire Arduino to the Controller

  • Arduino GND → Controller signal GND (critical — must share ground)
  • Arduino digital pin 9 → Controller SV (speed setpoint, accepts 0–5V analog or 0–100% PWM)
  • Arduino digital pin 7 → Controller FR (forward when LOW, reverse when HIGH)
  • Arduino digital pin 6 → Controller EN (enable when HIGH, coast when LOW)
  • Optional: Arduino A0 → 10kΩ potentiometer wiper (potentiometer ends to Arduino +5V and GND)

Step 4 — The Simplest Sketch

// Basic BLDC speed control with Arduino + Shenghe BLD22010
const int PIN_SV = 9;   // PWM out → controller SV
const int PIN_FR = 7;   // direction
const int PIN_EN = 6;   // enable
const int PIN_POT = A0; // 10kΩ pot wiper

void setup() {
  pinMode(PIN_SV, OUTPUT);
  pinMode(PIN_FR, OUTPUT);
  pinMode(PIN_EN, OUTPUT);
  digitalWrite(PIN_FR, LOW);   // forward
  digitalWrite(PIN_EN, HIGH);  // enable
}

void loop() {
  int pot = analogRead(PIN_POT);              // 0–1023
  int speed = map(pot, 0, 1023, 0, 255);      // 0–255 PWM
  analogWrite(PIN_SV, speed);
  delay(20);
}

Upload, then turn the potentiometer slowly. The motor should ramp from stop to full speed.

Step 5 — Test at Low Speed First

Power up the bench supply with current limit set to roughly 2–3A above the motor's expected no-load current (a 100W 24V motor draws ~0.5A at no-load, so set ~3A limit). Start with the potentiometer at minimum. Slowly raise it to confirm the motor turns smoothly, no hum, no controller fault LED. Reverse direction by setting digitalWrite(PIN_FR, HIGH).

Step 6 — Read Motor Speed Back (Optional)

The BLD22010 exposes one Hall pulse output (labeled M or PG depending on revision). One pulse per electrical revolution. Connect it to Arduino pin 2 (interrupt-capable) and count pulses:

volatile unsigned long pulse_count = 0;

void setup() {
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), countPulse, RISING);
  Serial.begin(9600);
}

void countPulse() { pulse_count++; }

void loop() {
  static unsigned long last = 0;
  if (millis() - last > 1000) {
    noInterrupts();
    unsigned long pps = pulse_count;
    pulse_count = 0;
    interrupts();
    int rpm = (pps * 60) / (4 * 6);  // 4 pole pairs, 6 sectors
    Serial.println(rpm);
    last = millis();
  }
}

Step 7 — Tune PWM Frequency to Kill the Whine

Arduino's default PWM on pin 9 runs at ~490Hz — squarely in human hearing range, so the motor windings vibrate audibly. To raise PWM to 20kHz (above hearing) on Arduino Uno, set the Timer1 prescaler:

// In setup(), after pinMode(PIN_SV, OUTPUT):
TCCR1B = (TCCR1B & 0xF8) | 0x01;  // Timer1 prescaler = 1, PWM ~31kHz
// pin 9 and 10 are now ~31kHz

The controller filters PWM internally, so high frequency is fine.

Step 8 — Step Up to RS485 / Modbus for Production

Arduino + 0–5V analog is great for prototyping. For production AGV, conveyor or factory builds, switch to RS485 / Modbus. RS485 is differential and noise-immune over 100+ meter cable runs — the right choice when the controller is in a cabinet and the host computer is across the factory. Hardware: a MAX485 transceiver module on Arduino (or jump to ESP32 / STM32 with built-in UART). Software: any ModbusRTU library — set the controller's slave address and bus speed in its config registers.

Production builds typically use a PLC or industrial controller talking RS485 to one or more BLDC controllers, with Arduino reserved for benchtop prototyping. See our 24V BLDC controller page for the RS485 register map and integration with Siemens / Mitsubishi / Allen-Bradley PLCs.

Common Issues

  • Motor turns wrong way: swap any two of the three motor phases and any two corresponding Hall wires. Both must match.
  • Motor hums but doesn't turn: Hall sensor wiring problem. Check HU/HV/HW are correctly mapped.
  • Controller fault LED on: usually overcurrent — increase bench supply current limit, or motor/load is jammed.
  • analogWrite() does nothing visible: check that EN pin is HIGH and FR is set. Both must be valid before SV does anything.
  • Speed jitters: 0–5V analog with long wires picks up noise. Either shorten the analog wire, switch to PWM at high frequency, or move to RS485.

Further Reading

Sourcing the Hardware

Need a BLDC Motor + Controller for Your Arduino Project?

Our BLD22010 + BLDC motor kits ship as matched, tested sets — pre-wired Hall cable and ready-to-deploy PID parameters. Tell us your motor voltage, power and quantity for a benchtop or production build.

WhatsApp
Get a BLDC controller + motor kit — quote in 24 hours Get Quote Browse Controllers