1

Yay. Got my MLX90640 working and boy it works great. However, the ambient temp of around 20C keeps showing as a green background and i would like it to be blue or even grey. Has anyone attempted to setup any of the example programmes (especially the hotspot example as i'm peticularly interested in it) of the MLX90640 thermal camera to display the temperatures colours with blue or grey at 15°C and red as body temp?

Also, how do I get the hotspot example (code below) to show fullscreen? If you could either link or write the code it would be great as I don't know C++. I did try to fiddle about with the code but did not get any changes even though the file was saved and reloaded. Thanks in advance.

OK. Here's the code.

#include "< stdint.h>"
#include < iostream >
#include < cstring >
#include < fstream >
#include < chrono >
#include < thread >
#include < math.h >
#include "headers/MLX90640_API.h"
#include "lib/fb.h"

#define MLX_I2C_ADDR 0x33

#define IMAGE_SCALE 1

// Valid frame rates are 1, 2, 4, 8, 16, 32 and 64
// The i2c baudrate is set to 1mhz to support these
#define FPS 32
#define FRAME_TIME_MICROS (1000000/FPS)

// Despite the framerate being ostensibly FPS hz
// The frame is often not ready in time
// This offset is added to the FRAME_TIME_MICROS
// to account for this.
#define OFFSET_MICROS 850

uint8_t font[] = {
    0b01111110,
    0b10000001,
    0b10000001,
    0b10000001,
    0b01111110,

    0b00000000,
    0b00000001,
    0b11111111,
    0b10000001,
    0b00000000,

    0b01100001,
    0b10010001,
    0b10010001,
    0b10010001,
    0b10001111,

    0b01101110,
    0b10010001,
    0b10010001,
    0b10010001,
    0b10010001,

    0b11111111,
    0b00010000,
    0b00010000,
    0b00010000,
    0b11100000,

    0b10001111,
    0b10010001,
    0b10010001,
    0b10010001,
    0b01100001,

    0b10001110,
    0b10010001,
    0b10010001,
    0b10010001,
    0b01111110,

    0b11111111,
    0b10000000,
    0b10000000,
    0b10000000,
    0b10000000,

    0b01101110,
    0b10010001,
    0b10010001,
    0b10010001,
    0b01101110,

    0b11111111,
    0b10010000,
    0b10010000,
    0b10010000,
    0b01100000
};

void put_pixel_scaled(int x, int y, int r, int g, int b){
    x *= IMAGE_SCALE;
    y *= IMAGE_SCALE;
    for (int px = 0; px < IMAGE_SCALE; px++){
        for (int py = 0; py < IMAGE_SCALE; py++){
            fb_put_pixel(x + px, y + py, r, g, b);
        }
    }
}

void put_digit(int x, int y, int number) {
    for (int n_x = 10; n_x < 50; n_x++) {
        int col = font[(number * 5) + (4-n_x)];
        for (int n_y = 0; n_y < 8; n_y++) {
            int pixel = (col & 0b10000000) ? 255 : 0;
            col <<= 1;
            put_pixel_scaled(x + n_x, y + n_y, pixel, pixel, pixel);
        }
    }   
}

void put_number(int x, int y, float number) {
    float div = 0.01;
    unsigned int digits = 1;
    unsigned int o_x = 0;
    if (number > 999.99){
        number = 999.99;
    }
    while (div <= number / 10) {
        digits++;
        div *= 10;
    }
    if (number < 100) {
        put_digit(x + o_x, y, 0);
        o_x += 6;
    }
    while (digits > 0) {
        put_digit(x + o_x, y, number / div);
        number = fmod(number, div); 
        div /= 10;
        if (digits == 3){
            put_pixel_scaled(x + o_x + 6, y + 7, 255, 255, 255);
            o_x += 2;
        }
        digits--;        
        o_x += 6;
    }
}

void put_pixel_false_colour(int x, int y, double v) {
    // Heatmap code borrowed from: http://www.andrewnoske.com/wiki/Code_-_heatmaps_and_color_gradients
    const int NUM_COLORS = 7;
    static float color[NUM_COLORS][3] = { {0,0,0}, {0,0,1}, {0,1,0}, {1,1,0}, {1,0,0}, {1,0,1}, {1,1,1} };
    int idx1, idx2;
    float fractBetween = 0;
    float vmin = 5.0;
    float vmax = 50.0;
    float vrange = vmax-vmin;
    v -= vmin;
    v /= vrange;
    if(v <= 0) {idx1=idx2=0;}
    else if(v >= 1) {idx1=idx2=NUM_COLORS-1;}
    else
    {
        v *= (NUM_COLORS-1);
        idx1 = floor(v);
        idx2 = idx1+1;
        fractBetween = v - float(idx1);
    }

    int ir, ig, ib;


    ir = (int)((((color[idx2][0] - color[idx1][0]) * fractBetween) + color[idx1][0]) * 255.0);
    ig = (int)((((color[idx2][1] - color[idx1][1]) * fractBetween) + color[idx1][1]) * 255.0);
    ib = (int)((((color[idx2][2] - color[idx1][2]) * fractBetween) + color[idx1][2]) * 255.0);

    put_pixel_scaled(x, y, ir, ig, ib);
    /*for(int px = 0; px < IMAGE_SCALE; px++){
        for(int py = 0; py < IMAGE_SCALE; py++){
            fb_put_pixel(x + px, y + py, ir, ig, ib);
        }
    }*/
}

int main(){

    static uint16_t eeMLX90640[832];
    float emissivity = 1;
    uint16_t frame[834];
    static float image[768];
    static float mlx90640To[768];
    float eTa;
    static uint16_t data[768*sizeof(float)];

    auto frame_time = std::chrono::microseconds(FRAME_TIME_MICROS + OFFSET_MICROS);

    MLX90640_SetDeviceMode(MLX_I2C_ADDR, 0);
    MLX90640_SetSubPageRepeat(MLX_I2C_ADDR, 0);
    switch(FPS){
        case 1:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b001);
            break;
        case 2:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b010);
            break;
        case 4:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b011);
            break;
        case 8:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b100);
            break;
        case 16:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b101);
            break;
        case 32:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b110);
            break;
        case 64:
            MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b111);
            break;
        default:
            printf("Unsupported framerate: %d", FPS);
            return 1;
    }
    MLX90640_SetChessMode(MLX_I2C_ADDR);

    paramsMLX90640 mlx90640;
    MLX90640_DumpEE(MLX_I2C_ADDR, eeMLX90640);
    MLX90640_ExtractParameters(eeMLX90640, &mlx90640);

    fb_init();

    while (1){
        float hotspot = 0;
        int hotspot_x = 0;
        int hotspot_y = 0;
        auto start = std::chrono::system_clock::now();
        MLX90640_GetFrameData(MLX_I2C_ADDR, frame);
        // MLX90640_InterpolateOutliers(frame, eeMLX90640);

        eTa = MLX90640_GetTa(frame, &mlx90640);
        MLX90640_CalculateTo(frame, &mlx90640, emissivity, eTa, mlx90640To);

        MLX90640_BadPixelsCorrection((&mlx90640)->brokenPixels, mlx90640To, 1, &mlx90640);
        MLX90640_BadPixelsCorrection((&mlx90640)->outlierPixels, mlx90640To, 1, &mlx90640);

        for(int y = 0; y < 24; y++){
            for(int x = 0; x < 32; x++){
                float val = mlx90640To[32 * (23-y) + x];
                if (val > hotspot){
                    hotspot = val;
                    hotspot_x = y;
                    hotspot_y = x;
                }
                put_pixel_false_colour(y, x, val);
            }
        }

        if(hotspot_x - 1 >= 0){
            put_pixel_scaled(hotspot_x - 1, hotspot_y, 255, 255, 255);
        }
        if(hotspot_x + 1 < 24){
            put_pixel_scaled(hotspot_x + 1, hotspot_y, 255, 255, 255);
        }
        if(hotspot_y - 1 >= 0){
            put_pixel_scaled(hotspot_x, hotspot_y - 1, 255, 255, 255);
        }
        if(hotspot_y + 1 < 32){
            put_pixel_scaled(hotspot_x, hotspot_y + 1, 255, 255, 255);
        }

        put_number(0, 33, hotspot);

        auto end = std::chrono::system_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        std::this_thread::sleep_for(std::chrono::microseconds(frame_time - elapsed));
    }

    fb_cleanup();
    return 0;
}



