vl53l1x+stm32激光测距分析(待修改)

之前已经做了2m的vl53l0x激光测距,写了一篇博客也分享了自己的工程,这里把链接发一下:                                        

   博客分析:VL53L0X+stm32激光测距_tiramisu_L的博客-CSDN博客_stm32激光测距                                                                                           

   工程链接:VL53L0X+stm32激光测距_激光测距传感器stm32-C代码类资源-CSDN下载

感谢正点原子论坛上ID为“DSG”的网友对我的帮助。我正是在他提供的一份代码上做修改,然后测试出距离的。

 VL53L1X跟VL53L0X的差别就是距离提升了,从2m升级为4m。至于性能这些,我就不管了,我也不多做分析。这个跟vl53l0x的差别还是有点大的。主要是他的测距流程不一样还有就是提供的API接口很多都不一样了。主要看下面的图。

                                                                                                       测距流程图

                                                                                          校准流程图 

I2C已经没什么好说的了,我还是采用之前的vl53l0x的I2C写法,测试过程也没什么问题。但是有一个疑惑的地方,VL53L1X数据手册提供和三个寄存器来测试I2C通信(分别是0x010f,0x0110,0x0111)但是只是可以对这三个寄存器读,没办法写。不确定是不是这三个寄存器只能读不可写。然后就是说的校准出错,上面红色框框选出来的就是我出错的地方。然后I2C的引脚还是SDA->PA2,SCL->PA3,但是XShut->PA4。这里我只要说一下VL53L1X的测距代码。整个代码的风格和流程跟之前的VL53L0X的差不多。

首先是测距的初始化,这部分代码在VL53L1_init()函数里

Status = VL53L1_WaitDeviceBooted(pMyDevice);
    if(Status!=VL53L1_Error_NONE)
	{
		printf("Wait device Boot failed!\r\n");
		return Status;
	}

  delay_ms(2);
  Status = VL53L1_addr_set(pMyDevice, 0x54);//set provious VL53L1X I2C addr
  if(Status!=VL53L1_Error_NONE)
  {
	  printf("set addr failed!\r\n");
	  return Status;
  }

	Status = VL53L1_DataInit(pMyDevice);//device init
	if(Status!=VL53L1_Error_NONE) 
	{
		printf("datainit failed!\r\n");
		return Status;
	}

	delay_ms(2);
//--may be delete
	Status = VL53L1_StaticInit(pMyDevice);
	if(Status!=VL53L1_Error_NONE) 
	{
		printf("static init failed!\r\n");
		return Status;
	}
	 
	Status = VL53L1_SetDistanceMode(pMyDevice, VL53L1_DISTANCEMODE_LONG);	//short,medium,long
	if(Status!=VL53L1_Error_NONE) 
	{
		printf("set discance mode failed!\r\n");
		return Status;
	}
	delay_ms(2);

 VL53L1_WaitDeviceBooted()函数确保设备已启动并准备就绪。

VL53L1_DataInit()和VL53L1_StaticInit()与vl53l0x的作用是一样的就不说了。

VL53L1_SetDistanceMode()设置测距的模式,有三种模式,短距离,中距离和长距离。关于这些宏定义,在代码里面都用定义。

上面的函数在API手册都是用分析的,大家百度可以搜索到这个API手册。上面的初始化还不够,最重要的一个函数是VL53L1_StartMeasurement()必须要有这个函数,芯片才会开始测距。这个函数我放在下面了。

status = VL53L1_PerformRefSpadManagement(dev);//perform ref SPAD management
	if(status!=VL53L1_Error_NONE) 
	{
		printf("refspad failed!\r\n");
		return status;
	}
	delay_ms(2);
	/*status = VL53L1_PerformOffsetSimpleCalibration(dev,140);
	if(status!=VL53L1_Error_NONE) 
	{
		printf("offset calibration failed!\r\n");
		//return status;
	}
	delay_ms(2);
	status = VL53L1_SetXTalkCompensationEnable(dev,1);
	if(status!=VL53L1_Error_NONE) 
	{
		printf("XTalk enable failed!\r\n");
		//return status;
	}
	delay_ms(2);
	status = VL53L1_PerformSingleTargetXTalkCalibration(dev,140);
	if(status!=VL53L1_Error_NONE) 
	{
		printf("XTalk calibration failed!\r\n");
		//return status;
	}*/
    delay_ms(30);
	status = VL53L1_SetLimitCheckEnable(dev,VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE,1);//sigma--standard deviation, enable SIGMA limit check
	if(status!=VL53L1_Error_NONE) 
		return status;
	delay_ms(2);
	status = VL53L1_SetLimitCheckEnable(dev,VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,1);
																																												//-reflected. enable signal rate limit check
	if(status!=VL53L1_Error_NONE) 
		return status;
	delay_ms(2);
	status = VL53L1_SetLimitCheckValue(dev,VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE,Mode_data[mode].sigmaLimit);//set SIGMA limit
	if(status!=VL53L1_Error_NONE) 
		return status;
