当前位置:   article > 正文

基于stm32的智能小车_stm32智能小车

stm32智能小车

目录

一、功能实现

二、硬件清单

三、代码实现

1.先让小车动起来

2.串口控制小车行动

3.点动控制小车

4.硬件pwm调速

5. 左右轮各自调速

6. 循迹小车

7. 解决转弯平滑问题

8. 跟随小车

9. 摇头避障小车

9.1封装摇头功能

9.2封装超声波

9.3 封装电机驱动

10.小车测速实现

11.  串口控制小车并使用Oled显示速度

12. Wi-Fi测速小车并本地Oled显示

13. 语音控制小车


一、功能实现

左右转与前进后退:通过控制左组轮和右组轮的配合实现。pwm调速使其更平滑

循迹功能:基于光电传感器原理,通过判断黑线和白线来决定左转或者右转

跟随功能:通过超声波测出小车和跟随物的距离决定移动方向

避障功能:通过超声波检测出前方障碍物,做出改变方向的决定

语音模块控制:多种语音改变多种引脚的电平,通过语音控制实现以上多种功能的切换

old屏显示速度:将测速模块的数据通过oled屏显示

二、硬件清单

1.stm32f103(其他型号也行)板子

2.智能小车底盘、电机马达

3.电池盒和电池

4.超声波模块

5.sg90舵机模块

(黄pwm 红vcc 灰gnd)

6.old屏

7.测速模块

8.红外模块

9.esp8266

10.语音识别模块

三、代码实现

1.先让小车动起来

电机接线:B-1A -- PB0 B-1B -- PB1 A-1A -- PB2 A-1B -- PB10

motor.c
  1. #include "motor.h"
  2. void goForward(void)//前进
  3. {
  4. // 左轮
  5. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
  6. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  7. // 右轮
  8. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
  9. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  10. }
  11. void goBack(void)后退
  12. {
  13. // 左轮
  14. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
  15. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
  16. // 右轮
  17. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  18. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
  19. }
  20. void goLeft(void)//左转
  21. {
  22. // 左轮
  23. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
  24. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  25. // 右轮
  26. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
  27. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  28. }
  29. void goRight(void)//右转
  30. {
  31. // 左轮
  32. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
  33. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  34. // 右轮
  35. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  36. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  37. }
  38. void stop(void)//停止
  39. {
  40. // 左轮
  41. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
  42. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
  43. // 右轮
  44. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  45. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  46. }
motor.h
  1. #ifndef __MOTOR_H__
  2. #define __MOTOR_H__
  3. #include "main.h"
  4. void goForward(void);
  5. void goBack(void);
  6. void goLeft(void);
  7. void goRight(void);
  8. void stop(void);
  9. #endif
main.c
  1. #include "motor.h"
  2. //main函数的while循环部分:
  3. while (1)
  4. {
  5. /* USER CODE END WHILE */
  6. goForward();
  7. HAL_Delay(1000);
  8. goBack();
  9. HAL_Delay(1000);
  10. goLeft();
  11. HAL_Delay(1000);
  12. goRight();
  13. HAL_Delay(1000);
  14. stop();
  15. HAL_Delay(1000);
  16. /* USER CODE BEGIN 3 */
  17. }

2.串口控制小车行动

