前言
關於電機的選擇。
學校發的無刷電機:
我們准備的有刷電機:
帶霍爾編碼器!
電機參數:
名稱:馳名電機(直流減速電機)型號:JGA25-370
電壓:12V
轉數:1360r/min
既然做雲台,那么核心是PID控制。PID以后再講。本期先講電機的部分內容。
無刷or有刷?
無刷電機需要foc控制與SVPWM調制,算法較為繁瑣。搗鼓期間也遇到不少bug,故舍棄無刷電機,選擇有刷電機。為啥?代碼簡單唄!
(補充:若無刷電機用PWM而不是SVPWM,則會很燙很燙,燒起來也說不定~)
一、硬件准備
- stm32F401/411開發版(SAST)
- J-LINK/ST-LINK下載器
- 直流有刷電機JGA25-370(帶編碼器)
- 電機驅動板L298N/TB6612
- 12V鋰電池
二、工程配置
新建stm32工程,這里采用的是cubmx+keil5方式。(不會還用人用標准庫吧:-))
我用的是F411。
1、嘗龜配置
使用外部高速晶振、Debug選Serial Wire。(我用的是J-LINK下載器)時鍾樹開HCLK為100MHz。(F411最大HCLK)
2、設置PWM輸出
TIM5設置為內部時鍾—CH3—PWM Generation。命名為PWM。
一般而言,給電機的PWM波大約2kHz。
配置HCLK
=100MHz(F411最大HCLK
),PSC
=50-1,ARR
=1000-1。
由頻率計算公式可得:
其余默認配置即可。
(注:因為是PWM輸出,所以沒必要使能NVIC中斷)
3、設置兩個IO口輸出
用於控制電機轉動方向,命名為DIR1和DIR2。
設置PA3—Output與PA4—Output。其余默認配置即可。
4、設置編碼器模式
關於編碼器模式,很多人可能不李姐。詳細的會在以后的文章里寫。這里先粗略寫一下。
電機工作時,通過霍爾編碼器輸出AB相脈沖,單片機讀取脈沖數以得到轉速與角度等信息,我們還要對采集到的數據進行處理。而stm32定時器正好有個編碼器模式,我們只需讀取定時器計數值就能知道脈沖數為多少。
TIM2—Combined Channels—Encoder Mode
下面的都不用設置。
把圖中的三個(TIM2_CH1和TIM2_CH2和PWM)Signal Pinning一下。
5、設置中斷
打開一個定時器更新中斷,在這個中斷里我們處理編碼器的數據以得到轉速、角度等信息,並進行PID控制。
TIM4設置為內部時鍾即可。
配置HCLK
=100MHz(F411最大HCLK
),PSC
=1000-1,ARR
=1000-1。
中斷一般為100Hz。
別忘了在NVIC Settings使能中斷。
6、打開一個串口
用於調試。
嘗龜設置,設置設置MODE為異步通信(Asynchronous)。其余的默認即可。(波特率為115200)
別忘了在keil里寫串口重定向。
7、生成keil工程
嘗龜配置。
設置工程名稱、路徑(不要有中午路徑),
配置IDE為MDK-ARM。代碼生成配置勾選圖中紅框處。
點擊GENERATE CODE生成工程!
8、keil配置
打開工程配置,勾選“use MicroLIB”,Debug選擇J-LINK,並在Settings-Flash-Download勾選“Reset and Run”,然后編譯一次。
接下來加上串口重定向:
先包含頭文件#include<stdio.h>
,在/* USER CODE BEGIN 4 // USER CODE END 4 */之間添加以下代碼:
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
工程基本配置ok!
三、驅動板L298N/TB6612
電機驅動需要驅動板,直接用單片機驅動是不行的。我們比賽時用的是L298N。
1、L298N
L298N驅動模塊,可以驅動2個直流電機,可分別實現正轉,反轉功能。
供電:L298N的12V和5V都接5V供電,GND不但要接驅動電源的GND。這里要和單片機連接在一起,要從這里再引出一根GND和單片機的GND相連(共地)。
OUT1、OUT2和OUT3、OUT4分別接兩個直流電機Motor1兩腳、Motor2兩腳,IN1、IN2、IN3、IN4引腳從單片機接入控制電平,控制電機的正反轉,ENA、ENB接控制使能端,控制電機調速,L298N控制邏輯關系圖如下:
對於ENA通道使能引腳,若不考慮電機的轉速,可接為高電平或低電平控制接通還是關斷。
若需要控制電機的轉速,則需要拔掉跳線帽,將其連接在單片機PWM輸出上,通過調節PWM的占空比,以此來達到控制轉速的目的。
轉速控制原理:利用STM32 的IO輸出不同占空比的脈沖信號來達到調速的過程,當占空比大的時候就表明在一個脈沖周期內高電平的時間越長,而脈沖信號輸出頻率極快,高電平的時間越長就表明在一段時間內IO口輸出的控制電壓越高,控制電壓越高使得L298N輸出的電壓越高,這樣就使得車輪的轉速越快。
接線:
這里我們因為只要一個電機轉,故OUT3、OUT4接電機的兩腳,IN3、IN4分別接PA3、PA4控制轉動方向,ENB接PA2輸出PWM,12V供電腳和GND接12V鋰電池,GND和單片機共地。
2、TB6612
原理、接線類似於L298N。此處不再贅述。
接下來是代碼部分。
首先我們讓電機轉起來!
四、PWM控制
先寫定時器PWM輸出啟動函數:
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3);
/* USER CODE END 2 */
然后寫一個PWM調制函數void set_pwm(int pwm);
int型變量pwm的范圍應在-100~100之間(ARR設定的值為100),將它賦值給CRR(通過調節CRR的值來調節PWM波占空比,進而實現轉速控制)。pwm的正負表示轉動方向,分別使PA3和PA4輸出不同電平來控制方向(見邏輯表)。
/* USER CODE BEGIN 4 */
void set_pwm(int pwm)
{
//限定pwm范圍
if(pwm > 1000)pwm = 1000;
if(pwm < -1000)pwm = -1000;
//轉速控制
if(pwm < 0)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, 1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
}
if(pwm > 0)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
}
//寫CRR的值調節占空比
TIM5->CCR3 = (int)fabs((float)pwm); //記得#include<math.h>
}
/* USER CODE END 4 */
比如,輸出一個占空比50%的PWM波控制電機正轉:
set_pwm(500);
OK本期就到這里。往后還有電機控制part2、3,分別分享PID、編碼器相關。還有MPU6050移植從入坑到入墳。