MLX90621驱动编写2

MLX90621驱动编写2

  1. 该传感器的讲解第一部分链接为MLX90621驱动编写1
  2. 该器件的温度计算总体分为2部分,Part1为器件本身的温度,用于在计算物体温度时的补偿;Part2为计算测量物体的温度。器件本身温度计算公式以及所需要的寄存器如图1所示:Ta的计算公式及所需要的寄存器
    图1 Ta的计算公式及所需要的寄存器
    计算Ta的代码如下:
/**
**Description : 计算芯片的温度
               :Ta=(-KT1_F+pow((KT1_F*KT1_F-4*KT2_F*(VTH_F-PTAT_data)),0.5))/(2*KT2_F)+25
**Param       : None
**Return Code : None
**/
void Calculation_Ta(void)
{   
	u8 KT1_Scale=0;
    u8 KT2_Scale=0;
    int32_t KT1_V=0;
	int32_t KT2_V=0;
	int32_t VTH_V=0;
	double KT1_F=0;
	double KT2_F=0;
	double VTH_F=0;
	double tempd=0.0f;
	double diff=0;
	int16_t PTAT_Data=0;
	/*************从EEPROM读取数据结束****************/
	PTAT_Data=Frame_Data[64];
	/*************从EEPROM读取数据开始****************/
	KT1_Scale=(EEProm_Data[0XD2]&0XF0)>>4;  //KT1_Scale
	KT2_Scale=(EEProm_Data[0XD2]&0X0F); 
	/*************计算VTH***************/
	VTH_V=256*EEProm_Data[0XDB]+EEProm_Data[0XDA];
	if(VTH_V>32767)
	{
	    VTH_V=VTH_V-65536;
	}
	VTH_F=(double)VTH_V/(double)(pow((double)2,(double)Reso));
    /*************计算KT1***************/
	KT1_V=256*EEProm_Data[0XDD]+EEProm_Data[0XDC];
	if(KT1_V>32767)
	{
	    KT1_V=KT1_V-65536;
	}
	KT1_F=(double)KT1_V/(double)(pow((double)2,(double)(Reso+KT1_Scale)));
	/*************计算KT2***************/
	KT2_V=256*EEProm_Data[0XDF]+EEProm_Data[0XDE];
    if(KT2_V>32767)
	{
	    KT2_V=KT2_V-65536;
	}
	KT2_F=(double)KT2_V/(double)(pow((double)2,(double)(Reso+KT2_Scale+10)));
	/*************计算TA***********/
	diff=VTH_F-(double)PTAT_Data;  //求差
	tempd=KT1_F*KT1_F-4*KT2_F*diff;//计算
	tempd=pow(tempd,0.5);          //开方
	Ta=(tempd-KT1_F)/(2*KT2_F)+25.0f;//得到Ta
#if TEST_EN
	printf("VTH_F:%f\r\n",VTH_F);
	printf("KT1_F:%f\r\n",KT1_F);
	printf("KT2_F:%f\r\n",KT2_F);
	printf("TA:%f\r\n",Ta);
#endif
	
}

第二部分则是计算测量的物体的温度,该部分用到的补偿比较多,需要注意的是变量数据类型的定义,不要在程序计算的过程中溢出。该部门计算的公式如图2所示:
图2 计算物体的温度公式
图2 计算物体的温度公式
敲公式太麻烦了,直接上代码吧