usart.c
  1. #include "string.h"
  2. #include "stdio.h"
  3. #include "motor.h"
  4. //串口接收缓存(1字节)
  5. uint8_t buf=0;
  6. //定义最大接收字节数 200,可根据需求调整
  7. #define UART1_REC_LEN 200
  8. // 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
  9. uint8_t UART1_RX_Buffer[UART1_REC_LEN];
  10. // 接收状态
  11. // bit15, 接收完成标志
  12. // bit14, 接收到0x0d
  13. // bit13~0, 接收到的有效字节数目
  14. uint16_t UART1_RX_STA=0;
  15. #define SIZE 12
  16. char buffer[SIZE];
  17. // 接收完成回调函数,收到一个数据后,在这里处理
  18. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  19. {
  20. //判断中断由哪个串口触发
  21. if(huart->Instance == USART1)
  22. {
  23. //判断接收是否完成(UART1_RX_STA bit15 位是否为1)
  24. if((UART1_RX_STA & 0x8000) == 0)
  25. {
  26. //如果已经收到了 0x0d (回车),
  27. if(UART1_RX_STA & 0x4000)
  28. {
  29. //判断是否收到 0x0a (换行)
  30. if(buf == 0x0a)
  31. {
  32. //如果 0x0a和0x0d都收到,则将bit15位置为1
  33. UART1_RX_STA |= 0x8000;
  34. if(!strcmp(UART1_RX_Buffer, "M1"))
  35. goForward();
  36. else if(!strcmp(UART1_RX_Buffer, "M2"))
  37. goBack();
  38. else if(!strcmp(UART1_RX_Buffer, "M3"))
  39. goLeft();
  40. else if(!strcmp(UART1_RX_Buffer, "M4"))
  41. goRight();
  42. else
  43. stop();
  44. memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
  45. UART1_RX_STA = 0;
  46. }
  47. else
  48. //否则认为接收错误,重新开始
  49. UART1_RX_STA = 0;
  50. }
  51. else // 如果没有收到了 0x0d (回车)
  52. {
  53. //则先判断收到的这个字符是否是 0x0d (回车)
  54. if(buf == 0x0d)
  55. {
  56. //是的话则将 bit14 位置为1
  57. UART1_RX_STA |= 0x4000;
  58. }
  59. else
  60. {
  61. //否则将接收到的数据保存在缓存数组里
  62. UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
  63. UART1_RX_STA++;
  64. //如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
  65. if(UART1_RX_STA > UART1_REC_LEN - 1)
  66. UART1_RX_STA = 0;
  67. }
  68. }
  69. }
  70. //重新开启中断
  71. HAL_UART_Receive_IT(&huart1, &buf, 1);
  72. }
  73. }
  74. int fputc(int ch, FILE *f)
  75. {
  76. unsigned char temp[1]={ch};
  77. HAL_UART_Transmit(&huart1,temp,1,0xffff);
  78. return ch;
  79. }
main.c
  1. #include "motor.h"
  2. extern uint8_t buf;
  3. //main函数
  4. HAL_UART_Receive_IT(&huart1, &buf, 1);

3.点动控制小车

usart.c
  1. if (!strcmp(UART1_RX_Buffer, "M1"))
  2. {
  3. goForward();
  4. HAL_Delay(10);
  5. }
  6. else if (!strcmp(UART1_RX_Buffer, "M2"))
  7. {
  8. goBack();
  9. HAL_Delay(10);
  10. }
  11. else if (!strcmp(UART1_RX_Buffer, "M3"))
  12. {
  13. goLeft();
  14. HAL_Delay(10);
  15. }
  16. else if (!strcmp(UART1_RX_Buffer, "M4"))
  17. {
  18. goRight();
  19. HAL_Delay(10);
  20. }
  21. else
  22. stop();
main.c
  1. HAL_NVIC_SetPriority(SysTick_IRQn,0,0); //或者通过cubeMX配置
  2. while(1)
  3. {
  4. stop();
  5. }

4.硬件pwm调速

cubeMX 配置

 根据公式配置psc和arr

 

 代码实现

main.c

  1. // main函数里
  2. HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  3. HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
  4. while (1)
  5. {
  6. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 8);
  7. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 8);
  8. HAL_Delay(1000);
  9. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 10);
  10. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 10);
  11. HAL_Delay(1000);
  12. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 15);
  13. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 15);
  14. HAL_Delay(1000);
  15. }

5. 左右轮各自调速

代码实现
  1. // main函数里
  2. while (1)
  3. {
  4. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8);
  5. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15);
  6. HAL_Delay(1000);
  7. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15);
  8. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8);
  9. HAL_Delay(1000);
  10. }

6. 循迹小车

