SimpleFOC turns OK and stops/stutters

Hello wonderful people!

I’ve got some hoverboard motors and I bought some XY-BLDC 200W drivers for them but they had the wrong version of the JY01 IC with a 3 second acceleration/wait times making them unusable for closed loop control.
I then went the SimpleFOC route by hijacking an Arduino Nano to the above boards but with Software Interrupts I could only get the motor to run at 4KHz in closed loop mode (open loop worked OK at 32KHz).
Next step was to try with a Blue Pill (STM32F103), motion was a lot smoother and I could set the frequency to 20KHz or whatever I wanted.

Here is where the problem lies;
examples/utils/sensor_test - OK!
examples/utils/driver_standalone_test - OK!
examples/motion_control/open_loop_motion_control - OK! (velocity and position)
examples/motion_control/torque_control - FAIL

Passes Pole Pairs and other checks.
In closed loop, low speed movements the motor stalls within the first rotations and locks up. Needs a negative speed to unlock.
At higher speeds the motor runs very well but will suddenly draw a huge current spike making the whole motor shudder violently.

I’ve added 3K pull-ups to the Hall sensors and no difference from the 10K ones.
Enabled the monitor for the motor and I can see these sudden current spikes causing the motor to jump.

01:10:36.829 -> MOT: Monitor enabled!
01:10:36.829 -> MOT: Init
01:10:37.329 -> MOT: Enable driver.
01:10:38.332 -> MOT: Align sensor.
01:10:40.521 -> MOT: sensor_direction==CCW
01:10:40.521 -> MOT: PP check: OK!
01:10:41.253 -> MOT: Zero elec. angle: 2.09
01:10:41.958 -> MOT: No current sense.
01:10:41.958 -> MOT: Ready.
01:10:41.958 -> Motor ready.
01:10:41.958 -> Set the target voltage using serial terminal:
01:10:42.928 -> 0.0000	0.0000	0.0000	0.1396
01:10:42.928 -> 0.0000	0.0000	0.0000	0.1396

And setting Target to 5 the motor runs fine but with these current spikes. I can see in the monitor that the motor nearly instantly changes direction:


01:13:10.019 -> 5.0000	5.0000	14.2097	280.9980
01:13:10.019 -> 5.0000	5.0000	14.4118	281.0678
01:13:10.019 -> 5.0000	5.0000	14.9905	281.1377
01:13:10.019 -> 5.0000	5.0000	11.9271	281.1377
01:13:10.052 -> 5.0000	5.0000	5.1911	281.1377
01:13:10.052 -> 5.0000	5.0000	2.1693	280.9282
01:13:10.052 -> 5.0000	5.0000	-10.2313	280.9980
01:13:10.052 -> 5.0000	5.0000	-4.6934	280.9980
01:13:10.052 -> 5.0000	5.0000	-1.8396	281.2773
01:13:10.052 -> 5.0000	5.0000	-0.7671	281.1377
01:13:10.052 -> 5.0000	5.0000	-0.3134	281.1377
01:13:10.052 -> 5.0000	5.0000	-0.1313	280.9980
01:13:10.085 -> 5.0000	5.0000	-0.0624	280.9980
01:13:10.085 -> 5.0000	5.0000	-0.0231	280.9980
01:13:10.085 -> 5.0000	5.0000	-0.0102	281.0678
01:13:10.085 -> 5.0000	5.0000	-0.0045	281.0678
01:13:10.085 -> 5.0000	5.0000	2.4683	281.1377
01:13:10.085 -> 5.0000	5.0000	6.0658	281.1377
01:13:10.085 -> 5.0000	5.0000	8.5486	281.2075
01:13:10.120 -> 5.0000	5.0000	10.3784	281.2773
01:13:10.120 -> 5.0000	5.0000	11.7862	281.3471
01:13:10.120 -> 5.0000	5.0000	12.8391	281.4169
01:13:10.120 -> 5.0000	5.0000	12.9580	281.4867
01:13:10.120 -> 5.0000	5.0000	13.3730	281.5565
01:13:10.120 -> 5.0000	5.0000	13.3115	281.6263
01:13:10.120 -> 5.0000	5.0000	13.6609	281.6263
01:13:10.120 -> 5.0000	5.0000	14.5072	281.6961
01:13:10.152 -> 5.0000	5.0000	14.5277	281.7660
01:13:10.152 -> 5.0000	5.0000	14.5291	281.8358

