Hi @quentin , thank you for getting back.
Thank you for all the efforts you guys are putting on this library.
It’s a custom board built based off of the BG431-ESC1.
The moment I put motor.init(); motor.initFOC(); in loop(), it’s drawing over current and burning the fuses.
#include <SimpleFOC.h>
#include "mxx_can.h"
#define CAN_ID 0x001
#define GEAR 25
#define TERM_CAN_BUS false
#define DELAY_BETWEEN_CMDS 150
#define MIN_POS -12.5
#define MAX_POS 12.5
#define MIN_VEL -5.0
#define MAX_VEL 5.0
#define POWER_SUPPLY 54
#define MAX_RPM 200 // we have run it upto 230 rad/s as well
#define MAX_BATTRYBRD_CMD 10.0
MxxCan can;
bool enableFlag=false;
bool motorUP=false;
bool motorDOWN=false;
bool motorInitialized=false;
float currentAngle = 0.0;
long lastUpdate = 0;
float vel_cmd = 0.0;
float notused_cmd = 0.0;
BLDCMotor motor = BLDCMotor(21);
BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);
LowsideCurrentSense currentSense = LowsideCurrentSense(0.003, -64.0/7.0, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT);
Encoder encoder = Encoder(A_HALL1, A_HALL2, 1000);
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
FDCAN_RxHeaderTypeDef canRxHeader;
uint8_t canRxData[4];
// converts from 0 to 1, to 0 to MAX_RPM range
float mapSpeed(float value)
{
value = (value / MAX_BATTRYBRD_CMD) * MAX_RPM;
return value;
}
void can_callback(FDCAN_RxHeaderTypeDef rx_header, uint8_t *rx_data)
{
can.packetRcvd = true;
canRxHeader = rx_header;
memcpy(&canRxData[0], &rx_data[0], 4);
//can.process_packet(rx_header, rx_data);
//digitalToggle(LED_BUILTIN);
}
void setup()
{
Serial.begin(115200);
delay(1000);
pinMode(PB10, INPUT_PULLDOWN);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(PB13, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(PB13, LOW);
SimpleCan::RxHandler *can_rx_handler = new SimpleCan::RxHandler(4, can_callback);
if(!can.init(CAN_ID, TERM_CAN_BUS, MIN_POS, MAX_POS, MIN_VEL, MAX_VEL, can_rx_handler))
{
Serial.println("CAN init failed");
// while(1);
}
// initialize encoder sensor hardware
encoder.init();
encoder.enableInterrupts(doA, doB);
// link the motor to the sensor
motor.linkSensor(&encoder);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = POWER_SUPPLY;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// link current sense and the driver
currentSense.linkDriver(&driver);
// current sensing
currentSense.init();
// no need for aligning
currentSense.skip_align = true;
motor.linkCurrentSense(¤tSense);
// aligning voltage [V] - reduced to prevent overcurrent
motor.voltage_sensor_align = 1.0; // Reduced from 3V to 1V
// index search velocity [rad/s]
motor.velocity_index_search = 3;
// Skip sensor alignment if you know the motor parameters
// Uncomment these lines if you want to skip alignment entirely:
// motor.sensor_direction = Direction::CW; // or CCW
// motor.zero_electric_angle = 0.0; // Set to your motor's electrical zero angle
// set motion control loop to be used
motor.controller = MotionControlType::velocity;
motor.torque_controller = TorqueControlType::foc_current;
// velocity PI controller parameters
motor.PID_velocity.P = 0.2;
motor.PID_velocity.I = 20;
// default voltage_power_supply
motor.voltage_limit = POWER_SUPPLY;
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 1000;
// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01;
// angle P controller
motor.P_angle.P = 30;
// maximal velocity of the position control
motor.current_limit = 30;
motor.velocity_limit = 10; //previously 19
// Motor initialization deferred until first enable command
// This prevents overcurrent during startup when no CAN commands are sent
//assign some delay
delay(1000);
}
void loop()
{
// main FOC algorithm function
motor.loopFOC();
// Motion control function
motor.move();
if(can.packetRcvd)
{
// Serial.println("CAN received from motherST");
can.process_packet(canRxHeader, canRxData);
lastUpdate = millis();
switch(can.check_rx())
{
case RX_TYPE::MOTOR_ENABLE:
// Initialize motor on first enable command
if (!motorInitialized) {
motorInitialized = true;
motor.init(); // This already calls motor.enable()
motor.initFOC();
}
vel_cmd = 0.0;
enableFlag = true;
break;
case RX_TYPE::MOTOR_DISABLE:
// Disable motor
motor.disable()
enableFlag = false;
motorInitialized = false;
break;
case RX_TYPE::MOTOR_CMD:
can.get_cmd(vel_cmd, notused_cmd);
break;
}
// can.update_tx_data(motor.shaft_angle/gear, motor.shaft_velocity/gear,
// currentSense.getDCCurrent(), motor.current.q, temperature, motor.voltage.q);
// can.send_data();
digitalToggle(LED_BUILTIN);
can.packetRcvd = false;
}
unsigned long curr_time = millis();
if(enableFlag)
{
if ((curr_time - lastUpdate) > DELAY_BETWEEN_CMDS)
{
// stop the motor
motor.target = 0.0;
}
else
{
motor.target = mapSpeed(vel_cmd);
}
}
}