The MLX90640 on the RaspberryPi with FreeBSD

31 Mar 2024 - tsp
Last update 31 Mar 2024
Reading time 51 mins

What is the MLX90640?

The MLX90640 by Melexis is a very cheap far infrared thermal sensor that offers 32x24 pixels. It’s one of the cheapest FIR sensors available on the market and very well suited for robots and DIY applications like security monitoring, counting people, monitoring the front of Harvesters to prevent killing fawns hiding in the corn, preventing lawn mowing robots from killing animals, monitoring machines, etc. - the applications are endless. It’s also used by some car manufacturers to monitor presence inside the car (to automatically disable the belt notifications on seats where some weight has been placed but no one is sitting for example) and microwave ovens to monitor defrosting.

It interfaces via a simple 5V tolerant I2C interface though the part is a 3.3V part (you can directly interface with a AVR for example), consumes less than 25 mA of current and provides refresh rates between 0.5Hz and 64Hz. The noise is pretty low (around 0.1K at 1 Hz) - and one can of course always perform averaging afterwards when detecting non moving targets. They are so small that one can even mount them on ones own drones. The device is offered with two field of view configurations (55x35 degree vs 110x75 degree) and has embedded optics - one can of course use specialized infrared optics (I’m sometimes using ZnSe optics for FIR - this gets pretty expensive) and when one is using them outside one at least requires ZnSe windows in front of the sensors to not expose them to harsh environments. Those windows are available rather inexpensive (Note: This link is an Amazon affiliate link, the pages author profits from qualified purchases). The sensor can measure temperatures between $-40C$ to $300C$. The typical accuracy for absolute measurements is about $\pm 1C$.

When one wants to get started using the MLX90640 there are breakout boards readily available (Note: This link is an Amazon affiliate link, the pages author profits from qualified purchases) which is nice since one can separate hardware- from software development. Those boards can be directly attached to other development boards or devices like the RaspberryPi - which is what will happen in this blog post to first test the temperature recovery algorithm and be able to test the behavior of the system. Also since I’m using them also in Robots that are controlled via RaspberryPi boards this can be used when translated to native code.

Why Python?

In this blog article I’m going to look into the usage of the MLX90640 using Python. Even though it’s not my favorite programming language it allows for very simple hacking around and playing with various algorithms as well as visualizing results extremely easy. Since the FIR sensor requires some more sophisticated recovery and calibration algorithms this has been chosen to first try out how to talk with the sensor and check it’s capabilities before using it in an actual application.

Since I’m usually using FreeBSD on my RaspberryPi’s as well as on my workstations the whole article focuses on using it on this platform. The code should also work on other Unixoid systems like Linux though since most structures are similar. In the worst case one will have to adapt the lightweight $I^2C$ shim to support a different system. The following article has been written using FreeBSD 13.3.

Interfacing

Electrical interface

The used RaspberryPi is an RaspberryPi 3B. The electrical interface is extremely simple - when using the breakout board mentioned above one just has to attach:

Then one should be able to see the I2C device using the i2c command line tool:

exampleuser@generic:~ $ i2c -s -f /dev/iic0
Hardware may not support START/STOP scanning; trying less-reliable read method.
Scanning I2C devices on /dev/iic0: 3

In this case the device has been configured with the device address 0x33.

The used I2C interface

To access the I2C interface there would be a myriad of options. For example one could use the I2C methods of wiring pi or the Adafruit BusIO libraries. Since I wanted to keep dependencies to an absolut minimum and minimize abstractions to the absolut required minimum so translation to native code works flawless later on I’ve choosen to use my own I2C wrapper that’s also available on PyPi and described in an earlier blog post. This interface exposes my pylabdevs I2C base class interface so it can be easily interchanged with different implementations.

Some readout theory

First how does readout work from the MLX90640. To easier interleave processing with data aquisition and to increase reaction times the sensor always senses two different subpages in an alternating fashion. The sensor can be configured to do this either in an TV interleaved mode or in an chessboard pattern. Note that the refresh rate specifies the rate of subpage measurements, not of full frame measurements! To get a full frame one requires two cycles. One has to process always both subpages to get correct ambient temperature readings. Depending on the configured mode the device is just overwiting it’s RAM buffer all the time and just signalling new data has been written or waiting for a measurement trigger. We’re going to stay in default mode where the chessboard pattern is used and overwriting is enabled since it offers the simplest way of performing measurements. The chess pattern is used as default mode since it offers the highest precision.

Read out of data is a little bit teadious since it uses signed values that are hidden in some bitmasked fields so most of the code will be handling extraction of parameters from bitfields and converting unsigned two complements values in signed values.

Please note that the complicated compensation calculations are not optional. One really has to do offset compensation, different compesation for thermal ($K_{Ta}$) and voltage dependent ($K_V$) factors for each pixel, each read out row and read out column. The first one compensates for pixel manufacturing differences, the latter two for differences in shifting through the CMOS device. This is required since - in contrast to optical sensors - the number of charge carriers is very low for highly sensitive FIR devices and also manufacturing differences make a huge difference. We’ll see how this looks like shortly.

For each frame one:

For each pixel one then:

[ pix_{gain}(i,j) = raw(i,j) * K_{gain} ] [ pix_{o,ref}(i,j) = offset_{avg} + offset_{row}(i) * 2^{offset_{scale,row}} + offset_{column}(j) * 2^{offset_{scale,column}} + offset(i,j) * 2^{offset_{scale,remnant}} ]

As one can see this compensation happens based on the average offset of all pixels, an independent offset drift of the row and column which is caused by the charge shifting logic as well as a remnant part that is measured during the calibration process for each pixel.

[ pix_{os}(i,j) = pix_{gain}(i,j) - pix_{o,ref}(i,j) * \left(1 + K_{Ta}(i,j) * (T_a - T_{a,0}) \right) * \left( 1 + K_V(i,j) * (V_{dd} - V_{dd,0}) \right) ]

As one can see the factors $K_V$ and $K_{Ta}$ that are supplied for each and every pixel in calibration data are providing the linear response of the pixel around the calibration operation point at $V_{dd,0}=3.3V$ and $T_{a,0} = 25C$ - these are used to rescale the reference offset.

[ V_{IR,\epsilon comp}(i,j) = \frac{1}{\epsilon} * pix_{os}(i,j) ] [ V_{IR,comp}(i,j) = V_{IR,\epsilon comp}(i,j) - TGC * \left( (1-pattern(i,j)) * pix_{OS_CP_SP0} + pattern(i,j) * pix_{OS_CP_SP1} \right) ]

The idea is just to use the gradient compensation factor TGC that takes into account of the weighting of the compensation pixels due to their location in an unexposed area and rescale the offset of the reference compensation pixels.

[ \alpha(i,j) = \frac{\alpha_{ref} + \alpha_{CC,row}(i) * 2^{\alpha_{CC,scale,row}} + \alpha_{CC,col}(j) * 2^{\alpha_{CC,scale,col}} + \alpha_{pix}(i,j) * 2^{\alpha_{CC,scale,remnant}}}{2^{\alpha_{scale}}} ]

After that the temperature compensation and compensation using compensation pixels is applied - again assuming linear gradient response and linear temperature response:

[ \alpha_{comp}(i,j) = \left( \alpha(i,j) - TGC * \left( (1 - pattern(i,j)) * \alpha_{CP_SP_0} + pattern(i,j) * \alpha_{CP_SP_1} \right) \right) * (1 + K_{STa} * (T_a - T_{a,0} ) ]

In this step one also requires a measure for the IR signal that is reflected by the target object. The temperature measured by an object is made up of two components: The heat emitted by the object itself and the reflection of ambient infrared radiation. The reflected IR relates to a temperature $T_r$. Since this is a material property one only has access to this parameter whenever one has a specialized application - for general purpose applications one has no way of telling the amount of reflected energy. It’s a safe assumption to assume $T_r \approx T_a - 8$ for most situations the sensor has been designed for.

Now the most computation intensive part of the compensation is happening by applying the assuming the Stefan Boltzman law. This law describes the relation of radiated power with temperature and surface of a body:

[ P = \sigma * A * T^4 ]

In this law $P$ is the irradiated power, $A$ the surface of the black body radiator, $T$ the temperature and $\sigma$ the Stefan-Boltzmann constant ($\sigma \approx 5.67 * 10^{-8} \frac{W}{m^2 K^4}$).

Note that all temperatures in those calculations are supplied in Kelvin:

[ T_{aK4} = (T_a + 273.15)^4 \\ T_{rK4} = (T_r + 273.15)^4 \\ ]

Now we’re usually only interested in the irradiated values and not the reflected ones:

[ T_{a-r} = T_{rK4} - \frac{T_{rK4} - T_{aK4}}{\epsilon} ]

This is the difference of the reflected and absorbed heat with the background of reflected energy subtracted. Here we’ve again used the emissivity $\epsilon$ that is also a system parameter. Now one can calculate the sensitivity of the pixels at the estimated operating point:

[ S_{X}(i,j) = K_{STo,2} * {}^4\sqrt{\alpha_{comp}(i,j)^3 * V_{IR,compensated}(i,j) + \alpha_{comp}(i,j)^4 * T_{a-r}} ]

The final step is now to apply the inverse Stefan-Boltzman law and apply a linearized sensitivity model to the captured compensated data:

[ T_{O,basic}(i,j) = {}^4\sqrt{\frac{V_{IR,compensated}(i,j)}{\alpha_{comp}(i,j) * (1 - K_{STo,2} * 273.15) + S_X(i,j)} + T_{a-r}} - 273.15 ] [ T_{O,extra}(i,j) = {}^4\sqrt{\frac{V_{IR,compensated}(i,j)}{\alpha_{comp}(i,j) * \alpha_{corr,range R} * (1 + K_{STo R} * (T_{O,basic}(i,j) - CT_X))} + T_{a-r}} - 273.15 ]

As one can see the compensation model includes different factors to account for different systematic effects - like loosing charge carriers during shifting, different locations on the chip, different temperature responses as well as many linearized models during calibration. All of this is done to adjust for the different response of the pixels due to systematics and the nonlinear temperature dependence of the whole system. When one takes a look at the datasheet also per pixel noise is massively dependent on the pixel location with relation to the on chip analog to digital converter (i.e. it depends on the number of shifts and the time of charge carriers in the pipeline).

Actually getting data

Raw pixels

So first let’s get raw pixels. This can be done by simply reading two subpages out of the RAM that’s located at 0x0400 with one 16 bit word per pixel. One just has to wait for the data to be available by watching the Bit 3 in the control register at 0x8000. As soon as this bit is set the lower bits in the control register indicate which page has been read - one then clears the status bit and fetches the pixels associated with the given subpage. This has to be done for both subpages!

This is extremly simple and exposed in my example code in the _fetch_raw_frame_sync method (that assumes chessboard pattern readout):

    def _fetch_raw_frame_sync(self):
        framedata = np.empty((self._rows, self._cols))
        fetchedFrames = 0

        # Wait till data ready flag ...
        for _ in range(2):
            while True:
                r = self._i2c_read_word(0x8000)[0]
                if r & 0x08:
                    r = r & 0xFFF7
                    self._i2c_write_word(0x8000, r)
                    break
            fetchedSubpage = r & 0x01

            # Checkerboard fetch
            for iPixelH in range(int(self._cols * self._rows / 2)):
                iPixel = iPixelH * 2 + fetchedSubpage

                iCol = iPixel % self._cols
                iRow = int(iPixel / self._cols)
                framedata[iRow,iCol] = self._i2c_read_word(0x400 + iPixel)[0]
                if framedata[iRow,iCol] > 32766:
                    framedata[iRow,iCol] = framedata[iRow,iCol] - 65536

   return framedata

So what can one do with uncompensated pixels? On first sight the results don’t look to useful:

import numpy as np
import matplotlib.pyplot as plt

data = np.asarray([[65473.0, 65468.0, 65474.0, 65461.0, 65472.0, 65465.0, 65471.0, 65457.0, 65467.0, 65458.0, 65466.0, 65452.0, 65465.0, 65454.0, 65473.0, 65455.0, 65465.0, 65452.0, 65465.0, 65446.0, 65462.0, 65449.0, 65460.0, 65443.0, 65463.0, 65446.0, 65459.0, 65441.0, 65458.0, 65444.0, 65460.0, 65433.0], [65465.0, 65459.0, 65456.0, 65461.0, 65464.0, 65455.0, 65454.0, 65456.0, 65460.0, 65449.0, 65451.0, 65449.0, 65456.0, 65448.0, 65469.0, 65463.0, 65460.0, 65445.0, 65450.0, 65446.0, 65458.0, 65440.0, 65448.0, 65444.0, 65458.0, 65441.0, 65446.0, 65442.0, 65453.0, 65436.0, 65447.0, 65434.0], [65472.0, 65466.0, 65472.0, 65460.0, 65471.0, 65463.0, 65472.0, 65459.0, 65467.0, 65459.0, 65468.0, 65454.0, 65463.0, 65456.0, 65486.0, 65471.0, 65474.0, 65452.0, 65463.0, 65444.0, 65462.0, 65446.0, 65462.0, 65442.0, 65463.0, 65446.0, 65461.0, 65440.0, 65461.0, 65443.0, 65462.0, 65435.0], [65465.0, 65458.0, 65456.0, 65461.0, 65464.0, 65455.0, 65454.0, 65456.0, 65459.0, 65454.0, 65464.0, 65457.0, 65457.0, 65445.0, 65467.0, 65470.0, 65472.0, 65447.0, 65446.0, 65446.0, 65459.0, 65440.0, 65447.0, 65441.0, 65458.0, 65438.0, 65446.0, 65440.0, 65454.0, 65435.0, 65448.0, 65433.0], [65474.0, 65466.0, 65470.0, 65461.0, 65474.0, 65463.0, 65472.0, 65459.0, 65469.0, 65460.0, 65487.0, 65470.0, 65472.0, 65456.0, 65475.0, 65468.0, 65489.0, 65467.0, 65464.0, 65446.0, 65465.0, 65447.0, 65463.0, 65445.0, 65463.0, 65447.0, 65461.0, 65441.0, 65462.0, 65449.0, 65465.0, 65438.0], [65467.0, 65456.0, 65456.0, 65460.0, 65465.0, 65454.0, 65455.0, 65457.0, 65461.0, 65448.0, 65466.0, 65470.0, 65469.0, 65454.0, 65456.0, 65463.0, 65483.0, 65461.0, 65451.0, 65443.0, 65455.0, 65438.0, 65447.0, 65444.0, 65457.0, 65438.0, 65443.0, 65441.0, 65461.0, 65447.0, 65458.0, 65440.0], [65470.0, 65465.0, 65471.0, 65461.0, 65470.0, 65462.0, 65472.0, 65459.0, 65481.0, 65472.0, 65472.0, 65465.0, 65488.0, 65475.0, 65469.0, 65458.0, 65491.0, 65478.0, 65470.0, 65448.0, 65461.0, 65445.0, 65462.0, 65442.0, 65461.0, 65445.0, 65464.0, 65457.0, 65484.0, 65468.0, 65476.0, 65441.0], [65463.0, 65454.0, 65454.0, 65458.0, 65460.0, 65450.0, 65454.0, 65456.0, 65475.0, 65468.0, 65458.0, 65458.0, 65480.0, 65469.0, 65458.0, 65455.0, 65486.0, 65471.0, 65462.0, 65451.0, 65454.0, 65438.0, 65444.0, 65439.0, 65454.0, 65438.0, 65457.0, 65460.0, 65479.0, 65459.0, 65453.0, 65438.0], [65470.0, 65463.0, 65469.0, 65460.0, 65469.0, 65463.0, 65470.0, 65457.0, 65476.0, 65472.0, 65489.0, 65472.0, 65482.0, 65477.0, 65493.0, 65476.0, 65494.0, 65485.0, 65492.0, 65472.0, 65468.0, 65450.0, 65460.0, 65442.0, 65463.0, 65453.0, 65482.0, 65468.0, 65480.0, 65452.0, 65464.0, 65435.0], [65462.0, 65449.0, 65448.0, 65456.0, 65461.0, 65451.0, 65449.0, 65453.0, 65464.0, 65453.0, 65469.0, 65471.0, 65473.0, 65465.0, 65477.0, 65476.0, 65488.0, 65473.0, 65477.0, 65475.0, 65469.0, 65444.0, 65444.0, 65438.0, 65461.0, 65449.0, 65468.0, 65465.0, 65466.0, 65442.0, 65447.0, 65434.0], [65472.0, 65465.0, 65471.0, 65460.0, 65472.0, 65462.0, 65469.0, 65457.0, 65470.0, 65459.0, 65473.0, 65469.0, 65493.0, 65484.0, 65494.0, 65480.0, 65500.0, 65486.0, 65498.0, 65484.0, 65496.0, 65480.0, 65479.0, 65465.0, 65489.0, 65475.0, 65484.0, 65463.0, 65464.0, 65445.0, 65463.0, 65433.0], [65460.0, 65452.0, 65450.0, 65454.0, 65460.0, 65449.0, 65451.0, 65452.0, 65458.0, 65447.0, 65450.0, 65456.0, 65483.0, 65472.0, 65478.0, 65477.0, 65493.0, 65477.0, 65482.0, 65481.0, 65489.0, 65471.0, 65473.0, 65472.0, 65485.0, 65464.0, 65469.0, 65460.0, 65454.0, 65437.0, 65444.0, 65429.0], [65467.0, 65467.0, 65467.0, 65457.0, 65468.0, 65463.0, 65473.0, 65463.0, 65468.0, 65460.0, 65466.0, 65452.0, 65484.0, 65481.0, 65497.0, 65483.0, 65503.0, 65489.0, 65501.0, 65482.0, 65499.0, 65482.0, 65493.0, 65475.0, 65492.0, 65474.0, 65485.0, 65454.0, 65462.0, 65447.0, 65457.0, 65432.0], [65456.0, 65450.0, 65446.0, 65451.0, 65454.0, 65450.0, 65456.0, 65461.0, 65464.0, 65454.0, 65453.0, 65453.0, 65477.0, 65470.0, 65478.0, 65479.0, 65493.0, 65477.0, 65482.0, 65480.0, 65488.0, 65472.0, 65473.0, 65470.0, 65484.0, 65462.0, 65466.0, 65450.0, 65453.0, 65434.0, 65442.0, 65430.0], [65466.0, 65464.0, 65466.0, 65456.0, 65466.0, 65461.0, 65470.0, 65463.0, 65480.0, 65473.0, 65485.0, 65477.0, 65489.0, 65481.0, 65498.0, 65483.0, 65501.0, 65492.0, 65502.0, 65487.0, 65499.0, 65483.0, 65489.0, 65473.0, 65494.0, 65476.0, 65476.0, 65447.0, 65458.0, 65444.0, 65458.0, 65431.0], [65453.0, 65445.0, 65441.0, 65446.0, 65453.0, 65444.0, 65446.0, 65450.0, 65461.0, 65451.0, 65461.0, 65467.0, 65477.0, 65468.0, 65476.0, 65477.0, 65493.0, 65478.0, 65485.0, 65482.0, 65487.0, 65470.0, 65474.0, 65469.0, 65482.0, 65465.0, 65451.0, 65441.0, 65447.0, 65433.0, 65440.0, 65428.0], [65468.0, 65464.0, 65463.0, 65455.0, 65464.0, 65459.0, 65464.0, 65452.0, 65466.0, 65455.0, 65464.0, 65452.0, 65488.0, 65483.0, 65493.0, 65479.0, 65500.0, 65489.0, 65500.0, 65487.0, 65498.0, 65484.0, 65491.0, 65473.0, 65491.0, 65475.0, 65463.0, 65443.0, 65456.0, 65442.0, 65457.0, 65432.0], [65451.0, 65446.0, 65442.0, 65447.0, 65451.0, 65441.0, 65440.0, 65442.0, 65451.0, 65438.0, 65442.0, 65442.0, 65467.0, 65464.0, 65472.0, 65473.0, 65488.0, 65475.0, 65478.0, 65480.0, 65486.0, 65470.0, 65472.0, 65468.0, 65481.0, 65462.0, 65443.0, 65438.0, 65446.0, 65430.0, 65440.0, 65426.0], [65460.0, 65460.0, 65463.0, 65458.0, 65462.0, 65458.0, 65461.0, 65452.0, 65460.0, 65454.0, 65462.0, 65448.0, 65460.0, 65451.0, 65482.0, 65475.0, 65498.0, 65486.0, 65494.0, 65481.0, 65496.0, 65483.0, 65490.0, 65474.0, 65491.0, 65473.0, 65462.0, 65443.0, 65454.0, 65442.0, 65456.0, 65432.0], [65446.0, 65438.0, 65436.0, 65447.0, 65449.0, 65438.0, 65437.0, 65442.0, 65447.0, 65435.0, 65437.0, 65439.0, 65444.0, 65433.0, 65452.0, 65460.0, 65482.0, 65469.0, 65472.0, 65472.0, 65482.0, 65467.0, 65469.0, 65468.0, 65481.0, 65462.0, 65442.0, 65438.0, 65444.0, 65428.0, 65436.0, 65428.0], [65457.0, 65460.0, 65458.0, 65452.0, 65459.0, 65457.0, 65457.0, 65449.0, 65459.0, 65453.0, 65458.0, 65445.0, 65458.0, 65451.0, 65455.0, 65440.0, 65482.0, 65474.0, 65489.0, 65476.0, 65489.0, 65480.0, 65491.0, 65477.0, 65491.0, 65475.0, 65470.0, 65446.0, 65455.0, 65442.0, 65454.0, 65433.0], [65442.0, 65439.0, 65435.0, 65441.0, 65444.0, 65436.0, 65431.0, 65437.0, 65444.0, 65432.0, 65433.0, 65436.0, 65444.0, 65433.0, 65430.0, 65429.0, 65456.0, 65447.0, 65466.0, 65467.0, 65478.0, 65465.0, 65467.0, 65468.0, 65477.0, 65461.0, 65452.0, 65440.0, 65445.0, 65428.0, 65436.0, 65426.0], [65459.0, 65462.0, 65459.0, 65455.0, 65461.0, 65456.0, 65459.0, 65448.0, 65458.0, 65455.0, 65455.0, 65447.0, 65457.0, 65448.0, 65452.0, 65440.0, 65456.0, 65451.0, 65469.0, 65461.0, 65492.0, 65481.0, 65490.0, 65474.0, 65487.0, 65475.0, 65479.0, 65455.0, 65456.0, 65445.0, 65453.0, 65433.0], [65432.0, 65432.0, 65421.0, 65431.0, 65434.0, 65428.0, 65423.0, 65426.0, 65433.0, 65426.0, 65422.0, 65426.0, 65432.0, 65422.0, 65421.0, 65422.0, 65433.0, 65421.0, 65431.0, 65433.0, 65468.0, 65454.0, 65459.0, 65457.0, 65462.0, 65445.0, 65449.0, 65440.0, 65437.0, 65421.0, 65426.0, 65416.0]])

for i in range(len(data)):
    for j in range(len(data[i])):
        if data[i][j] > 65536/2:
            data[i][j] = data[i][j] - 65536

# Normalize

data = data - np.min(data)
data = data / np.max(data)

fig, ax = plt.subplots(1, figsize=(6.4*2, 4.8*2))
ax.imshow(data, cmap="plasma")
ax.set_title("Raw pixel data")
plt.savefig("MLX90640_Raspi_RawPixel01.png")
plt.show()

But even with those simple samples one can do actual measurements in case one does only want to produce fancy images and does not care about absolute values. This can be done by simply performing a reference measurement without the object in place and then applying a simple subtraction:

[ I(i,j) = I_{meas}(i,j) - I_{back}(i,j) ]

This is an approach used in many different physical applications and is also highly efficient for example for my measurement library for the AvaSpec 2048-2 spectrometer as well as NMR, cold atoms and electron spin resonance experiments.

Trying this with the MLX90640 results in useable measurement data:

data1 = np.asarray([[65472.0, 65467.0, 65471.0, 65459.0, 65469.0, 65464.0, 65469.0, 65457.0, 65464.0, 65452.0, 65466.0, 65447.0, 65461.0, 65450.0, 65463.0, 65445.0, 65463.0, 65450.0, 65464.0, 65446.0, 65461.0, 65448.0, 65459.0, 65440.0, 65460.0, 65445.0, 65459.0, 65439.0, 65456.0, 65441.0, 65460.0, 65431.0], [65465.0, 65461.0, 65456.0, 65459.0, 65462.0, 65456.0, 65453.0, 65452.0, 65458.0, 65449.0, 65448.0, 65447.0, 65455.0, 65443.0, 65446.0, 65443.0, 65456.0, 65442.0, 65447.0, 65444.0, 65455.0, 65441.0, 65445.0, 65441.0, 65456.0, 65438.0, 65444.0, 65440.0, 65451.0, 65436.0, 65446.0, 65433.0], [65471.0, 65462.0, 65470.0, 65459.0, 65469.0, 65460.0, 65467.0, 65455.0, 65463.0, 65451.0, 65464.0, 65447.0, 65460.0, 65450.0, 65461.0, 65444.0, 65463.0, 65448.0, 65460.0, 65442.0, 65462.0, 65445.0, 65460.0, 65440.0, 65463.0, 65444.0, 65460.0, 65438.0, 65460.0, 65441.0, 65461.0, 65433.0], [65463.0, 65455.0, 65453.0, 65458.0, 65462.0, 65454.0, 65451.0, 65453.0, 65454.0, 65445.0, 65448.0, 65447.0, 65454.0, 65444.0, 65446.0, 65444.0, 65456.0, 65441.0, 65444.0, 65443.0, 65455.0, 65439.0, 65446.0, 65441.0, 65456.0, 65438.0, 65445.0, 65439.0, 65452.0, 65434.0, 65445.0, 65431.0], [65473.0, 65462.0, 65470.0, 65459.0, 65473.0, 65461.0, 65469.0, 65455.0, 65464.0, 65451.0, 65465.0, 65446.0, 65462.0, 65452.0, 65461.0, 65445.0, 65464.0, 65448.0, 65460.0, 65444.0, 65462.0, 65444.0, 65460.0, 65440.0, 65461.0, 65443.0, 65458.0, 65441.0, 65458.0, 65442.0, 65459.0, 65433.0], [65464.0, 65454.0, 65453.0, 65456.0, 65463.0, 65452.0, 65453.0, 65454.0, 65456.0, 65443.0, 65447.0, 65445.0, 65455.0, 65443.0, 65446.0, 65445.0, 65456.0, 65441.0, 65444.0, 65441.0, 65454.0, 65438.0, 65445.0, 65441.0, 65456.0, 65438.0, 65444.0, 65440.0, 65451.0, 65437.0, 65445.0, 65431.0], [65469.0, 65463.0, 65470.0, 65459.0, 65469.0, 65459.0, 65469.0, 65454.0, 65465.0, 65452.0, 65461.0, 65447.0, 65462.0, 65451.0, 65459.0, 65444.0, 65461.0, 65448.0, 65459.0, 65440.0, 65459.0, 65445.0, 65459.0, 65439.0, 65458.0, 65442.0, 65459.0, 65438.0, 65458.0, 65440.0, 65460.0, 65432.0], [65463.0, 65455.0, 65452.0, 65457.0, 65461.0, 65452.0, 65450.0, 65452.0, 65457.0, 65444.0, 65443.0, 65446.0, 65454.0, 65441.0, 65444.0, 65441.0, 65453.0, 65438.0, 65443.0, 65441.0, 65452.0, 65436.0, 65444.0, 65438.0, 65452.0, 65438.0, 65441.0, 65436.0, 65450.0, 65432.0, 65445.0, 65432.0], [65469.0, 65461.0, 65467.0, 65459.0, 65467.0, 65461.0, 65467.0, 65454.0, 65466.0, 65455.0, 65457.0, 65444.0, 65459.0, 65450.0, 65459.0, 65443.0, 65461.0, 65447.0, 65457.0, 65440.0, 65460.0, 65446.0, 65459.0, 65440.0, 65459.0, 65442.0, 65458.0, 65437.0, 65457.0, 65441.0, 65459.0, 65433.0], [65460.0, 65451.0, 65446.0, 65454.0, 65459.0, 65452.0, 65448.0, 65451.0, 65457.0, 65445.0, 65439.0, 65438.0, 65450.0, 65440.0, 65442.0, 65441.0, 65452.0, 65436.0, 65440.0, 65439.0, 65453.0, 65437.0, 65440.0, 65438.0, 65452.0, 65436.0, 65442.0, 65438.0, 65449.0, 65432.0, 65444.0, 65432.0], [65470.0, 65463.0, 65468.0, 65459.0, 65470.0, 65462.0, 65467.0, 65454.0, 65467.0, 65455.0, 65456.0, 65444.0, 65461.0, 65449.0, 65457.0, 65443.0, 65460.0, 65445.0, 65456.0, 65443.0, 65458.0, 65445.0, 65455.0, 65438.0, 65459.0, 65443.0, 65455.0, 65437.0, 65455.0, 65442.0, 65458.0, 65432.0], [65459.0, 65452.0, 65449.0, 65452.0, 65459.0, 65450.0, 65447.0, 65451.0, 65456.0, 65445.0, 65442.0, 65440.0, 65451.0, 65439.0, 65439.0, 65437.0, 65452.0, 65436.0, 65441.0, 65439.0, 65450.0, 65436.0, 65439.0, 65435.0, 65452.0, 65434.0, 65438.0, 65434.0, 65447.0, 65433.0, 65443.0, 65428.0], [65466.0, 65462.0, 65466.0, 65454.0, 65466.0, 65459.0, 65464.0, 65453.0, 65463.0, 65456.0, 65462.0, 65445.0, 65453.0, 65449.0, 65458.0, 65439.0, 65456.0, 65445.0, 65456.0, 65438.0, 65458.0, 65444.0, 65456.0, 65439.0, 65460.0, 65441.0, 65457.0, 65435.0, 65456.0, 65440.0, 65456.0, 65430.0], [65454.0, 65450.0, 65444.0, 65447.0, 65453.0, 65446.0, 65444.0, 65446.0, 65451.0, 65443.0, 65441.0, 65439.0, 65443.0, 65435.0, 65437.0, 65437.0, 65448.0, 65434.0, 65436.0, 65432.0, 65450.0, 65434.0, 65438.0, 65437.0, 65450.0, 65431.0, 65438.0, 65431.0, 65445.0, 65432.0, 65441.0, 65429.0], [65464.0, 65461.0, 65463.0, 65454.0, 65464.0, 65460.0, 65463.0, 65453.0, 65464.0, 65454.0, 65460.0, 65447.0, 65451.0, 65444.0, 65456.0, 65439.0, 65459.0, 65445.0, 65456.0, 65438.0, 65455.0, 65443.0, 65455.0, 65439.0, 65457.0, 65440.0, 65455.0, 65436.0, 65453.0, 65440.0, 65456.0, 65429.0], [65452.0, 65444.0, 65440.0, 65445.0, 65453.0, 65445.0, 65442.0, 65446.0, 65451.0, 65442.0, 65439.0, 65441.0, 65441.0, 65432.0, 65436.0, 65435.0, 65447.0, 65433.0, 65436.0, 65434.0, 65446.0, 65432.0, 65435.0, 65433.0, 65449.0, 65431.0, 65438.0, 65433.0, 65444.0, 65430.0, 65438.0, 65425.0], [65465.0, 65464.0, 65463.0, 65455.0, 65463.0, 65457.0, 65460.0, 65449.0, 65462.0, 65452.0, 65458.0, 65444.0, 65456.0, 65445.0, 65454.0, 65439.0, 65457.0, 65445.0, 65454.0, 65438.0, 65455.0, 65443.0, 65451.0, 65435.0, 65456.0, 65442.0, 65452.0, 65434.0, 65450.0, 65439.0, 65455.0, 65429.0], [65450.0, 65446.0, 65441.0, 65445.0, 65450.0, 65440.0, 65439.0, 65441.0, 65449.0, 65438.0, 65440.0, 65439.0, 65444.0, 65431.0, 65431.0, 65433.0, 65443.0, 65433.0, 65432.0, 65434.0, 65443.0, 65429.0, 65432.0, 65430.0, 65445.0, 65429.0, 65433.0, 65431.0, 65443.0, 65428.0, 65438.0, 65424.0], [65457.0, 65460.0, 65459.0, 65455.0, 65460.0, 65456.0, 65459.0, 65450.0, 65460.0, 65451.0, 65457.0, 65447.0, 65454.0, 65442.0, 65450.0, 65438.0, 65456.0, 65443.0, 65453.0, 65437.0, 65453.0, 65442.0, 65451.0, 65436.0, 65453.0, 65440.0, 65452.0, 65437.0, 65452.0, 65438.0, 65454.0, 65432.0], [65445.0, 65440.0, 65436.0, 65444.0, 65447.0, 65438.0, 65436.0, 65439.0, 65445.0, 65437.0, 65435.0, 65439.0, 65440.0, 65430.0, 65429.0, 65428.0, 65443.0, 65430.0, 65431.0, 65430.0, 65439.0, 65429.0, 65431.0, 65429.0, 65443.0, 65425.0, 65433.0, 65431.0, 65441.0, 65426.0, 65436.0, 65427.0], [65456.0, 65459.0, 65457.0, 65451.0, 65455.0, 65456.0, 65455.0, 65449.0, 65458.0, 65451.0, 65457.0, 65443.0, 65455.0, 65447.0, 65448.0, 65436.0, 65455.0, 65441.0, 65450.0, 65436.0, 65450.0, 65442.0, 65449.0, 65438.0, 65450.0, 65440.0, 65452.0, 65436.0, 65452.0, 65439.0, 65453.0, 65432.0], [65441.0, 65439.0, 65433.0, 65438.0, 65441.0, 65434.0, 65430.0, 65437.0, 65441.0, 65432.0, 65431.0, 65434.0, 65440.0, 65432.0, 65427.0, 65424.0, 65440.0, 65425.0, 65428.0, 65426.0, 65438.0, 65428.0, 65428.0, 65427.0, 65439.0, 65425.0, 65430.0, 65427.0, 65441.0, 65427.0, 65433.0, 65426.0], [65457.0, 65462.0, 65457.0, 65452.0, 65459.0, 65456.0, 65455.0, 65447.0, 65456.0, 65452.0, 65453.0, 65445.0, 65454.0, 65447.0, 65449.0, 65437.0, 65453.0, 65445.0, 65451.0, 65435.0, 65453.0, 65441.0, 65451.0, 65437.0, 65450.0, 65440.0, 65449.0, 65437.0, 65451.0, 65440.0, 65451.0, 65432.0], [65431.0, 65434.0, 65421.0, 65430.0, 65433.0, 65425.0, 65421.0, 65426.0, 65432.0, 65426.0, 65421.0, 65424.0, 65431.0, 65420.0, 65419.0, 65419.0, 65431.0, 65419.0, 65420.0, 65420.0, 65430.0, 65417.0, 65420.0, 65419.0, 65428.0, 65418.0, 65421.0, 65415.0, 65432.0, 65418.0, 65423.0, 65413.0]])
data2 = np.asarray([[65473.0, 65468.0, 65474.0, 65461.0, 65472.0, 65465.0, 65471.0, 65457.0, 65467.0, 65458.0, 65466.0, 65452.0, 65465.0, 65454.0, 65473.0, 65455.0, 65465.0, 65452.0, 65465.0, 65446.0, 65462.0, 65449.0, 65460.0, 65443.0, 65463.0, 65446.0, 65459.0, 65441.0, 65458.0, 65444.0, 65460.0, 65433.0], [65465.0, 65459.0, 65456.0, 65461.0, 65464.0, 65455.0, 65454.0, 65456.0, 65460.0, 65449.0, 65451.0, 65449.0, 65456.0, 65448.0, 65469.0, 65463.0, 65460.0, 65445.0, 65450.0, 65446.0, 65458.0, 65440.0, 65448.0, 65444.0, 65458.0, 65441.0, 65446.0, 65442.0, 65453.0, 65436.0, 65447.0, 65434.0], [65472.0, 65466.0, 65472.0, 65460.0, 65471.0, 65463.0, 65472.0, 65459.0, 65467.0, 65459.0, 65468.0, 65454.0, 65463.0, 65456.0, 65486.0, 65471.0, 65474.0, 65452.0, 65463.0, 65444.0, 65462.0, 65446.0, 65462.0, 65442.0, 65463.0, 65446.0, 65461.0, 65440.0, 65461.0, 65443.0, 65462.0, 65435.0], [65465.0, 65458.0, 65456.0, 65461.0, 65464.0, 65455.0, 65454.0, 65456.0, 65459.0, 65454.0, 65464.0, 65457.0, 65457.0, 65445.0, 65467.0, 65470.0, 65472.0, 65447.0, 65446.0, 65446.0, 65459.0, 65440.0, 65447.0, 65441.0, 65458.0, 65438.0, 65446.0, 65440.0, 65454.0, 65435.0, 65448.0, 65433.0], [65474.0, 65466.0, 65470.0, 65461.0, 65474.0, 65463.0, 65472.0, 65459.0, 65469.0, 65460.0, 65487.0, 65470.0, 65472.0, 65456.0, 65475.0, 65468.0, 65489.0, 65467.0, 65464.0, 65446.0, 65465.0, 65447.0, 65463.0, 65445.0, 65463.0, 65447.0, 65461.0, 65441.0, 65462.0, 65449.0, 65465.0, 65438.0], [65467.0, 65456.0, 65456.0, 65460.0, 65465.0, 65454.0, 65455.0, 65457.0, 65461.0, 65448.0, 65466.0, 65470.0, 65469.0, 65454.0, 65456.0, 65463.0, 65483.0, 65461.0, 65451.0, 65443.0, 65455.0, 65438.0, 65447.0, 65444.0, 65457.0, 65438.0, 65443.0, 65441.0, 65461.0, 65447.0, 65458.0, 65440.0], [65470.0, 65465.0, 65471.0, 65461.0, 65470.0, 65462.0, 65472.0, 65459.0, 65481.0, 65472.0, 65472.0, 65465.0, 65488.0, 65475.0, 65469.0, 65458.0, 65491.0, 65478.0, 65470.0, 65448.0, 65461.0, 65445.0, 65462.0, 65442.0, 65461.0, 65445.0, 65464.0, 65457.0, 65484.0, 65468.0, 65476.0, 65441.0], [65463.0, 65454.0, 65454.0, 65458.0, 65460.0, 65450.0, 65454.0, 65456.0, 65475.0, 65468.0, 65458.0, 65458.0, 65480.0, 65469.0, 65458.0, 65455.0, 65486.0, 65471.0, 65462.0, 65451.0, 65454.0, 65438.0, 65444.0, 65439.0, 65454.0, 65438.0, 65457.0, 65460.0, 65479.0, 65459.0, 65453.0, 65438.0], [65470.0, 65463.0, 65469.0, 65460.0, 65469.0, 65463.0, 65470.0, 65457.0, 65476.0, 65472.0, 65489.0, 65472.0, 65482.0, 65477.0, 65493.0, 65476.0, 65494.0, 65485.0, 65492.0, 65472.0, 65468.0, 65450.0, 65460.0, 65442.0, 65463.0, 65453.0, 65482.0, 65468.0, 65480.0, 65452.0, 65464.0, 65435.0], [65462.0, 65449.0, 65448.0, 65456.0, 65461.0, 65451.0, 65449.0, 65453.0, 65464.0, 65453.0, 65469.0, 65471.0, 65473.0, 65465.0, 65477.0, 65476.0, 65488.0, 65473.0, 65477.0, 65475.0, 65469.0, 65444.0, 65444.0, 65438.0, 65461.0, 65449.0, 65468.0, 65465.0, 65466.0, 65442.0, 65447.0, 65434.0], [65472.0, 65465.0, 65471.0, 65460.0, 65472.0, 65462.0, 65469.0, 65457.0, 65470.0, 65459.0, 65473.0, 65469.0, 65493.0, 65484.0, 65494.0, 65480.0, 65500.0, 65486.0, 65498.0, 65484.0, 65496.0, 65480.0, 65479.0, 65465.0, 65489.0, 65475.0, 65484.0, 65463.0, 65464.0, 65445.0, 65463.0, 65433.0], [65460.0, 65452.0, 65450.0, 65454.0, 65460.0, 65449.0, 65451.0, 65452.0, 65458.0, 65447.0, 65450.0, 65456.0, 65483.0, 65472.0, 65478.0, 65477.0, 65493.0, 65477.0, 65482.0, 65481.0, 65489.0, 65471.0, 65473.0, 65472.0, 65485.0, 65464.0, 65469.0, 65460.0, 65454.0, 65437.0, 65444.0, 65429.0], [65467.0, 65467.0, 65467.0, 65457.0, 65468.0, 65463.0, 65473.0, 65463.0, 65468.0, 65460.0, 65466.0, 65452.0, 65484.0, 65481.0, 65497.0, 65483.0, 65503.0, 65489.0, 65501.0, 65482.0, 65499.0, 65482.0, 65493.0, 65475.0, 65492.0, 65474.0, 65485.0, 65454.0, 65462.0, 65447.0, 65457.0, 65432.0], [65456.0, 65450.0, 65446.0, 65451.0, 65454.0, 65450.0, 65456.0, 65461.0, 65464.0, 65454.0, 65453.0, 65453.0, 65477.0, 65470.0, 65478.0, 65479.0, 65493.0, 65477.0, 65482.0, 65480.0, 65488.0, 65472.0, 65473.0, 65470.0, 65484.0, 65462.0, 65466.0, 65450.0, 65453.0, 65434.0, 65442.0, 65430.0], [65466.0, 65464.0, 65466.0, 65456.0, 65466.0, 65461.0, 65470.0, 65463.0, 65480.0, 65473.0, 65485.0, 65477.0, 65489.0, 65481.0, 65498.0, 65483.0, 65501.0, 65492.0, 65502.0, 65487.0, 65499.0, 65483.0, 65489.0, 65473.0, 65494.0, 65476.0, 65476.0, 65447.0, 65458.0, 65444.0, 65458.0, 65431.0], [65453.0, 65445.0, 65441.0, 65446.0, 65453.0, 65444.0, 65446.0, 65450.0, 65461.0, 65451.0, 65461.0, 65467.0, 65477.0, 65468.0, 65476.0, 65477.0, 65493.0, 65478.0, 65485.0, 65482.0, 65487.0, 65470.0, 65474.0, 65469.0, 65482.0, 65465.0, 65451.0, 65441.0, 65447.0, 65433.0, 65440.0, 65428.0], [65468.0, 65464.0, 65463.0, 65455.0, 65464.0, 65459.0, 65464.0, 65452.0, 65466.0, 65455.0, 65464.0, 65452.0, 65488.0, 65483.0, 65493.0, 65479.0, 65500.0, 65489.0, 65500.0, 65487.0, 65498.0, 65484.0, 65491.0, 65473.0, 65491.0, 65475.0, 65463.0, 65443.0, 65456.0, 65442.0, 65457.0, 65432.0], [65451.0, 65446.0, 65442.0, 65447.0, 65451.0, 65441.0, 65440.0, 65442.0, 65451.0, 65438.0, 65442.0, 65442.0, 65467.0, 65464.0, 65472.0, 65473.0, 65488.0, 65475.0, 65478.0, 65480.0, 65486.0, 65470.0, 65472.0, 65468.0, 65481.0, 65462.0, 65443.0, 65438.0, 65446.0, 65430.0, 65440.0, 65426.0], [65460.0, 65460.0, 65463.0, 65458.0, 65462.0, 65458.0, 65461.0, 65452.0, 65460.0, 65454.0, 65462.0, 65448.0, 65460.0, 65451.0, 65482.0, 65475.0, 65498.0, 65486.0, 65494.0, 65481.0, 65496.0, 65483.0, 65490.0, 65474.0, 65491.0, 65473.0, 65462.0, 65443.0, 65454.0, 65442.0, 65456.0, 65432.0], [65446.0, 65438.0, 65436.0, 65447.0, 65449.0, 65438.0, 65437.0, 65442.0, 65447.0, 65435.0, 65437.0, 65439.0, 65444.0, 65433.0, 65452.0, 65460.0, 65482.0, 65469.0, 65472.0, 65472.0, 65482.0, 65467.0, 65469.0, 65468.0, 65481.0, 65462.0, 65442.0, 65438.0, 65444.0, 65428.0, 65436.0, 65428.0], [65457.0, 65460.0, 65458.0, 65452.0, 65459.0, 65457.0, 65457.0, 65449.0, 65459.0, 65453.0, 65458.0, 65445.0, 65458.0, 65451.0, 65455.0, 65440.0, 65482.0, 65474.0, 65489.0, 65476.0, 65489.0, 65480.0, 65491.0, 65477.0, 65491.0, 65475.0, 65470.0, 65446.0, 65455.0, 65442.0, 65454.0, 65433.0], [65442.0, 65439.0, 65435.0, 65441.0, 65444.0, 65436.0, 65431.0, 65437.0, 65444.0, 65432.0, 65433.0, 65436.0, 65444.0, 65433.0, 65430.0, 65429.0, 65456.0, 65447.0, 65466.0, 65467.0, 65478.0, 65465.0, 65467.0, 65468.0, 65477.0, 65461.0, 65452.0, 65440.0, 65445.0, 65428.0, 65436.0, 65426.0], [65459.0, 65462.0, 65459.0, 65455.0, 65461.0, 65456.0, 65459.0, 65448.0, 65458.0, 65455.0, 65455.0, 65447.0, 65457.0, 65448.0, 65452.0, 65440.0, 65456.0, 65451.0, 65469.0, 65461.0, 65492.0, 65481.0, 65490.0, 65474.0, 65487.0, 65475.0, 65479.0, 65455.0, 65456.0, 65445.0, 65453.0, 65433.0], [65432.0, 65432.0, 65421.0, 65431.0, 65434.0, 65428.0, 65423.0, 65426.0, 65433.0, 65426.0, 65422.0, 65426.0, 65432.0, 65422.0, 65421.0, 65422.0, 65433.0, 65421.0, 65431.0, 65433.0, 65468.0, 65454.0, 65459.0, 65457.0, 65462.0, 65445.0, 65449.0, 65440.0, 65437.0, 65421.0, 65426.0, 65416.0]])
data3 = np.asarray([[1.0, 1.0, 3.0, 2.0, 3.0, 1.0, 2.0, 0.0, 3.0, 6.0, 0.0, 5.0, 4.0, 4.0, 10.0, 10.0, 2.0, 2.0, 1.0, 0.0, 1.0, 1.0, 1.0, 3.0, 3.0, 1.0, 0.0, 2.0, 2.0, 3.0, 0.0, 2.0], [0.0, -2.0, 0.0, 2.0, 2.0, -1.0, 1.0, 4.0, 2.0, 0.0, 3.0, 2.0, 1.0, 5.0, 23.0, 20.0, 4.0, 3.0, 3.0, 2.0, 3.0, -1.0, 3.0, 3.0, 2.0, 3.0, 2.0, 2.0, 2.0, 0.0, 1.0, 1.0], [1.0, 4.0, 2.0, 1.0, 2.0, 3.0, 5.0, 4.0, 4.0, 8.0, 4.0, 7.0, 3.0, 6.0, 25.0, 27.0, 11.0, 4.0, 3.0, 2.0, 0.0, 1.0, 2.0, 2.0, 0.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0], [2.0, 3.0, 3.0, 3.0, 2.0, 1.0, 3.0, 3.0, 5.0, 9.0, 16.0, 10.0, 3.0, 1.0, 21.0, 26.0, 16.0, 6.0, 2.0, 3.0, 4.0, 1.0, 1.0, 0.0, 2.0, 0.0, 1.0, 1.0, 2.0, 1.0, 3.0, 2.0], [1.0, 4.0, 0.0, 2.0, 1.0, 2.0, 3.0, 4.0, 5.0, 9.0, 22.0, 24.0, 10.0, 4.0, 14.0, 23.0, 25.0, 19.0, 4.0, 2.0, 3.0, 3.0, 3.0, 5.0, 2.0, 4.0, 3.0, 0.0, 4.0, 7.0, 6.0, 5.0], [3.0, 2.0, 3.0, 4.0, 2.0, 2.0, 2.0, 3.0, 5.0, 5.0, 19.0, 25.0, 14.0, 11.0, 10.0, 18.0, 27.0, 20.0, 7.0, 2.0, 1.0, 0.0, 2.0, 3.0, 1.0, 0.0, -1.0, 1.0, 10.0, 10.0, 13.0, 9.0], [1.0, 2.0, 1.0, 2.0, 1.0, 3.0, 3.0, 5.0, 16.0, 20.0, 11.0, 18.0, 26.0, 24.0, 10.0, 14.0, 30.0, 30.0, 11.0, 8.0, 2.0, 0.0, 3.0, 3.0, 3.0, 3.0, 5.0, 19.0, 26.0, 28.0, 16.0, 9.0], [0.0, -1.0, 2.0, 1.0, -1.0, -2.0, 4.0, 4.0, 18.0, 24.0, 15.0, 12.0, 26.0, 28.0, 14.0, 14.0, 33.0, 33.0, 19.0, 10.0, 2.0, 2.0, 0.0, 1.0, 2.0, 0.0, 16.0, 24.0, 29.0, 27.0, 8.0, 6.0], [1.0, 2.0, 2.0, 1.0, 2.0, 2.0, 3.0, 3.0, 10.0, 17.0, 32.0, 28.0, 23.0, 27.0, 34.0, 33.0, 33.0, 38.0, 35.0, 32.0, 8.0, 4.0, 1.0, 2.0, 4.0, 11.0, 24.0, 31.0, 23.0, 11.0, 5.0, 2.0], [2.0, -2.0, 2.0, 2.0, 2.0, -1.0, 1.0, 2.0, 7.0, 8.0, 30.0, 33.0, 23.0, 25.0, 35.0, 35.0, 36.0, 37.0, 37.0, 36.0, 16.0, 7.0, 4.0, 0.0, 9.0, 13.0, 26.0, 27.0, 17.0, 10.0, 3.0, 2.0], [2.0, 2.0, 3.0, 1.0, 2.0, 0.0, 2.0, 3.0, 3.0, 4.0, 17.0, 25.0, 32.0, 35.0, 37.0, 37.0, 40.0, 41.0, 42.0, 41.0, 38.0, 35.0, 24.0, 27.0, 30.0, 32.0, 29.0, 26.0, 9.0, 3.0, 5.0, 1.0], [1.0, 0.0, 1.0, 2.0, 1.0, -1.0, 4.0, 1.0, 2.0, 2.0, 8.0, 16.0, 32.0, 33.0, 39.0, 40.0, 41.0, 41.0, 41.0, 42.0, 39.0, 35.0, 34.0, 37.0, 33.0, 30.0, 31.0, 26.0, 7.0, 4.0, 1.0, 1.0], [1.0, 5.0, 1.0, 3.0, 2.0, 4.0, 9.0, 10.0, 5.0, 4.0, 4.0, 7.0, 31.0, 32.0, 39.0, 44.0, 47.0, 44.0, 45.0, 44.0, 41.0, 38.0, 37.0, 36.0, 32.0, 33.0, 28.0, 19.0, 6.0, 7.0, 1.0, 2.0], [2.0, 0.0, 2.0, 4.0, 1.0, 4.0, 12.0, 15.0, 13.0, 11.0, 12.0, 14.0, 34.0, 35.0, 41.0, 42.0, 45.0, 43.0, 46.0, 48.0, 38.0, 38.0, 35.0, 33.0, 34.0, 31.0, 28.0, 19.0, 8.0, 2.0, 1.0, 1.0], [2.0, 3.0, 3.0, 2.0, 2.0, 1.0, 7.0, 10.0, 16.0, 19.0, 25.0, 30.0, 38.0, 37.0, 42.0, 44.0, 42.0, 47.0, 46.0, 49.0, 44.0, 40.0, 34.0, 34.0, 37.0, 36.0, 21.0, 11.0, 5.0, 4.0, 2.0, 2.0], [1.0, 1.0, 1.0, 1.0, 0.0, -1.0, 4.0, 4.0, 10.0, 9.0, 22.0, 26.0, 36.0, 36.0, 40.0, 42.0, 46.0, 45.0, 49.0, 48.0, 41.0, 38.0, 39.0, 36.0, 33.0, 34.0, 13.0, 8.0, 3.0, 3.0, 2.0, 3.0], [3.0, 0.0, 0.0, 0.0, 1.0, 2.0, 4.0, 3.0, 4.0, 3.0, 6.0, 8.0, 32.0, 38.0, 39.0, 40.0, 43.0, 44.0, 46.0, 49.0, 43.0, 41.0, 40.0, 38.0, 35.0, 33.0, 11.0, 9.0, 6.0, 3.0, 2.0, 3.0], [1.0, 0.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0, 0.0, 2.0, 3.0, 23.0, 33.0, 41.0, 40.0, 45.0, 42.0, 46.0, 46.0, 43.0, 41.0, 40.0, 38.0, 36.0, 33.0, 10.0, 7.0, 3.0, 2.0, 2.0, 2.0], [3.0, 0.0, 4.0, 3.0, 2.0, 2.0, 2.0, 2.0, 0.0, 3.0, 5.0, 1.0, 6.0, 9.0, 32.0, 37.0, 42.0, 43.0, 41.0, 44.0, 43.0, 41.0, 39.0, 38.0, 38.0, 33.0, 10.0, 6.0, 2.0, 4.0, 2.0, 0.0], [1.0, -2.0, 0.0, 3.0, 2.0, 0.0, 1.0, 3.0, 2.0, -2.0, 2.0, 0.0, 4.0, 3.0, 23.0, 32.0, 39.0, 39.0, 41.0, 42.0, 43.0, 38.0, 38.0, 39.0, 38.0, 37.0, 9.0, 7.0, 3.0, 2.0, 0.0, 1.0], [1.0, 1.0, 1.0, 1.0, 4.0, 1.0, 2.0, 0.0, 1.0, 2.0, 1.0, 2.0, 3.0, 4.0, 7.0, 4.0, 27.0, 33.0, 39.0, 40.0, 39.0, 38.0, 42.0, 39.0, 41.0, 35.0, 18.0, 10.0, 3.0, 3.0, 1.0, 1.0], [1.0, 0.0, 2.0, 3.0, 3.0, 2.0, 1.0, 0.0, 3.0, 0.0, 2.0, 2.0, 4.0, 1.0, 3.0, 5.0, 16.0, 22.0, 38.0, 41.0, 40.0, 37.0, 39.0, 41.0, 38.0, 36.0, 22.0, 13.0, 4.0, 1.0, 3.0, 0.0], [2.0, 0.0, 2.0, 3.0, 2.0, 0.0, 4.0, 1.0, 2.0, 3.0, 2.0, 2.0, 3.0, 1.0, 3.0, 3.0, 3.0, 6.0, 18.0, 26.0, 39.0, 40.0, 39.0, 37.0, 37.0, 35.0, 30.0, 18.0, 5.0, 5.0, 2.0, 1.0], [1.0, -2.0, 0.0, 1.0, 1.0, 3.0, 2.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 2.0, 2.0, 3.0, 2.0, 2.0, 11.0, 13.0, 38.0, 37.0, 39.0, 38.0, 34.0, 27.0, 28.0, 25.0, 5.0, 3.0, 3.0, 3.0]])

for i in range(len(data1)):
    for j in range(len(data1[i])):
        if data1[i][j] > 65536/2:
            data1[i][j] = data1[i][j] - 65536
        if data2[i][j] > 65536/2:
            data2[i][j] = data2[i][j] - 65536
        if data3[i][j] > 65536/2:
            data3[i][j] = data3[i][j] - 65536

# Normalize

data1 = data1 - np.min(data1)
data2 = data2 - np.min(data2)
data3 = data3 - np.min(data3)

data1 = data1 / np.max(data1)
data2 = data2 / np.max(data2)
data3 = data3 / np.max(data3)

fig, ax = plt.subplots(1, 3, figsize=(6.4*2*3, 4.8*2))
ax[0].imshow(data1, cmap="plasma")
ax[1].imshow(data2, cmap="plasma")
ax[2].imshow(data3, cmap="plasma")

ax[0].set_title("Background")
ax[1].set_title("Measurement")
ax[2].set_title("Background subtracted")

plt.savefig("MLX90640_Raspi_RawPixel01_Bgsub.png")
plt.show()

png

data = np.asarray([[1.0, 1.0, 3.0, 2.0, 3.0, 1.0, 2.0, 0.0, 3.0, 6.0, 0.0, 5.0, 4.0, 4.0, 10.0, 10.0, 2.0, 2.0, 1.0, 0.0, 1.0, 1.0, 1.0, 3.0, 3.0, 1.0, 0.0, 2.0, 2.0, 3.0, 0.0, 2.0], [0.0, -2.0, 0.0, 2.0, 2.0, -1.0, 1.0, 4.0, 2.0, 0.0, 3.0, 2.0, 1.0, 5.0, 23.0, 20.0, 4.0, 3.0, 3.0, 2.0, 3.0, -1.0, 3.0, 3.0, 2.0, 3.0, 2.0, 2.0, 2.0, 0.0, 1.0, 1.0], [1.0, 4.0, 2.0, 1.0, 2.0, 3.0, 5.0, 4.0, 4.0, 8.0, 4.0, 7.0, 3.0, 6.0, 25.0, 27.0, 11.0, 4.0, 3.0, 2.0, 0.0, 1.0, 2.0, 2.0, 0.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0], [2.0, 3.0, 3.0, 3.0, 2.0, 1.0, 3.0, 3.0, 5.0, 9.0, 16.0, 10.0, 3.0, 1.0, 21.0, 26.0, 16.0, 6.0, 2.0, 3.0, 4.0, 1.0, 1.0, 0.0, 2.0, 0.0, 1.0, 1.0, 2.0, 1.0, 3.0, 2.0], [1.0, 4.0, 0.0, 2.0, 1.0, 2.0, 3.0, 4.0, 5.0, 9.0, 22.0, 24.0, 10.0, 4.0, 14.0, 23.0, 25.0, 19.0, 4.0, 2.0, 3.0, 3.0, 3.0, 5.0, 2.0, 4.0, 3.0, 0.0, 4.0, 7.0, 6.0, 5.0], [3.0, 2.0, 3.0, 4.0, 2.0, 2.0, 2.0, 3.0, 5.0, 5.0, 19.0, 25.0, 14.0, 11.0, 10.0, 18.0, 27.0, 20.0, 7.0, 2.0, 1.0, 0.0, 2.0, 3.0, 1.0, 0.0, -1.0, 1.0, 10.0, 10.0, 13.0, 9.0], [1.0, 2.0, 1.0, 2.0, 1.0, 3.0, 3.0, 5.0, 16.0, 20.0, 11.0, 18.0, 26.0, 24.0, 10.0, 14.0, 30.0, 30.0, 11.0, 8.0, 2.0, 0.0, 3.0, 3.0, 3.0, 3.0, 5.0, 19.0, 26.0, 28.0, 16.0, 9.0], [0.0, -1.0, 2.0, 1.0, -1.0, -2.0, 4.0, 4.0, 18.0, 24.0, 15.0, 12.0, 26.0, 28.0, 14.0, 14.0, 33.0, 33.0, 19.0, 10.0, 2.0, 2.0, 0.0, 1.0, 2.0, 0.0, 16.0, 24.0, 29.0, 27.0, 8.0, 6.0], [1.0, 2.0, 2.0, 1.0, 2.0, 2.0, 3.0, 3.0, 10.0, 17.0, 32.0, 28.0, 23.0, 27.0, 34.0, 33.0, 33.0, 38.0, 35.0, 32.0, 8.0, 4.0, 1.0, 2.0, 4.0, 11.0, 24.0, 31.0, 23.0, 11.0, 5.0, 2.0], [2.0, -2.0, 2.0, 2.0, 2.0, -1.0, 1.0, 2.0, 7.0, 8.0, 30.0, 33.0, 23.0, 25.0, 35.0, 35.0, 36.0, 37.0, 37.0, 36.0, 16.0, 7.0, 4.0, 0.0, 9.0, 13.0, 26.0, 27.0, 17.0, 10.0, 3.0, 2.0], [2.0, 2.0, 3.0, 1.0, 2.0, 0.0, 2.0, 3.0, 3.0, 4.0, 17.0, 25.0, 32.0, 35.0, 37.0, 37.0, 40.0, 41.0, 42.0, 41.0, 38.0, 35.0, 24.0, 27.0, 30.0, 32.0, 29.0, 26.0, 9.0, 3.0, 5.0, 1.0], [1.0, 0.0, 1.0, 2.0, 1.0, -1.0, 4.0, 1.0, 2.0, 2.0, 8.0, 16.0, 32.0, 33.0, 39.0, 40.0, 41.0, 41.0, 41.0, 42.0, 39.0, 35.0, 34.0, 37.0, 33.0, 30.0, 31.0, 26.0, 7.0, 4.0, 1.0, 1.0], [1.0, 5.0, 1.0, 3.0, 2.0, 4.0, 9.0, 10.0, 5.0, 4.0, 4.0, 7.0, 31.0, 32.0, 39.0, 44.0, 47.0, 44.0, 45.0, 44.0, 41.0, 38.0, 37.0, 36.0, 32.0, 33.0, 28.0, 19.0, 6.0, 7.0, 1.0, 2.0], [2.0, 0.0, 2.0, 4.0, 1.0, 4.0, 12.0, 15.0, 13.0, 11.0, 12.0, 14.0, 34.0, 35.0, 41.0, 42.0, 45.0, 43.0, 46.0, 48.0, 38.0, 38.0, 35.0, 33.0, 34.0, 31.0, 28.0, 19.0, 8.0, 2.0, 1.0, 1.0], [2.0, 3.0, 3.0, 2.0, 2.0, 1.0, 7.0, 10.0, 16.0, 19.0, 25.0, 30.0, 38.0, 37.0, 42.0, 44.0, 42.0, 47.0, 46.0, 49.0, 44.0, 40.0, 34.0, 34.0, 37.0, 36.0, 21.0, 11.0, 5.0, 4.0, 2.0, 2.0], [1.0, 1.0, 1.0, 1.0, 0.0, -1.0, 4.0, 4.0, 10.0, 9.0, 22.0, 26.0, 36.0, 36.0, 40.0, 42.0, 46.0, 45.0, 49.0, 48.0, 41.0, 38.0, 39.0, 36.0, 33.0, 34.0, 13.0, 8.0, 3.0, 3.0, 2.0, 3.0], [3.0, 0.0, 0.0, 0.0, 1.0, 2.0, 4.0, 3.0, 4.0, 3.0, 6.0, 8.0, 32.0, 38.0, 39.0, 40.0, 43.0, 44.0, 46.0, 49.0, 43.0, 41.0, 40.0, 38.0, 35.0, 33.0, 11.0, 9.0, 6.0, 3.0, 2.0, 3.0], [1.0, 0.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0, 0.0, 2.0, 3.0, 23.0, 33.0, 41.0, 40.0, 45.0, 42.0, 46.0, 46.0, 43.0, 41.0, 40.0, 38.0, 36.0, 33.0, 10.0, 7.0, 3.0, 2.0, 2.0, 2.0], [3.0, 0.0, 4.0, 3.0, 2.0, 2.0, 2.0, 2.0, 0.0, 3.0, 5.0, 1.0, 6.0, 9.0, 32.0, 37.0, 42.0, 43.0, 41.0, 44.0, 43.0, 41.0, 39.0, 38.0, 38.0, 33.0, 10.0, 6.0, 2.0, 4.0, 2.0, 0.0], [1.0, -2.0, 0.0, 3.0, 2.0, 0.0, 1.0, 3.0, 2.0, -2.0, 2.0, 0.0, 4.0, 3.0, 23.0, 32.0, 39.0, 39.0, 41.0, 42.0, 43.0, 38.0, 38.0, 39.0, 38.0, 37.0, 9.0, 7.0, 3.0, 2.0, 0.0, 1.0], [1.0, 1.0, 1.0, 1.0, 4.0, 1.0, 2.0, 0.0, 1.0, 2.0, 1.0, 2.0, 3.0, 4.0, 7.0, 4.0, 27.0, 33.0, 39.0, 40.0, 39.0, 38.0, 42.0, 39.0, 41.0, 35.0, 18.0, 10.0, 3.0, 3.0, 1.0, 1.0], [1.0, 0.0, 2.0, 3.0, 3.0, 2.0, 1.0, 0.0, 3.0, 0.0, 2.0, 2.0, 4.0, 1.0, 3.0, 5.0, 16.0, 22.0, 38.0, 41.0, 40.0, 37.0, 39.0, 41.0, 38.0, 36.0, 22.0, 13.0, 4.0, 1.0, 3.0, 0.0], [2.0, 0.0, 2.0, 3.0, 2.0, 0.0, 4.0, 1.0, 2.0, 3.0, 2.0, 2.0, 3.0, 1.0, 3.0, 3.0, 3.0, 6.0, 18.0, 26.0, 39.0, 40.0, 39.0, 37.0, 37.0, 35.0, 30.0, 18.0, 5.0, 5.0, 2.0, 1.0], [1.0, -2.0, 0.0, 1.0, 1.0, 3.0, 2.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 2.0, 2.0, 3.0, 2.0, 2.0, 11.0, 13.0, 38.0, 37.0, 39.0, 38.0, 34.0, 27.0, 28.0, 25.0, 5.0, 3.0, 3.0, 3.0]])

for i in range(len(data)):
    for j in range(len(data[i])):
        if data[i][j] > 65536/2:
            data[i][j] = data[i][j] - 65536

data = data - np.min(data)
data = data / np.max(data)

fig, ax = plt.subplots(figsize=(6.4*2, 4.8*2))
ax.imshow(data, cmap="plasma", interpolation="gaussian")

ax.set_title("Background subtracted, Interpolated")

plt.savefig("MLX90640_Raspi_RawPixel01_Bgsub_Interpol.png")
plt.show()

As one can see this yields already useable data for imaging and object detection purposes though the sensor has not been designed to be used in that way. There is no absolute temperature scale and no correct scaling of the sensitivity slope of the sensor. It’s nice for playing, imaging and art though and may even be sufficient for target following.

Applying compensation

Applying the compensation described in the theory part above is what happens in my implementation in the _process_frame method (that requires _update_ram to be executed before to fetch values requires for correct gain compensation and ambient temperature measurement). Applying these directly yields valid absolute temperature measurements without any background compensation:

data = [[26.773377077041516, 26.401300870689454, 26.69458777351946, 27.21313093404848, 26.64517827158039, 26.69399929939658, 26.56118464056874, 26.823950777021082, 26.282190065501595, 26.16015076325766, 26.31953480305566, 26.458187932080875, 26.27777473623206, 26.676899165829184, 29.44834593036046, 29.698383857995395, 26.80814918716942, 25.685066791920974, 25.61105025724879, 26.332422855199695, 26.168179229066993, 26.16301379166191, 26.071093922098783, 26.320983349458515, 26.207965041833006, 26.220433807599704, 26.314285299945652, 26.52930420050808, 26.250470003806242, 26.652620145138997, 26.886115016082556, 27.39085633222919], [26.702565456392563, 26.922495697117824, 27.491131989422456, 27.291971785577914, 26.735304078946683, 26.791667983698346, 26.884931845803976, 27.04366804247462, 26.225474088869532, 26.245307605329515, 26.458635264608347, 26.141606359701086, 26.34886927846196, 27.405186890792265, 32.27820033525171, 32.117540463061744, 27.07028240064608, 25.89480397307682, 25.87709579868124, 25.841499705638455, 26.069396034228475, 26.217729824854985, 26.368702297658842, 26.170478981903102, 26.096198298876743, 25.91065405118053, 26.389870755443212, 26.37947947518171, 26.67058535384473, 27.263647857143326, 27.57116350153092, 27.218471707701724], [26.424607844704838, 26.509889705003957, 26.794658104054122, 26.874531544513275, 26.73440951736228, 26.98616474464893, 26.649047174277882, 26.91866563966863, 25.94839306312656, 26.150022162562493, 26.589974019930878, 26.836101510846902, 26.507571823990475, 27.52556492642043, 30.866443348999553, 31.085189313080434, 28.506476284114456, 26.295148503752444, 26.025985835950962, 26.28659427979568, 25.8858524866248, 25.96974561960394, 26.147816509357938, 26.075199301920293, 25.93017124670348, 26.174878114859837, 26.375560117054476, 26.621421159157535, 26.286173554078687, 26.547184748923485, 26.527048262891128, 27.246992326078157], [26.57843327182428, 26.821913883155844, 27.154650977447886, 27.096684931444656, 26.670115777031413, 26.696392340685406, 26.7759666388489, 26.76192648840663, 25.999248412000156, 26.52644755481407, 26.532616260300017, 26.205263054895568, 26.27789283306811, 27.433873005062424, 31.546755728500955, 31.864021197195086, 28.706178209678228, 26.520766986900753, 26.637779035638573, 26.480247033092155, 26.258114671176713, 26.02430586277478, 26.559340117814827, 26.437713409836874, 26.160876794542162, 26.40170976111648, 26.637585427611327, 26.658787207200305, 26.348780749333343, 26.23601347844368, 27.04036024903968, 27.060394629632015], [26.670608090492294, 26.61763635366293, 27.050377123638953, 26.922511117803708, 26.66362297461791, 26.488056929376626, 26.830556422215068, 26.759691629698636, 26.328658095906405, 26.483354433426143, 26.29213584206809, 26.416422569184306, 27.096703022826148, 27.25207998787471, 30.701243734423542, 31.910967938216118, 31.095751466545835, 30.069151444412, 29.46072886830217, 29.023003585781737, 26.927100024972844, 26.358601823791503, 26.367581886287212, 26.421809699703545, 26.011793687014404, 26.39140492709498, 26.105756051007575, 26.132312584198473, 25.842513199869813, 26.20432457347539, 26.411091459374404, 26.479118215243602], [26.60736714958989, 27.06268566728022, 26.983151373691896, 26.620448166122117, 26.1731316866381, 26.572492380896108, 26.605116733472414, 26.610333597756892, 26.232029596178734, 26.562164032688884, 26.736421297666652, 26.301172289287535, 28.54342740866656, 29.181275907504414, 31.038451767764514, 31.16824145458071, 30.971469228246804, 30.97140942345885, 30.718659926326552, 30.425459638887958, 27.93085186782912, 27.198065550402532, 26.433934543963005, 26.284526136956856, 25.74319169188425, 26.11930744311428, 26.338444180730278, 25.990194743355744, 25.88252402631838, 25.91572524314074, 26.897335607025127, 26.535702511401382], [26.98350563545341, 26.620166675903306, 26.69693622875343, 26.758006759744433, 26.31953480305566, 26.27793221343086, 26.401648350856135, 26.65216794685682, 26.37865419554845, 26.07362113714464, 27.024066737992825, 28.041712279975684, 30.65092509510123, 30.75561944614725, 31.180936207971, 30.670221347339805, 30.899817240821505, 30.791409086131296, 30.353973195436254, 30.091365286424093, 30.480561363868674, 30.068631173539416, 27.41632382161515, 26.83545166646354, 26.117895301339104, 25.96399171094623, 25.841355371542363, 26.047897433884316, 25.912433221229207, 25.983774476207316, 26.108396450196267, 26.92499938331349], [26.69348093261698, 26.70624072601254, 27.023581701591866, 26.466483437449824, 26.253726235000443, 26.489509980893956, 26.522437943430248, 26.21081080593251, 26.10423375707194, 26.605182846850994, 27.789283811758423, 29.025162996453957, 30.37215662521578, 30.940717165733417, 31.406552473124634, 30.5359364708043, 30.340646586716446, 30.81418210908072, 30.53821047174631, 28.59594670985024, 29.173894449201043, 30.098421551350498, 29.837654876031365, 27.493185940008345, 25.991696814167597, 25.84947242316605, 26.593369801037966, 26.093868346302145, 25.780816271778235, 26.1834105767943, 26.749999268790248, 26.582284487191544], [26.269881780128685, 26.351034918123275, 26.78511941008469, 26.976194134305047, 26.539460495789285, 26.110961827757308, 26.3191648611691, 26.506477758285655, 26.234191604697116, 26.43857084543032, 29.991638763902984, 31.097387049538554, 27.569301728209382, 29.278241742452224, 30.632234977756355, 30.646911877577963, 30.590223959839022, 30.61047026787486, 29.280061891790695, 27.82534506575405, 26.826798146867134, 28.254913329424483, 29.76560691931627, 27.33510497146608, 25.506871632087496, 25.36541728605812, 26.208950263598524, 26.059098421957685, 25.972500815696833, 26.007581226928437, 26.29582931812007, 26.791213332869972], [26.535390120890895, 26.413831504345183, 26.74522260230276, 26.499437734614276, 26.308753729318653, 26.676720670116595, 26.628768887798344, 26.41344425568218, 26.141829436468527, 26.829336169658347, 30.86097599740941, 30.076432597544, 26.60285270822476, 28.430940719326713, 31.139753216467284, 30.94743455111194, 30.619946786098808, 30.631502416875776, 30.079404295779113, 27.528184030412945, 26.720020214083377, 29.343882683186393, 28.751030000447543, 26.599491390705793, 25.385672444389343, 25.5584472817456, 25.7952290548007, 26.09346205558427, 25.85032094719537, 26.064766664188937, 26.020359326988228, 26.62371486986831], [26.478956310594583, 26.51261208902065, 26.55083391530377, 26.66477736225619, 26.417174944958106, 26.071474670045575, 25.995403340026144, 26.669187931117563, 25.98420264763905, 26.1414595490113, 29.75760788907587, 30.087669799695846, 26.26031317568578, 27.338663948630256, 30.570488670458474, 30.913017529449803, 30.562146924909484, 30.71855257231465, 29.278948110910562, 27.663347623353218, 28.697360472285254, 29.32033706227162, 26.225528127449707, 25.49590844488108, 25.507026383943867, 25.417667417228472, 25.907849175593583, 25.609147031562884, 25.49168150733243, 25.99539452294215, 25.951865126354278, 26.40485714905668], [26.362110006653722, 26.210153635476217, 26.695054876081088, 26.515684349259573, 26.331019296219097, 25.99080097051774, 26.75337521023249, 26.399193878905066, 25.90173262637518, 25.886114066096525, 28.897511898768244, 29.948000377057326, 26.335630084237494, 27.3963136655708, 30.815402585156903, 30.630321341957597, 30.035962036028423, 30.185355778804364, 29.333632711479595, 28.299678679351587, 28.728071858861938, 27.855223382164183, 25.528434392108466, 25.696520621001525, 25.079507642029228, 25.465072199831468, 25.82555897208158, 25.962740159225916, 25.715854219959624, 25.861005146428568, 26.02100925476566, 26.262827099768288], [26.506777323947745, 26.309857054302825, 26.192019429111156, 26.671222410327516, 26.450841467983594, 26.13862418389408, 26.208931045326665, 26.25069419631518, 26.17785262117752, 25.85436519912855, 26.192740514420223, 27.181501778976497, 28.689216776345745, 28.39541534288844, 29.13628093403497, 29.748329553729604, 28.838785268306935, 28.70243089846724, 28.99311818460336, 28.737235180194943, 26.089495525240466, 25.38601277873613, 25.57956691054727, 25.72361351646464, 25.035960464677146, 25.270193164428463, 25.58283519747613, 25.96888600050545, 25.66276404127308, 25.493639073261306, 25.837847323535982, 25.82253482471566], [25.972077231327717, 26.57885700080749, 26.365227892691678, 26.3918186363436, 26.329162001273346, 26.18907711118152, 26.28259796434844, 26.12372756987304, 25.903324086752377, 25.441120389427113, 26.130578441885405, 26.28763984700805, 27.690365212813163, 28.299205582382797, 29.359544528865626, 29.186649743864223, 28.431874910392935, 28.60436544173774, 29.960005461303012, 29.633259235045273, 25.82928860818788, 25.438000907336573, 25.818463555630387, 25.588529689180803, 24.92405871735133, 25.487021612174942, 25.651877219579262, 25.83642955190635, 25.516328301067176, 25.691363367277575, 25.905429586966306, 26.055127893941403], [26.42941236630577, 26.07352958499132, 26.56468659917772, 26.466383791963267, 26.21763384669339, 25.69499382774802, 26.004613705659153, 26.320116675130862, 25.774228811628745, 25.859676363693154, 25.74356524108572, 26.045225873983554, 26.43894722908027, 27.65963336059997, 32.28858426435693, 31.532377518809312, 29.439395506309552, 30.188018013180056, 31.887130632223602, 31.421748205223025, 26.092020294761937, 25.508906717909838, 25.40438765332277, 25.57389722895357, 25.50733773765478, 25.571792642044443, 26.048730425608483, 26.45520095829181, 26.36494824611941, 25.780695441417095, 26.16144532492558, 26.611489332411622], [26.321432270757327, 26.193577384681532, 26.551586366829156, 26.735519157643694, 26.09930140411359, 26.318409353187803, 26.613647178775466, 26.22299362371291, 25.860206714166793, 25.622247695941326, 25.98381235158206, 26.240686119158568, 25.890966702617675, 28.003949705203695, 32.64218102392641, 31.986879158612, 30.673780047771515, 31.11883579471032, 32.25628733390681, 31.583027212644822, 26.14575852905091, 25.7143703657149, 25.64037610636882, 25.784525380218952, 25.877222191735825, 26.574376870995934, 27.648870545360637, 27.315600361516715, 26.419064975108427, 26.725485172491688, 26.418566877170008, 26.625613199108045], [26.187431024115597, 26.402122887193343, 26.176291695551072, 26.207787732458428, 26.138083157096105, 25.871006622090874, 26.145967983312744, 26.047214520914395, 25.738454296516807, 25.98649614611446, 25.817619368930934, 26.210064543681142, 26.224283802531943, 27.79003063701765, 32.17038074902831, 32.30891162877833, 29.58970167444943, 29.933453761677697, 32.060706492284055, 31.809907901187557, 26.531998389483363, 25.597412004434716, 25.721359334006706, 26.387350010243267, 27.43338410834025, 27.28833726280783, 27.571440334764247, 27.595144783352794, 27.025704741343304, 27.015997904879328, 27.046245259696377, 27.30005855267416], [26.52022267788766, 26.311209070825157, 26.502667467839217, 26.836793690627587, 26.010964913047474, 26.131901366152363, 26.5989680491561, 26.261169947001463, 25.654202372471048, 25.89450891483716, 26.06407280263437, 25.928168442250637, 26.13302227075701, 27.529466957042132, 32.1235410025908, 32.20471433000455, 28.44984331588347, 28.76865986299657, 32.2853020269045, 31.84982556434983, 26.59687601966857, 26.138954345173772, 25.947050382037787, 26.578456792801205, 27.329640205541523, 27.699508243110586, 27.823294179529967, 27.4497338083317, 26.70060240937096, 26.68862058597199, 27.496137659602766, 27.360624378786554], [26.371092392689775, 26.23113663796056, 26.531034895802293, 26.304527079324885, 26.27883051531137, 25.990520109593433, 26.442435184858766, 26.284313500861344, 26.183872037051344, 25.93278441877129, 25.965515909407657, 26.449015133713715, 26.035294009813356, 27.02394642076314, 31.661738659035564, 31.9211992881647, 26.97722949301857, 26.68814493113041, 31.20828191793123, 31.401789680421757, 26.654640492452415, 25.68562132708462, 26.13622051563499, 26.976066112552076, 27.25196171384391, 27.120248382281716, 27.54925614116189, 27.56623320542326, 26.775890462927578, 26.59257830623426, 27.41822222749545, 27.851075636483188], [26.481647935602837, 26.746606262946216, 26.71941751844247, 26.57076038212807, 26.165907742865386, 26.42442695704881, 26.729779243616917, 26.517571995722165, 25.74239690514878, 26.494535896429966, 26.40198710873409, 26.140949574095202, 25.93405089264496, 26.783728097385733, 31.474625412690216, 31.81145126344245, 26.565254569270735, 26.292299017487665, 30.695636911600616, 30.97874100677228, 26.71126823744339, 25.735901114792398, 26.22244001557283, 27.193877661469628, 26.9635765311545, 27.494046297772343, 27.623734925844815, 27.76796837176886, 26.81531342573703, 27.00016694584201, 27.492620836958736, 28.11736861173233], [26.542438824759586, 26.291115992543894, 26.67666746565203, 26.47272010892283, 26.228156172681565, 26.047936308758608, 26.39167636733646, 26.185833229798106, 25.945171130172184, 25.81156222048918, 26.02814848686046, 26.595994221933154, 25.932333163623753, 26.446356462012602, 30.82178156233539, 30.96687811316258, 26.591647443098395, 25.89425151836474, 28.73955114406465, 30.37010968307891, 27.94589753310072, 26.437297591744937, 26.54606419626765, 26.91023319887279, 27.051194215457087, 27.591694259169913, 27.500788842078407, 27.731903536299797, 27.226637025645744, 27.069782347643013, 27.58247786081222, 28.041290514858474], [26.893426726240932, 26.62715517821937, 27.06634833793146, 26.78932057159119, 26.322610275915224, 26.523040105214136, 26.901700631346614, 26.443973301773724, 25.86339908881746, 25.914649834618388, 26.490627705343343, 26.12034478850819, 26.00971375563296, 26.688848489377904, 30.8008453679887, 30.712855240162014, 26.32973075642218, 25.77513516494639, 28.378556806547863, 30.26226632654442, 28.98161493870623, 26.66218993599341, 26.487284355857867, 27.283247119996645, 27.270187473137526, 27.813932034960942, 27.96144558574133, 27.92471337561028, 27.29391080977109, 27.547014678436767, 27.877279492988578, 27.900288020821108], [26.90550424015663, 26.807207220575833, 27.01327255321604, 26.77656031076657, 26.27053555158392, 26.485057774726954, 26.605519452253247, 27.024672781219692, 26.525534921068243, 26.155664217733374, 26.443843798117996, 26.451655286051903, 26.34758591709749, 26.554169707676863, 32.06729977696676, 31.460021327006245, 26.0385200853554, 25.69617204417625, 27.02769230047153, 29.967432741512027, 30.449230957458894, 27.922333275281517, 26.78967166606236, 27.54705386474268, 27.697074622710545, 27.697417087875692, 28.020076638367414, 28.234603681860733, 27.57409988182883, 27.795448505268837, 27.968770943944662, 28.23562982459964], [27.089652872582235, 26.753053405605897, 27.260703679966298, 27.187055024827657, 26.8652062930106, 26.445823316965573, 27.062872306207396, 26.74701474867885, 26.297909650127508, 26.50114937821212, 26.437315503581317, 26.58173763330916, 26.30566354018316, 26.32242551419546, 31.65239700621248, 31.772123326538804, 25.96892169366373, 25.630992052800707, 26.839942928852622, 28.733109871506883, 30.09041060893918, 27.682942395766133, 27.12971142329809, 28.028089431747446, 27.637141598414075, 27.637302954796382, 27.80288203547906, 28.18808332034496, 28.12363714345088, 28.132150620856237, 27.68365621536543, 27.94392194741181]]
data = np.asarray(data)
fig, ax = plt.subplots(figsize = (6.4*2,4.8*2))
im = ax.imshow(data, cmap="plasma")
cbar = fig.colorbar(im, ax=ax, extend='both')
cbar.minorticks_on()
plt.savefig("MLX90640_Raspi_Comp01.png")
plt.show()

png

If we want to get this measurement look more nice we may interpolate between the pixels:

data = [[26.773377077041516, 26.401300870689454, 26.69458777351946, 27.21313093404848, 26.64517827158039, 26.69399929939658, 26.56118464056874, 26.823950777021082, 26.282190065501595, 26.16015076325766, 26.31953480305566, 26.458187932080875, 26.27777473623206, 26.676899165829184, 29.44834593036046, 29.698383857995395, 26.80814918716942, 25.685066791920974, 25.61105025724879, 26.332422855199695, 26.168179229066993, 26.16301379166191, 26.071093922098783, 26.320983349458515, 26.207965041833006, 26.220433807599704, 26.314285299945652, 26.52930420050808, 26.250470003806242, 26.652620145138997, 26.886115016082556, 27.39085633222919], [26.702565456392563, 26.922495697117824, 27.491131989422456, 27.291971785577914, 26.735304078946683, 26.791667983698346, 26.884931845803976, 27.04366804247462, 26.225474088869532, 26.245307605329515, 26.458635264608347, 26.141606359701086, 26.34886927846196, 27.405186890792265, 32.27820033525171, 32.117540463061744, 27.07028240064608, 25.89480397307682, 25.87709579868124, 25.841499705638455, 26.069396034228475, 26.217729824854985, 26.368702297658842, 26.170478981903102, 26.096198298876743, 25.91065405118053, 26.389870755443212, 26.37947947518171, 26.67058535384473, 27.263647857143326, 27.57116350153092, 27.218471707701724], [26.424607844704838, 26.509889705003957, 26.794658104054122, 26.874531544513275, 26.73440951736228, 26.98616474464893, 26.649047174277882, 26.91866563966863, 25.94839306312656, 26.150022162562493, 26.589974019930878, 26.836101510846902, 26.507571823990475, 27.52556492642043, 30.866443348999553, 31.085189313080434, 28.506476284114456, 26.295148503752444, 26.025985835950962, 26.28659427979568, 25.8858524866248, 25.96974561960394, 26.147816509357938, 26.075199301920293, 25.93017124670348, 26.174878114859837, 26.375560117054476, 26.621421159157535, 26.286173554078687, 26.547184748923485, 26.527048262891128, 27.246992326078157], [26.57843327182428, 26.821913883155844, 27.154650977447886, 27.096684931444656, 26.670115777031413, 26.696392340685406, 26.7759666388489, 26.76192648840663, 25.999248412000156, 26.52644755481407, 26.532616260300017, 26.205263054895568, 26.27789283306811, 27.433873005062424, 31.546755728500955, 31.864021197195086, 28.706178209678228, 26.520766986900753, 26.637779035638573, 26.480247033092155, 26.258114671176713, 26.02430586277478, 26.559340117814827, 26.437713409836874, 26.160876794542162, 26.40170976111648, 26.637585427611327, 26.658787207200305, 26.348780749333343, 26.23601347844368, 27.04036024903968, 27.060394629632015], [26.670608090492294, 26.61763635366293, 27.050377123638953, 26.922511117803708, 26.66362297461791, 26.488056929376626, 26.830556422215068, 26.759691629698636, 26.328658095906405, 26.483354433426143, 26.29213584206809, 26.416422569184306, 27.096703022826148, 27.25207998787471, 30.701243734423542, 31.910967938216118, 31.095751466545835, 30.069151444412, 29.46072886830217, 29.023003585781737, 26.927100024972844, 26.358601823791503, 26.367581886287212, 26.421809699703545, 26.011793687014404, 26.39140492709498, 26.105756051007575, 26.132312584198473, 25.842513199869813, 26.20432457347539, 26.411091459374404, 26.479118215243602], [26.60736714958989, 27.06268566728022, 26.983151373691896, 26.620448166122117, 26.1731316866381, 26.572492380896108, 26.605116733472414, 26.610333597756892, 26.232029596178734, 26.562164032688884, 26.736421297666652, 26.301172289287535, 28.54342740866656, 29.181275907504414, 31.038451767764514, 31.16824145458071, 30.971469228246804, 30.97140942345885, 30.718659926326552, 30.425459638887958, 27.93085186782912, 27.198065550402532, 26.433934543963005, 26.284526136956856, 25.74319169188425, 26.11930744311428, 26.338444180730278, 25.990194743355744, 25.88252402631838, 25.91572524314074, 26.897335607025127, 26.535702511401382], [26.98350563545341, 26.620166675903306, 26.69693622875343, 26.758006759744433, 26.31953480305566, 26.27793221343086, 26.401648350856135, 26.65216794685682, 26.37865419554845, 26.07362113714464, 27.024066737992825, 28.041712279975684, 30.65092509510123, 30.75561944614725, 31.180936207971, 30.670221347339805, 30.899817240821505, 30.791409086131296, 30.353973195436254, 30.091365286424093, 30.480561363868674, 30.068631173539416, 27.41632382161515, 26.83545166646354, 26.117895301339104, 25.96399171094623, 25.841355371542363, 26.047897433884316, 25.912433221229207, 25.983774476207316, 26.108396450196267, 26.92499938331349], [26.69348093261698, 26.70624072601254, 27.023581701591866, 26.466483437449824, 26.253726235000443, 26.489509980893956, 26.522437943430248, 26.21081080593251, 26.10423375707194, 26.605182846850994, 27.789283811758423, 29.025162996453957, 30.37215662521578, 30.940717165733417, 31.406552473124634, 30.5359364708043, 30.340646586716446, 30.81418210908072, 30.53821047174631, 28.59594670985024, 29.173894449201043, 30.098421551350498, 29.837654876031365, 27.493185940008345, 25.991696814167597, 25.84947242316605, 26.593369801037966, 26.093868346302145, 25.780816271778235, 26.1834105767943, 26.749999268790248, 26.582284487191544], [26.269881780128685, 26.351034918123275, 26.78511941008469, 26.976194134305047, 26.539460495789285, 26.110961827757308, 26.3191648611691, 26.506477758285655, 26.234191604697116, 26.43857084543032, 29.991638763902984, 31.097387049538554, 27.569301728209382, 29.278241742452224, 30.632234977756355, 30.646911877577963, 30.590223959839022, 30.61047026787486, 29.280061891790695, 27.82534506575405, 26.826798146867134, 28.254913329424483, 29.76560691931627, 27.33510497146608, 25.506871632087496, 25.36541728605812, 26.208950263598524, 26.059098421957685, 25.972500815696833, 26.007581226928437, 26.29582931812007, 26.791213332869972], [26.535390120890895, 26.413831504345183, 26.74522260230276, 26.499437734614276, 26.308753729318653, 26.676720670116595, 26.628768887798344, 26.41344425568218, 26.141829436468527, 26.829336169658347, 30.86097599740941, 30.076432597544, 26.60285270822476, 28.430940719326713, 31.139753216467284, 30.94743455111194, 30.619946786098808, 30.631502416875776, 30.079404295779113, 27.528184030412945, 26.720020214083377, 29.343882683186393, 28.751030000447543, 26.599491390705793, 25.385672444389343, 25.5584472817456, 25.7952290548007, 26.09346205558427, 25.85032094719537, 26.064766664188937, 26.020359326988228, 26.62371486986831], [26.478956310594583, 26.51261208902065, 26.55083391530377, 26.66477736225619, 26.417174944958106, 26.071474670045575, 25.995403340026144, 26.669187931117563, 25.98420264763905, 26.1414595490113, 29.75760788907587, 30.087669799695846, 26.26031317568578, 27.338663948630256, 30.570488670458474, 30.913017529449803, 30.562146924909484, 30.71855257231465, 29.278948110910562, 27.663347623353218, 28.697360472285254, 29.32033706227162, 26.225528127449707, 25.49590844488108, 25.507026383943867, 25.417667417228472, 25.907849175593583, 25.609147031562884, 25.49168150733243, 25.99539452294215, 25.951865126354278, 26.40485714905668], [26.362110006653722, 26.210153635476217, 26.695054876081088, 26.515684349259573, 26.331019296219097, 25.99080097051774, 26.75337521023249, 26.399193878905066, 25.90173262637518, 25.886114066096525, 28.897511898768244, 29.948000377057326, 26.335630084237494, 27.3963136655708, 30.815402585156903, 30.630321341957597, 30.035962036028423, 30.185355778804364, 29.333632711479595, 28.299678679351587, 28.728071858861938, 27.855223382164183, 25.528434392108466, 25.696520621001525, 25.079507642029228, 25.465072199831468, 25.82555897208158, 25.962740159225916, 25.715854219959624, 25.861005146428568, 26.02100925476566, 26.262827099768288], [26.506777323947745, 26.309857054302825, 26.192019429111156, 26.671222410327516, 26.450841467983594, 26.13862418389408, 26.208931045326665, 26.25069419631518, 26.17785262117752, 25.85436519912855, 26.192740514420223, 27.181501778976497, 28.689216776345745, 28.39541534288844, 29.13628093403497, 29.748329553729604, 28.838785268306935, 28.70243089846724, 28.99311818460336, 28.737235180194943, 26.089495525240466, 25.38601277873613, 25.57956691054727, 25.72361351646464, 25.035960464677146, 25.270193164428463, 25.58283519747613, 25.96888600050545, 25.66276404127308, 25.493639073261306, 25.837847323535982, 25.82253482471566], [25.972077231327717, 26.57885700080749, 26.365227892691678, 26.3918186363436, 26.329162001273346, 26.18907711118152, 26.28259796434844, 26.12372756987304, 25.903324086752377, 25.441120389427113, 26.130578441885405, 26.28763984700805, 27.690365212813163, 28.299205582382797, 29.359544528865626, 29.186649743864223, 28.431874910392935, 28.60436544173774, 29.960005461303012, 29.633259235045273, 25.82928860818788, 25.438000907336573, 25.818463555630387, 25.588529689180803, 24.92405871735133, 25.487021612174942, 25.651877219579262, 25.83642955190635, 25.516328301067176, 25.691363367277575, 25.905429586966306, 26.055127893941403], [26.42941236630577, 26.07352958499132, 26.56468659917772, 26.466383791963267, 26.21763384669339, 25.69499382774802, 26.004613705659153, 26.320116675130862, 25.774228811628745, 25.859676363693154, 25.74356524108572, 26.045225873983554, 26.43894722908027, 27.65963336059997, 32.28858426435693, 31.532377518809312, 29.439395506309552, 30.188018013180056, 31.887130632223602, 31.421748205223025, 26.092020294761937, 25.508906717909838, 25.40438765332277, 25.57389722895357, 25.50733773765478, 25.571792642044443, 26.048730425608483, 26.45520095829181, 26.36494824611941, 25.780695441417095, 26.16144532492558, 26.611489332411622], [26.321432270757327, 26.193577384681532, 26.551586366829156, 26.735519157643694, 26.09930140411359, 26.318409353187803, 26.613647178775466, 26.22299362371291, 25.860206714166793, 25.622247695941326, 25.98381235158206, 26.240686119158568, 25.890966702617675, 28.003949705203695, 32.64218102392641, 31.986879158612, 30.673780047771515, 31.11883579471032, 32.25628733390681, 31.583027212644822, 26.14575852905091, 25.7143703657149, 25.64037610636882, 25.784525380218952, 25.877222191735825, 26.574376870995934, 27.648870545360637, 27.315600361516715, 26.419064975108427, 26.725485172491688, 26.418566877170008, 26.625613199108045], [26.187431024115597, 26.402122887193343, 26.176291695551072, 26.207787732458428, 26.138083157096105, 25.871006622090874, 26.145967983312744, 26.047214520914395, 25.738454296516807, 25.98649614611446, 25.817619368930934, 26.210064543681142, 26.224283802531943, 27.79003063701765, 32.17038074902831, 32.30891162877833, 29.58970167444943, 29.933453761677697, 32.060706492284055, 31.809907901187557, 26.531998389483363, 25.597412004434716, 25.721359334006706, 26.387350010243267, 27.43338410834025, 27.28833726280783, 27.571440334764247, 27.595144783352794, 27.025704741343304, 27.015997904879328, 27.046245259696377, 27.30005855267416], [26.52022267788766, 26.311209070825157, 26.502667467839217, 26.836793690627587, 26.010964913047474, 26.131901366152363, 26.5989680491561, 26.261169947001463, 25.654202372471048, 25.89450891483716, 26.06407280263437, 25.928168442250637, 26.13302227075701, 27.529466957042132, 32.1235410025908, 32.20471433000455, 28.44984331588347, 28.76865986299657, 32.2853020269045, 31.84982556434983, 26.59687601966857, 26.138954345173772, 25.947050382037787, 26.578456792801205, 27.329640205541523, 27.699508243110586, 27.823294179529967, 27.4497338083317, 26.70060240937096, 26.68862058597199, 27.496137659602766, 27.360624378786554], [26.371092392689775, 26.23113663796056, 26.531034895802293, 26.304527079324885, 26.27883051531137, 25.990520109593433, 26.442435184858766, 26.284313500861344, 26.183872037051344, 25.93278441877129, 25.965515909407657, 26.449015133713715, 26.035294009813356, 27.02394642076314, 31.661738659035564, 31.9211992881647, 26.97722949301857, 26.68814493113041, 31.20828191793123, 31.401789680421757, 26.654640492452415, 25.68562132708462, 26.13622051563499, 26.976066112552076, 27.25196171384391, 27.120248382281716, 27.54925614116189, 27.56623320542326, 26.775890462927578, 26.59257830623426, 27.41822222749545, 27.851075636483188], [26.481647935602837, 26.746606262946216, 26.71941751844247, 26.57076038212807, 26.165907742865386, 26.42442695704881, 26.729779243616917, 26.517571995722165, 25.74239690514878, 26.494535896429966, 26.40198710873409, 26.140949574095202, 25.93405089264496, 26.783728097385733, 31.474625412690216, 31.81145126344245, 26.565254569270735, 26.292299017487665, 30.695636911600616, 30.97874100677228, 26.71126823744339, 25.735901114792398, 26.22244001557283, 27.193877661469628, 26.9635765311545, 27.494046297772343, 27.623734925844815, 27.76796837176886, 26.81531342573703, 27.00016694584201, 27.492620836958736, 28.11736861173233], [26.542438824759586, 26.291115992543894, 26.67666746565203, 26.47272010892283, 26.228156172681565, 26.047936308758608, 26.39167636733646, 26.185833229798106, 25.945171130172184, 25.81156222048918, 26.02814848686046, 26.595994221933154, 25.932333163623753, 26.446356462012602, 30.82178156233539, 30.96687811316258, 26.591647443098395, 25.89425151836474, 28.73955114406465, 30.37010968307891, 27.94589753310072, 26.437297591744937, 26.54606419626765, 26.91023319887279, 27.051194215457087, 27.591694259169913, 27.500788842078407, 27.731903536299797, 27.226637025645744, 27.069782347643013, 27.58247786081222, 28.041290514858474], [26.893426726240932, 26.62715517821937, 27.06634833793146, 26.78932057159119, 26.322610275915224, 26.523040105214136, 26.901700631346614, 26.443973301773724, 25.86339908881746, 25.914649834618388, 26.490627705343343, 26.12034478850819, 26.00971375563296, 26.688848489377904, 30.8008453679887, 30.712855240162014, 26.32973075642218, 25.77513516494639, 28.378556806547863, 30.26226632654442, 28.98161493870623, 26.66218993599341, 26.487284355857867, 27.283247119996645, 27.270187473137526, 27.813932034960942, 27.96144558574133, 27.92471337561028, 27.29391080977109, 27.547014678436767, 27.877279492988578, 27.900288020821108], [26.90550424015663, 26.807207220575833, 27.01327255321604, 26.77656031076657, 26.27053555158392, 26.485057774726954, 26.605519452253247, 27.024672781219692, 26.525534921068243, 26.155664217733374, 26.443843798117996, 26.451655286051903, 26.34758591709749, 26.554169707676863, 32.06729977696676, 31.460021327006245, 26.0385200853554, 25.69617204417625, 27.02769230047153, 29.967432741512027, 30.449230957458894, 27.922333275281517, 26.78967166606236, 27.54705386474268, 27.697074622710545, 27.697417087875692, 28.020076638367414, 28.234603681860733, 27.57409988182883, 27.795448505268837, 27.968770943944662, 28.23562982459964], [27.089652872582235, 26.753053405605897, 27.260703679966298, 27.187055024827657, 26.8652062930106, 26.445823316965573, 27.062872306207396, 26.74701474867885, 26.297909650127508, 26.50114937821212, 26.437315503581317, 26.58173763330916, 26.30566354018316, 26.32242551419546, 31.65239700621248, 31.772123326538804, 25.96892169366373, 25.630992052800707, 26.839942928852622, 28.733109871506883, 30.09041060893918, 27.682942395766133, 27.12971142329809, 28.028089431747446, 27.637141598414075, 27.637302954796382, 27.80288203547906, 28.18808332034496, 28.12363714345088, 28.132150620856237, 27.68365621536543, 27.94392194741181]]
data = np.asarray(data)
fig, ax = plt.subplots(1, 3, figsize = (6.4*2*3,4.8*2))
im = ax[0].imshow(data, cmap="plasma")
cbar = fig.colorbar(im, ax=ax[0], extend='both')
cbar.minorticks_on()
ax[0].set_title("No interpolation")

im = ax[1].imshow(data, cmap="plasma", interpolation="gaussian")
cbar = fig.colorbar(im, ax=ax[1], extend='both')
cbar.minorticks_on()
ax[1].set_title("Gaussian")

im = ax[2].imshow(data, cmap="plasma", interpolation="bicubic")
cbar = fig.colorbar(im, ax=ax[2], extend='both')
cbar.minorticks_on()
ax[2].set_title("Bicubic")
plt.savefig("MLX90640_Raspi_Comp01_Interpol.png")
plt.show()

png

Using the pylmx90640-tspspi library

Since I’ve now written interface code for the MLX90640 I decided to make this available as a library for quickly testing sensors and interfacing. The library is available in the pymlx90640-tspspi PyPi package as usual. It can be installed using

pip install pymlx90640-tspspi

Not that it also requires an I2C interface library - in my case I’m using pyfbsdi2c-tspspi that exposes an extremly simple API specified in the pylabdevs baseclass - the library is described in a previous blog article. This makes my implementation very simple to adapt to different I2C implementations.

Internal API

One can simply instantiate the MLX90640 and fetch single frames using it’s internal API - which is of course subject to change

from fbsdi2c import FbsdI2C
from mlx90640 import MLX90640

import matplotlib.pyplot as plt
#import numpy as np

with FbsdI2C() as i2c:
    with MLX90640(i2c) as mlx:
        rawframe = mlx._fetch_raw_frame_sync()
        mlx._update_ram()
        framedata = mlx._process_frame(rawframe)

        fig, ax = plt.subplots(1, 2, figsize=(6.4*2, 4.8))
        ax[0].imshow(rawframe, cmap="plasma", interpolation="gaussian")
        ax[0].set_title("Raw pixel data")

        im = ax[1].imshow(framedata, cmap="plasma", interpolation="gaussian")
        ax[1].set_title("Temperatures")
        cbar = fig.colorbar(im, ax=ax[1], extend="both")
        cbar.minorticks_on()

        plt.show()

Public fetch frame API

Or even simpler use the fetch_frame() method (note this may be subject to change) when one does not need access to raw frames:

from fbsdi2c import FbsdI2C
from mlx90640 import MLX90640

import matplotlib.pyplot as plt
#import numpy as np

with FbsdI2C() as i2c:
    with MLX90640(i2c) as mlx:
        framedata = mlx.fetch_frame()

        fig, ax = plt.subplots(figsize=(6.4*2, 4.8*2))

        im = ax.imshow(framedata, cmap="plasma", interpolation="gaussian")
        ax.set_title("Temperatures")
        cbar = fig.colorbar(im, ax=ax, extend="both")
        cbar.minorticks_on()

        plt.show()

pysimplecam API

As a last step this library exposes the same methods as my simple V4L Python capture library to allow simple interfacing to existing image processing routines:

from fbsdi2c import FbsdI2C
from mlx90640 import MLX90640

import matplotlib.pyplot as plt

plt.ion()
fig, ax = plt.subplots()
axim = None

framectr = 0

def updateFrame(cam, frame):
    global axim, framectr, fig

    if axim is None:
        axim = ax.imshow(frame, cmap = "plasma", interpolation="gaussian")
    else:
        axim.set_data(frame)
        axim.autoscale()
    fig.canvas.flush_events()

    plt.savefig(f"simplecam01_cap/{framectr:08}.png")

    framectr = framectr + 1
    if framectr > 60:
        return False
    else:
        return True


with FbsdI2C() as i2c:
    with MLX90640(i2c) as mlx:
        mlx._set_refresh_rate(2)
        mlx.frameCallback = [ updateFrame ]
        mlx.stream()

Conclusion

The MLX90640 is a nice low cost FIR array that allows to sense temperatures in many different settings. Depending on the application one can use either raw values directly or do proper compensation to get high resolution temperature measurements. Due to the low pixel count it’s of course no match for highly priced thermal cameras - but it’s still a very valueable part to perform monitoring and can also be used in art installations. The two different FOV models on the market allow a single sensor to monitor a full car interior, it can be used for security monitoring or in fire detection. The applications are endless. Due to it’s I2C interface it’s very simple to use though it requires some basic math to recover the samples due to the huge manufacturing differences between the different pixels and the shifting of low amounts of charge carriers over the charge doupled device. The different readout modes allow the MLX40690 to be used in many different applications though I’ve just focused on using it in the chessboard pattern. The low power consumption allows one to use the sensor on mobile robots and the high frame rate for tracking low to medium speed objects. In addition one may use external far infrared optics (for ex. ZnSe lenses that are cheap to obtain due to emergence of CO2 lasers in industry and hobby segments) to provide for zoom. The I2C interface makes the part very interesting since it’s possible to interface with low cost MCUs like AVRs, STM32 or RP2040. The readily available development boards make entry using the part very simple. Overall it’s an very nice part to have on the market.

References

This article is tagged:


Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support