My PSU is current limited but the higher I set the current limit the harder the motor jumps.
Can the HALL sensors be sending garbled data? They appear OK on the scope…

Any input and suggestions appreciated!!

Oh, and hall sensors to UVW outputs have been matched both hardware and software.

Are the phase currents matching the phases ?
What’s the ouput of current sense alignment ?

Hi Candas1,
I’m pretty sure that UVW and Halls match.
I’ve just enabled current sense on the Dual FOC Plus and the ESP is freaking out. Currents measure fine in testing sketch. I’m pretty new to ESP stuff.

14:41:05.356 -> MOT: Monitor enabled!
14:41:05.449 -> MOT: Monitor enabled!
14:41:05.449 -> MOT: Init
14:41:05.977 -> MOT: Enable driver.
14:41:06.975 -> MOT: Align sensor.
14:41:09.170 -> MOT: sensor_direction==CCW
14:41:09.170 -> MOT: PP check: OK!
14:41:09.874 -> MOT: Zero elec. angle: 2.09
14:41:10.562 -> MOT: Align current sense.
14:41:10.562 -> Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
14:41:10.595 -> 
14:41:10.595 -> Core  1 register dump:
14:41:10.595 -> PC      : 0x400d330e  PS      : 0x00060c30  A0      : 0x800d1fe7  A1      : 0x3ffc5a80  
14:41:10.595 -> A2      : 0x3ffc2028  A3      : 0x00000001  A4      : 0xffffcfc7  A5      : 0x00000000  
14:41:10.595 -> A6      : 0x00000000  A7      : 0x00000001  A8      : 0x00000027  A9      : 0x3ffc5ab0  
14:41:10.595 -> A10     : 0x00000000  A11     : 0x3f800000  A12     : 0x8008140c  A13     : 0x3ffbf5ec  
14:41:10.636 -> A14     : 0x3ffc2550  A15     : 0x3ffbdf00  SAR     : 0x00000020  EXCCAUSE: 0x0000001c  
14:41:10.636 -> EXCVADDR: 0x00000000  LBEG    : 0x4008669d  LEND    : 0x400866ad  LCOUNT  : 0xffffffff  
14:41:10.636 -> 
14:41:10.636 -> 
14:41:10.636 -> Backtrace: 0x400d330b:0x3ffc5a80 0x400d1fe4:0x3ffc5af0 0x400d256c:0x3ffc5b10 0x400d18f2:0x3ffc5b30 0x400d6456:0x3ffc5b60
14:41:10.636 -> 
14:41:10.636 -> 
14:41:10.636 -> 
14:41:10.636 -> 
14:41:10.636 -> ELF file SHA256: f63fe4154609feea
14:41:10.636 -> 
14:41:10.760 -> Rebooting...

The UVW and Halls have to match, ok. But the current sense should also match.
The current sense alignment will let you know if 2 phases currents are swapped, or if the gains are inverted.
What is this error you are getting ?

Currents sense if on A and B phases, no C. The error is during the motor.initFOC() when it tries to align the current sense. If I unlink the CurrentSense the FOC will start but as usual the motor runs fine and suddenly starts stuttering… weird…

