Using the following example modified for my setup (SimpleFOCShield 2.0.4+GM4108 with magnetic encoder + Arduino UNO R4 minima), I have tested torque control using FOC currents.
- When the target current is small, the control seems to be smooth as in the picture.
- When the target current > 0.08A (voltage_q exceeds 6V), the motor starts to oscillate and rotate reverse as in the video.
Is there any way to stabilize the FOC current control in wider target current range even with driving voltage saturation ?
#include <SimpleFOC.h>
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// encoder instance
MagneticSensorSPI sensor = MagneticSensorSPI(AS5147_SPI, 10);
// current sensor
InlineCurrentSense current_sense = InlineCurrentSense(0.01f, 50.0f, A2, A0);
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&motor.target, cmd); }
void setup() {
// initialize encoder sensor hardware
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
motor.voltage_limit = 6;
driver.init();
// link driver
motor.linkDriver(&driver);
// link the driver to the current sense
current_sense.linkDriver(&driver);
// current sense init hardware
current_sense.init();
motor.linkCurrentSense(¤t_sense);
current_sense.gain_a *= -1; // for SimpleFOCShield v2.0.4
current_sense.skip_align = true;
// set torque mode:
motor.torque_controller = TorqueControlType::foc_current;
// set motion control loop to be used
motor.controller = MotionControlType::torque;
// foc current control parameters (Arduino UNO/Mega)
motor.PID_current_q.P = 5;
motor.PID_current_q.I= 300;
motor.PID_current_d.P= 5;
motor.PID_current_d.I = 300;
motor.LPF_current_q.Tf = 0.01;
motor.LPF_current_d.Tf = 0.01;
// initialize motor
motor.init();
// align sensor and start FOC
motor.initFOC();
// add target command T
command.add('T', doTarget, "target current");
motor.useMonitoring(Serial);
motor.monitor_variables = _MON_VOLT_Q | _MON_CURR_Q;
motor.monitor_downsample = 100;
Serial.begin(115200);
while(!Serial);
Serial.println("VOLT_Q:0 CURR_Q:0");
_delay(1000);
}
void loop() {
// main FOC algorithm function
motor.loopFOC();
// Motion control function
motor.move();
motor.monitor();
// user communication
command.run();
}