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:
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…
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.
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.
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?
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.
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
So I figured it’s the (WEMOS) LOLIN32 Lite
@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?
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
/**
*
* 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(¤t_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.
@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)