OK. Just found out that when changing a c++ file you have to recompile and reinstall it.
Can anyone either guide me through it or link me to a website so I can learn more about how to do it please? 
  • There's the code. Had to do some editing because the webpage kept ommiting some of the information. – Antonio Lambranca Jun 29 at 9:56
  • Possible duplicate of Can't get MLX90640 working – Milliways Jun 29 at 10:20
  • Same guy, different question. I have my MLX90640 working now. Just need to know how to configure it as I tried to adjust the colour setting and the scale and nothing worked. – Antonio Lambranca Jun 29 at 10:30
  • webpage kept ommiting some of the information... @AntonioLambranca, when inserting code listing into a question, the code listing has to be indented by at least 4 spaces for it to be shown as code (gray background and spaces preserved) ..... you can do the indentation before you paste the code or you can select all of the code listing and click the {} button after you pasted the code listing into the question – jsotola Jun 29 at 17:42
  • try changing the gradient array to something like this just to see what happens static float color[NUM_COLORS][3] = { {0.0, 0.0, 0.0}, {0.1, 0.1, 0.1}, {0.2, 0.2, 0.2}, {0.3, 0.3, 0.3}, {0.4, 0.4, 0.4}, {1.0, 0.0, 0.0}, {0.6, 0.6, 0.6} }; – jsotola Jun 29 at 18:48
0

I figured it out.

Edit the file you want in Geany. On the top right of the bar, you have buttons to compile and to build. After editing, press compile. Go to your terminal window and run:

sudo make

It will show the compiled file. After that, run the file and enjoy

Not the answer you're looking for? Browse other questions tagged or ask your own question.