#include #include "mlx90640_lcd_display.h" #include "stm32_hx8347d_lcd.h" #include "MLX90640_API.h" #include "MLX90640_I2C_Driver.h" #include "sys_app.h" #include "bmp.h" #define FPS2HZ 0x02 #define FPS4HZ 0x03 #define FPS8HZ 0x04 #define FPS16HZ 0x05 #define FPS32HZ 0x06 #define MLX90640_ADDR 0x33 #define RefreshRate FPS4HZ #define EMMISIVITY 0.95f #define TA_SHIFT 8 //Default shift for MLX90640 in open air paramsMLX90640 mlx90640; static uint16_t eeMLX90640[832]; int status; // start with some initial colors float minTemp = 1.0f; float maxTemp = 60.0f; float centerTemp; float averageTemp; char tempBuffer[6]; // variables for interpolated colors uint8_t red, green, blue; // variables for row/column interpolation float intPoint, val, a, b, c, d, ii; int x, y, i, j; // array for the 32 x 24 measured tempValues static float tempValues[32*24]; static uint8_t zoneMask[32*24]={0x0}; static uint16_t TempToColor(float val); static void setTempScale(void); static void setAbcd(void); static void drawLegend(void); static void drawMeasurement(void); static void drawPicture(void); static void readTempValues(void); extern LCD_DrawPropTypeDef DrawProp; static uint16_t TempToColor(float val){ /* pass in value and figure out R G B several published ways to do this I basically graphed R G B and developed simple linear equations again a 5-6-5 color display will not need accurate temp to R G B color calculation equations based on http://web-tech.ga-usa.com/2012/05/creating-a-custom-hot-to-cold-temperature-color-gradient-for-use-with-rrdtool/index.html */ red = constrain(255.0f / (c - b) * val - ((b * 255.0f) / (c - b)), 0, 255); if ((val > minTemp) & (val < a)) { green = constrain(255.0f / (a - minTemp) * val - (255.0f * minTemp) / (a - minTemp), 0, 255); } else if ((val >= a) & (val <= c)) { green = 255; } else if (val > c) { green = constrain(255.0f / (c - d) * val - (d * 255.0f) / (c - d), 0, 255); } else if ((val > d) | (val < a)) { green = 0; } if (val <= b) { blue = constrain(255.0f / (a - b) * val - (255.0f * b) / (a - b), 0, 255); } else if ((val > b) & (val <= d)) { blue = 0; } else if (val > d) { blue = constrain(240.0f / (maxTemp - d) * val - (d * 240.0f) / (maxTemp - d), 0, 240); } // use the displays color mapping function to get 5-6-5 color palet (R=5 bits, G=6 bits, B-5 bits) return BSP_LCD_GetColor565(red, green, blue); } static void setTempScale(void) { minTemp = 255; maxTemp = 0; for (i = 0; i < 768; i++) { minTemp = min(minTemp, tempValues[i]); maxTemp = max(maxTemp, tempValues[i]); } setAbcd(); drawLegend(); } // Function to get the cutoff points in the temp vs RGB graph. static void setAbcd(void) { a = minTemp + (maxTemp - minTemp) * 0.2121f; b = minTemp + (maxTemp - minTemp) * 0.3182f; c = minTemp + (maxTemp - minTemp) * 0.4242f; d = minTemp + (maxTemp - minTemp) * 0.8182f; } // Draw a legend. static void drawLegend(void) { #if 0 //float inc = (maxTemp - minTemp) / 224.0f; float inc = (maxTemp - minTemp) / 224.0f; j = 0; for (ii = minTemp; ii < maxTemp; ii += inc) { BSP_LCD_DrawVLine(8+ + j++, 260, 20, TempToColor(ii)); } #endif BSP_LCD_SetFont(&Font16); DrawProp.BackColor = LCD_COLOR_BLACK; memset(tempBuffer,0,sizeof(tempBuffer)); sprintf(tempBuffer,(char *)"%2.1f",minTemp); BSP_LCD_DisplayStringAt(8,260,(uint8_t *)tempBuffer,LEFT_MODE,LCD_COLOR_BLUE); memset(tempBuffer,0,sizeof(tempBuffer)); sprintf(tempBuffer,(char *)"%2.1f",maxTemp); BSP_LCD_DisplayStringAt(190,260,(uint8_t *)tempBuffer,LEFT_MODE,LCD_COLOR_RED); } // Draw a circle + measured value. static void drawMeasurement(void ) { // Mark center measurement //BSP_LCD_DrawCircle(120, 8+84, 10, LCD_COLOR_WHITE); // Measure and print center temperature centerTemp = (tempValues[383 - 16] + tempValues[383 - 15] + tempValues[384 + 15] + tempValues[384 + 16]) / 4; averageTemp = 0.0; for (i=0; i<32*24; i++) averageTemp += tempValues[i]; averageTemp /= 768; BSP_LCD_SetFont(&Font16); memset(tempBuffer,0,sizeof(tempBuffer)); DrawProp.BackColor = LCD_COLOR_BLACK; sprintf(tempBuffer,(char *)"Yunhorn Technology"); BSP_LCD_DisplayStringAt(18,240,(uint8_t *)tempBuffer,LEFT_MODE,LCD_COLOR_BLUE); memset(tempBuffer,0,sizeof(tempBuffer)); sprintf(tempBuffer,(char *)"%2.2f ",centerTemp); BSP_LCD_DisplayStringAt(60,260,(uint8_t *)tempBuffer,LEFT_MODE,LCD_COLOR_RED); memset(tempBuffer,0,sizeof(tempBuffer)); sprintf(tempBuffer,(char *)"%2.2f ",averageTemp); BSP_LCD_DisplayStringAt(120,260,(uint8_t *)tempBuffer,LEFT_MODE,LCD_COLOR_BLUE); } static void drawPicture(void) { float temp1=0.0; uint8_t blackdot=0; averageTemp = 0.0; for (i=0; i<32*24; i++) averageTemp += tempValues[i]; averageTemp /= 768; BSP_LCD_FillRect(0,0,240, 240, LCD_COLOR_BLACK); for (y=2; y<23; y++) { for (x=2; x<31; x++) { temp1 = tempValues[(x) + (y*32)]; if ((temp1+ 1.5) > averageTemp ) { //BSP_LCD_FillRect(x*8, y*11, 7, 10, LCD_COLOR_BLACK); temp1=0.0; } else { BSP_LCD_FillRect(x*8, y*11, 7, 11, LCD_COLOR_YELLOW); BSP_LCD_DrawCircle(x*8, y*11, 20, LCD_COLOR_RED); zoneMask[y*32+x]=0x57; } } } } // Read pixel data from MLX90640. static void readTempValues(void) { char buf[128]; for (uint8_t x = 0 ; x < 2 ; x++) // Read both subpages { uint16_t mlx90640Frame[834]; status = MLX90640_GetFrameData(MLX90640_ADDR, mlx90640Frame); if (status < 0) { APP_LOG(TS_OFF, VLEVEL_L, "GetFrame Error: %d\r\n",status); } float vdd = MLX90640_GetVdd(mlx90640Frame, &mlx90640); float Ta = MLX90640_GetTa(mlx90640Frame, &mlx90640); float tr = Ta - TA_SHIFT; //Reflected temperature based on the sensor ambient temperature MLX90640_CalculateTo(mlx90640Frame, &mlx90640, EMMISIVITY, tr, tempValues); } #if 0 APP_LOG(TS_OFF,VLEVEL_L, "\r\n\n\n"); for (uint8_t y=0; y < 24; y++) { for (uint8_t x=0; x<32; x++) { APP_LOG(TS_OFF, VLEVEL_L, "%c ", (uint8_t)((((float)tempValues[y*32+x]- 25.0)) + 0x30)); } APP_LOG(TS_OFF,VLEVEL_L, "\r\n"); } #endif } void mlx90640_display_process(void){ readTempValues(); setTempScale(); drawPicture(); drawMeasurement(); } void mlx90640_display_init(void){ MLX90640_SetRefreshRate(MLX90640_ADDR, RefreshRate); MLX90640_SetChessMode(MLX90640_ADDR); status = MLX90640_DumpEE(MLX90640_ADDR, eeMLX90640); if (status != 0) APP_LOG(TS_OFF, VLEVEL_L, "\r\nload system parameters error with code:%d\r\n",status); status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640); if (status != 0) APP_LOG(TS_OFF, VLEVEL_L, "\r\nParameter extraction failed with error code:%d\r\n",status); }