MLX90640 紅外熱成像儀測溫模塊開發(fā)筆記(一)概述及開發(fā)資料準(zhǔn)備
現(xiàn)在自己在做紅外成像儀的越來越多了,兩年前有個(gè)井下機(jī)電設(shè)備運(yùn)行狀態(tài)的科研項(xiàng)目,當(dāng)時(shí)使用了 AMG8833(8*8 像素),科研畢竟就是科研,后來也沒有聽說成果得到應(yīng)用的消息, 我想也是, 8*8 能干什么,也就能做個(gè)紅外測溫槍吧。 前段時(shí)間因?yàn)?a target="_blank">公司生產(chǎn)電路板測試需要,打算買一臺(tái)紅外成像儀測量電路板發(fā)熱是否正常,商用的價(jià)格還是有些小貴的,我們電路板都不大所以就找了一臺(tái)便宜的先用著,無意中發(fā)現(xiàn)了 MLX90640 這個(gè)東西, 32*24像素, 768 個(gè)測溫點(diǎn),基本上可以成像用了。現(xiàn)在都智能手機(jī)、信息化、人工智能了,能不能用 MLX90640 做個(gè)能和手機(jī)連接成像的紅外模塊呢,那樣的話測試、存儲(chǔ)豈不是很方便。 說做就做,馬上行動(dòng)。。。。。
MLX90640 有兩個(gè)型號(hào), A 型和 B 型,各拍了一個(gè),在等待物流的過程中索性先做些準(zhǔn)備工作,也科普一下紅外成像是怎么回事。
首先是上 MLX 的官網(wǎng)下載幾個(gè)必備文件,有用的其實(shí)只有兩個(gè)文件。
(1) MLX90640 數(shù)據(jù)手冊(cè)
下載地址不好放上,大家可以私信。
(2) MLX90640 驅(qū)動(dòng)庫和說明文檔
下載地址
關(guān)于官網(wǎng)下載的兩個(gè)文件,手冊(cè)寫得很一般,說一點(diǎn)用處也沒有也不至于,但看完后覺得大部分是沒有意義和不知所以然要寫的,但手冊(cè)不看畢竟是不行的。同時(shí)也做了中文翻譯, MLX90640 中文手冊(cè)下載地址
另一個(gè)下載的文件 mlx90640-library-master.zip 問題比較嚴(yán)重(折騰了我大概一天多時(shí)間)。過程不多說了,直接說問題在哪。 這個(gè)壓縮包里有 API 使用說明、 API 的 C 語言源代碼以及一組用 Excel 文件計(jì)算完成的參數(shù)計(jì)算實(shí)例,實(shí)例的原數(shù)據(jù)和計(jì)算結(jié)果都是沒有問題的,但我按照 API 使用說明里的指導(dǎo)調(diào)用函數(shù)庫存里的函數(shù),使用 Excel 里的原始數(shù)據(jù)無論如何也得到不正確的結(jié)果,后來發(fā)現(xiàn)問題出在下載的 API 函數(shù)。
MLX90640_API.h 文件里定義了一個(gè)結(jié)構(gòu)體類型,里面較為明顯的錯(cuò)誤有:
uint16_t alpha[768];
int8_t kta[768];
int8_t kv[768];
上面三個(gè)變量被定義為整型,但是, Excel 計(jì)算表里面,這三個(gè)數(shù)組的值分別顯示為0.0000000397885742132、 0.00634766、 0.43750000 的樣子,這是整數(shù)?其它的不說, Excel和 API 不是同一個(gè)版本或者說不一致是 100%的。經(jīng)過不斷找別人用過的 API、測試,下面的文件是可用的,同時(shí)也做了一份 API 說明文件的中文翻譯。
MLX90640 驅(qū)動(dòng)庫:
MLX90640API 中文說明
MLX90640 紅外熱成像儀測溫模塊開發(fā)筆記(二)API 移植-I2C 和關(guān)鍵接口函數(shù)
API 說明文件里面有官方的移植指導(dǎo),但我覺得可以把重點(diǎn)放在與 MLX90640 具體操作有關(guān)的幾個(gè)函數(shù)上,而與標(biāo)準(zhǔn) I2C 相關(guān)的函數(shù)和文件結(jié)構(gòu)還是按照自己習(xí)慣的套路實(shí)現(xiàn)。這樣更符合我們開發(fā)人員的可控性的習(xí)慣。步驟如下:
(1) 建立標(biāo)準(zhǔn) I2C 文件 IIC.h 和 IIC.c
用自己的方法實(shí)現(xiàn)如下幾個(gè)函數(shù)(硬件也好,GPIO 模擬也好),函數(shù)名稱用下面建議的。
void IIC_Init(void); //I2C 接口初始化
void IIC_Start(void); //發(fā)送開始信號(hào)
void IIC_Stop(void); //發(fā)送結(jié)束信號(hào)
void IIC_SendACK(void); //發(fā)送應(yīng)答信號(hào)
void IIC_SendNAK(void); //發(fā)送非應(yīng)答信號(hào)unsigned char IIC_RecvACK(void); //讀取應(yīng)答信號(hào)unsigned char IIC_RecvData(void); //讀取 1 個(gè)字節(jié)void IIC_SendData(char dat); //發(fā)送 1 個(gè)字節(jié)
(2) 在工程中引入 MLX90640_API.c
并做如下幾處修改
第一行#include 改為#include
(3) 添加 3 個(gè)函數(shù)
void MLX90640_I2CInit(void)
unsigned char MLX90640_I2CRead (unsigned short startAddress, unsigned short nWordsRead, unsigned short *datas)
unsigned char MLX90640_I2CWrite (unsigned short writeAddress, unsigned short word)
void MLX90640_I2CInit(void)
{
IIC_Stop();
}
//從指定地址讀取 n 個(gè)字(每個(gè)字占用 2 個(gè)字節(jié))
unsigned char MLX90640_I2CRead(unsigned short startAddress, unsigned short nWordsRead, unsigned short *datas)
{
unsigned char c1,c2; unsigned short i; unsigned char Msb,Lsb;
Msb=(unsigned char)(startAddress>>8); Lsb=(unsigned char)(startAddress&0x00FF);
IIC_Start(); //發(fā)送起始命令
IIC_SendData(0x66); //發(fā)送設(shè)備地址+寫命令I(lǐng)IC_RecvACK();
IIC_SendData(Msb); //發(fā)送要操作的地址值 2 字節(jié)
IIC_RecvACK();
IIC_SendData(Lsb);
IIC_RecvACK();
IIC_Start(); //發(fā)送起始命令
IIC_SendData(0x67); //發(fā)送設(shè)備地址+讀命令I(lǐng)IC_RecvACK();
for (i=0;i{
c1=IIC_RecvData(); IIC_SendACK();
c2=IIC_RecvData();
if (i==(nWordsRead-1)) IIC_SendNAK();
else
IIC_SendACK();;i++)
datas[i]=c1; datas[i]<<=8; datas[i]|=c2;
}
IIC_Stop(); //發(fā)送停止命令
return 0;
}
//向指定地址寫入 1 個(gè)字(2 字節(jié))
unsigned char MLX90640_I2CWrite(unsigned int writeAddress, unsigned int word)
{
IIC_Start(); //發(fā)送起始命令
IIC_SendData(0x66); //發(fā)送設(shè)備地址+寫命令I(lǐng)IC_RecvACK();
IIC_SendData(writeAddress>>8); //發(fā)送要操作的地址值 2 字節(jié)
IIC_RecvACK();
IIC_SendData(writeAddress&0x00FF); IIC_RecvACK();
IIC_SendData(word>>8); IIC_RecvACK();
IIC_SendData(word&0x00FF); IIC_RecvACK();
IIC_Stop(); return 0;
(4)修改 2 個(gè)函數(shù)
unsigned char MLX90640_DumpEE(unsigned short *eeData)
{
return MLX90640_I2CRead(0x2400, 832, eeData);
}
unsigned char MLX90640_GetFrameData(unsigned short *frameData)
{
unsigned short statusRegister,controlRegister1;
MLX90640_I2CRead(0x8000, 1, &statusRegister); if (statusRegister&0x0008)//有測量完成的 Frame
{
MLX90640_I2CRead(0x800D, 1, &controlRegister1); MLX90640_I2CWrite(0x8000, statusRegister&(~0x0018)); MLX90640_I2CRead(0x0400, 832, frameData); frameData[832] = controlRegister1;
frameData[833] = statusRegister & 0x0001; return 0;
}
Return -1;
}
至此移植完成
編譯工程,若沒有錯(cuò)誤提示則基本上沒有問題了,下一篇開始講述如何操作MLX90640。
MLX90640 紅外熱成像儀測溫模塊開發(fā)筆記(三)工作流程和操作MLX90640 的一般步驟
默認(rèn)參數(shù)時(shí)
MLX90640 的工作流程
(1) 上電,內(nèi)部初始化(約 40ms)
(2) 讀取工作參數(shù)到控制和狀態(tài)寄存器
(3) 開始以 2Hz 的速率測量實(shí)時(shí)數(shù)據(jù)并更新到 RAM,自動(dòng)更新狀態(tài)寄存器。
測量幀解釋
MLX90640 共有 768 個(gè)測量像素點(diǎn),每次測量其中的一半,稱為 1 幀,故此完成 768 像
素需要測量 2 幀,用幀 0 和幀 1 來表示。即:所謂的 1 幀數(shù)據(jù)其實(shí)是完整像素的一半。
可以修改的參數(shù)
可以修改的參數(shù)有以下幾個(gè)方面:
? 自動(dòng)測量:默認(rèn)為自動(dòng)測量,即自動(dòng)循環(huán)測量幀 0 和幀 1 更新到RAM 中。與其對(duì)應(yīng)的是手動(dòng)測量,即:用指令來控制測量幀 0 還是幀 1。手動(dòng)測量已經(jīng)在官方的數(shù)據(jù)手冊(cè)中被刪除,看來 MLX 也不喜歡別人用,所以我們也就別用了。自動(dòng)測量保持默認(rèn)值,不要改就好。
? 幀分布:前面已經(jīng)說了,1 幀實(shí)際上是測量完成了一半的像素點(diǎn),這一半像素有兩種分布模式,手冊(cè)上稱為 TV 模式和 Chess 模式,TV 模式以行為單位,是指每幀只測量奇數(shù)行或者偶數(shù)行,Chess 模式是指以像素為單位,每次交錯(cuò)著像素測 384 個(gè)像素點(diǎn)。我們可以稱之為“行交錯(cuò)模式”和“像素交錯(cuò)模式”。
在這方面,手冊(cè)上又說了,出廠時(shí)是以 Chess 模式校準(zhǔn)的,具有最好的精度(言下之意就是說如果修改為了 TV 模式時(shí)會(huì)不準(zhǔn)),鑒于此,這個(gè)參數(shù)也不要?jiǎng)印?br />
? 測量分辨率:可選的有 16~19 位 AD 轉(zhuǎn)換精度,默認(rèn)是 18 位,轉(zhuǎn)換位數(shù)當(dāng)然是越
高越好了,但 18 和 19 位經(jīng)過測試也沒有發(fā)現(xiàn)有什么實(shí)際區(qū)別,這個(gè)參數(shù)可改可不改。
? 測量速率:每秒測量幾幀數(shù)據(jù),這個(gè)參數(shù)很有用處,畢竟我們希望成像后是連續(xù)的
動(dòng)畫,每秒 2 次一定是不好的,我們可以調(diào)用 API 將這個(gè)參數(shù)修改為 8Hz 或者 16Hz 甚至 32Hz,64Hz 是不建議的,因?yàn)闇y量速率太快時(shí)噪聲特別大,圖像特別亂。普通相機(jī)的刷新速率也就 15Hz 左右,所以建議最高設(shè)置為 16Hz 吧。
所以,雖然數(shù)據(jù)手冊(cè)上寫的感覺好像可修改的參數(shù)挺多,這么一分析,其實(shí)只有 1 個(gè)測量速率是有用處的,其它都是浮云(雞肋)。
參數(shù)修改方法討論:
有兩種修改方法,修改寄存器和修改 EEPROM。
(1) 修改寄存器(推薦)
傳感器上電后會(huì)自動(dòng)從 EEPROM 讀取參數(shù)到寄存器,寄存器內(nèi)的參數(shù)值是運(yùn)行時(shí)實(shí)際執(zhí)行的參數(shù),直接通過 I2C 修改寄存器值即可,隨用隨改、立即生效。寄存器的值是掉電遺失的, 所以每次上電后都要修改一次。
(2) 修改 EEPROM
EEPROM 是掉電不丟失的,所以修改 EEPROM 內(nèi)的運(yùn)行參數(shù)只需要一次,下次啟動(dòng)生效。但
EEPROM 內(nèi)存儲(chǔ)的不僅只是同步到運(yùn)行寄存器的幾個(gè)參數(shù),大部分的是 768 個(gè)像素的校準(zhǔn)參數(shù),這些參數(shù)是出廠時(shí)寫入的,特別重要,所以我的建議還是不要對(duì) EEPROM 有任何的寫操作,以免發(fā)生意外,EEPROM 里的像素校正參數(shù)一旦被意外修改就再也找不回來了。
MLX90640 底層驅(qū)動(dòng)Keil 項(xiàng)目(STC 單片機(jī))下載
建議的操作流程
unsigned short EE[832]; unsigned short Frame[834]; paramsMLX90640 MLXPars; float Vdd,Ta,Tr;
float Temp[768];
IIC_Init(); //I2C 初始化
MLX90640_I2CInit(); //MLX 傳感器初始化
Delay_ms(50); //預(yù)留一點(diǎn)時(shí)間讓 MLX 傳感器完成自己的初始化
MLX90640_SetRefreshRate(0); //測量速率 1Hz(0~7 對(duì)應(yīng) 0.5,1,2,4,8,16,32,64Hz)
MLX90640_I2CRead(0x2400, 832, EE); //讀取像素校正參數(shù)MLX90640_ExtractParameters(EE, &MLXPars); //解析校正參數(shù)(計(jì)算溫度時(shí)需要)
while (1)
{
Delay_ms(5);
if (MLX90640_GetFrameData(Frame)==0) //有轉(zhuǎn)換完成的幀
{
Vdd=MLX90640_GetVdd(Frame, MLXPars); //計(jì)算 Vdd(這句可有可無) Ta=MLX90640_GetTa(Frame, MLXPars); //計(jì)算實(shí)時(shí)外殼溫度
Tr=Ta-8.0; //計(jì)算環(huán)境溫度用于溫度補(bǔ)償
//手冊(cè)上說的環(huán)境溫度可以用外殼溫度-8℃ MLX90640_CalculateTo(Frame, MLXPars, 0.95, Tr, Temp); //計(jì)算像素點(diǎn)溫度
/*
Temp 數(shù)組內(nèi)即是轉(zhuǎn)換完成的實(shí)時(shí)溫度值,單位℃
可以在這里對(duì)得到的 32*24=768 個(gè)溫度值進(jìn)行處理、轉(zhuǎn)換為顏色值、顯示關(guān)于溫度轉(zhuǎn)顏色方法,在后續(xù)的文章中會(huì)有專門介紹
*/
}
}
一點(diǎn)疑問
校正參數(shù)存儲(chǔ)于傳感器內(nèi)部的 EEPROM,實(shí)時(shí)數(shù)據(jù)也來自傳感器,如何利用實(shí)時(shí)數(shù)據(jù)和校正
參數(shù)計(jì)算溫度的方法也是事先規(guī)定好的,MLX 為什么不直接在內(nèi)部完成這個(gè)溫度計(jì)算讓用戶直接讀取溫度值?為了體現(xiàn)這個(gè)傳感器的復(fù)雜性或者是讓用戶有成就感嗎?
本來可以在傳感器內(nèi)部解決的問題被廠家要求在外部完成,對(duì) MCU 的性能要求是特別高的, 大量的浮點(diǎn)運(yùn)算,大量的RAM 消耗,較低的效率。
MLX90640 紅外熱成像儀測溫模塊開發(fā)筆記(四)損壞和不良像素的處理
如前“開發(fā)筆記(一)”所說,MLX90640 可能存在不超過 4 個(gè)像素的損壞或者不良像素,在溫度計(jì)算過程完成后,這些不良像素點(diǎn)會(huì)得到錯(cuò)誤的溫度數(shù)據(jù),對(duì)于處理這些不良數(shù)據(jù) MLX 也給出了推薦方法和具體的函數(shù)。(其實(shí)就是找相鄰的正常的溫度數(shù)據(jù)取平均來代替不良數(shù)據(jù))
前面開發(fā)筆記(一)的內(nèi)容中所說的 API 庫,里面缺少了對(duì)不良像素點(diǎn)的處理函數(shù),在這里補(bǔ)上。
int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2)
{
int pixPosDif;
pixPosDif = pix1 - pix2;
if(pixPosDif > -34 && pixPosDif < -30)
{
return -6;
}
if(pixPosDif > -2 && pixPosDif < 2)
{
return -6;
}
if(pixPosDif > 30 && pixPosDif < 34)
{
return -6;
}
return 0;
}
float GetMedian(float *values, int n)
{
float temp;
for(int i=0; i{
for(int j=i+1; j{
if(values[j] < values[i])
{
temp = values[i]; values[i] = values[j]; values[j] = temp;;>;>
}
}
if(n%2==0)
{
return ((values[n/2] + values[n/2 - 1]) / 2.0);
}
else
{
}
return values[n/2];
}
int IsPixelBad(uint16_t pixel,paramsMLX90640 *params)
{
for(int i=0; i<5; i++)
{
if(pixel == params->outlierPixels[i] || pixel == params->brokenPixels[i])
{
return 1;
}
}
return 0;
}
void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640
*params)
{
float ap[4]; uint8_t pix; uint8_t line; uint8_t column;
pix = 0;
while(pixels[pix] != 0xFFFF)
{
line = pixels[pix]>>5;
column = pixels[pix] - (line<<5);
if(mode == 1)
{
if(line == 0)
{
if(column == 0)
{
to[pixels[pix]] = to[33];
}
else if(column == 31)
{
}
else
{
}
}
to[pixels[pix]] = to[62];
to[pixels[pix]] = (to[pixels[pix]+31] + to[pixels[pix]+33])/2.0;
else if(line == 23)
{
if(column == 0)
{
to[pixels[pix]] = to[705];
}
else if(column == 31)
{
}
else
{
}
}
to[pixels[pix]] = to[734];
to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]-31])/2.0;
else if(column == 0)
{
to[pixels[pix]] = (to[pixels[pix]-31] + to[pixels[pix]+33])/2.0;
}
else if(column == 31)
{
}
else
{
to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]+31])/2.0;
ap[0] = to[pixels[pix]-33];
ap[1] = to[pixels[pix]-31]; ap[2] = to[pixels[pix]+31]; ap[3] = to[pixels[pix]+33];
to[pixels[pix]] = GetMedian(ap,4);
}
else
{
}
if(column == 0)
{
to[pixels[pix]] = to[pixels[pix]+1];
}
else if(column == 1 || column == 30)
{
to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0;
}
else if(column == 31)
{
}
else
{
0)
to[pixels[pix]] = to[pixels[pix]-1];
if(IsPixelBad(pixels[pix]-2,params) == 0 && IsPixelBad(pixels[pix]+2,params) ==
{
ap[0] = to[pixels[pix]+1] - to[pixels[pix]+2]; ap[1] = to[pixels[pix]-1] - to[pixels[pix]-2];
if(fabs(ap[0]) > fabs(ap[1]))
{
}
else
{
}
else
{
}
to[pixels[pix]] = to[pixels[pix]-1] + ap[1];
to[pixels[pix]] = to[pixels[pix]+1] + ap[0];
to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0;
}
}
}
pix = pix + 1;
}
}
用法很簡單,在開發(fā)筆記(三)MLX90640_CalculateTo(Frame, MLXPars, 0.95, Tr, Temp);之后添加兩行即可。如下(斜體是添加的內(nèi)容):
……
MLX90640_CalculateTo(Frame, MLXPars, 0.95, Tr, Temp); MLX90640_BadPixelsCorrection(MLXPars.brokenPixels, Temp, 1, MLXPars); MLX90640_BadPixelsCorrection(MLXPars.outlierPixels, Temp, 1, MLXPars);
……
/*
經(jīng)過上面的處理后,Temp 中的損壞和不良像素點(diǎn)已經(jīng)處理,Temp 數(shù)組中是處理完成后的
768 個(gè)溫度值。
*/
MLX90640 紅外熱成像儀測溫模塊開發(fā)筆記(五)陣列插值-由 32*24 像素到 512*384 像素
MLX90640 的 32*24=768 像素雖然比以往的 8*8 或者 16*8 像素提高了很多,但若直接用這些像素還是不能很好的形成熱像圖,為了使用這些像素點(diǎn)平滑成像就需要對(duì)其進(jìn)行插值,使用更多的像素來繪制圖像。
看了一些別人的算法,感覺主要就是多項(xiàng)式插值,僅是插值方法的組合方式不同。
算法依據(jù)
比較有代表性的是杭州電子科技大學(xué)楊風(fēng)健等《基于 MLX90620 的低成本紅外熱成像系統(tǒng)設(shè)計(jì)》,使用三次多項(xiàng)式+雙線性插值,將原 16*4 像素?cái)U(kuò)展為 256*64 像素。雙線性插值的本質(zhì)就是一次函數(shù)(一次多項(xiàng)式)。該文章得到的結(jié)論是:
(1) 雙線性插值法計(jì)算量小、速度快,但對(duì)比度低、細(xì)節(jié)模糊。
(2) 三次多項(xiàng)式插值,圖像效果較清晰,對(duì)比度較高,但計(jì)算量較大。
(3) 先雙線性插值再三次多項(xiàng)式插值,效果優(yōu)于上兩種單一插值方法。
(4) 先三次多項(xiàng)式插值再雙線性插值,高低溫分布更加明顯,圖像效果更接趨于真實(shí)。同時(shí),該文章還使用了一種對(duì)圖像質(zhì)量的評(píng)估方法---熵&平均梯度
熵,熱力學(xué)中表征物質(zhì)狀態(tài)的參量之一,用符號(hào) S 表示,其物理意義是體系混亂程度的度量。用于圖像評(píng)價(jià)表示圖像表達(dá)信息量的多少。圖像熵越高信息量越大。
平均梯度,指圖像的邊界或影線兩側(cè)附近灰度有明顯差異,即灰度變化率大,這種變化率的大小可用來表示圖像清晰度。它反映了圖像微小細(xì)節(jié)反差變化的速率,即圖像多維方向上密度變化的速率,表征圖像的相對(duì)清晰程度。值越大表示圖像越清晰。
插值實(shí)現(xiàn)
每行或者列的首個(gè)像素在前面插值 2 個(gè)點(diǎn) 1~n-1 像素,每個(gè)像素后面插值 3 個(gè)點(diǎn)最后一個(gè)像素,在后面插值 1 個(gè)點(diǎn) n+2+(n-1)*3+1=n+2+n*3-1*3+1=4n+2-3+1=4n,即:像素變?yōu)樵瓉淼?4 倍 上面的處理方法,首個(gè)像素之前插入 2 個(gè)點(diǎn),最后一個(gè)像素之后插入 1 個(gè)點(diǎn),下次插值時(shí),應(yīng)首個(gè)之前插值 1 個(gè)點(diǎn),末個(gè)像素之后插值 2 個(gè)點(diǎn),以達(dá)到圖像平衡。 每次插值后像素為插值前的 4 倍,經(jīng)過兩次插值,即可將 32*24 改變?yōu)?512*384 像素。下面是已經(jīng)實(shí)際使用的插值算法,不過是用 Pascal(Delphi)寫的,有興趣的可以改為C 語言的,語句對(duì)應(yīng)直接改就行,語言本來就是相通的嘛。
//這是一維數(shù)組插值算法
//SourceDatas:TDoubles;插值前的一維數(shù)組
//Dir:Integer;在哪個(gè)方向和末尾插入 2 個(gè)值(0:前面;1:末尾)
//times:Integer 多項(xiàng)式的項(xiàng)數(shù),一次多項(xiàng)式是 2 項(xiàng),二次多項(xiàng)式是 3 項(xiàng)
//返回值:插值后的一維數(shù)組(數(shù)量是插值前*4) function PolynomialInterpolationArr(
SourceDatas:TDoubles; Dir:Integer;
times:Integer):TDoubles;//一維數(shù)組插值
var
i,j,k:Integer;
arrCount:Integer;
MLX90640 紅外熱成像儀測溫傳感器模塊開發(fā)筆記(六)紅外圖像偽彩色編碼
什么是紅外成像偽彩編碼
紅外成像的最終目的是用圖像來表現(xiàn)溫度變化,并且可以通過顏色來區(qū)分出不同熱量的物體輪廓和形狀。那么,到底用什么顏色來表示什么溫度呢?是否有什么標(biāo)準(zhǔn)規(guī)范呢?
這個(gè)問題一開始也是心里沒底的,因?yàn)槲也皇菍I(yè)做紅外成像的,只能到處查資料了解溫度和顏色之間的關(guān)系,基本得到以下幾點(diǎn)結(jié)論:
(1)溫度和顏色之間沒有絕對(duì)的對(duì)應(yīng)關(guān)系,沒有人要求紅外成像必須要用什么顏色來表示某個(gè)溫度,這種對(duì)應(yīng)關(guān)系完全是由設(shè)計(jì)人員自已決定的。
(2)不同的應(yīng)用領(lǐng)域和行業(yè)出于不同的目的,會(huì)進(jìn)行一些溫度和顏色的研究,進(jìn)而用一種適用的漸變色來突出顯示某些特別關(guān)心的熱元素。
(3)顏色編碼絕大多數(shù)是漸變色。以下是幾種不同的顏色編碼
另外,還有人提出了“符合人的生理”讓人看著更加“舒服”的 HIS 彩色
溫度轉(zhuǎn)顏色的方法
(1)首先假設(shè)溫度范圍的上下限并將實(shí)際的溫度數(shù)據(jù)轉(zhuǎn)換為 0~255 之間的數(shù)值
(2)使用轉(zhuǎn)換后的數(shù)值代入下面的偽彩編碼計(jì)算函數(shù),生成偽彩色
//偽彩 1
procedure GrayToPseColor(grayValue:Integer; var colorR,colorG,colorB:Ingeger);
Begin
colorR:=Abs(0-grayValue);
colorG:=Abs(127-grayValue);
colorB:=Abs(255-grayValue);
End;
MLX90640 紅外熱成像儀測溫傳感器模塊開發(fā)筆記(七) 小結(jié)-注意事項(xiàng)
Red Eye Camera(以下簡稱“IDF-x” 或“設(shè)備” )是基于紅外陣列高精度溫度傳感器以及先進(jìn)軟件算法的非接觸式熱成像儀器,可對(duì)視場范圍內(nèi)任何物體進(jìn)行紅外成像,成像分辨率512*384 像素,溫度靈敏度 0.1℃,絕對(duì)精度±1.5℃,刷新頻率最高 64Hz。自帶存儲(chǔ)和實(shí)時(shí)時(shí)鐘,具備數(shù)據(jù)實(shí)時(shí)輸出顯示、拍照存儲(chǔ)功能,數(shù)字接口包括 UART 和 USB,可直接連接計(jì)算機(jī)和 Android 手機(jī),配合上位機(jī)軟件或者手機(jī) APP 程序,使用十分方便。
(1)硬件設(shè)計(jì)注意事項(xiàng)
電源: MLX90640 使用 3.3V 供電,并且使用供電電壓做為溫度測量的參考電壓來使用,所以對(duì)電源的要求比較高,盡量使用 LDO 穩(wěn)壓元件,并且 10uF 和 0.1uF 的退耦電容不能省,一定要靠近 VDD 管腳放置。電源電流沒太多要求,能夠平衡的輸出 100mA 就足夠。通訊: I2C的兩個(gè)管腳到MCU的距離不能過長(小于5CM吧),由于通訊速率可以1MHz,所以上拉電阻不能太大,推薦使用 1k~2k 的電阻。
(2)軟件設(shè)計(jì)注意事項(xiàng)
I2C 部分: 盡量使用已經(jīng)經(jīng)過驗(yàn)證的 I2C 驅(qū)動(dòng)程序,可以從其它項(xiàng)目中復(fù)制過來稍加改動(dòng),這部分是通訊的基礎(chǔ),一定要可靠。接口層: 主要是指讀和寫 MLX90640 的兩個(gè)函數(shù),可以先讀寫 MLX90640 的寄存器(地址 0x8000~0x8016) 對(duì)讀寫函數(shù)進(jìn)行驗(yàn)證。計(jì)算層: 這部分就直接用 API 庫中的對(duì)應(yīng)函數(shù)就可以,基本不會(huì)有問題。
(3)數(shù)據(jù)正確性驗(yàn)證
在操作過程中必須注意解算出的 Vdd 的值,如果這個(gè)值與實(shí)際值相差超過 0.1V 就應(yīng)該檢查問題。
(4)水平方向問題
如果鏡頭向前, MLX90640 的像素排列規(guī)則是從右向左(和我們的習(xí)慣相反),即:有點(diǎn)像手機(jī)的自拍攝像頭,圖像會(huì)是左右顛倒的,在成圖之前記得把每行的像素前后顛倒一下,再顯示就對(duì)了
MLX90640 紅外熱成像儀測溫傳感器模塊開發(fā)筆記(八)擴(kuò)展知識(shí)-輻射率、靈敏度、精度、探測距離
輻射率
是描述面輻射源特性的物理量。它表示某物體的單位面積輻射的熱量和黑體在相同溫度、相同條件下的輻射熱量之比。即:輻射率通俗地說就是某物體會(huì)將自身溫度轉(zhuǎn)換為輻射擴(kuò)散出去的能力, 1 表示可以將自身溫度轉(zhuǎn)換為 100%的輻射, 0.9 表示可以降低自身溫度的 90%轉(zhuǎn)換為熱輻射擴(kuò)散出去。實(shí)際上輻射率為 1 的物質(zhì)(黑體)是不存在的,所以任何材料的輻射率均是 0~1 之間的數(shù)值。
任何物體在高于絕對(duì)零度(-273.15℃)的時(shí)候,其物體表面就會(huì)有紅外能量也就是紅外線發(fā)射出來,溫度越高,發(fā)射的紅外能量越強(qiáng)。紅外線測溫儀和紅外熱像儀就是根據(jù)這個(gè)特點(diǎn)來測量物體表面的溫度的,因?yàn)榧t外線測溫儀和紅外熱像儀是測量物體表面的溫度的,所以在測量時(shí)會(huì)被物體表面的光潔度所影響。實(shí)驗(yàn)證明:物體表面越接近于鏡面(反射越強(qiáng)),其表面所發(fā)出的紅外能量衰減越厲害,就需要對(duì)不同物體的表面對(duì)紅外能量的衰減情況做出補(bǔ)償,即設(shè)置一個(gè)補(bǔ)償系數(shù),這個(gè)補(bǔ)償系數(shù)就是輻射率。
不同材料的輻射率差別還是很大的,比如人體是 0.95~0.98,而光滑的不銹鋼是 0.16,生銹的鐵是 0.65 左右,當(dāng)探測過程中想要得到較為準(zhǔn)確的溫度值時(shí),就需要設(shè)置被探測物體的輻射系數(shù)。(若僅是為了成像則無需這么嚴(yán)格)
靈敏度與溫度探測精度
噪聲等效溫差(NETD) 是指紅外探測器能探測到的最小溫差,即:當(dāng)被測物體的溫度變化多少時(shí)紅外探測器可以探測出來。衡量紅外探測器性能的主要指標(biāo)之一。
熱探測器的噪聲等效溫差在 100mK 左右(0.1℃)。第二代光探測器在 20mK 左右(0.02℃)。第三代探測器目標(biāo)是在 1mK(0.001℃)。
紅外探測計(jì)算出的絕對(duì)溫度值與被測物體的輻射率參數(shù)有直接關(guān)系,不同材料的輻射率值是不同的,更為嚴(yán)重的是即便是同種材料,表面光潔度、含水率、溫度高低等因素的影響也會(huì)直接改變輻射率,這就導(dǎo)致了紅外探測絕對(duì)溫度無法絕對(duì)準(zhǔn)確,問題不在于紅外探測器的對(duì)輻射量的感知準(zhǔn)確度而在于材料的輻射率是隨時(shí)在小范圍變化的。所以,衡量紅外探測器的性能指標(biāo)一般不能用絕對(duì)溫度,而應(yīng)該用溫度靈敏度,即: 噪聲等效溫差(NETD)。這也可以得出一個(gè)結(jié)論,紅外熱成像儀的主要作用是盡量區(qū)分出不同區(qū)域的溫度差異,用數(shù)字表現(xiàn)出來,進(jìn)而展示為帶有顏色的圖像,只有溫度區(qū)分開以后,圖像才會(huì)細(xì)致分明。
紅外探測距離
紅外熱成像儀是用光學(xué)鏡頭來收集被測物體的熱輻射能量的,故此探測距離會(huì)受到鏡頭視場角和熱成像像素分辨率有關(guān)。假如某成像儀的成像分辨率為 32*32 像素,視場角為 75 度,則可以理解為從鏡頭里發(fā)射出 32*32=1024 條激光來探測 1024 個(gè)點(diǎn)的溫度(32 行*32 列), 每行 32 個(gè)點(diǎn),每列 32 個(gè)點(diǎn)。每相鄰兩條激光線的夾角為 75/31=2.4193°發(fā)散出去。隨著距離的增長,兩條激光線的間距會(huì)變大,當(dāng)被測物體足夠小時(shí),有可能處于兩條激光線之間未被探測到,這就是探測距離的問題。
即:當(dāng)成像儀的像素?cái)?shù)量和視場角一定時(shí),它的有效探測距離就與被測物體的大小有關(guān)。當(dāng)被測物體尺寸已知時(shí),對(duì)其進(jìn)行探測的理論最遠(yuǎn)距離為:
MLX90640 紅外熱成像儀測溫傳感器模塊開發(fā)筆記(九) EEPROM、 RAM、寄存器說明
EEPROM
地址范圍為 0x2400~0x273F,共 832 個(gè)字(1664 字節(jié)), 前 16 個(gè)字包含了唯一 ID 碼、工作參數(shù)(上電后自動(dòng)同步到寄存器)、 MLX90640 的 I2C 地址。后面的 816 個(gè)字全部是每個(gè)像素的校正或者測量參數(shù),數(shù)據(jù)手冊(cè)也沒有寫每個(gè)數(shù)據(jù)到底是什么意思,直接用就是了,不要問為什么。
RAM
地址范圍為 0x0400~0x073F,共 832 個(gè)字(1664 字節(jié)),前 768 個(gè)字是實(shí)時(shí)的 768 像素的測量數(shù)據(jù),后面 64 個(gè)字是與當(dāng)前剛剛測量完成的一半像素有關(guān)的計(jì)算因數(shù)。 RAM 是只讀的。
寄存器
地址范圍為 0x8000~0x8010,共 16 個(gè)字(32 字節(jié)),其中用戶可以訪問的有狀態(tài)寄存器0x8000、控制寄存器 0x800D,改變控制寄存器可以直接控制 MLX90640 的運(yùn)行行為,是既有讀又有寫的部分。
三部分建議的操作
上電后讀取一下 EEPROM,扔給 API 函數(shù) MLX90640_ExtractParameters 得到的參數(shù)項(xiàng)變量。根據(jù)需要修改控制寄存器的值。循環(huán)讀取狀態(tài)寄存器,當(dāng)有新的數(shù)據(jù)測量完成時(shí)讀取全部 RAM 扔給 API 函數(shù)MLX90640_CalculateTo 得到每個(gè)像素的溫度值。
狀態(tài)寄存器說明
狀態(tài)寄存器從字面來理解應(yīng)該是只讀的,但數(shù)據(jù)手冊(cè)里卻定義了一些位是參數(shù)(可修改的),不管寄存器叫什么了,根據(jù)參數(shù)功能來用吧。
STA[15:5]:保留,只能寫入 0STA[4]: RAM 是否可寫, 0:不可寫; 1:可寫。在幀測量完成后,是否允許 MLX90640將測量的數(shù)據(jù)寫入(更新)到 RAM 里,這個(gè)功能可以在讀取一幀數(shù)據(jù)的過程中設(shè)置為不允許,即:當(dāng)上位機(jī)正在讀取 RAM 的過程中,不允許再更新 RAM。這個(gè)位置同時(shí)還受控制寄存器中的 bit2 的限制,當(dāng) CTR[2]=0 時(shí),無論這個(gè)位置怎樣設(shè)置,都會(huì)自動(dòng)更新 RAM,僅當(dāng) CTR[2]=1時(shí), STA[4]參數(shù)才會(huì)起作用。STA[3]:子頁測量完成標(biāo)志位。 0:表示沒有完成; 1 表示已經(jīng)完成了一幀的測量。STA[2:0]:剛剛完成的是幀 0 還是幀 1。
控制寄存器說明
CTR[15:13]:保留,只能寫入 0
CTR[12]:幀交錯(cuò)模式,默認(rèn)為 1(像素交錯(cuò)模式),數(shù)據(jù)手冊(cè)上說了只有這種模式才能保證精度,那就不要改這一位,保持默認(rèn) 1。
CTR[11:10]:測量精度, 00~11 表示 16 位~19 位,默認(rèn)為 10(18 位)。改成 11 也沒什么效果,所以這個(gè)參數(shù)也保持默認(rèn)吧。
CTR[9:7]:設(shè)置測量速率, 0~7 表示 0.5、 1、 2、 4、 8、 16、 32、 64Hz,默認(rèn)為 010(2Hz),這個(gè)參數(shù)是唯一有用的參數(shù)。
CTR[6:4]:手動(dòng)測量時(shí),指定要測量哪個(gè)子頁(幀 0 還是幀 1)。數(shù)據(jù)手冊(cè)已經(jīng)把手動(dòng)測量部分刪除了,所以手動(dòng)測量相關(guān)的參數(shù)可以忽略。
CTR[3]:手動(dòng)測量還是自動(dòng)測量,默認(rèn)為 0(自動(dòng)測量),不要使用手動(dòng)測量(原因同上)。
CTR[2]:如何更新 RAM。 0:測量完成后自動(dòng)更新; 1:根據(jù) STA[4]參數(shù)。
CTR[1]:保留,只能寫入 0。
CTR[0]: 0:所有數(shù)據(jù)更新在一頁里; 1:使能子頁模式(頁 0 和頁 1),默認(rèn)
MLX90640 紅外熱成像儀測溫傳感器模塊開發(fā)筆記(十) 成果展示-紅眼睛相機(jī)
現(xiàn)在自己在做紅外成像儀的越來越多了,兩年前有個(gè)井下機(jī)電設(shè)備運(yùn)行狀態(tài)的科研項(xiàng)目,當(dāng)時(shí)使用了 AMG8833(8*8 像素),科研畢竟就是科研,后來也沒有聽說成果得到應(yīng)用的消息, 我想也是, 8*8 能干什么,也就能做個(gè)紅外測溫槍吧。 前段時(shí)間因?yàn)楣旧a(chǎn)電路板測試需要,打算買一臺(tái)紅外成像儀測量電路板發(fā)熱是否正常,商用的價(jià)格還是有些小貴的,我們電路板都不大所以就找了一臺(tái)便宜的先用著,無意中發(fā)現(xiàn)了 MLX90640 這個(gè)東西, 32*24像素, 768 個(gè)測溫點(diǎn),基本上可以成像用了。
現(xiàn)在都智能手機(jī)、信息化、人工智能了,能不能用 MLX90640 做個(gè)能和手機(jī)連接成像的紅外模塊呢,那樣的話測試、存儲(chǔ)豈不是很方便。 說做就做,馬上行動(dòng)。
最終的成果是一個(gè)微型的 USB 接口紅外成像模塊(微型紅外成像儀 30*30mm),可以連接到 Android 手機(jī)或者計(jì)算機(jī)的 USB 接口,實(shí)時(shí)顯示熱像視頻,和手機(jī)相機(jī)差不多,只不過它是熱紅外成像,所以叫“紅眼睛相機(jī)”。模塊圖片如下:
Red Eye Camera(以下簡稱“IDF-x” 或“設(shè)備” )是基于紅外陣列高精度溫度傳感器以及先進(jìn)軟件算法的非接觸式熱成像儀器,可對(duì)視場范圍內(nèi)任何物體進(jìn)行紅外成像,成像分辨率512*384 像素,溫度靈敏度 0.1℃,絕對(duì)精度±1.5℃,刷新頻率最高 64Hz。自帶存儲(chǔ)和實(shí)時(shí)時(shí)鐘,具備數(shù)據(jù)實(shí)時(shí)輸出顯示、拍照存儲(chǔ)功能,數(shù)字接口包括 UART 和 USB,可直接連接計(jì)算機(jī)和 Android 手機(jī),配合上位機(jī)軟件或者手機(jī) APP 程序,使用十分方便。
優(yōu)勢與特點(diǎn)
可 USB 接口供電,即插即用。
多種濾波方法,參數(shù)自由設(shè)置。
多種顏色方案,滿足不同需求。
高斯濾波,保留原始信息不畸變。
應(yīng)用領(lǐng)域:安防生物識(shí)別,發(fā)熱檢測,水暖電施工,故障排查,空調(diào)熱度檢測,安檢通道等。
河北穩(wěn)控科技MLX90640 紅外熱成像儀應(yīng)用領(lǐng)域
關(guān)于 MLX90640 的文章暫時(shí)先寫這么多,文章中的各種資料、程序、產(chǎn)品,均可通過網(wǎng)址獲取。
審核編輯 黃昊宇
-
紅外熱成像儀
+關(guān)注
關(guān)注
1文章
111瀏覽量
14898 -
熱成像
+關(guān)注
關(guān)注
3文章
360瀏覽量
20344 -
測溫傳感器
+關(guān)注
關(guān)注
0文章
40瀏覽量
7077 -
開發(fā)模型
+關(guān)注
關(guān)注
0文章
2瀏覽量
1930
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論