B-G431B-ESC1 Current Control

Okay so i did some testing and here are my findings thus far:

LowsideCurrentSense doesn’t work only InlineCurrentSense, which is contrary to how the hardware configuration of the B-G431 module actually is?

Poor efficiency: when target is set to 0.5A for example, the driver seems to be able to maintain this target, but the velocity is very low for such a consumption. This also leads to excesive heating of the motor. Does the FOC loop also apply braking force to maintain the target value?

When velocity gets to above 200 the current sensing no longer works as expected (the current drawn seems to fall and the target is never reached)

I made the test using a 2830 7PP 1050KV motor with hall sensor feedback.

Yes, the pull request fixes that.

The FOC loop should not brake in this scenario. foc_current should be the most efficient way to drive the motor, if you have significantly better performance with other modes something must be off.

I’ve also had issues obtaining high speeds with SimpleFOC. With a 20pp motor and AS5600 sensor, the setup becomes quite inefficient above 100rad/s. With a 7pp motor I managed up to 500rad/s. But when I replaced the sensor with an AMT-103 I suddenly obtained speeds above 1000rad/s (until the sensor slipped and the board died). Clearly max speed is very dependent on sensor quality. Are you using the interrupt-based encoder? At high speeds the interrupts take a lot of cpu time, you might get better performance with stm32HWEncoder or by reducing the cpr of your encoder.

Also try modifying the voltage limit and pid parameters.



Absolutely! And also the following factors:

  • MCU speed & loop iteration speed. An I2C sensor will limit your iteration speed even on a fast MCU
  • Sensor latency - the encoders are better for this, and the hardware one is best, hardly any MCU overhead
  • Sensor accuracy - things like misplaced magnets for magnetic sensors can adversely affect the results
  • Motor pole count - much harder to drive high pole counts quickly
  • PID tuning and software limits
  • Physical limits: BEMF vs PSU voltage

I really do not understand the equations can you please explain in detail how the factor 64/7 is derived.
The equations

i really do not understand, in I1 resistor 2.2e3 is used, in the 2nd different equation used. Please help.

