ToF 测距传感器 VL6180 测量范围修改(软件 I2C)

TOF 测距传感器 VL6180 传感器修改测量范围  ...... by  矜辰所致

前言

之前写过一篇关于ToF 测距传感器 VL6180 使用的文章:

ToF 测距传感器 VL6180 使用踩坑记(软件 I2C)

之后有粉丝问我如何修改测量距离,当时我只回答让粉丝去找一下寄存器,最近找了点时间自己来测试了一下,发现其实直接找手册好像不那么容易解决问题,于是自己还是想着得写一篇文章来说明一下,所以本文的内容就是如何修改 VL6180 的测量距离。

我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!

目录

  • 前言
  • 一、 参考资料
  • 二、代码移植说明
  • 结语

一、 参考资料

在官方手册中,我们可以查到, 对于 VL6180 的测量范围说明如下:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第1张图片

默认情况下,缩放因子为1 ,测距的范围最大是 20cm ,我们想要测量更大需要进行设置 。

但是对于如何修改,其实从官方文档中我是没有找到很直接的答案,这里我还是在网上借鉴的大佬的文章:

添加链基于STM32CUBEMX驱动TOF模块VL6180与VL6180X(2)----修改测量范围描述

根据文章的指引,我也在官方的 SDK 包中找到了官方提供的修改测量范围的函数:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第2张图片

在本文中,我们也只需要根据根据大佬的文章和官方的API 来移植即可。

我自己测试起来,也遇到了一些小疑问,但是后来还是成功实现修改距离的,下面我来一一说明。

二、代码移植说明

我们移植的只有一个函数,就是 int VL6180_UpscaleSetScaling(VL6180Dev_t dev, uint8_t scaling)这个函数,在大佬的文章中,也说到了,官方的函数相对 “ 复杂 ”,在文章中大佬也给出了简化后的代码。

首先,我们我们根据文章中的指示,该定义的定于,该写的写:

uint8 scaling;
uint16 ScalerValues[] = {0, 253, 127, 84};

