【STM32实战项目】基于STM32的双路激光测距系统

🎀 文章作者:二土电子

🌸 关注公众号获取PCB与原理图!

🐸 期待大家一起学习交流!


文章封面

一、项目简介

本项目基于STM32设计了一个双路激光测距系统,能够实现双路测距、测量结果显示、按键控制测量开关、超阈值声光报警功能,并且能够通过串口输出测量结果帧,方便上位机处理并进行后续操作。

🔧软件工具:Keil5

二、硬件选型

  • 主控:STM32F103C8T6核心板
  • 显示模块:OLED
  • VL53L0X 激光测距模块
  • 有源低电平触发蜂鸣器
  • 按键、LED

三、硬件简介

这里主要是介绍之前没有出现过的VL53L0X 激光测距传感器

激光测距传感器
VL53L0X 是一款基于飞行时间 (Time of Flight, ToF) 技术的激光测距传感器,能够精确测量目标物体的距离。该模块具有高精度、低功耗以及快速响应的特点。

VL53L0X 使用脉冲激光发射器向被测对象发送短促而强烈的光脉冲,并通过内置接收器捕捉返回来的散射光信号。利用这些数据计算出发射与接收之间的时间差 Δt ,再乘以光速 c 并除以两倍得到实际距离 d=Δtc/2 。为了提高准确性,设备内部还进行了复杂的算法处理来消除环境干扰等因素的影响。

VL53L0X 通过IIC总线与MCU通信实现数据交互,默认地址为0x52。本设计使用两路激光测距,如果两个VL53L0X 共用一个IIC总线会涉及到地址冲突问题,因为本设计IO资源比较充足,所以博主选择使用两路模拟IIC实现两个VL53L0X 的通信,从而实现两路激光测距,而不需要考虑地址冲突问题。

四、程序设计

4.1 IIC程序设计

像上面所说的,我们使用两路模拟IIC来实现两个VL53L0X 的通信,所以在设计IIC程序时需要分两种情况,这里以II起始信号函数设计为例来解释一下具体设计思路

uint8_t i2c_start(void)
{
    if (VL53L0X_Index == 1)
		{
			I2C_SDA_HIGH();
			I2C_SCL_HIGH();
			i2c_delay();
			//i2c_delay();
			if(!I2C_SDA_STATE)
					return 1;
			I2C_SDA_LOW();
			i2c_delay();
			if(I2C_SDA_STATE)
					return 1;
			I2C_SCL_LOW();
			i2c_delay();
		}
		else if (VL53L0X_Index == 2)
		{
			I2C_SDA_HIGH2();
			I2C_SCL_HIGH2();
			i2c_delay();
			//i2c_delay();
			if(!I2C_SDA_STATE2)
					return 1;
			I2C_SDA_LOW2();
			i2c_delay();
			if(I2C_SDA_STATE2)
					return 1;
			I2C_SCL_LOW2();
			i2c_delay();
		}
    return 0;
}

其中的VL53L0X_Index是用来控制选择的是第几路VL53L0X传感器,通过修改VL53L0X_Index的值来控制当前使用的是那个IIC总线,其他的IIC程序设计和起始信号的设计思路相同。

4.2 测量业务函数

下面介绍一下整体的业务函数设计,老规矩,先贴代码。

