STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结-3

简介: STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结

STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结-2

https://developer.aliyun.com/article/1507941


4.测速小车

4.1 测速模块

f556279c0405545cdff2567f6876546f_73dbf22a61d64520979435491780d5df.png


  • 用途:广泛用于电机转速检测,脉冲计数,位置限位等。
  • 有遮挡,输出高电平;无遮挡,输出低电平
  • 接线 :VCC 接电源正极3.3-5V
  • GND 接电源负极 DO TTL开关信号输出
  • AO 此模块不起作用

4.2 测试原理和单位换算

  • 轮子走一圈,经过一个周长,C = 2x3.14x半径= 3.14 x 直径(6.5cm)
  • 对应的码盘也转了一圈,码盘有20个格子,每经过一个格子,会遮挡(高电平)和不遮挡(低电平), 那么一个脉冲就是走了 3.14 * 6.5 cm /20 = 1.0205CM
  • 定时器可以设计成一秒,统计脉冲数,一个脉冲就是1cm
  • 假设一秒有80脉冲,那么就是80cm/s
  • 4.3 定时器和中断实现测速开发和调试代码

测试数据通过串口发送到上位机


硬件接线


测速模块:


  • VCC -- 3.3V 不能接5V,否则遮挡一次会触发3次中断
  • OUT -- PB14

cubeMX配置

代码实现:

unsigned int speedCnt;
 
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_14)
        if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)
            speedCnt++;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    printf("speed: %d\r\n", speedCnt);
    speedCnt = 0;
}
 
main函数里:
HAL_TIM_Base_Start_IT(&htim2);


4.4 小车速度显示在OLED屏

OLED模块介绍:STM32 OLED屏幕显示详解

硬件接线

  • SCL -- PB6
  • SDA -- PB7

代码示例:

oled.c

#include "oled.h"
#include "i2c.h"
#include "oledfont.h"
 
void Oled_Write_Cmd(uint8_t dataCmd)
{
  
  HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
                    &dataCmd, 1, 0xff);
}
 
void Oled_Write_Data(uint8_t dataData)
{
  HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
                    &dataData, 1, 0xff);
}
 
void Oled_Init(void){
  Oled_Write_Cmd(0xAE);//--display off
  Oled_Write_Cmd(0x00);//---set low column address
  Oled_Write_Cmd(0x10);//---set high column address
  Oled_Write_Cmd(0x40);//--set start line address  
  Oled_Write_Cmd(0xB0);//--set page address
  Oled_Write_Cmd(0x81); // contract control
  Oled_Write_Cmd(0xFF);//--128   
  Oled_Write_Cmd(0xA1);//set segment remap 
  Oled_Write_Cmd(0xA6);//--normal / reverse
  Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
  Oled_Write_Cmd(0x3F);//--1/32 duty
  Oled_Write_Cmd(0xC8);//Com scan direction
  Oled_Write_Cmd(0xD3);//-set display offset
  Oled_Write_Cmd(0x00);//
  
  Oled_Write_Cmd(0xD5);//set osc division
  Oled_Write_Cmd(0x80);//
  
  Oled_Write_Cmd(0xD8);//set area color mode off
  Oled_Write_Cmd(0x05);//
  
  Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
  Oled_Write_Cmd(0xF1);//
  
  Oled_Write_Cmd(0xDA);//set com pin configuartion
  Oled_Write_Cmd(0x12);//
  
  Oled_Write_Cmd(0xDB);//set Vcomh
  Oled_Write_Cmd(0x30);//
  
  Oled_Write_Cmd(0x8D);//set charge pump enable
  Oled_Write_Cmd(0x14);//
  
  Oled_Write_Cmd(0xAF);//--turn on oled panel   
}
 