循迹模块(左) -- PB3  循迹模块(右) -- PB4

代码实现

  1. #define LeftWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
  2. #define RightWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)
  3. // main函数里
  4. while (1)
  5. {
  6. if (LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_RESET)
  7. goForward();
  8. if (LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_RESET)
  9. goLeft();
  10. if (LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_SET)
  11. goRight();
  12. if (LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_SET)
  13. stop();
  14. }

7. 解决转弯平滑问题

代码实现
  1. #define LeftWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
  2. #define RightWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)
  3. // main函数里
  4. while (1)
  5. {
  6. if(LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_RESET)
  7. {
  8. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,19);
  9. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,19);
  10. }
  11. if(LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_RESET)
  12. {
  13. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15);
  14. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8);
  15. }
  16. if(LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_SET)
  17. {
  18. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8);
  19. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15);
  20. }
  21. if(LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_SET)
  22. {
  23. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,0);
  24. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,0);
  25. }
  26. }

8. 跟随小车

跟随模块(左) -- PB5  跟随模块(右) -- PB6
代码实现
  1. #define LeftWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5)
  2. #define RightWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6)
  3. // main函数里
  4. while (1)
  5. {
  6. if(LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_RESET)
  7. goForward();
  8. if(LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_RESET)
  9. goRight();
  10. if(LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_SET)
  11. goLeft();
  12. if(LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_SET)
  13. stop();
  14. }

9. 摇头避障小车

9.1封装摇头功能
舵机接线:sg90 -- PB9
sg90.c
  1. #include "sg90.h"
  2. #include "gpio.h"
  3. #include "tim.h"
  4. void initSG90(void)//初始化90度
  5. {
  6. HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4); //启动定时器4
  7. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 17); //将舵机置为90度
  8. }
  9. void sgMiddle(void)
  10. {
  11. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 17); //将舵机置为90度
  12. }
  13. void sgRight(void)
  14. {
  15. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5); //将舵机置为0度
  16. }
  17. void sgLeft(void)
  18. {
  19. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25); //将舵机置为180度
  20. }

sg90.h

  1. #ifndef __SG90_H__
  2. #define __SG90_H__
  3. void initSG90(void);
  4. void sgMiddle(void);
  5. void sgRight(void);
  6. void sgLeft(void);
  7. #endif

main.c

  1. initSG90();
  2. HAL_Delay(1000);
  3. while (1)
  4. {
  5. sgLeft();
  6. HAL_Delay(1000);
  7. sgMiddle();
  8. HAL_Delay(1000);
  9. sgRight();
  10. HAL_Delay(1000);
  11. sgMiddle();
  12. HAL_Delay(1000);
  13. }
9.2封装超声波

超声波接线 Trig       --    PB7  Echo     -- PB8

cubeMX 配置

 

 

 

代码实现
sr04.c
  1. #include "sr04.h"
  2. #include "gpio.h"
  3. #include "tim.h"
  4. //使用TIM2来做us级延时函数
  5. void TIM2_Delay_us(uint16_t n_us)
  6. {
  7. /* 使能定时器2计数 */
  8. __HAL_TIM_ENABLE(&htim2);
  9. __HAL_TIM_SetCounter(&htim2, 0);
  10. while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
  11. /* 关闭定时器2计数 */
  12. __HAL_TIM_DISABLE(&htim2);
  13. }
  14. double get_distance(void)
  15. {
  16. int cnt=0;
  17. //1. Trig ,给Trig端口至少10us的高电平
  18. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);//拉高
  19. TIM2_Delay_us(20);
  20. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);//拉低
  21. //2. echo由低电平跳转到高电平,表示开始发送波
  22. //波发出去的那一下,开始启动定时器
  23. while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET);//等待输入电平拉高
  24. HAL_TIM_Base_Start(&htim2);
  25. __HAL_TIM_SetCounter(&htim2,0);
  26. //3. 由高电平跳转回低电平,表示波回来了
  27. while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET);//等待输入电平变低
  28. //波回来的那一下,我们开始停止定时器
  29. HAL_TIM_Base_Stop(&htim2);
  30. //4. 计算出中间经过多少时间
  31. cnt = __HAL_TIM_GetCounter(&htim2);
  32. //5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)
  33. return (cnt*340/2*0.000001*100); //单位:cm
  34. }
sr04.h
  1. #ifndef __SR04_H__
  2. #define __SR04_H__
  3. double get_distance(void);
  4. #endif
main.c
  1. while (1)
  2. {
  3. if(dir != MIDDLE)
  4. {
  5. sgMiddle();
  6. dir = MIDDLE;
  7. HAL_Delay(300);
  8. }
  9. disMiddle = get_distance();
  10. if(disMiddle > 35)
  11. {
  12. //前进
  13. }
  14. else
  15. {
  16. //停止
  17. //测左边距离
  18. sgLeft();
  19. HAL_Delay(300);
  20. disLeft = get_distance();
  21. sgMiddle();
  22. HAL_Delay(300);
  23. sgRight();
  24. dir = RIGHT;
  25. HAL_Delay(300);
  26. disRight = get_distance();
  27. }
  28. }
9.3 封装电机驱动
硬件接线与1一样: B-1A -- PB0  B-1B -- PB1  A-1A -- PB2  A-1B -- PB10
代码实现
  1. while (1)
  2. {
  3. /* USER CODE END WHILE */
  4. /* USER CODE BEGIN 3 */
  5. if(dir != MIDDLE){
  6. sgMiddle();
  7. dir = MIDDLE;
  8. HAL_Delay(300);
  9. }
  10. disMiddle = get_distance();
  11. if(disMiddle > 35){
  12. //前进
  13. goForward();
  14. }else if(disMiddle < 10){
  15. goBack();
  16. }else
  17. {
  18. //停止
  19. stop();
  20. //测左边距离
  21. sgLeft();
  22. HAL_Delay(300);
  23. disLeft = get_distance();
  24. sgMiddle();
  25. HAL_Delay(300);
  26. sgRight();
  27. dir = RIGHT;
  28. HAL_Delay(300);
  29. disRight = get_distance();
  30. if(disLeft < disRight){
  31. goRight();
  32. HAL_Delay(150);
  33. stop();
  34. }
  35. if(disRight < disLeft){
  36. goLeft();
  37. HAL_Delay(150);
  38. stop();
  39. }
  40. }
  41. HAL_Delay(50);
  42. }

10.小车测速实现

硬件接线 测速模块: VCC -- 3.3V 不能接5V,否则遮挡一次会触发 3 次中断  OUT -- PB14
cubeMX 配置

 

 

 代码实现

  1. unsigned int speedCnt;
  2. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  3. {
  4. if (GPIO_Pin == GPIO_PIN_14)
  5. if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)
  6. speedCnt++;
  7. }
  8. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  9. {
  10. printf("speed: %d\r\n", speedCnt);
  11. speedCnt = 0;
  12. }
  13. main函数里:
  14. HAL_TIM_Base_Start_IT(&htim2);

11.  串口控制小车并使用Oled显示速度

