赞
踩
目录
花上一周的时间制作一个智能小车玩玩吧,一直想要制作一辆自己的智能小车,看多了网上的各种小车,有循迹的,超声波的,蓝牙的,还有WIFI的,总之是各种各样。看别人做自己也想亲手制作一辆。网上的小车动则好几百,少则也得百来块钱,对于初学者真的很不友好。
怎样花费最少的钱,来制作想要的东西成为了今天的话题,今天就让我来带你用最少的资金最喜欢的小车车。话不多说,先上成品:
一.购买元器件
1.底盘:看到这里大家一定很好奇,这是什么地盘。相信自己的眼睛,那就是一次性筷子粘合在一起的地盘,虽然简陋,但我感觉跟花上20元买的亚克力没有太大区别。
2.直流电机:四个差不多10元。
3.L298N:直流电机驱动模块,可以同时驱动两路电机,我这里一路接了两个电机,一个L298N的驱动能力完全可以带动四个电机,4元。相比于已经停产TB6612要便宜很多。
4.蓝牙模块HC-05:用于手机上位机与小车通信,实现远程遥控,15元
5.超声波模块HC-SR04:用于小车避障功能,3元
6.SG90舵机:这里选择-90°~90°就可以满足条件了,4元
7.0.96寸OLED显示屏:用于显示当前距离,还有模式的切换,6元
8.STM32c8t6:主控芯片,便宜又好用,15元
9.一些电子元器件:几块钱解决
二.绘制PCB电路板
智能小车原理图
3D主板模型
软件部分是基于HAL库来编写的,我也是刚接触不久HAL库,因为ST官方现在主推的HAL库,所以作为一名合格的码农,应该紧跟时代发展。HAL库确实方便了程序的开发,以前需要花费大量的时间在写初始化配置上,现在有了这个工具(CUBEMX)可以说是拿到了程序的句柄,把更多的时间用在实现功能上,大大缩短了开发周期。下面就跟着我的步伐开始配置工程。
1.使能RCC外部高速时钟与低速时钟
2.将时钟倍频至72MHZ
3.在SYS中选择Debug->Serial Wire,这一步的配置是为了在下载的时候自动复位,一定要选择,不然很麻烦,我是使用的ST-link烧写器
4.首先给L298N配置参数,需要两路PWM用于电机调速,CH1,与CH2。还需要四个IO口用于控制电机正反转跟停止,将GPIO设置为推挽模式,参数配置如图。
5 .将定时器1设置为驱动舵机的PWM信号,配置如下:
6.将定时器3设置为超声波测距的时钟,配置如下:
这边的配置很关键,一定要将预分频设置为71,主计数器为最大值,用于超声波的定时模式,否则会有错误。
7.配置定时器4为20ms中断一次,用于不间断的显示OLED上面的信息。防止频闪。
8.这样所有的定时器都设置完成了。还有驱动OLED的引脚没有设置,我们继续配置引脚。这里我使用的是0.96寸OLED,四根线的,也就是iic总线。iic总线有软件和硬件的传输方式,这里我用的是软件的IIC。
9.由于采用的是HC_05蓝牙模块,采用的是串口通信,那么我们来配置串口,这里需要注意,一定要打开串口的NVIC,在NVIC中把勾勾打上,否则MCU不会接收中断,也接收不到数据。
10.到这里基本的功能已经配置完成,为了方便以后扩展功能,我还增加了四个独立按键。按键要选择上拉输入模式。上拉是为了读取按键的低电平检测,即使外部有上电阻,也最好打开内部上拉电阻。
11.配置完成我们生成大代码。在生成的过程中我们需要注意几点。最好不要有中文路径,我这里讲解就放桌面了,选择使用MDK-arm打开方式。
选择仅加载需要的文件进行配置,这样可以缩短编译时间。完后生成独立的.c与.h文件,这样会让整个程序看起来清爽干净。最后点击生成完成配置工作。
完成配置我们打开工程文件,这边我就直接提供各个模块的程序,我把他们都差分出来,方便大家一一对应着理解。
1.小车运动
- #define N1_on HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
- #define N1_off HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
- #define N2_on HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
- #define N2_off HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
- #define N3_on HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
- #define N3_off HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
- #define N4_on HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
- #define N4_off HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
-
-
- void for_word(void);
- void back_word(void);
- void left_word(void);
- void right_word(void);
- void off_word(void);
- void for_word(void)
- {
- N1_on;
- N2_off;
- N3_on;
- N4_off;
- }
-
- void back_word(void)
- {
- N1_off;
- N2_on;
- N3_off;
- N4_on;
- }
-
- void left_word(void)
- {
- N1_off;
- N2_on;
- N3_on;
- N4_off;
- }
-
- void right_word(void)
- {
- N1_on;
- N2_off;
- N3_off;
- N4_on;
- }
- void off_word(void)
- {
- N1_off;
- N2_off;
- N3_off;
- N4_off;
- }
启动定时器2,开启通道1与通道2
- HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//左路PWM波
- HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//右路PWM波
设置PWM占空比,我这边PWM占空比达到100%的话,直接放200就可以。
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, 110);
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 110);
2.舵机驱动,这边可以在某宝上面看到怎么使用。只需要给舵机通电(5V),在信号线送入不同占空比的PWM信号就可以控制舵机的旋转角度。
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);//舵机PWM
测试程序
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 5);HAL_Delay(2000);//-90
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 10);HAL_Delay(2000);//-45
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 15);HAL_Delay(2000);//0
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 20);HAL_Delay(2000);//45
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 25); HAL_Delay(2000);//90
4.超声波测距
- #define Trig_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET)
- #define Trig_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET)
- void user_delaynus_tim(uint32_t nus)
- {
- uint16_t differ = 0xffff-nus-5;
- __HAL_TIM_SetCounter(&htim3,differ);//设置定时器2的计数初始值
- HAL_TIM_Base_Start(&htim3);//开启定时器
- while( differ<0xffff-5)
- {
- differ = __HAL_TIM_GetCounter(&htim3);
- }
- HAL_TIM_Base_Stop(&htim3);//关闭定时器
- }
-
-
- uint16_t csb_value(void)
- {
- uint16_t count=0;
-
- Trig_H ;
- user_delaynus_tim(12);//维持12us高电平
- Trig_L ;
-
- HAL_TIM_Base_Start(&htim3); //开启定时器3
-
- while( HAL_GPIO_ReadPin (GPIOB ,GPIO_PIN_0) != GPIO_PIN_SET);
-
- __HAL_TIM_SetCounter(&htim3,0);//将定时器3初始值清零,以便开始从零计数
-
- while(HAL_GPIO_ReadPin (GPIOB ,GPIO_PIN_0) == GPIO_PIN_SET); //检测到低电平停止计数
-
- HAL_TIM_Base_Stop(&htim3);//关闭定时器3
-
- count = __HAL_TIM_GetCounter(&htim3);//读出计数值
-
- // distance = (uint16_t )count*0.017;
- // OLED_ShowNum(72,0,distance,4,16);
- count=(uint16_t )count*0.017;
-
- //HAL_Delay (500);//两次测量之间间隔时间
-
- return count;
-
- }
5.蓝牙串口通信,这边主要是用于调试串口收发数据,记得蓝牙的波特率与串口一的波特率一定要一致,一般为9600,这一步很关键,否则将无法接收上位机发送的数据。
HAL_UART_Receive_IT(&huart1,arr1,3);
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart->Instance == huart1.Instance)
- {
- if(arr1[0]==0XBF && arr1[1]==0XA1 && arr1[2]==0XFb )
- {
- printf("*");
- HAL_UART_Receive_IT(&huart1,arr1,3);
- }
- if(arr1[0]==0XBF && arr1[1]==0XA2 && arr1[2]==0XFb )
- {
- printf("&");
- HAL_UART_Receive_IT(&huart1,arr1,3);
- }
- }
- }
6.OLED 的程序普遍一致,我就不展示了,大家可以去下载别人的程序修改或者私聊我。
7.主函数程序演示
- if(csbvalue > 20 || csbvalue == 20)
- {
-
- for_word();
- }
- else
- {
- off_word();
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 25);
- HAL_Delay(500);
- left_distance=csbvalue;
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 5);
- HAL_Delay(500);
- right_distance=csbvalue;
-
- __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 15);
-
- if(left_distance>right_distance && left_distance>20)
- {
- left_word();
- HAL_Delay(1000);
- }
- else if(right_distance>left_distance && right_distance>20)
- {
- right_word();
- HAL_Delay(1000);
- }
- else
- {
- back_word();
- HAL_Delay(500);
- }
- }
看到这里相信你已经完成了你的小车,小车整体不难,相比之下调试部分是需要花费一些功夫,比如控制小车转弯的时间,超声波读取回来数据在到小车做出反应的时间,都是需要根据自己的实际情况来调节。相信大家那么聪明一定能用最短的时间做出自己心仪的小车。
我认为小车还有不足的一点,就是在接收障碍物后,小车要停止做出反应,但是由于惯性,小车不可能立即停止,一直与小车会继续前进而撞向障碍物,这样我就不得不增加检测到障碍物的距离。而增加距离的话,看起来会很笨,还没到障碍物就停止了。我能想到的是给它加上PID控制,PID控制我会放在下篇文章来详细给大家分析。感谢支持。
如有错误,欢迎指正,如有帮助,不胜荣幸。
下面再来欣赏一下我这极具性价比的小车吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。