Hi everyone,
I’ve been working on a compact non-contact temperature measurement project using the MLX90614 infrared sensorand an SSD1306 OLED display. The goal was to create a straightforward temperature gun setup that could show live object temperature readings directly on an OLED.
Hardware Used:
- Arduino (Nano or Uno)
- Adafruit MLX90614 IR Temperature Sensor
- 0.96" I2C OLED Display (128x64)
- Breadboard + Wires
Wiring:
- MLX90614 and OLED both use I2C, so:
- VCC → 3.3V or 5V (depending on your breakout)
- GND → GND
- SDA → A4 (on Uno/Nano)
- SCL → A5 (on Uno/Nano)
Code:
#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
void setup() {
Serial.begin(9600);
delay(2000); // Let sensors power up
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
Serial.println(F("OLED not found"));
} else {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("MLX90614 Temp Sensor");
display.display();
delay(1500);
}
if (!mlx.begin()) {
Serial.println(F("MLX90614 not found"));
}
}
void loop() {
float ambient = mlx.readAmbientTempC();
float object = mlx.readObjectTempC();
Serial.print("Ambient Temp: ");
Serial.print(ambient);
Serial.print(" °C | Object Temp: ");
Serial.print(object);
Serial.println(" °C");
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println("Object Temp:");
display.setTextSize(2);
display.setCursor(0, 20);
display.print(object, 1);
display.cp437(true);
display.write(248); // Degree symbol
display.println("C");
display.display();
delay(1000);
}
Calibration and Accuracy: Why Add 4°C?
Most commercial infrared temperature guns—especially those used for medical screening—are not just displaying the raw skin temperature. Instead, they’re calibrated to estimate core body temperature, which is generally 3–5°C higherthan the temperature measured on the skin or forehead surface.
This is important because:
- Skin temperature fluctuates due to ambient conditions (e.g. weather, wind, sweating).
- But core temperature is more stable and medically relevant (e.g. fever detection).
- So many IR thermometers add a fixed offset (typically 3–5°C) to bridge this gap.
Adding a 4°C Offset in Code
To simulate this behaviour, I’ve modified my code to add 3 degrees Celsius to the object temperature before displaying it on the OLED. This simulates how a commercial thermometer might function.
code:
#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED display config
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Temperature sensor
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
// Buzzer pin
const int buzzerPin = 8;
// Fever threshold
const float FEVER_THRESHOLD = 38.0;
void setup() {
Serial.begin(9600);
delay(1000); // Power-up delay
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, LOW);
// Initialise OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
Serial.println(F("OLED not found"));
} else {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Starting Sensor...");
display.display();
delay(1500);
}
// Initialise temperature sensor
if (!mlx.begin()) {
Serial.println(F("MLX90614 not found"));
}
}
void loop() {
float objectTemp = mlx.readObjectTempC();
float coreTemp = objectTemp + 3.0; // Adjust to estimate core body temp
Serial.print("Raw Temp: ");
Serial.print(objectTemp);
Serial.print(" °C | Core Temp Est.: ");
Serial.println(coreTemp);
// Check for fever
if (coreTemp >= FEVER_THRESHOLD) {
tone(buzzerPin, 1000, 500); // 1000Hz tone for 500ms
}
// Update display
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println("Body Temp (Est):");
display.setTextSize(2);
display.setCursor(0, 20);
display.print(coreTemp, 1);
display.cp437(true);
display.write(248); // Degree symbol
display.println("C");
// Optional status message
display.setTextSize(1);
display.setCursor(0, 50);
if (coreTemp >= FEVER_THRESHOLD) {
display.println("Warning: Fever Detected!");
} else {
display.println("Temperature Normal");
}
display.display();
delay(2000); // Refresh every 2 seconds
}