大家好,欢迎来到IT知识分享网。
平时工作的时候会遇到如下场景:
- 新焊接好的板子,通电后发现电流异常,需要看下板子上哪里发热异常。
- 需要监控某个器件(比如三极管、MOS)的温度,以防过热烧掉。
- 测量温升。
因此需要一个红外热像仪,可是网上看了一下都要2000左右了,虽然分辨率很高,可是我并不需要那么好的性能,于是干脆自己做一个。AMG8833的像素点是8×8的,感觉太低了,于是选用了32×24像素点的MLX90640。
MLX90640介绍
特性和优点
- 小尺寸,低功耗, 32*24 像素红外阵列
- 方便集成
- 标准的 TO39 封装
- 出厂校准
- 噪声等效温差( NETD)0.1K RMS@1Hz 速率
- I2C 兼容数字接口
- 可编程刷新速率 0.5Hz~60Hz
- 供电电压 3.3V
- 电流消耗:≤23mA
- 两种视场角可选: 55° *30° 和 110° *75°
- 工作温度: -45~85℃
- 测温范围: -40~300℃
- 符合 RoHS 标准
应用实例
- 高精度非接触温度测量
- 安防、入侵检测
- 人体检测
- 智能楼宇环境温度测控
- 汽车空调控制
- 微波炉、烤箱温度检测与控制
- 工业零件温度监测
- 可视化温度传感器
- 驱动程序可从下面网页下载:
- https://github.com/melexis/mlx90640-library
概述
管脚定义
A 型和 B 型
MLX90640 有两个型号, A 型和 B 型,型号全称为:MLX90640ESF_BAA/BAB。
他们区别在于:
- 视场角不同: A 型为 110*75° , B 型为 55*35° ,通俗一点讲就是 A 型是广角,所以镜
头矮一些,视野更宽,但对远处物体的捕捉能力更低, B 型更适于拍摄稍远的物体。 - 精度不同: A 型的噪声比 B 型大,所以 B 型的绝对温度和灵敏度都好一些。
一般电气特性
像素位置对应关系
通信协议
该设备采用 I2C 协议,支持快速模式( FM+)(最高 1MHz
时钟频率),只可作为从机在总线上使用。
SDA 和 SCL 端口 5V 兼容,可以直接连接到 5V 逻辑的 I2C 总线网络。
从地址可编程的,可以有多达 127 个不同的从地址。
使用标准的IIC时序:
测量模式
测量完成的红外阵列数据更新到 RAM 区,占用 1536 字节, MLX90640 每次测量一半像素点,分两次完成所有 768 像素的测量,在逻辑上将每次测量完成的一半称为一个子页,故此数据帧有两个子页面(两个子页合并以后才是完整的 768 个像素数据), 每次完成一半像素点的分布模式有两种,可通过控制寄存器 1( 0x800D) 的 bit12 位来设置。
- ( 1) 棋盘模式(默认),( 每个像素间隔排列-像素交错模式)
- ( 2)电视交错模式,( 隔行排列-行交错模式)
注 1:标准的 MLX90640 出厂的时候是在棋盘模式下校准的,因此传感器在棋盘模式下具有更好的噪声滤除性能。为了得到最好的结果,建议使用默认的棋盘模式。
刷新率和噪声
精度、坏点
原理图
API库的移植
软件模拟IIC移植(stm32)
/ * @copyright (C) 2017 Melexis N.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ / * As the timings depend heavily on the MCU in use, it is recommended * to make sure that the proper timings are achieved. For that purpose * an oscilloscope might be needed to strobe the SCL and SDA signals. * The Wait(int) function could be modified in order to better * trim the frequency. For coarse setting of the frequency or * dynamic frequency change using the default function implementation, * ‘freqCnt’ argument should be changed – lower value results in * higher frequency. */ #include "MLX90640_I2C_Driver.h" #define Wait(freqCnt) freqCnt++ int I2CSendByte(int8_t); void I2CReadBytes(int, char *); void I2CStart(void); void I2CStop(void); void I2CRepeatedStart(void); void I2CSendACK(void); void I2CSendNack(void); int I2CReceiveAck(void); //void Wait(int); int freqCnt = 1; void MLX90640_I2CInit() {
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); IIC_SDA_HIGH(); IIC_SCL_HIGH(); } int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress,uint16_t nMemAddressRead, uint16_t *data) {
uint8_t sa; int ack = 0; int cnt = 0; int i = 0; char cmd[2] = {
0,0}; char i2cData[1664] = {
0}; uint16_t *p; p = data; sa = (slaveAddr << 1); cmd[0] = startAddress >> 8; cmd[1] = startAddress & 0x00FF; I2CStop(); Wait(freqCnt); I2CStart(); Wait(freqCnt); ack = I2CSendByte(sa)!=0; if(ack != 0) {
return -1; } ack = I2CSendByte(cmd[0])!=0; if(ack != 0) {
return -1; } ack = I2CSendByte(cmd[1])!=0; if(ack != 0) {
return -1; } I2CRepeatedStart(); sa = sa | 0x01; ack = I2CSendByte(sa); if(ack != 0) {
return -1; } I2CReadBytes((nMemAddressRead << 1), i2cData); I2CStop(); for(cnt=0; cnt < nMemAddressRead; cnt++) {
i = cnt << 1; *p++ = (int)i2cData[i]*256 + (int)i2cData[i+1]; } return 0; } void MLX90640_I2CFreqSet(int freq) {
freqCnt = freq>>1; } int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data) {
uint8_t sa; int ack = 0; char cmd[4] = {
0,0,0,0}; static uint16_t dataCheck; sa = (slaveAddr << 1); cmd[0] = writeAddress >> 8; cmd[1] = writeAddress & 0x00FF; cmd[2] = data >> 8; cmd[3] = data & 0x00FF; I2CStop(); Wait(freqCnt); I2CStart(); ack = I2CSendByte(sa); if (ack != 0x00) {
return 1; } for(int i = 0; i<4; i++) {
ack = I2CSendByte(cmd[i]); if (ack != 0x00) {
return -1; } } I2CStop(); MLX90640_I2CRead(slaveAddr,writeAddress,1, &dataCheck); if ( dataCheck != data) {
return -2; } return 0; } int I2CSendByte(int8_t data) {
int ack = 1; int8_t byte = data; for(int i=0;i<8;i++) {
Wait(freqCnt); if(byte & 0x80) {
IIC_SDA_HIGH(); } else {
IIC_SDA_LOW(); } Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); Wait(freqCnt); IIC_SCL_LOW(); byte = byte<<1; } Wait(freqCnt); ack = I2CReceiveAck(); return ack; } void I2CReadBytes(int nBytes, char *dataP) {
char data; for(int j=0;j<nBytes;j++) {
Wait(freqCnt); IIC_SDA_HIGH(); data = 0; for(int i=0;i<8;i++){
Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); data = data<<1; if(IIC_SDA_READ()){
data = data+1; } Wait(freqCnt); IIC_SCL_LOW(); Wait(freqCnt); } if(j == (nBytes-1)) {
I2CSendNack(); } else {
I2CSendACK(); } *(dataP+j) = data; } } //void Wait(int freqCnt) //{
int i; i=0; for(i = 0;i<freqCnt;i++); {
cnt = cnt++; } while(freqCnt--); for(cnt=20;cnt>0;cnt--); //} void I2CStart(void) {
IIC_SDA_HIGH(); IIC_SCL_HIGH(); Wait(freqCnt); Wait(freqCnt); IIC_SDA_LOW(); Wait(freqCnt); IIC_SCL_LOW(); Wait(freqCnt); } void I2CStop(void) {
IIC_SCL_LOW(); IIC_SDA_LOW(); Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); IIC_SDA_HIGH(); Wait(freqCnt); } void I2CRepeatedStart(void) {
IIC_SCL_LOW(); Wait(freqCnt); IIC_SDA_HIGH(); Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); IIC_SDA_LOW(); Wait(freqCnt); IIC_SCL_LOW(); } void I2CSendACK(void) {
IIC_SDA_LOW(); Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); Wait(freqCnt); IIC_SCL_LOW(); Wait(freqCnt); IIC_SDA_HIGH(); } void I2CSendNack(void) {
IIC_SDA_HIGH(); Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); Wait(freqCnt); IIC_SCL_LOW(); Wait(freqCnt); IIC_SDA_HIGH(); } int I2CReceiveAck(void) {
int ack; IIC_SDA_HIGH(); Wait(freqCnt); IIC_SCL_HIGH(); Wait(freqCnt); if(IIC_SDA_READ() == 0) {
ack = 0; } else {
ack = 1; } Wait(freqCnt); IIC_SCL_LOW(); IIC_SDA_LOW(); return ack; }
打开MLX90640_I2C_Driver.h文件,把SDA和SCL拉高拉低的宏定义实现:
/ * @copyright (C) 2017 Melexis N.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef _MLX90640_I2C_Driver_H_ #define _MLX90640_I2C_Driver_H_ //#ifdef __cplusplus // extern "C" {
//#endif #include <stdint.h> #include "stm32f10x.h" //IO方向设置 #define SDA_IN() {
GPIOA->CRH&=0X0FFFFFFF;GPIOA->CRH|=8<<28;} #define SDA_OUT() {
GPIOA->CRH&=0X0FFFFFFF;GPIOA->CRH|=3<<28;} #define GPIO_PORT_I2C GPIOA #define RCC_I2C_PORT RCC_APB2Periph_GPIOA #define I2C_SCL_PIN GPIO_Pin_9 /* 连接到SCL时钟线的GPIO */ #define I2C_SDA_PIN GPIO_Pin_15 /* 连接到SDA数据线的GPIO */ #define IIC_SCL_HIGH() GPIO_PORT_I2C->BSRR = I2C_SCL_PIN /* SCL = 1 */ #define IIC_SCL_LOW() GPIO_PORT_I2C->BRR = I2C_SCL_PIN /* SCL = 0 */ #define IIC_SDA_HIGH() GPIO_PORT_I2C->BSRR = I2C_SDA_PIN /* SDA = 1 */ #define IIC_SDA_LOW() GPIO_PORT_I2C->BRR = I2C_SDA_PIN /* SDA = 0 */ #define IIC_SDA_READ() ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0) /* 读SDA口线状态 */ void MLX90640_I2CInit(void); int MLX90640_I2CRead(uint8_t slaveAddr,uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data); int MLX90640_I2CWrite(uint8_t slaveAddr,uint16_t writeAddress, uint16_t data); void MLX90640_I2CFreqSet(int freq); //#ifdef __cplusplus //} //#endif #endif
硬件IIC移植
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/124612.html