Home

Awesome

MicroPython (and CircuitPython) driver module for MLX90615 infrared temperature sensor

MicroPython and CircuitPython drivers for MLX90615 infrared temperature sensor, with features :

These drivers for MLX90615 are optimised for low memory usage :

1) MLX90615

The Melexis MLX90615 infrared thermometer :

Boards with MLX90615 :

2) MicroPython/CircuitPython driver definitions

The 'no-errors' version of the driver doesn't check the PEC (Packet Error Code, based on CRC-8) on each reading, doesn't read the value after writing to EEPROM to confirm, nor have specific error messages. Advantages : lower RAM usage, faster to import and a little bit to run the functions. Disadvantages : less robust, more difficult to debug errors.

The 'simple' version of the driver has just the most important functions : read ambient and object temperatures, read unique ID, read EEPROM and read of any register. Advantages : robust, lower RAM usage. Disadvantages : not possible to change MLX90615 configuration, less features.

The 'simple' and 'no-errors' version combined the above limitations.

The BBC Micro:bit full version is limited to fewer functions due to RAM limitations, so there are no sleep/wake, PWM and IIR filter functions.

The full version of the driver is described in the table below.

ConstantsDescription
MLX90615_I2C_DEFAULT_ADDR0x5B (91 in decimal) is the I2C default (from factory) address writen in EEPROM
EEPROM_DEFAULT_TIME_MS50 is the time in ms (miliseconds) recommended after erasing/writing EEPROM

All the functions can return error messagens using exceptions, so it is recommended to call them inside Micro(Python) try/except.

When the function has the argument option :

