由于疫情的原因,红外测温枪大火,与之相应的传感器我目前了解的有MLX90632和MLX90614以及BM43THD80A,因为90632封装体积小,方便嵌入,所以采用这款传感器来采集温度。一下是调试过程。
废话不多说,官方的Demo源码直接去github就可以搜找到。拿到Demo例程过后,mlx90632_depends.h 文件中主要有3个函数需要我们完善。
附上我的代码
int32_t mlx90632_i2c_write(int16_t register_address, uint16_t value)
{
IIC_Start();
Write_IIC_Byte(MLX90632_DEVICE_ADDR_W);
IIC_Wait_Ack();
Write_IIC_Byte(register_address >> 8);
IIC_Wait_Ack();
Write_IIC_Byte(register_address & 0xff);
IIC_Wait_Ack();
Write_IIC_Byte(value >> 8);
IIC_Wait_Ack();
Write_IIC_Byte(value & 0xff);
IIC_Wait_Ack();
IIC_Stop();
return 0;
}
int32_t mlx90632_i2c_read(int16_t register_address, uint16_t *value)
{
uint8 Val[2];
IIC_Start();
Write_IIC_Byte(MLX90632_DEVICE_ADDR_W);
IIC_Wait_Ack();
Write_IIC_Byte(register_address >> 8);
IIC_Wait_Ack();
Write_IIC_Byte(register_address & 0xff);
IIC_Wait_Ack();
IIC_Start();
Write_IIC_Byte(MLX90632_DEVICE_ADDR_R);
IIC_Wait_Ack();
Val[0] = Read_IIC_Byte(1);
Val[1] = Read_IIC_Byte(0);
IIC_Stop();
*value = (Val[0] << 8) | Val[1];
return 0;
}
void usleep(int min_range, int max_range)
{
delay_ue(10500); //10.5ms
}
完成这个三个函数过后移植就已经完成了一大半,由于我使用的模拟IIC,所以在初始化函数还需要初始化引脚如下:
int32_t mlx90632_init(void)
{
int32_t ret;
uint16_t eeprom_version, reg_status;
gpio_init_output(IIC_CLK, GPIO_PULL_UP, 1);
gpio_init_output(IIC_SDA, GPIO_PULL_UP, 1);
ret = mlx90632_i2c_write(MLX90632_REG_CTRL, 0x0002); //sleeping step mode
if (ret < 0)
{
return ret;
}
ret = mlx90632_i2c_read(MLX90632_EE_VERSION, &eeprom_version);
if (ret < 0)
{
return ret;
}
if ((eeprom_version & 0x00FF) != MLX90632_DSPv5)
{
// this here can fail because of big/little endian of cpu/i2c
return -EPROTONOSUPPORT;
}
ret = mlx90632_i2c_read(MLX90632_REG_STATUS, ®_status);
if (ret < 0)
return ret;
// Prepare a clean start with setting NEW_DATA to 0
ret = mlx90632_i2c_write(MLX90632_REG_STATUS, reg_status & ~(MLX90632_STAT_DATA_RDY));
if (ret < 0)
return ret;
/* Read sensor EEPROM registers needed for calcualtions */
mlx90632_read_eeprom(&P_R, &P_G, &P_O, &P_T, &Ea, &Eb, &Fa, &Fb, &Ga, &Gb, &Ha, &Hb, &Ka);
return 0;
}
这里有个要注意的地方。 mlx90632_read_eeprom(&P_R, &P_G, &P_O, &P_T, &Ea, &Eb, &Fa, &Fb, &Ga, &Gb, &Ha, &Hb, &Ka); 这个函数是读取官方出厂存储在EEPROM中的校准数据,我直接读取出来使用,经过调试发现读取的温度始终偏低,拿自己额头做实验大约在2cm,测到数据不到34度?不知道是不是还需要我们补偿,官方给的datasheet中也没有对P_R,P_G,P_O等校准参数的说明。下面附上读取代码,看是否有知情人士能够解答。
float Get_MXL90632_Vlaue(void)
{
static int16_t ambient_new_raw;
static int16_t ambient_old_raw;
static int16_t object_new_raw;
static int16_t object_old_raw;
double pre_ambient;
double pre_object;
double ambient; /**< Ambient temperature in degrees Celsius */
double object; /**< Object temperature in degrees Celsius */
int32_t ret = 0; /**< Variable will store return values */
uint8 buf[16];
// int32_t P_T = 0;
// int32_t P_R = 6095107;
// int32_t P_G = 85785317;
// int32_t P_O = 6400;
// int16_t Gb = 9728;
// int16_t Ka = 10752;
// int32_t Ea = 5361582;
// int32_t Eb = 6095107;
// int32_t Ga = 0xFDFFA7A5;
// int32_t Fa = 55599953;
// int32_t Fb = 0xFE2571F1;
// int16_t Ha = 16384;
// int16_t Hb = 0;
/* Now we read current ambient and object temperature */
ret = mlx90632_read_temp_raw(&ambient_new_raw, &ambient_old_raw,
&object_new_raw, &object_old_raw);
if(ret < 0)
/* Something went wrong - abort */
return ret;
/* Get preprocessed temperatures needed for object temperature calculation */
pre_ambient = mlx90632_preprocess_temp_ambient(ambient_new_raw,
ambient_old_raw, Gb);
pre_object = mlx90632_preprocess_temp_object(object_new_raw, object_old_raw,
ambient_new_raw, ambient_old_raw, Ka);
/* Set emissivity = 1 */
mlx90632_set_emissivity(1.0);
ambient = mlx90632_calc_temp_ambient(ambient_new_raw, ambient_old_raw, P_T, P_R, P_G, P_O, Gb);
/* Calculate object temperature */
object = mlx90632_calc_temp_object(pre_object, pre_ambient, Ea, Eb, Ga, Fa, Fb, Ha, Hb);
//Uart DEBUG
//sprintf((char*)buf, "%.2f %.2f\r\n", ambient, object);
//STTM_sendToUart(buf, strlen((char*)buf));
return object;
}