Create an IR thermometer to check the temperature in yourself and others to see if you need to go to the doctor!

We are going through the biggest health crisis in recent years due to the increase in the number of cases of COVID-19.

In some countries, there are not enough tests to detect the presence of the Coronavirus in people, which makes it difficult to correctly count the number of cases and impairs the decision-making of public policies such as the adoption of social isolation to stop the increase in the number of cases or Flexibilization.

One of the main symptoms of Coronavirus is an increase in body temperature above 39ºC, in addition to other symptoms such as pain in the body, difficulty in breathing.

So we need a device that is able to measure body temperature without having to come into direct contact with the person's body to avoid contamination of the device.

For this, we can use the MLX 90614 sensor. It allows the measurement of temperature without having to come into contact with the person's body, as it performs the measurement through infrared radiation.

So, just bring the sensor close to the person's body and perform the temperature measurement.

With the use of this sensor, we were able to identify the first symptoms of the presence of the Coronavirus in a possibly sick person and recommend that she see a doctor.

Based on this, you will develop a NEXTPCB Thermometer using an MLX 90614 infrared sensor with an Arduino Nano. This system will consist of an OLED display to show the temperature value and a button to activate or not the sensor reading.

In addition, we will have a blue led to indicate when the system is on and a red led to indicate when the temperature is above 39 ºC.

Therefore, through this article you will learn:

  • Perform the circuit assembly on the protoboard
  • Understand how I2C communication works
  • Communicate the Arduino Nano with the OLED I2C display
  • Communicate the Arduino Nano with the MLX 90614 temperature sensor
  • Understand how the MLX 90614 temperature sensor works.
  • Develop the NEXTPCB Printed Circuit Board

Now, let's look at the development of the thermometer with the MLX 90614 infrared temperature sensor.

Developing the Thermometer With the  Infrared Temperature Sensor

As previously mentioned, the project consists of creating a system to monitor people's temperature using the MLX 90614 infrared temperature sensor.

In Figure 1, you can see the circuit mounted on the protoboard to perform the system tests.

1.jpg

Figure 1 - Screen to start reading the temperature value.

The following message appears in Portuguese on the screen "IR Thermometer - Press the button to activate the sensor".

To activate the temperature reading, you need to press the green button.

After pressing, the system is activated and the blue LED lights up as shown in Figure 2.

2.jpg
3.jpg

In the OLED display in Figure 2, the following message appears in Portuguese "IR Thermometer - Temperature: 28.07 and Normal Temperature!".

In addition to displaying the temperature value, this system displays a message indicating whether the temperature is normal or if she needs to see a doctor. This can be seen in Figure 3.

4.jpg
5.jpg

The figure above shows the following message in Portuguese "IR Thermometer - Temperature: 40.00C and Find a doctor!"

In the figure, the system detected a temperature above 39 ºC and therefore displayed the message: Look for a doctor and switched on the red alert LED.

Now let's go to the list of electronic components needed to assemble the project.

Below, we present the electronic schematic for you to assemble this project on the protoboard.

6.jpg

To assemble the device, we need to assemble the circuit on the protoboard as shown in figure 4.

Both the OLED display and the MLX 90614 temperature sensor uses I2C communication to communicate with the Arduino Nano.

I2C Communication

I2C communication - is a communication protocol developed by the company Philips that uses only two wires to carry out the communication between devices (SDA- Serial data line and SCL - Serial clock line).

In our project, two components use this communication: the OLED display and the MLX 90614 sensor.

The Arduino Nano has two specific pins to use this communication, which are the A4 - SDA pins and the A5 SCL pin.

Therefore, we must connect the SDA pins of the OLED display and the sensor to the A4 pin of the Arduino Nano and the SCL pin of both components to the A5 pin of the Arduino Nano.

On the VCC pin of the display and the MLX sensor, we supply 5 V of the Arduino Nano.

And the GND pin of the display and the MLX sensor to the Arduino GND.

To activate the MLX 90614 sensor, we are using a button connected to Arduino digital input 2, this button will be activated at logic level 0.

Thus, we need to place a 10 KΩ pull-up resistor on digital input 2 so that this input does not float when the button is not pressed.

To signal when the sensor is making measurements, we use a blue LED connected to digital output 5 of the Arduino Nano.

To limit the current of the led, a 220 Ω resistor was used.

When the temperature is above 39 ºC, a message will appear on the display and the red LED (connected to digital output 6 of the Arduino Nano) will be accessed to indicate an alert.

To limit the current of the red led, a 220 Ω resistor was used.

After performing the circuit assembly on the protoboard, we need to program our Arduino to read the temperature sensor and display the values on the OLED display.

Next, we will present the complete schedule for this project.

Code to Find the Device's I2C Address

As previously mentioned, we are using two I2C devices. These devices have different addresses and to find these addresses you need to write the firmware below on the Arduino Nano.

The Arduino will read the I2C bus and find the address of the MLX 90614 display and sensor. After that, we will be able to configure the device addresses in our code.

The code is provided below.

        #include <Wire.h>
void setup() 
{
Wire.begin();
Serial.begin(9600);
Serial.println("Scanner I2C");
}

void loop() 
{
byte erro, endereco;
int dispositivos;

Serial.println("Procurando Dispositivo I2C ...");
dispositivos = 0;

for (endereco = 1; endereco < 127; endereco++ ) 
{
Wire.beginTransmission(endereco);
erro = Wire.endTransmission();

if (erro == 0) 
{
Serial.print("Dispositivo I2C encontrado. Endereco 0x");
if (endereco < 16) Serial.print("0");
Serial.print(endereco, HEX);
Serial.println(" !");
dispositivos++;
}

else 

if (erro == 4) 
{
Serial.print("Erro desconhecido no Endereco 0x");
if (endereco < 16) Serial.print("0");
}

}

if (dispositivos == 0)
{
Serial.println("Nenhum dispositivo I2C encontrado\n");
}
else
Serial.println("Scaneamento Concluido\n");
while(Serial);
}
    

After recording this code on the Arduino Nano, if everything goes well, we will find the following addresses:

I2C device found OLED display. Address 0x3C!

I2C device found MLX 90614 sensor. Address 0x5A! temperature sensor

After finding the addresses of each device, save this information, as we will need it later in our code to read the sensor and communicate with the OLED display.

Next, we will understand the complete step by step to develop the programming logic for this project.

The Source Code for the Project

To build this project we used the logic presented below. Now we will explain the entire structure of this schedule.

        Com o comando   temperatura.ambient() realiza a leitura da temperatura do ambiente
temperatura.object() realiza a   leitura da temperatura do objeto
*/
// --- Inclusao de bibliotecas
#include <Wire.h> //INCLUSÃO   DE BIBLIOTECA
#include <Adafruit_GFX.h> //INCLUSÃO   DE BIBLIOTECA
#include <Adafruit_SSD1306.h> //INCLUSÃO   DE BIBLIOTECA
#include <SparkFunMLX90614.h>
Adafruit_SSD1306 display = Adafruit_SSD1306(); //OBJETO   DO TIPO Adafruit_SSD1306
IRTherm temperatura; // Instancia a variavel temperatura   como um objeto do IRTherm
// ----MAPEAMENTO DE HARDWARE
#define B0 2 //   Mapeia o pino 2 como B0
#define led_azul 5 //
#define led_vermelho 6
//--- Declaração de variaveis
float  soma_temp =0,   media_temp =0;
boolean en_sensor =0;
unsigned long   interval = 200;
void setup()
{
Wire.begin(); //INICIALIZA   A BIBLIOTECA WIRE
temperatura.begin(0x5A);
temperatura.setUnit(TEMP_C);
display.begin(0x3C); //INICIALIZA   O DISPLAY COM ENDEREÇO I2C 0x3C
display.setTextColor(WHITE);   //DEFINE A COR DO TEXTO
pinMode(B0,INPUT);
pinMode(led_azul,OUTPUT);
pinMode(led_vermelho,OUTPUT);
Serial.begin(9600);
Serial.println("Termometro   infravermelho ");
Serial.println("Covid   19 ");
}
void loop()
{
if(!digitalRead(B0) && en_sensor==0)
{
en_sensor =1;
display.clearDisplay();
while(digitalRead(B0)==0);
}
if(!digitalRead(B0) && en_sensor==1)
{
en_sensor =0 ;
display.clearDisplay();
digitalWrite(led_azul,0);
while(digitalRead(B0)==0);
}
if(en_sensor   ==1)
{
display.clearDisplay();
digitalWrite(led_azul,1);
if(millis () -   interval >200 )
{
if   (temperatura.read())
{
interval = millis();
for (int i=0;   i<10; i++)
{
soma_temp+= temperatura.object();
delay(10);
}
media_temp = soma_temp /10;
soma_temp =0;
display.clearDisplay();
display.setCursor(10, 0);       // Posiciona o cursor
display.setTextSize(1);       // Define tamanho da fonte
display.print("TERMOMETRO   IR ");
display.setCursor(0, 10);       // Posiciona o cursor
display.setTextSize(1);        // Define tamanho da fonte
display.print("Temperatura: " + String(media_temp,   2));
display.println("   oC ");
Serial.print("Temperatura   objeto :");
Serial.print(media_temp,   2);
Serial.println("   oC ");
if(media_temp   >39 )
{
display.setCursor(0, 20);       // Posiciona o cursor
display.setTextSize(1);        // Define tamanho da fonte
display.print("Procure   um medico !" );
digitalWrite(led_vermelho,1);
}
else
{
display.setCursor(0, 20);       // Posiciona o cursor
display.setTextSize(1);        // Define tamanho da fonte
display.print("Temperatura   normal !" );
digitalWrite(led_vermelho,0);
}
display.display();
}
}
}
else
{
display.clearDisplay();
display.setCursor(10, 0);       // Posiciona o cursor
display.setTextSize(1);       // Define tamanho da fonte
display.print("TERMOMETRO   IR ");
display.setCursor(0, 10);       // Posiciona o cursor
display.setTextSize(1);       // Define tamanho da fonte
display.print("Pressione   o botao");
display.setCursor(0, 20);
display.print("Para   ativar o sensor");
display.display();
}
}
    

