MLX90614 Infrared Non-Contact Temperature Sensor
The MLX90614 series modules are a group of general-purpose infrared temperature measurement modules. Before leaving the factory, this module has been calibrated and linearized, featuring non-contact, small size, high precision, and low cost. The target temperature and ambient temperature can be output through a single channel, and there are two output interfaces, suitable for automotive air conditioning, indoor heating, household appliances, handheld devices, and medical equipment applications. Temperature measurement methods can be divided into contact and non-contact types. Contact temperature measurement can only measure the temperature after the measured object and the temperature sensor reach thermal equilibrium, so the response time is long and it is easily affected by the ambient temperature. Infrared temperature measurement determines the object's temperature based on the infrared radiation energy of the measured object, without contacting the measured object, featuring no influence on the temperature distribution field of the measured object, high temperature resolution, fast response speed, wide temperature measurement range, no limitation on the upper limit of temperature measurement, and good stability. Therefore, we choose MLX90614 as the infrared temperature measurement module. The communication method between the microcontroller and the MLX90614 infrared temperature measurement module is "IIC-like" communication, which means the communication method is very similar to IIC but is not IIC; it has another name called SMBus. SMBus (System Management Bus) is an efficient synchronous serial bus proposed by Intel in 1995. SMBus has only two signal lines: a bidirectional data line and a clock signal line. It allows the CPU to communicate and exchange information with various peripheral interface devices in a serial manner, which not only improves transmission speed but also reduces the resource occupation of devices. In addition, even on microcontrollers without an SMBus interface, it can be simulated using software.
Module Source
Purchase link: https://item.taobao.com/item.htm?spm=a1z09.2.0.0.204e2e8d2hPeAl&id=609920555320&_u=h2t4uge53d5e Materials download link: https://pan.baidu.com/s/1AsEBvVCiNAvTKqTeGSA60w Extraction code: g06n
Specifications
Operating voltage: 4.5~5.5V Operating current: 1.3~2.5mA
Principle Analysis
There are two memories in the MLX90614: EEPROM and RAM.
- The MLX90614 has a total of 32 EEPROM storage units with a word length of 16 bits, with addresses ranging from 000H to 01FH. All registers in the EEPROM can be read via SMBus, but only some registers can be rewritten (addresses 0x00, 0x01, 0x02, 0x03, 0x04, 0x05*, 0x0E, 0x0F, 0x19). The writable parts are shown in the figure below. Since the module has been calibrated and linearized before leaving the factory, we directly use the default parameters without modification.
- The MLX90614 has a total of 32 RAM storage units of 17 bits. Users cannot write data to the RAM; they can only read 16-bit stored data from some storage units in the RAM. The collected ambient temperature data is saved in the storage unit at address 06H, and the collected measured object temperature data is saved in the storage unit at address 07H. Therefore, by using the data stored in the RAM address and through formula calculation, the ambient temperature Ta and the measured object temperature data To can be obtained.
Timing description Note that the low 8 bits of the data come first, and the high 8 bits come after.
The device address (Slave Address) is described in the datasheet; the default device address is 0X5A;
The command is determined by BIT7~BIT5 of a byte based on whether the RAM or EEPROM is to be controlled. The remaining BIT4~BIT0 are determined by the address to be operated.
For example, if I want to read the Ta temperature data from RAM, the command composition is shown in the table below. The RAM address is 000x_xxxx, and the Ta temperature data address is 0x06 = 0000_0110; taking only the low 5 bits gives xxx0_0110.
PEC is a CRC-8 checksum data with polynomial X8+X2+X1+1. Two examples are given in the datasheet. Where 0xB4 is the value of the device address after being shifted left by one bit.
After obtaining the raw temperature data, convert it according to the datasheet instructions to obtain the temperature.
Above is an example given in the datasheet. If the read temperature data is 0X3AF7, its decimal value is 15095. Divide the decimal number by 50 or multiply by 0.02 to get 301.9, then subtract 273.15 to get the actual temperature.
This temperature conversion formula applies to both To and Ta.
Porting Process
Pin Selection
Port to Project
Our goal is to port the example to the ESP32-S3 dev board. Complete driver code has been provided for you. Follow the steps below to complete the porting. For detailed instructions on creating folders and new .c and .h files, refer to section 1.4.2 in the [DHT11 Temperature and Humidity Sensor] chapter; we will not repeat it here. However, here we change the file names bsp_dht11.c and bsp_dht11.h to bsp_mlx90614.c and bsp_mlx90614.h, and rename the folder to mlx90614.
Write Code
In the file bsp_mlx90614.c, write:
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2024-01-02 LCKFB-lp first version
*/
#include "bsp_mlx90614.h"
#include "stdio.h"
void delay_ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
void delay_us(unsigned int us)
{
ets_delay_us(us);
}
/******************************************************************
* Function Name: MLX90614_GPIO_Init
* Function Description: Pin initialization for MLX90614
* Function Parameters: None
* Function Return: None
* Author: LC
* Notes: MLX90614 is 5V
******************************************************************/
void MLX90614_GPIO_Init(void)
{
gpio_config_t mlx90614_config = {
.pin_bit_mask = (1ULL<<GPIO_SCL_PIN)|(1ULL<<GPIO_SDA_PIN), // Configure pin
.mode =GPIO_MODE_OUTPUT, // Output mode
.pull_up_en = GPIO_PULLUP_ENABLE, // Enable pull-up
.pull_down_en = GPIO_PULLDOWN_DISABLE, // Disable pull-down
.intr_type = GPIO_INTR_DISABLE // Disable pin interrupt
};
gpio_config(&mlx90614_config);
}
/******************************************************************
* Function Name: IIC_Start
* Function Description: IIC start timing
* Function Parameters: None
* Function Return: None
* Author: LC
* Notes: None
******************************************************************/
void IIC_Start(void)
{
SDA_OUT();
SDA(1);
delay_us(5);
SCL(1);
delay_us(5);
SDA(0);
delay_us(5);
SCL(0);
delay_us(5);
}
/******************************************************************
* Function Name: IIC_Stop
* Function Description: IIC stop signal
* Function Parameters: None
* Function Return: None
* Author: LC
* Notes: None
******************************************************************/
void IIC_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
SCL(1);
delay_us(5);
SDA(1);
delay_us(5);
}
/******************************************************************
* Function Name: IIC_Send_Ack
* Function Description: Master sends acknowledge or non-acknowledge signal
* Function Parameters: 0 sends acknowledge 1 sends non-acknowledge
* Function Return: None
* Author: LC
* Notes: None
******************************************************************/
void IIC_Send_Ack(unsigned char ack)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(5);
if(!ack) SDA(0);
else SDA(1);
SCL(1);
delay_us(5);
SCL(0);
SDA(1);
}
/******************************************************************
* Function Name: I2C_WaitAck
* Function Description: Wait for slave acknowledge
* Function Parameters: None
* Function Return: 0 acknowledged 1 timeout no acknowledge
* Author: LC
* Notes: None
******************************************************************/
unsigned char I2C_WaitAck(void)
{
char ack = 0;
unsigned char ack_flag = 10;
SCL(0);
SDA(1);
SDA_IN();
delay_us(5);
SCL(1);
delay_us(5);
while( (SDA_GET()==1) && ( ack_flag ) )
{
ack_flag--;
delay_us(5);
}
if( ack_flag <= 0 )
{
IIC_Stop();
return 1;
}
else
{
SCL(0);
SDA_OUT();
}
return ack;
}
/******************************************************************
* Function Name: Send_Byte
* Function Description: Write one byte
* Function Parameters: dat data to write
* Function Return: None
* Author: LC
* Notes: None
******************************************************************/
void Send_Byte(uint8_t dat)
{
int i = 0;
SDA_OUT();
SCL(0);// Pull clock low to start data transmission
for( i = 0; i < 8; i++ )
{
SDA( (dat & 0x80) >> 7 );
delay_us(1);
SCL(1);
delay_us(5);
SCL(0);
delay_us(5);
dat<<=1;
}
}
/******************************************************************
* Function Name: Read_Byte
* Function Description: IIC read timing
* Function Parameters: None
* Function Return: Data read
* Author: LC
* Notes: None
******************************************************************/
unsigned char Read_Byte(void)
{
unsigned char i,receive=0;
SDA_IN();// Set SDA as input
for(i=0;i<8;i++ )
{
SCL(0);
delay_us(5);
SCL(1);
delay_us(5);
receive<<=1;
if( SDA_GET() )
{
receive|=1;
}
delay_us(5);
}
SCL(0);
return receive;
}
/******************************************************************
* Function Name: PEC_Calculation
* Function Description: PEC checksum
* Function Parameters: pec data address to verify len length to verify
* Function Return: Verified value
* Author: LC
* Notes: None
******************************************************************/
static unsigned char PEC_Calculation(unsigned char *dat , unsigned char len)
{
unsigned char i;
unsigned char crc=0;
while( len-- )
{
crc ^= *dat++;
for( i=0 ; i<8 ; i++ )
{
if( crc&0x80 )
{
crc = (crc<<1)^0x07;
}
else
{
crc = (crc<<1);
}
}
}
return crc;
}
/************************************************************
* Function Name: MLX90615_Read
* Function Description: Read the temperature of MLX90615
* Parameters: SlaveAddr = device address RegAddr = register address to operate
* Return Value: Temperature value
* Notes: SlaveAddr = 0X5A default device address
* RegAddr = 0X07 read measured object temperature
* RegAddr = 0X06 read ambient temperature
*************************************************************/
#define CRC_VERIFY_ENABLE 1
float MLX90614_Read(unsigned char SlaveAddr, unsigned char RegAddr)
{
int i = 0;
unsigned char buff[3]={0}; // Save temperature high/low bytes and checksum
unsigned char arr[6]={0}; // For checksum verification
uint16_t temp = 0; // High/low combined data storage
float T=0.0; // Converted actual temperature
IIC_Start();
Send_Byte((SlaveAddr<<1)|0);// Write command
I2C_WaitAck(); // Wait for response
Send_Byte(RegAddr);// Write register address to operate
I2C_WaitAck();
do{
delay_ms(1);
IIC_Start(); // Restart IIC
Send_Byte((SlaveAddr<<1)|1); // Read command
}while( I2C_WaitAck() );
buff[0] = Read_Byte(); // Save low 8 bits of temperature data
IIC_Send_Ack(0); // Master sends acknowledge
buff[1] = Read_Byte(); // Save high 8 bits of temperature data
IIC_Send_Ack(0); // Master sends acknowledge
buff[2] = Read_Byte(); // Save checksum
IIC_Send_Ack(1); // Master sends acknowledge
IIC_Stop(); // Stop timing
// Using checksum
#if CRC_VERIFY_ENABLE
arr[0] = (SlaveAddr<<1); // Device address + write
arr[1] = RegAddr; // Command
arr[2] = (SlaveAddr<<1)+1; // Device address + read
arr[3] = buff[0]; // Data low 8 bits
arr[4] = buff[1]; // Data high 8 bits
if( PEC_Calculation(arr, 5) == buff[2] )// If checksum is correct
{
temp = (short)(buff[1]<<8) | buff[0];// Combine high/low bits
T = (temp * 0.02) - 273.15 ; // Apply formula to convert actual temperature
}
else
{
printf("ERROR CODE 4\r\n");
}
#endif
// Without using checksum
#if !CRC_VERIFY_ENABLE
temp = (uint16_t)(buff[1]<<8) | buff[0];
T = (temp*0.02)-273.15 ;
#endif
return T;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
In the file bsp_mlx90614.h, write:
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2024-01-02 LCKFB-lp first version
*/
#ifndef _BSP_MLX90614_H_
#define _BSP_MLX90614_H_
#include "driver/gptimer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include <inttypes.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "rom/ets_sys.h"
#include "esp_system.h"
#include "driver/gptimer.h"
#include "esp_timer.h"
// Port porting
#define GPIO_SCL_PIN 1
#define GPIO_SDA_PIN 2
// Set SDA output mode
#define SDA_OUT() gpio_set_direction(GPIO_SDA_PIN,GPIO_MODE_OUTPUT)
// Set SDA input mode
#define SDA_IN() gpio_set_direction(GPIO_SDA_PIN,GPIO_MODE_INPUT)
// Get the level change of SDA pin
#define SDA_GET() gpio_get_level(GPIO_SDA_PIN)
// SDA and SCL output
#define SDA(x) gpio_set_level(GPIO_SDA_PIN, (x?1:0))
#define SCL(x) gpio_set_level(GPIO_SCL_PIN, (x?1:0))
void delay_ms(unsigned int ms);
void delay_us(unsigned int us);
void MLX90614_GPIO_Init(void);
float MLX90614_Read(unsigned char SlaveAddr, unsigned char RegAddr);
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Porting Verification
Enter the following code in main.c
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2024-01-02 LCKFB-lp first version
*/
#include <stdio.h>
#include "bsp_mlx90614.h"
void app_main(void)
{
MLX90614_GPIO_Init();
printf("Start.....\r\n");
while(1)
{
printf("temperature = %.2f\r\n", MLX90614_Read(0X5A, 0X07) );
delay_ms(1000);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Power-on effect:
Driver code (adapted):
File Download
📌 Materials Download Center (click to jump)
📌 In the Materials Download Center -> Module Porting Materials Download, inside the compressed package of this chapter.