void App_Measure_Task (void)
{
	u8 keyValue = 0;
	u8 string[5];
	u16 distance1 = 0;
	u16 distance2 = 0;
	u8 mode = 0;
	u8 sendData[6];
	
	VL53L0X_Index = 1;
	vl53l0x_init();
	VL53L0X_Index = 2;
	vl53l0x_init();
	
	while (1)
	{
		keyValue = Med_KeyScan();
		
		if (keyValue == 0xAA)
		{
			Med_Oled_Clear();   // 清屏
			mode = 1;
		}
		else if (keyValue == 0x55)
		{
			Med_Oled_Clear();   // 清屏
			mode = 0;
		}
		
		if (mode == 0)
		{
			Med_Oled_ShowCHinese16x16(30,3,"激光测距");
		}
		else if (mode == 1)
		{
			keyValue = Med_KeyScan();
			
			if (keyValue == 0x55)
			{
				Med_Oled_Clear();   // 清屏
				mode = 0;
			}
			
			// 开启测距
			Med_Oled_ShowCHinese16x16(30,1,"激光测距");
			Med_Oled_ShowCHinese16x16(20,3,"第一路");
			Med_Oled_ShowCHinese16x16(20,5,"第二路");
			
			// 开启双路激光测距
			if (VL53L0X_Index == 1)
			{  
				if(vl53l0x_status == VL53L0X_ERROR_NONE)
				{
					vl53l0x_start_single_test(&vl53l0x_dev, &vl53l0x_data); //输出数据为mm
					distance1 = gDistance;
					gDistance = 0;
					VL53L0X_Index = 2;
				}
			}
			else if (VL53L0X_Index == 2)
			{
				if(vl53l0x_status == VL53L0X_ERROR_NONE)
				{
					vl53l0x_start_single_test(&vl53l0x_dev, &vl53l0x_data); //输出数据为mm
					distance2 = gDistance;
					gDistance = 0;
					VL53L0X_Index = 1;
				}
				// OLED显示测量结果
				sprintf((char*)string,"%dcm  ",distance1);
				Med_Oled_ShowString(70,3,string,16);
				sprintf((char*)string,"%dcm   ",distance2);
				Med_Oled_ShowString(70,5,string,16);
				// 串口输出测量数据
				sendData[0] = 0xD1;
				sendData[1] = (distance1 >> 8) & 0xFF;
				sendData[2] = distance1 & 0xFF;
				sendData[3] = 0xD2;
				sendData[4] = (distance2 >> 8) & 0xFF;
				sendData[5] = distance2 & 0xFF;
				USART1_Send(sendData,6);
				
				// 距离在10cm内报警
				if ((distance1 > 0 && distance2 > 0) && (distance1 <= 10 | distance2 <= 10))
				{
					LED = 1;
					BEEP = 0;
				}
				else
				{
					LED = 0;
					BEEP = 1;
				}
			}
		}
	}
}

我们通过在业务函数中修改VL53L0X_Index的值,实现两路测距之间的切换,使用两个变量distance1distance2来存储测量结果,除了将测量结果显示到OLED上之外还会将测量结果存储到sendData数组中,通过串口1发送出去,方便上位机进行接收处理。

下面简单介绍一下帧格式

D1 Dis1_H Dis1_L D2 Dis2_H Dis2_L

其中D1D2用来指示后面的测量结果是哪一路的测量结果,紧接着后面跟着两字节测量结果。

4.3 OLED显示程序设计

关于OLED显示程序设计就不再做过多的介绍了,大家可以到外设系列查看,或者直接关注公众号,在STM32专栏中找到OLED即可在文末获取源码。

OLED程序

五、问题总结

简单说一下这次设计中遇到的小问题,调试过程中发现即使贴着VL53L0X传感器,测量距离最小只是4cm,也就是说4cm一下没有测量出来,另外VL53L0X的输出结果都是整数值,没有小数值。

TOF200C是一种飞行时间(ToF)激光测距模块,它采用了VL53L0X芯片,可以提供精确的距离测量。下面是使用TOF200C的教程: 1. 硬件准备: - Arduino开发板:可以使用Windows 7/10/11操作系统的电脑。 - USB线:使用USB-B接头连接线,一般UNO板带有这种接头。 - 杜邦线:准备一些一头公一头母的杜邦线。 - TOF200C尾线:购买时会自带一根尾线。 2. 软件准备: - Arduino IDE:参考Arduino官网下载安装教程,安装好Arduino IDE。 3. 硬件接线: 根据硬件接线图将TOF200C模块连接到Arduino开发板上。 4. 使用方法: - 准备:确保已经烧录了最新的固件到开发板上,并连接好TOF200C模块。 - 运行:修改示例代码中的配置部分,将激光瞄头对准测量点后,运行代码,终端将打印出距离信息。 示例代码如下: ``` #include <Wire.h> #include <VL53L0X.h> VL53L0X tof; void setup() { Wire.begin(); tof.init(); tof.setTimeout(500); Serial.begin(9600); Serial.println("TOF200C Distance Measurement"); } void loop() { if (tof.timeoutOccurred()) { Serial.print("Timeout!"); } uint16_t distance = tof.readRangeSingleMillimeters(); if (distance > 2000) { Serial.print("Out of range"); } else { Serial.print(distance); } delay(100); } ``` 这段代码的主要步骤是: - 创建TOF对象并初始化。 - 读取距离,如果读取到的距离大于2000mm,则显示"Out of range",否则显示实际距离。 希望这个教程对您有帮助!\[1\]\[2\] #### 引用[.reference_title] - *1* [【Arduino】TOF250(IIC)基于UNO板的运用](https://blog.csdn.net/HCJ_Application/article/details/124058324)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [【新手基础教程】SP-MOD之 TOF测距的使用](https://blog.csdn.net/xuguoliang757/article/details/119419008)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二土电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值