// clang-format off #include #include #include #include #include #include #include #include "common/base_classes/FOCMotor.h" #include "hal_conf_extra.h" #include "wiring_analog.h" #include "wiring_constants.h" // clang-format on STM32_CAN Can(CAN2, DEF); static CAN_message_t CAN_TX_msg; static CAN_message_t CAN_inMsg; SPIClass spi; MagneticSensorAS5045 encoder(AS5045_CS, AS5045_MOSI, AS5045_MISO, AS5045_SCLK); BLDCMotor motor(POLE_PAIRS); DRV8313Driver driver(TIM1_CH1, TIM1_CH2, TIM1_CH3, EN_W_GATE_DRIVER, EN_U_GATE_DRIVER, EN_V_GATE_DRIVER, SLEEP_DRIVER, RESET_DRIVER, FAULT_DRIVER); LowsideCurrentSense current_sense(0.01, 10.0, CURRENT_SENSOR_1, CURRENT_SENSOR_2, CURRENT_SENSOR_3); Commander command(Serial); struct MotorControlInputs { float target_angle = 0.0; float target_velocity = 0.0; bool motor_enabled = false; }; MotorControlInputs motor_control_inputs; void doMotor(char *cmd) { command.motor(&motor, cmd); digitalWrite(PC10, !digitalRead(PC10)); delayMicroseconds(2); } void setup_foc(MagneticSensorAS5045 *encoder, BLDCMotor *motor, DRV8313Driver *driver, LowsideCurrentSense *current_sense, Commander *commander, CommandCallback callback) { encoder->init(&spi); driver->pwm_frequency = 20000; driver->voltage_power_supply = 24; driver->voltage_limit = 24; driver->init(); current_sense->linkDriver(driver); current_sense->init(); motor->linkSensor(encoder); motor->linkDriver(driver); motor->linkCurrentSense(current_sense); motor->useMonitoring(Serial); motor->monitor_downsample = 5000; // default 0 motor->controller = MotionControlType::angle; motor->torque_controller = TorqueControlType::voltage; motor->foc_modulation = FOCModulationType::SpaceVectorPWM; // PID start motor->PID_velocity.P = 0.75; motor->PID_velocity.I = 20; motor->LPF_velocity.Tf = 0.005; motor->P_angle.P = 0.5; motor->LPF_angle.Tf = 0.001; // PID end motor->velocity_limit = 40; // Ограничение по скорости вращения rad/s (382 rpm) motor->voltage_limit = 24; motor->current_limit = 0.5; motor->sensor_direction = Direction::CCW; motor->init(); motor->initFOC(); } void send_velocity() { float current_velocity = motor.shaftVelocity(); CAN_TX_msg.id = 1; CAN_TX_msg.buf[0] = 'V'; CAN_TX_msg.len = 5; memcpy(&CAN_TX_msg.buf[1], ¤t_velocity, sizeof(current_velocity)); Can.write(CAN_TX_msg); } void send_angle() { float current_angle = motor.shaftAngle(); CAN_TX_msg.id = 1; CAN_TX_msg.buf[0] = 'A'; CAN_TX_msg.len = 5; memcpy(&CAN_TX_msg.buf[1], ¤t_angle, sizeof(current_angle)); Can.write(CAN_TX_msg); } void send_motor_enabled() { CAN_TX_msg.id = 1; CAN_TX_msg.buf[0] = 'E'; memcpy(&CAN_TX_msg.buf[1], &motor_control_inputs.motor_enabled, sizeof(motor_control_inputs.motor_enabled)); Can.write(CAN_TX_msg); } void send_data() { send_velocity(); send_angle(); send_motor_enabled(); // read_temperature(); digitalWrite(PC11, !digitalRead(PC11)); } void read_can_step() { char flag = CAN_inMsg.buf[0]; if (flag == 'V') { motor.enable(); memcpy(&motor_control_inputs.target_velocity, &CAN_inMsg.buf[1], sizeof(motor_control_inputs.target_velocity)); } else if (flag == 'A') { motor.enable(); memcpy(&motor_control_inputs.target_angle, &CAN_inMsg.buf[1], sizeof(motor_control_inputs.target_angle)); } else if (flag == 'E') { bool enable_flag = CAN_inMsg.buf[1]; if (enable_flag == 1) { memcpy(&motor_control_inputs.motor_enabled, &CAN_inMsg.buf[1], sizeof(motor_control_inputs.motor_enabled)); motor.enable(); } else if (enable_flag == 0) { memcpy(&motor_control_inputs.motor_enabled, &CAN_inMsg.buf[1], sizeof(motor_control_inputs.motor_enabled)); motor.disable(); } } digitalWrite(PC10, !digitalRead(PC10)); } void foc_step(BLDCMotor *motor, Commander *commander) { if (motor_control_inputs.target_velocity != 0 || motor->controller == MotionControlType::velocity) { if (motor->controller != MotionControlType::velocity) { motor->controller = MotionControlType::velocity; } motor->target = motor_control_inputs.target_velocity; } else { if (motor->controller != MotionControlType::angle) { motor->controller = MotionControlType::angle; } motor->target = motor_control_inputs.target_angle; } motor->loopFOC(); motor->move(); motor->monitor(); commander->run(); } void setup() { Serial.setRx(HARDWARE_SERIAL_RX_PIN); Serial.setTx(HARDWARE_SERIAL_TX_PIN); Serial.begin(115200); // setup led pin pinMode(PC11, OUTPUT); pinMode(PC10, OUTPUT); // Setup thermal sensor pin // pinMode(TH1, INPUT_ANALOG); Can.begin(); Can.setBaudRate(1000000); TIM_TypeDef *Instance = TIM2; HardwareTimer *SendTimer = new HardwareTimer(Instance); SendTimer->setOverflow(100, HERTZ_FORMAT); // 50 Hz SendTimer->attachInterrupt(send_data); SendTimer->resume(); setup_foc(&encoder, &motor, &driver, ¤t_sense, &command, doMotor); } void loop() { foc_step(&motor, &command); while (Can.read(CAN_inMsg)) { read_can_step(); } }