To carry out this project we will use 4 libraries.

Wire - This library is not necessary to install, as it is already the default of the Arduino IDE, this library configures the peripherals to perform I2C communication.

Adafruit GFX and Adafruit SSD1306 - Both libraries are required to communicate with the OLED display.

SparkFunMLX90614 - To communicate with the MLX 90614 sensor.

All project libraries and source code can be downloaded through this link - Library download

Now, we will present the programming logic developed in a few steps.

Inclusion of All Necessary Libraries 

        #include <Wire.h> //INCLUSÃO DE BIBLIOTECA
#include <Adafruit_GFX.h> //INCLUSÃO DE BIBLIOTECA
#include <Adafruit_SSD1306.h> //INCLUSÃO DE BIBLIOTECA
#include <SparkFunMLX90614.h>
    

Define the Display and Sensor 

        Adafruit_SSD1306 display = Adafruit_SSD1306(); //OBJETO DO TIPO Adafruit_SSD1306
IRTherm temperatura; // Instancia a variavel temperatura como um objeto do IRTherm
    

Hardware Mapping

        // ----MAPEAMENTO DE HARDWARE
#define B0 2 // Mapeia o pino 2 como B0
#define led_azul 5 //
#define led_vermelho 6
    

The hardware mapping helps us to name the outputs or inputs of the microcontroller with the name of the physical component that they will trigger which helps when developing the code.

#define - Command to name a pin, const int could be used, but define takes up less memory space than const int.

Declaration of Variables

        //--- Declaração de variaveis
float soma_temp =0, media_temp =0;
boolean en_sensor =0;
unsigned long interval = 200;
    

Next, we will start our setup function, which is the function where we perform the input and output configurations and configuration of the I2C peripherals, serial communication speed to display the values on the serial monitor.

Start-up the void setup () Function

        void setup()
{

Wire.begin(); //INICIALIZA A BIBLIOTECA WIRE
temperatura.begin(0x5A);
temperatura.setUnit(TEMP_C);

display.begin(0x3C); //INICIALIZA O DISPLAY COM ENDEREÇO I2C 0x3C
display.setTextColor(WHITE); //DEFINE A COR DO TEXTO

pinMode(B0,INPUT);
pinMode(led_azul,OUTPUT);
pinMode(led_vermelho,OUTPUT);

Serial.begin(9600);
Serial.println("Termometro infravermelho ");
Serial.println("Covid 19 ");
}
    

In the function Temperatura.begin () - we must put the address found with the code I2C scanner. Our address is 0x5A.

Already the command temperatura.setUnit(TEMP_C); determines the measurement unit.

Finally, we config the address of the display and text color of the display as is shown below.

        display.begin(0x3C); //INICIALIZA O DISPLAY COM ENDEREÇO I2C 0x3C
display.setTextColor(WHITE); //DEFINE A COR DO TEXTO
    

The void loop () Function

