I’d like some help to understand why I am seeing such a low torque output with my Hoverboard motor, in theory capable of achieving 10-15 Nm.
Hardware used: ESP32, DRV8302, Hoverboard motor, AS5048A encoder.
Tested max torque with these two setups:
-
Using DC adjustable power supply at 24V, max current limit set to 9A. Result: Current limit reached on power supply, max torque measured: 3-4 Nm
-
Using Hoverboard battery 36V. Result: motor.voltage_limit is reached, measured torque is a bit smaller than scenario 1, around 3 Nm
Any help/ideas to try would be appreciated!!
Below is the relevant part of my code
#include <Arduino.h>
#include <SimpleFOC.h>
// DRV8302 pins connections
// don't forget to connect the common ground pin
#define INH_A_1 14
#define INH_B_1 12
#define INH_C_1 13
#define EN_GATE_1 27
#define M_PWM 32
#define M_OC 25
#define OC_ADJ 26
#define OC_GAIN 33
#define IOUTA 36
#define IOUTB 39
#define IOUTC 34
// Define the SPI pins for VSPI
#define CS_PIN_ENCODER 5
// motor instance
BLDCMotor motor = BLDCMotor(15);
// driver instance
BLDCDriver3PWM driver = BLDCDriver3PWM(INH_A_1, INH_B_1, INH_C_1, EN_GATE_1);
// DRV8302 board has 0.005Ohm shunt resistors and the gain of 12.22 V/V
LowsideCurrentSense currentSense = LowsideCurrentSense(0.005f, 12.22f, IOUTA, IOUTB, IOUTC);
// Create sensor objects
MagneticSensorSPI sensor = MagneticSensorSPI(CS_PIN_ENCODER, 14, 0x3FFF);
float target;
float step = 0.2; // angle step
const float span = 3.14/4; // allowed rotation in each direction
float uBound, lBound;
float maxv = 0, maxi = 0; // max voltage and current Q
bool motorEnable = true;
long ts, ts2;
// commander interface
Commander command = Commander(Serial);
void doTarget(char* cmd){ command.motor(&motor, cmd); }
void setup() {
ts = millis();
ts2 = millis();
Serial.begin(115200);
Serial.println("SETUP");
// initialise magnetic sensor hardware
sensor.init();
motor.linkSensor(&sensor);
Serial.println("Sensor Ready");
// DRV8302 specific code
// M_OC - enable over-current protection
pinMode(M_OC,OUTPUT);
digitalWrite(M_OC,HIGH);
// M_PWM - enable 3pwm mode
pinMode(M_PWM,OUTPUT);
digitalWrite(M_PWM,HIGH);
// OD_ADJ - set the maximum over-current limit possible
// Better option would be to use voltage divisor to set exact value
pinMode(OC_ADJ,OUTPUT);
digitalWrite(OC_ADJ,HIGH);
pinMode(OC_GAIN,OUTPUT);
digitalWrite(OC_GAIN,LOW);
Serial.println("Driver config");
_delay(1000);
// configure driver
driver.voltage_power_supply = 36;
driver.voltage_limit = driver.voltage_power_supply;
driver.pwm_frequency = 15000;
driver.init();
Serial.println("Driver init");
_delay(1000);
motor.linkDriver(&driver);
// link current sense and the driver
currentSense.linkDriver(&driver);
currentSense.init();
currentSense.skip_align = true;
// link the current sense to the motor
// driver 8302 has inverted gains on all channels
currentSense.gain_a *=-1;
currentSense.gain_b *=-1;
currentSense.gain_c *=-1;
motor.linkCurrentSense(¤tSense);
// limiting motor movements
motor.voltage_limit = 24; // [V]
motor.velocity_limit = 20;
motor.voltage_sensor_align = 4;
motor.velocity_index_search = 3;
// set control loop type to be used
motor.controller = MotionControlType::angle;
// velocity PI controller parameters
motor.PID_velocity.P = 1.0;
motor.PID_velocity.I = 15.0;
motor.LPF_velocity.Tf = 0.02; // velocity low pass filtering time constant
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 1000;
// position P controller parameters
motor.P_angle.P = 1.0;
motor.P_angle.I = 0.0;
motor.P_angle.D = 0.0;
// use monitoring with serial for motor init
// monitoring port
Serial.begin(115200);
// comment out if not needed
motor.useMonitoring(Serial);
motor.sensor_direction = Direction::CCW;
motor.zero_electric_angle = 1.88;
// initialize motor
motor.init();
motor.initFOC();
delay(100);
target = sensor.getAngle(); // set target
uBound = target + span;
lBound = target - span;
// downsampling
motor.motion_downsample = 10;
motor.monitor_downsample = 10; // default 10
// define the motor id
char motor_id = 'M';
command.add(motor_id, doTarget, "motor");
// configuring the monitoring to be well parsed by the webcontroller
//motor.monitor_start_char = motor_id; // the same latter as the motor id in the commander
//motor.monitor_end_char = motor_id; // the same latter as the motor id in the commander
//command.verbose = VerboseMode::machine_readable; // can be set using the webcontroller - optional
Serial.println("Setup DONE");
_delay(1000);
}
void loop() {
motor.loopFOC();
motor.move(target*(-1));
//motor.monitor();
//command.run();
}