void Oled_Screen_Clear(void){
  char i,n;
  Oled_Write_Cmd (0x20);                    //set memory addressing mode
  Oled_Write_Cmd (0x02);                    //page addressing mode
 
  for(i=0;i<8;i++){
    Oled_Write_Cmd(0xb0+i);               
    Oled_Write_Cmd(0x00);                 
    Oled_Write_Cmd(0x10);                 
    for(n=0;n<128;n++)Oled_Write_Data(0x00);      
  } 
}
 
void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
  unsigned int  i;
  Oled_Write_Cmd(0xb0+(row*2-2));                           //page 0
  Oled_Write_Cmd(0x00+(col&0x0f));                          //low
  Oled_Write_Cmd(0x10+(col>>4));                            //high  
  for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
    Oled_Write_Data(F8X16[i]);                            //写数据oledTable1
  }
 
  Oled_Write_Cmd(0xb0+(row*2-1));                           //page 1
  Oled_Write_Cmd(0x00+(col&0x0f));                          //low
  Oled_Write_Cmd(0x10+(col>>4));                            //high
  for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
    Oled_Write_Data(F8X16[i]);                            //写数据oledTable1
  }   
}
 
 
/******************************************************************************/
// 函数名称:Oled_Show_Char 
// 输入参数:oledChar 
// 输出参数:无 
// 函数功能:OLED显示单个字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){
  while(*str!=0){
    Oled_Show_Char(row,col,*str);
    str++;
    col += 8; 
  }   
}

main.c

extern uint8_t buf;
unsigned int speedCnt = 0;
char speedMes[24];  //主程序发送速度数据的字符串缓冲区
 
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == GPIO_PIN_14)
    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)
      speedCnt++;
}
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  printf("speed: %d\r\n", speedCnt);
  sprintf(speedMes,"speed:%2d cm/s",speedCnt);//串口数据的字符串拼装,speed是格子,每个格子1cm
  Oled_Show_Str(2,2,speedMes);
  speedCnt = 0;
}


5.远程控制小车

5.1 蓝牙控制小车
  • 使用蓝牙模块,串口透传
  • 蓝牙模块,又叫做蓝牙串口模块

串口透传技术:


  • 透传即透明传送,是指在数据的传输过程中,通过无线的方式这组数据不发生任何形式的改变,仿 佛传输过程是透明的一样,同时保证传输的质量,原封不动地到了最终接收者手里。
  • 以太网,蓝牙,Zigbee, GPRS 等模块玩法一样,对嵌入式程序员来说,不需要关心通讯模块内部数据 及协议栈工作原理,只要通过串口编程获得数据即可


代码实现:

整合前面串口控制小车代码,接入蓝牙模块

