BLDC電機(jī)原理以及開發(fā)板電機(jī)驅(qū)動能力評測(含工程源碼)

原創(chuàng) 面包板社區(qū) 2022-01-21 20:00

前段時間公務(wù)繁忙,收到的MM32SPIN160C開發(fā)板也無暇顧及,趁周末時間,來體驗一下這款開發(fā)板的電機(jī)驅(qū)動能力。


一、硬件方面:
板卡為專用電機(jī)驅(qū)動板,因此底板加了一塊散熱片,開發(fā)板的四腳加了腳墊,以便更好地散熱,防止底板電路與金屬物件接觸而導(dǎo)致短路。開發(fā)板采用ARM Cortex-M0的32位MCU,MCU最高工作頻率可達(dá)72MHz,內(nèi)置高速存儲器,豐富的I/O 端口和外設(shè)連接到外部總線。具有1個12位的ADC、1個比較器、1個16位通用定時器、1個32位通用定時器、3個16位基本定時器和1個16位高級定時器。還包含標(biāo)準(zhǔn)的通信接口,即1個I2C接口、1個SPI接口和1個UART接口。適合開發(fā)吊風(fēng)扇,電動工具,三相永磁無刷電機(jī)等多種應(yīng)用場合。
? ?? ? 由MM32SPIN160C的名稱可知該型號的基礎(chǔ)配置

? ?? ? 開發(fā)板主要功能列表:
①、輸入電壓范圍: 12V~28V
②、使用60V/40A N-MOS管*6
③、使用外掛(SPIN0x) GBW 6MHz 高速運(yùn)放*4
④、MCU 電源使用5V
⑤、支持有/無霍, 方波/弦波驅(qū)動
⑥、支持1/2 Shunt R 三相電流采樣
⑦、BEMF 電壓回授使用ADC 采樣
⑧、DC Bus 電壓, 總電流量測
⑨、使用MCU 內(nèi)建比較器做為過電流保護(hù)
? ?? ? 在淘寶上買了個尼得科無刷電機(jī),無刷電機(jī)最大優(yōu)點(diǎn)是沒有碳刷轉(zhuǎn)換器,壽命長,適合長時間工作的場所。
? ?? ?【額定電壓】DC 12V
? ?? ?【空載電流】1A
? ?? ?【額定功率】10W
? ?? ?【空載轉(zhuǎn)速】12000轉(zhuǎn)/分鐘
? ?? ?【適合電壓】6-12V(6000-12000轉(zhuǎn))
? ?? ?【重量】130克

? ?? ?? ? 電機(jī)的接口線路如下圖所示:


二、電路圖方面
? ?? ?關(guān)于該開發(fā)板的PCBA點(diǎn)位圖如下:

開發(fā)板的電路原理圖如下:


三、開發(fā)環(huán)境方面
板上集成了JLink調(diào)試接口,支持串行調(diào)試(SWD),官方提供的資源包中包括基本工程示例,可使用IAR、MDK工具打開,本人習(xí)慣使用MDK,因此將基本工程示例導(dǎo)入進(jìn)Keil中,如果電腦聯(lián)網(wǎng),此時會提示安裝“MindMotion.MM32SPIN0x_DFP.1.0.8”pack包;如果電腦處于離線狀態(tài),可從靈動微官網(wǎng)下載基于MM32SPIN160C開發(fā)板的pack包,如下附件,然后將pack導(dǎo)入Keil工具中,而后直接編譯即可。


將JLink燒錄器與開發(fā)板上的CN7接口相連接,Keil中設(shè)置SWD模式,即可識別到調(diào)試器,并設(shè)置燒錄后自動重啟。


然后將開發(fā)板上CN1、CN2、CN3與電機(jī)、電源適配器正確連接,由于板卡支持12~28V的電壓輸入,而電機(jī)的額定電壓是12V,因此采用12V/1A的電源適配器,實(shí)物連線圖如下:




采用不帶霍爾的輪詢控制方式,直接燒錄后,電機(jī)起震,沒有如期得向逆時針或順時針旋轉(zhuǎn),現(xiàn)象如同是前進(jìn)兩步后退兩步,一直在抖動。在線調(diào)試,發(fā)現(xiàn)驅(qū)動換相函數(shù)存在問題,每種無刷電機(jī)的接線有所差異。關(guān)于BLDC電機(jī),推薦看看TI的技術(shù)視頻教程深入理解無刷直流電機(jī)(BLDC)原理以及控制,關(guān)于有刷電機(jī)與無刷電機(jī)的工作原理如下:

