← All projects
Sensors Beginner

A Contactless Thermometer on the MLX90614 with an OLED Display

The MLX90614 infrared sensor measures surface temperature from a distance, from a cup of tea to a forehead. We show the reading on an OLED, beep on a "fever", and look at the field of view, emissivity, and why this is not a medical device.

Difficulty
Beginner
Time
40 min
Category
Sensors
Updated

About the project

Every object emits infrared light, and the hotter it is, the brighter. The MLX90614 is a thermopile with a filter and a processor inside: it catches that radiation and reports a ready-made temperature over I2C. It is what infrared thermometer "guns" use. We build a pocket thermometer: digits on a 0.96″ OLED and a beep when the surface is hotter than 37.5 °C.

What you need

  • ESP32 DevKit
  • MLX90614 module (GY-906, the 3 V version or the 5 V one with a regulator)
  • SSD1306 128×64 OLED (I2C)
  • A buzzer and a 100 Ω resistor
  • The Adafruit MLX90614 and Adafruit SSD1306 (+ Adafruit GFX) libraries

Wiring

Both modules share the I2C bus at different addresses (MLX90614 is 0x5A, the OLED 0x3C):

Module VIN/VCC GND SDA SCL
MLX90614 3V3 GND GPIO21 GPIO22
OLED 3V3 GND GPIO21 GPIO22

Buzzer: GPIO25 → 100 Ω → "+", "−" → GND.

What the sensor actually measures

  • Two values. readAmbientTempC() is the temperature of the sensor's own case (≈ the air). readObjectTempC() is the average temperature of everything in its field of view.
  • A ~90° field of view on the GY-906 (the BAA model). At 5 cm that is a spot about 10 cm across. Step back and the sensor also "sees" the wall around the cup. For readings from afar there are narrow-field versions (BCI: 5°).
  • Emissivity (ε). The sensor is set to ε = 1.0 (a perfect "black body"). Skin is ≈ 0.98, so it reads ~0.3 °C low. Polished metal with ε ≈ 0.1 is nearly "invisible": the sensor reports the room temperature reflected off it. For metal, stick on a piece of black electrical tape and measure that.

Code

// Contactless thermometer: MLX90614 + 128×64 OLED + buzzer
#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <Adafruit_SSD1306.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614();
Adafruit_SSD1306 oled(128, 64, &Wire);
const int BUZZER = 25;
const float FEVER = 37.5;   // "hot surface" threshold, °C

void setup() {
  Serial.begin(115200);
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED not found");
    while (true) delay(1000);
  }
  oled.setTextColor(SSD1306_WHITE);
  if (!mlx.begin()) {
    oled.clearDisplay();
    oled.println("MLX90614 missing");
    oled.display();
    while (true) delay(1000);
  }
}

void loop() {
  float obj = mlx.readObjectTempC();    // whatever the sensor looks at
  float amb = mlx.readAmbientTempC();   // the sensor case ≈ the air
  oled.clearDisplay();
  oled.setTextSize(1);
  oled.setCursor(0, 0);
  oled.print("Object");
  oled.setTextSize(3);
  oled.setCursor(0, 16);
  oled.printf("%.1f", obj);
  oled.setTextSize(1);
  oled.print(" C");
  oled.setCursor(0, 54);
  oled.printf("Ambient %.1f C", amb);
  if (obj >= FEVER) {
    oled.setCursor(92, 0);
    oled.print("HOT!");
    tone(BUZZER, 2500, 150);
  }
  oled.display();
  Serial.printf("object %.2f °C, ambient %.2f °C\n", obj, amb);
  delay(1000);
}

Why this is not a medical thermometer

  • The forehead is 0.5–2 °C cooler than the body core and depends heavily on wind, sweat and hair.
  • The sensor reacts to the heat of its own case: hold it by the edges, not by the cap.
  • After moving it from the cold into the warm, give it 10–15 minutes for the case temperature to settle.

For comparing "hotter or colder" (pipes, sockets, motors, bearings), its ±0.5 °C accuracy is more than enough.

What next

  • A "measure" button that holds the maximum over 2 seconds, like real IR guns.
  • ε can be changed in software (writeEmissivity()), but the value goes into the sensor's EEPROM and only takes effect after the sensor is power-cycled. Don't do it in every setup(): EEPROM endurance is limited.