硬件接线 SCL -- PB6 SDA -- PB7
封装 Oled 模块
代码实现
oled.c
  1. #include "oled.h"
  2. #include "i2c.h"
  3. #include "oledfont.h"
  4. void Oled_Write_Cmd(uint8_t dataCmd)
  5. {
  6. HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
  7. &dataCmd, 1, 0xff);
  8. }
  9. void Oled_Write_Data(uint8_t dataData)
  10. {
  11. HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
  12. &dataData, 1, 0xff);
  13. }
  14. void Oled_Init(void){
  15. Oled_Write_Cmd(0xAE);//--display off
  16. Oled_Write_Cmd(0x00);//---set low column address
  17. Oled_Write_Cmd(0x10);//---set high column address
  18. Oled_Write_Cmd(0x40);//--set start line address
  19. Oled_Write_Cmd(0xB0);//--set page address
  20. Oled_Write_Cmd(0x81); // contract control
  21. Oled_Write_Cmd(0xFF);//--128
  22. Oled_Write_Cmd(0xA1);//set segment remap
  23. Oled_Write_Cmd(0xA6);//--normal / reverse
  24. Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
  25. Oled_Write_Cmd(0x3F);//--1/32 duty
  26. Oled_Write_Cmd(0xC8);//Com scan direction
  27. Oled_Write_Cmd(0xD3);//-set display offset
  28. Oled_Write_Cmd(0x00);//
  29. Oled_Write_Cmd(0xD5);//set osc division
  30. Oled_Write_Cmd(0x80);//
  31. Oled_Write_Cmd(0xD8);//set area color mode off
  32. Oled_Write_Cmd(0x05);//
  33. Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
  34. Oled_Write_Cmd(0xF1);//
  35. Oled_Write_Cmd(0xDA);//set com pin configuartion
  36. Oled_Write_Cmd(0x12);//
  37. Oled_Write_Cmd(0xDB);//set Vcomh
  38. Oled_Write_Cmd(0x30);//
  39. Oled_Write_Cmd(0x8D);//set charge pump enable
  40. Oled_Write_Cmd(0x14);//
  41. Oled_Write_Cmd(0xAF);//--turn on oled panel
  42. }
  43. void Oled_Screen_Clear(void){
  44. char i,n;
  45. Oled_Write_Cmd (0x20); //set memory addressing mode
  46. Oled_Write_Cmd (0x02); //page addressing mode
  47. for(i=0;i<8;i++){
  48. Oled_Write_Cmd(0xb0+i); //éè??ò3μ??·£¨0~7£?
  49. Oled_Write_Cmd(0x00); //éè????ê??????aáDμíμ??·
  50. Oled_Write_Cmd(0x10); //éè????ê??????aáD??μ??·
  51. for(n=0;n<128;n++)Oled_Write_Data(0x00);
  52. }
  53. }
  54. void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
  55. unsigned int i;
  56. Oled_Write_Cmd(0xb0+(row*2-2)); //page 0
  57. Oled_Write_Cmd(0x00+(col&0x0f)); //low
  58. Oled_Write_Cmd(0x10+(col>>4)); //high
  59. for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
  60. Oled_Write_Data(F8X16[i]); //写数据oledTable1
  61. }
  62. Oled_Write_Cmd(0xb0+(row*2-1)); //page 1
  63. Oled_Write_Cmd(0x00+(col&0x0f)); //low
  64. Oled_Write_Cmd(0x10+(col>>4)); //high
  65. for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
  66. Oled_Write_Data(F8X16[i]); //写数据oledTable1
  67. }
  68. }
  69. /******************************************************************************/
  70. // 函数名称:Oled_Show_Char
  71. // 输入参数:oledChar
  72. // 输出参数:无
  73. // 函数功能:OLED显示单个字符
  74. /******************************************************************************/
  75. void Oled_Show_Str(char row,char col,char *str){
  76. while(*str!=0){
  77. Oled_Show_Char(row,col,*str);
  78. str++;
  79. col += 8;
  80. }
  81. }
oled显示速度
代码实现
  1. extern uint8_t buf;
  2. unsigned int speedCnt = 0;
  3. char speedMes[24]; //主程序发送速度数据的字符串缓冲区
  4. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  5. {
  6. if (GPIO_Pin == GPIO_PIN_14)
  7. if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)
  8. speedCnt++;
  9. }
  10. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  11. {
  12. printf("speed: %d\r\n", speedCnt);
  13. sprintf(speedMes,"speed:%2d cm/s",speedCnt);//串口数据的字符串拼装,speed是格子,每个格子1cm
  14. Oled_Show_Str(2,2,speedMes);
  15. speedCnt = 0;
  16. }

12. Wi-Fi测速小车并本地Oled显示