delay_ms(2);
	status = VL53L1_SetLimitCheckValue(dev,VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,Mode_data[mode].signalLimit);//set signal rate limit
	if(status!=VL53L1_Error_NONE) 
		return status;
status = VL53L1_SetMeasurementTimingBudgetMicroSeconds(dev,Mode_data[mode].timingBudget);
	if(status!=VL53L1_Error_NONE) 
		return status;
	delay_ms(2);
	status = VL53L1_SetInterMeasurementPeriodMilliSeconds(dev, 500);
	if(status!=VL53L1_Error_NONE) 
	{
		printf("SetInterMeasurementPeriodMilliSeconds failed!\r\n");
		return status;
	}
	delay_ms(2);
	status = VL53L1_StartMeasurement(dev);
	if(status!=VL53L1_Error_NONE) 
	{
		printf("start measurement failed!\r\n");
		return status;
	}

注意上面注释的一大段就会测距程序,目前这部分代码会出错,去掉注释完全没办法测距。所以我先把他注释。校准其实是为了让距离更准确的,没有校准虽然可以测距,但是误差可能会比较大。前面的代码跟vl53l0x的基本一致,只要是后面的

VL53L1_SetInterMeasurementPeriodMilliSeconds()这个函数是设置测试的时间间隔的,手册上说好像是最少的间隔是220ms,反正我给500ms已经够了。

然后就是VL53L1_StartMeasurement()。到现在为止就可以测距了。

上面的代码是放在VL53L1_set_mode()函数里面的。主函数先调用VL53L1_init()然后调用VL53L1_set_mode()

说明一下,我刚开始的时候是把VL53L1_StartMeasurement()放在VL53L1_init()里的,但是这样没办法测距,最后才把他放在VL53L1_set_mode()函数里的。下面分析测距函数

VL53L1_Error VL53L1_single_test(VL53L1_Dev_t *dev,VL53L1_RangingMeasurementData_t *pdata)
{
	VL53L1_Error Status = VL53L1_Error_NONE;
	u8 isDataReady = 0;
	
//	Status = VL53L1_poll_for_range_completion(dev, VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
	Status = VL53L1_GetMeasurementDataReady(dev,&isDataReady);
	//Status = VL53L1_WaitMeasurementDataReady(dev);
	if(Status != VL53L1_Error_NONE)
		return Status;
    if(1 == isDataReady)
	{
		Status = VL53L1_GetRangingMeasurementData(dev, pdata);
		Distance = pdata->RangeMilliMeter;
	}
	Status = VL53L1_ClearInterruptAndStartMeasurement(dev);
	return Status;
}

我没有用中断的方式,用的是主机轮循的方式。所以这里要用VL53L1_GetMeasurementDataReady()来等待。中断方式才用VL53L1_WaitMeasurementDataReady()来等待。这是个重点,因为VL53L1_WaitMeasurementDataReady()是会阻塞等待的。VL53L1_GetRangingMeasurementData()是用来测距的,测距完成之后用VL53L1_ClearInterruptAndStartMeasurement()清除中断。

到这里测距就完成了。说明一点,我还是用f103vet6来测试的,同一个系列修改cpu应该就可以了。

2019年6月1号于广州。

补充:vl53l1x测距代码下载链接:STM32_VL53.zip_VL53L1XI2C配置-C代码类资源-CSDN下载

百度云链接

链接:https://pan.baidu.com/s/1sTO7fDVjQXbX3YCAtpy_Mg 提取码:5aik

  • 73
    点赞
  • 243
    收藏
    觉得还不错? 一键收藏
  • 167
    评论