I’ve mentioned elsewhere that the MKS dual FOC PLUS has 6PWM drivers and the L_IN needs inverted logic.
It’s the #define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH true line in
…/documents/arduino/libraries/simpefoc/src/drivers/hardware_api.h`
that I’ve changed to false.
It’s not the most elegant way, because it will change the behavior of all 6PWM drivers.

V2.2.1 OK! (still stutters, stalls)
V2.2.2 NOPE (instant panic)
V2.3.0 nope (panic at current sense)
V2.3.0 nope (panic at current sense)

Going to give that a try with V2.3.0 and no current sense because I can’t find it in V2.2.1:
Nope, it did not like that being changed! Motor barely moves or makes horrendous rattling sounds!

The MKS Dual FOC Plus has 3PWM pins per motor, they are tied together in the schematic:

Gonna stick with 2.2.1 and see…

Maybe the Hall sensor hysteresis is causing issues? Do I need external de-bounce hardware?

Have you called currentsense.linkDriver() and currentsense.init()?

Ah yeah it could the linkdriver missing.
I had reported this but I finally closed it because it wasn’t impacting stm32 but only my gd32. So could be impacting other chips finally.

So we can’t apply external dead-time to prevent shoot-through. Have to check the EG2133 datasheet, what the internal dT is.

Today I received my MKS DualFOC 3.1 and wanted to know, which of the many ESP32 boards in ArduinoIDE should I pick? I found lots of example programs for it, but no clue what type of ESP32 I got. The bag just labelled ESP32 REV1

//edit
I’m so glad, I speak chinese fluently :wink:
So I figured it’s the (WEMOS) LOLIN32 Lite

1 Like

The dead-time is 100ns long (min50-max200). That doesn’t sound much :worried:

@runger, @Candas1,
Yup, you were right, I was missing the current_sense.linkDriver(&driver)! No more Core 1 panics!
Still terrible at running the hoverboard motors hahahaha! I must have something setup wrong… or noise from somewhere?

@o_lampe yeah, its the Wemos Lolin32 lite :smiley:

Going to check again all the pinouts and pin numbers because I’m getting a number 2 for the current sensor align and ABC UVW might not be jumbled even tho I’ve already checked ABC with the PWM voltage test… ah well

    0 - fail
    1 - success and nothing changed
    2 - success but pins reconfigured
    3 - success but gains inverted
    4 - success but pins reconfigured and gains inverted

So it’s good with voltage mode and bad with foc_current?

Exactly. In closed loop the motor will stall at low speeds, and at high speeds it stutters and has huge current spikes.

I have rechecked the pins and connections, pull-ups and all. According to SimpleFOC all is good:


22:19:53.523 -> MOT: Monitor enabled!
22:19:53.523 -> MOT: Init
22:19:54.005 -> MOT: Enable driver.
22:19:55.999 -> MOT: Align sensor.
22:19:58.230 -> MOT: sensor_direction==CW
22:19:58.230 -> MOT: PP check: OK!
22:19:58.918 -> MOT: Zero elec. angle: 0.00
22:19:59.635 -> MOT: Align current sense.
22:20:02.449 -> MOT: Success: 1
22:20:02.449 -> MOT: Ready.
22:20:02.449 -> Motor ready.
22:20:02.449 -> Set the target voltage using serial terminal:

Is it low side current sensing? Maybe sharing your code will help

Yeah, could help! inline current sensing.

/**
 * 
 * Torque control example using voltage control loop.
 * 
 * Most of the low-end BLDC driver boards doesn't have current measurement therefore SimpleFOC offers 
 * you a way to control motor torque by setting the voltage to the motor instead of the current. 
 * 
 * This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
 */
#include <SimpleFOC.h>
// software interrupt library

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(15);
//Blue Pill
//BLDCDriver6PWM driver = BLDCDriver6PWM(5,6, 9,10, 3,11);
//MKS Dual Foc Plus
BLDCDriver3PWM driver = BLDCDriver3PWM(32,33,25);

// hall sensor instance
//Blue Pill
//HallSensor sensor = HallSensor(7, 8, 12, 15);
//MKS Dual Foc Plus
HallSensor sensor = HallSensor(15, 18, 19, 15);

// current sensor
// shunt resistor value
// gain value
// pins phase A,B, (C optional)
//MKS Dual FOC Plus
InlineCurrentSense current_sense = InlineCurrentSense(0.01f, 20.0f, 39, 36, _NC);

// Interrupt routine intialisation
// channel A and B callbacks
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}
// If no available hadware interrupt pins use the software interrupt
/*PciListenerImp listenA(sensor.pinA, doA);
PciListenerImp listenB(sensor.pinB, doB);
PciListenerImp listenC(sensor.pinC, doC);*/

// voltage set point variable
float target_voltage = 0;
// instantiate the commander
Commander command = Commander(Serial);

void doTarget(char* cmd) { command.scalar(&target_voltage, cmd); }

void setup() {
  // use monitoring with serial 
  Serial.begin(115200);
  delay(1000);

  motor.useMonitoring(Serial);
  //SimpleFOCDebug::enable(NULL);

  // pwm frequency to be used [Hz]
  // for atmega328 fixed to 32kHz
  // esp32/stm32/teensy configurable
  driver.pwm_frequency = 20000;

  //sensor.pullup = Pullup::USE_INTERN;
  // initialize encoder sensor hardware
  sensor.init();

  // software interrupts
  /*PciManager.registerListener(&listenA);
  PciManager.registerListener(&listenB);
  PciManager.registerListener(&listenC);*/
  sensor.enableInterrupts(doA, doB, doC); 
  
  // link the motor to the sensor
  motor.linkSensor(&sensor);

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

  // aligning voltage
  motor.voltage_sensor_align = 1;
  
  // choose FOC modulation (optional)
  //motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  //motor.foc_modulation = FOCModulationType::Trapezoid_120;
  //motor.foc_modulation = FOCModulationType::SinePWM;

  // set motion control loop to be used
  motor.controller = MotionControlType::torque;

  // use monitoring with serial comment out if not needed
  motor.useMonitoring(Serial);

  // initialize motor
  motor.init();
  // initialise the current sensing
  current_sense.init();
  // for SimpleFOCShield v2.01/v2.0.2
  //current_sense.gain_b *= -1;
  // link the current sensor to the motor
  motor.linkCurrentSense(&current_sense);

  // align sensor and start FOC
  motor.initFOC();

  // add target command T
  command.add('T', doTarget, "target voltage");

  Serial.println(F("Motor ready."));
  Serial.println(F("Set the target voltage using serial terminal:"));
  _delay(1000);
  //motor.move(target_voltage);
}


void loop() {
  // main FOC algorithm function
  // the faster you run this function the better
  // Arduino UNO loop  ~1kHz
  // Bluepill loop ~10kHz 
  motor.loopFOC();

  // Motion control function
  // velocity, position or voltage (defined in motor.controller)
  // this function can be run at much lower frequency than loopFOC() function
  // You can also use motor.move() and set the motor.target in the code
  motor.move(target_voltage);
  
  //motor.monitor();

  /*PhaseCurrent_s currents = current_sense.getPhaseCurrents();
  if(currents.a!=0||currents.b!=0||currents.c!=0){  
    //float current_magnitude = current_sense.getDCCurrent();
    Serial.print(currents.a*1000); // milli Amps
    Serial.print(" A\t");
    Serial.print(currents.b*1000); // milli Amps
    Serial.println(" B\t");
    //Serial.print(currents.c*1000); // milli Amps
    //Serial.print(" C\t");
    //Serial.println(current_magnitude*1000); // milli Amps
  }*/

  // user communication
  command.run();
  //driver.setPwm(3,0,0);//Ca
}

PSU power sags from the sudden current draw. Looks like very noisy Hall sensors.

The Hall sensors seem to be picking up the coil current, will try some L/C/R filtering tomorrow…

@OiD-W I’m using the dev-branch of simpleFOC and work my way through the Deng FOC github examples
I’ve noticed during my inlineCurrent test, that I had to add NOT_SET for the third current sensor.
InlineCurrentSense current_sense0 = InlineCurrentSense(0.01, 50.0, 39, 36, NOT_SET);

Maybe the example was written for the older Dual FOC board which has 2 onchip current sensors and there is a third sensor I have to identify? No i just checked, there are only 4 shunt resistors for both drivers…
What is your currentSense constructor for both drivers?

BTW, did you check the shunts value? There are two different versions out there (0.01R vs. 0.06R IIRC)