BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Need help with my project - Remote IR temperature sensor with MLX-90614 & LCD 2.4" & IR proximity sensor

Dears
I need help with my code ,as i’m designing an IR temperature detection with MLX-90614 with Arduino MEGA and 2.4 “TFT LCD (mcufriend) and IR proximity sensor .
My code sequence (what i hope) is as following :
1- The 2.4” LCD is displaying BMP files from SD card .
2-when the face come near to the box (as attached pic) its been detected by the IR proximity sensor ,and i want the MLX-90614 to detect the temp. and print it instantly (cut the BMP photo drawing sequence).
3- after printing the temp , the LCD resume displaying BMP images again from SD card.

My problem is i can’t use the I2C protocol of MLX-90614 & the 2.4" LCD inside the ISR (because the use interrupt) , and what i’m getting now that after any face detection by the IR proximity sensor ,the MLX-90614 detect the temp but it doesn’t print it until the LCD finish the current BMP drawing !!

I need help in the code so that at face detection by proximity sensor the MLX-90614 read the temp and print it instantly(cut BMP drawing sequance).


#include <SPI.h>             // f.k. for Arduino-1.5.2
#define USE_SDFAT
#include <SdFat.h>           // Use the SdFat library
SdFatSoftSpi<12, 11, 13> SD; //Bit-Bang on the Shield pins

#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();

#include <Adafruit_GFX.h>    // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#define SD_CS     10
#define NAMEMATCH ""   // "" matches any name
#define PALETTEDEPTH   8     // support 256-colour Palette

#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>

#include <FreeDefaultFonts.h>

#define BLACK   0x0000
#define RED     0xF800
#define GREEN   0x07E0
#define WHITE   0xFFFF
#define GREY    0x8410

volatile boolean detection;
const int ir=41;
const int greenled=43;
const int redled=45;
const int blueled=47;
int counter=0;
int person;

int f;
double temp;
const double tempthres=37.70;



void setup()
{
  mlx.begin(); 
  pinMode (ir,INPUT) ;
  pinMode (greenled,OUTPUT) ;
  pinMode (redled,OUTPUT) ;
  pinMode (blueled,OUTPUT) ;
 
  pinMode (18,INPUT) ;
 
    uint16_t ID;
    ID = tft.readID();
    if (ID == 0x0D3D3) ID = 0x9481;
    tft.begin(ID);
    SD.begin(SD_CS);
    tft.setRotation(1);

attachInterrupt(5,irdetect,CHANGE);   
}

void loop()
{

    uint8_t ret;
   tft.fillScreen(BLACK);

 
if (person==0)
{
counter++;

temp =mlx.readObjectTempC();


     tft.setCursor(20, 80);


    tft.setTextColor(BLACK); // the second color add backtext shade for system font only
    tft.setTextSize(9);
 

if(temp <= tempthres)  { digitalWrite(greenled,HIGH);
tone(39, 680, 250);
tft.fillScreen(GREEN);
tft.print(temp);
tft.setCursor(170,220);
tft.setTextSize(2);
tft.print("Counter: ");
tft.print(counter);

delay (3000);


}
 
if(temp > tempthres) {
digitalWrite(redled,HIGH);
tft.fillScreen(RED);
tft.print(temp);
tft.setCursor(170,220);
tft.setTextSize(2);
tft.print("Counter: ");
tft.print(counter);

  for (int i=0 ; i<15;i++)
  {
  for(f=635;f<=912;f++)
  {tone(39, f);
     delay(1); }

  for(f=911;f>=634;f--)
  {tone(39, f);
     delay(1);}
    }
}

person=1;
}

noTone(39);

digitalWrite(redled,HIGH);
digitalWrite(greenled,HIGH);
digitalWrite(blueled,HIGH);


       ret = showBMP("/1.bmp", 0, 0);
}

void irdetect(){
person =0;
}



#define BMPIMAGEOFFSET 54
#define BUFFPIXEL      20

uint16_t read16(File& f) {
    uint16_t result;         // read little-endian
    f.read(&result, sizeof(result));
    return result;
}

uint32_t read32(File& f) {
    uint32_t result;
    f.read(&result, sizeof(result));
    return result;
}