Hi, I got B-G431-ESC1, and tried the example for open_loop_velocity_example in Arduino IDE 2.0.3
But I got this error:
-none-eabi/bin/ld.exe: region `FLASH’ overflowed by 29916 bytes
How can I fix it?

When I change board to Arduino UNO or ESP32, it will compile with no problem, but I got b-g431_esc.
Can I choose a different board instead of generic STM32G4 series? Can I use Discovery insted of STM32G4?
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8); What number should I put in here?


What number should I put in here?

Could you please read this entire thread below? I believe you need a little more that that.


Thank you @Valentine :smiley:

Hi, I just got the first code uploaded from the Arduino IDE to B_G431.

I used the example code: B_G431B_ESC1 with some small modification.

I do not have encoder, so the line motor.linkSensor(&encoder) was commented out, and the driver.voltage_power_supply =6;

I can put in commands, but I do not see any movements of the motor?
From code:
// link the motor to the sensor
// motor.linkSensor(&encoder);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 6;

From monitor:

MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: No sensor.
MOT: Align current sense.
MOT: Success: 1
MOT: Ready.
Motor ready.
Set the target angle using serial terminal:
Target: 0.000

Any suggestions to make the motor turn?

Now I have tested this with a different B-G431B board and a different motor (Rase Star BR2205 KV=2600),but no luck.
I am not sure if encoder is needed?

Dear @Svein_Utne ,

Yes, with SimpleFOC you will currently need the encoder to do closed loop control.

Without an encoder or hall sensors / position sensor, you can try our open loop examples, but be careful to set the voltage limits low enough in your tests, so nothing gets damaged…

1 Like

Thank you for your help.
I am not sure what will be best to start with, but both open_loop_velocity and open_loop_position is almost identical.
In both I guess I need to make some modification so it will match the hardware I am using. I use B-G431B, and the motor got 7 pol pair, but I wonder if I should use BLDCDriver3PWM(9, 5, 6, 8);
or if I can use any of this?

For the B-G431-ESC1 you have to use 6-PWM control, so BLDCDriver6PWM.

I admit it is a little bit of work, but you kind of have to combine the examples - the B-G431 specific examples are what you need for the pins and general setup.

Then to do open loop control, you modify the controller

motor.controller = MotionControlType::velocity_openloop.

and comment out or remove the calls to motor.initFOC() and motor.loopFOC()

You always have to modify the pole pairs, driver.voltage_power_supply, driver.voltage_limit to match your setup.
In this control mode, the target value is a velocity in rad/s, so you can start with some low values like 1 or 2 rad/s when testing.

Thank you agein @runger. With this code it started to spin very slowly, and I could increase the speed with command T2 or T3. Very good. I feel that is a good start.

I use a 12 volt battery, but I have a controlbox where I can adjust the voltage and ampere. I started with 12V and 1 ampere, but increased it till 2 ampere to get a smuter run.
For 3 seconds I increased the max allowed current till 4 amp, G431 looked like it had no limit on current.
Maybe this is OK, but if I am doing something wrong here it would be nice to correct it before I burn the driver.


  • B-G431B-ESC1 position motion control example with encoder

#include <SimpleFOC.h>

// Motor instance
BLDCMotor motor = BLDCMotor(7);
LowsideCurrentSense currentSense = LowsideCurrentSense(0.003, -64.0/7.0, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT);

// encoder instance
//Encoder encoder = Encoder(A_HALL2, A_HALL3, 2048, A_HALL1);

// Interrupt routine intialisation
// channel A and B callbacks
//void doA(){encoder.handleA();}
//void doB(){encoder.handleB();}
//void doIndex(){encoder.handleIndex();}

// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.motion(&motor, cmd); }

void setup() {

// initialize encoder sensor hardware
//encoder.enableInterrupts(doA, doB);

// link the motor to the sensor

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
// limit the maximal dc voltage the driver can set
// as a protection measure for the low-resistance motors
// this value is fixed on startup
driver.voltage_limit = 6;

// link the motor and the driver
// link current sense and the driver

// current sensing
// no need for aligning
currentSense.skip_align = true;
// aligning voltage [V]
motor.voltage_sensor_align = 3;
// index search velocity [rad/s]
motor.velocity_index_search = 3;

// open loop control config
motor.controller = MotionControlType::velocity_openloop;

// contoller configuration
// default parameters in defaults.h
// velocity PI controller parameters
motor.PID_velocity.P = 0.2;
motor.PID_velocity.I = 20;
// default voltage_power_supply
motor.voltage_limit = 3;
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 1000;

// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01;

// angle P controller
motor.P_angle.P = 20;

// maximal velocity of the position control
motor.velocity_limit = 2;

// use monitoring with serial
// comment out if not needed

// initialize motor
// align encoder and start FOC

// add target command T
command.add(‘T’, doTarget, “target angle”);

Serial.println(F(“Motor ready.”));
Serial.println(F(“Set the target angle using serial terminal:”));

void loop() {
// main FOC algorithm function

// Motion control function

// function intended to be used with serial plotter to monitor motor variables
// significantly slowing the execution down!!!
// motor.monitor();

// user communication

Hi, did some more run.
Adjusting the allowed current was changing the sound from the motor. At T10 it was less noise at 1.3A at T20 it was about 1.5A and at T40 it was 1.7A vere I got less noise.
But if I do not limit the ampere I feel it might break or melt?
Something I do must be wrong.

Redused the voltage_limit down till 3 volts, and it run much better.
driver.voltage_limit = 3;
Made a new run today with a different setting:
driver.voltage_power_supply = 6;
driver.voltage_limit = 2.6;
With this it was using 1.4 A at T10, and at T250 it was 1.36A . This was with a four blade propeller on.
So the motor is runnig fine with very little noice.
I wonder if this is open loop is FOC or just a rotating field with no feedback?
I needed to change the speed with only small increment or it would stall.

Yes, you are exactly right - open loop is just sine-wave commutation with no feedback.

Yes, exactly, this is the problem, with open loop. If you change the speed too quickly, or if you stall the motor by hand, the system does not know if it misses steps, so the behaviour can’t be correct in these situations.

You would now have to add a sensor to “close the loop” and then the performance will be much better:

  • high torque even at low speeds
  • less energy used for the same torque
  • less noise (normally)

Hi @runger, thank you agein. I have ordered some sensors from China, but it will take several weeks befor I get it.
When I look in the spesification for FOC 2.2.3 it mention low side current sensing. I thougt that might could detect the motor speed, but maybe this is only in some beta or test face yet?

Yes, and it is supported on the G431-B, but the current sensing is used only for current control at the moment, not for sensing the motor’s position.

:slight_smile: look out for the next version of the library. there may be some developments in this direction

1 Like

KCL basic equations i understood now, thank you.