硬件接线  把esp8266插进串口 1
代码实现
main.c
  1. #define MIDDLE 0
  2. #define LEFT 1
  3. #define RIGHT 2
  4. #define BZ 1
  5. #define XJ 2
  6. #define GS 3
  7. #define LeftWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
  8. #define RightWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)
  9. #define LeftWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)
  10. #define RightWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9)
  11. #define A25 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)
  12. #define A26 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_13)
  13. #define A27 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_14)
  14. char dir;
  15. void xunjiMode()
  16. {
  17. if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_RESET)
  18. goForward();
  19. if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_RESET)
  20. goLeft();
  21. if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_SET)
  22. goRight();
  23. if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_SET)
  24. stop();
  25. }
  26. void gensuiMode()
  27. {
  28. if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_RESET)
  29. goForward();
  30. if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_RESET)
  31. goRight();
  32. if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_SET)
  33. goLeft();
  34. if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_SET)
  35. stop();
  36. }
  37. void bizhangMode()
  38. {
  39. double disMiddle;
  40. double disLeft;
  41. double disRight;
  42. if(dir != MIDDLE){
  43. sgMiddle();
  44. dir = MIDDLE;
  45. HAL_Delay(300);
  46. }
  47. disMiddle = get_distance();
  48. if(disMiddle > 35){
  49. //前进
  50. goForward();
  51. }else if(disMiddle < 10){
  52. goBack();
  53. }else
  54. {
  55. //停止
  56. stop();
  57. //测左边距离
  58. sgLeft();
  59. HAL_Delay(300);
  60. disLeft = get_distance();
  61. sgMiddle();
  62. HAL_Delay(300);
  63. sgRight();
  64. dir = RIGHT;
  65. HAL_Delay(300);
  66. disRight = get_distance();
  67. if(disLeft < disRight){
  68. goRight();
  69. HAL_Delay(150);
  70. stop();
  71. }
  72. if(disRight < disLeft){
  73. goLeft();
  74. HAL_Delay(150);
  75. stop();
  76. }
  77. }
  78. HAL_Delay(50);
  79. }
  80. //main部分
  81. MX_GPIO_Init();
  82. MX_TIM4_Init();
  83. MX_TIM2_Init();
  84. MX_I2C1_Init();
  85. initSG90();
  86. HAL_Delay(1000);
  87. dir = MIDDLE;
  88. Oled_Init();
  89. Oled_Screen_Clear();
  90. Oled_Show_Str(2,2,"-----Ready----");
  91. while (1)
  92. {
  93. //满足寻迹模式的条件
  94. if(A25 == 1 && A26 == 1 && A27 == 0){
  95. if(mark != XJ){
  96. Oled_Screen_Clear();
  97. Oled_Show_Str(2,2,"-----XunJi----");
  98. }
  99. mark = XJ;
  100. xunjiMode();
  101. }
  102. //满足跟随模式的条件
  103. if(A25 == 0 && A26 == 1 && A27 == 1){
  104. if(mark != GS){
  105. Oled_Screen_Clear();
  106. Oled_Show_Str(2,2,"-----GenSui----");
  107. }
  108. mark = GS;
  109. gensuiMode();
  110. }
  111. //满足避障模式的条件
  112. if(A25 == 1 && A26 == 0 && A27 == 1){
  113. if(mark != BZ){
  114. Oled_Screen_Clear();
  115. Oled_Show_Str(2,2,"-----BiZhang----");
  116. }
  117. mark = BZ;
  118. bizhangMode();
  119. }
  120. }
  121. }

13. 语音控制小车