void VL6180x_UpscaleSetScaling(uint8 new_scaling)
{
	uint8 DefaultCrosstalkValidHeight = 20; // default value of SYSRANGE__CROSSTALK_VALID_HEIGHT
	// do nothing if scaling value is invalid
	if (new_scaling < 1 || new_scaling > 3) return;

	scaling = new_scaling;

	VL6180X_WriteByte_16Bit(RANGE_SCALER,ScalerValues[scaling]);

对于博主来说,产品上只会有一个 VL6180 探头,所以在代码中的函数,并没有 add 地址这个参数,因为对我来说,地址是固定的,直接写在了代码中。如果大家测试可能 I2C 上带多个传感器,是可能出现不同地址,需要多一个参数的。

所以在我给出的示例代码中,都没有add 这个参数,大家可以从我下面的代码中也能看出来,我在写数据的函数中,写的是固定地址。

到这里有一个VL6180X_WriteByte_16Bit,这个地方我们需要修改一下,因为在我原本的应用中并没有写 16bit 的函数,

官方的说明都是针对硬件 I2C ,我们需要使用的是软件 I2C ,所以我们自己还得写一下这个函数。 这里也很简单,直接上一下函数比较图,大家根据自己的writeByte 函数修改即可:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第3张图片

当然,在函数中的一些宏定义,我们可以直接从官方的 SDK 包中照样复制到自己的代码中,如下图:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第4张图片

然后接着往下写,有一个关键的语句:

...
VL6180X_WriteByte(add,SYSRANGE_PART_TO_PART_RANGE_OFFSET,ptp_offset / scaling);
...

这里有一个ptp_offset ,在推荐的文章中,其实也说得不是很清楚,我们无法追溯它是怎么来的,那么我们还是得去官方 API 对应的地方查看,我们找到写SYSRANGE_PART_TO_PART_RANGE_OFFSET 这个寄存器地址的地方,看一下官方是怎么处理的:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第5张图片

从上面我们可以看到,我们要实现的只是往SYSRANGE_PART_TO_PART_RANGE_OFFSET这个地址写入一个值,这个值 = 某一个数值 / 我们设置的 scaling 参数。 这个值是通过 VL6180DevDataGet 得到的,那么这个 VL6180DevDataGet 是什么东西,我们直接查找,如下图:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第6张图片

所以这么一分析,就是这样的:

Offset = VL6180DevDataGet(dev, Part2PartOffsetNVM) / scaling;
等于
Offset = SingleVL6180DevData.Part2PartOffsetNVM / scaling;

所以我们要确定的就是 SingleVL6180DevData.Part2PartOffsetNVM 这个等于多少,我们在 vl6180_api.c
中搜索 Part2PartOffsetNVM 这个值,我们可以找到设置这个值的地方,下图中也有对应的分析:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第7张图片

上面代码对 Part2PartOffsetNVM 赋值的地方在 VL6180_InitData 函数中,使用了 VL6180DevDataSet 宏定义, 和 Get 一样:

VL6180DevDataSet(dev, Part2PartOffsetNVM, offset);
等于
SingleVL6180DevData.Part2PartOffsetNVM = offset;

分析到这里,我们就知道了在 官方 API 中,在初始化的时候先读取SYSRANGE_PART_TO_PART_RANGE_OFFSET 的值,保存在 Part2PartOffsetNVM 这个结构体成员中。

在我们自己的代码中,并不需要那个复杂的结构体,我直接简单的处理:

ToF 测距传感器 VL6180 测量范围修改(软件 I2C)_第8张图片

好了,解决完了这条语句,后面几条语句直接按照大佬文章来就行了。

这里直接上一下我修改的代码主要部分:

#include "vl6180.h"

uint8 u8Ack;
uint8 scaling;
uint16 ScalerValues[] = {0, 253, 127, 84};
uint8  Part2PartOffsetNVM; 


uint8 VL6180X_WriteByte(uint16 reg,uint8 data1)
{
/*
防止内容太多省略
*/
}
uint8 VL6180X_WriteByte_16Bit(uint16 reg,uint16 data1)
{
/*
防止内容太多省略
*/
}
uint8 VL6180X_ReadByte(uint16 reg)
{
/*
防止内容太多省略
*/
}

void VL6180x_UpscaleSetScaling(uint8 new_scaling)
{
	uint8 DefaultCrosstalkValidHeight = 20; // default value of SYSRANGE__CROSSTALK_VALID_HEIGHT
	// do nothing if scaling value is invalid
	if (new_scaling < 1 || new_scaling > 3) return;

	scaling = new_scaling;

	VL6180X_WriteByte_16Bit(RANGE_SCALER,ScalerValues[scaling]);

	VL6180X_WriteByte(SYSRANGE_PART_TO_PART_RANGE_OFFSET,Part2PartOffsetNVM / scaling);

	VL6180X_WriteByte(SYSRANGE_CROSSTALK_VALID_HEIGHT, DefaultCrosstalkValidHeight / scaling);

	VL6180X_ReadByte(SYSRANGE_RANGE_CHECK_ENABLES);
	
	VL6180X_WriteByte(SYSRANGE_CROSSTALK_VALID_HEIGHT, DefaultCrosstalkValidHeight / scaling);
}

uint8 VL6180X_Read_ID(void)
{
	return VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODEL_ID);
}

uint8 VL6180X_Init(void)
{
	if(VL6180X_Read_ID() == VL6180X_DEFAULT_ID)
	{
		/*
		防止内容太多省略
		*/
		while(VL6180X_WriteByte(0x003e, 0x31));      //????	ALS??
									// to 500ms		
		while(VL6180X_WriteByte(0x0014, 0x24));       // Configures interrupt on 'New Sample
									// Ready threshold event'
//		VL6180X_WriteByte(VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00);
		Part2PartOffsetNVM = VL6180X_ReadByte(SYSRANGE_PART_TO_PART_RANGE_OFFSET);
		VL6180x_UpscaleSetScaling(3);
		return 0;
	}
	else return 1;
}

/*
VL6180X_Read_Range 不用变,但是值得注意的是,上面VL6180x_UpscaleSetScaling(3)
得到的距离的实际值是 下面返回的 range  的值 * 3。
*/
uint8 VL6180X_Read_Range(void)
{
	uint8 range = 0;
	uint16 count = 0;

	while(!(VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_STATUS)&0x01));   //发送 0 和 01001101   读到的是1   STM32读到的是2

	while(VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START,0x01));	//??????	00011000	  正常,while(0);
	//???????????(New Sample Ready threshold event)
	while(!(VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO)&0x04))	//01001111	读到的是0
	{
		count++;
		if(count >= 100){
			count = 0;
			VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR,0x07);
			VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START,0x01);
		}	
	}

	range = VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_VAL);

	while(VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR,0x07));	//0111b ?????????
	return range;
}

至于 .h 文件,都是宏定义和 函数声明:

#ifndef _VL6180_H_
#define _VL6180_H_