if (!strcmp(UART1_RX_Buffer, "M1"))
{
    goForward();
    HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M2"))
{
    goBack();
    HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M3"))
{
    goLeft();
    HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M4"))
{
    goRight();
    HAL_Delay(10);
}
else
    stop();


5.2 蓝牙控制并测速小车

原理:运用上面讲到的蓝牙模块和测速模块,将两者代码整合


5.3 wifi控制测速小车

5a30951289c62c992f953bc9c2063bb0_2f6bb9ae1cb044efa31f28486acc5781.png


  • Wifi模块-ESP-01s
  • 蓝牙,ESP-01s,Zigbee, NB-Iot等通信模块都是基于AT指令的设计

AT指令介绍:


  • AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。
  • 其对所传输的数据包大小有定义:即对于AT指令的发送,除AT两个字符外,最多可以接收1056个 字符的长度(包括最后的空字符)。
  • 每个AT命令行中只能包含一条AT指令;对于由终端设备主动向PC端报告的URC指示或者response 响应,也要求一行最多有一个,不允许上报的一行中有多条指示或者响应。AT指令以回车作为结 尾,响应或上报以回车换行为结尾。

硬件接线


  • 把esp8266插进串口1

使用方法:

Wifi模块-ESP-01s_esp01s波特率-CSDN博客

5.4 4g控制小车

原理:运用EC03-DNC4G通信模块


模块介绍:


  • 基于串口AT指令的开发方式
  • 有两种工作模式,默认是透传模式,通过其他方式进入AT指令模式
  • 注意插卡不要出错,下图红色位置为SIM卡状态灯,亮才是正常

代码不做修改,直接基于蓝牙小车整合, 4g模块只要做好外网透传就可以了


6.语音控制小车

6.1语音模块配置:

使用SU-03T / LD3320

具体介绍看我之前写过的博客:SU-03T语音模块的使用_罗小白的干爹的博客-CSDN博客

6.2 语音控制小车开发和调试代码

硬件接线:


循迹小车:


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

跟随小车:


  • 跟随模块(左) -- PA8
  • 跟随模块(右) -- PA9

避障小车:


  • sg90:PB9
  • Trig:PA10
  • Echo:PA11

OLED模块:


  • SCL -- PB6
  • SDA -- PB7

语音模块:


  • A25 -- PA15 (跟随)
  • A26 -- PA13 (避障)
  • A27 -- PA14 (循迹)

cubeMX配置  

d711bbcedfedcc00a0be185022bd2e3d_ddc99e48a02341f98e58c8b734470169.png

代码示例:

#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "gpio.h"
 
#include "sg90.h"
#include "sr04.h"
#include "motor.h"
#include "oled.h"
 
#define MIDDLE 0
#define LEFT 1
#define RIGHT 2
 
#define BZ 1
#define XJ 2
#define GS 3
 
#define LeftWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
#define RightWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)
 
#define LeftWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)
#define RightWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9)
 
#define A25 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)
#define A26 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_13)
#define A27 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_14)
 
void SystemClock_Config(void);
 
char dir;
 
void xunjiMode()
{
  if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_RESET)
    goForward();
  if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_RESET)
    goLeft();
  if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_SET)
    goRight();
  if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_SET)
    stop();
}
 
void gensuiMode()
{
  if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_RESET)
    goForward();
  if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_RESET)
    goRight();
  if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_SET)
    goLeft();
  if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_SET)
    stop();
}
 
void bizhangMode()
{
  double disMiddle;
  double disLeft;
  double disRight;
 
  if(dir != MIDDLE){
    sgMiddle();
    dir = MIDDLE;
    HAL_Delay(300);
  }
  disMiddle = get_distance();
  
  if(disMiddle > 35){
    //前进
    goForward();
  }else if(disMiddle < 10){
    goBack();
    
  }else
  {
    //停止
    stop();
    //测左边距离
    sgLeft();
    HAL_Delay(300);
    disLeft = get_distance();
    
    sgMiddle();
    HAL_Delay(300);
    
    sgRight();
    dir = RIGHT;
    HAL_Delay(300);
    disRight = get_distance();
    
    if(disLeft < disRight){
      goRight();
      HAL_Delay(150);
      stop();
    }
    if(disRight < disLeft){
      goLeft();
      HAL_Delay(150);
      stop();
    }
  }
  HAL_Delay(50);
}
 