uint8_t showBMP(char *nm, int x, int y)
{
    File bmpFile;
    int bmpWidth, bmpHeight;    // W+H in pixels
    uint8_t bmpDepth;           // Bit depth (currently must be 24, 16, 8, 4, 1)
    uint32_t bmpImageoffset;    // Start of image data in file
    uint32_t rowSize;           // Not always = bmpWidth; may have padding
    uint8_t sdbuffer[3 * BUFFPIXEL];    // pixel in buffer (R+G+B per pixel)
    uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
    uint8_t bitmask, bitshift;
    boolean flip = true;        // BMP is stored bottom-to-top
    int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
    uint32_t pos;               // seek position
    boolean is565 = false;      //

    uint16_t bmpID;
    uint16_t n;                 // blocks read
    uint8_t ret;

    if ((x >= tft.width()) || (y >= tft.height()))
        return 1;               // off screen

    bmpFile = SD.open(nm);      // Parse BMP header
    bmpID = read16(bmpFile);    // BMP signature
    (void) read32(bmpFile);     // Read & ignore file size
    (void) read32(bmpFile);     // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile);       // Start of image data
    (void) read32(bmpFile);     // Read & ignore DIB header size
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    n = read16(bmpFile);        // # planes -- must be '1'
    bmpDepth = read16(bmpFile); // bits per pixel
    pos = read32(bmpFile);      // format
    if (bmpID != 0x4D42) ret = 2; // bad ID
    else if (n != 1) ret = 3;   // too many planes
    else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
    else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
    else {
        bool first = true;
        is565 = (pos == 3);               // ?already in 16-bit format
        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
        if (bmpHeight < 0) {              // If negative, image is in top-down order.
            bmpHeight = -bmpHeight;
            flip = false;
        }

        w = bmpWidth;
        h = bmpHeight;
        if ((x + w) >= tft.width())       // Crop area to be loaded
            w = tft.width() - x;
        if ((y + h) >= tft.height())      //
            h = tft.height() - y;

        if (bmpDepth <= PALETTEDEPTH) {   // these modes have separate palette
            //bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
            bmpFile.seek(bmpImageoffset - (4<<bmpDepth)); //54 for regular, diff for colorsimportant
            bitmask = 0xFF;
            if (bmpDepth < 8)
                bitmask >>= bmpDepth;
            bitshift = 8 - bmpDepth;
            n = 1 << bmpDepth;
            lcdbufsiz -= n;
            palette = lcdbuffer + lcdbufsiz;
            for (col = 0; col < n; col++) {
                pos = read32(bmpFile);    //map palette to 5-6-5
                palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
            }
        }

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
        for (row = 0; row < h; row++) { // For each scanline...
            // Seek to start of scan line.  It might seem labor-
            // intensive to be doing this on every line, but this
            // method covers a lot of gritty details like cropping
            // and scanline padding.  Also, the seek only takes
            // place if the file position actually needs to change
            // (avoids a lot of cluster math in SD library).
            uint8_t r, g, b, *sdptr;
            int lcdidx, lcdleft;
            if (flip)   // Bitmap is stored bottom-to-top order (normal BMP)
                pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
            else        // Bitmap is stored top-to-bottom
                pos = bmpImageoffset + row * rowSize;
            if (bmpFile.position() != pos) { // Need seek?
                bmpFile.seek(pos);
                buffidx = sizeof(sdbuffer); // Force buffer reload
            }

            for (col = 0; col < w; ) {  //pixels in row
                lcdleft = w - col;
                if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
                for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
                    uint16_t color;
                    // Time to read more pixel data?
                    if (buffidx >= sizeof(sdbuffer)) { // Indeed
                        bmpFile.read(sdbuffer, sizeof(sdbuffer));
                        buffidx = 0; // Set index to beginning
                        r = 0;
                    }
                    switch (bmpDepth) {          // Convert pixel from BMP to TFT format
                        case 24:
                            b = sdbuffer[buffidx++];
                            g = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            color = tft.color565(r, g, b);
                            break;
                        case 16:
                            b = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            if (is565)
                                color = (r << 8) | (b);
                            else
                                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
                            break;
                        case 1:
                        case 4:
                        case 8:
                            if (r == 0)
                                b = sdbuffer[buffidx++], r = 8;
                            color = palette[(b >> bitshift) & bitmask];
                            r -= bmpDepth;
                            b <<= bmpDepth;
                            break;
                    }
                    lcdbuffer[lcdidx] = color;

                }
                tft.pushColors(lcdbuffer, lcdidx, first);
                first = false;
                col += lcdidx;
            }           // end cols
        }               // end rows
        tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
        ret = 0;        // good render
    }
    bmpFile.close();
    return (ret);

No pic attached.

There’s no mention of a Blynk anywhere in this post, and this is the Blynk community forum after all :crazy_face:
I know we can be a friendly and helpful bunch (sometimes at least) but there is a general expectation that there is some tentative link to Blynk somewhere in your project.

Having this in your void loop isn’t going to help your system responsiveness. You should adopt the Blynk good practice approach of keeping your void loop clean and using a timer to call functions every 3 seconds rather than having a 3 second delay in your void loop.

I think I’d also adopt the use of a flag, or possible multiple flags, to control the code execution depending on the condition of those flags.
If you’re in ‘standby’ mode then set a ‘mode’ flag to ‘standby’ and check that flag status and run your BMP drawing routine.
When the mode changes to ‘detected’ then set your flag accordingly so that when the BMP is called with the timer then it doesn’t execute.
If the routine takes a long time to execute, as opposed to the issue being caused by the delay, then check the status of your mode flag at various points through the routine and break the routine if it’s no longer ‘standby’.

You could take a similar approach with your interrupt, or simply poll the GPIO that has the PIR attached with a timer, maybe set to something like 100ms.

Pete.