# Testing the sensorless foc with SimpleFOC

**URL:** https://community.simplefoc.com/t/testing-the-sensorless-foc-with-simplefoc/7019
**Category:** tips-n-tutorials
**Tags:** sensorless
**Created:** [April 3, 2025, 10:37am UTC](https://community.simplefoc.com/t/testing-the-sensorless-foc-with-simplefoc/7019 "2025-04-03T10:37:45Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Antun\_Skuric](https://community.simplefoc.com/user_avatar/community.simplefoc.com/antun_skuric/32/21_2.png) [@Antun\_Skuric](https://community.simplefoc.com/u/Antun_Skuric)
#### Post date: [April 3, 2025, 10:37am UTC](https://community.simplefoc.com/t/testing-the-sensorless-foc-with-simplefoc/7019/1 "2025-04-03T10:37:45Z")

</div>

Hi guys,

Some time ago @Candas1 has implemented sensorless flux observer compatible with SimpleFOC into the drivers repo.

> **[Arduino-FOC-drivers/src/encoders/MXLEMMING\_observer at dev ·...](https://github.com/simplefoc/Arduino-FOC-drivers/tree/dev/src/encoders/MXLEMMING_observer)**
>
> Drivers and support code for SimpleFOC. Contribute to simplefoc/Arduino-FOC-drivers development by creating an account on GitHub.

Given that it’s such an awesome addition to SimpleFOC and I did not see many people use it so far, I just wanted to add a quick post here to encourage people to try to use it.  
Especially since from recently @mcells provided the library with a simple tool to estimate motor parameters (inductance and resistance) which is crucial for the sensorless foc.

> <https://github.com/simplefoc/Arduino-FOC/pull/436>
>
> This adds a function to characterise a motors resistance, d&q-axis inductance an…d electrical-zero-angle.
> It \_should\_ run on all platforms, as long as there is working current sensing (and optionally an angle sensor for the electrical zero only(!)), but I can only test on the ESP32, so it would be great if someone tried this out on other micros. 
> And perhaps someone could try the stepper motor support, because I´m not sure if the measurements will need a correction factor there.
> 
> In my experience, the resistance measurement is quite accurate for gimbal motors, with maybe -+10% for a drone type BLDC. 
> The inductances are less accurate and vary about +-10% for gimbals and can occasionally be as bad as +-20-50% for drone motors, but doing several measurements will usually reveal a pattern. 
> 
> The electrical zero is a datum that pretty much comes out as a side-product of the d&q measurements, which is why i´ve included it. Whats very useful is that during the measurement the motor doesn´t move (or shouldn´t, at least), so the electrical zero is less dependant on low friction and pole pairs. As is, it can vary a bit, but this variance will not increase with higher pole count.
> Due to there always being two possible values, we cannot easily determine the true zero, so we still need an approximate zero. That´s why this won´t replace our current zero finding method, only supplement it.
> 
> This is something we wanted for some time, but the question is whether my implementation is appropriate or a bit overkill.
> I know the theory behind this code isn´t very \_simple\_, but I´ve tried to make the code somewhat understandable. 
> 
> What do you think?

The code is very simple, as usual 😃

```cpp
#include <SimpleFOC.h>
#include <SimpleFOCDrivers.h>

#include "encoders/MXLEMMING_observer/MXLEMMINGObserverSensor.h"

// BLDC motor & driver instance
// sunnysky x4108s-17 380Kv motor
// BLDCMotor motor = BLDCMotor(11, 0.13, 380, 0.00003);
// My big BDUAV 6354-180KV motor
BLDCMotor motor = BLDCMotor(7, 0.045, 180, 0.00004);

// MXLEMMING observer sensor instance
MXLEMMINGObserverSensor sensor = MXLEMMINGObserverSensor(motor);

// SimpleFOC Drive Shiled
BLDCDriver3PWM driver = BLDCDriver3PWM(D5, D6, D10, D8);

// inline current sensor instance
// ACS712-30B 
// - amp gain in 66mA/V
// but there is a voltage divider 3.3/5.0 volts 
// - 4.7k and 10k -> (10/14.7) = 0.68
LowsideCurrentSense current_sense = LowsideCurrentSense(0.68*66.0f, A0, A2);

// commander communication instance
Commander command = Commander(Serial);
//void doMotion(char* cmd){ command.motion(&motor, cmd); }
void doMotor(char* cmd){ command.motor(&motor, cmd); }

void setup() {

 // use monitoring with serial 
 Serial.begin(115200);
 // enable more verbose output for debugging
 // comment out if not needed
 SimpleFOCDebug::enable(&Serial);

 sensor.init();
 // link the motor to the sensor
 motor.linkSensor(&sensor);

 // driver config
 // power supply voltage [V]
 driver.voltage_power_supply = 20;
 driver.init();
 // link driver
 motor.linkDriver(&driver);
 // link current sense and the driver
 current_sense.linkDriver(&driver);

 // set control loop type to be used
 motor.controller = MotionControlType::torque;
 motor.torque_controller = TorqueControlType::foc_current;

 // comment out if not needed
 motor.useMonitoring(Serial);

 // current sense init and linking
 current_sense.init();
 current_sense.gain_b *= -1;
 current_sense.skip_align = true;
 motor.linkCurrentSense(&current_sense);

 // should not do the sensor alignement with the observer
 // so these params need to be set
 motor.sensor_direction= Direction::CW;
 motor.zero_electric_angle = 0;

 // initialise motor
 motor.init();
 // align encoder and start FOC
 motor.initFOC();

 // subscribe motor to the commander
 command.add('M', doMotor, "motor");
 
 // Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
 Serial.println("Motor ready.");

 // if you do not know your motor parameters uncomment the lines below
 // and the program will output the motor parameters to the serial
 // motor.characteriseMotor(1.0);
 // return;

 // run the FOC at a fixed frequency (optional)
 HardwareTimer* timer = new HardwareTimer(TIM5);
 timer->setOverflow(15000, HERTZ_FORMAT); // Set timer frequency to 10kHz
 // add the loopFOC and move to the timer
 timer->attachInterrupt([](){
   motor.loopFOC();
   motor.move();
 });
 timer->resume();

 _delay(1000);
}

void loop() {

 // user communication
 command.run();
 
 _delay(50);
}

```

Here are some cool videos (that are a bit scary too).

The motors are torque controlled and I’m setting the torque target value in amps. In both cases I’m using a nucleo g747re and the SimpleFOC Drive shield. The current sensing is inline, but I’m using low-side as it is much faster.  
The motor parameters are measured using the `motor.characteriseMotor(1.0);` method.

[![](https://img.youtube.com/vi/zGS2-zRe0Ew/maxresdefault.jpg "E-Skateboard motor sensorless FOC with SimpleFOC") ](https://www.youtube.com/watch?v=zGS2-zRe0Ew)

[![](https://img.youtube.com/vi/Ht4P33vdp8M/maxresdefault.jpg "Drone motor sensorless FOC with SimpleFOC") ](https://www.youtube.com/watch?v=Ht4P33vdp8M)

This is an awesome addition to SimpleFOC and I just wanned to thank the community it! ❤

---

<div class="post-metadata">

### Author: ![aklvis](https://community.simplefoc.com/user_avatar/community.simplefoc.com/aklvis/32/7471_2.png) [@aklvis](https://community.simplefoc.com/u/aklvis)
#### Post date: [April 25, 2025, 10:10am UTC](https://community.simplefoc.com/t/testing-the-sensorless-foc-with-simplefoc/7019/3 "2025-04-25T10:10:51Z")

</div>

Very cool, Have you managed to get velocity control to work?

---

<div class="post-metadata">

### Author: ![Antun\_Skuric](https://community.simplefoc.com/user_avatar/community.simplefoc.com/antun_skuric/32/21_2.png) [@Antun\_Skuric](https://community.simplefoc.com/u/Antun_Skuric)
#### Post date: [April 3, 2025, 11:42am UTC](https://community.simplefoc.com/t/testing-the-sensorless-foc-with-simplefoc/7019/2 "2025-04-03T11:42:57Z")

</div>

I’ve also tested a gimbal motor iPower GBM5108-120T  
Its parameters were:

```cpp
BLDCMotor motor = BLDCMotor(11, 6.7, 34, 0.004);

```

[![](https://img.youtube.com/vi/ErIKb9M5t2o/hqdefault.jpg "Gimbal motor sensorless FOC with SimpleFOC") ](https://www.youtube.com/watch?v=ErIKb9M5t2o)

And a nema17 motor:

```cpp
StepperMotor motor = StepperMotor(50, 3.9f, 35.0f, 0.018f);

```

[![](https://img.youtube.com/vi/9fNi3aSNi8Y/hqdefault.jpg "Nema17 stepper motor sensorless FOC with SimpleFOC") ](https://www.youtube.com/watch?v=9fNi3aSNi8Y)

---

<div class="post-metadata">

### Author: ![Zain\_ur\_Rehman](https://community.simplefoc.com/user_avatar/community.simplefoc.com/zain_ur_rehman/32/7129_2.png) [@Zain\_ur\_Rehman](https://community.simplefoc.com/u/Zain_ur_Rehman)
#### Post date: [December 13, 2025, 11:43am UTC](https://community.simplefoc.com/t/testing-the-sensorless-foc-with-simplefoc/7019/4 "2025-12-13T11:43:48Z")

</div>

Trying to do this, as i already have a simple foc working with encoder. Just want to redirect get angle to observer, having issues with angle i don’t know what could go wrong and its a simple equation.

But the only thing in my mind, I call get angle and inside that i do clarke for alpha beta currents fine, but what Ualpha and Ubeta i would use? That only we could know after we know electrical angle but i used Ualpha beta here what is calculated in setPhaseVoltage. So its not working for me but i am debugging as what could be the issue!
