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

   

实在没有办法每时每刻看邮箱,就算看了还要逐个回复很麻烦,而且这篇博客其实是求助类的,想要继续完善的,但是拿到代码的网友基本都没有回复我给我一些建议和改进的办法。我做了一个百度云的链接,大家不用留言了,直接去百度云下载。以后公司断外网了,基本没有机会上传资源了。还是希望有积分的可以积分下载。

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

   博客分析:https://blog.csdn.net/tiramisu_L/article/details/89502121                                                                                           

   工程链接:https://download.csdn.net/download/tiramisu_l/11142368

       说回我们本次的4m激光测距,为什么题目说是待修改呢?因为我还有一些没有完成的 ,我觉得是比较关键的部分,就是我没有校准。一校准就会出错。而且目前只能测到3m。再远的距离测到的距离就不准。我个人觉得是校准的问题。因为实在没有办法了,这个芯片资料太少了,我把能逛的论坛都逛了,能发的帖子都发了,但是依旧没有能找到解决方法,所以提前放上来,一个是给需要的网友做个参考,另外是希望有网友看到了,有什么高见的话可以联系我,我再继续完善。

       在开始之前我想说一个事。我在某论坛发帖求助,希望有网友可以提供一份参考代码给我。回帖的人寥寥可数,有一位网友表示愿意有偿提供 。我表示理解的,因为大家辛辛苦苦的做出来的成果凭什么要免费给我。但是他最后要我300块我就有点无法接受了。我还是一个学生,做这个也只是在学习的。但是我没有怼他什么的,我也很礼貌说了句谢谢。说真的我可以理解这种做法,知识是无价的,就好像是商业上,用了别人的专利要给专利费一样。但是我觉得像我们这些小东西,不会涉及到什么商业机密,纯属是学习上的东西,我个人的看法是能免费分享就免费分享。这件事给我两个感悟,第一,求助很多时候是很无助的,就像我在很多个论坛上发帖一样,最后能回复真的很少,所以还是要尽量深耕自己的技术,提升自己。第二,我一定要坚持做免费分享,只要不是涉及到商业利益的,我可以分享的我都会无偿分享。最后感谢正点原子论坛上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应该就可以了。

最后,这份代码还没有之前vl53l0x的代码完善,肯定会有很多错误,各位在测试过程发现问题一定要跟我联系,大家一起进步。这份代码我也会上传到csdn下载。还是那句话,有积分的可以下载,没积分的,评论区留言留下你的邮箱,看到评论之后我会在24小时内发送代码。csdn的下载链接我晚点贴上来。

2019年6月1号于广州。

补充:vl53l1x测距代码下载链接:https://download.csdn.net/download/tiramisu_l/11221225

百度云链接

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

你可能感兴趣的:(stm32)