找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 9713|回復(fù): 12
收起左側(cè)

無刷無感電機過零檢測單片機源程序

  [復(fù)制鏈接]
ID:299262 發(fā)表于 2018-3-30 09:18 | 顯示全部樓層 |閱讀模式
附件中的源文件是無感三相電機零速定位,開環(huán)加速以前閉環(huán)控制(含過零檢測的程序)

單片機源程序如下:

  1. #include "hardware.h"
  2. #include "bldc.h"

  3. u16 Temp = 0;

  4. volatile State_TypeDef State = Idle;

  5. Task_TypeDef Task;

  6. Flag_TypeDef Flag;

  7. vu16        ADC_VALUE[ADC_NUMBER*ADC_BUFFER]={0};
  8. u16          SysTime = 0;                                                                                                                                                                                /* 系統(tǒng)時間 */
  9. u8                 Phase = 0;                                                                                                                                                                                        /* 通電繞組 */
  10. u16         PwmDuty = 0;                                                                                                                                                                                /* PWM占空比 */
  11. u8                 AlignRotorCount = 0;                                                                                                                                                /* 電機啟動時鎖定轉(zhuǎn)子的次數(shù) */
  12. u8                 BlankingCount = 0;                                                                                                                                                        /* 消隱時長 */
  13. //u8         ZeroBeforeCount = 0;                                                                                                                                                /* 過零點之前的檢測次數(shù) */
  14. u8                 ZeroCrossCount = 0;                                                                                                                                                        /* 到達(dá)過零點的檢測次數(shù) */
  15. u8                 ZeroAcquireCount = 0;                                                                                                                                                /* 進(jìn)入到同步運行狀態(tài)前的過零點次數(shù) */
  16. u16         CommutateTime = 0;                                                                                                                                                        /* 過零檢測到到換向的時間 */
  17. u16         AccelerateCommutateTime = 0;                                                                                                                /* 電機加速的換向的時間 */
  18. u16         AdcPotentiometer = 0;                                                                                                                                                /* 電位器ADC轉(zhuǎn)換結(jié)果 */
  19. u16         AdcBEMF = 0;                                                                                                                                                                                /* BEMF電壓ADC轉(zhuǎn)換結(jié)果 */
  20. u16         AdcCurrent = 0;                                                                                                                                                                        /* 電流放大器ADC轉(zhuǎn)換結(jié)果 */
  21. u16         AdcVbus = 0;                                                                                                                                                                                /* 電源電壓ADC轉(zhuǎn)換結(jié)果 */
  22. u16         ZeroVref = 0;                                                                                                                                                                                /* 過零檢測基準(zhǔn)電壓,等于電源電壓的一半 */
  23. u8                 SpeedErrorCount = 0;                                                                                                                                                /* 電機速度異常次數(shù) */
  24. u16         ZeroPeriod = 1000;                                                                                                                                                        /* 過零周期即60度換向時間 */
  25. u16         MotorRpm = 0;                                                                                                                                                                                /* 電機轉(zhuǎn)速,單位RPM */
  26. u16                AccelerateTime = 0;                                                                                                                                                        /* 電機加速運轉(zhuǎn)的時間 */
  27. //u16 PhaseAdvance = 0;                                                                                                                                                                /* 超前相位 */
  28. u16         Current = 0;                                                                                                                                                                                /* 電流值 */
  29. u16         Iref = 0;                                                                                                                                                                                                /* 電流放大器輸出偏置 */

  30. #define MaxIX                                                                999                                                                                                                         //最大記錄條數(shù)
  31. vu16        BEMF_REC[MaxIX+1]={0};                                                                                                                                        // 反電動勢記錄
  32. u16   ix = 0;                                                                                                                                                                                                        // 記錄下標(biāo)
  33. /********************************************************************************************
  34. * Function Name  : void Scan_Key(void)
  35. * Description    : 按鍵掃描程序,用于啟動或者停止電機運轉(zhuǎn)
  36. * Input          : 無
  37. * Return         : 無
  38. *********************************************************************************************/
  39. void Scan_Key(void)
  40. {
  41.     if(Key_Status() == PRESS)
  42.     {
  43.         if(State == Idle)
  44.         {
  45.             while(Key_Status() != RELEASE);
  46.             State = Start;
  47.         }
  48.         else
  49.         {
  50.             while(Key_Status() != RELEASE);
  51.             State = Stop;
  52.         }
  53.     }
  54. }


  55. void Start_Motor(void)
  56. {
  57.     Close_LED7();
  58.     Close_LED8();
  59.     Close_LED9();

  60.     Flag.AcquireZero         = 0;
  61.     Flag.ZeroCross                 = 0;
  62.     SpeedErrorCount                = 0;
  63.     AccelerateTime                 = 0;
  64.     AlignRotorCount         = 3;                                                                                                                                                                                                                                /* 初始化電機轉(zhuǎn)子定位次數(shù) */

  65.     Update_PwmDuty((u32)ALIGN_ROTOR_PWM*FULL_DUTY/100);
  66.     Phase                                                 = 0;
  67.     Commutate();
  68.     TIM_CtrlPWMOutputs(TIM1, ENABLE);
  69.     State                                                 = AlignRotor;
  70.     SysTime                                         = 0;
  71.     Task.AlignRotor         = 0;
  72.     printf("Start AlignRotor !!!\n\r");
  73. }

  74. /********************************************************************************************
  75. * Function Name  : void AlignMotorRotor(void)
  76. * Description    : 轉(zhuǎn)子定位程序
  77. * Input          : 無
  78. * Return         : 無
  79. *********************************************************************************************/
  80. void Align_MotorRotor(void)
  81. {
  82.     if(AlignRotorCount > 0)
  83.     {
  84.                                 Phase                                                 = 0;
  85.         Commutate();
  86.         Update_PwmDuty((u32)ALIGN_ROTOR_PWM*FULL_DUTY/100);
  87.         AlignRotorCount --;
  88.         if (AlignRotorCount == 0)
  89.         {
  90.             Update_PwmDuty((u32)PWM_ACCELERATE_START*FULL_DUTY/100);                                                                                //更新初始加速占空比
  91.             AccelerateCommutateTime = TIM2_FREQ*20/START_RPM/MOTOR_POLES;                                                                //設(shè)計初始加速時間參數(shù)

  92.             /* 啟動TIM2,進(jìn)入到加速狀態(tài) */
  93.             TIM2_Counter = 0;
  94.             Clear_TIM2_Update_IF();
  95.             Enable_TIM2_Update_IT();

  96.             Clear_TIM1_CC4_IF();
  97.             Enable_TIM1_CC4_IT();

  98.             State = Accelerate;
  99.             //State = Stop;
  100.         }
  101.     }
  102. }

  103. void Commutate(void)
  104. {
  105.     Disable_AH();
  106.     Disable_AL();
  107.     Disable_BH();
  108.     Disable_BL();
  109.     Disable_CH();
  110.     Disable_CL();

  111.     switch(Phase)
  112.     {
  113.         case 0:                                                                                                                                                                                                                                                                                                /* AB相 */
  114.         {
  115.             //Disable_CH();
  116.             Enable_AH();
  117.             Enable_BL();
  118.             #if (DIRECTION == COUNTER_CLOCKWISE)
  119.                 Flag.BemfEdge = FALLING;
  120.                 Phase = 1;
  121.             #else
  122.                 Flag.BemfEdge = RISING;
  123.                 Phase = 5;
  124.             #endif
  125.         }
  126.         break;

  127.         case 1:                                                                                                                                                                                                                                                                                                /* AC相 */
  128.         {
  129.             Enable_AH();
  130.             //Disable_BL();
  131.             Enable_CL();
  132.             #if (DIRECTION == COUNTER_CLOCKWISE)
  133.                 Flag.BemfEdge = RISING;
  134.                 Phase = 2;
  135.             #else
  136.                 Flag.BemfEdge = FALLING;
  137.                 Phase = 0;
  138.             #endif
  139.         }
  140.         break;

  141.         case 2:                                                                                                                                                                                                                                                                                                /* BC相 */
  142.         {
  143.             //Disable_AH();
  144.             Enable_BH();
  145.             Enable_CL();
  146.             #if (DIRECTION == COUNTER_CLOCKWISE)
  147.                 Flag.BemfEdge = FALLING;
  148.                 Phase = 3;
  149.             #else
  150.                 Flag.BemfEdge = RISING;
  151.                 Phase = 1;
  152.             #endif
  153.         }
  154.         break;
  155.                                
  156.         case 3:                                                                                                                                                                                                                                                                                                /* BA相 */
  157.         {
  158.             Enable_BH();
  159.             //Disable_CL();
  160.             Enable_AL();
  161.             #if (DIRECTION == COUNTER_CLOCKWISE)
  162.                 Flag.BemfEdge = RISING;
  163.                 Phase = 4;
  164.             #else
  165.                 Flag.BemfEdge = FALLING;
  166.                 Phase = 2;
  167.             #endif
  168.         }
  169.         break;

  170.         case 4:                                                                                                                                                                                                                                                                                                /* CA相 */
  171.         {
  172.             //Disable_BH();
  173.             Enable_CH();
  174.             Enable_AL();
  175.             #if (DIRECTION == COUNTER_CLOCKWISE)
  176.                 Flag.BemfEdge = FALLING;
  177.                 Phase = 5;
  178.             #else
  179.                 Flag.BemfEdge = RISING;
  180.                 Phase = 3;
  181.             #endif
  182.         }
  183.         break;

  184.         case 5:                                                                                                                                                                                                                                                                                                /* CB相 */
  185.         {
  186.             Enable_CH();
  187.             //Disable_AL();
  188.             Enable_BL();
  189.             #if (DIRECTION == COUNTER_CLOCKWISE)
  190.                 Flag.BemfEdge = RISING;
  191.                 Phase = 0;
  192.             #else
  193.                 Flag.BemfEdge = FALLING;
  194.                 Phase = 4;
  195.             #endif
  196.         }
  197.         break;

  198.         default:
  199.             break;
  200.     }

  201.     Flag.ZeroCross = 0;
  202.     BlankingCount = BLANKING_COUNT;
  203.     ZeroCrossCount = 0;
  204. }

  205. void Stop_Running(void)
  206. {
  207.     Disable_PwmOutput();
  208.     Clear_TIM1_CC4_IF();
  209.     Disable_TIM1_CC4_IT();
  210.     Clear_TIM2_Update_IF();
  211.     Disable_TIM2_Update_IT();
  212.     State = Idle;

  213.     if(Flag.FailedStart)                                                                                                                                                                                                                                                                                        /* 輸出錯誤標(biāo)志 */
  214.     {
  215.         Flag.FailedStart = 0;
  216.         printf("Error: Failed to start!!!\n\r");
  217.     }

  218.     if(Flag.CurrentHigh)
  219.     {
  220.         Flag.CurrentHigh = 0;
  221.         printf("Error: Current is too large!!!\n\r");
  222.     }

  223.     if(Flag.SpeedHigh)
  224.     {
  225.         Flag.SpeedHigh = 0;
  226.         printf("Error: Motor speed is too high !!!\n\r");
  227.     }

  228.     if(Flag.SpeedLow)
  229.     {
  230.         Flag.SpeedLow = 0;
  231.         printf("Error: Motor speed is too low !!!\n\r");
  232.     }

  233.     if(Flag.LostZero)
  234.     {
  235.         Flag.LostZero = 0;
  236.         printf("Error: Sensor error !!!\n\r");
  237.     }

  238.     printf("Motor stop !!!\n\r");
  239. }
  240. //  ROUNDUP(    INDIRECT("E7") * 20      /    (    INDIRECT("D13")*   B7*B7   /   INDIRECT("F13")   /    INDIRECT("F13")   +   INDIRECT("F7")   )  /   INDIRECT("G7")            ,0     )
  241. void Accelerate_Motor(void)                                                                                                                                                                                                                                                                                // 加速
  242. {
  243.     u16 speed = 0;                                                                                                                                                                                                                                                                                                     // 新的目標(biāo)速度
  244.     u32 ct = 0;                                                                                                                                                                                                                                                                                                        // 新的換向時間

  245.     speed = ((u32)AccelerateTime*AccelerateTime)/ACCELERATE_TIME;                                                                                                                        /* 計算新的目標(biāo)速度 */
  246.     speed = ((u32)(END_RPM - START_RPM)*speed)/ACCELERATE_TIME;
  247.     speed += START_RPM;
  248.                
  249.     ct = (u32)TIM2_FREQ*20/speed/MOTOR_POLES;                                                                                                                                                                                                        /* 將速度轉(zhuǎn)換為相應(yīng)的換向時長 */
  250.                
  251.                 //ct = AccelerateCommutateTime*14/15-1;
  252.     if(ct > 65535)        AccelerateCommutateTime = 65535;
  253.     else                                                AccelerateCommutateTime = ct;
  254.        
  255.                

  256.     PwmDuty = ((u32)PWM_ACCELERATE_DELTA*AccelerateTime/ACCELERATE_TIME);                                                                                        /* 計算PWM增量 */
  257.     PwmDuty += (u16)((u32)PWM_ACCELERATE_START*FULL_DUTY/100);                                                                                                                                /* 更新PWM */
  258.     Update_PwmDuty(PwmDuty);

  259.     if((AccelerateCommutateTime <= TIM2_FREQ*20/ZERO_ACQUIRE_RPM/MOTOR_POLES)&&                                                                /* 開始捕獲過零點 */
  260.        (Flag.AcquireZero == 0))
  261.     {
  262.                                 Flag.AcquireZero = 1;
  263.         ZeroAcquireCount = 0;
  264. //                                Open_LED7();
  265.                 }

  266.                 if(AccelerateCommutateTime <= TIM2_FREQ*20/END_RPM/MOTOR_POLES)                                                                                                                /* 加速到啟動終止速度時,啟動失敗 */
  267.     {
  268.         State = Stop;
  269.         Flag.FailedStart = 1;
  270.                                 Open_LED6();
  271.                 }
  272. }

  273. void Check_ZeroCrossing(void)
  274. {
  275.     u16 t = 0;

  276.     if(BlankingCount > 0)                                                                                                                                                /* 等待消隱 */
  277.     {
  278.         BlankingCount --;
  279.         return;
  280.     }

  281.     if((Flag.BemfEdge == FALLING)&&(AdcBEMF < ZeroVref))                /* 判斷BEMF電壓是否過零 */
  282.         ZeroCrossCount ++;

  283.     if((Flag.BemfEdge == RISING)&&(AdcBEMF > ZeroVref))
  284.         ZeroCrossCount ++;
  285.        
  286.     //Open_LED7();
  287.     if (ZeroCrossCount > ZERO_SAMPLES-1)                                                                                /* 達(dá)到預(yù)期的過零次數(shù) */
  288.     {
  289.                                 BEMF_REC[ix] = AdcBEMF;
  290.                                 ix++;
  291.                                 if(ix>MaxIX) ix = 0;
  292.         //Open_LED8();
  293.         ZeroPeriod = TIM3_Counter;                                                                                                        /* 從TIM3計數(shù)器讀取2次過零點的周期 */
  294.         TIM3_Counter = 0;

  295.         t = ZeroPeriod >> 1;                                                                                                                                /* 計算30度換向時長 */
  296.         CommutateTime = ((u32)t * (30 - ADVANCE_ANGLE))/30;        /* 超前相位補償 */

  297.         if(CommutateTime > ZERO_CHECK_DELAY)                                                                /* ADC過零檢測延遲補償 */
  298.                                           CommutateTime -= ZERO_CHECK_DELAY;
  299.         else
  300.             CommutateTime = 1;

  301.         if (State == Running)
  302.         {
  303.             Flag.ZeroCross = 1;

  304.             Disable_TIM2_Update_IT();
  305.             TIM2->ARR = CommutateTime;
  306.             TIM2_Counter = 0;
  307.             Clear_TIM2_Update_IF();
  308.             Enable_TIM2_Update_IT();
  309.                                                 Open_LED9();                                                                                                                                                // 標(biāo)志著已經(jīng)切換到閉環(huán)控制狀態(tài)
  310.         }
  311.         else                                                                                                                                                                                                /* 電機加速到同步運轉(zhuǎn)狀態(tài)的判斷 */
  312.         {
  313.             ZeroAcquireCount ++;
  314.             
  315.             if(ZeroAcquireCount > ZERO_ACQUIRE_COUNT-1)                        /* 進(jìn)入過零點同步狀態(tài) */
  316.             {
  317.                 Flag.ZeroCross = 1;
  318.                 Disable_TIM2_Update_IT();
  319.                 Flag.AcquireZero = 0;
  320.                 State = Running;

  321.                 TIM2->ARR = CommutateTime;                                                                        /* 更新TIM2定時換向 */
  322.                 TIM2_Counter = 0;
  323.                 Clear_TIM2_Update_IF();
  324.                 Enable_TIM2_Update_IT();
  325. //                                                                Open_LED9();                                                                                                                                // 標(biāo)志著已經(jīng)從開環(huán)加速正在切換到閉環(huán)控制狀態(tài)
  326.             }
  327.         }
  328.     }
  329. }

  330. /********************************************************************************************
  331. * Function Name  : void Get_MotorSpeed(void)
  332. * Description    : 計算電機速度程序
  333.                    RPM = 60/((60°換向周期(秒)*6)*(極數(shù)/2)) = 20/(T*P)
  334. * Input          : 無
  335. * Return         : 無
  336. *********************************************************************************************/
  337. void Get_MotorSpeed(void)
  338. {
  339.     static u16 t = 0;

  340.     t += ZeroPeriod;                                                                                                                                                        /* 計算2次60度換向周期的平均值 */
  341.     t = t >> 1;
  342.     MotorRpm = (u32)TIM2_FREQ*20/t/MOTOR_POLES;                                                /* RPM = 60/((60°換向周期(秒)*6)*(極數(shù)/2)) = 20/(T*P) */
  343. }

  344. void Control_Speed(void)
  345. {
  346.     u16 duty = 0;

  347.     duty = ((u32)AdcPotentiometer*FULL_DUTY)/4095;                                /* 將ADC轉(zhuǎn)換結(jié)果線性轉(zhuǎn)換為PWM的占空比 */
  348.     if(duty > PwmDuty)                                                                                                                                                /* 逐漸調(diào)整PWM占空比,避免占空比調(diào)整步長太大導(dǎo)致電機失速 */
  349.     {
  350.         PwmDuty += 4;
  351.         if(PwmDuty > FULL_DUTY)                PwmDuty = FULL_DUTY;
  352.     }
  353.     else if(duty < PwmDuty)
  354.     {
  355.         if(PwmDuty < 4)         PwmDuty = 0;
  356.         else                                 PwmDuty -= 4;
  357.     }
  358.     else     return;
  359.     Update_PwmDuty(PwmDuty);                                                                                                                        /* 更新PWM占空比 */
  360. }

  361. /********************************************************************************************
  362. * Function Name  : void Monitor_Speed(void)
  363. * Description    : 電機失速監(jiān)控程序
  364. * Input          : 無
  365. * Return         : 無
  366. *********************************************************************************************/
  367. void Monitor_Speed(void)
  368. {
  369.     if(MotorRpm < MIN_SPEED)                                                                                                                        /* 檢查電機速度是否過低 */
  370. ……………………

  371. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼

下載:
bldc.rar (3.46 KB, 下載次數(shù): 183)

回復(fù)

使用道具 舉報

ID:268389 發(fā)表于 2018-4-19 21:03 | 顯示全部樓層
正在做相關(guān)方向,參考一下,謝謝無私分享
回復(fù)

使用道具 舉報

ID:324611 發(fā)表于 2018-7-9 11:00 | 顯示全部樓層
好東西,學(xué)習(xí)下。
回復(fù)

使用道具 舉報

ID:324611 發(fā)表于 2018-7-9 11:01 | 顯示全部樓層
正在研究BLCD相關(guān)的東西,學(xué)習(xí)下。
回復(fù)

使用道具 舉報

ID:427831 發(fā)表于 2018-11-16 17:16 | 顯示全部樓層
led是8位IO口嗎?沒太看懂你的
回復(fù)

使用道具 舉報

ID:460143 發(fā)表于 2019-1-2 15:43 | 顯示全部樓層
樓主可以提供電路圖嗎?
回復(fù)

使用道具 舉報

ID:460143 發(fā)表于 2019-1-2 16:15 | 顯示全部樓層
程序中的兩個頭文件在哪里呢?
回復(fù)

使用道具 舉報

ID:691135 發(fā)表于 2020-2-10 22:51 | 顯示全部樓層
正在做相關(guān)方向,參考一下,謝謝無私分享,如果有原理圖配合程序那就更完美了。
回復(fù)

使用道具 舉報

ID:967978 發(fā)表于 2021-9-28 14:05 | 顯示全部樓層
請問樓主有頭文件嗎?
回復(fù)

使用道具 舉報

ID:640527 發(fā)表于 2021-10-18 10:45 | 顯示全部樓層
正要做這塊,幫大忙了,非常感謝
回復(fù)

使用道具 舉報

ID:194006 發(fā)表于 2021-11-27 21:03 | 顯示全部樓層
正在學(xué)習(xí)無刷驅(qū)動,謝謝分享
回復(fù)

使用道具 舉報

ID:826226 發(fā)表于 2022-1-7 18:14 | 顯示全部樓層
有更完整源碼嗎?
回復(fù)

使用道具 舉報

ID:412301 發(fā)表于 2023-9-9 15:51 | 顯示全部樓層
配上原理圖就更完善了
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表