Wednesday, November 1, 2023

MLX90640 and ESP32 Thermal Imaging Camera with 2.8" TFT SPI

I decided to update my old thermal imaging camera.  Back in 2020 I had built a AMG8833 based camera.  Its resolution was only 8x8 pixels.  The MLX90640 is 32x24 pixels, that is a huge improvement for about $40.  I was hoping that I could just unplug the one sensor and plug in the new one.  Things are never that simple!  

This is a picture of the completed project.  The camera does not do a good job.  I tried multiple cameras and they all fail to show the varying shades of colors!  BTW that is me holding the camera.

This is a picture from the blog post about the AMG8833:

For several hours I tried to get the module to work.  When using a I2C scanner I got various responses back for several addresses.  Eventually I discovered that if I powered down then up the module I would get the correct I2C address aback (0x033) but it still would not work with the Adafruit MLX90640_Simpletest example program. Then I realized that the module I have has an extra IC on it. I had ordered a MLX90640 module on eBay for a little over $40.  Eventually I discovered that on the back it says GY-MCU90640 and looked up the manual for that module.
The manual is as clear as mud.  However I was able to guess that I needed to jumper the two solder pads together to get the I2C mode to work properly. Without that jumper it is configured for serial communication.

I could not get the sparkfun MLX90640 library to load or run.  That was desired to be able to use some software already available on the web. So I was stuck with the Adafruit library that was easily installed within the Arduino IDE.  But I had to write my own interface for the LCD screen.  Then I added the screen support to the simpletest program instead of sending the results to the serial port.  Make sure you also install the ILI9341 driver within the Arduino IDE.

3.3V=VCC,RES,LED (Jumpered on display)


Here is my code:

#include <Adafruit_MLX90640.h>

#include "Adafruit_GFX.h"

#include "Adafruit_ILI9341.h"

#include "SPI.h"


// Use the default pins for all but:

#define TFT_CS    5 

#define TFT_DC   26

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

Adafruit_MLX90640 mlx;

float frame[32*24]; // buffer for full frame of temperatures

int r,g,b;

void setup() {



  if (! mlx.begin(MLX90640_I2CADDR_DEFAULT, &Wire)) {

    Serial.println("MLX90640 not found!");

    while (1) delay(10);


  Serial.println("Found Adafruit MLX90640");

  Serial.print("Serial number: ");

  Serial.print(mlx.serialNumber[0], HEX);

  Serial.print(mlx.serialNumber[1], HEX);

  Serial.println(mlx.serialNumber[2], HEX);





  // Screen setup       






void loop() {

  if (mlx.getFrame(frame) != 0) {


    return;  }

    // determine the ranges

    int maxt=0;

    int mint=255;

    for (uint8_t h = 0; h < 24; h++) {

      for (uint8_t w = 0; w < 32; w++) {

        int t = frame[h*32 + w];             

        if (t > maxt) maxt=t ;

        if (t < mint) mint=t ;



    tft.setCursor(0, 210);

    tft.print("IR Camera Max Temp: "); 

    tft.fillRect(230, 210, 32, 16, ILI9341_BLACK );

    tft.setCursor(230, 210);


    // drawing the picture

    for (uint8_t h = 0; h < 24; h++) {

      for (uint8_t w = 0; w < 32; w++) {

        int t = frame[h*32 + w]; 

        r=0; g=0; b=0;

        int t2= map(t, mint, maxt, 0, 255);

        if (t2 > 70) r = t2+120;

        if (r > 255) r=255;

        if (t2 > 130) g = t2; // Highlight higher temps

        if (t2 < 70) b = 255-t2; // More blue=colder

        tft.fillRect(w * 8, h * 8, 8, 8, tft.color565(r, g, b));




Here are several views of the completed wiring if you need something to compare yours to.

No comments: