User Tools

Site Tools

blog:2024-05-27_simple_foc_8



2024-05-27 SimpleFOC (8) 理論+實務深度分析SVPWM

Local Backup

  • SimpleFOC的教程比較多,做了一個總的鏈接,歡迎點擊閱讀:SimpleFOC教程鏈接匯總

說明

  • SimpleFOC的基本操作在前幾節都已經示範過了,雖然還有很多沒示範的例程,但是觸類旁通,仔細琢磨下難度不大。
  • 網路上關於FOC和SVPWM的文章很多,但大都偏理論,最多用matlab驗證下,本文透過程式示範驗證SVPWM演算法,有助於對理論的理解。對理論沒興趣的同學可以跳過。

一、有感FOC控制原理


  • 有感foc控制原理
  • 1.測量馬達三相定子電流,可得到Ia 和Ib。將三相電流經Clark變換至兩相電流Iα和Iβ ,
  • 2、依照控制環上一次迭代計算出的馬達角度, 透過Park變換得到旋轉座標系下相互正交的電流Id和Iq,
  • 3、Id、 Iq與設定值比較得到電流環PI控制器的輸入。調節PI控制器的參數,得到Vd 和Vq ,即要施加到馬達上的電壓向量,
  • 4、透過位置感測器得到新的馬達位置,從而得到新的角度和轉速。新的馬達角度可告知FOC演算法下一個電壓向量在何處,
  • 5.透過使用新的馬達角度,Vd 和Vq經過Park逆變換產生下一個正交電壓值Vα、Vβ,
  • 6、採用SVPWM演算法判定其合成的電壓向量位於哪個扇區,計算出三相各橋臂開關管的導通時間,最後經過三相逆變器驅動模組輸出馬達所需的三相電壓。

二、SVPWM原理

  • 由三相功率逆變器的六個功率開關元件組成的特定開關模式所產生的脈寬調變波,能夠使馬達電流波形盡可能接近理想的正弦波形。
  • 請看以下這兩片文章:

三、SimpleFOC(不含電流採樣)的控制原理:

  • 首先去掉了電流採樣,所以簡單了很多,有位置感測器,所以不用觀測器估算位置。對空間向量作用時間可以直接利用下面的公式(這些公式來自《SVPWM分析、各個扇區詳細計算以及Matlab模擬》演算法推導的中間狀態,《SVPWM演算法原理及詳解》只寫了第一個扇區) :
  • 對照向量圖,可以總結如下:
  • Udc表示電源電壓(在程式碼中是voltage_limit),Uref表示設定的力矩大小(在程式碼中是target_voltage),Ts表示PWM週期(程式碼中沒有把Ts體現出來,程式碼中的T1、T2是週期的百分比)。

四、SimpleFOC核心程式碼

  • 在simpleFOC工程中,先來看看被創作者稱為核心的程式碼(程式碼路徑: …\Arduino-FOC-minimal\library_source\ BLDCMotor.cpp)
  • 輸入變數Uq、Ud和角度θ,計算3路PWM佔空比。對照上面的SimpleFOC原理框圖,一個函數基本上就把主要工作做完了,確實是核心。

五、程式碼實驗

5.1、實驗目的

  • 透過設定不同的Ud和θ角度來實現不同的波形輸出,並將三相輸出波形與SVPWM的理論波形做比較。
  • 本實驗分兩階段完成,第一階段先直觀感受下SVPWM參數對馬達運轉的影響,第二階段馬達三相輸出波形與理論做比較。

5.2、硬體準備

序號 名稱 數量
1 Arduino UNO 1
2 simpleFOCShield V2.0.3 1
3 雲台馬達 1
4 12V電源 1
5 方口USB線 1
  • 依照開環模式連接

5.3、修改程式碼第一階段

5.3.1 打開例程