This function will execute your programming logic. The full source code is presented below.

        void loop()
{
if(!digitalRead(B0) && en_sensor==0)
{
en_sensor =1;
display.clearDisplay();
while(digitalRead(B0)==0);
}
if(!digitalRead(B0) && en_sensor==1)
{
en_sensor =0 ;
display.clearDisplay();
digitalWrite(led_azul,0);
while(digitalRead(B0)==0);
}
if(en_sensor ==1)
{
display.clearDisplay();
digitalWrite(led_azul,1);
if(millis () - interval >200 )
{
if (temperatura.read())
{
interval = millis();
for (int i=0; i<10; i++)
{
soma_temp+= temperatura.object();
delay(10);
}
media_temp = soma_temp /10;
soma_temp =0;
display.clearDisplay();
display.setCursor(10, 0); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("TERMOMETRO IR ");
display.setCursor(0, 10); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Temperatura: " + String(media_temp, 2));
display.println(" oC ");
Serial.print("Temperatura objeto :");
Serial.print(media_temp, 2);
Serial.println(" oC ");
if(media_temp >39 )
{
display.setCursor(0, 20); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Procure um medico !" );
digitalWrite(led_vermelho,1);
}
else
{
display.setCursor(0, 20); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Temperatura normal !" );
digitalWrite(led_vermelho,0);
}
display.display();
}
}
}
else
{
display.clearDisplay();
display.setCursor(10, 0); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("TERMOMETRO IR ");
display.setCursor(0, 10); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Pressione o botao");
display.setCursor(0, 20);
display.print("Para ativar o sensor");
display.display();
}
}
    

First, we check if the button was pressed or not, if it is not pressed we display the following message:

        display.clearDisplay();
display.setCursor(10, 0); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("TERMOMETRO IR ");
display.setCursor(0, 10); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Pressione o botao");
display.setCursor(0, 20);
display.print("Para ativar o sensor");
display.display();
display.clearDisplay(); - função para limpar o display
    

Whenever we write something on the display we must use the command display.display (); to update the display.

Pressing the button activates the flag en_sensor with the value 1. Thus, if en_sensor is equal at 1, the program will enter the condition below.

        if(en_sensor ==1)
{
display.clearDisplay();
digitalWrite(led_azul,1);
if(millis () - interval >200 )
{
if (temperatura.read())
{
interval = millis();
for (int i=0; i<10; i++)
{
soma_temp+= temperatura.object();
delay(10);
}
media_temp = soma_temp /10;
soma_temp =0;
display.clearDisplay();
display.setCursor(10, 0); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("TERMOMETRO IR ");
display.setCursor(0, 10); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Temperatura: " + String(media_temp, 2));
display.println(" oC ");
Serial.print("Temperatura objeto :");
Serial.print(media_temp, 2);
Serial.println(" oC ");
if(media_temp >39 )
{
display.setCursor(0, 20); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Procure um medico !" );
digitalWrite(led_vermelho,1);
}
else
{
display.setCursor(0, 20); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Temperatura normal !" );
digitalWrite(led_vermelho,0);
}
display.display();
}
    

Under this condition, we turn on the blue led and check if 200 ms has passed. If so, we check if it is being read using the function below.

        temperatura.read())
    

After the reading starts, we take 10 readings and average the values to be displayed on the screen, as shown in the code below.

        media_temp = soma_temp /10;
soma_temp =0;
display.clearDisplay();
display.setCursor(10, 0); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("TERMOMETRO IR ");
display.setCursor(0, 10); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Temperatura: " + String(media_temp, 2));
display.println(" oC ");
Serial.print("Temperatura objeto :");
Serial.print(media_temp, 2);
Serial.println(" oC ");
    

The temperature.object () command reads the temperature of the object. The temperature.ambient command reads the ambient temperature.

After taking the temperature measurement, we check if the value is greater than 39ºC. If it is true, we will activate the red LED. The code is presented below.

        if(media_temp >39 )
{
display.setCursor(0, 20); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Procure um medico !" );
digitalWrite(led_vermelho,1);
}

else

{
display.setCursor(0, 20); // Posiciona o cursor
display.setTextSize(1); // Define tamanho da fonte
display.print("Temperatura normal !" );
digitalWrite(led_vermelho,0);
}

display.display();
    

In addition, we have developed an electronic board with NEXTPCB Printed Circuit Board. This board will allow you to assemble this prototype and use it in your projects.

The Printed Circuit Board 

In the figure below we present the project's prototype in its 3D version.

7.jpg

This project was developed from the following electronic schematic.

8.jpg

Finally, we finish the build of this project. Download the Gerber files to create a thermometer of your own.

Conclusion

In this article, we learned how to build a thermometer with the MLX 90614 sensor with the Arduino. For this, we use an OLED display to display the measurements and create a useful device to measure the temperature of people and environments.

In this way, we can contribute to the fight against the pandemic that we are currently experiencing.

A suggestion for future projects is to add a memory card module to save the measurements and create a datalogger. With that, we can add a Bluetooth module and create an application to display temperature measurements and alert messages.

The Escola Robô Lúdico thanks to the NEXTPCB for providing the PCB to assembly this project. 

Lima Moreira