FunctionDescription
MLX90615(i2c, address=0x5B)class to construct an MLX90615 object. 'i2c' argument is I2C object created previously. 'address' option has default I2C address value 0x5B (91).
read_ambient_temp(pec_check=True)reads the ambient temperature in the range [-40, 85] C, returning a integer 100x the Celsius degree value, so 2851 = 28.51 C. There is also error message for invalid value.
read_object_temp(pec_check=True)reads the object temperature in the range [-40, 115] C, returning a integer 100x the Celsius degrees, so 3647 = 36.47 C. There is also error message for invalid value.
read_raw_ir_data(pec_check=True)reads the raw IR data, returning a 16 bits integer.
read_id(pec_check=True)reads the unique sensor ID, a 32 bits integer stored in EEPROM.
read_eeprom(pec_check=True)reads the EEPROM returning a list of 16 values, each one a 16 bits integer. Very useful to save a backup of the EEPROM, including the factory calibration data. See the MLX90615 datasheet, section 8.3.3 and table 6.
read_emissivity(pec_check=True)reads the emissivity stored in EEPROM, an integer from 5 to 100 corresponding to emissivity from 0.05 to 1.00.
set_emissivity(value=100, eeprom_read_check=True, eeprom_write_time=50)sets the emissivity to EEPROM, accepting an integer from 5 to 100 (default is 100) corresponding to emissivity from 0.05 to 1.00. With error messages for out of range of emissivity value and erasing/writing to EEPROM.
read_i2c_addres(pec_check=True)reads the I2C address stored in EEPROM, a 7 bits integer.
set_i2c_address(addr=0x5B, eeprom_read_check=False, eeprom_write_time=50)sets 'addr' (default is 0x5B = 91) as the I2C address stored in EEPROM, a 7 bits integer, in the range of [0x08, 0x77] (8 to 119 in decimal). With error messages for using current I2C address <> 0, out of range of EEPROM I2C address value and erasing/writing to EEPROM.
read_iir_filter(pec_check=True)reads the bits 12, 13 and 14 of EEPROM config register, returning a number from 1 to 7 (default is 1) corresponding to configurations of IIR (Infinite Impulse Response) digital filter. The IIR filter allows customization of the thermometer output in order to trade-off noise versus settling time, but the refresh rate of 2 Hz (0.5 s) of the data in the RAM remain constant. See the MLX90615 datasheet, section 8.2 and table 7.
set_iir_filter(iir=1, eeprom_read_check=True, eeprom_write_time=50)sets 'iir' value (1 to 7, default is 1) in bits 12, 13 and 14 of EEPROM config register corresponding to configurations of IIR (Infinite Impulse Response) digital filter. The IIR filter allows customization of the thermometer output in order to trade-off noise versus settling time, but the refresh rate of 2 Hz (0.5 s) of the data in the RAM remain constant. With error messages for erasing/writing to EEPROM. See the MLX90615 datasheet, section 8.2 and table 7.
sleep()enable the MLX90615 low power/sleep mode, disabling the sensor functions and saving approx. 1.5 mA. The I2C bus should not be used during the sleep mode. See the MLX90615 datasheet, section 8.4.8.
wake(scl_pin)disable the MLX90615 low power/sleep mode, powering-up with default mode as defined by the EEPROM. 'scl_pin' is the definition of the I2C SCL pin. See the MLX90615 datasheet, section 8.4.8.
pwm_to_i2c(scl_pin)switch to I2C mode if PWM is enabled. 'scl_pin' is the definition of the I2C SCL pin. But after power off/on the I2C or PWM mode will be chosen depending on the bit 0 of EEPROM config register. See the MLX90615 datasheet, section 8.5.1.
read_pwm_mode(pec_check=True)reads the bit 0 of EEPROM config register, returning True if PWM mode is enabled, False if I2C mode is enabled (default). See the MLX90615 datasheet, table 7.
set_pwm_mode(pwm=False, eeprom_read_check=True, eeprom_write_time=50)sets 'pwm' (default is False) as communication mode stored in bit 0 of EEPROM config register, True for PWM mode enabled, False for I2C mode enabled (default). With error messages for erasing/writing to EEPROM. This setting is used after power on. See the MLX90615 datasheet, table 7.
read_pwm_fast(pec_check=True)reads the bit 1 of EEPROM config register, returning True if PWM fast frequency (10 kHz) is enabled, False if PWM slow frequency (1 kHz) is enabled (default). See the MLX90615 datasheet, table 7.
set_pwm_fast(pwm_fast=False, eeprom_read_check=True, eeprom_write_time=50)sets 'pwm_fast' (default is False) in bit 1 of EEPROM config register, True for PWM fast frequency (10 kHz) stored, False for PWM slow frequency (1 kHz). With error messages for erasing/writing to EEPROM. This setting is used after power on in PWM mode. See the MLX90615 datasheet, table 7.
read_pwm_object_temp(pec_check=True)reads the bit 2 of EEPROM config register, returning True if PWM output is for object temperature (default), False if it is for ambient temperature. See the MLX90615 datasheet, table 7.
set_pwm_object_temp(object_temp=True, eeprom_read_check=True, eeprom_write_time=50)sets 'object_temp' (default is True) in bit 2 of EEPROM config register, True for PWM output of object temperature, False for PWM output of ambient temperature. With error messages for erasing/writing to EEPROM. This setting is used after power on in PWM mode. See the MLX90615 datasheet, table 7.
read_pwm_tmin(pec_check=True)reads the minimum temperature when PWM is used, the output scale is 0.02 K/LSB, so to convert to degrees Celsius the equation is: Tmin(C) = output × 0.02 − 273.15. Factory default is 0x355B corresponding to +0.03°C. See the MLX90615 datasheet, sections 8.3.3, 8.3.4 and 8.6.
set_pwm_tmin(tmin=0x355B, eeprom_read_check=True, eeprom_write_time=50)sets 'tmin' (default is 0x355B corresponding to +0.03°C) as the minimum temperature when PWM is used. The scale is 0.02 K/LSB, so to convert to degrees Celsius the equation is: Tmin(C) = tmin × 0.02 − 273.15. With error messages for erasing/writing to EEPROM. This setting is used after power on in PWM mode. Beware that the 7 less significant bits of 'tmin' composes the I2C address stored in EEPROM. See the MLX90615 datasheet, sections 8.3.3, 8.3.4 and 8.6.
read_pwm_trange(pec_check=True)reads the range for the temperature (Trange = Tmax – Tmin) when PWM is used, the output scale is 0.02 K/LSB, so to convert to degrees Celsius the equation is: Trange(C) = output × 0.02 − 273.15. Factory default is 0x09C4 corresponding to +49.98°C. See the MLX90615 datasheet, sections 8.3.3, 8.3.4 and 8.6.
set_pwm_trange(trange=0x09C3, eeprom_read_check=True, eeprom_write_time=50)sets 'trange' (default is 0x09C3 corresponding to +49.98°C) as the range for the temperature (Trange = Tmax – Tmin) when PWM is used. The scale is 0.02 K/LSB, so to convert to degrees Celsius the equation is: Trange(C) = trange × 0.02 − 273.15. With error messages for erasing/writing to EEPROM. This setting is used after power on in PWM mode. See the MLX90615 datasheet, sections 8.3.3, 8.3.4 and 8.6.
read16(register, crc_check=True)reads any MLX90615 register : EEPROM range is 0x10-0x1F, RAM range is 0x25-0x27 (see the MLX90615 datasheet, sections 8.3.3 and 8.3.4). The 'crc_check' argument option, enabled by default, checks the reading with a CRC-8, with error message when the CRC-8 doesn't match the PEC (Packet Error Code).
write16(register, data, read_check=True, eeprom_time=50)writes 'data' (16 bit integer number) to any MLX90615 register : EEPROM range is 0x10-0x1F, RAM range is 0x25-0x27 (see the MLX90615 datasheet, sections 8.3.3 and 8.3.4). The 'read_check' argument option, enabled by default, reads the value after writing to EEPROM to confirm. 'eeprom_time' defines the write time in ms after EEPROM writing, the recommended and default value is 50 ms. With error messages for out of range of emissivity value and erasing/writing to EEPROM. With error message if the reading value after writing doesn't check.

( * ) : writing to I2C address in EEPROM is risky because sometimes (3-10%) there is an error while erasing/writing to the EEPROM, rendering the I2C connection to MLX90615 unstable.

3) Examples

3.1) Initialization

Beware that MLX90615 I2C bus frequency should be in the range of 10-100 kHz (see the section '8.4.7 Timing specification' of the MLX90615 datasheet). I2C frequencies lower than 100 kHz are usually needed for longer cables connecting the microcontroller to the MLX90615 sensor.

If MLX90615 sensor is on a break-out board, it usually has pull-up resistors for I2C SDA and SCL pins. But the microcontroller internal pull-up or even external resistors may be needed depending on the lenght of cable connecting to the MLX90615, electromagnetic interference from the environment, etc.

3.1.1) Pyboard (Lite) v1.x
import machine
import mlx90615
i2c = machine.I2C(scl='X9', sda='X10', freq=100000)   # Software I2C
i2c.scan()   # returns : [91]  
irsensor = mlx90615.MLX90615(i2c)
3.1.2) Pyboard D and link above
import machine
import mlx90615
machine.Pin('EN_3V3').on()
machine.Pin('PULL_SCL', machine.Pin.OUT, value=1)     # 5.6k pull-up, if needed
machine.Pin('PULL_SDA', machine.Pin.OUT, value=1)     # 5.6k pull-up, if needed
i2c = machine.I2C(scl='X9', sda='X10', freq=100000)   # Software I2C
i2c.scan()   # Output : [91]
irsensor = mlx90615.MLX90615(i2c)
3.1.3) ESP8266
import machine
import mlx90615
i2c = machine.I2C(sda=machine.Pin(4), scl=machine.Pin(5), freq=100000)   # Software I2C
i2c.scan()   # Output : [91]
irsensor = mlx90615.MLX90615(i2c)
3.1.4) ESP32
import machine
import mlx90615
i2c = machine.I2C(sda=machine.Pin(21), scl=machine.Pin(22), freq=100000)   # Software I2C
i2c.scan()   # Output : [91]
irsensor = mlx90615.MLX90615(i2c)
3.1.5) BBC Micro:bit
from microbit import i2c
import mlx90615
i2c.scan()   # Output : [91]
irsensor = mlx90615.MLX90615(i2c)
3.1.6) Pycom boards like LoPy4
import machine
import mlx90615
i2c = machine.I2C(2, baudrate=100000)   # Software I2C
i2c.scan()   # Output : [91]
irsensor = mlx90615.MLX90615(i2c)

3.2) Reading the MLX90615 IR temperature

irsensor.read_raw_ir_data()    # Output : 108       # IR raw data with no physical unit
irsensor.read_ambient_temp()   # Output : 3059      # i.e., 30.59 C
irsensor.read_object_temp()    # Output : 3621      # i.e., 36.21 C

3.3) Reading the MLX90615 configuration

It is recommended that the ID and EEPROM data of each MLX90615 unit be saved (in a file like spreadsheet, etc) as a backup. Because the EEPROM includes the factory calibration data which is different for earch sensor unit, the EEPROM registers can be written by mistake, the EEPROM can become corrupted, etc.

irsensor.read_id()            # Output : 7623496   # 32 bits unique ID
irsensor.read_eeprom()        # Output : [13659, 2499, 5321, 15892, 24768, 13658, 17180, 8209, 73, 32786, 7504, 616, 6765, 14908, 21320, 116]

Factory default values are emissivity = 1.00 and I2C address = 0x5B (91 in decimal) :

irsensor.read_emissivity()    # Output : 100       # e = 1.00
irsensor.read_i2c_address()   # Output : 91 

3.4) Setting the MLX90615 configuration

Emissivity depends on the material type, so it should be set to correctly measure the object temperature :

irsensor.set_emissivity(97)   # e = 0.97

The current I2C address of MLX90615 should be 0x00 to avoid errors while setting the new I2C address in EEPROM :

irsensor = mlx90615.MLX90615(i2c, address=0x00)
irsensor.set_i2c_address(0x5C)
irsensor.read_i2c_address()      # Output : 92        # 92 = 0x5C, checked

4) Benchmarks

When not stated, using MicroPython v1.12 firmware, with single float precision, default clock speed for the board, driver on internal flash memory and wireless disabled.

OOM = Out Of Memory (error), so the driver version can not fit in the available RAM.

Table for driver 'mlx90615.py' v0.2.1 with all features. '[simple]' means driver 'mlx90615_simple.py'/'mlx90615_microbit_simple.py' v0.2.1 with simple read functions :

MicrocontrollerImport RAM usage (kB)Import time (ms)[Simple] Import RAM usage (kB)[Simple] Import time (ms)Time to read object temp. (ms)Time to read object temp. without PEC (ms)
Pyboard Lite10.141291.3852.10961.3821.590.996
Pyboard v1.110.344177.3342.31337.6681.200.83
Pyboard D SF2W10.344161.652.31334.641.230.92
Pyboard D SF6W11.109128.292.10927.291.060.801
ESP8266OOMOOM2.547202.93.92.1
ESP3211.359304.52.67268.32.631.92
ESP32 PSRAM11.359563.52.672112.82.351.80
BBC Micro:bitOOMOOM2.547505.4910.54.5
WiPy 211.578684.462.813148.7121.9931.392
LoPy v111.578713.82.813154.572.0671.41
WiPy 311.297817.72.516164.092.0411.424
LoPy411.297829.02.516166.132.141.49
FiPy v1.011.344925.92.531189.21.9951.39
OpenMV M7------
OpenMV H7------
Sipeed MAix BiT------
ItsyBitsy M0------
ItsyBitsy M4------
Adafruit CLUE------

Table for driver 'mlx90615_no-errors.py'/'mlx90615_microbit_no-errors.py' v0.2.1 without error checking. '[simple]' means driver 'mlx90615_simple_no-errors.py'/'mlx90615_microbit_simple_no-errors.py' v0.2.1 with simple read functions and without error checking :

MicrocontrollerImport RAM usage (kB)Import time (ms)[Simple] Import RAM usage (kB)[Simple] Import time (ms)Time to read object temp. without PEC (ms)
ESP82664.6415641.125105.81.807
BBC Micro:bit2.672603.291.500240.424.13
ItsyBitsy M0-----

Pyboard Lite v1.0, default clock @ 96 MHz.
Pyboard v1.1, default clock @ 168 MHz.
Pyboard D SF2W, default clock @ 120 MHz.
Pyboard D SF6W, firmware with double precision, default clock @ 144 MHz.
ESP8266 in Wemos D1 Mini, default clock @ 80 MHz.
BBC Micro:bit, with MicroPython v1.9.2-34-gd64154c73, micro:bit v1.0.1, default clock @ 16 MHz.
ESP32 in M5Stack Core Basic, default clock @ 160 MHz.
ESP32 PSRAM in M5Stack Core Gray PSRAM, default clock @ 160 MHz.
LoPy v1 has a ESP32 without PSRAM, LoPy4 with PSRAM, both with Pycom MicroPython 1.20.2.rc7, default clock @ 160 MHz.

5) References

MLX90615 documentation :

  1. official Melexis MLX90615 web page, with datasheet, application notes, etc;
  2. Melexis Comparative Table of InfraRed Thermometer Family - MLX90614 and MLX90615;
  3. Comparative table between the MLX90614 and the MLX90615.

MLX90615 tutorials :

Other MLX90615 drivers :

  1. 'Arduino library for MLX90615 module from Seeed-Studio' has some features like optional SoftI2cMaster library, PEC/CRC-8 checking and writing to EEPROM registers;
  2. 'mlx90615-on-raspberryPi from paulvha' is a C driver and interactive software for Raspberry Pi, with many features and excelent documentation complementing the official MLX96015 documentation, like citation of the time delay needed after erasing/writing to the MLX90615 EEPROM;
  3. 'A minimal Arduino library for Melexis MLX90615' from skiselev has only some reading functions;
  4. MLX90615 library functions from Melexis is a reference C++ driver with many features and good documentation.