# Sensorless BEMF reading with B-G431-ESC1

**URL:** https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173
**Category:** developement
**Tags:** bldc, sensorless, b\_g431\_esc, stm32
**Created:** [July 10, 2024, 5:59pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173 "2024-07-10T17:59:51Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![vkeiper](https://community.simplefoc.com/user_avatar/community.simplefoc.com/vkeiper/32/6967_2.png) [@vkeiper](https://community.simplefoc.com/u/vkeiper)
#### Post date: [July 10, 2024, 5:59pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/1 "2024-07-10T17:59:51Z")

</div>

I am currently using the B-G431-ESC1 to drive a sensorless BLDC motor. I have the motor running well in an velocity open loop, but I need to run the motor in a closed loop. From my understanding I need to use BEMF as feedback but don’t know how to actually get the BEMF values and then what to do with those values afterwards. Is there a different way to do a sensorless closed velocity loop? Does anyone have any pointers as to how to get the BEMF values and what to do with them afterwards?

I have attempted to configure the ADC using the STM32 library but was unsuccessful. If that is the path to take are there any pointers there?

This is my current code:

```auto

#include <Arduino.h>
#include <SimpleFOC.h>
#include <string>
#include "stm32g4xx_hal.h"

//local variable definitions
float target = 0.0; // used to change currently tested variable
int spinIt = 1; // iterator for the startup
int spinItSpeed = 1500; // rate of the startup, higher = slower
float radPerSec = 0; // driver the motor speed
int mxRads = 0; // max motor speed
int outIt = 0; //used for communication rate iteration

//Set up the motor and driver, motor is 7 pp, .12 phase resistor, and 1400KV 
BLDCMotor motor = BLDCMotor(7, .12, 1400);
BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);

/*controls the motor using the UART. 
-g starts the motor and revs up to 300 rad/s, 
-s stops the motor, 
-and entering a number sets the P in pid to that number
  -(currently not useful, but implemented for later tuning)
*/
void serialControl(){
  static String received_chars;
  while (Serial.available())
  {
    char inChar = (char)Serial.read();
    received_chars += inChar;
    if (inChar == '\n')
    {
      float num = received_chars.toFloat();
      if(received_chars == "s\n"){
        radPerSec = 0;
        mxRads = 0;
        received_chars = "";
        Serial.println("Stopping Motor.");
        break;
      }
      else if(received_chars == "g\n"){
        radPerSec = 0;
        mxRads = 300;
        received_chars = "";
        Serial.println("Starting Motor.");
        break;
      }
      else{
        target = num;
        Serial.print("PID.P = ");
        Serial.println(target);
        received_chars = "";
      }    
    }
  }
}

void setup()
{

  //initializes the psu and driver
  driver.voltage_power_supply = 14.8;
  driver.init();

  motor.linkDriver(&driver);
  motor.voltage_limit = 14.8;
  motor.velocity_limit = 2212;

  //Sets up openloop FOC
  motor.controller = MotionControlType::velocity_openloop;
  // set FOC modulation type to sinusoidal
  motor.foc_modulation = FOCModulationType::SinePWM;

  motor.init();

  motor.initFOC();

  
  Serial.begin(115200);
  delay(1000);

}

void loop()
{
  //starts the motor moving at radPerSec
  motor.loopFOC();
  motor.move(radPerSec);
  //this loop controls the rate at which the motor speeds up
  if (spinIt%spinItSpeed == 0 && radPerSec<mxRads){
    radPerSec++;
    spinIt = 1;
  }
  else{
    spinIt++;
  }

  //motor.PID_velocity.P = target;
  
  serialControl();
}

```

---

<div class="post-metadata">

### Author: ![Candas1](https://community.simplefoc.com/user_avatar/community.simplefoc.com/candas1/32/5296_2.png) [@Candas1](https://community.simplefoc.com/u/Candas1)
#### Post date: [July 10, 2024, 6:31pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/2 "2024-07-10T18:31:30Z")

</div>

It’s not using the BEMF sensing but maybe you can try the flux observer I ported as a [simplefoc sensor](https://github.com/Candas1/Arduino-FOC-drivers/blob/flux_observer/src/encoders/MXLEMMING_observer/README.md), I tested it on a hoverboard motor with [this](https://github.com/Candas1/SimpleFOC_b-g431b-esc1/tree/sensorless_observer) example project.

I am actually working on a unified current sense driver for stm32 that let’s you sample any other pin easily, it works but I still have a list of things to do there.  
[Here](https://github.com/Candas1/Arduino-FOC/blob/3910a080c5eda1ddf90712ed665bedb0ba33473a/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp#L159) you can see I added the BEMF pins already.  
If I remember well you need to do this in the main loop to get the values:

> \_readADCVoltageLowSide(A\_BEMF1, currentSense-\>params);

But I haven’t tried to use it for sensorless, you should probably calibrate the 0 offset for each phase. I am not sure if this is meant for 6 step communation only, or you can do a clarke transform and use atan2 to get an angle.

---

<div class="post-metadata">

### Author: ![Copper280z](https://community.simplefoc.com/user_avatar/community.simplefoc.com/copper280z/32/5514_2.png) [@Copper280z](https://community.simplefoc.com/u/Copper280z)
#### Post date: [July 10, 2024, 10:51pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/3 "2024-07-10T22:51:29Z")

</div>

> [@Candas1](#):
>
> But I haven’t tried to use it for sensorless, you should probably calibrate the 0 offset for each phase. I am not sure if this is meant for 6 step communation only, or you can do a clarke transform and use atan2 to get an angle.

That’s meant for 6 step, iirc. You only get an interesting value by reading the voltage of a phase when it’s half bridge is in high-z mode, otherwise it’ll just read psu voltage or ground.

---

<div class="post-metadata">

### Author: ![Candas1](https://community.simplefoc.com/user_avatar/community.simplefoc.com/candas1/32/5296_2.png) [@Candas1](https://community.simplefoc.com/u/Candas1)
#### Post date: [July 11, 2024, 4:35am UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/4 "2024-07-11T04:35:49Z")

</div>

OK so other than 6 step it could be interesting for tracking when the motor is not driven only.

---

<div class="post-metadata">

### Author: ![arpakai](https://community.simplefoc.com/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@arpakai](https://community.simplefoc.com/u/arpakai)
#### Post date: [March 23, 2025, 8:03pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/5 "2025-03-23T20:03:38Z")

</div>

Hello sir, I was trying to use the code that you provided for my project. I have a B-G431-ESC1 and x2216-5 2400KV BLDC motor. I adapted it to my current motor, but motor did not spin. It just created sounds. I will provide the code and the images from my osilloscope. Could you help me about it? At least i expected it to spin, however it did not.

 ![Screenshot 2025-03-23 at 23.03.27](https://community.simplefoc.com/uploads/default/original/2X/3/3edb2dd46051fba012d8330d3bca1c9a901d42cf.jpeg)

#include \<Arduino.h\>  
#include \<SimpleFOC.h\>  
#include   
#include “stm32g4xx\_hal.h”

//local variable definitions  
float target = 0.0; // used to change currently tested variable  
int spinIt = 1; // iterator for the startup  
int spinItSpeed = 1500; // rate of the startup, higher = slower  
float radPerSec = 0; // driver the motor speed  
int mxRads = 0; // max motor speed  
int outIt = 0; //used for communication rate iteration  
BLDCMotor motor = BLDCMotor(7, .36, 2400, 0.02);  
BLDCDriver6PWM driver = BLDCDriver6PWM(A\_PHASE\_UH, A\_PHASE\_UL, A\_PHASE\_VH, A\_PHASE\_VL, A\_PHASE\_WH, A\_PHASE\_WL);

LowsideCurrentSense current\_sense = LowsideCurrentSense(0.003, 9.1f, A\_OP1\_OUT, A\_OP2\_OUT, A\_OP3\_OUT);

void serialControl(){  
static String received\_chars;  
while (Serial.available())  
{  
char inChar = (char)Serial.read();  
received\_chars += inChar;  
if (inChar == ‘\n’)  
{  
float num = received\_chars.toFloat();  
if(received\_chars == “s\n”){  
radPerSec = 0;  
mxRads = 0;  
received\_chars = “”;  
Serial.println(“Stopping Motor.”);  
break;  
}  
else if(received\_chars == “g\n”){  
radPerSec = 0;  
mxRads = 300;  
received\_chars = “”;  
Serial.println(“Starting Motor.”);  
break;  
}  
else{  
target = num;  
Serial.print("PID.P = ");  
Serial.println(target);  
received\_chars = “”;  
}  
}  
}  
}

void setup()  
{

//initializes the psu and driver  
driver.voltage\_power\_supply = 14.8;  
driver.init();  
motor.linkDriver(&driver);

current\_sense.init();  
current\_sense.skip\_align = false;  
motor.linkCurrentSense(&current\_sense);

motor.voltage\_limit = 14.8;  
motor.velocity\_limit = 2212;

//Sets up openloop FOC  
motor.controller = MotionControlType::velocity\_openloop;  
// set FOC modulation type to sinusoidal  
motor.foc\_modulation = FOCModulationType::SinePWM;

motor.init();  
motor.initFOC();

Serial.begin(115200);  
delay(1000);  
mxRads = 300;  
}

void loop()  
{  
//starts the motor moving at radPerSec  
motor.loopFOC();  
motor.move(radPerSec);  
//this loop controls the rate at which the motor speeds up  
if (spinIt%spinItSpeed == 0 && radPerSec\<mxRads){  
radPerSec++;  
spinIt = 1;  
}  
else{  
spinIt++;  
}

serialControl();  
}

---

<div class="post-metadata">

### Author: ![dekutree64](https://community.simplefoc.com/user_avatar/community.simplefoc.com/dekutree64/32/3398_2.png) [@dekutree64](https://community.simplefoc.com/u/dekutree64)
#### Post date: [March 23, 2025, 9:14pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/6 "2025-03-23T21:14:46Z")

</div>

With the full 14.8V applied to a 0.36 ohm motor, it’s a puzzle why it didn’t go up in smoke immediately. I’d recommend motor.voltage\_limit = 1.0 or less for open loop.

For [confusing reasons](https://docs.simplefoc.com/foc_theory), the maximum motor voltage limit is half of the driver limit (or 58% with SpaceVectorPWM). So 7.4V in this case. With it set to 14.8V, the sine waves will be saturated to trapezoidal.

---

<div class="post-metadata">

### Author: ![arpakai](https://community.simplefoc.com/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@arpakai](https://community.simplefoc.com/u/arpakai)
#### Post date: [March 25, 2025, 7:50pm UTC](https://community.simplefoc.com/t/sensorless-bemf-reading-with-b-g431-esc1/5173/7 "2025-03-25T19:50:41Z")

</div>

I have updated the code as you suggested. motor.voltage\_limit = 1.0  
and the driver voltage to 12.0. This is the osilloscope image. It does not spin still. I have ordered AS5600 btw. I did not research deeply, but i will try to implement it for my motor. However, firstly i need to spin that motor w/o a sensor. So, i need your help about it sir.

 ![Screenshot 2025-03-25 at 22.50.15](https://community.simplefoc.com/uploads/default/original/2X/6/67e2a21a887aec3b9d72af383d60d7e85807527d.png)