对于VL53L1x TOF激光测距模块,可以使用STM32的I2C总线进行控制和通信。下面是基于HAL库的VL53L1x驱动代码: ```c #include "vl53l1x.h" // 初始化VL53L1x模块 VL53L1_Error VL53L1x_Init(VL53L1_Dev_t *dev) { VL53L1_Error status = VL53L1_ERROR_NONE; uint8_t sensor_state = 0; uint32_t refSpadCount; uint8_t isApertureSpads; uint8_t VhvSettings; uint8_t PhaseCal; uint32_t sequence_config_timeout_us; // 打开I2C总线 HAL_I2C_MspInit(dev->I2cHandle); // 软复位 status = VL53L1_software_reset(dev); if (status != VL53L1_ERROR_NONE) { return status; } // 等待传感器初始化完成 while (sensor_state == 0) { status = VL53L1_RdByte(dev, 0x010F, &sensor_state); if (status != VL53L1_ERROR_NONE) { return status; } } // 设备版本号 uint8_t version[3]; status = VL53L1_GetVersion(dev, version); if (status != VL53L1_ERROR_NONE) { return status; } // 设备参数配置 status = VL53L1_DataInit(dev); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_StaticInit(dev); if (status != VL53L1_ERROR_NONE) { return status; } // 设备校准 status = VL53L1_PerformRefSpadManagement(dev, &refSpadCount, &isApertureSpads); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_PerformRefCalibration(dev, &VhvSettings, &PhaseCal); if (status != VL53L1_ERROR_NONE) { return status; } // 设备配置 status = VL53L1_SetXTalkCompensationEnable(dev, 0); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetOffsetCalibrationDataMicroMeter(dev, 0); if (status != VL53L1_ERROR_NONE) { return status; } // 设备开始测距 status = VL53L1_SetDistanceMode(dev, VL53L1_DISTANCEMODE_LONG); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetMeasurementTimingBudgetMicroSeconds(dev, 50000); if (status != VL53L1_ERROR_NONE) { return status; } sequence_config_timeout_us = (uint32_t)VL53L1_calc_timeout_us(dev, 2000); status = VL53L1_SetSequenceStepTimeout(dev, VL53L1_SEQUENCESTEP_TCC, sequence_config_timeout_us); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetSequenceStepTimeout(dev, VL53L1_SEQUENCESTEP_DSS, sequence_config_timeout_us); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetSequenceStepTimeout(dev, VL53L1_SEQUENCESTEP_MSRC, sequence_config_timeout_us); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetSequenceStepTimeout(dev, VL53L1_SEQUENCESTEP_PRE_RANGE, sequence_config_timeout_us); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetSequenceStepTimeout(dev, VL53L1_SEQUENCESTEP_FINAL_RANGE, sequence_config_timeout_us); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetInterMeasurementPeriodMilliSeconds(dev, 100); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_SetGPIOConfig(dev, 0, VL53L1_GPIOFUNCTIONALITY_NEW_MEASURE_READY, VL53L1_INTERRUPTPOLARITY_LOW); if (status != VL53L1_ERROR_NONE) { return status; } return status; } // 触发一次测量 VL53L1_Error VL53L1x_StartMeasurement(VL53L1_Dev_t *dev) { VL53L1_Error status = VL53L1_ERROR_NONE; uint8_t measurement_mode; uint8_t system_health; uint8_t measurement_device_ready; // 获取测量模式 status = VL53L1_GetMeasurementMode(dev, &measurement_mode); if (status != VL53L1_ERROR_NONE) { return status; } // 如果设备未准备好,则等待 if (measurement_mode == VL53L1_DEVICEREADY_WAIT_FOR_MEASURE_VALID) { status = VL53L1_WaitDeviceBooted(dev); if (status != VL53L1_ERROR_NONE) { return status; } } // 触发测量 status = VL53L1_StartMeasurement(dev); if (status != VL53L1_ERROR_NONE) { return status; } // 等待测量完成 do { status = VL53L1_GetMeasurementDataReady(dev, &measurement_device_ready); if (status != VL53L1_ERROR_NONE) { return status; } status = VL53L1_GetSystemHealth(dev, &system_health); if (status != VL53L1_ERROR_NONE) { return status; } } while ((measurement_device_ready == 0) && (system_health == 0)); return VL53L1_ERROR_NONE; } // 读取测量距离 VL53L1_Error VL53L1x_ReadMeasurement(VL53L1_Dev_t *dev, uint16_t *distance) { VL53L1_Error status = VL53L1_ERROR_NONE; VL53L1_RangingMeasurementData_t ranging_data; // 读取测量数据 status = VL53L1_GetRangingMeasurementData(dev, &ranging_data); if (status != VL53L1_ERROR_NONE) { return status; } // 检查数据是否有效 if (ranging_data.RangeStatus != 0) { return VL53L1_ERROR_RANGE_ERROR; } // 保存测量距离 *distance = ranging_data.RangeMilliMeter; return VL53L1_ERROR_NONE; } ``` 使用时,可以调用VL53L1x_Init()函数初始化设备,然后使用VL53L1x_StartMeasurement()函数触发一次测量,最后使用VL53L1x_ReadMeasurement()函数读取测量距离。需要注意的是,VL53L1x模块的I2C地址为0x29,可以在VL53L1x_Init()函数中进行配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 167
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值