/**
**Description : 计算VIR(i,j)_OffsetCompensated
:VIR_Offset(i,j)=VIR(I,J)-(A(i,j)+B(i,j)*(Ta-TA0))
:A(i,j)=A_common+A_I(i,j)
**Param       : None
**Return Code : None
**/
void Calculation_VIR_Offset(void)
{
    u8 i=0;
	u8 j=0;
	u32 temp2=0;
	u32 temp3=0;
	int32_t sum=0;
	int32_t VIR_i_j=0;                    //不同的i,j对应不同的Framedata数据,存储形式为补码形式
	int32_t A_Common=0;                   //该值是EEPROM中的0XD0和0XD1组成D1为高位,D0为低8位
    int16_t A_i_j_EE=0;                   //不同的i,j对应不同的EEPROM数据 地址为0X00-0X3F (0-63)     
	int16_t B_i_j_EE=0;                   //不同的i,j对应不同的EEPROM数据,地址为0X40-0X7F(64-127)
	double A_I_J[64]={0.0f};
	double B_I_J[64]={0.0F};
    u8 A_i_Scale=0;                       //地址为0XD9的高4位
	u8 B_i_Scale=0;                       //地址为0XD9的低4为
	A_i_Scale=(EEProm_Data[0XD9]&0XF0)>>4;
	B_i_Scale=EEProm_Data[0XD9]&0X0F;
	/************对A_Common进行合成*****/
	A_Common=256*EEProm_Data[0XD1]+EEProm_Data[0XD0];
	if(A_Common>32767)
	{
	    A_Common=A_Common-65536;
	}
	temp2=pow((double)2,(double)A_i_Scale);    //为了防止溢出用32类型
	temp3=pow((double)2,(double)B_i_Scale);    //为了防止溢出用32类型
	for(i=0;i<4;i++)
	{
	    for(j=0;j<16;j++)
		{ 
			/********读取VIR[64]中的每个数据*******/
			VIR_i_j=Frame_Data[i+4*j];                                 //取出当前像素测量的数据
			if(VIR_i_j>32767)
	        {
	             VIR_i_j=VIR_i_j-65536;
	        }   			
		    /******计算A_I_J[64]数组中的每一个成员********/
		    A_i_j_EE=EEProm_Data[i+4*j];
            sum=A_Common+A_i_j_EE*temp2;
            A_I_J[i+4*j]=(double)(sum)/(double)temp1;  //求出Ai(i,j),
			/******计算B_I_J[64]数组中的每一个成员********/
			B_i_j_EE=EEProm_Data[64+i+4*j];                            //从EEPROM中读出
		    if(B_i_j_EE>127)
			{
			    B_i_j_EE=B_i_j_EE-256;
			}
			B_I_J[i+4*j]=(double)B_i_j_EE/(double)(temp1*temp3);
			VIR_Offset[i+4*j]=(double)VIR_i_j-(double)(A_I_J[i+4*j]+B_I_J[i+4*j]*(Ta-TA0));
#if TEST_EN 
			printf("当前为第:%d",i+4*j);
			printf("    ");
			printf("V_IR_I_J:%d",VIR_i_j);
			printf("    ");
			printf("A_I_J:%1.2f",A_I_J[i+4*j]);
			printf("    ");
			printf("B_I_J:%1.2f",B_I_J[i+4*j]);
			printf("    ");
			printf("VIR_Offset:%1.2f\r\n",VIR_Offset[i+4*j]);
#endif
		}
	
	}
}
/**
**Description : 计算VIR(i,j)_COMPENSATED,每个VIR补偿减去TGC和VIRCP_COMPENSATED乘积
              : 首先计算VIRCP_COMPENSATED
              :然后可以得到VIR(i,j)_COMPENSATED的数据
**Param       : None
**Return Code : None
**/
double VIR_COMPEN[64]={0.0f};  //存储最终补偿值
double VIR_TCG_OFF[64]={0.0f}; //存放EGC补偿后的数据
void Calculation_VIR_COMPENSATED(void)
{   
	u8 i=0;
	u8 j=0;
	u32 temp3=0;
	u8 B_i_Scale=0;                                //地址为0XD9的低4位
    int32_t ACP_V=0;                               //ACP整数                  
	int16_t BCP_EE=0;                              //BCP整数
	double  ACP_F=0.0f;                            //ACP小数
	double  BCP_F=0.0f;                            //BCP小数
	double VIR_CP_OFF=0.0f;                        //存放CP补偿后的数据
	double EMM_F=0.0f;
	BCP_EE=EEProm_Data[0XD5];                      //存放在EEPROM[0XD5]中
	
	B_i_Scale=EEProm_Data[0XD9]&0X0F;              //去除BiScale
	ACP_V=256*EEProm_Data[0XD4]+EEProm_Data[0XD3]; //计算ACP_V
	temp3=pow((double)2,(double)B_i_Scale);        //为了防止溢出用32类型
	/**********计算ACP***************/
	if(ACP_V>32767)
	{
	    ACP_V=ACP_V-65536;
	}
    ACP_F=(double)(ACP_V)/(double)temp1;
	/*********计算BCP***************/
	if(BCP_EE>127)
    {
	   BCP_EE=BCP_EE-256;
	}	
	BCP_F=(double)BCP_EE/(double)(temp1*temp3);	
	/***********读取VCP************/
	VCP=Frame_Data[65];                            //该值从Framdata[65]中读取
	if(VCP>32767)
	{
	    VCP=VCP-65536;
	}
    /*******计算CP补偿后的VIR**********/
	VIR_CP_OFF=VCP-(ACP_F+BCP_F*(Ta-TA0));
	/*******计算发射率*****************/
	EMM_F=(double)(256*EEProm_Data[0XE5]+EEProm_Data[0XE4])/32768.0f;
#if TEST_EN
	printf("    ");
	printf("ACP_F:%1.2f",ACP_F);
	printf("    ");
	printf("BCP_F:%1.2f",BCP_F);
	printf("    ");
	printf("VCP:%d",VCP);
	printf("    ");
	printf("VIR_CP_OFF:%1.2f",VIR_CP_OFF);
	printf("    ");
	printf("EMM_F:%1.2f",EMM_F);
	printf("    ");
#endif
	for(i=0;i<4;i++)
	{
	    for(j=0;j<16;j++)
		{ 
		    VIR_TCG_OFF[i+4*j]=VIR_Offset[i+4*j]-TCG_F*VIR_CP_OFF;//
			VIR_COMPEN[i+4*j]=VIR_TCG_OFF[i+4*j]/EMM_F;           //计算得到VIR_COMPEN,一共是64个
#if TEST_EN 
			printf("当前为第:%d",i+4*j);
			printf("    ");
			printf("VIR_TCG_OFF:%1.2f",VIR_TCG_OFF[i+4*j]);
			printf("    ");
			printf("VIR_COMPEN:%1.2f\r\n",VIR_COMPEN[i+4*j]);
#endif
		}
	
	}
}
double a_comp[64]={0.0f};
/**
**Description : 计算a_comp(i,j)
**Param       : None
**Return Code : None
**/
void Calculation_a_comp(void)
{
    u8 i=0;
    u8 j=0; 
	int32_t KSTA=0;
   	double a_cp=0.0f;
	double KSTA_F=0;
	double a_i_j_1=0.0f;
	double a_i_j_2[64]={0.0f};
	uint64_t a_scale1=0;
	uint64_t a_scale2=0;
	/****************计算KSTA********************/
	KSTA=256*EEProm_Data[0XE7]+EEProm_Data[0XE6];
	if(KSTA>32767)
	{
	    KSTA=KSTA-65536;
	}
	KSTA_F=(double)KSTA/(double)(pow(2.0f,20.0f));
	/**************计算a_comp(i,j)****************/
    a_scale1=pow(2.0f,(double)EEProm_Data[0XE2]);
	a_scale2=pow(2.0f,(double)EEProm_Data[0XE3]);
    a_i_j_1=(double)(256*EEProm_Data[0XE1]+EEProm_Data[0XE0])/(double)a_scale1;     //计算(256*a0H+a0L)/pow(2,a_scale1)
    a_cp=(double)(256*EEProm_Data[0XD7]+EEProm_Data[0XD6])/(double)(a_scale1*temp1);
#if TEST_EN
	printf("a_cp:%1.16f",a_cp);
#endif
	for(i=0;i<4;i++)
	{
	    for(j=0;j<16;j++)
		{
		    a_i_j_2[i+4*j]=(double)(EEProm_Data[128+i+4*j])/(double)a_scale2;   //a(i,j)的a(i,j)/a_scale2
			a_i_j_2[i+4*j]=a_i_j_2[i+4*j]+a_i_j_1 ;                             //a(i,j)的分子部分
		    a_i_j_2[i+4*j]=a_i_j_2[i+4*j]/temp1;                                //和分母相除
			a_comp[i+4*j]=(1+KSTA_F*(Ta-TA0))*(a_i_j_2[i+4*j]-TCG_F*a_cp);      //最后得到a(i,j)
#if TEST_EN
			printf("当前为第:%d",i+4*j);
			printf("    ");
			printf("a_i_j_2[i+4*j]:%1.16f",a_i_j_2[i+4*j]);
			printf("    ");
			printf("a_comp[i+4*j]:%1.16f",a_comp[i+4*j]);
#endif
            
		}
	
	}

}
uint64_t Tak4=0;
double KS4_F=0.0f;
double S_X_i_j[64]={0.0f};
/**
**Description : 计算TAK4
**Param       : None
**Return Code : None
**/
void Calculation_TAK4(void)
{
    Tak4=ceil(pow((double)(Ta+273.15),4.0f));//ceil函数向上取整
#if TEST_EN
    printf("Tak4:%lld\r\n",Tak4);
#endif
}
/**
**Description : 计算S_X_i_j(i,j)
**Param       : None
**Return Code : None
**/
void Calculation_S_X_i_j(void)
{
    u8 i=0;
	u8 j=0;
	int16_t KS4_V=0;
	Calculation_TAK4();
	/*****************计算KS4_F**********/
	KS4_V=EEProm_Data[0XC4];
	if(KS4_V>127)
    {
	   KS4_V=KS4_V-256;
	}
	KS4_F=(double)(KS4_V)/(double)(pow(2.0f,(double)(8+EEProm_Data[0XC0])));
#if TEST_EN
	printf("KS4_F:%1.16f",KS4_F);	
	printf("    ");
#endif
    for(i=0;i<4;i++)
	{
	    for(j=0;j<16;j++)
		{
		    S_X_i_j[i+4*j]=pow(a_comp[i+4*j],3.0f)*VIR_COMPEN[i+4*j]+pow(a_comp[i+4*j],4.0f)*Tak4;//先计算
			S_X_i_j[i+4*j]=pow(S_X_i_j[i+4*j],0.25);          //开四次方
			S_X_i_j[i+4*j]=KS4_F*S_X_i_j[i+4*j];              //和KS4_F相乘即可
		}
#if TEST_EN
            printf("当前为第:%d",i+4*j);
			printf("    ");
			printf("S_X_i_j[i+4*j]:%1.16f\r\n",S_X_i_j[i+4*j]);		
#endif
	}

}
double TO_i_j[64]={0.0f};
/**
**Description : 计算物体的温度
**Param       : None
**Return Code : None
**/
void Calculation_TO_i_j(void)
{
    u8 i,j;
    Common();                      //读取一些基本数据
	Calculation_Ta();              //计算TA
	Calculation_VIR_Offset();      //计算VIR补偿
	Calculation_VIR_COMPENSATED(); //计算完整的VIR补偿
	Calculation_a_comp();          //计算a_comp(i,j)
#if MLX_BAB
	Calculation_TAK4();            //计算TAK4
#else
    Calculation_S_X_i_j();         //计算SX(I,J)
#endif
	for(i=0;i<4;i++)
	{
	    for(j=0;j<16;j++)
		{
#if MLX_BAB
			TO_i_j[i+4*j]=VIR_COMPEN[i+4*j]/(a_comp[i+4*j])+Tak4;
#else
			TO_i_j[i+4*j]=VIR_COMPEN[i+4*j]/(a_comp[i+4*j]*(1-KS4_F*273.15)+S_X_i_j[i+4*j])+Tak4;//如果是BAB则KS4_F为0
#endif			
		    TO_i_j[i+4*j]=pow(TO_i_j[i+4*j],0.25f)-273.15f;       //计算得到TO(I,J)
		
		}
	}
}

通过以上步骤,即可完成对MLX90621的使用。其他的传感器也一样,有的传感器不常用,可能网上没有直接能用的驱动,这时候就需要我们按照器件手册,根据芯片手册中的时序图来进行传感器软件驱动的编写。总体经验是:先写最底层的通信协议程序,然后利用协议写传感器的读写数据函数,最后利用读写函数编写传感器的配置函数等操作函数。在编写的过程中要注意变量的数据类型,注意时序图中时序的控制等小问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dog345

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值