5.3.2 修改代碼

  • simpleFOC工程以函式庫的形式安裝到Arduino中,不能修改底層程式碼,所以只能把程式碼複製出來,以子程式的形式放到目前程式中。之所以選擇standalone例程,是因為這個例程比較簡單,而且本身就是示範向量控制的。
    • ①、增加SVPWM演算法的子程序
    • ②、loop循環中呼叫子程序
  • 例程為唯讀文件,可以驗證上傳,如需保存要「另存為」。
  • SVPWM子程序(為了讓程式碼看起來更簡潔,所以程式中沒有約束條件,參數設定一定要依要求範圍輸入):
    • void setPhaseVoltage(float Uq, float Ud, float angle_el) {
        
        int sector = (angle_el / _PI_3) + 1;    // find the sector we are in currently
        float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uq/driver.voltage_limit;
        float T2 = _SQRT3*_sin(angle_el - (sector-1)*_PI_3) * Uq/driver.voltage_limit;
        float T0 = 1 - T1 - T2;
        
        float Ta,Tb,Tc; 
        switch(sector){
          case 1:
            Ta = T1 + T2 + T0/2;
            Tb = T2 + T0/2;
            Tc = T0/2;
            break;
          case 2:
            Ta = T1 +  T0/2;
            Tb = T1 + T2 + T0/2;
            Tc = T0/2;
            break;
          case 3:
            Ta = T0/2;
            Tb = T1 + T2 + T0/2;
            Tc = T2 + T0/2;
            break;
          case 4:
            Ta = T0/2;
            Tb = T1+ T0/2;
            Tc = T1 + T2 + T0/2;
            break;
          case 5:
            Ta = T2 + T0/2;
            Tb = T0/2;
            Tc = T1 + T2 + T0/2;
            break;
          case 6:
            Ta = T1 + T2 + T0/2;
            Tb = T0/2;
            Tc = T1 + T0/2;
            break;
          default:  // possible error state
            Ta = 0;
            Tb = 0;
            Tc = 0;
        }
        // calculate the phase voltages and center
        float Ua = Ta*driver.voltage_limit;
        float Ub = Tb*driver.voltage_limit;
        float Uc = Tc*driver.voltage_limit;
        
        driver.setPwm(Ua,Ub,Uc);
      }

5.3.3 驗證上傳

5.3.4 馬達觀測

  • 上電後馬達開始轉動,目前的轉動方式其實就是開環速度模式。

5.3.5 修改力矩

  • 修改Uq值(範圍0—6.928),重新驗證上傳,會發現馬達的力矩改變了,如果有萬用電表會發現馬達的工作電流隨Uq等比例改變。
  •   注意:Uq值設定越大,力矩越大,電流越大,馬達發熱越嚴重。

5.3.6 修改轉速

  • 修改角度增量,重新驗證上傳,會發現馬達的轉速改變了,
  • 注意:增量越大馬達轉速越快,增量太大電機會因失步變振動。

5.4、修改程式碼第二階段

5.4.1 修改代碼

  • 在第一階段程序的基礎上,
    • ①、增加了串口通信子程序,實現通過串口設置電機的電角度,
    • ②、通信程序放入主循環
    • ③、角度值由上一節的循環增加變為串口設置。注意為了更直觀,串列埠設定的角度單位為“度”,所以會有“度”轉換為“弧度”的計算。
  • 串口通訊子程式:
    • void serialReceiveUserCommand() {
      
        // a string to hold incoming data
        static String received_chars;
      
        while (Serial.available()) {
          // get the new byte:
          char inChar = (char)Serial.read();
          // add it to the string buffer:
          received_chars += inChar;
          // end of user input
          if (inChar == '\n') {
      
            // change the motor target
            theta = received_chars.toFloat();
            Serial.print("Target Angle:");
            Serial.println(theta);
      
            // reset the command buffer
            received_chars = "";
          }
        }
      }

5.4.2 驗證上傳

5.4.3 馬達觀測

  • 程式運轉後,馬達固定在0度位置,類似開環位置模式。

5.4.4 串列埠操作

  • 透過串列埠發送角度值(直接發送數字,範圍0—359),馬達移動到指定的角度。 (此時的角度為電角度,所以馬達在很小的範圍內移動。例如目前用的馬達為7對極,馬達從0轉動到360度,轉過了馬達的1/7圈。電角度和機械角度的概念請自行百度。

5.4.5 觀察三相波形

  • 串口輸入角度,示波器查看三相輸出波形,並與理論做比較。 (示波器只有兩個通道,所以三相波形只能透過拼接得到)
  • ①、30度
  • ②、90度
  • ③、150度
  • ④、210度
  • ⑤、270度
  • ⑥、330度
  • 順便說下,Arduino UNO 的PWM頻率是31.25KHz。 16MHz晶振,時脈不分頻,PWM模式為相位校正模式(Phase Correct PWM Mode,在STM32稱為中央對齊模式),16000/256/2=31.25KHz。
  • 以下是PWM的設定碼(程式碼路徑:…\Arduino-FOC-minimal\library_source\drivers\hardware_specific\atmega328_mcu)
  • 本文涉及理論的部分寫的很籠統,存在用詞不準確,語句不通順的問題,請大家不要太糾結,做為合格的工程師就是要把科學研究人員的理論轉變為可以落地的程式碼,理論不是我的強項也不是我的目標。

請繼續閱讀相關文章:

TAGS

  • 36 person(s) visited this page until now.

Permalink blog/2024-05-27_simple_foc_8.txt · Last modified: 2024/05/27 16:11 by jethro

oeffentlich