??? ? 由上圖,有刷電機(jī)的主要結(jié)構(gòu)就是定子+轉(zhuǎn)子+電刷,通過旋轉(zhuǎn)磁場獲得轉(zhuǎn)動力矩,從而輸出動能。電刷與換向器不斷接觸摩擦,在轉(zhuǎn)動中起到導(dǎo)電和換相作用。有刷電機(jī)采用機(jī)械換向,磁極不動,線圈旋轉(zhuǎn)。電機(jī)工作時,線圈和換向器旋轉(zhuǎn),磁鋼和碳刷不轉(zhuǎn),線圈電流方向的交替變化是隨電機(jī)轉(zhuǎn)動的換相器和電刷來完成的。

? ? ? ?由上圖,無刷電機(jī)中,換相的工作交由控制器中的控制電路(一般為霍爾傳感器+控制器,更先進(jìn)的技術(shù)是磁編碼器)來完成。無刷電機(jī)采取電子換向,線圈不動,磁極旋轉(zhuǎn)。無刷電機(jī),是使用一套電子設(shè)備,通過霍爾元件,感知永磁體磁極的位置,根據(jù)這種感知,使用電子線路,適時切換線圈中電流的方向,保證產(chǎn)生正確方向的磁力,來驅(qū)動電機(jī),消除了有刷電機(jī)的缺點(diǎn)。
? ?? ? 四、工程源碼
部分源碼如下:

  1. #include "sys.h"


  2. typedef enum {

  3. ? ? CW? ?? ?= 0,? ? // 順時鐘方向

  4. ? ? CCW? ???= 1? ???// 逆時針方向

  5. } motor_dir_t;


  6. typedef enum {

  7. ? ? START? ?= 0,? ? // 啟動

  8. ? ? STOP? ? = 1,? ? // 停機(jī)

  9. ? ? RUN? ???= 2? ???// 運(yùn)行

  10. } motor_state_t;


  11. typedef struct{

  12. ? ? motor_dir_t tMotorDirection;? ?? ???// 電機(jī)旋轉(zhuǎn)方向

  13. ? ? motor_state_t tMotorState;? ?? ?? ? // 電機(jī)狀態(tài)

  14. ? ? uint16_t tDuty;? ?? ?? ?? ?? ?? ?? ?// 速度占空比:0~100??為100是占空比為100%

  15. ? ? uint16_t tSpeed;? ?? ?? ?? ?? ?? ???// 電機(jī)轉(zhuǎn)速

  16. ? ? uint8_t chHallValue;? ?? ?? ?? ?? ? // 霍爾狀態(tài)

  17. ? ? struct{

  18. ? ?? ???uint8_t chStartCount;? ?? ?? ???// 啟動計數(shù)

  19. ? ?? ???uint16_t hwTimeCount;? ?? ?? ???// 堵轉(zhuǎn)超時溢出計數(shù)

  20. ? ? }tCount;

  21. }User_TypeDef_t;


  22. volatile User_TypeDef_t g_tMotor = {

  23. ? ? CW,

  24. ? ? START,

  25. ? ? 40,

  26. ? ? 0,

  27. ? ? 1,

  28. ? ? 0,

  29. ? ? 0

  30. };


  31. extern void Bldc_Phase_Chaneg(uint8_t step);

  32. extern void Hall_Exti_Callback(void);

  33. extern void Systick_Callback(void);


  34. int main(void)

  35. {

  36. ? ? Systick_Init();

  37. ? ?

  38. ? ? Led_Init();

  39. ? ? Hall_Init();

  40. ? ? Bldc_Pwm_Init();

  41. ? ? Gate_Driver_Init();


  42. ? ? while(1) {

  43. ? ?? ???switch(g_tMotor.tMotorState) {

  44. ? ?? ?? ?? ?case START:? ?? ?? ?// 電機(jī)啟動

  45. ? ?? ?? ?? ?? ? if(++g_tMotor.tCount.chStartCount > 20){? ? //電機(jī)啟動失敗

  46. ? ?? ?? ?? ?? ?? ???g_tMotor.tMotorState = STOP;

  47. ? ?? ?? ?? ?? ?? ???g_tMotor.tCount.chStartCount = 0;

  48. ? ?? ?? ?? ?? ? }

  49. ? ?? ?? ?? ?? ? SET_DUTY_U(BLDC_TIM_PERIOD * g_tMotor.tDuty / 100);

  50. ? ?? ?? ?? ?? ? SET_DUTY_V(BLDC_TIM_PERIOD * g_tMotor.tDuty / 100);

  51. ? ?? ?? ?? ?? ? SET_DUTY_W(BLDC_TIM_PERIOD * g_tMotor.tDuty / 100);

  52. ? ?? ?? ?? ?? ? GATE_DRIVER_ENABLE();

  53. ? ?? ?? ?? ?? ? Hall_Exti_Callback();

  54. ? ?? ?? ?? ?? ? Systick_Delay(5);

  55. ? ?? ?? ?? ?? ? break;

  56. ? ?? ?? ?? ?case RUN:? ?? ?? ?// 電機(jī)運(yùn)行

  57. ? ?? ?? ?? ?? ? if (0){//some err

  58. ? ?? ?? ?? ?? ?? ???g_tMotor.tMotorState = STOP;

  59. ? ?? ?? ?? ?? ? }

  60. ? ?? ?? ?? ?? ? Hall_Exti_Callback();

  61. ? ?? ?? ?? ?? ? break;

  62. ? ?? ?? ?? ?case STOP:? ?? ?? ?// 停機(jī)

  63. ? ?? ?? ?? ?? ? GATE_DRIVER_DISABLE();

  64. ? ?? ?? ?? ?? ? BLDC_UH_DISABLE();

  65. ? ?? ?? ?? ?? ? BLDC_UL_DISABLE();

  66. ? ?? ?? ?? ?? ? BLDC_VH_DISABLE();

  67. ? ?? ?? ?? ?? ? BLDC_VL_DISABLE();

  68. ? ?? ?? ?? ?? ? BLDC_WH_DISABLE();

  69. ? ?? ?? ?? ?? ? BLDC_WL_DISABLE();

  70. ? ?? ?? ?? ?? ? break;

  71. ? ?? ???}

  72. ? ? }

  73. }


  74. void Bldc_Phase_Chaneg(uint8_t step)

  75. {

  76. ? ? ? ? Systick_Delay(5);? ? //為了更好得看清楚,稍加延時

  77. ? ? ? ? switch(step) {

  78. ? ?? ???case 3: //A+ C-

  79. ? ?? ?? ?? ?BLDC_UH_ENABLE();

  80. ? ?? ?? ?? ?BLDC_UL_DISABLE();

  81. ? ?? ?? ?? ?BLDC_VH_DISABLE();;

  82. ? ?? ?? ?? ?BLDC_VL_DISABLE();

  83. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  84. ? ?? ?? ?? ?BLDC_WL_ENABLE();

  85. ? ?? ?? ?? ?break;

  86. ? ?? ???case 1: //B+ C-

  87. ? ?? ?? ?? ?BLDC_UH_DISABLE();

  88. ? ?? ?? ?? ?BLDC_UL_DISABLE();

  89. ? ?? ?? ?? ?BLDC_VH_ENABLE();

  90. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? BLDC_VL_DISABLE();

  91. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  92. ? ?? ?? ?? ?BLDC_WL_ENABLE();

  93. ? ?? ?? ?? ?break;

  94. ? ?? ???case 5: //B+ A-

  95. ? ?? ?? ?? ?BLDC_UH_DISABLE();

  96. ? ?? ?? ?? ?BLDC_UL_ENABLE();

  97. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ???BLDC_VH_ENABLE();

  98. ? ?? ?? ?? ?BLDC_VL_DISABLE();

  99. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  100. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  101. ? ?? ?? ?? ?break;

  102. ? ?? ???case 4: //C+ A-

  103. ? ?? ?? ?? ?BLDC_UH_DISABLE();

  104. ? ?? ?? ?? ?BLDC_UL_ENABLE();

  105. ? ?? ?? ?? ?BLDC_VH_DISABLE();

  106. ? ?? ?? ?? ?BLDC_VL_DISABLE();

  107. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ???BLDC_WH_ENABLE();

  108. ? ?? ?? ?? ?BLDC_WL_DISABLE();

  109. ? ?? ?? ?? ?break;

  110. ? ?? ???case 6: //C+ B-

  111. ? ?? ?? ?? ?BLDC_UH_DISABLE();

  112. ? ?? ?? ?? ?BLDC_UL_DISABLE();

  113. ? ?? ?? ?? ?BLDC_VH_DISABLE();

  114. ? ?? ?? ?? ?BLDC_VL_ENABLE();

  115. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ???BLDC_WH_ENABLE();

  116. ? ?? ?? ?? ?BLDC_WL_DISABLE();

  117. ? ?? ?? ?? ?break;

  118. ? ?? ???case 2: //A+ B-

  119. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?BLDC_UH_ENABLE();

  120. ? ?? ?? ?? ?BLDC_UL_DISABLE();

  121. ? ?? ?? ?? ?BLDC_VH_DISABLE();

  122. ? ?? ?? ?? ?BLDC_VL_ENABLE();

  123. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  124. ? ?? ?? ?? ?BLDC_WL_DISABLE();

  125. ? ?? ?? ?? ?break;

  126. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

  127. ? ?? ???default:

  128. ? ?? ?? ?? ?BLDC_UH_DISABLE();

  129. ? ?? ?? ?? ?BLDC_UL_DISABLE();

  130. ? ?? ?? ?? ?BLDC_VH_DISABLE();

  131. ? ?? ?? ?? ?BLDC_VL_DISABLE();

  132. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  133. ? ?? ?? ?? ?BLDC_WL_DISABLE();

  134. ? ?? ?? ?? ?break;

  135. ? ? }

  136. ? ? ? ?

  137. }


  138. void Systick_Callback(void)

  139. {

  140. ? ? if(RUN == g_tMotor.tMotorState) {

  141. ? ?? ???g_tMotor.tCount.hwTimeCount ++;

  142. ? ?? ???if(g_tMotor.tCount.hwTimeCount > 2000) { // 2s超時,電機(jī)卡住不運(yùn)轉(zhuǎn)超過2s時間

  143. ? ?? ?? ?? ?GATE_DRIVER_DISABLE();

  144. ? ?? ?? ?? ?BLDC_UH_DISABLE();

  145. ? ?? ?? ?? ?BLDC_UL_DISABLE();

  146. ? ?? ?? ?? ?BLDC_VH_DISABLE();

  147. ? ?? ?? ?? ?BLDC_VL_DISABLE();

  148. ? ?? ?? ?? ?BLDC_WH_DISABLE();

  149. ? ?? ?? ?? ?BLDC_WL_DISABLE();

  150. ? ?? ?? ?? ?g_tMotor.tMotorState = STOP;

  151. ? ?? ?? ?? ?g_tMotor.tCount.hwTimeCount = 0;

  152. ? ?? ???}

  153. ? ? }

  154. }


  155. void Hall_Exti_Callback(void)

  156. {

  157. ? ? volatile uint8_t chStep = 0;

  158. //? ? chStep = (uint8_t)((HALL_PORT_U->IDR >> HALL_PINSOURCE_U) |

  159. //? ?? ?? ?? ?? ?? ?? ???(HALL_PORT_V->IDR >> (HALL_PINSOURCE_V - 1)) |

  160. //? ?? ?? ?? ?? ?? ?? ???(HALL_PORT_W->IDR >> (HALL_PINSOURCE_W - 2))) & 0x07;

  161. ? ? if(g_tMotor.tMotorState == STOP) {

  162. ? ?? ???return;

  163. ? ? }

  164. ? ? if((HALL_PORT_U ->IDR & HALL_PIN_U) != (uint32_t)Bit_RESET) {

  165. ? ?? ???chStep |= 0x01;

  166. ? ? }

  167. ? ? if((HALL_PORT_V ->IDR & HALL_PIN_V) != (uint32_t)Bit_RESET) {

  168. ? ?? ???chStep |= 0x02;

  169. ? ? }

  170. ? ? if((HALL_PORT_W ->IDR & HALL_PIN_W) != (uint32_t)Bit_RESET) {

  171. ? ?? ???chStep |= 0x04;

  172. ? ? }

  173. ? ? ? ? ? ? ? ?

  174. ? ? if (g_tMotor.chHallValue != chStep) {? ?//判斷是否換向

  175. ? ?? ???g_tMotor.tMotorState = RUN;

  176. ? ?? ???g_tMotor.chHallValue = chStep ;

  177. ? ? }


  178. ? ? if(g_tMotor.tMotorDirection == CCW) {? ?// 方向判斷

  179. ? ?? ???chStep =??7 - chStep;

  180. ? ? }

  181. ? ? Bldc_Phase_Chaneg(chStep);? ? //驅(qū)動換相

  182. ? ? ? ?

  183. ? ? g_tMotor.tCount.hwTimeCount = 0;

  184. }


? ???? Jumper設(shè)定為出廠設(shè)置狀態(tài),工程編譯后,燒錄完成,電機(jī)順利啟動,代碼中稍加了點(diǎn)延時,方便更清楚得看到電機(jī)的轉(zhuǎn)動,電機(jī)轉(zhuǎn)動又快又有勁,可與通用電動螺絲批相比較,但噪聲有點(diǎn)大,有待優(yōu)化。驅(qū)動工程源碼見如下附件,通過MM32SPIN160C電機(jī)驅(qū)動板的使用,體驗了靈動微MCU的庫函數(shù)與ST的相兼容,移植起來更便捷,如果靈動微有像ST一樣CubeMX開發(fā)工具就更強(qiáng)了。


下載程序源代碼等資料,請點(diǎn)擊閱讀原文!