一:使用正点原子的直流无刷驱动板自写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();

}
View Code

3、初始化FOC,设置uq,ud,以及电角度rad,就可以让电机保持在rad位置

  initFoc();//Init FOC
  setPhaseVoltage(4.0,0,3.14);//uq = 4.0V ud = 0V, rad = 3.14

 

posted @ 2024-12-12 11:45  阿坦  阅读(84)  评论(0编辑  收藏  举报