#include "EO3000I_API.h"
#include "EO3000I_CFG.h"
#include 
#include "i2c.h"

#define	VL6180X_DEFAULT_ID						0xB4
//#define I2C_DEBUG
#define VL6180X_DEFAULT_I2C_ADDR 				0x29  ///< The fixed I2C addres
/*------------------VL6180X内部寄存器------------------*/
///! Device model identification number
#define VL6180X_REG_IDENTIFICATION_MODEL_ID    0x000
///! Interrupt configuration
#define VL6180X_REG_SYSTEM_INTERRUPT_CONFIG    0x014
///! Interrupt clear bits
#define VL6180X_REG_SYSTEM_INTERRUPT_CLEAR     0x015
///! Fresh out of reset bit
#define VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET  0x016
///! Trigger Ranging
#define VL6180X_REG_SYSRANGE_START             0x018
///! Trigger Lux Reading
#define VL6180X_REG_SYSALS_START               0x038
///! Lux reading gain
#define VL6180X_REG_SYSALS_ANALOGUE_GAIN       0x03F
///! Integration period for ALS mode, high byte
#define VL6180X_REG_SYSALS_INTEGRATION_PERIOD_HI  0x040
///! Integration period for ALS mode, low byte
#define VL6180X_REG_SYSALS_INTEGRATION_PERIOD_LO  0x041
///! Specific error codes
#define VL6180X_REG_RESULT_RANGE_STATUS        0x04d
///! Interrupt status
#define VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO       0x04f
///! Light reading value
#define VL6180X_REG_RESULT_ALS_VAL             0x050
///! Ranging reading value
#define VL6180X_REG_RESULT_RANGE_VAL           0x062

#define RANGE_SCALER                            0x096

#define SYSRANGE_CROSSTALK_VALID_HEIGHT       0x021
#define SYSRANGE_EARLY_CONVERGENCE_ESTIMATE   0x022
#define SYSRANGE_PART_TO_PART_RANGE_OFFSET    0x024

#define SYSRANGE_RANGE_CHECK_ENABLES          0x02D

#define VL6180X_ALS_GAIN_1         0x06  ///< 1x gain
#define VL6180X_ALS_GAIN_1_25      0x05  ///< 1.25x gain
#define VL6180X_ALS_GAIN_1_67      0x04  ///< 1.67x gain
#define VL6180X_ALS_GAIN_2_5       0x03  ///< 2.5x gain
#define VL6180X_ALS_GAIN_5         0x02  ///< 5x gain
#define VL6180X_ALS_GAIN_10        0x01  ///< 10x gain
#define VL6180X_ALS_GAIN_20        0x00  ///< 20x gain
#define VL6180X_ALS_GAIN_40        0x07  ///< 40x gain

#define VL6180X_ERROR_NONE         0   ///< Success!
#define VL6180X_ERROR_SYSERR_1     1   ///< System error
#define VL6180X_ERROR_SYSERR_5     5   ///< Sysem error
#define VL6180X_ERROR_ECEFAIL      6   ///< Early convergence estimate fail
#define VL6180X_ERROR_NOCONVERGE   7   ///< No target detected
#define VL6180X_ERROR_RANGEIGNORE  8   ///< Ignore threshold check failed
#define VL6180X_ERROR_SNR          11  ///< Ambient conditions too high
#define VL6180X_ERROR_RAWUFLOW     12  ///< Raw range algo underflow
#define VL6180X_ERROR_RAWOFLOW     13  ///< Raw range algo overflow
#define VL6180X_ERROR_RANGEUFLOW   14  ///< Raw range algo underflow
#define VL6180X_ERROR_RANGEOFLOW   15  ///< Raw range algo overflow


uint8 VL6180X_WriteByte(uint16 reg,uint8 data1);
uint8 VL6180X_Read_ID(void);
uint8 VL6180X_Init(void);
uint8 VL6180X_Read_Range(void);
uint8 VL6180X_ReadByte(uint16 reg);

#endif 

在上面代码中使用过程中有一点需要说明一下, 读取函数 VL6180X_Read_Range 不用变,但是值得注意的是,因为我们设置了 VL6180x_UpscaleSetScaling(3) ,所以得到的距离实际值是 VL6180X_Read_Range 函数的返回值 * 3。

结语

到这里大家应该都知道如何修改 VL6180 传感器的测量范围,本文还是比较简单的。

好了,本文就到这里,谢谢大家!

你可能感兴趣的:(方案记录,VL6180,I2C,TOF传感器,测距传感器)