DIY a Thermal Imaging Monitor

DIY a Thermal Imaging Monitor

January 06, 2022

DIY-a-Therma-Imaging-Monitor
In this article, I will DIY a thermal imaging monitor using the ESP32-S2 parallel TFT touch screen and the MLX90640 Thermal imaging camera.

It has been a long time since I want to make a thermal imaging monitor in the epidemic for our office. But the array thermal sensor was once very expensive in 2020, as there are huge demands in the COVID-19, that I have to pause my plan, and until recently, I have the chance to do this. Of course, it is good to buy one from the market, but the price is expensive, and actually not so good as my design. Open source both on hardware& firmware.

1. What I used for this?

● The parallel TFT Touch based on ESP32-S2, with resolution 320*240:
ESP32-S2-3_5-Inch-Parallel-DisplayESP32-S2-3_5-Inch-Parallel-Display-1
The reason I use this touch is that:
1.) It has a much higher refresh rate than the SPI display, check the comparison video.
2.) Based on ESP32-S2, with WIFi, so it can directly transmit the data/result to the local network, for remote monitoring.

● And the MLX90640 Thermal imaging camera, which is I designed especially for this application.
Makerfabs-MLX90460
● And a set of acrylic case designed for this, with laser cutting:
Custom-Acrylic-Case

2. Hardware assembly

The Thermal camera use I2C for communication with controllers, with I2C address 0x33, while The ESP32-S2 Parallel TFT has build-on connectors(I2C/GPIO) for external sensors, so it gets very easy to connect the Thermal camera to the TFT, by simple plug-n-play cable:
Makerfabs-DIY-Thermal-Imager-Cable-Connect

Insert an SD card into the SD slot for data storing:
Makerfabs-DIY-Thermal-Imager-SD-Card-Install

3. Firmware:

Firmware is core work for this application, for the MLX90640, I used the Adfruit_MLX90640 Lib. Besides, as the raw data MLX90640 get is 32*24 data, with noises, that we need to deal with it more with:

a. Filter the data, to make them smooth for display, or the display will be harsh.
b. Check out the highest temperature among all the raw data. Normally, the highest temperature points it what we are interested in, which tells us if a man is in good/ bad health.
c. Linear Interpolation Algorithm of raw data, to make it not so-pixel looking, and suitable for display (I make it displayed in 320x240 area, 50% area of the display).

1. Filter the temperature data:
Void filter_frame(float *in, float *out)
{
    if (MLX_MIRROR == 1)
    {
        for (int i = 0; i < 32 * 24; i++)
        {
            out[i] = (out[i] + in[i]) / 2;
        }
    }
    else
    {
        for (int i = 0; i < 24; i++)
            for (int j = 0; j < 32; j++)
            {
                out[32 * i + 31 - j] = (out[32 * i + 31 - j] + in[32 * i + j]) / 2;
            }
    }
}
In the filter, the temperature final output was averaged by the input, and thus to create stable& smooth output;

The contrast of output without/ with the filter:
Without-FilterWith-Filter

2. Quick sorting out of the temperature, to find out the highest temperature point, and store it at frame[767]:
void qusort(float s[], int start, int end)
{
    int i, j;        
    i = start;       
    j = end;         
    s[0] = s[start];
    while (i < j)
    {
        while (i < j && s[0] < s[j])
            j--;
        if (i < j)
        {
            s[i] = s[j];
            i++;         
        }
        while (i < j && s[i] <= s[0])
            i++;
        if (i < j)
        {
            s[j] = s[i];
            j--;         
        }
    }
    s[i] = s[0];
    if (start < i)
        qusort(s, start, j - 1);
    if (i < end)
        qusort(s, j + 1, end);
}
3. Linear Interpolation Algorithm of the raw data, to make it better for display, and suitable for the 320x240 display area:
//Transform 32*24 to 320 * 240 pixel
void interpolation(float *data, uint16_t *out)
{


    for (uint8_t h = 0; h < 24; h++)
    {
        for (uint8_t w = 0; w < 32; w++)
        {
            out[h * 10 * 320 + w * 10] = map_f(data[h * 32 + w], MINTEMP, MAXTEMP);
        }
    }
    for (int h = 0; h < 240; h += 10)
    {
        for (int w = 1; w < 310; w += 10)
        {
            for (int i = 0; i < 9; i++)
            {
                out[h * 320 + w + i] = (out[h * 320 + w - 1] * (9 - i) + out[h * 320 + w + 9] * (i + 1)) / 10;
            }
        }
        for (int i = 0; i < 9; i++)
        {
            out[h * 320 + 311 + i] = out[h * 320 + 310];
        }
    }
    for (int w = 0; w < 320; w++)
    {
        for (int h = 1; h < 230; h += 10)
        {
            for (int i = 0; i < 9; i++)
            {
                out[(h + i) * 320 + w] = (out[(h - 1) * 320 + w] * (9 - i) + out[(h + 9) * 320 + w] * (i + 1)) / 10;
            }
        }
        for (int i = 0; i < 9; i++)
        {
            out[(231 + i) * 320 + w] = out[230 * 320 + w];
        }
    }
    for (int h = 0; h < 240; h++)
    {
        for (int w = 0; w < 320; w++)
        {
            out[h * 320 + w] = camColors[out[h * 320 + w]];
        }
    }
}
The contrast of output without/ with the Linear Interpolation Algorithm:
Without-the-Linear-Interpolation-AlgorithmWith-Linear-Interpolation-Algorithm

The code is available at: Makerfabs Github.

4. Test and Result

After programming, power the system with 5V power by USB-type C, the display works OK, and the temperature detects:
Thermal-Imaging-Monitor-32-CelsiusTest-32-Celsius

Thermal-Imaging-Monitor-40-CelsiusTest-40-Celsius

Thermal-Imaging-Monitor-55-CelsiusTest-55-Celsius

There all the temperatures can be stored on the SD card for storing.
Data-Stored-on-SD-Card

Besides, as the ESP32 WIFI, all the data& pictures can be displayed& stored in local network PC or smartphone, there I made a simple temperature display with Python:
Temperature-Display-with-Python-Program

If you have further questions for this application about How to DIY a Thermal Imaging Monitor, or need some custom PCB assembly service, please contact service@makerfabs.com.heart

Contact us