一:使用正点原子的直流无刷驱动板自写FOC控制永磁同步(PMSM)电机(位置开环)
由于ST官方MotorControlWorkbench生成的FOC代码过于复杂,决定自己使用正点原子的直流无刷驱动板自己编写FOC去控制PMSM电机。FOC代码参考的是灯哥的教材DengFOC官方文档。
1、配置TIM1高级定时器
重映射IO口并配置
2、foc.c代码
/* * foc.c * * Created on: Dec 11, 2024 * Author: ME-LZQ */ #include "main.h" // Constants #define PI 3.14159265359f #define PWM_RESOLUTION 5250.0f // Global variables float voltage_power_supply = 24.0f; // Supply voltage float zero_electric_angle = 0.0f; // Zero electrical angle float cur_angle = 0; // PWM duty cycles float dc_a = 0.0f; float dc_b = 0.0f; float dc_c = 0.0f; // Intermediate variables float Ualpha = 0.0f; float Ubeta = 0.0f; float Ua = 0.0f; float Ub = 0.0f; float Uc = 0.0f; // Constrain function float _constrain(float x, float min, float max) { if (x < min) return min; if (x > max) return max; return x; } // Calculate electrical angle float _electricalAngle(float shaft_angle, int pole_pairs) { return (shaft_angle * pole_pairs); } // Normalize angle to [0, 2PI] float _normalizeAngle(float angle) { float a = fmod(angle, 2 * PI); // Modulo operation return a >= 0 ? a : (a + 2 * PI); } // Set PWM output to the controller void setPwm(float Ua, float Ub, float Uc) { // Calculate duty cycles and constrain values dc_a = _constrain(Ua / voltage_power_supply, 0.0f, 1.0f); dc_b = _constrain(Ub / voltage_power_supply, 0.0f, 1.0f); dc_c = _constrain(Uc / voltage_power_supply, 0.0f, 1.0f); // Convert duty cycles to PWM values uint32_t pwm_a = (uint32_t)(dc_a * PWM_RESOLUTION); uint32_t pwm_b = (uint32_t)(dc_b * PWM_RESOLUTION); uint32_t pwm_c = (uint32_t)(dc_c * PWM_RESOLUTION); // TODO: Replace with actual platform-specific PWM output __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm_a); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, pwm_b); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, pwm_c); } // Set phase voltage for motor control void setPhaseVoltage(float Uq, float Ud, float angle_el) { // Normalize electrical angle angle_el = _normalizeAngle(angle_el + zero_electric_angle); // Inverse Park transform Ualpha = -Uq * sin(angle_el); Ubeta = Uq * cos(angle_el); // Inverse Clarke transform Ua = Ualpha + voltage_power_supply / 2.0f; Ub = (sqrt(3.0f) * Ubeta - Ualpha) / 2.0f + voltage_power_supply / 2.0f; Uc = (-Ualpha - sqrt(3.0f) * Ubeta) / 2.0f + voltage_power_supply / 2.0f; // Write to PWM channels setPwm(Ua, Ub, Uc); } //Init FOC,start the PWM for U, V, W, and their complementary channels. void initFoc() { // Start PWM output on TIM1 Channel 1 (main output) if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK) Error_Handler(); // Start complementary PWM output on TIM1 Channel 1 (n output) if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1) != HAL_OK) Error_Handler(); // Start PWM output on TIM1 Channel 2 (main output) if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK) Error_Handler(); // Start complementary PWM output on TIM1 Channel 2 (n output) if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2) != HAL_OK) Error_Handler(); // Start PWM output on TIM1 Channel 3 (main output) if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK) Error_Handler(); // Start complementary PWM output on TIM1 Channel 3 (n output) if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3) != HAL_OK) Error_Handler(); }
3、初始化FOC,设置uq,ud,以及电角度rad,就可以让电机保持在rad位置
initFoc();//Init FOC setPhaseVoltage(4.0,0,3.14);//uq = 4.0V ud = 0V, rad = 3.14