Testing the sensorless foc with SimpleFOC

Hi guys,

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

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.

The code is very simple, as usual :smiley:

#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.

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

2 Likes

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

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

And a nema17 motor:

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