前言
tmf8801是一个飞行时间(ToF)激光测距传感器,通过测量光波的脉冲差测量距离。能够在±5%范围内进行高精度距离测量,并且能够在黑暗环境和有阳光的情况下运行。
图1 tmf8801的技术特点
在tmf881官方技术手册上写明了测量最大距离是2500mm,但是用户在使用官网提供的tmf8801驱动代码实现之后,发现实现的距离最多只能到达2200mm左右。本文章的目标主要描述的是如何让tmf8801能够测量达到2500距离的技术方法。
一、说明
tmf8801 内部算法是按照 5MHz 的晶振频率进行计算的,但实际上 tmf8801内部晶振 频率有偏差,并不是准确的 5MHz,这就会给距离测量带来误差。
在博客《TMF8801的频偏校正》已经进行的解释。有两种方法可获取tmf8801 的频偏因子:第一种方法是主机设置一个固定周期T的定时器,在定时器中断服务函数里获取tmf8801的时间戳,第一次中断获取的时间戳为t1,第二次中断获取到时间戳为t2,则可算出频偏因子为(t2-t1)/T;第二种方法是主机设置一个计数器,在第一次获取tmf8801的距离值的时候,同时获取自身的时间戳 t_host_1 和tmf8801 的时间戳 t_tof_1,第二次获取tmf8801的距离值的时候,再同时获取自身的时间 戳 t_host_2 和 TMF8x01 的 时 间 戳 t_tof_2 , 则可算出频偏因子为 (t_tof_2-t_tof_1)/(t_host_2-t_host_1)。
通过以上方法可以计算得到g_freq_bias_fac参数,我们只需要调节g_freq_bias_fac值,就可以达到要求。
二、使用步骤
在tmf8801的驱动代码包含__tmf8801_app0_osc_trim、__tmf8801_app0_osc_trim_up和__tmf8801_app0_osc_trim_down三个函数,如下所示。
/**
* \brief 调节TOF晶振频率
*/
static int8_t __tmf8801_app0_osc_trim (int32_t change)
{
uint8_t regval = 0;
uint8_t fuse3 = 0;
uint8_t fuse6 = 0;
int32_t trim_val = 0;
uint32_t tick = 0;
regval = 0x29;
if (my_iic_write(0x06, ®val, 1) == -1) {
return TMF8x01_NK;
}
regval = 0x00; /* PON = 0 */
if (my_iic_write(0xE0, ®val, 1) == -1) {
return TMF8x01_NK;
}
tick = my_tick_get();
while (1) { /* 等待进入待机模式 */
if (my_iic_read(0xE0, ®val, 1) == 0) {
if (regval == 0x00) {
break;
}
}
if (my_tick_over(tick, 1000) == true) {
PRINTF("tmf8801_app0_osc_trim tmo!\r\n");
return TMF8x01_NK;
}
}
if (my_iic_read(0x03, &fuse3, 1) == -1) {
return TMF8x01_NK;
}
if (my_iic_read(0x06, &fuse6, 1) == -1) {
return TMF8x01_NK;
}
trim_val = (((int32_t)fuse3) << 1) | ((fuse6 & (0x01 << 6)) >> 6);
trim_val += change;
trim_val &= 0x1FF;
fuse6 &= ~(0x01 << 6);
fuse6 |= ((trim_val & 0x01) << 6);
fuse3 = ((trim_val >> 1) & 0xFF);
if (my_iic_write(0x03, &fuse3, 1) == -1) {
return TMF8x01_NK;
}
if (my_iic_write(0x06, &fuse6, 1) == -1) {
return TMF8x01_NK;
}
regval = 0x01; /* PON = 1 */
if (my_iic_write (0xE0, ®val, 1) == -1) {
return TMF8x01_NK;
}
tick = my_tick_get();
while (1) { /* 等待进入空闲模式 */
if (my_iic_read(0xE0, ®val, 1) == 0) {
if (regval == 0x41) {
break;
}
}
if (my_tick_over(tick, 1000) == true) {
PRINTF("tmf8801_app0_osc_trim tmo!\r\n");
return TMF8x01_NK;
}
}
return TMF8x01_OK;
}
/**
* \brief 调快TOF晶振频率
*/
static int8_t __tmf8801_app0_osc_trim_up (void)
{
int8_t error;
error = tmf8801_app0_stop();
if (error)
return error;
error = __tmf8801_app0_osc_trim(1);
if (error)
return error;
error = tmf8801_app0_start(&g_app_config);
return error;
}
/**
* \brief 调慢TOF晶振频率
*/
static int8_t __tmf8801_app0_osc_trim_down (void)
{
int32_t error;
error = tmf8801_app0_stop();
if (error)
return error;
error = __tmf8801_app0_osc_trim(-1);
if (error)
return error;
error = tmf8801_app0_start(&g_app_config);
return error;
}
我们需要通过这三个函数动态调节g_freq_bias_fac的值。通过验证测试,将频率微调到[0.93,0.95]之间的情况下,tmf8801比较合适,测量距离大概就在2500mm左右。
if (g_freq_bias_fac < 0.93)
{
__tmf8801_app0_osc_trim_up();
}
if (g_freq_bias_fac > 0.95)
{
__tmf8801_app0_osc_trim_down();
}
总结
验证测试g_freq_bias_fac的值在[0.93,0.95]之间的情况下,测量距离和精度都符合技术指标,在调节到其他值,我这里也没有去测试验证,大家可以用此方法验证测试。