Problems starting a BLDC motor with a homemade driver

Hello everyone, I’ll just say that I’m using Google Translate to write this text. I apologize in advance for any distorted words.

I’m trying to run a MT5208 340kV BLDC motor on an Arduino NANO microcontroller using a homemade IR2401S driver (The driver is powered separately from the motor). I assembled it according to the schematic below:

I’m using the code from the Simple FOC example to move the motor between 1 radian and -1 radian every second. If I specify open-loop control in the code, i.e., “motor.controller = MotionControlType::angle_openloop,” the motor does indeed rotate at the specified angles every second, but some vibration is felt (the motor is fully functional and operates via an ESC controller). Here’s code:

#include <SimpleFOC.h>

BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);


void setup() {

  driver.init();
  motor.linkDriver(&driver);
  motor.controller = MotionControlType::angle_openloop;
  motor.PID_velocity.P = 0.2;
  motor.PID_velocity.I = 20;
  motor.PID_velocity.D = 0.001;
  motor.PID_velocity.output_ramp = 1000;
  motor.LPF_velocity.Tf = 0.01;
  motor.P_angle.P = 20;
  motor.velocity_limit = 4;
  motor.voltage_limit = 10;
  Serial.begin(115200);
  motor.useMonitoring(Serial);
  motor.init();
  Serial.println("Motor ready.");
  _delay(1000);
}

float target_angle = 1;
long timestamp_us = _micros();

void loop() {

  if(_micros() - timestamp_us > 1e6) {
      timestamp_us = _micros();
      target_angle = -target_angle;   
  }

  motor.loopFOC();
  motor.move(target_angle);
}

But if I simply specify “motor.controller = MotionControlType::angle” and connect the as5600 magnetic encoder, the motor starts to jerk violently, but still turns at the specified angles. (The encoder is also working; for one motor rotation, the encoder shows 6.28 radians.) Here’s the code with the encoder connected:

#include <SimpleFOC.h>

BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);
MagneticSensorI2C encoder = MagneticSensorI2C(AS5600_I2C);

void setup() {
  encoder.init();
  motor.linkSensor(&encoder);
  driver.init();
  motor.linkDriver(&driver);
  motor.controller = MotionControlType::angle;
  motor.PID_velocity.P = 0.2;
  motor.PID_velocity.I = 20;
  motor.PID_velocity.D = 0.001;
  motor.PID_velocity.output_ramp = 1000;
  motor.LPF_velocity.Tf = 0.01;
  motor.P_angle.P = 20;
  motor.velocity_limit = 4;
  motor.voltage_limit = 10;
  Serial.begin(115200);
  motor.useMonitoring(Serial);
  motor.init();
  motor.initFOC();
  Serial.println("Motor ready.");
  _delay(1000);
}

float target_angle = 1;
long timestamp_us = _micros();

void loop() {

  if (_micros() - timestamp_us > 1e6) {
    timestamp_us = _micros();
    target_angle = -target_angle;
  }

  motor.loopFOC();
  motor.move(target_angle);
}

Unfortunately, I can’t provide the driver output data via an oscilloscope, as I don’t have one. Please help me figure out what I’m doing wrong.

Try motor.voltage_limit = 1.0; or less. That motor only has 83 milliohms resistance, so with 10V you may be getting over 100 amps. I’m surprised nothing exploded.

Hi @Vortex , welcome to SimpleFOC!

please don’t go directly from open loop to angle mode…

First, please try the closed loop torque voltage mode. This needs only your sensor to work, and does not use any PIDs.

Once torque-voltage mode is working, please try velocity mode next. For this you will need to tune the PID for velocity.

Once velocity mode is working well, angle mode is next. That should not be hard after the lower level modes are working well.

Hi! I’ll assume you’re Russian, because I definitely remember seeing exactly the same schematic somewhere :)I’ve got the exact same motors and the exact same wiring.Just so you know — all my work was done through vibe-coding with ChatGPT.I had exactly the same problem you described above, and I struggled with it for about a month.I’d like to share my code, which should help you — because in my case, the issue was specifically in the code.

The problem was specifically caused by too high a voltage being supplied to the motor windings, which created noise.
In my case, during testing with ChatGPT, I ran into another issue — the code was putting a heavy load on the Arduino, which made it constantly restart.
The code I’m sharing here is the most optimal one I’ve ever received.

P.S. To make the gearbox spin, just set the voltage a bit higher :wink:


Привет! Я предполагаю, что вы русский, так как я знаю, где видел похожую схему. У меня такие же моторы и такая же схема. Хочу сразу сказать, что я занимаюсь вайбкодином с помощью ChatGPT. У меня была похожая проблема, и я боролся с ней около месяца. Я хочу поделиться своим кодом, который может вам помочь, так как проблема была именно в нём.

Проблема заключалась в слишком большом напряжении, которое подавалось на обмотки двигателя, что создавало шум. В процессе тестов через ChatGPT я столкнулся с проблемой: код создавал слишком большую нагрузку на Ардуино, из-за чего он постоянно перезагружался. Код, который я прилагаю, является оптимальным среди всех, что я получал.

P.S. Чтобы редуктор проработал, увеличьте напряжение :wink:

// UNO + SimpleFOC — Fixed speed, NO SERIAL (diagnostic build)
// 3PWM: U=9, V=10, W=11, EN=8 ; Sensor: AS5600 (I2C)

#include <SimpleFOC.h>

static const int   PP        = 11;
static const float V_SUPPLY  = 12.0;
static const float V_LIMIT   = 0.9;     // super-safe
static const float W_SET     = 22.0f;   // rad/s (\~210 RPM)
#define  SENSOR_DIR_CCW      1

const int U=9, V=10, W=11, EN=8;

MagneticSensorI2C sensor(AS5600_I2C);
BLDCMotor        motor(PP);
BLDCDriver3PWM   driver(U,V,W,EN);

void setup() {
pinMode(EN, OUTPUT);
digitalWrite(EN, HIGH);

Wire.begin();
Wire.setClock(100000);     // robust for AS5600

sensor.init();

driver.voltage_power_supply = V_SUPPLY;
driver.voltage_limit        = V_LIMIT;
driver.init();

motor.linkSensor(&sensor);
motor.linkDriver(&driver);
motor.foc_modulation     = FOCModulationType::SinePWM;
motor.torque_controller  = TorqueControlType::voltage;
motor.controller         = MotionControlType::velocity;
motor.sensor_direction   = SENSOR_DIR_CCW ? Direction::CCW : Direction::CW;
motor.voltage_limit      = V_LIMIT;
motor.velocity_limit     = 140.0f;

motor.voltage_sensor_align   = 0.25f;
motor.PID_velocity.P         = 0.12f;
motor.PID_velocity.I         = 0.80f;
motor.PID_velocity.D         = 0.00f;
motor.PID_velocity.output_ramp = 30.0f;
motor.PID_velocity.limit     = V_LIMIT;
motor.LPF_velocity.Tf        = 0.06f;

motor.init();
motor.initFOC();
delay(100);
}

static float ramp(float cur, float tgt, float step){
if (cur < tgt) return min(cur + step, tgt);
if (cur > tgt) return max(cur - step, tgt);
return cur;
}

void loop() {
motor.loopFOC();

static float tgt = 0.0f;
tgt = ramp(tgt, W_SET, 0.5f);
motor.move(tgt);
}