直流有刷電機
直流有刷電機(Brushed DC motor)具有結構簡單、易于控制、成本低等特點, 在一些功能簡單的應用場合,或者說在能夠滿足必要的性能、低成本和足夠的可靠性的前提下, 直流有刷電機往往是一個很好的選擇。 例如便宜的電子玩具、各種風扇和汽車的電動座椅等。 基本的直流有刷電機在電源和電機之間只需要兩根電纜,這樣就可以節省配線和連接器所需的空間, 并降低電纜和連接器的成本。 此外,還可以使用MOSFET/IGBT開關對直流有刷電機進行控制, 給電機提供足夠好的性能的同時,整個電機控制系統也會比較便宜。
直流有刷電機轉速快、扭矩小,在某些應用中可能無法滿足要求。 這種情況就需要做一些改進來降低轉速,并提高力矩。 直流減速電機就是這樣一種電機。
這種電機通常也叫齒輪減速電機,它是在普通直流有刷電機的基礎上增加了一套齒輪減速箱, 用來提供更大的力矩和更低的轉速。 齒輪減速箱可以通過配置不同的減速比,提供各種不同的轉速和力矩。 在實際使用中減速電機使用的最為廣泛,所以本章節將主要介紹直流有刷減速電機。
本章節將介紹直流有刷電機的工作原理、電機參數和驅動電路,最后通過實驗來實現電機運動的簡單控制。
直流有刷電機工作原理
在分析原理前我們先復習一下左手定則。
左手定則是判斷通電導體處于磁場中時,所受安培力 F (或運動)的方向、 磁感應強度B的方向以及通電導體棒的電流 I 三者方向之間的關系的定律。 通過左手定則可以知道通電導體在磁場中的受力方向,如下圖所示。
判斷方法是:伸開左手,使拇指與其他四指垂直且在一個平面內,讓磁感線從手心流入, 四指指向電流方向,大拇指指向的就是安培力方向(即導體受力方向)。
有刷直流電機在其電樞上繞有大量的線圈,所產生強大的磁場與外部磁場相互作用產生旋轉運動。 磁極方向的跳轉是通過移動固定位置的接觸點來完成的,該接觸點在電機轉子上與電觸點相對連接。 這種固定觸點通常由石墨制成,與銅或其他金屬相比,在大電流短路或斷路/起動過程中石墨不會熔斷或者與旋轉觸點焊接到一起, 并且這個觸點通常是彈簧承載的,所以能夠獲得持續的接觸壓力,保證向線圈供應電力。 在這里我們將通過其中一組線圈和一對磁極來分析其工作原理,如下圖所示。
圖中C和D兩片半圓周的銅片構成換向器,兩個彈性銅片靠在換向器兩側的A和B是電刷,電源通過電刷向導線框供電, 線框中就有電流通過,在線框兩側放一對磁極N和S,形成磁場,磁力線由N到S。 線框通有電流時, 兩側導線就會受到磁場的作用力,方向依左手定則判斷,紅色和藍色線框部分分別會受到力F1和F2 , 這兩個力的方向相反,這使得線框會轉動,當線框轉過90°時,換向器改變了線框電流的方向,產生的安培力方向不變, 于是導線框會連續旋轉下去,這就是直流電動機的工作原理。
4.2. 直流有刷減速電機幾個重要參數
- 空載轉速:正常工作電壓下電機不帶任何負載的轉速(單位為r/min(轉/分))。 空載轉速由于沒有反向力矩,所以輸出功率和堵轉情況不一樣,該參數只是提供一個電機在規定電壓下最大轉速的參考。
- 空載電流:正常工作電壓下電機不帶任何負載的工作電流(單位mA(毫安))。 越好的電機,在空載時,該值越小。
- 負載轉速:正常工作電壓下電機帶負載的轉速。
- 負載力矩:正常工作電壓下電機帶負載的力矩 (N·m(牛米))。
- 負載電流:負載電流是指電機拖動負載時實際檢測到的定子電流數值。
- 堵轉力矩:在電機受反向外力使其停止轉動時的力矩。 如果電機堵轉現象經常出現, 則會損壞電機,或燒壞驅動芯片。 所以大家選電機時,這是除轉速外要考慮的參數。 堵轉時間一長,電機溫度上升的很快,這個值也會下降的很厲害。
- 堵轉電流:在電機受反向外力使其停止轉動時的電流,此時電流非常大,時間稍微就可能會燒毀電機, 在實際使用時應盡量避免。
- 減速比:是指沒有減速齒輪時轉速與有減速齒輪時轉速之比。
- 功率:般指的是它的額定功率(單位W(瓦)),即在額定電壓下能夠長期正常運轉的最大功率, 也是指電動機在制造廠所規定的額定情況下運行時, 其輸出端的機械功率。
4.3. 直流有刷電機驅動設計與分析
我們先來想一個問題,假設你手里現在有一個直流電機和一節電池, 當你把電機的兩根電源線和電池的電源連接在一起時,這時電機可以正常旋轉, 當想要電機反向旋轉時,只需要把兩根電源線交換一下就可以了。 但是當在實際應用中要實現正轉和反轉的控制也通過交換電源線實現嗎? 顯然這樣的方法是不可行的。 這時候我們可以用一個叫做“H橋電路”來驅動電機。
4.3.1. 控制電路原理設計與分析
如下圖所示,是使用4個三極管搭建的H橋電路。
上圖中,H橋式電機驅動電路包括4個三極管和一個電機。 要使電機運轉,必須導通對角線上的一對三極管。 根據不同三極管對的導通情況,電流可能會從左至右或從右至左流過電機,從而控制電機的轉向。
上圖中,當Q1和Q4導通時,電流將經過Q1從左往右流過電機, 在經過Q4流到電源負極,這時圖中電機可以順時針轉動。
上圖中,當Q3和Q2導通時,電流將經過Q3從右往左流過電機, 在經過Q2流到電源負極,這時圖中電機可以逆時針轉動。
特別地,當同一側的Q1和Q2同時導通時,電流將從電源先后經過Q1和Q2 ,然后直接流到電源負極, 在這個回路中除了三極管以外就沒有其他負載(沒有經過電機),這時電流可能會達到最大值,此時可能會燒毀三極管, 同理,當Q3和Q4同時導通時,也會出現相同的狀況。 這樣的情況肯定是不能發生的, 但是我們寫程序又是三分寫代碼七分在調試,這就難免會有寫錯代碼將同一測得三極管導通的情況, 為此我們就需要從硬件上來避免這個問題。 下面電路圖是改進后的驅動電路圖。
與改進前的電路相比,在上面的改進電路中新增加了兩個非門和4個與門,以及Q1和Q3換成了NPN三極管, 經過這樣的組合就可以實現一個信號控制兩個同一側的三極管, 并且可以保證在同一側中兩個三級管不會同時導通在同一時刻只會有一個三極管是導通的。
我們來分析一下電信號的變化:在ENABLE腳接入高電平,在IN1腳接入高電平,在經過第一個非門后,AND1的2腳就是低電平, 此時與門AND1的輸出(3腳)就是低電平,所以Q1截止。 而AND2的1腳和2腳都是高電平,所以AND2的3腳也是高電平, 這樣Q2就導通了。 在IN2接入低電平,同理分析可得,Q3導通Q4截止。 在IN1和IN2處分別接入低電平和高電平, 則Q1和Q4導通,Q3和Q2截止。 當IN1和IN2都接入高電平或者低電平時都只會同時導通上面或者下面的兩個三極管, 不會出現同一側的三極管同時導通的情況。
4.3.2. 驅動芯片分析
通常在驅動電機的時候我們會選擇集成H橋的IC,因為H橋使用分立元件搭建比較麻煩,增加了硬件設計難度, 當然如果集成IC無法滿足我們的功率要求時,還是需要我們自己使用MOS管、三極管等元件來搭建H橋電路, 這樣的分立元件搭建的H橋一般驅動能力都會比集成IC要高。 當我們在選擇集成IC時, 我們需要考慮集成IC是否能滿足電機的驅動電壓要求,是否能承受電機工作時的電流等情況。
4.3.2.1. L298N驅動芯片
L298N是ST公司的產品,內部包含4通道邏輯驅動電路,是一種二相和四相電機的專門驅動芯片, 即內含兩個H橋的高電壓大電流雙橋式驅動器,接收標準的TTL邏輯電平信號,可驅動4.5V~46V、 2A以下的電機,電流峰值輸出可達3A,其內部結構如下圖所示。
其工作原理與上面的講解的H橋原理一樣,這里不再贅述。 L298N引腳圖如下圖所示。
L298N邏輯功能表。
IN1 | IN2 | ENA | 電機狀態 |
---|---|---|---|
× | × | 0 | 電機停止 |
1 | 0 | 1 | 電機正轉 |
0 | 1 | 1 | 電機反轉 |
0 | 0 | 1 | 電機停止 |
1 | 1 | 1 | 電機停止 |
IN3,IN4的邏輯圖與上表相同。 由上表可知ENA為低電平時,INx輸入電平對電機控制不起作用, 當ENA為高電平,輸入電平為一高一低,電機正或反轉。 同為低電平電機停止,同為高電平電機停止。 L298N的應用電路圖將在后面硬件設計小節講解。
4.4. 直流有刷減速電機控制實現
4.4.1. 速度控制原理
脈沖寬度調制(Pulse width modulation,PWM)信號,即PWM是一種按一定的規則對各脈沖的寬度進行調制, 既可改變電路輸出電壓的大小,也可改變輸出頻率。 PWM通過一定的頻率來改變通電和斷電的時間, 從而控制電路輸出功率,在電機的控制周期中,通電時間決定了它的轉速。 其中, 通電時間/(通斷時間+斷電時間)=占空比,即,高電平占整個周期的百分比,如下圖所示:
上圖中:T1為高電平時間,T2為低電平時間,T是周期。
D(占空比) = T 1/T*100%
設電機的速度為V,最大速度為Vmax 。
則:V=Vmax*D
當占空比D(0≤D≤1)的大小改變時,速度V也會改變,所以只要改變占空比就能達到控制的目的。
4.4.2. 硬件設計
主控有刷電機接口原理圖如下圖所示,有刷電機接口與無刷接口使用的是同一個接口,舍去了其中一些多余的接口, 用到了兩個定時器通道,編碼器、兩路ADC采集通道(后續章節講解)。 本節實驗只用到了TIM1的CH1和CH2, 即PA8和PA9來輸出PWM信號來控制電機,注意主控板需要和電機驅動板供地。
4.4.2.1. L298N
驅動板可以支持12-42V的寬電壓供電,并且帶輸入電壓轉5V的電壓芯片,所以驅動板只需要一個電源輸入。 具體需要多大電壓需要根據電機來選擇。 電路圖見下圖所示。
在下圖電機控制接口中,ENABLEA和ENABLEB是使能輸入腳,ENABLEA用于控制A橋,可以接到單片機的引腳控制, 也是直接使用跳冒連接到5V,ENABLEB用于控制B橋,控制方式與ENABLE一樣。 INPUT1和INPUT2是A橋的控制信號,INPUT1和INPUT2是B橋的控制信號,可以接PWM控制電機。 OUTPUT1和OUTPUT2是A橋的輸出接口,OUTPUT3和OUTPUT4是B橋的輸出接口。
上圖中8個二極管用于防止電機的反電動勢損壞L298N,當E點反電勢為正,超過電源+0.7V時, 上端二極管導通,這樣輸出線就被限位在電源電壓+0.7V上,不會超過這個數值; 當E點反電勢為負,低于-0.7V時,下端二極管導通,這樣輸出線就被限位在-0.7V上, 不會低于-0.7V了。 這兩個二極管是作為鉗位使用,使得輸出線上電壓(或叫電位) 被箝位在-0.7V~+Vcc+0.7V之間。 其他二極管作用于E點這兩個一樣。
電機與L298N驅動板連接見下表所示。
電機與L298N驅動板連接
電機 | L298N驅動板 |
---|---|
M+ | 電機輸出:1 |
M- | 電機輸出:2 |
L298N驅動板與主控板連接見下表所示。
L298N驅動板與主控板連接
L298N驅動板 | 主控板 |
---|---|
PWM1 | PA9 |
PWM2 | PA8 |
GND | GND |
ENA | PG12 |
在L298N驅動板與主控板連接中,ENA可以不接PG12,使用跳冒連接到5V。
4.4.2.2. 野火直流有刷電機驅動板-MOS管搭建板
野火有刷電機驅動板是使用MOS管搭建的大功率H橋電機驅動板,實物圖如下圖所示。
驅動板可支持12V~70V的寬電壓輸入,10A過電流保護電路,超過10A可自動禁用電機控制信號,最高功率支持700W。 實際使用輸入電壓需要根據電機進行選擇,同時還具有電流采樣電路、編碼器接口和電源電壓檢測電路等等, 本小節主要講解電機驅動部分電路,其他功能將在后續章節中講解。
野火使用MOS管搭建的直流有刷驅動板做到了信號完全隔離,其他驅動板基本都只是使用光耦隔離了控制信號, 并沒有對ADC采樣電路進行隔離,野火不僅使用光耦對控制信號進行了隔離, 還使用AMC1200SDUBR隔離運放對ADC采樣電路進行了隔離。
PWM控制信號使用了TLP2362高速光耦進行了隔離,SD控制信號使用了EL357N光耦進行了隔離,如下圖所示。
與門的作用是可以使單片機和過流保護電路共同控制SD腳,過流保護電路將在電流電壓采集章節講解, 與門輸入輸出與MOS管狀態真值表如下表所示。
與門輸入輸出與MOS管狀態真值表
A | B | Y | MOS |
---|---|---|---|
H | H | H | 可導通 |
H | L | L | 關斷(過流保護) |
L | H | L | 關斷(單片機控制關斷) |
L | L | L | 關斷(單片機控制關斷,過流保護) |
下圖是使用MOS管搭建的H橋電路,使用兩個EG2104驅動四個MOS管。
EG2104S主要功能有邏輯信號輸入處理、死區時間控制、電平轉換功能、懸浮自舉電源結構和上下橋圖騰柱式輸出。 邏輯信號輸入端高電平閥值為 2.5V 以上,低電平閥值為 1.0V 以下,要求邏輯信號的輸出電流小, 可以使MCU輸出邏輯信號直接連接到EG2104S的輸入通道上。 EG2104S芯片有一個shutdown引腳, 邏輯輸入控制信號低電平有效,控制強行使LO、HO輸出低電平。 這樣可以直接使用這個引腳做軟件控制電機的旋轉與停止, 還可以實現硬件的限流保護(后續章節分析保護電路),輸入信號和輸出信號邏輯真值表如下表所示。
EG2104S輸入信號和輸出信號邏輯真值表
IN(引腳2) | SD(引腳3) | HO(引腳7) | LO(引腳5) |
---|---|---|---|
L | L | L | L |
H | L | L | L |
L | H | L | H |
H | H | H | L |
從真值表可知,在輸入邏輯信號SD為“L”時,不管IN為“H”或者“L”情況下,驅動器控制輸出HO、LO同時為“L”, 上、下功率管同時關斷; 當輸入邏輯信號SD為“H”、IN為“L”時,HO輸出為“L”,LO輸出為“H”; 當輸入邏輯信號SD為“H”、IN 為“H”時,HO輸出為“H”,LO輸出為“L”。
EG2104S內部集成了死區時控制電路,死區時間波形圖如下圖所示,其中死區時間DT的典型值為640ns。
EG2104S采用自舉懸浮驅動電源結構大大簡化了驅動電源設計, 只用一路電源電壓VCC即可完成高端N溝道MOS管和低端N溝道MOS管兩個功率開關器件的驅動,給實際應用帶來極大的方便。 EG2104S自舉電路結構如下圖所示,EG2104S可以使用外接一個自舉二極管和一個自舉電容自動完成自舉升壓功能, 假定在下管開通、上管關斷期間VC自舉電容已充到足夠的電壓(Vc=VCC),當HO輸出高電平時上管開通、下管關斷時, VC自舉電容上的電壓將等效一個電壓源作為內部驅動器VB和VS的電源,完成高端N溝道MOS管的驅動。
電機與MOS管搭建驅動板連接見下表所示。
電機與MOS管搭建驅動板連接
電機 | MOS管搭建驅動板 |
---|---|
M+ | M+ |
M- | M- |
MOS管搭建驅動板與主控板連接見下表所示。
MOS管搭建驅動板與主控板連接
MOS管搭建驅動板 | 主控板 |
---|---|
PWM1 | PA9 |
PWM2 | PA8 |
SD | PG12 |
電源輸入:5V | 5V |
電源輸入:GND | GND |
推薦使用配套的牛角排線直接連接驅動板和主控板。
4.4.3. 軟件設計
這里只講解核心的部分代碼,有些變量的設置,頭文件的包含等并沒有涉及到,完整的代碼請參考本章配套的工程。 我們創建了四個文件:bsp_general_tim.c、bsp_general_tim.h、bsp_motor_control.c和bsp_motor_control.h 文件用來存定時器驅動和電機控制程序及相關宏定義。
4.4.3.1. 編程要點
- 定時器 IO 配置
- 定時器時基結構體TIM_TimeBaseInitTypeDef配置
- 定時器輸出比較結構體TIM_OCInitTypeDef配置
- 根據定時器定義電機控制相關函數
bsp_general_tim.h-宏定義
/*宏定義*/
#define PWM_TIM TIM1
#define PWM_TIM_GPIO_AF GPIO_AF1_TIM1
#define PWM_TIM_CLK_ENABLE() __TIM1_CLK_ENABLE()
#define PWM_CHANNEL_1 TIM_CHANNEL_1
#define PWM_CHANNEL_2 TIM_CHANNEL_2
/* 累計 TIM_Period個后產生一個更新或者中斷*/
/* 當定時器從0計數到PWM_PERIOD_COUNT,即為PWM_PERIOD_COUNT+1次,為一個定時周期 */
#define PWM_PERIOD_COUNT (5600)
/* 通用控制定時器時鐘源TIMxCLK = HCLK=168MHz */
/* 設定定時器頻率為=TIMxCLK/(PWM_PRESCALER_COUNT+1) */
#define PWM_PRESCALER_COUNT (2)
/* 最大比較值 */
#define PWM_MAX_PERIOD_COUNT (PWM_PERIOD_COUNT - 100)
/*PWM引腳*/
#define PWM_TIM_CH1_GPIO_PORT GPIOA
#define PWM_TIM_CH1_PIN GPIO_PIN_8
#define PWM_TIM_CH2_GPIO_PORT GPIOA
#define PWM_TIM_CH2_PIN GPIO_PIN_9
#define PWM_TIM_CH3_GPIO_PORT GPIOA
#define PWM_TIM_CH3_PIN GPIO_PIN_10
使用宏定義非常方便程序升級、移植。 如果使用不同的定時器IO,修改這些宏即可。
定時器復用功能引腳初始化
定時器復用功能引腳初始化
static void TIMx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* 定時器通道功能引腳端口時鐘使能 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* 定時器通道1功能引腳IO初始化 */
/*設置輸出類型*/
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
/*設置引腳速率 */
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
/*設置復用*/
GPIO_InitStruct.Alternate = PWM_TIM_GPIO_AF;
/*選擇要控制的GPIO引腳*/
GPIO_InitStruct.Pin = PWM_TIM_CH1_PIN;
/*調用庫函數,使用上面配置的GPIO_InitStructure初始化GPIO*/
HAL_GPIO_Init(PWM_TIM_CH1_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = PWM_TIM_CH2_PIN;
HAL_GPIO_Init(PWM_TIM_CH2_GPIO_PORT, &GPIO_InitStruct);
}
定時器通道引腳使用之前必須設定相關參數,這選擇復用功能,并指定到對應的定時器。 使用GPIO之前都必須開啟相應端口時鐘。
定時器模式配置 [
TIM_HandleTypeDef TIM_TimeBaseStructure;
static void TIM_PWMOUTPUT_Config(void)
{
TIM_OC_InitTypeDef TIM_OCInitStructure;
/*使能定時器*/
PWM_TIM_CLK_ENABLE();
TIM_TimeBaseStructure.Instance = PWM_TIM;
/* 累計 TIM_Period個后產生一個更新或者中斷*/
//當定時器從0計數到PWM_PERIOD_COUNT,即為PWM_PERIOD_COUNT+1次,為一個定時周期
TIM_TimeBaseStructure.Init.Period = PWM_PERIOD_COUNT - 1;
// 通用控制定時器時鐘源TIMxCLK = HCLK/2=84MHz
// 設定定時器頻率為=TIMxCLK/(PWM_PRESCALER_COUNT+1)
TIM_TimeBaseStructure.Init.Prescaler = PWM_PRESCALER_COUNT - 1;
/*計數方式*/
TIM_TimeBaseStructure.Init.CounterMode = TIM_COUNTERMODE_UP;
/*采樣時鐘分頻*/
TIM_TimeBaseStructure.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
/*初始化定時器*/
HAL_TIM_PWM_Init(&TIM_TimeBaseStructure);
/*PWM模式配置*/
TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1;
TIM_OCInitStructure.Pulse = 0;
TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;
TIM_OCInitStructure.OCNPolarity = TIM_OCPOLARITY_HIGH;
TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_SET;
TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE;
/*配置PWM通道*/
HAL_TIM_PWM_ConfigChannel(&TIM_TimeBaseStructure, &TIM_OCInitStructure, PWM_CHANNEL_1);
/*開始輸出PWM*/
HAL_TIM_PWM_Start(&TIM_TimeBaseStructure,PWM_CHANNEL_1);
/*配置脈寬*/
TIM_OCInitStructure.Pulse = 0; // 默認占空比為50%
/*配置PWM通道*/
HAL_TIM_PWM_ConfigChannel(&TIM_TimeBaseStructure, &TIM_OCInitStructure, PWM_CHANNEL_2);
/*開始輸出PWM*/
HAL_TIM_PWM_Start(&TIM_TimeBaseStructure,PWM_CHANNEL_2);
}
首先定義兩個定時器初始化結構體,定時器模式配置函數主要就是對這兩個結構體的成員進行初始化, 然后通過相應的初始化函數把這些參數寫入定時器的寄存器中。 有關結構體的成員介紹請參考定時器詳解章節。
不同的定時器可能對應不同的APB總線,在使能定時器時鐘是必須特別注意。 通用控制定時器屬于APB1, 定時器內部時鐘是84MHz。
在時基結構體中我們設置定時器周期參數為PWM_PERIOD_COUNT(5599),頻率為15KHz,使用向上計數方式。 因為我們使用的是內部時鐘,所以外部時鐘采樣分頻成員不需要設置,重復計數器我們沒用到,也不需要設置。
在輸出比較結構體中,設置輸出模式為PWM1模式,通道輸出高電平有效,設置脈寬為ChannelPulse, ChannelPulse是我們定義的一個無符號16位整形的全局變量,用來指定占空比大小, 實際上脈寬就是設定比較寄存器CCR的值,用于跟計數器CNT的值比較。
最后使用HAL_TIM_PWM_Start函數讓計數器開始計數和通道輸出。
bsp_motor_control.h-電機方向控制枚舉
/* 電機方向控制枚舉 */
typedef enum
{
MOTOR_FWD = 0,
MOTOR_REV,
}motor_dir_t;
在這里枚舉了兩個變量,用于控制電機的正轉與反轉。 注意 :在這里并不規定什么方向是正轉與反轉, 這個是你自己定義的。
變量定義
/* 私有變量 */
static motor_dir_t direction = MOTOR_FWD; // 記錄方向
static uint16_t dutyfactor = 0; // 記錄占空比
定義兩個私有變量,direction用于記錄電機旋轉方向,dutyfactor用于記錄當前設置的占空比。
定時器到電機控制的宏接口 [
/* 設置速度(占空比) */
#define SET_FWD_COMPAER(ChannelPulse) TIM1_SetPWM_pulse(PWM_CHANNEL_1,ChannelPulse) // 設置比較寄存器的值
#define SET_REV_COMPAER(ChannelPulse) TIM1_SetPWM_pulse(PWM_CHANNEL_2,ChannelPulse) // 設置比較寄存器的值
/* 使能輸出 */
#define MOTOR_FWD_ENABLE() HAL_TIM_PWM_Start(&TIM_TimeBaseStructure,PWM_CHANNEL_1); // 使能 PWM 通道 1
#define MOTOR_REV_ENABLE() HAL_TIM_PWM_Start(&TIM_TimeBaseStructure,PWM_CHANNEL_2); // 使能 PWM 通道 2
/* 禁用輸出 */
#define MOTOR_FWD_DISABLE() HAL_TIM_PWM_Stop(&TIM_TimeBaseStructure,PWM_CHANNEL_1); // 禁用 PWM 通道 1
#define MOTOR_REV_DISABLE() HAL_TIM_PWM_Stop(&TIM_TimeBaseStructure,PWM_CHANNEL_2); // 禁用 PWM 通道 2
使用宏定義非常方便程序升級、移植。 如果使用不同的定時器IO,修改這些宏即可。
設置電機速度
void set_motor_speed(uint16_t v)
{
dutyfactor = v;
if (direction == MOTOR_FWD)
{
SET_FWD_COMPAER(dutyfactor); // 設置速度
}
else
{
SET_REV_COMPAER(dutyfactor); // 設置速度
}
}
根據電機的旋轉方向來設置電機的速度(占空比),并記錄下設置的占空比,方便在切換旋轉 方向時設置另一路為相同的占空比。
設置電機方向
void set_motor_direction(motor_dir_t dir)
{
direction = dir;
if (direction == MOTOR_FWD)
{
SET_FWD_COMPAER(dutyfactor); // 設置速度
SET_REV_COMPAER(0); // 設置占空比為 0
}
else
{
SET_FWD_COMPAER(0); // 設置速度
SET_REV_COMPAER(dutyfactor); // 設置占空比為 0
}
}
將一路PWM的占空比設置為0,另一路用于設置速度。
主要
/**
* @brief 主函數
* @param 無
* @retval 無
*/
int main(void)
{
__IO uint16_t ChannelPulse = PWM_MAX_PERIOD_COUNT/2;
uint8_t i = 0;
/* 初始化系統時鐘為168MHz */
SystemClock_Config();
/* 初始化按鍵GPIO */
Key_GPIO_Config();
/* 電機初始化 */
motor_init();
set_motor_disable();
set_motor_speed(ChannelPulse);
while(1)
{
/* 掃描KEY1 */
if( Key_Scan(KEY1_GPIO_PORT, KEY1_PIN) == KEY_ON)
{
/* 使能電機 */
set_motor_enable();
}
/* 掃描KEY2 */
if( Key_Scan(KEY2_GPIO_PORT, KEY2_PIN) == KEY_ON)
{
set_motor_disable();
}
/* 掃描KEY3 */
if( Key_Scan(KEY3_GPIO_PORT, KEY3_PIN) == KEY_ON)
{
/* 增大占空比 */
ChannelPulse += PWM_MAX_PERIOD_COUNT/10;
if(ChannelPulse > PWM_MAX_PERIOD_COUNT)
ChannelPulse = PWM_MAX_PERIOD_COUNT;
set_motor_speed(ChannelPulse);
}
/* 掃描KEY4 */
if( Key_Scan(KEY4_GPIO_PORT, KEY4_PIN) == KEY_ON)
{
if(ChannelPulse < PWM_MAX_PERIOD_COUNT/10)
ChannelPulse = 0;
else
ChannelPulse -= PWM_MAX_PERIOD_COUNT/10;
set_motor_speed(ChannelPulse);
}
/* 掃描KEY5 */
if( Key_Scan(KEY5_GPIO_PORT, KEY5_PIN) == KEY_ON)
{
/* 轉換方向 即Forward,正轉運行;相對地,REV,即Reverse,反轉運行
采用三元運算符 i是奇數是反轉運行,i是偶數是正轉運行,*/
set_motor_direction( (++i % 2) ? MOTOR_FWD : MOTOR_REV);
}
}
}
首先初始化系統時鐘,然后初始化定時器和按鍵,將占空比設置為50%。 在死循環里面掃描按鍵,KEY1按下使能電機驅動板,KEY2按下失能電機驅動板,KEY3按鍵按下增加速度(占空比),KEY4按鍵按下減少速度(占空比), KEY5按鍵按下切換電機旋轉方向。 (轉換方向 即Forward,正轉運行; 相對地,REV,即Reverse,反轉運行,采用三元運算符:i是奇數是反轉運行,i是偶數是正轉運行)
4.4.4. 下載驗證
如果有條件的話,這里我們先不連接電機,先通過示波器連接到開發板的PWM輸出引腳上,通過示波器來觀察PWM 的變化情況:
- 使用DAP連接開發板到電腦;
- 使用示波器的CH1連接到PA15,CH2連接到PB3,注意示波器要與開發板共地;
- 給開發板供電,編譯下載配套源碼,復位開發板。
上電后我們通過示波器可以觀察到兩個通道都是低電平,當按下KEY1后,使能PWM輸出,按KEY3可以增加CH1通道的占空比, ,按KEY4可以減小占空比,按KEY5可以交換PWM輸出,如下圖所示。
在上圖中黃色波形為CH1通道,藍色波形為CH2通道,按下一次KEY1后,能使PWM輸出。 此時可以通過計算示波器上顯示的波形在占空比和頻率, 通過波形計算也與理論相符,這說明我們的PWM的配置是正確的,其中CH2通道的波形 一直為低電平。 當CH1和CH2都為低電平時,電機停止轉動。 當CH1上的平均電壓大于電機的啟動電壓后電機就 可以轉動了,電源電壓為12V,占空比為D,則平均電壓為:12V*D。 當按下KEY5后兩通道輸出相反,CH1一直為 低電平,CH2為PWM波,電機反向轉動。
在確定PWM輸出正確后我們就可以接上電機進行驗證我們的程序了。
按鍵操作:
- KEY1:使能電機
- KEY2:禁用電機
- KEY3:加速
- KEY4:減速比
- KEY5:換向
可以通過按鍵來操作來觀察電機的執行效果
評論