The project
I want to use a BLDC motor with a SimpleFOCShield+Nucleo-64 to point a laser at a precise angle.
Moving to the target angle needs to be as fast as possible. And the torque applied to the motor needs to be strong enough, so to strongly maintain the laser in position, as the device is mounted on a moving/shaking vehicle.
At a later stage, I will also need to compensate part of the vehicle angular movement using an IMU, just like in a camera gimbal, but as you’ll see below, that is the least of my concerns right now
What I did until now
magnetic_sensor_spi_example
, open_loop_velocity_example
and single_full_control_example
seem to work well.
What I’m doing now
I’m experimenting with MotionControlType::angle
.
Here is my code:
#include <SimpleFOC.h>
#include "SimpleFOCDrivers.h"
#include "encoders/as5048a/MagneticSensorAS5048A.h"
//----------------------------------------
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
MagneticSensorAS5048A sensor(10);
// inline current sensor instance
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A0, A2);
//----------------------------------------
void setup() {
// Sensor
sensor.init();
motor.linkSensor(&sensor);
// Driver
driver.voltage_power_supply = 14.8;
driver.init();
motor.linkDriver(&driver);
// Control loop type
// INITIALLY DISABLED -> motor.torque_controller = TorqueControlType::foc_current;
motor.controller = MotionControlType::angle;
// Motion control limits
motor.velocity_limit = 20;
motor.voltage_limit = 5;
// Current sense
current_sense.init();
motor.linkCurrentSense(¤t_sense);
// Initialise motor
motor.init();
// Align encoder and start FOC (current_sense settings below specific to SimpleFOCShield)
current_sense.gain_b *=-1;
current_sense.skip_align = true;
motor.initFOC();
_delay(1000);
}
//----------------------------------------
float target_angle = 3.1416;
long timestamp_us = _micros();
void loop() {
// Inverse angle each four seconds
if(_micros() - timestamp_us > 4e6) {
timestamp_us = _micros();
target_angle = -target_angle;
}
// Move motor
motor.loopFOC();
motor.move(target_angle);
}
//----------------------------------------
Initial Questions
With motor.torque_controller = TorqueControlType::voltage
, I get the following behavior:
- EDIT: Every 4s, the angle goes from -PI/2 to PI/2 (instead of -PI to PI as I expect).
- The movement is jerky.
- When the motor stops at its target, it remains still, silent, with no vibration.
- The applied torque is very weak. Sometimes the motor doesn’t even move and I need to manually help it starting. EDIT: Sometimes the motor stops before reaching the -PI or PI value, unless I help it manually.
With motor.torque_controller = TorqueControlType::foc_current
, I get the following behavior:
- Every 4s, the angle goes from -PI to PI as expected.
- The movement is smooth.
- When the motor stops at its target, it vibrates a lot.
- The applied torque is very strong.
- The motor overheats.
Are these the expected behaviors? Is it all about PID tuning now?
If it is, where should I start? It seems I have four PIDs to tune (PID_current_q
, PID_current_d
, PID_velocity
, P_angle
), what tools do you guys use?
Thanks.