tag 标签: iic压力传感器

相关博文
  • 热度 6
    2020-6-4 21:35
    3877 次阅读|
    1 个评论
    IIC压力传感器控制与使用(上)
    ------TE 篇 公司以往水表上都是用的模拟输出的压力传感器,压力传感器输出的电压经单片机上的 AD 转换后,按照对应公式确定压力值。最近客户招标要求使用 IIC 输出的压力传感器,按照领导要求,国产的国外的都找到了一款,进行调试对比,以确定最终设计方案. 国外的找到一款 TE 生产的 M3200 , 14 位压力数字输出及 11 位温度数字输出,零偏移为 0.5% ,精度 ( 总误差带 )1.5% 。 我拿到的样品具体型号是 M32JM-00010B-020BG ,这个根据 M3200 参数手册的第 10 页看到型号的定义, J 表示 IIC 输出, M 表示 1m 长线, 000 表示无缓存装置, 1 表示睡眠模式, 0 表示数字地址为 0x28 , B 表示 G1/4 螺纹, 020B 表示压力最大支持 20bar , G 表示测量值为表压。 Tips : 绝对压力 相对完全真空测量(零压力)。 表压 绝对压力与当地大气压力的差值。 真空压力 相对当地大气压力测量。真空总是负值。 密封压力 相对任意设定的压力测量。 根据 M3200 参数手册的第 4 页介绍,传感器引出的四根线分别是红色、黑色、白色及绿色。红色线接 VCC ,黑色线接 GND ,白色线为 SCL 线,绿色线为 SDA 线。在另一个名为“ interface to digital modules ”的文档中第 1 页介绍了外部电路的连接,与常规的 IIC 电路一样,外接电源并且与单片机供电,并将 SCL 和 SDA 分别接到单片机的对应引脚上,并在 SCL 线和 SDA 线分别上拉 4.7k 电阻。 M3200 电压范围支持 2.7V~5.0V ,我所用的单片机需要 3.3V 供电,故传感器我也直接 3.3V 供电 ( 在 3.3V 供电下,实测正常非睡眠模式电流 20mA ,睡眠模式下电流 16uA) 。 外部硬件电路搞通后,就要研究如何用单片机去控制压力传感器,并且去读取内部数据了,这就需要仔细阅读 TE 提供的“ interface to digital modules ”文档了。我认为如果有过 IIC 使用经验的话,直接从该文档的第三页开始看第 1.6 小节即可,这里讲的是有关命令集和数据传输顺序。( IIC 的功能莫过于:主机发送起始信号 + 主机向总线上发送一个字节数据 + 等待从机应答 + 主机从总线上获取从机发来的一个字节数据 + 主机收到后应答或不应答 + 主机发送结束信号) 可以看到有四条指令,这四条指令都是由单片机充当主机,传感器充当从机,由主机向从机发送起始信号,由从机应答。 (1) I2C_Read_MR 该指令是由主机发送测量命令,从机接到该命令后开始一轮测量与计算(注意并不回复测量结果)。实现方式是先由主机发送起始信号 Start ,然后发送一个字节数据,该数据为从机的默认地址 0x28 和一位读写位,先将 0x28 左移一位,给读写位留出地方,变成 0x50 ,由于指令上最后一位读写位为 R ,即读写位位 1 ,则该字节合起来为 0x51 ,主机发送完以字节数据后要等待从机的应答信号,用于确认从机收到命令。收到从机的应答信号后,主机发送停止信号 Stop 信号,结束该条命令。此时,从机开始进行一轮测量。 (2) I2C_Read_DF2 该指令为主机获取从机的两字节数据的功能,这两字节数据包括 2bit 用于表示数据状态, 14bit 用于表示压力输出数值。从指令图可以看出,主机发送 Start 信号后,再发出 0x51 (从机地址 +R ),等待从机应答,收到应答后,主机从总线上获取两字节数据的高 8 位,然后主机发送应答信号,告诉从机,我收到你发的数据了,请你继续发,然后从机就会继续发送低 8 位数据,主机只需要从总线上再获取低 8 位数据就可以直接发送 Stop 信号,结束该指令即可,主机不需要收到低八位数据后再应答了,因为主机发现自己要的两个字节数据已经够了。 我们接下来要对收到的这两字节数据进行处理,首先提取出来 BIT15 和 BIT14 ,这两位组合起来去表示状态位。 00 表示数据正常, 10 表示该测量数据以前被读取过,不是最新的数据了, 11 表示检查到故障。把 BIT13 至 BIT0 组合起来,转换为十进制数,这是压力输出数值。注意,压力输出数字并不是压力值,需要根据压力输出数字去计算对应的压力值。具体可以参考 ” M3200 Pressure Transducer ” 文件中的第六页介绍。以下是我自己的推导原理公式。 压力当前输出数值 D ,是指当前压力传感器输出的数值 (BIT13~BIT0); 压力输出最大数值Dmax, 是指该压力传感器满量程时可以输出的最大数值 (BIT13~BIT0) ,这个值在 ” M3200 Pressure Transducer ” 文件中的第三页中介绍到最大输出数值为 15000 ,最小输出数值为 1000 。这个是官方给的参考值,我建议还是实际去测量下,满量程和无压力时对应的输出数值,要不然用推荐值代入公式后计算,误差太大。 压力输出最小数值Dmin, 是指该压力传感器负载压力为 0Pa 时,对应的压力输出值。官方推荐值为 1000 ,建议实际测量。 当前压力值 P ,是指当前的实际压力值,单位可以是 Pa 、 KPa ,或者 MPa ,这个根据具体项目确定,我这里定义单位为 KPa 。 压力最大值Pmax, 指该压力传感器的满量程值,该压力传感器最大值为 20bar ,即 2MPa 。 压力最小值Pmin, 指该压力传感器的量程最小值,一般是 0KPa 。 上面这个公式就是将压力数值转换为压力值的公式,利用的是压力数值占比与压力占比相等的原理。将上述公式进行继续推导,就可以得到压力值的表达式。 带入Dmin=1000,Dmax=15000,Pmax=2000,Pmin=0, 可得,P=(D-1000)*2000/14000. 所以,我们在程序中将上公式录入,从传感器获得压力数值 D 时,代入带公式中就可以得到实际压力 P 的值。 (3) I2C_Read_DF3 & (4) I2C_Read_DF4 之所以将获取指令 3 和 4 放在一起,是因为 3 其实单独用没有啥实际意义,因为 3 获取的数据相比 2 来将,只是多了个温度值的高八位,通过指令 4 才可以获得温度值的整个 11 位数据。传感器可以通过温度值去自动校对压力值,输出当前温度下的压力值,这个校准在压力传感器内部的芯片已经自动校准了,不需要我们根据输出值进行校准。这个输出的温度值对于一些即需要压力数据又需要温度数据的用户比较方便。温度输出值转换为实际温度值的方法和压力的转换方法类似,具体可以参考 ” M3200 Pressure Transducer ” 文件中第七页公式进行计算,在此不再分析。 故,一般需要获取压力压力值的项目,直接使用指令 (2)I2C_Read_DF2 获取当前的压力值即可。 压力传感器有 sleep 睡眠模式和 update 激活模式两种。这个是由压力传感器内部的 EEROM 中存储的模式状态位决定的。修改模式,需要进入指令模式,然后读写 EEROM 进行修改,由于 TE 没有详细资料对此进行介绍,进入睡眠模式的指令不确定就没法进行切换。但国产压力传感器对本部分进行了介绍,我会在下篇 ( 国产篇 ) 中介绍如何修改模式。 sleep 模式下,传感器是睡着的,你要读取压力数据时,要先进行唤醒它,它会进行测量并计算出压力数值,存放到 EEROM 中等待你去读取。等你读取完,它就继续睡觉了,等待你下一次的唤醒。而 update 模式的压力传感器,它不睡觉,它以一定周期的频率去自己主动测量压力值,并计算后存放到 EEROM 中,不管你是否读取该数据,它都会以一定周期的频率去刷新数据。它刷新的频率也是由其内部的 EEROM 中存储的周期值决定的,但 TE 并没有对该部分描述如何去修改。一般来讲,你如果读取频率不是太快,你读到的数据都是最新的压力值。 区分 sleep 模式和 update 模式的一个重要途径是问商家,另一个就是通过万能表去测量电流大小,若是 uA 级别,就是 sleep 模式,若是 mA 级别,就是 update 模式。 我拿到的这个 TE 的样品是个 update 模式的,使用起来比较简单,就是我想获取压力值的时侯,就对压力传感器上电,然后按照指令 (2)I2C_Read_DF2 的时序,对其进行读取,获得压力数值后代入我上面推导的公式,然后转换成压力值,显示到外界屏幕上,再把压力传感器断电即可。 程序控制部分,我建议使用模拟 IIC 去进行通讯,我试过用 ST 的硬件 IIC 去读取,发现能通讯成功的概率很低,这大概是 FLP 当年埋下的雷吧。这个模拟 IIC 的例程在网上都可以找到,在此不再啰嗦。以下程序,以读取四个字节为例,进行展示如何获取压力数据。 //----------------------------------------------------------------------------// //压力传感器相关参数定义 //----------------------------------------------------------------------------// #define Pressure_Address 0x28 //压力传感器默认地址 //--------------------------------------------// //全局变量声明 //--------------------------------------------// u8 Pressure_Data_Buf ; //--------------------------------------------// //函数名称:I2C_Read_DF4 //入口参数:无 //出口参数:是否成功,ERROR为0 //说 明:获取四字节数据 //-------------------------------------------// ErrorStatus I2C_Read_DF4(void) { u8 Address,i; Address = Pressure_Address; Address = (Address << 1)+ 0x01; //0x01表示读 IIC_Send_Start(); //发送起始信号 if(0x00 == IIC_Send_Byte(Address)) //发送地址 return ERROR; for(i=0; i<3; i++) { Pressure_Data_Buf = IIC_Get_Byte(0); //非最后一字节数据,要ACK } Pressure_Data_Buf = IIC_Get_Byte(1); //最后一字节数据,无ACK IIC_Send_Stop(); //发送结束信号 return SUCCESS; } //获得压力传感器输出的4字节数据后,就要对数据进行转换,转换成压力值进行输出。 //--------------------------------------------// //全局变量声明 //--------------------------------------------// u8 Pressure_Data_Buf ; float Pressure; //----------------------------------------------------------------------------// //压力传感器相关参数定义 //----------------------------------------------------------------------------// #define D_min 1000.0 //压力输出最小数值 #define D_max 15000.0 //压力输出最大数值 #define P_min 0.0 //压力量程最小值KPa #define P_max 2000.0 //压力量程最大值KPa //--------------------------------------------// //函数名称:Pressure_Data_Handle //入口参数:无 //出口参数:是否成功,ERROR为0 //说 明:用于处理转换压力数据 //-------------------------------------------// ErrorStatus Pressure_Data_Handle(void) { u16 temp; //临时变量 if((Pressure_Data_Buf & 0xC0) == 0x00) //判断最高两位,确定数据是否正常 { temp = Pressure_Data_Buf & 0x3F; temp = temp << 8; temp = Pressure_Data_Buf + temp; //组合压力输出值 Pressure = (((float) temp)-D_min) * (P_max-P_min) / (D_max -D_min)+P_min; //代入压力计算公式 return SUCCESS; } else return ERROR; } 在使用时,调用一次 Pressure_Data_Handle 函数,若返回值为成功,则将全局变量 Pressure 以浮点数的形式输出,即可表示当前的压力值。获取温度值的方式与获取压力值的方式类似,在此不再体现。 下载视频