语音模块硬件接线 A25 -- PA15 (跟随) A26 -- PA13 (避障) A27 -- PA14 (循迹)
cubeMX配置

 

 代码实现

  1. #include "sg90.h"
  2. #include "sr04.h"
  3. #include "motor.h"
  4. #include "oled.h"
  5. #include "string.h"
  6. #define MIDDLE 0
  7. #define LEFT 1
  8. #define RIGHT 2
  9. #define BZ 1
  10. #define XJ 2
  11. #define GS 3
  12. #define LeftWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
  13. #define RightWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)
  14. #define LeftWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)
  15. #define RightWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9)
  16. #define XJ_VALUE HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_14)
  17. #define GS_VALUE HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)
  18. #define BZ_VALUE HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_13)
  19. char dir;
  20. void xunjiMode()
  21. {
  22. if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_RESET)
  23. goForward();
  24. if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_RESET)
  25. goLeft();
  26. if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_SET)
  27. goRight();
  28. if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_SET)
  29. stop();
  30. }
  31. void gensuiMode()
  32. {
  33. if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_RESET)
  34. goForward();
  35. if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_RESET)
  36. goRight();
  37. if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_SET)
  38. goLeft();
  39. if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_SET)
  40. stop();
  41. }
  42. void bizhangMode()
  43. {
  44. double disMiddle;
  45. double disLeft;
  46. double disRight;
  47. if(dir != MIDDLE){
  48. sgMiddle();
  49. dir = MIDDLE;
  50. HAL_Delay(300);
  51. }
  52. disMiddle = get_distance();
  53. if(disMiddle > 35){
  54. //前进
  55. goForward();
  56. }else if(disMiddle < 10){
  57. goBack();
  58. }else
  59. {
  60. //停止
  61. stop();
  62. //测左边距离
  63. sgLeft();
  64. HAL_Delay(300);
  65. disLeft = get_distance();
  66. sgMiddle();
  67. HAL_Delay(300);
  68. sgRight();
  69. dir = RIGHT;
  70. HAL_Delay(300);
  71. disRight = get_distance();
  72. if(disLeft < disRight){
  73. goRight();
  74. HAL_Delay(150);
  75. stop();
  76. }
  77. if(disRight < disLeft){
  78. goLeft();
  79. HAL_Delay(150);
  80. stop();
  81. }
  82. }
  83. HAL_Delay(50);
  84. }
  85. int main(void)
  86. {
  87. int mark = 0;
  88. HAL_Init();
  89. SystemClock_Config();
  90. MX_GPIO_Init();
  91. MX_TIM4_Init();
  92. MX_TIM2_Init();
  93. MX_I2C1_Init();
  94. initSG90();
  95. HAL_Delay(1000);
  96. dir = MIDDLE;
  97. Oled_Init();
  98. Oled_Screen_Clear();
  99. Oled_Show_Str(2,2,"-----Ready----");
  100. while (1)
  101. {
  102. if(XJ_VALUE == GPIO_PIN_RESET && GS_VALUE == GPIO_PIN_SET && BZ_VALUE ==
  103. GPIO_PIN_SET)
  104. {
  105. if(mark != XJ)
  106. {
  107. Oled_Screen_Clear();
  108. Oled_Show_Str(2,2,"-----XunJi----");
  109. }
  110. mark = XJ;
  111. xunjiMode();
  112. }
  113. //满足循迹模式的条件
  114. if(XJ_VALUE == GPIO_PIN_SET && GS_VALUE == GPIO_PIN_RESET && BZ_VALUE ==
  115. GPIO_PIN_SET)
  116. {
  117. if(mark != GS)
  118. {
  119. Oled_Screen_Clear();
  120. Oled_Show_Str(2,2,"-----GenSui----");
  121. }
  122. mark = GS;
  123. gensuiMode();
  124. }
  125. //满足避障模式的条件
  126. if(XJ_VALUE == GPIO_PIN_SET && GS_VALUE == GPIO_PIN_SET && BZ_VALUE ==
  127. GPIO_PIN_RESET)
  128. {
  129. if(mark != BZ)
  130. {
  131. Oled_Screen_Clear();
  132. Oled_Show_Str(2,2,"-----BiZhang----");
  133. }
  134. mark = BZ;
  135. bizhangMode();
  136. }
  137. HAL_Delay(50);
  138. }
  139. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46180
推荐阅读
相关标签
  

闽ICP备14008679号