hello,周六休息了一天,出去打本了。趁著夜色,花費了幾個小時,也是將閉環代碼寫完,參考了燈哥的思路。接下來介紹一下我的整個流程:
一、閉環位置控制思路:
其實懂得了開環,那么閉環其實很簡單了。我們可以看函數
void setPhaseVoltage(float Uq,float Ud, float angle_el) {angle_el = _normalizeAngle(angle_el);// 帕克逆變換Ualpha = -Uq*sin(angle_el); Ubeta = Uq*cos(angle_el); // 克拉克逆變換Ua = Ualpha + voltage_power_supply/2;Ub = (sqrt(3)*Ubeta-Ualpha)/2 + voltage_power_supply/2;Uc = (-Ualpha-sqrt(3)*Ubeta)/2 + voltage_power_supply/2;setPwm(Ua,Ub,Uc);
}
????????這個函數的三個參數,首先第一個其實就是力矩大小。第二個我們默認是0,是磁場分量(理論上保持 0,才能保證最大力矩輸出效率)。第三個就是angle_el → 電角度(決定定子磁場的方向,等于是你要把轉子“拉”到哪個位置)
? ? ? ? 那么在我們開環的過程中時候,是給了一個恒定的力。角度也是我們計算 一個規定的角度,其實也差不多就是恒定的角度。那么很簡單,套到閉環的時候,就是這個力,我們需要自己去根據角度來計算。同時,這個電角度也需要實時去計算。然后帶入進去。
接下來給出我的代碼:
CloseLoop.c
#include "CloseLoop.h"float Motor_target = 3.14;
int DIR= 1;
float Cur_Uq = 0.0;
float zero_electric_angle=0;
#define _3PI_2 4.71238898038ffloat _electricalAnglew_without_para(){return _normalizeAngle((float)(DIR * 7) * GetAngle_Without_Track()-zero_electric_angle);
}//開始校準電角度的值
void zero_electric_angle_correct()
{setPhaseVoltage(6,0,_3PI_2);HAL_Delay(3000);zero_electric_angle = _electricalAnglew_without_para();setPhaseVoltage(0,0,_3PI_2);
}float kp = 0.133;
float sensor_Angle;
void closeLoop()
{//0-6.28sensor_Angle =GetAngle();/*這里是這樣計算的,當前我接入的是24v電壓,需要將12v設定為0電壓位置。所以我實際最大為12v。這里我規定,45度偏差的時候,達到最大允許的偏差角度,這個時候輸出最大的糾正力矩,來控制它回正。所以對應關系就是 當前角度偏差/最大允許的45度角度偏差 = 當前輸出電壓/最大允許輸出電壓12v。這樣子就一下子知道對應的關系了,我們需要的是根據當前角度偏差,輸出當前應該給定的電壓所以就是12/45 = 0.266*///把獲取的弧度制,轉化為角度制。角度得到后,通過kp這個比例,轉化到電壓值。Cur_Uq = _constrain(kp*(Motor_target-DIR*sensor_Angle)*180/PI,-6,6);setPhaseVoltage(Cur_Uq, 0, _electricalAnglew_without_para());}
ClsoeLoop.h
#ifndef __CLOSELOOP_H
#define __CLOSELOOP_H
#include "OpenLoop.h"
#include "AS5600.h"
#include "math.h"
float _electricalAnglew_without_para();void zero_electric_angle_correct();
void closeLoop();
#endif
????????這里也說了,這里的kp計算,其實是就是將當前的角度,轉化為力矩。
????????當前我接入的是12v電壓,需要將6v設定為0電壓位置。所以我實際最大為6v。這里我規定,45度偏差的時候,達到最大允許的偏差角度,這個時候輸出最大的糾正力矩,來控制它回正。所以對應關系就是 當前角度偏差/最大允許的45度角度偏差 ?= ? 當前輸出電壓/最大允許輸出電壓6v。這樣子就一下子知道對應的關系了,我們需要的是根據當前角度偏差,輸出當前應該給定的電壓所以就是6/45 = 0.133。
????????里邊寫的是24v,我輸入的也是24v,但是我只用12v的幅值。當然你也可以按照這個來改。但是會出現一變化過快,畢竟電壓大了,力矩變大,加速度就大,速度就大。
為什么會有DIR
DIR
的存在是因為:
-
編碼器測的機械角度方向 ≠ 電機實際需要的方向
-
通過
DIR=±1
可以快速修正這個“方向不一致”的問題 -
如果方向對了,
DIR=+1
;如果電機老是“往反方向跑”,改成DIR=-1
就行了
為什么要做電角度零點標定
也就是函數:void zero_electric_angle_correct()
1. 電角度 vs 機械角度
-
機械角度:編碼器(AS5600、霍爾等)測得的是轉子物理位置 0~2π。
-
電角度:FOC 控制需要的角度是定子電流和轉子磁極之間的相對角度:
-
這個
offset
(偏移量)就是電角度零點。因為轉子磁極和編碼器零點未必對齊。
如果不知道這個偏移,FOC 算出來的電角度就會有一個常數錯誤,結果就是:
電流打不到正確的磁場方向,電機就發抖、狂轉或者根本轉不動。
2. 標定思路
-
給一個固定的定子磁場方向(
_3PI_2
),電機轉子會被吸住,停在這個方向。 -
保持一段時間(3s),讓轉子完全對齊,不再晃動。
-
讀取編碼器角度,這個角度就是轉子在“已知磁場方向”下的位置。
-
保存為 zero offset,以后電角度計算時減去它,就能保證坐標系對齊。
3.為什么電機必須初始化時做?
-
如果不做,電角度和機械角度坐標系不同步,FOC 算出來的電壓會打偏 → 電機亂抖或直接燒 MOS。
-
做一次標定后,系統就知道“編碼器零點” 和 “定子 d 軸” 的對應關系,后續計算電角度時才正確。
現象解決
在調試過程中,我遇到了一些現象。
一、首先是轉速過快,一直慢速跑,沒有說到達目標地方就停下來了。我們進行調試,發現Uq一直是最大的允許電壓值。
那么這種主要是兩方面:
1:看看有沒有正常讀取到角度值,我發現這個排線比較松,調試過程中,觀測發現,角度值有的時候沒有。導致差距一直存在,就一直最大速度轉動。
2、看看DIR是不是反了,可能你需要設定的是-1.即反方向過來。
二、出現抖動,你轉動它到哪個位置,他就在哪個位置。那么這個也可能是DIR設定反了。這時候要立刻關閉電源,以免溫度過高,燒了。
效果展示
智能旋鈕(二)—foc閉環位置控制