飛書文檔https://x509p6c8to.feishu.cn/wiki/InUfwEeJNimqctkyW1mcImianLh
一、步進電機與直流電機:
1-1、什么是直流電機?
直流電機是最常見的電機類型。直流電動機通常只有兩個引線,一個正極和一個負極。直流電機的轉速控制主要依靠改變輸入電壓的大小來實現,電壓越高,電機轉速越快。
1-2、什么是步進電機?
步進電機是一種將電脈沖信號轉換成相應角位移的電機,每個脈沖使電機轉動一個固定的角度(步進角),它可以實現更精準的位置控制。
1-3、直流電機與步進電機的對比:
直流電機:
優點:價格低、控制方便
缺點:精確的位置控制相對困難,除非采用額外的編碼器反饋
步進電機:
優點:低速扭矩大,控制更精準;
缺點:成本相對高,轉速相對較低。
二、思考?為什么STM32芯片引腳不能直接接步進電機或直流電機?但可以直接接舵機?
這要從舵機的構造說起,控制芯片+電機組成,stm32實際接的是控制芯片引腳,而不是電機本身。
而步進電機和直流電機內部是沒有控制芯片的,如果使用stm32直接接電機,因為stm32芯片引腳驅動能力弱而驅動不起甚至損壞芯片,stm32每個IO的最大電流為40mA,一般步進電機跑起來可能需要幾百mA到幾A。
驅動能力可以理解為引腳的可以輸出的力氣,如果力氣過小,當然推不動電機運行。
三、如何提升驅動能力呢?
下圖就是應用三極管的開關功能,使芯片IO的驅動能力提高。
上圖可以簡單理解為三極管開關電路,通過控制輸入口的電平高低,就可以控制后端電路的開啟關閉。
四、直流電機的控制?
4-1、控制轉/停
4-2、控制轉速
直流電機的速度可以通過改變其輸入電壓來控制,使用單片機控制轉速可以通過PWM控制。
PWM是一種通過發送一系列ON-OFF脈沖來調整輸入電壓平均值的技術。該平均電壓與脈沖的寬度成正比,稱為占空比。
占空比越高,施加到直流電機的平均電壓就越高,從而導致電機速度增加。占空比越短,施加到直流電機的平均電壓越低,導致電機速度降低。
下圖顯示了具有各種占空比和平均電壓的PWM技術。
4-3、控制方向
前面我們都只是控制電機往一個方向轉動,如果需要更換方向,就需要重新接線,那如果需要自動控制電機的正反轉呢?這就需要升級下電路。
下面電路被稱為H橋,是因為它使用四個晶體管連接,使示意圖看起來像一個“H”。
為了控制直流電機的旋轉方向,無需互換引線,可以使用稱為H橋的電路。H橋是可以雙向驅動電機的電子電路。H橋用于許多不同的應用中。最常見的應用之一是控制機器人中的電機。
| |
如果需要使用多個三極管,一個一個連接太麻煩了,有沒有更好的方式呢?當然有,L293D、L298、和課程用的TC118S都是集成H橋的芯片。
直流驅動芯片TC118S
https://item.szlcsc.com/89487.html
應用電路圖
原理圖:
新建工程,設置PB14 PB15為GPIO輸出
修改IO名稱為DC_AN1、DC_AN2,這里PB14命名應該是DC_AN1,PB15應該是DC_AN2,不過這個命名錯不影響控制效果,只影響電機旋轉方向,大家留意下即可。
方向控制:
main.cwhile (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///正轉HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET);HAL_Delay(5000);//停止HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET);HAL_Delay(5000);//反轉HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_SET);HAL_Delay(5000);//停止HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET);HAL_Delay(5000);}/* USER CODE END 3 */
速度控制:
如果需要對直流電機進行速度控制,我們可以使用PWM,我們可以在STM32CUBEMX中看到PB15是支持綁定TIM1_CH3N這個通道的
TIM1_CH3N與TIM1_CH3為互補輸出,例如黃色是TIM1_CH3,TIM1_CH3N則為藍色部分
| 設置完成后,IO變為黃色 |
我們在左側設置TIM1的CH3N為PWM模式即可
需要注意的是:
普通PWM開啟的函數為
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);
CH3N由于是高級定時器才有的通道,開啟函數為:
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
最終代碼
main.c/* USER CODE BEGIN 2 */uint16_t pwm_value = 0;?? //占空比?HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); //開啟PWM輸出HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET); //設置DC_AN2為低,只保持一個方向轉動/* USER CODE END 2 */while (1){/* USER CODE BEGIN 3 */while (pwm_value < 150){pwm_value++;//修改比較值,修改占空比,占空比為pwm_value/500__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, pwm_value);???HAL_Delay(10);}HAL_Delay(1000);while (pwm_value){pwm_value--;__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, pwm_value);??HAL_Delay(10);}HAL_Delay(1000);}/* USER CODE END 3 */
參考工程:參考飛書文檔
五、步進電機的控制?
右手法則
步進電機工作原理
步進電機的基本工作原理為:給一個或多個定子相位通電,線圈中通過的電流會產生磁場,而轉子會與該磁場對齊;依次給不同的相位施加電壓,轉子將旋轉特定的角度并最終到達需要的位置。
步進電機中間的轉子是一個磁鐵,周圍線圈在通電時會形成磁場,然后把轉子吸過來,如果周圍線圈按照一定的順序逐個通電斷電時,轉子就會被帶動轉起來。
電機類型
步進電機又分為單極性的步進電機和雙極性的步進電機
| |
其中左側為單極性步進電機,右側為雙極性的步進電機。
單雙極性是指一個步進電機里面有幾種電流的流向
單極性是指電機線圈只有一個方向的電流流向。
雙極性是指電機線圈有兩個電流的回路。
單級性電機驅動
下圖是單極性步進電機整步旋轉的過程,其中,在圖示中分為5根線,分別為A、B、C、D和公共端(+),公共端需要一直通電, 剩下ABCD相中只要有一個相通電,即可形成回路產生磁場,圖中的通電順序為A->B->C->D,即可完成上圖中的順時針旋轉, 如果想要逆時針旋轉只需要將其倒序即可。
雙極性的步進電機
下圖是一個雙極性的步進電機整步,步進順序。 在第一步中:將A相通電,根據電磁鐵原理,產生磁性,并且因異性相吸,所以磁場將轉子固定在第一步的位置; 第二步:當A相關閉,B相通電時,轉子會旋轉90°; 第三步:B相關閉、A相通電,但極性與第1步相反,這促使轉子再次旋轉90°。 在第四步中:A相關閉、B相通電,極性與第2步相反。重復該順序促使轉子按90°的步距角順時針旋轉。
滿步驅動:
單拍滿步驅動??????????????????????????????????????????????? 雙拍滿步驅動
?
半步驅動:
半步驅動的好處是提高分辨率,但是缺點是扭矩只有滿步驅動的70%,當然,也可以通過優化線圈中電流大小,來提高半步驅動扭矩。
總結:
步距角:改變一次通電狀態(或者說一個脈沖信號)電機轉子對應轉過的角度。θ=360°/(z*n),θ是步距角,z是轉子齒數,n是工作拍數。
在非超載情況下,電機的轉速和停止位置只取決于控制脈沖信號的頻率和脈沖數;
脈沖數越多,轉動角度越大;頻率越高,轉動速度越快(不能超過電機規定的最高頻率)。
42步進電機
這里的42一般指電機的安裝尺寸42mm*42mm,同理,還有28、35、57、60,一般來說尺寸和扭矩成正比
| |
| | |
- 兩相:2組線圈
- 步距角:每走一步的角度為1.8度
步進驅動芯片BDR6622T
https://item.szlcsc.com/769389.html
芯片框圖
內部一個橋的框圖:
控制:
- 半步模式:1-4步
- 滿步模式:1-8步
有了上面的理論基礎后
我們可以編寫代碼用全步或半步控制步進電機了,
| |
接線說明
綠色A-
黑色A+
藍色B-
紅色B+
參考代碼如下
main.c/* USER CODE BEGIN 0 */void motor_run(uint8_t direction,uint8_t step){if(direction == 0){//正轉switch(step){case 0:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);break;case 1:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);break;case 2:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);break;case 3:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);break;}}else{//反轉switch(step){case 0:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);break;case 1:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);break;case 2:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);break;case 3:HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);break;}}}void runstep(){uint8_t direction = 0;int step = 500;for(int i = 0;i < step ;i++){motor_run(direction,i%4);HAL_Delay(1);}HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);}
/* USER CODE END 0 *//* USER CODE BEGIN 2 */runstep();/* USER CODE END 2 *///改變runstep()中的direction就是改變方向,改變step就是改變步數。
示例工程
參考飛書文檔