由于ST官方MotorControlWorkbench生成的FOC代码过于复杂,决定自己使用正点原子的直流无刷驱动板自己编写FOC去控制PMSM电机。FOC代码参考的是灯哥的教材DengFOC官方文档。
1、配置TIM1高级定时器
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 operationreturn 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 valuesdc_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 valuesuint32_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 angleangle_el = _normalizeAngle(angle_el + zero_electric_angle);// Inverse Park transformUalpha = -Uq * sin(angle_el);Ubeta = Uq * cos(angle_el);// Inverse Clarke transformUa = 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 FOCsetPhaseVoltage(4.0,0,3.14);//uq = 4.0V ud = 0V, rad = 3.14