5. 智能小车

文章目录

  • 智能小车
  • 电机驱动模块L9110S介绍
  • 循迹模块TCRT5000
    • [1. 模块介绍](#1. 模块介绍)
      • [1.1 型号介绍](#1.1 型号介绍)
      • [1.2 工作参数及引脚介绍](#1.2 工作参数及引脚介绍)
      • [1.3 通信示意图](#1.3 通信示意图)
      • [1.3 TCRT5000工作原理](#1.3 TCRT5000工作原理)
  • 测速模块
    • [1. 测速模块介绍](#1. 测速模块介绍)
      • [1.1 测速模块型号介绍](#1.1 测速模块型号介绍)
      • [1.2 测速模块参数及引脚介绍](#1.2 测速模块参数及引脚介绍)
    • [2. 使用逻辑](#2. 使用逻辑)
  • 4G模块
    • [1. 内网穿透](#1. 内网穿透)
    • [2. 花生壳配置【借助该工具生成IP地址】](#2. 花生壳配置【借助该工具生成IP地址】)
    • [3. 4G模块配置](#3. 4G模块配置)
  • 项目1:让小车动起来
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
      • [3.1 框架搭建](#3.1 框架搭建)
      • [3.2 小车内容](#3.2 小车内容)
  • 项目2:串口控制小车
    • 1.项目需求
    • [2. 构思环节](#2. 构思环节)
      • [2.1 框架搭建](#2.1 框架搭建)
      • [2.2 功能处理](#2.2 功能处理)
  • 项目3:蓝牙控制小车
  • 项目4:小车点动控制
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
    • [4. 实验结果](#4. 实验结果)
  • 项目5:PWM调速小车
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
    • [4. 实验结果](#4. 实验结果)
  • 项目6:循迹小车
  • 项目7:跟随小车
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
    • [4. 实验结果](#4. 实验结果)
  • 项目8:避障小车
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
    • [4. 出现的问题](#4. 出现的问题)
    • [5. 实验结果](#5. 实验结果)
  • 项目9:测速小车
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
      • [1. 测速](#1. 测速)
      • [2. 速度显示在OLED屏幕上,并通过蓝牙模块传输到手机上](#2. 速度显示在OLED屏幕上,并通过蓝牙模块传输到手机上)
    • [4. 实验结果](#4. 实验结果)
  • 项目10:Wifi控制小车并发送速度
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
    • [4. 出现的问题](#4. 出现的问题)
    • [5. 实验结果](#5. 实验结果)
  • [项目11: 4G 控制小车](#项目11: 4G 控制小车)
  • [项目12 :语音控制小车](#项目12 :语音控制小车)
    • 语音模块:SU-03T
      • [1. 语音模块介绍](#1. 语音模块介绍)
        • [1.1 型号介绍](#1.1 型号介绍)
        • [1.2 工作参数及引脚介绍](#1.2 工作参数及引脚介绍)
      • [2. 通信示意图](#2. 通信示意图)
      • [3. SU-03T 配置](#3. SU-03T 配置)
      • [4. 如何烧录?](#4. 如何烧录?)
    • [1. 项目需求](#1. 项目需求)
    • [2. 硬件接线](#2. 硬件接线)
    • [3. 构思环节](#3. 构思环节)
    • [4. 实验结果](#4. 实验结果)

智能小车


电机驱动模块L9110S介绍

1. L9110S型号介绍

L9110S有二路和四路两种,二路可以驱动2个直流电机,或者1个4线2相式步进电机;四路可以驱动4个直流电机,或者2个4线2相式步进电机。

二路和四路

2. L9110S参数及引脚介绍

L9110S参数:

  • 双L9110S芯片的电机驱动
  • 模块供电电压:2.5V~12V
  • 工作温度:0℃~80℃
  • 适合的电机范围:电机工作电压2.5V~12V之间,最大工作电流0.8A
  • 可以同时驱动2个直流电机,或者1个4线2相式步进电机
  • PCB板尺寸:2.8cm*2.1cm超小体积,适合组装
  • 设有固定安装孔,直径:3mm
STM32 电机驱动L9110S 备注
任意GPIO口 A-1A 控制电机
任意GPIO口 A-1B 控制电机
任意GPIO口 B-1A 控制电机
任意GPIO口 B-1B 控制电机
VCC 外接电源正极(2.5~12V)
GND 外接电源负极

用杜邦线可以直接插进模块绿色的接口,其他的线用螺丝刀调整接口大小即可接入。

接通VCC、GND,模块电源指示灯(红)灯亮。

以驱动2个直流电机为例:

A-1A输入高电平,A-1B输入低电平,MotorA电机正转;

A-1A输入低电平,A-1B输入高电平,MotorA电机反转;

B-1A输入高电平,B-1B输入低电平,MotorB电机正转;

B-1A输入低电平,B-1B输入高电平,MotorB电机反转;

思考?【为什么左转时,左轮全设置为高电平,而不是低电平?】

如果在左转时把左轮两个引脚都设为高电平。

  • 左轮会瞬间急刹,不仅导致车身剧烈抖动,转弯极不平稳
  • 瞬间短路电流极大,会导致电源电压剧烈波动(可能复位单片机),甚至烧毁电机驱动芯片的MOS管。

循迹模块TCRT5000

在自动驾驶和机器人技术领域,循迹模块是至关重要的组成部分。它能够使车辆或机器人沿着预定的路径精确行驶,从而实现各种复杂任务。

1. 模块介绍

1.1 型号介绍

TCRT5000 不断发射红外信号,当红外信号:

  1. 有反射回来,DO 输出低电平,开关指示灯(绿灯)亮。
  2. 没反射回来,DO 输出高电平,开关指示灯(绿灯)灭。

TCRT5000 常见用途:

  1. 电度表脉冲数据采样
  2. 传真机碎纸机纸张检测
  3. 障碍检测
  4. 黑白线检测(包含循迹小车)

1.2 工作参数及引脚介绍

TCRT5000红外循迹模块工作参数:

  • 工作电压:DC 3.3V ~ 5V
  • 检测反射距离:1mm ~ 25mm适用(不同厂家会略有差异)

模拟中蓝色的电位器用于调节灵敏度,顺时针旋转,灵敏度变高;

逆时针越小,灵敏度变低。

上电后电源指示灯(红灯)亮

接线如下:

TCRT5000 STM32 备注
VCC 3.3/5V 电源正极
GND GND 电源负极
DO 任意GPIO口 数字输出
AO 有ADC功能的引脚 模拟输出(一般不用)

1.3 通信示意图

这个小案例的应用场景可以应用在工业自动化,当物体或人在禁止区域或危险区域时,红灯亮起以提醒离开此区域。

1.3 TCRT5000工作原理

简述:

有障碍物,DO输出低电平,开关指示灯亮

无障碍物,DO输出高电平,开关指示灯灭

测速模块

测速是现代化测控系统中不可或缺的一部分,它通过精确测量物体或现象的速度,为众多应用领域提供了关键的数据支持。

1. 测速模块介绍

1.1 测速模块型号介绍

测速模块常见用途:

  1. 电机转速检测
  2. 脉冲计数
  3. 位置限位
  4. 工件计数

常见的测速模块有以下三款,大同小异,都是接三个引脚(四引脚的那款AO引脚不起作用),除了正负极就是数字输出(OUT)。

1.2 测速模块参数及引脚介绍

测速模块参数:

  • 使用进口槽型光耦传感器,槽宽度10mm
  • 有遮挡,输出高电平;无遮挡,输出低电平
  • 有输出状态指示灯,输出高电平灯灭,输出低电平灯亮
  • 使用宽电压LM393比较器
  • 比较器输出,信号干净,波形好,驱动能力强,超过15mA
  • 工作电压:3.3V ~ 5V
  • 输出形式:数字开关量输出(0和1)
  • 设有固定螺栓孔,方便安装
  • 小板PCB尺寸:2.3cm × 2cm

    参考接线:
测速模块 STM32 备注
VCC 3.3/5V 电源正极
OUT 任意GPIO口 数字输出
GND GND 电源负极

OUT连接:

  1. 与单片机IO口直接相连,检测传感器是否有遮挡,如用电机码盘则可检测电机的转速。
  2. 与继电器相连,组成限位开关等功能。
  3. 与有源蜂鸣器模块相连,组成报警器。

2. 使用逻辑

  1. 测速模块槽汇总无遮挡时,输出低电平,灯亮;遮挡时,输出高电平,灯灭;
  2. 圆周长C = 2 × 3.14 × r = 3.14 × d

以TT马达和配套轮胎(直径6.5cm)、码盘(20个格子)为例:

  1. 码盘每经过一个格子,会遮挡(高电平)和不遮挡(低电平);
  2. 20格的码盘转一圈会经历20个下降沿中断,一个下降沿中断就是圆的周长÷20 = 3.14 × 6.5 / 20 = 1.0205 cm, 约等于一个中断走1 cm。
    测速模块测距离:计算中断次数,即距离
    测速模块测速度:利用定时器,1秒内接收多少个外部中断,即每秒速度。

使用逻辑:

  1. 如何计算中断次数?

    对GPIO口进行配置,接着对测速模块的引脚计算产生多少中断,在中断中进行++,算出距离

  2. 单位时间内测算距离?

    定时器定时1秒,观察中断几次,将中断里的变量拿出来。

其他轮胎或码盘可套用公式:

测距离 = 3.14×直径/码盘格子×中断次数。

测速度 = 定时器每秒输出 3.14×直径/码盘格子×中断次数,记得重置中断次数。

4G模块

局域网:可理解为设备连接到同一个路由器

1. 内网穿透

简单说,连接到一个路由器的为一个内网;路由器以外是外网,两个路由器是外网。

如何用外网访问内网?

------内网穿透

如何实现内网穿透?

借助花生壳工具 实现内网穿透

2. 花生壳配置【借助该工具生成IP地址】

用网络调试助手,外网方式访问(内网穿透)

外网与内网通信:

内网之间也可以通信:

3. 4G模块配置

接线图:

4G模块:可理解为自带网络

相关参数:

注意:上述表格中"DATA与LINK"的后面介绍反了

4g模块支持AT指令,可通过EC05配置上位机:

上位机配置:

  1. 选择端口号(根据自己的端口选择)
  2. 选择波特率(默认115200)
  3. 打开串口
  4. 点击进入配置,上位机会自动发送AT指令进行配置
  5. 读取参数,此命令可以读取4G模块的详细信息,并打印带有基本信息栏(这一步很重要,否则第九步时会出现问题)
  6. 选择链路
  7. 默认是连接亿佰特的服务器,需要修改成我们自己的,具体从花生壳获取(是一串域名,或者IP地址,他都支持,根据自己获取到的填写就可以)
  8. 输入从花生壳获取的端口号
  9. 点击保存配置(对应第五步,我们很多配置需要获取到模块默认配置,保存时才会不改变)
  10. 点击重启(重启后默认进入透传模式,无需在做其他操作,直接链接到串口助手上即可发送与接收信息)

    上位机配置完成,接下来开始发送数据,可通过串口调试助手发送

串口调试助手相当于4G模块

心跳包 :每隔10秒钟发送一次

进入AT指令,发送+++不用换行,收\r\n+OK\r\n,即进入到

项目1:让小车动起来

1. 项目需求

让小车动起来,实现小车前进、后退、左转、右转功能。

2. 硬件接线

STM32 电机驱动
PB1 A-1A
PB0 A-1B
PB10 B-1A
PB2 B-1B

电机由电池供电;

上官二号由ST-Link供电;

3. 构思环节

3.1 框架搭建

  1. 创建智能小车项目文件夹
  2. 将串口打印功能实验的文件夹改名为"让小车动起来"
  3. 在BSP文件夹中创建motor文件夹
  4. 打开keil软件,将motor文件加载进来

3.2 小车内容

motor.c

c 复制代码
#include "motor.h"

void motor_init(void)
{
   1. 打开时钟
   2. 引脚【多个引脚】
   3. 推挽输出
   4. 上拉
   5. 高速
   HAL_GPIO_Init(GPIOB, 句柄);
 
   6. 小车停止 // 小车上电后,处于停止状态
}

void motor_go_forward(void)
{
      // 左轮 PB0和PB1是左轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
      // 右轮 PB2和PB10是右轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}

void motor_go_backward(void)
{
      // 左轮 PB0和PB1是左轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
      // 右轮 PB2和PB10是右轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
}

// 左转时,左轮不动,右轮动
void motor_go_left(void)
{
      // 左轮 PB0和PB1是左轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
      // 右轮 PB2和PB10是右轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}

// 右转时,右轮不动左轮动
void motor_go_right(void)
{
      // 左轮 PB0和PB1是左轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
      // 右轮 PB2和PB10是右轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}

void motor_stop(void)
{
      // 左轮 PB0和PB1是左轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
      // 右轮 PB2和PB10是右轮
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}

main.c

  1. 初始化
  2. 实现前进后退左转右转
c 复制代码
while(1)
{
  motor_go_forward();
  delay_ms(2000);
  motor_go_backward();
  delay_ms(2000);
  motor_go_left();
  delay_ms(2000);
  motor_go_right();
  delay_ms(2000);
  motor_go_stop();
  delay_ms(2000);
}

项目2:串口控制小车

1.项目需求

串口控制小车

2. 构思环节

2.1 框架搭建

  1. 在让小车动起来实验基础上做该项目
  2. 在BSP文件夹中加入蓝牙bluetooth文件夹
  3. 先注释while循环中的代码
  4. 加载蓝牙模块进来,msp函数加入串口2,因为蓝牙要用到

2.2 功能处理

蓝牙控制小车实现效果:

发送M1,前进

发送M2,后退

发送M3,左转

发送M4,右转

蓝牙模块,是在串口2中断服务函数中获取数据,接收串口收到的数据,接下来对串口的数据进行处理:

  1. 比对接收到的数据和**"M1"**, 前进
c 复制代码
if(strcmp((char *)uart2_rx_buf, "M1") == 0)
   motor_go_forward();
else if(strcmp((char *)uart2_rx_buf, "M2") == 0)
   motor_go_backward();
else if(strcmp((char *)uart2_rx_buf, "M3") == 0)
   motor_go_left();
else if(strcmp((char *)uart2_rx_buf, "M4") == 0)
   motor_go_right();
else
   motor_stop();
  1. 主函数
    main.c
c 复制代码
bt_init(9600);
  1. 硬件上
    插上串口2
    串口2发送M1,串口1接收到M1,小车前进
    串口2发送M2,串口1接收到M2,小车后退
    串口2发送M3,串口1接收到M3,小车左转
    串口2发送M4,串口1接收到M4,小车右转

项目3:蓝牙控制小车

本节项目不涉及代码,直接从项目2串口控制小车中,串口2换成蓝牙模块,通过手机HC蓝牙助手软件发送M1、M2、M3、M4,观察结果。

该小车目前通过ST-Link供电,如何让上官二号通过电池供电,实现小车自己跑?

1个电池1.5V,4个电池6V

找一个公对母的杜邦线,一边接面包板正极,一边接主板的5V

项目4:小车点动控制

1. 项目需求

利用HC蓝牙助手软件,按下前进按键,小车前进一下,实现点动控制小车。

2. 硬件接线

硬件接线上,拔掉蓝牙模块,插入串口2,同时去掉上一个实验的5V杜邦线

3. 构思环节

  1. 在串口控制小车实验基础上做
  2. 实现环节
    main.c
c 复制代码
while(1)
{
    motor_stop();
}

初始化时,处于stop状态;

串口接收数据时,小车动起来

bluetooth.c

在中断函数这,对小车的前进后退左转右转进行延时

c 复制代码
delay_ms(10);

4. 实验结果

利用串口2循环发"M1",实现点动效果

项目5:PWM调速小车

1. 项目需求

小车控速,不一直以最快速度跑。

2. 硬件接线

STM32 电机驱动
PA0 A-1A
PB1 A-1B
PA1 B-1A
PB10 B-1B

3. 构思环节

  1. 在项目1基础上做该项目
  2. 复制呼吸灯实验的pwm文件夹
  3. 一系列加载动作,不具体说明【HAL库的定时器记得也加载起来】
  4. pwm修改
    pwm.c
c 复制代码
pwm_init()
{
    // 时基单元
    修改定时器为TIM2

    // 配置
    Pluse = 0
    高电平
    配置为通道1和通道2
    开启通道1和通道2
}

msp函数
1. 修改引脚为PA0和PA1
2. 推挽输出
3. 上拉
4. 高速

修改CCR值的函数
// 左轮
void pwm_left_motor_set(uint16_t val)
{
  __HAL_TIM_SET_COMPARE(&pwm_handle, TIM_CHINNEL_1, val);
}

// 右轮
void pwm_right_motor_set(uint16_t val)
{
   __HAL_TIM_SET_COMPARE(&pwm_handle, TIM_CHINNEL_2, val);
}

main.c

c 复制代码
pwm_init(20 - 1, 72 - 1);

// 调速
while(1)
{
   pwm_left_motor_set(8);
   pwm_right_motor_set(8);
   delay_ms(1000);
   pwm_left_motor_set(10);
   pwm_right_motor_set(10);
   delay_ms(1000);
   pwm_left_motor_set(15);
   pwm_right_motor_set(15);
   delay_ms(1000);
}

如何实现左轮快,右轮慢?

c 复制代码
pwm_left_motor_set(8);
pwm_right_motor_set(15);
delay_ms(1000);
pwm_left_motor_set(15);
pwm_right_motor_set(8);
delay_ms(1000);

4. 实验结果

上电后,小车左轮先慢后快,右轮先快后慢。

项目6:循迹小车

1. 项目需求

实现小车按跑道路线行驶。

2. 硬件接线

STM32 电机驱动 循迹模块
PB0 A-1A
PB1 A-1B
PB2 B-1A
PB10 B-1B
PB13 DO(左)
PB14 DO(右)

3. 构思环节

3.1 框架搭建

  1. 在项目1【让小车动起来】实验基础上做该项目
  2. 先复制智能台灯项目中的ia_sensor文件夹,并添加到该项目的BSP文件夹中,改名为track。

3.2 循迹模块修改

  1. 修改引脚PB13和PB14
  2. 功能:
    左边循迹模块是否踩到黑线,踩到则输出一个值;未踩到输出另一个值
c 复制代码
uint8_t track_left_flag(void)
{
   if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == GPIO_PIN_RESET)
        return TRUE;
   else
        return  FALSE;
}

uint8_t track_right_flag(void)
{
   if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)
        return TRUE;
   else
        return  FALSE;
}

3.3 主函数

main.c

c 复制代码
track_init();
while(1)
{
    1. 判断循迹模块返回的是true还是false
    2. 如果为false,踩到黑线,需左转或右转
    if(track_left_flag() == TRUE && track_right_flag() == TRUE)
      motor_go_forward();
      // 车头往右,所以要左转来回正
    else if (track_left_flag() == FALSE && track_right_flag() == TRUE)
       motor_go_left();
    else if (track_left_flag() == TRUE && track_right_flag() == FALSE)
       motor_go_right();
    else if (track_left_flag() == FALSE && track_right_flag() == FALSE) 
    motor_stop();
}

小车在跑道上拐弯后,冲出跑道,如何解决?

小车降速;电池换成锂电池,重量减轻。

循迹+pwm调速功能实现

在pwm调速小车实验基础上做搞项目

接线与pwm调速项目接线一致

STM32 电机驱动
PB10 A-1A
PA0 A-1B
PB1 B-1A
PA1 B-1B
主函数

main.c

c 复制代码
// 因为设置10过快,设置9过慢,所以修改arr和psc的值
pwm_init(200 - 1, 720 - 1);
track_init();
while(1)
{
    if(track_left_flag() == TRUE && track_right_flag() == TRUE)
    {
       pwm_left_motor_set(95);
       pwm_right_motor_set(95);
    }
    
        else if(track_left_flag() == FALSE && track_right_flag() == TRUE)
        {
          pwm_left_motor_set(0);
          pwm_right_motor_set(95);
        }

        else if(track_left_flag() == TRUE && track_right_flag() == FALSE)
        {
            pwm_left_motor_set(95);
            pwm_right_motor_set(0);
        }
            
        else if(track_left_flag() == FALSE && track_right_flag() == FALSE)
        {
              pwm_left_motor_set(0);
              pwm_right_motor_set(0);
        }
            
}
出现的问题:占空比太低,带不动右轮

解决:

可修改arr和psc的值;

也可以先加速调速,判断是否为占空比低导致的

项目7:跟随小车

1. 项目需求

使用红外模块,

左边红外模块检测到有物体,左转【右轮动】,追随物体;

右边红外模块检测到有物体,右转【左轮动】,追随物体;

如果物体过大,左右红外模块同时检测到物体,小车一直前进,追随物体。

2. 硬件接线

STM32 电机驱动 跟随模块
PB10 A-1A
PB2 A-1B
PB1 B-1A
PB0 B-1B
PB5 OUT(左)
PB6 OUT(右)

3. 构思环节

  1. 在项目1【让小车动起来】基础上做该实验
  2. 复制循迹模块文件夹,添加到该项目的BSP文件夹中,改名为follow。
  3. 内容修改
c 复制代码
修改引脚
  1. main函数
c 复制代码
follow_init();
while(1)
{
  if(follow_left_flag() == TRUE && follow_right_flag() == TRUE)
       motor_go_forward();
  else if(follow_left_flag() == TRUE && follow_right_flag() == FALSE)
      motor_go_left();
   else if(follow_left_flag() == FALSE && follow_right_flag() == TRUE)
      motor_go_right();
   else if(follow_left_flag() == TRUE && follow_right_flag() == FALSE)
      motor_stop();
}

4. 实验结果

跟着障碍物路线走

项目8:避障小车

1. 项目需求

超声波传感器测距,小于某个值就是障碍物,小车遇到障碍物之后,小车停下,判断左转还是右转,

这时超声波传感器左转,测量左边距离,再转回中间;

接下来超声波传感器右转,测量右边距离;

判断左边与右边的距离,

如果左边距离<右边距离,左边障碍物距离更近,往右转;

反之,则左转。

2. 硬件接线

STM32 电机驱动 舵机 超声波
PB10 A-1A
PB2 A-1B
PB1 B-1A
PB0 B-1B
PA6 橙线
PA12 Trig
PA11 Echo

3. 构思环节

  1. 在项目1【让小车动起来】基础上做搞项目
  2. 在BSP文件夹添加sg90文件夹、hcsr04文件夹,并加载进来,将HAL库的定时器加载进来。
  3. sg90模块内容【摇头】
c 复制代码
1. 左转
void sg90_turn_left(void)
{
   sg90_angle_set(180);
}

2. 居中
void sg90_turn_middle(void)
{
    sg90_angle_set(90);
}

3. 右转
void sg90_turn_right(void)
{
  sg90_angle_set(0);
}
  1. main函数
c 复制代码
sg90_init();
while(1)
{
   sg90_turn_left();
   delay_ms(1000);
   sg90_turn_middle();
   delay_ms(1000);
   sg90_turn_right();
   delay_ms(1000);
}
  1. hcsr40【测距】
    main.c
c 复制代码
hcsr04_init();
while(1)
{
    printf("dis: %.2f\r\n", hcsr04_get_length());
    delay_ms(1000);
}
  1. 测距+摇头
c 复制代码
double dis_left = 0, dis_middle = 0, dis_right = 0;
// 传感器初始化时,为居中状态
sg90_turn_middle();
// 开始测量
while(1)
{
// 先测量中间数据
dis_middle = hcsr04_get_length();
 如果大于某个距离
 if(dis_middle > 35)
      motor_go_forward();
 else if(dis_middle < 15)
     motor_go_backward();
 else
 {
     1. 先停下
     motor_stop();
     2. 向左看,并测量左侧距离
     sg90_turn_left();
     delay_ms(500);
     dis_left = hcsr04_get_length();
     3. 居中
     sg90_turn_middle();
     delay_ms(500);
     4. 向右看,并测量右边距离
     sg90_turn_right();
     delay_ms(500);
     dis_right = hcsr04_get_length();
     5. 根据距离判断是左转还是右转
     if(dis_left < dis_right)
           motor_go_right();
     else
          motor_go_left();
     delay_ms(200);
     motor_stop();
     sg90_turn_middle();
 }
delay_ms(100);
   
}

4. 出现的问题

小车在判断转向时,小车并不左转还是右转,而是一直原地转。

c 复制代码
if(dis_left < dis_right)
                sg90_turn_right();
 else
                sg90_turn_left();

解决:【自己对小车理解错误】

5. 实验结果

链接:https://live.csdn.net/v/537461?spm=1001.2014.3001.5501

项目9:测速小车

1. 项目需求

串口输出电机旋转距离(cm)和速度(cm/s);

速度显示在OLED屏幕上,并通过蓝牙模块传输到手机上;

2. 硬件接线

STM32 电机驱动 测速模块 OLED
PB0 A-1A
PB1 A-1B
PB2 B-1A
PB10 B-1B
PB12 OUT
PB8 SCL
PB9 SDA
3.3V VCC VCC VCC
GND GND GND GND

⚠️注意:测速模块、蓝牙模块、OLED模块,都需要接到3.3V电源!

3. 构思环节

1. 测速

  1. 在项目2【串口控制小车】基础上做该项目
  2. 新建speed文件夹,加入相关.c和.h文件,用来测速;别忘记加入HAL库中的定时器
  3. 测速模块内容
    speed.c
c 复制代码
#include "speed.h"
#include "stdio.h"

用来接收产生多少个中断
uint16_t speed_cnt = 0;
 
void speed_gpio_init(void)
{
     参考中断代码
     1. 引脚PB12
     2. 无上拉下拉
     3. 中断时10~15
}

// 中断处理函数
void EXTI_IRQHandler(void)
{
     修改引脚
}
// 中断服务函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    修改引脚
    speed_cnt++;
    printf("speed: %d\r\n", speed_cnt);
}


void speed_time_init(void)
{

}
void speed_init(void)
{
    speed_gpio_init();
}

main.c

c 复制代码
speed_init();
motor_go_forward();

先测试,串口的速度一直在一个格子的增加,说明在数格子,即成功

接下来,加入定时器,定时1秒钟,1秒钟数了多少个格子

speed.c

c 复制代码
void speed_time_init(psc,arr)
{
   参考之前定时器中断点灯代码
   定时器2
}

msp函数
中断服务函数

更新中断回调函数:功能实现
printf("speed: %d\r\n", speed_cnt);
speed_cnt = 0; // 清空,否则出现影响下一次计数

测试模块初始化
void speed_init(void)
{
    speed_gpio_init();
    speed_time_init(10000 - 1, 7200 - 1);
}

测试:如果速度在30~60多,说明正确。

2. 速度显示在OLED屏幕上,并通过蓝牙模块传输到手机上

  1. 在测速小车实验基础上做
  2. 在BSP文件夹中,添加OLED文件夹【在以前实验中复制过来最简单】
  3. main函数中进行初始化
  4. 在speed.c中的中断回调函数里,已经获取到速度的值,接下来要把这个值显示在oled屏幕上,实现如下:

oled引脚也需要修改

c 复制代码
#include "string.h"
#include "oled.h"

char speed_str[24] = {0};
void HAL_TIM_PeriodElapsedCalback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM2)
    {
       printf("speed: %d\r\n", speed_cnt);
       先进行清空
       memset(speed_str, 0, sizeof(speed_str));
       sprintf(speed_str, "speed: %2d cm/s", speed_cnt);
       oled_show_string(10, 2, speed_str, 16);
       蓝牙模块
       bt_send(speed_str);
       bt_send("\r\n");
       speed_cnt = 0;
    }
}

oled.c

修改oled引脚

oled修改

c 复制代码
oled_init(void)
{
    最后要清屏,否则全是雪花
    oled_fill(0x00);
}

这时,蓝牙收到的速度可能会有点异常

bt_send函数中,发送数据函数修改

HAL_UART_Transmit(&uart2_handle, send_buf, strlen((char *)send_buf), 100);

4. 实验结果

oled屏幕显示速度:

蓝牙模块显示速度:

项目10:Wifi控制小车并发送速度

1. 项目需求

通过Wifi模块控制小车前进后退,测速模块测量到的数据传递到上位机中,电脑可查看小车速度。

2. 硬件接线

将蓝牙模块的接线换成ESP8266 Wifi模块,注意VCC一定要接3.3V,否则会烧坏板子

3. 构思环节

  1. 在项目10【测速小车OLED显示并上传蓝牙】基础上做该实验,wifi控制小车并发送速度
  2. 添加esp8266文件夹,并加载;去掉蓝牙模块代码
  3. esp8266内容
    WIFI账号和密码
    TCP_SERVER_IP:电脑上架设的服务器
    服务器通过网络调试助手,选择TCP服务器,本地主机地址通过ipconfig查找

    main.c
c 复制代码
esp8266_init();

蓝牙模块使用空闲中断,而esp8266只用到接收中断

  1. 通过esp8266 wifi模块收发数据
    speed.c
c 复制代码
在更新中断回调函数中
esp8266_send_data(speed_str); // 数据通过esp8266发出去

在哪里接收数据呢?

main.c

c 复制代码
char recv_data[ESP8266_RX_BUF_SIZE]
while(1)
{
   eps8266_receive_data(recvive_data);
   1. 如果发送"M1",前进
   if(strstr(recvive_data, "M1") != NULL)
         motor_go_forward();
     2. 如果发送"M2",后退
   else if(strstr(recvive_data, "M2") != NULL)
        motor_go_backward();
       3. 如果发送"M3",左转
   else if(strstr(recvive_data, "M3") != NULL)
        motor_go_left();
      4. 如果发送"M4",右转
   else if(strstr(recvive_data, "M4") != NULL)
        motor_go_right();
   else
        motor_stop();
delay_ms(10);


}

4. 出现的问题

因为中断这里加了延时导致的发送"M1"后前进,到发送"M2",不能立即执行小车后退。之前的实验是为了消抖,所以加入了延时,在这里不需要。

5. 实验结果

  1. 通过串口打印到串口调试助手;
  2. oled屏幕显示速度
  3. 通过esp8266将数据传递到上位机【网络调试助手】 ,网络调试助手可以发送"M1、M2、M3、M4"控制小车。

项目11: 4G 控制小车

  1. 用花生壳搭建服务器【第146~149课】

    花生壳做内网穿透

  2. 配置4G模块

    使用指令工具配置,填写服务器地址和端口

  3. 4G模块接线

    将esp8266模块替换为4G模块

    VCC------接到USB转TTL上的5V引脚

    GND------GND

  4. 代码直接使用项目9

    修改bt_init(115200), 4G波特率为115200,蓝牙模块波特率为9600。

  5. 实验效果:

    打开网络调试助手和串口调试助手

    网络调试助手发送"M1",小车前进,串口调试助手和oled屏幕显示速度;

    网络调试助手发送"M2",小车后退,串口调试助手和oled屏幕显示速度;

    网络调试助手发送"M3",小车左转,串口调试助手和oled屏幕显示速度;

    网络调试助手发送"M4",小车右转,串口调试助手和oled屏幕显示速度。

⚠️4G模块重点在于配置部分,内网穿透、花生壳配置等。

项目12 :语音控制小车

语音模块:SU-03T

语音模块结合了语音识别和控制技术,使得我们可以通过简单的口令来轻松操控灯光等设备,实现更智能化的生活体验。

1. 语音模块介绍

1.1 型号介绍

SU-03T,是一款低成本、小体积的高性价比离线语音识别模块。

直接语音控制,无需联网,无需手机;

AI智能语音芯片,反应灵敏。

SU-03T板载一个高灵敏度咪头,一个8Ω的喇叭和四个继电器。

可以用于产品原型测试验证功能,DIY自己的语音控制设备,改装各种小家电。

支持自定义开机播报、唤醒词、命令词等。

产品特性:

  • 32bit RISC内核,运行频率240M
  • 支持DSP指令集以及FPU浮点运算单元
  • FFT加速器:最大支持1024点复数FFT/IFFT运算,或者是2048点的实数FFT/IFFT运算
  • 内置高速SRAM,内置2MB FLASH
  • 支持1路驻极体麦
  • 支持 I2S input/output
  • 支持 5V 电源输入
  • 内置 5V 转 3.3V,3.3V 外部负载不超过 150mA
  • RC 12MHz 时钟源和 PLL 锁相环时钟源
  • 内置 POR(Power on Reset),低电压检测和看门狗
  • 所有 GPIO 均可配置为外部中断输入和唤醒源
  • 1个标准 SPI Master 接口,最高速率 30MHz
  • 1个 SPI Slave 接口最高速率 30MHz
  • 1个全双工 UART 最高速率 3Mbps
  • 1个 I2C 主/从控制器最高速率 400kHz
  • 2个 PWM 输出
  • 1个 12-bit SAR-ADC 最大 450Khz 采样率
1.2 工作参数及引脚介绍

工作温度:-20 ~ 85℃

工作电压:3.6V ~ 5.5V,一般5V供电

供电电流:>200mA

SU-03T 说明
VCC 5V供电
GND 接地
3V3 芯片内部LDO输出3.3V,外部负载不能超过150mA
B8 打印信息引脚,不用可悬空
B7 ADC13 / UART1_TXD / I2C_SCL
B6 ADC12 / UART1_RXD / I2C_SDA
B2 UART1_TXD / I2C_SCL / TIM3_PWM
MIC- 驻极体麦负极
MIC+ 驻极体麦正极
B3 UART1_RXD / I2C_SDA / TIM4_PWM
A27 ADC6 / SPIS_MOSI / SPIM_MOSI / I2S0_DO / DMIC1_CLK / TIM3_PWM
A26 ADC5 / SPIS_CLK / SPIM_CLK / I2S0_BCLK / I2S1_BCLK / DMIC0_CLK
A25 ADC4 / SPIS_MISO / SPIM_MISO / I2S0_LRCLK / I2S1_LRCLK / DMIC_DAT
B0 UART0_TXD / I2C_SCL / TIM3_PWM
B1 UART0_RXD / I2C_SDA / TIM4_PWM
GND 接地
SPK- 喇叭负极
SPK+ 喇叭正极

注意:UART0串口B0、B1引脚是调试器的烧录口,串口烧录使用UART1(B6、B7脚)。

2. 通信示意图

实现目标:有一个三色LED灯,说【打开红灯】,红灯亮;说【关闭红灯】,红灯灭;说【打开绿灯】,绿灯亮;说【关闭绿灯】,绿灯灭;说【反转黄灯】,黄灯状态反转。

3. SU-03T 配置

网站:搜索"智能公元"

  1. 注册 → 登录

  2. 产品管理 → 所有产品 → 创建产品 → 选择SU-03T

  3. 前端信号处理

  4. Pin脚配置

    功能:GPIO A25、A26、A27,默认低电平

    上电记忆:工作过程到断电之前,一直处于高电平,如果勾上上电记忆,下一次上电为高电平

  5. 唤醒词自定义【自己随便添加】

  6. 命令词自定义

    这里的A25、A26、A27,是语音模块的引脚,而不是STM32的引脚

    将这三个引脚接到STM32的某个引脚,

    检测GPIO的状态,如果识别到A27是低电平,其他两个是高电平,即进入到循迹模式;

    其他模式同理。

  7. 右上角的发布版本

    生成一个SDK【大概10~30分钟】,下载并烧录。

  8. 下载固件 → jx_firm.tar.gz压缩包,这是一个镜像,将它烧录到板子上

4. 如何烧录?

烧录工具:

接线图:根据手册,交叉接线

USB转TTL SU-03T语音模块
5V VCC
GND GND
TXD B6
RXD B7

bin文件解压出来,放到随意一个英文目录下,不要中文目录

烧录成功

1. 项目需求

语音输出,循迹模式、避障模式、跟随模式,三种模式的切换。

2. 硬件接线

STM32 电机驱动 OLED 循迹模块 跟随模块 舵机 超声波 SU-03T
PB0 A-1A
PB1 A-1B
PB2 B-1A
PB10 B-1B
PB8 SCL
PB9 SDA
PB13 DO(左)
PB14 DO(右)
PB5 OUT(左)
PB6 OUT(右)
PA6 橙线
PA12 Trig
PA11 Echo
PA0 A25
PA1 A26
PA2 A27

3. 构思环节

  1. 在项目1【让小车动起来】基础上做该项目,语音控制小车
  2. 在BSP文件夹中添加track文件夹【循迹】、follow【跟随】、【避障】sg90和hcsr04文件夹,在前面的项目中找这些文件夹,将HAL库中的定时器加载进来,常规操作,不细说
  3. 主函数中加入各模块的初始化函数【4个】
  4. 将各模块进行模式封装 main.c
c 复制代码
1. 循迹模式:
void track_mode(void)
{
    if(track_left_flag() == TRUE && track_right_flag() == TRUE)
        motor_go_forward();
    else if(track_left_flag() == FALSE && track_right_flag() == TRUE)
        motor_go_left();
    else if(track_left_flag() == TRUE && track_right_flag() == FALSE)
        motor_go_right();
    else if(track_left_flag() == FALSE && track_right_flag() == FALSE)
        motor_stop();
}
2. 跟随模式:
void follow_mode(void)
{
    if(follow_left_flag() == TRUE && follow_right_flag() == TRUE)
        motor_go_forward();
    else if(follow_left_flag() == TRUE && follow_right_flag() == FALSE)
        motor_go_left();
    else if(follow_left_flag() == FALSE && follow_right_flag() == TRUE)
        motor_go_right();
    else if(follow_left_flag() == FALSE && follow_right_flag() == FALSE)
        motor_stop();
}
3. 避障模式:
void avoidance_mode(void)
{
    // 先测量中间数据
    dis_middle = hcsr04_get_length();
    // 如果大于某个距离,就前进
    if(dis_middle > 35)
        motor_go_forward();
    else if(dis_middle < 15)
        motor_go_backward();
    else
    {
        // 1.先停下
        motor_stop();
        // 2. 向左看,并测量左侧距离
        sg90_turn_left();
        delay_ms(500);
        dis_left = hcsr04_get_length();
        // 3. 居中
        sg90_turn_middle();
        delay_ms(500);
        // 4. 向右看,并测量右边距离
        sg90_turn_right();
        delay_ms(500);
        dis_right = hcsr04_get_length();
        // 5. 根据距离判断是左转还是右转
        if(dis_left < dis_right)
            motor_go_right();
        else
            motor_go_left();
        
        delay_ms(200);
        // 停下
        motor_stop();
        // 居中
        sg90_turn_middle();
    }
    delay_ms(100);
}

while(1)
{
   track_mode();
   follow_mode();
   avoidance_mode();
}
  1. 通过语音控制这三种模式
    BSP文件夹中创建一个voice文件夹,增加voice.c和voice.h文件
c 复制代码
void voice_init(void)
{
   1. 初始化3个引脚PA0、PA1、PA2
   2. 输入模式
   3. 无上拉
   4. 高速
   HAL_GPIO_Init(GPIOA, 句柄);
}

voice.h

c 复制代码
// 宏定义
#define TRACK_PIN       HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2)
#define AVIODANCE_PIN   HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)
#define FOLLOW_PIN      HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)

main.c

c 复制代码
voice_init();

while(1)
{
   语音模块有三个引脚,低电平时进入模式
   if(TRACK_PIN == GPIO_PIN_RESET FOLLOW_PIN == GPIO_PIN_SET && AVIODANCE_PIN == GPIO_PIN_SET)
   {
       track_mode();
   }
   else if(TRACK_PIN == GPIO_PIN_SET && FOLLOW_PIN == GPIO_PIN_RESET && AVIODANCE_PIN == GPIO_PIN_SET)
       follow_mode();
  else if(TRACK_PIN == GPIO_PIN_SET && FOLLOW_PIN == GPIO_PIN_SET && AVIODANCE_PIN == GPIO_PIN_RESET)
       avoidance_mode();
}

4. 实验结果

语音输出三种模式,切换到各种模式。

相关推荐
sramdram20 小时前
基于MCU微控制器的冰箱压缩机系统解决方案
单片机·嵌入式硬件·mcu·mcu微控制器
小黄蚁21 小时前
使用状态机实现按键消抖
stm32·单片机
集芯微电科技有限公司21 小时前
16V/5A高效率COT模式同步降压转换器集成高低功率MOSFET
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
longxingiot1 天前
单片机数传终端助力物联网数据稳定采集传输
单片机·嵌入式硬件·物联网
合兴软件@1 天前
芯片适配快讯:ISDT 完成对意法半导体(ST)Stellar MCU 平台的适配
单片机·嵌入式硬件·嵌入式实时数据库
KaifuZeng1 天前
电源面试问题汇总二
单片机·嵌入式硬件·面试
CodeQingqing1 天前
STM32HAL + FreeRTOS:改时基进入HardFault_Handler
stm32·单片机·嵌入式硬件
老k一步步来1 天前
CAN通信知识汇总,软件和硬件部分相关问题。
单片机·嵌入式硬件·人机交互
刘延林.1 天前
esp32 s3+ML307N-DL 4G模组通信链路修复记录
单片机·嵌入式硬件