圓曾經(jīng)的小車夢,造一臺智能小車(三)之小車前進后退左右轉(zhuǎn)基本框架
接前面幾篇文章:
圓曾經(jīng)的小車夢,造一臺智能小車(一)
圓曾經(jīng)的小車夢,造一臺智能小車(二)
基于小熊派WIFI PWM控制小車前進后退
這節(jié),終于讓我們的小車成功的驅(qū)動起來了,能夠?qū)崿F(xiàn)基本功能:前進、后退、左轉(zhuǎn)、右轉(zhuǎn),完成這一步,剩下的也就不難了,本節(jié)采用的是Wifi通信的方式來進行控制。
1、本節(jié)實驗平臺
-
小熊派開發(fā)板(當(dāng)然如果你手上沒有可以用別的stm32板子代替) 用于控制小車
-
普中STM32F103ZET6開發(fā)板(小車上的載板)
2、Wifi小車控制原理
2.1 說說Wifi控制的邏輯
本節(jié)采用的是小熊派上的兩個按鍵,分別來控制小車前進、后退、停止,由于只有兩個按鍵,所以后面又把它用來測試小車的左轉(zhuǎn)、右轉(zhuǎn)。
那么要用wifi控制小車動起來,控制板(小熊派)需要有一個wifi,讓它處于客戶端模式,而小車上的載板(上面連接著WIFI),讓它處于服務(wù)器模式,這樣,讓控制板連接載板成功以后,接下來控制板發(fā)送自定義指令給載板,載板收到指令后即響應(yīng)具體的指令,完成小車的前進、后退、左轉(zhuǎn)、右轉(zhuǎn)、停止的工作。
自定義協(xié)議定義:
控制指令 | 含義 |
---|---|
LEFT | 讓小車左轉(zhuǎn) |
RIGHT | 讓小車左轉(zhuǎn) |
GO | 讓小車前進 |
BACK | 讓小車后退 |
STOP | 讓小車停止 |
那么如何讓W(xué)IFI處于服務(wù)器、客戶端模式呢?請看以前的文章鏈接:
基于小熊派WIFI-ESP8266實踐(上)
基于小熊派WIFI-ESP8266實踐(中)-多功能處理顯示等大雜燴
WIFI DTU產(chǎn)品設(shè)計與實現(xiàn)(基于STM32F103+QT配置上位機案例設(shè)計分享)
我們直接用以前做好的成功來完成我們的功能就好了。
2.2 再說說小車的控制邏輯
在我們前面第一、第二篇文章測試電機轉(zhuǎn)的時候,默認(rèn)我們使用的是全速轉(zhuǎn),也就是給;298N電機驅(qū)動模塊某個管腳一個高電平,電機就全速轉(zhuǎn)起來了,至于讓四個輪如何向前轉(zhuǎn),如何向后轉(zhuǎn),這得根據(jù)你自己的接線方式來定,我是按照下面這個圖來接的:(自己畫的,還是不懂怎么接的話隨時騷擾我)
本人經(jīng)過接線測試后得出以下結(jié)論:
上面所表示的二進制數(shù)指的是電機驅(qū)動模塊的控制端,而我有兩個控制端,所以需要兩組。
看到這里,那大家可能就會說了,如果我只給某個IO輸出一個高電平,這樣電機不就一直是全速前進或者全速后退嗎?怎么能控制電機的速度呢?怎么能實現(xiàn)左轉(zhuǎn)、右轉(zhuǎn)呢?這里需要用到PWM的知識,什么是PWM呢?
PWM(Pulse Width Modulation):脈沖寬度調(diào)制
我們可以看看上圖,上圖就是一個典型的PWM的波形圖。
T是一個周期,T1就是高電平所占用的時間,T2就是低電平所占用的時間。
如上圖所示T1為脈沖寬度(就是導(dǎo)通時間),周期為T,則輸出電壓的平均值為U=VCC*T1/T=a*VCC
,a是占空比,變化范圍為0≤a≤1
。在電壓不變的情況下,改變a的大小就可以改變輸出電壓的平均值。這就是單片機的PWM調(diào)制技術(shù)。
如何改變a呢?可以采用定時器,也可以用普通的延時,一般情況下用定時器產(chǎn)生PWM輸出信號,誤差極小,而且控制也很準(zhǔn),我們平時經(jīng)常聽到的占空比,也就是高電平占整個周期的比例。
當(dāng)要前進的時候,左右前后電機同時向前轉(zhuǎn),這時候PWM值可以設(shè)大一些。
當(dāng)要后退的時候,左右前后電機同時向后轉(zhuǎn),這時候PWM值可以設(shè)大一些。
如下演示視頻所示:
當(dāng)要左轉(zhuǎn)的時候,右邊前后電機轉(zhuǎn)的快一點(PWM值大一些),左邊前后兩個電機轉(zhuǎn)的慢一點(PWM值小一些)。
當(dāng)要右轉(zhuǎn)的時候,左邊前后電機轉(zhuǎn)的快一點(PWM值大一些),右邊前后兩個電機轉(zhuǎn)的慢一點(PWM值小一些)。
如下演示視頻所示:
2.3 整體控制邏輯
-
(1)控制板連接小車載板 -
(2)連接載板成功后,控制板通過按鍵發(fā)送指令給小車載板(前進、后退、左轉(zhuǎn)、右轉(zhuǎn)) -
(3)小車載板收到控制指令后即控制電機實現(xiàn)指令要求的邏輯。
這樣小車的基本框架就有了。
核心處理邏輯如下:(1)省略,文末自行查看代碼,WIFI處理采用串口+DMA的方式
控制端(小熊派)
void button1_down_callback(void *ptr)
{
printf("按下1鍵\n");
//發(fā)送指令前進
wifi_init_printf("GO");
//發(fā)送指令左轉(zhuǎn)
//wifi_init_printf("LEFT");
}
void button1_up_callback(void *ptr)
{
printf("釋放1鍵\n");
//發(fā)送指令停止
wifi_init_printf("STOP");
}
void button2_down_callback(void *ptr)
{
printf("按下2鍵\n");
//發(fā)送指令后退
wifi_init_printf("BACK");
//發(fā)送指令右轉(zhuǎn)
//wifi_init_printf("RIGHT");
}
void button2_up_callback(void *ptr)
{
printf("釋放2鍵\n");
//發(fā)送指令停止
wifi_init_printf("STOP");
}
小車載板端(STM32F103ZET6)
電機的8個控制端采用的是PWM進行驅(qū)動:
TIM1:PWM控制左邊四路電機
TIM2:PWM控制右邊四路電機
改變PWM占空比函數(shù)實現(xiàn):
static void Motor_PWM_SetValue(TIM_HandleTypeDef *htim, uint32_t Channe, unsigned short value)
{
TIM_OC_InitTypeDef sConfigOC;
if(value >= 1000 - 1) value = 999;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
//改變PWM值
sConfigOC.Pulse = value;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, Channe) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Start(htim, Channe) != HAL_OK)
{
Error_Handler();
}
}
相應(yīng)的測試PWM值:
//停止
#define CCR0_Val 0
#define CCR1_Val 125
#define CCR2_Val 250
#define CCR3_Val 500
#define CCR4_Val 750
//最快速
#define CCR5_Val 999
WIFI小車控制處理
/*wifi接收指令處理*/
static void Wifi_Recv_Cmd_Process(void)
{
static int cmd_index = 0 ;
char *cmd[] = {"LEFT", "RIGHT", "GO", "BACK", "STOP"};
if(strstr((char *)esp8266_info.rx_buffer, cmd[cmd_index]) != NULL)
{
HAL_UART_DMAStop(&huart2);
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
printf("接收到客戶端發(fā)來的指令:%s\n", esp8266_info.rx_buffer);
switch(cmd_index)
{
//左轉(zhuǎn)
case 0:
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_1, CCR0_Val); //0 ==> 控制左前輪后
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_2, CCR2_Val); //1 ==> 控制左前輪前 ===> 慢
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_3, CCR5_Val); //1 ==> 控制右前輪前 ===> 快
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_4, CCR0_Val); //0 ==> 控制右前輪后
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_1, CCR2_Val); //1 ==> 控制左后輪前 ===> 慢
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_2, CCR0_Val); //0 ==> 控制左后輪后
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_3, CCR0_Val); //0 ==> 控制右后輪后
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_4, CCR5_Val); //1 ==> 控制右后輪前 ===> 塊
break ;
//右轉(zhuǎn)
case 1:
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_1, CCR0_Val); //0
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_2, CCR5_Val); //1 快
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_3, CCR2_Val); //1 慢
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_4, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_1, CCR5_Val); //1 快
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_2, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_3, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_4, CCR2_Val); //1 慢
break ;
//前進
case 2:
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_1, CCR0_Val); //0
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_2, CCR5_Val); //1
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_3, CCR5_Val); //1
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_4, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_1, CCR5_Val); //1
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_2, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_3, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_4, CCR5_Val); //1
break ;
//后退
case 3:
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_1, CCR5_Val); //1
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_2, CCR0_Val); //0
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_3, CCR0_Val); //0
Motor_PWM_SetValue(&htim1, TIM_CHANNEL_4, CCR5_Val); //1
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_1, CCR0_Val); //0
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_2, CCR5_Val); //1
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_3, CCR5_Val); //1
Motor_PWM_SetValue(&htim2, TIM_CHANNEL_4, CCR0_Val); //0
break ;
//停止
case 4:
Moto_Stop();
break ;
}
memset(esp8266_info.rx_buffer, 0, RX_BUFF_SIZE);
HAL_UART_Receive_DMA(&huart2, esp8266_info.rx_buffer, RX_BUFF_SIZE);
}
++cmd_index ;
if(5 == cmd_index)
cmd_index = 0 ;
}
這節(jié)我們直接實現(xiàn)了單片機跟單片機之前的WIFI通信,后面我們將繼續(xù)拓展,開發(fā)一個手機APP,實現(xiàn)Android手機wifi連接小車,或者在筆記本PC端開發(fā)一個QT APP,然后通過筆記本的wifi連接小車,控制小車前進,后退,左轉(zhuǎn),右轉(zhuǎn)。
案例下載
公眾號后臺回復(fù)wifi小車
即可獲取。
往期精彩
基于小熊派WIFI PWM控制小車前進后退
圓曾經(jīng)的小車夢,造一臺智能小車(二)
圓曾經(jīng)的小車夢,造一臺智能小車(一)
MCU串口命令解析器的實現(xiàn)
覺得本次分享的文章對您有幫助,隨手點[在看]
并轉(zhuǎn)發(fā)分享,也是對我的支持。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!