前言
tmf8801是一个飞行时间(ToF)激光测距传感器,通过测量光波的脉冲差测量距离。能够在±5%范围内进行高精度距离测量,并且能够在黑暗环境和有阳光的情况下运行。
对tmf8801校准可以有效减小由于光学结构、电气干扰、环境光干扰带来的误差,保证芯片测量结果的一致性。官网提供了一套校准的驱动代码,下面结合驱动代码描述tmf8801的校准过程。
一、校准环境
处于室内暗环境光条件下,并且tmf8801前方40-50cm内不能有障碍物。
二、执行步骤
1.停止APP0
执行校准之前一定要先调用tmf8801_app0_stop停止测距,保证tmf8801处于空闲状态。
2.执行校准
调用函数 tmf8801_factory_calibration 启动校准过程,函数如下所示:
int8_t tmf8801_factory_calibration (void)
{
uint8_t cali_ok = 0;
uint8_t regval = 0;
uint32_t tick = 0;
uint8_t i = 0;
my_iic_read(TMF8x01_REGADDR_ENABLE, ®val, 1);
if (regval != 0x41) { /* 传感器忙 */
return TMF8x01_ENOTREADY;
}
regval = 0x0A;
my_iic_write (TMF8x01_REGADDR_COMMAND, ®val, 1); /* 执行工厂校准命令 */
tick = my_tick_get();
while (1) { /* 等待校准数据生成完毕 */
my_iic_read(0x1E, ®val, 1);
if (regval == 0x0A) {
break;
}
if (my_tick_over(tick, 10000)) {
PRINTF("tmf8801_factory_calibration tmo!\r\n");
return TMF8x01_NK;
}
}
/* 读取14字节的校验数据 */
if (my_iic_read(0x20, g_cali_buf, 14) == TMF8x01_NK) {
return TMF8x01_NK;
}
cali_ok = 0xAA; /* 标志已经执行过工厂校准 */
/* 备份工厂校准数据 */
if (eepromRead(0, g_sys_para, SYSPARA_BUF_LEN) != EE_SUCCESS) {
return TMF8x01_NK;
}
for (i = 0; i < 14; i++) {
g_sys_para[i] = g_cali_buf[i];
}
g_sys_para[CALI_STA_ADDR] = cali_ok;
if (eepromWriteNByte(0, g_sys_para, SYSPARA_BUF_LEN) != EE_SUCCESS) {
return TMF8x01_NK;
}
PRINTF("工厂校准数据: ");
for (i = 0; i < 14; i++) {
printf("0x%02x, ", g_cali_buf[i]);
}
PRINTF("\r\n");
return TMF8x01_OK;
}
函数里面主要完成了三件事情:
(1) 在 TMF8801 空闲状态下,MCU 通过 I 2C 往 TMF8801 的 10 寄存器写 0A,在 TMF8801 接收的该命令后,会自动触发校准过程;
(2) 在 TMF8801 自动校准完成后,会往 1E 寄存器写 0A,以指示 14 个校准数据已经 生成完毕!MCU 通过轮询 1E 寄存器,等待 TMF8x01 的校准数据生成完毕;
(3) 实际上完成上面两步后,TMF8x01 的校准过程就算完成了,接下来 在 TMF8801
每次运行测距算法都会把刚得到的校准数据考虑进去。但是这些校准数据被保存在
TMF8x01 的 RAM 中,也就是说下次掉电后,这些数据会丢失!为了避免每次上 电都重复执行上面一、二步,这一步做的是 MCU 从 在 TMF8801读出这 14 个字节的 校准数据,然后保存在 Flash 中,以后每次上电只需要从 Flash 中读取现成的校准 数据提供给在 TMF8801即可。
3.启动APP0
校准完成后,调用函数 tmf8x01_app0_start 启动测距算法,在该函数内部实现了将 Flash
中的校准数据提供给 TMF8801。
/* 配置 APP0 相关参数 */
cmd_buf[0] = p_config->calibration_state_mask;
cmd_buf[2] = p_config->gpio_control;
cmd_buf[3] = p_config->gpio_output_control;
cmd_buf[5] = p_config->repetition_period_ms;
cmd_buf[6] = p_config->iterations & 0xFF;
cmd_buf[7] = (p_config->iterations >> 8) & 0xFF;
/* 预装载工厂校准数据或算法状态数据 */
if (cmd_buf[0] & FACTORY_CALIBRATION_PROVIDE) { /* 提供了工厂校准数据 */
/* 读取工厂校准数据 */
if (eepromRead(CALI_STA_ADDR, &cali_ok, 1) != EE_SUCCESS) {
return TMF8x01_NK;
}
if (cali_ok == 0xAA) { /* 执行过工厂校准 */
if (eepromRead(CALI_DATA_ADDR, g_cali_buf, 14) != EE_SUCCESS) {
return TMF8x01_NK;
}
}
/* 写入 14 字节校准数据 */
if (my_iic_write(0x20, g_cali_buf, 14) == TMF8x01_NK) {
return TMF8x01_NK;
}
if (cmd_buf[0] & ALGORITHM_STATE_PROVIDE) { /* 提供了算法状态数据 */
/* 写入 11 字节算法状态数据 */
if (my_iic_write(0x2E, g_state_buf, 11) == TMF8x01_NK) {
return TMF8x01_NK;
}
}
} else if (cmd_buf[0] & ALGORITHM_STATE_PROVIDE) { /* 提供了算法状态数据 */
/* 写入 11 字节算法状态数据 */
if (my_iic_write(0x20, g_state_buf, 11) == TMF8x01_NK) {
return TMF8x01_NK;
}
}
/* 配置 TOF 功能并启动 */
if (my_iic_write(0x08, cmd_buf, 9) == -1) {
return TMF8x01_NK;
}
总结
经过以上操作之后,能够有效保证芯片测量结果的一致性。TMF8801 内部算法是按照 5MHz 的晶振频率进行计算的,但实际上 TMF8801 内部晶振 频率有偏差,并不是准确的 5MHz,这就会给距离测量带来差。因此为了使测量结果更准确, 频偏的校准,下一章节发布。