The Direct Answer: Which IR Sensor and Board to Use
If you are building an IR camera Arduino project in 2026, the Melexis MLX90640 (32x24 resolution) paired with an Arduino Uno R4 Minima is the optimal hardware combination. The legacy Arduino Uno R3 (ATmega328P) lacks the SRAM required to buffer a 768-pixel float array, leading to immediate memory crashes. The Uno R4 Minima uses a Renesas RA4M1 ARM Cortex-M4 with 32KB of SRAM and a 48MHz clock, easily handling the I2C throughput and memory demands of real-time thermal rendering.
Thermal Sensor Showdown: Data-Sheet Comparison
Before ordering parts, you need to understand the trade-offs between the three most common microcontroller-compatible thermal arrays. The table below compares real-world specifications that affect your microcontroller selection and I2C bus design.
| Specification | Panasonic AMG8833 (Grid-EYE) | Melexis MLX90640 | FLIR Lepton 3.5 |
|---|---|---|---|
| Resolution | 8 x 8 (64 pixels) | 32 x 24 (768 pixels) | 160 x 120 (19,200 pixels) |
| Interface | I2C (up to 1MHz) | I2C (up to 1MHz, requires clock stretching) | SPI (with I2C CCI for telemetry) |
| SRAM Required | ~256 bytes | ~4,600 bytes | ~40,000+ bytes (Needs ESP32/Teensy) |
| Max Frame Rate | 10 Hz | 64 Hz (at 16-bit), 4 Hz (at 18-bit) | 8.7 Hz |
| Typical 2026 Price | $40 - $50 | $45 - $60 | $200 - $250 |
Source: Melexis MLX90640 Datasheet
Parts List and Pin Mapping
This build targets the Arduino Uno R4 Minima. The code uses hardware I2C for the sensor and hardware SPI for the display.
Required Components
- MCU: Arduino Uno R4 Minima (ABX00080)
- Sensor: Adafruit MLX90640 Thermal Camera Breakout (PID: 4407)
- Display: 1.44" 128x128 TFT ST7789 (SPI)
- Wiring: 22 AWG silicone stranded wire, 4.7kΩ pull-up resistors (optional, see debugging)
Pin Mapping Table
| Module | Module Pin | Arduino Uno R4 Minima Pin | Notes |
|---|---|---|---|
| MLX90640 | VIN | 5V | Sensor requires 3.3V logic but 5V VIN input on Adafruit breakout |
| MLX90640 | GND | GND | Common ground |
| MLX90640 | SCL | A5 (SCL) | Hardware I2C Clock |
| MLX90640 | SDA | A4 (SDA) | Hardware I2C Data |
| TFT ST7789 | VCC | 5V | Check your specific TFT voltage requirements |
| TFT ST7789 | GND | GND | Common ground |
| TFT ST7789 | SCL (SCK) | D13 | Hardware SPI Clock |
| TFT ST7789 | SDA (MOSI) | D11 | Hardware SPI Data |
| TFT ST7789 | CS | D10 | SPI Chip Select (defined in code) |
| TFT ST7789 | DC | D9 | Data/Command (defined in code) |
| TFT ST7789 | RES (RST) | D8 | Reset (defined in code) |
Step-by-Step Wiring and Assembly
- Prep the I2C Bus: Solder the included header pins to the MLX90640 breakout. Connect VIN to 5V, GND to GND, SDA to A4, and SCL to A5 on the Uno R4.
- Prep the SPI Display: Solder headers to the ST7789 TFT. Wire the SPI pins (SCK to D13, MOSI to D11) and the control pins (CS to D10, DC to D9, RST to D8).
- Verify Power Rails: Ensure both the TFT and the MLX90640 share a common ground with the Arduino. Floating grounds will cause I2C NACK errors and erratic TFT colors.
- Mounting: Mount the MLX90640 facing outward. The sensor has a 110° field of view (FOV); keep it at least 2 inches away from any enclosure walls to prevent reading the ambient temperature of your project box.
Complete Compilable Arduino Code
This code targets the Arduino Uno R4 Minima. It initializes the I2C bus at 400kHz, reads the 768-pixel thermal array, calculates the dynamic min/max temperature range, and renders a color-mapped thermal image to the ST7789 TFT. It includes explicit error handling for I2C initialization failures and frame-read timeouts.
Required Libraries (install via Arduino Library Manager): Adafruit MLX90640, Adafruit ST7735 and ST7789 Library, Adafruit GFX Library. Adafruit GFX Documentation.
#include <Wire.h>
#include <Adafruit_MLX90640.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
// --- PIN DEFINITIONS ---
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
// --- HARDWARE OBJECTS ---
Adafruit_MLX90640 mlx;
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
float frame[32*24];
const int BOX_SIZE = 4; // 32 cols * 4px = 128px width; 24 rows * 4px = 96px height
void setup() {
Serial.begin(115200);
while(!Serial) delay(10);
// Initialize TFT Display
tft.init(128, 128);
tft.setRotation(1);
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
// Initialize I2C Bus
Wire.begin();
Wire.setClock(400000); // 400kHz is optimal for MLX90640 bus capacitance
// Initialize Sensor with Error Handling
if (!mlx.begin(MLX90640_I2CADDR_DEFAULT, &Wire)) {
Serial.println(F("ERROR: Failed to find MLX90640 sensor! Check I2C wiring."));
tft.setTextColor(ST77XX_RED);
tft.setCursor(10, 50);
tft.print("I2C FAIL");
while (1) delay(10); // Halt execution
}
// Configure Sensor Parameters
mlx.setResolution(MLX90640_ADC_18BIT);
mlx.setRefreshRate(MLX90640_4_HZ); // 4Hz is stable for 18-bit resolution
tft.fillScreen(ST77XX_BLACK);
}
void loop() {
// Read Frame with Error Handling
if (mlx.getFrame(frame) != 0) {
Serial.println(F("ERROR: Frame read failed. I2C bus hang?"));
return; // Skip this loop iteration
}
// Calculate Dynamic Min/Max for Color Mapping
float minTemp = 1000.0;
float maxTemp = -1000.0;
for(int i=0; i<768; i++) {
if(frame[i] < minTemp) minTemp = frame[i];
if(frame[i] > maxTemp) maxTemp = frame[i];
}
// Render Thermal Array to TFT
for(int y=0; y<24; y++) {
for(int x=0; x<32; x++) {
float temp = frame[y * 32 + x];
uint16_t color = mapTempToColor(temp, minTemp, maxTemp);
tft.fillRect(x * BOX_SIZE, y * BOX_SIZE, BOX_SIZE, BOX_SIZE, color);
}
}
}
// Helper function to map temperature to a 16-bit 565 RGB color
uint16_t mapTempToColor(float temp, float minT, float maxT) {
float range = maxT - minT;
if(range < 0.1) range = 0.1; // Prevent division by zero
float ratio = (temp - minT) / range;
if(ratio < 0) ratio = 0;
if(ratio > 1) ratio = 1;
// Simple Blue (cold) to Red (hot) gradient
uint8_t r = (uint8_t)(ratio * 255);
uint8_t b = (uint8_t)((1.0 - ratio) * 255);
return tft.color565(r, 0, b);
}
Debugging: Exact Errors and the First Three Checks
Thermal arrays are notoriously sensitive to I2C bus conditions. If your build fails, these are the first three things to check, mapped to the exact error strings thrown by the code above.
Error 1: ERROR: Failed to find MLX90640 sensor! Check I2C wiring.
Ranked Causes:
- Missing Pull-up Resistors: The Adafruit breakout has 10kΩ pull-ups on board. If you are using long jumper wires (>6 inches) or a breadboard with high parasitic capacitance, 10kΩ is too weak to pull the bus high before the next clock edge. Fix: Solder additional 4.7kΩ or 2.2kΩ resistors between SDA/SCL and 3.3V.
- Voltage Logic Mismatch: The Uno R4 outputs 5V logic on I2C. While the MLX90640 is a 3.3V part, the Adafruit breakout includes a level shifter. If you are using a raw generic MLX90640 module from an online marketplace, 5V I2C will fry the sensor or cause it to NACK. Fix: Use a bidirectional logic level converter (like the BSS138 based modules).
- Incorrect I2C Address: The default address is
0x33. Run the standard ArduinoI2C_Scannersketch. If it shows up as0x34, the address pin is pulled high. UpdateMLX90640_I2CADDR_DEFAULTin the code to0x34.
Error 2: ERROR: Frame read failed. I2C bus hang?
Ranked Causes:
- I2C Clock Stretching Timeout: The MLX90640 uses clock stretching to tell the master to wait while it calculates the compensation math. The Arduino Uno R4 Wire library handles this, but if the sensor is set to a refresh rate higher than the I2C bus can support, it will hang. Fix: Ensure
Wire.setClock(400000);is set, and do not exceedMLX90640_4_HZat 18-bit resolution. - Power Supply Brownout: The MLX90640 draws spikes of current during the ADC conversion phase. If powered from a weak USB hub, the voltage drops, corrupting the I2C state machine. Fix: Power the Arduino via the barrel jack with a 9V/2A supply, or use a dedicated 5V buck converter for the sensor VIN.
How to Extend or Simplify the Build
Simplify: Drop the TFT for Serial CSV Output
If you don't have a TFT display or want to log data to a PC for advanced analysis, strip out all Adafruit_ST7789 code. In the loop(), replace the tft.fillRect block with a Serial print loop. Output the 768 values as comma-separated values (CSV). You can then pipe this serial output into a Python script using matplotlib to render a high-resolution, interpolated thermal heatmap on your desktop.
Extend: Add WiFi Telemetry and SD Logging
To turn this into a standalone thermal datalogger:
- Upgrade the MCU: Swap the Uno R4 Minima for an ESP32-S3 DevKit. The ESP32 has native WiFi and more than enough SRAM (512KB) to buffer multiple frames.
- Add an SD Card: Wire an SPI SD card module to the ESP32's secondary SPI bus (HSPI). Write the raw 16-bit EEPROM data directly to a .bin file to save space, rather than converting to floats.
- MQTT Streaming: Use the ESP32's WiFi to publish the min/max/average temperatures to an MQTT broker (like Mosquitto) every 5 seconds, allowing Home Assistant to trigger automations based on thermal anomalies (e.g., detecting an overheating breaker panel).






