平时工作的时候会遇到如下场景:

  • 新焊接好的板子,通电后发现电流异常,需要看下板子上哪里发热异常。
  • 需要监控某个器件(比如三极管、MOS)的温度,以防过热烧掉。
  • 测量温升。

  因此需要一个红外热像仪,可是网上看了一下都要2000左右了,虽然分辨率很高,可是我并不需要那么好的性能,于是干脆自己做一个。AMG8833的像素点是8x8的,感觉太低了,于是选用了32x24像素点的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

概述

  MLX90640 是工业标准并经过完全校准的 32*24像素热红外阵列传感器,采用 4 脚 TO39 封装以及I2C 兼容的数字接口。
  MLX90640 包含 768 个热红外像素点。内嵌自身环境温度传感器和 VDD 电压检测 ADC。通过 I2C 接口,可以访问存储于内部 RAM 中的红外阵列、 环境温度以及 VDD 实时数据。

管脚定义

A 型和 B 型


MLX90640 有两个型号, A 型和 B 型,型号全称为:MLX90640ESF_BAA/BAB。
他们区别在于:

  • 视场角不同: A 型为 110*75° , B 型为 55*35° ,通俗一点讲就是 A 型是广角,所以镜
    头矮一些,视野更宽,但对远处物体的捕捉能力更低, B 型更适于拍摄稍远的物体。
  • 精度不同: A 型的噪声比 B 型大,所以 B 型的绝对温度和灵敏度都好一些。

  做红外热像仪,一般用B型。
  A型尺寸:

  B型尺寸:

一般电气特性

像素位置对应关系

通信协议

该设备采用 I2C 协议,支持快速模式( FM+)(最高 1MHz时钟频率),只可作为从机在总线上使用。
SDA 和 SCL 端口 5V 兼容,可以直接连接到 5V 逻辑的 I2C 总线网络。
从地址可编程的,可以有多达 127 个不同的从地址。
使用标准的IIC时序:

测量模式

  测量完成的红外阵列数据更新到 RAM 区,占用 1536 字节, MLX90640 每次测量一半像素点,分两次完成所有 768 像素的测量,在逻辑上将每次测量完成的一半称为一个子页,故此数据帧有两个子页面(两个子页合并以后才是完整的 768 个像素数据), 每次完成一半像素点的分布模式有两种,可通过控制寄存器 1( 0x800D) 的 bit12 位来设置。

  • ( 1) 棋盘模式(默认),( 每个像素间隔排列-像素交错模式)
  • ( 2)电视交错模式,( 隔行排列-行交错模式)

注 1:标准的 MLX90640 出厂的时候是在棋盘模式下校准的,因此传感器在棋盘模式下具有更好的噪声滤除性能。为了得到最好的结果,建议使用默认的棋盘模式。


刷新率和噪声

  MLX90640 的测量速率最高可以达到 64Hz,但越快的速率时的噪声会越大,导致灵敏度下降,手册上给出的指标是 1Hz 时可以区分出 0.1℃。




精度、坏点

  测温精度和成像的区域有关,靠近中间位置是±0.5~1.0℃,最外侧 4 个角是±2.0℃,其它区域约是±1.0℃。

  传感器上电后有个热平衡时间,大约是 5 分钟,未达到热平衡时精度会差一些。
  手册里特别提到了每个 MLX90640 传感器可能存在最多 4 个不能使用或者精度达不到要求的像素,这也许和传感器的生产工艺有关吧,坏点都会在出厂时记录到传感器的EEPROM 里,实际使用时记得要读取一下并且在成像时特殊处理这种可能存在的像素点数据。

原理图

API库的移植

  从上面看好像MLX90640用起来比较复杂,其实不用担心,迈来芯官方已经提供了驱动库,只需要下载下来简单移植一下,然后调用库函数读取温度数据即可。
  驱动库下载链接:https://github.com/melexis/mlx90640-library
  下载下来后:

  functions文件夹中是源文件,headers文件夹中是头文件,把他们复制到自己的工程下。
  把源文件添加到自己的工程中,其中MLX90640_I2C_Driver.cpp是硬件IIC的,
MLX90640_SWI2C_Driver.cpp是软件模拟IIC的,根据自己的情况选择一个就行。

软件模拟IIC移植(stm32)

  假如使用软件模拟IIC,那么需要将functions文件夹下的MLX90640_API.cpp、MLX90640_SWI2C_Driver.cpp包含进工程,同时把headers文件夹下的MLX90640_API.h、MLX90640_I2C_Driver.h也包含进工程。
  效果如下:

  接下来只需要修改MLX90640_SWI2C_Driver.cpp。
  打开MLX90640_SWI2C_Driver.cpp,可以看到里面已经把模拟IIC的时序函数都实现了,只需要自己把IO口的初始化加上就可以了。
  修改后的样子:

/*** @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移植

  假如使用硬件IIC,那么需要将functions文件夹下的MLX90640_API.cpp、MLX90640_I2C_Driver.cpp包含进工程,同时把headers文件夹下的MLX90640_API.h、MLX90640_I2C_Driver.h也包含进工程。
  效果如下:

  添加好以后我们还需要适配 I2C 驱动,这样才能使得 MLX90640_API.cpp 文件可以正确的通过MLX90640_I2C_Driver.cpp 文件提供的方法读取传感器的值,如下图,将 MLX90640_I2CRead()方法和MLX90640_I2CWrite()关联 STM32 的 I2C 读写函数即可:
  读函数

  写函数

使用MLX90640自制红外热像仪(一):MLX90640介绍与API库移植相关推荐

  1. 使用MLX90640自制红外热像仪(二):API函数的使用

      前面一篇文章介绍了MLX90640的相关信息和API库的移植,接下来介绍一下API库中的函数,和使用方法.   首先给出API函数的调用顺序,再对每个用到的API函数做说明: #define FP ...

  2. 使用MLX90640自制红外热像仪(三):图像插值、图像彩色编码

      经过上一节,已经把MLX90640的32x24个像素点读出来了,可是使用32x24直接显示在屏幕上,显示区域显示太小了,于是就需要对图像就行放大. 图像插值   常见的插值算法可以分为两类:自适应 ...

  3. 使用MLX90640自制红外热像仪(四):stm32f103c8t6刷320x240分辨率屏的时间测试

    要显示MLX90640的数据,需要每次把320*240个像素点全部刷新一次.现在来测试下stm32f103c8t6使用普通IO刷屏. 72M主频的stm32f103c8t6刷TFT,全屏一直刷新测试 ...

  4. 热像仪 二次开发 c++_一种全新的红外热像仪——“可编程红外热像仪”

    如 今,红外热像仪对于很多人而言已经不是一个新鲜事物了,它利用红外探测器对被测目标的红外辐射进行探测,并加以光电转换和信号处理等手段,将被测目标的温度分布转换为我们人眼可以直观识别的图像.受益于这种温 ...

  5. 两点定标法_一种两点校正红外热像仪的非均匀性的模块及方法

    一种两点校正红外热像仪的非均匀性的模块及方法 [技术领域] [0001] 本发明属于红外热成像系统的非均匀性校正领域,特别是一种两点校正红外热像 仪的非均匀性的模块及方法. [背景技术] [0002] ...

  6. 福禄克FLUKE TIX650红外热像仪3.5英寸高像素大屏

    主要特性 640 x 480 像素红外热像仪,3.5 英寸高分辨率 LCD 大屏幕 温度测量范围 -40°C 至 2000°C 随附 SmartView R&D 软件 产品概述: Fluke ...

  7. FLIR E95红外热像仪,带你走进建筑诊断解决方案

    众所周知,从商业摩天大楼到工业制造厂,关键设施必须维持在一个相对安全可靠的环境,以实现最佳运营.为满足这一需求,更多建筑团队正利用FLIR红外热像仪加强周边的入侵检测,并简化入口处的体表温度升高筛查. ...

  8. FLIR E85/E95/T620/t610/T540/T530红外热像仪全齐

    FLIR E85/E95/T620/t610/T540/T530红外热像仪,优异的MSX场景增强加持 耐用更实用 FLIR推出Exx系列,旨在提供具备最出色性能.分辨率和灵敏度的手式握把手持热像仪.E ...

  9. 福禄克FLUKE 重磅发布两款红外热像仪— TiS55+和TiS75+

    美国福禄克公司于2021年1月重磅发布两款红外热像仪--TiS55+和TiS75+. 作为福禄克优选系列热像仪中的拳头产品,TiS55+和TiS75+在传承福禄克仪器高品质的同时,也在硬件方面做了许多 ...

最新文章

  1. wsimport 不是内部或外部命令,也不是可运行的程序或批处理文件
  2. Linux内核学习--内存管理模块
  3. ROS-3 : Catkin工作空间和ROS功能包
  4. Python基础之函数与装饰器
  5. 微信小程序时间标签与范围联动设计实现
  6. Linux 命令之 ps -- 显示进程状态/查看进程信息
  7. 添加远程链接MySQL的权限
  8. string中concat_JavaScript中带示例的String concat()方法
  9. java 命令行读取_Java:从控制台(console,命令行)读取字符 | 学步园
  10. 什么是死锁及死锁的必要条件和解决方法【转】
  11. ctfshow-网络迷踪-初学乍练( 离谱! 一张图判断飞机的目的地?)
  12. Nginx解决前端调用后端接口跨域问题
  13. mysqli_connect参数的写法以及如何设置特定端口
  14. Msfconsole爆破ssh
  15. 数据库关闭的四种方式
  16. 线性代数【8】-1 线性方程组 - 非常重要的概念 - 三个基本的问题
  17. zoomit的使用 - 一个可以直接在演示的时候写字的软件
  18. 元宇宙链游OAS即将正式上线,社区热度只增不减
  19. git 某个分支直接覆盖当前master分支
  20. 如果让测试员来拍《程序员那么可爱》,剧情会是什么样的?

热门文章

  1. 复星金服微服务_阿里巴巴财报:蚂蚁金服净利润59亿元,支付宝服务用户约12亿...
  2. docker nginx部署web应用_docker部署Nginx
  3. 是把计算机分析和恢复力实测,土木工程测试试题.docx
  4. python 传感器数据结构_Python常用的数据结构详解
  5. 穿上就能凉快近5°C,华中大浙大夏日“避暑神器”登Science
  6. 马斯克又破纪录了:120米史上最高火箭已组装,计划今年完成首次轨道试飞
  7. 仿真环境跟车2分钟,就让自动驾驶系统撞上马路牙子,攻破率超90%,多传感器融合系统都失效...
  8. 27年前被Nature拒稿,如今斩获诺贝尔奖!学术投稿模式再引热议:都有神奇的评审2...
  9. Docker构建YApi镜像, Docker安装YApi, Docker部署YApi
  10. STM32F103--(二) GPIO实践