I need some help here.
I have a Technics direct drive PMSM that I’m driving with an STM32F4. In openloop it runs tolerably well, but speed stability is still well off the 1970’s analog PLL.
This is the openloop code and it starts the motor and I’m able to send T and L commands to the STM32 via the USB
// Open loop motor control example
#include <SimpleFOC.h>
// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(10, 27);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(PA7, PA6, PA5, PA3); // STM32
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);
//target variable
float target_velocity = 0;
float target = 0.0f;
LowPassFilter targetFilter = LowPassFilter(5.4f); // 1s time constant
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
void setup() {
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 20;
// limit the maximal dc voltage the driver can set
// as a protection measure for the low-resistance motors
// this value is fixed on startup
driver.voltage_limit = 6.0;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// limiting motor movements
// limit the voltage to be set to the motor
// start very low for high resistance motors
// current = voltage / resistance, so try to be well under 1Amp
motor.current_limit = 0.5; // [Amps]
// open loop control config
motor.controller = MotionControlType::velocity_openloop;
// init motor hardware
motor.init();
// add target command T
command.add('T', doTarget, "target velocity");
command.add('L', doLimit, "voltage limit");
Serial.begin(115200);
Serial.println("Motor ready!");
Serial.println("Set target velocity [rad/s]");
Serial.println("Set voltage limit");
_delay(1000);
}
void loop() {
// open loop velocity movement
// using motor.voltage_limit and motor.velocity_limit
// to turn the motor "backwards", just set a negative target_velocity
// command (T 3.4903) 33.33rpm = 3.48rad/s on test SP10
motor.move(targetFilter(target_velocity));
// user communication
command.run();
}
My issue is if the platter is disturbed it takes more than 30seconds for it to stabilize again. I’m looking to close the loop and add a PID.
My first issue the sensorless code will not send serial commands to the STM32 like the previous code does via the USB.
// Sensorless FOC for STM32
#include <SimpleFOC.h>
#include <SimpleFOCDrivers.h>
#include "encoders/MXLEMMING_observer/MXLEMMINGObserverSensor.h"
// Stepper motor & BLDC driver instance
BLDCMotor motor = BLDCMotor(10, 27);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(PA7, PA6, PA5, PA3); // STM32
// MXLEMMING observer sensor instance
MXLEMMINGObserverSensor observer = MXLEMMINGObserverSensor(motor);
// inline current sensor instance
// ACS712-05B has the resolution of 0.185mV per Amp
LowsideCurrentSense current_sense = LowsideCurrentSense(185.0f, PA1, PA2);
// commander communication instance
Commander command = Commander(Serial);
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);
// link the motor to the sensor
motor.linkSensor(&observer);
// 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::velocity;
motor.torque_controller = TorqueControlType::foc_current;
// current sense init and linking
current_sense.init();
motor.linkCurrentSense(¤t_sense);
// initialise motor
motor.init();
// skip the sensor alignment
motor.sensor_direction= Direction::CW;
motor.zero_electric_angle = 0;
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.");
_delay(1000);
}
void loop() {
// iterative setting FOC phase voltage
motor.loopFOC();
// iterative function setting the outter loop target
motor.move();
// motor monitoring
motor.monitor();
// user communication
command.run();
}