Friday, June 5, 2020

AMG8833 8x8 Thermal Camera with ESP8266 D1 Board and ILI9341 LCD


My latest project is to make a thermal camera.  Adafruit has lots of info on the AMG8833 8x8 thermal camera, as well as example software to use it with a ILI9341 LCD screen.

AMG8833 -> ESP8266 -> ILI9341LCD = Thermal Camera!

The Adafruit examples include an interpolated version.  Although the camera is 8x8 it calculates the colors between the pixels to yield many more pixels.  The Adafruit AMG8833 tutorial is here: 
https://learn.adafruit.com/adafruit-amg8833-8x8-thermal-camera-sensor

The drivers and example files are here:  https://github.com/adafruit/Adafruit_AMG88xx

I made this change to the interpolate example code:
#ifdef ESP8266
   #define STMPE_CS 16
   #define TFT_CS   D10
   #define TFT_DC   D9
   #define SD_CS    2
#endif

Here is the back side of the LCD.  I soldered jumpers to power, reset and LED to reduce the number of jumper wires needed to connect the LCD.

This is the AMG8833 Thermal camera.  IT takes four wires to connect to the processor.
AMG8833 Thermal camera
This picture shows the connections to the D1 processor board.  The left 2 wires are from the camera the right 4 wires go to the LCD.

The LCD is powered by 3.3 volts and the thermal sensor is powered by 5 volts only because there is no other 3.3 volt pin available.

Here is a video of it working:



I have added a display of the maximum temperature. Basically you create two variables, scan through the readings and pick the highest temperature, then convert it to Fahrenheit and display it.


Here are the changes that are needed to the demo code to find and display the peak temperature:

int HighTemp = 0;
int HTemp = 0;

void loop() {
  //read all the pixels
  amg.readPixels(pixels);

  Serial.print("[");
  HighTemp=0;
  for(int i=1; i<=AMG88xx_PIXEL_ARRAY_SIZE; i++){
    Serial.print(pixels[i-1]);
    Serial.print(", ");
    if( i%8 == 0 ) Serial.println();
    if (pixels[i-1] > HighTemp) HighTemp = pixels[i-1];
  }
  Serial.println("]");
  Serial.println();
  HTemp = ((HighTemp * 9/5) + 32);
  Serial.println (HTemp);
 
  float dest_2d[INTERPOLATED_ROWS * INTERPOLATED_COLS];

  int32_t t = millis();
  interpolate_image(pixels, AMG_ROWS, AMG_COLS, dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);
  Serial.print("Interpolation took "); Serial.print(millis()-t); Serial.println(" ms");

  uint16_t boxsize = min(tft.width() / INTERPOLATED_COLS, tft.height() / INTERPOLATED_COLS);
 
  drawpixels(dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS, boxsize, boxsize, false);

  //delay(50);
}

void drawpixels(float *p, uint8_t rows, uint8_t cols, uint8_t boxWidth, uint8_t boxHeight, boolean showVal) {
  int colorTemp;
  for (int y=0; y<rows; y++) {
    for (int x=0; x<cols; x++) {
      float val = get_point(p, rows, cols, x, y);
      if(val >= MAXTEMP) colorTemp = MAXTEMP;
      else if(val <= MINTEMP) colorTemp = MINTEMP;
      else colorTemp = val;
     
      uint8_t colorIndex = map(colorTemp, MINTEMP, MAXTEMP, 0, 255);
      colorIndex = constrain(colorIndex, 0, 255);
      //draw the pixels!
      uint16_t color;
      color = val * 2;
      tft.fillRect(boxWidth * x, boxHeight * y, boxWidth, boxHeight, camColors[colorIndex]);
       
      if (showVal) {
        tft.setCursor(boxWidth * y + boxWidth/2 - 12, 40 + boxHeight * x + boxHeight/2 - 4);
        tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(2);
        tft.print(val,1);
      }
    }
  }
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.setCursor(rows*boxWidth,0);
  tft.print(" High");
  tft.setCursor(rows*boxWidth,20);
  tft.print(" Temp:");
  tft.setCursor(rows*(boxWidth+1),40);
  tft.print(HTemp);
  tft.print(" ");
//  }
}