int main(void)
{
    int mark = 0;
 
    HAL_Init();
 
 
    SystemClock_Config();
 
 
    MX_GPIO_Init();
    MX_TIM4_Init();
    MX_TIM2_Init();
    MX_I2C1_Init();
 
  initSG90();
  HAL_Delay(1000);
  dir = MIDDLE;
  Oled_Init();
  Oled_Screen_Clear();
  Oled_Show_Str(2,2,"-----Ready----");
 
  while (1)
  {
 
    //满足寻迹模式的条件
    if(A25 == 1 && A26 == 1 && A27 == 0){
      if(mark != XJ){
        Oled_Screen_Clear();
        Oled_Show_Str(2,2,"-----XunJi----");
      }
      mark = XJ;
      xunjiMode();
    }
    //满足跟随模式的条件
    if(A25 == 0 && A26 == 1 && A27 == 1){
      if(mark != GS){
        Oled_Screen_Clear();
        Oled_Show_Str(2,2,"-----GenSui----");
      }
      mark = GS;
      gensuiMode();
    }
    //满足避障模式的条件
    if(A25 == 1 && A26 == 0 && A27 == 1){
      if(mark != BZ){
        Oled_Screen_Clear();
        Oled_Show_Str(2,2,"-----BiZhang----");
      }
      mark = BZ;
      bizhangMode();
    }
  }
}
 
 
相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
相关文章
|
5月前
|
传感器 数据采集 监控
基于阿里云MQTT服务,设计一个STM32的智能光伏控制系统
这篇文章详细介绍了利用STM32F103C8T6单片机实现光伏发电系统的关键技术。全文分为四章:第一章阐述了光伏发电的背景、意义及应用场景,强调其在绿色能源领域的重要性。第二章介绍了如何通过STM32F103C8T6及光敏电阻和伺服电机实现光线追踪系统,详细描述了硬件选择、连接及使用HAL库编写的单片机程序。第三章讲解了最大功率点追踪(MPPT)的原理,并展示了如何利用STM32F103C8T6和相关传感器、DC-DC转换器实现MPPT功能。第四章描述了如何通过STM32F103C8T6与SIM7600CE 4G模块连接到阿里云MQTT服务,实现设备状态数据的远程传输和控制。本文提供了全面的硬
17705 5
|
4月前
|
算法
STM32CubeMX PID差速循迹小车
STM32CubeMX PID差速循迹小车
83 1
STM32CubeMX PID差速循迹小车
|
6月前
|
传感器 语音技术
STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结-1
STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结
STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结-1
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
444 2
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
714 0
|
6月前
|
传感器
STM32标准库ADC和DMA知识点总结-1
STM32标准库ADC和DMA知识点总结
|
5月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
509 4
|
5月前
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
690 2
|
5月前
|
存储 数据采集 数据安全/隐私保护
使用STM32F103读取TF卡并模拟U盘:使用标准库实现
通过以上步骤,你可以实现用STM32F103将TF卡内容变成U盘进行读取。这种功能在数据采集、便携式存储设备等应用中非常有用。如果你有更多的需求,可以进一步扩展此项目,例如添加文件管理功能、加密存储等。希望这篇博客能帮到你,如果有任何问题,欢迎在评论区留言讨论!
236 1

热门文章

最新文章

  • 1
    实时语音识别 使用websockt传输二进制数组 onSentenceEnd不返回结果
    30
  • 2
    在人工智能和机器学习的领域中,语音识别(Speech Recognition,SR)是一个重要的研究方向。它旨在将人类的语音转换为计算机可读的文本。
    112
  • 3
    Python基于librosa和人工神经网络实现语音识别分类模型(ANN算法)项目实战
    147
  • 4
    深度学习在语音识别中的进展
    59
  • 5
    语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
    64
  • 6
    语音识别-----列表的常用操作课后练习讲解,用变量追加,取出第一个,取出最后一个,下标位置,列表的循环遍历,下标+1的写法,len下标可以小于这个值,while循环对index循环的遍历
    38
  • 7
    语音识别-免费开源的语音转文本软件Whisper的本地搭建详细教程,python版本是3.805,ffmpeg是专门处理音视频的,ffmpeg的下载链接,现在要求安装python和ffmpeg
    221
  • 8
    语音识别,列表的定义语法,列表[],列表的下标索引,从列表中取出来特定的数据,name[0]就是索引,反向索引,头部是-1,my[1][1],嵌套列表使用, 列表常用操作, 函数一样,需引入
    41
  • 9
    语音识别,函数综合案例,黑马ATM,/t/t一个对不齐,用两个/t,数据容器入门,数据容器可以分为列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
    40
  • 10
    语音识别----函数基础定义联系案例,函数的参数,函数的参数练习案例,函数的返回值定义语法,函数返回值之None,函数的说明文档,函数的嵌套调用,变量在函数中的作用域,内部变量变全局变量用global
    45
  • 下一篇
    无影云桌面