Infrared Thermal Imaging Camera
Infrared Thermal Imaging Camera
Infrared Thermal Imaging Camera
PRESENTED BY:
Ali Riyadh, Abbas Shyal, & Essam Ramadan
2ND STAGE (EVENING STUDY)
DR. OMAR YOUSSEF
TABLE OF CONTENTS:
INTRODUCTION…………………………………………….2-5
MLX90640……………………………………………………….5-7
PARTS …………………………………………………....…….7 -8
VISUALIZATION ……………………………………11-12
CODE……………………………………………….…………15-18
1|Page
INFRARED THERMAL IMAGING CAMERA
INTRODUCTION:
2|Page
16x16 pixels. There are many applications of these sensors in
In the same time, having a real time infrared array sensor for
3|Page
the same sensor to be used for monitoring the state of objects
inside, thus being useful for the smart home automation and
off the stove or iron. If such scenario has occurred the system
4|Page
smart systems in home environment. It is designed as an IoT
chip and supply sensor to measure the VDD. The outputs of all
5|Page
sensors IR, Ta and VDD are stored in internal RAM and are
development of our IoT solution with its wide field of view (it
has two options for field of view - 55°x35° and 110°x75°) and
6|Page
selection of this sensor to be used in development of solutions
1-Melexis MLX90640
2-ESP32
4-DuPont wire
7|Page
You can get the MLX90640 for example from sparkfun. There
card-slot but for the thermal imaging camera you just need the
Here you can find the Arduino-code from sparkfun for the
MLX90640:
https://github.com/sparkfun/SparkFun_MLX90640_Ardu...
8|Page
I tried to run the code with an Arduino Due but I didn't succeed.
In the web I found several threads from other users who had
Module".
The ILI9341
library: https://github.com/adafruit/Adafruit_ILI9341
GFX-Library
9|Page
value at the position 0x800D has to be 1901 (HEX) = 6401
code. Another hint was very useful: You must add the
file MLX90640_I2C_Driver.cpp!
10 | P a g e
Now you should get reasonable values from the MLX90640-
will be:
mlx90640To[1*32 + 22]);
But this only works when the faulty pixel isn't exactly located
11 | P a g e
those you know from the company flir. below you can see a test
12 | P a g e
COMPLETE CIRCUIT, CODE AND RESULTS:
with the ESP32 (look at the picture and code added). During the
display.
13 | P a g e
regulator will get too hot. At the moment I'm just waiting for
14 | P a g e
Code:
15 | P a g e
//Set rate to 0.25Hz tft.setRotation(1); _address,
effective - Works tft.setCursor(80, mlx90640Frame);
220);
//MLX90640_SetRe tft.fillScreen(ILI934 if (status < 0)
freshRate(MLX906 1_BLACK); tft.setTextColor(ILI9 {
40_address, 0x01); tft.fillRect(0, 0, 341_WHITE,
//Set rate to 0.5Hz 319, 13, tft.color565(0, 0, Serial.print("GetFra
effective - Works tft.color565(255, 0, 0)); me Error: ");
10)); tft.print("T+ = ");
//MLX90640_SetRe Serial.println(status
freshRate(MLX906 tft.setCursor(100, );
40_address, 0x02); 3); // drawing the }
//Set rate to 1Hz colour-scale
effective - Works tft.setTextSize(1); // float vdd =
=============== MLX90640_GetVdd
//MLX90640_SetRe tft.setTextColor(ILI9 ========= (mlx90640Frame,
freshRate(MLX906 341_YELLOW, &mlx90640);
40_address, 0x03); tft.color565(255, 0, for (i = 0; i < 181; float Ta =
//Set rate to 2Hz 10)); i++) MLX90640_GetTa(
effective - Works { mlx90640Frame,
tft.print("Thermogra //value = &mlx90640);
MLX90640_SetRefr phie - stoppi"); random(180);
eshRate(MLX9064 float tr = Ta -
0_address, 0x04); tft.drawLine(250, getColour(i); TA_SHIFT;
//Set rate to 4Hz 210 - 0, 258, 210 - //Reflected
effective - Works 0, tft.color565(255, tft.drawLine(240, temperature based
255, 255)); 210 - i, 250, 210 - i, on the sensor
//MLX90640_SetRe tft.drawLine(250, tft.color565(R_colo ambient
freshRate(MLX906 210 - 30, 258, 210 - ur, G_colour, temperature
40_address, 0x05); 30, B_colour)); float emissivity
//Set rate to 8Hz tft.color565(255, } = 0.95;
effective - Works at 255, 255));
800kHz tft.drawLine(250, }
210 - 60, 258, 210 - MLX90640_Calcula
//MLX90640_SetRe 60, teTo(mlx90640Fra
freshRate(MLX906 tft.color565(255, me, &mlx90640,
40_address, 0x06); 255, 255)); // emissivity, tr,
//Set rate to 16Hz tft.drawLine(250, ********************** mlx90640To);
effective - Works at 210 - 90, 258, 210 - ************ }
800kHz 90, // **************
tft.color565(255, LOOP **************
//MLX90640_SetRe 255, 255)); // // determine
freshRate(MLX906 tft.drawLine(250, ********************** T_min and T_max
40_address, 0x07); 210 - 120, 258, 210 ************ and eliminate error
//Set rate to 32Hz - 120, pixels
effective - fails tft.color565(255, void loop() //
255, 255)); { ===============
tft.drawLine(250, for (byte x = 0 ; x ===============
210 - 150, 258, 210 < 2 ; x++) //Read ===============
pinMode(TFT_LED, - 150, both subpages =======
OUTPUT); tft.color565(255, {
255, 255)); uint16_t
digitalWrite(TFT_L tft.drawLine(250, mlx90640Frame[83 mlx90640To[1*32 +
ED, HIGH); 210 - 180, 258, 210 4]; 21] = 0.5 *
- 180, int status = (mlx90640To[1*32
tft.begin(); tft.color565(255, MLX90640_GetFra + 20] +
255, 255)); meData(MLX90640 mlx90640To[1*32 +
1|Page
22]); // eliminate // ===== determine
the error-pixels // determine tft.fillRect(260, the colour ====
T_center 25, 37, 10, //
mlx90640To[4*32 + // tft.color565(0, 0, ===============
30] = 0.5 * =============== 0)); ===============
(mlx90640To[4*32 === tft.fillRect(260, =
+ 29] + 205, 37, 10,
mlx90640To[4*32 + T_center = tft.color565(0, 0, void getColour(int j)
31]); // eliminate mlx90640To[11* 32 0)); {
the error-pixels + 15]; tft.fillRect(115, if (j >= 0 && j <
220, 37, 10, 30)
T_min = // drawing the tft.color565(0, 0, {
mlx90640To[0]; picture 0)); R_colour = 0;
T_max = // G_colour = 0;
mlx90640To[0]; =============== B_colour = 20
==== tft.setTextColor(ILI9 + (120.0/30.0) * j;
for (i = 1; i < 768; 341_WHITE, }
i++) for (i = 0 ; i < 24 ; tft.color565(0, 0,
{ i++) 0)); if (j >= 30 && j <
{ 60)
if((mlx90640To[i] > - for (j = 0; j < tft.setCursor(265, {
41) && 32; j++) 25); R_colour =
(mlx90640To[i] < { tft.print(T_max, (120.0 / 30) * (j -
301)) 1); 30.0);
{ mlx90640To[i*32 + G_colour = 0;
j] = 180.0 * tft.setCursor(265, B_colour =
if(mlx90640To[i] < (mlx90640To[i*32 + 205); 140 - (60.0/30.0) * (j
T_min) j] - T_min) / (T_max tft.print(T_min, - 30.0);
{ - T_min); 1); }
T_min =
mlx90640To[i]; tft.setCursor(120, if (j >= 60 && j <
} getColour(mlx9064 220); 90)
0To[i*32 + j]); tft.print(T_center, {
1); R_colour =
if(mlx90640To[i] > 120 + (135.0/30.0) *
T_max) tft.fillRect(217 - j * 7, (j - 60.0);
{ 35 + i * 7, 7, 7, tft.setCursor(300, G_colour = 0;
T_max = tft.color565(R_colo 25); B_colour = 80
mlx90640To[i]; ur, G_colour, tft.print("C"); - (70.0/30.0) * (j -
} B_colour)); 60.0);
} } tft.setCursor(300, }
else if(i > 0) // } 205);
temperature out of tft.print("C"); if (j >= 90 && j <
range tft.drawLine(217 120)
{ - 15*7 + 3.5 - 5, tft.setCursor(155, {
11*7 + 35 + 3.5, 217 220); R_colour =
mlx90640To[i] = - 15*7 + 3.5 + 5, tft.print("C"); 255;
mlx90640To[i-1]; 11*7 + 35 + 3.5, G_colour = 0 +
} tft.color565(255, delay(20); (60.0/30.0) * (j -
else 255, 255)); } 90.0);
{ tft.drawLine(217 B_colour = 10
- 15*7 + 3.5, 11*7 + - (10.0/30.0) * (j -
mlx90640To[i] = 35 + 3.5 - 5, 217 - 90.0);
mlx90640To[i+1]; 15*7 + 3.5, 11*7 + // }
} 35 + 3.5 + 5, ===============
} tft.color565(255, =============== if (j >= 120 && j <
255, 255)); = 150)
2|Page
{ R_colour =
R_colour = 255; //Returns true if the if
255; G_colour = MLX90640 is (Wire.endTransmis
G_colour = 60 235 + (20.0/30.0) * detected on the I2C sion() != 0)
+ (175.0/30.0) * (j - (j - 150.0); bus return (false);
120.0); B_colour = 0 + boolean //Sensor did not
B_colour = 0; 255.0/30.0 * (j - isConnected() ACK
} 150.0); {
} return (true);
if (j >= 150 && j Wire.beginTransmi }
<= 180) } ssion((uint8_t)MLX
{ 90640_address);
3|Page
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: