Hello, I’m having trouble getting some low-resistance “quadcoptor” type motors to spin past ~4K RPM. The motors work wonderfully, efficiently, and silently up to about 2K RPM, then after that start to use ridiculous amounts of power, topping out at ~4KRPM and consuming ~100W!
commanded_target_voltage, speed(rad/s), power consumed
0.1 - 28, 0.6W
0.5 - 103, 1.7W
1.0 - 356, 32W
1.5 - 439, 96W
-The motors work past 20K rpm with a cheap commercial ESC, consuming around 35W at 20KRPM
-The AS5048A sensor can accurately read RPMs past ~20KRPM (I tested this by leaving simpleFOC running with the monitor whilest hooking the 3 power phases to an ESC and cranking it up to 20KRPM)
-I tried different modulation types, motor downsampleing and anything else I could think of… NOthing works.
Motor: D3536, K=~2000, resistance=0.1Ohm, unloaded
Sensor: AS5048A
Driver: DRV8301 board, 3 PWM mode
Controller: NUCLEO G431RB
Algorithm: SimpleFOC, Torque mode, voltage feedback
/*
*/
#include <SimpleFOC.h>
#include "DRV8301.h"
MagneticSensorSPI sensor = MagneticSensorSPI(AS5147_SPI, 10); // MOSI=11, MISO=12, CSK=13.
DRV8301 gate_driver = DRV8301(3, 4, 5, 2, 6, 7); // MOSI, MISO, SCLK, CS, EN_GATE, FAULT
BLDCMotor motor = BLDCMotor(7); // 2208
BLDCDriver3PWM driver = BLDCDriver3PWM(PC0, PC1, PC2);
Commander command = Commander(Serial);
// void doMotor(char* cmd) { command.motor(&motor, cmd); }
void doTarget(char* cmd) {command.scalar(&motor.target, cmd);}
void doLimit(char* cmd) {command.scalar(&motor.voltage_limit, cmd);}
void doMotor(char* cmd) { command.motor(&motor, cmd); }
char msgbuf[256];
void setup() {
Serial.begin(921600); // WARNING: low value like 115200 cause distorted FOC
// for timer analysis
//SimpleFOCDebug::enable(&Serial);
//delay(5000);
Serial.printf("enter setup...\n");
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 18;
driver.voltage_limit = 4;
driver.init();
// configure the DRV8301
gate_driver.begin(PWM_INPUT_MODE_3PWM, 1); // no OCP
_delay(100);
int reg1, reg2, reg3, reg4, fault;
gate_driver.get_regs(®1, ®2, ®3, ®4);
fault = gate_driver.is_fault();
sprintf(msgbuf, "DRV8301: fault=%x, STATREG1=0x%.4x, STATREG2=0x%.4x, CTRLREG1=0x%.4x, CTRLREG2=0x%.4x", fault, reg1, reg2, reg3, reg4);
Serial.println(msgbuf);
// link driver
motor.linkDriver(&driver);
// link current sense and the driver
motor.voltage_sensor_align = 0.5;
//motor.controller = MotionControlType::torque;
motor.controller = MotionControlType::torque;
// default voltage_power_supply
motor.voltage_limit = 2;
motor.current_limit = 1000;
motor.velocity_limit = 100;
// contoller configuration based on the controll type
motor.PID_velocity.P = 0.1;
motor.PID_velocity.I = 1.0;
motor.PID_velocity.D = 0.0;
motor.PID_velocity.output_ramp = 1000.0;
motor.PID_velocity.limit = 1000.0;
motor.LPF_velocity.Tf = 0.1;
// angle loop controller
motor.P_angle.P = 30;
motor.motion_downsample = 10.0;
// set the inital target value
motor.target = 0;
// Serial.begin(115200); // WARNING: low value like 115200 cause distorted FOC
// comment out if not needed
motor.useMonitoring(Serial);
//motor.monitor_downsample = 0; // disable intially
motor.monitor_variables = _MON_TARGET | _MON_VOLT_Q | _MON_VOLT_D | _MON_CURR_Q | _MON_CURR_D | _MON_VEL | _MON_ANGLE; // monitor target velocity and angle
//motor.foc_modulation = SpaceVectorPWM;
// initialise motor
motor.init();
// align encoder and start FOC
motor.initFOC();
// subscribe motor to the commander
command.add('T', doTarget, "target"); // ssss space
command.add('L', doLimit, "voltage limit");
command.add('M',doMotor,"motor");
Serial.printf("setup complete...\n");
_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();
}