Random tampering 02 -- DIY thermal imaging realized by AMG8833+Arduino + interpolation

Keywords: Single-Chip Microcomputer arduino

1. Effect

As we all know, AMG8833 module belongs to a relatively low-end infrared temperature acquisition sensor, with low detection accuracy and poor distance conditions. There is no outline at a distance, but a circle. So this is what I personally think is a good rendering (in fact, that's it). If you don't say much, let's see the effect first.

The following is the effect drawing of 1.44 inch tft screen:


The following is the effect drawing of 1.8-inch tft:


2. Principle

Bloggers here use quadratic linear interpolation. For example, if a picture is composed of four pixels y1, y2, Q21 and Q22, interpolated pixels weighted with the original pixels (4) are inserted in the middle of the four pixels. See the specific principle Random tampering 01 -- interpolation Display Optimization Based on AMG8833 thermal imaging module.

3. Equipment

The main equipment used here are:

① AMG8833 module

② 1.8-inch tft display

③arduino due

Why use due? Instead of a cheaper board like uno and mega? Because we use the SRAM resources in the chip when interpolating, the computing power of the chip determines the range of interpolation we can do. In short, the SRAM of uno and nano is only 2k. After my test, it can only calculate the data of 11 * 11 at the top of the day, that is, when the total number of pixels exceeds 11 * 11 = 121, uno can no longer be calculated, so the real-time image will not be displayed on the tft card. Therefore, the due of 96k SRAM is selected here. Of course, I have also used Mega. Its SRAM is 8k. Can achieve 28 * 28 pixel display.

Of course, some people will say that esp32 can be used. It has 520k internal SRAM. Yes, esp32 is completely feasible, but bloggers don't have much time to engage in esp32 at present. Later, they will make trouble 03 and use esp32 to achieve better thermal imaging display.

4. Wiring

Let's look at the wiring of AMG8833 first. AMG8833 and arduino use IIC communication, that is, four pins, VCC, GND, SDA and SCL.

VCC------------3.3V/5V
GND------------GND
SDA ----------------- SDA (pin 20)
SCL ----------------- SCL (pin 21)

Let's look at the tft wiring. The wiring of tft and due includes four SPI communication pins and three display pins (three are defined in the code)

GND----------GND
VCC----------5V
SCL-----------SCK (red box in the figure below)
SDA-----------MOSI (red box in the figure below)
RES ----------- pin 9
DC ----------------- pin 8
CS ----------------- pin 10

There is also the power supply line. You can use 5V power supply, USB cable, charging treasure and so on.

5. Code

Here is the code of aduino
The notes inside are very clear
At present, NN interpolation has not been realized by parameters
However, there is no problem in understanding and modifying the NN data you want
Remember to install the corresponding libraries on aduino before using the code
Remember to praise!

	//Library used
	#include <Adafruit_GFX.h>    
	#include <Adafruit_ST7735.h> 
	#include <SPI.h>
	#include <Wire.h>
	#include <Adafruit_AMG88xx.h>
	#include <avr/pgmspace.h>
	
	//tft display pin
	#define TFT_CS     10  
	#define TFT_RST    9                     
	#define TFT_DC     8
	
	
	//Temperature, corresponding color
	#define MINTEMP 40
	#define MAXTEMP 25
	
	//256 colors
	const uint16_t camColors[] = {0x480F,
	0x400F,0x400F,0x400F,0x4010,0x3810,0x3810,0x3810,0x3810,0x3010,0x3010,
	0x3010,0x2810,0x2810,0x2810,0x2810,0x2010,0x2010,0x2010,0x1810,0x1810,
	0x1811,0x1811,0x1011,0x1011,0x1011,0x0811,0x0811,0x0811,0x0011,0x0011,
	0x0011,0x0011,0x0011,0x0031,0x0031,0x0051,0x0072,0x0072,0x0092,0x00B2,
	0x00B2,0x00D2,0x00F2,0x00F2,0x0112,0x0132,0x0152,0x0152,0x0172,0x0192,
	0x0192,0x01B2,0x01D2,0x01F3,0x01F3,0x0213,0x0233,0x0253,0x0253,0x0273,
	0x0293,0x02B3,0x02D3,0x02D3,0x02F3,0x0313,0x0333,0x0333,0x0353,0x0373,
	0x0394,0x03B4,0x03D4,0x03D4,0x03F4,0x0414,0x0434,0x0454,0x0474,0x0474,
	0x0494,0x04B4,0x04D4,0x04F4,0x0514,0x0534,0x0534,0x0554,0x0554,0x0574,
	0x0574,0x0573,0x0573,0x0573,0x0572,0x0572,0x0572,0x0571,0x0591,0x0591,
	0x0590,0x0590,0x058F,0x058F,0x058F,0x058E,0x05AE,0x05AE,0x05AD,0x05AD,
	0x05AD,0x05AC,0x05AC,0x05AB,0x05CB,0x05CB,0x05CA,0x05CA,0x05CA,0x05C9,
	0x05C9,0x05C8,0x05E8,0x05E8,0x05E7,0x05E7,0x05E6,0x05E6,0x05E6,0x05E5,
	0x05E5,0x0604,0x0604,0x0604,0x0603,0x0603,0x0602,0x0602,0x0601,0x0621,
	0x0621,0x0620,0x0620,0x0620,0x0620,0x0E20,0x0E20,0x0E40,0x1640,0x1640,
	0x1E40,0x1E40,0x2640,0x2640,0x2E40,0x2E60,0x3660,0x3660,0x3E60,0x3E60,
	0x3E60,0x4660,0x4660,0x4E60,0x4E80,0x5680,0x5680,0x5E80,0x5E80,0x6680,
	0x6680,0x6E80,0x6EA0,0x76A0,0x76A0,0x7EA0,0x7EA0,0x86A0,0x86A0,0x8EA0,
	0x8EC0,0x96C0,0x96C0,0x9EC0,0x9EC0,0xA6C0,0xAEC0,0xAEC0,0xB6E0,0xB6E0,
	0xBEE0,0xBEE0,0xC6E0,0xC6E0,0xCEE0,0xCEE0,0xD6E0,0xD700,0xDF00,0xDEE0,
	0xDEC0,0xDEA0,0xDE80,0xDE80,0xE660,0xE640,0xE620,0xE600,0xE5E0,0xE5C0,
	0xE5A0,0xE580,0xE560,0xE540,0xE520,0xE500,0xE4E0,0xE4C0,0xE4A0,0xE480,
	0xE460,0xEC40,0xEC20,0xEC00,0xEBE0,0xEBC0,0xEBA0,0xEB80,0xEB60,0xEB40,
	0xEB20,0xEB00,0xEAE0,0xEAC0,0xEAA0,0xEA80,0xEA60,0xEA40,0xF220,0xF200,
	0xF1E0,0xF1C0,0xF1A0,0xF180,0xF160,0xF140,0xF100,0xF0E0,0xF0C0,0xF0A0,
	0xF080,0xF060,0xF040,0xF020,0xF800,};
	
	//Create tft display object
	Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
	
	//Creating AMG objects
	Adafruit_AMG88xx amg;
	
	float pixels[AMG88xx_PIXEL_ARRAY_SIZE];   //One dimensional array is used to store 64 temperature data returned by amg
	
	uint16_t displayPixelWidth, displayPixelHeight; //Length and width of the smallest display unit of tft display screen
	
	float arr [8][8];                   //Put 64 temperature data in an 8 * 8 two-dimensional array
	
	float pixels2[85][85];              //Interpolated 85 * 85 two-dimensional array  
	
	float *pixels3 = new float[7225];   //Put the interpolated 85 * 85 two-dimensional array back into the one-dimensional array, with a total of 7225 temperature points  
	
	void setup() {
	  Serial.begin(9600);
	    Serial.println(F("AMG88xx thermal camera!"));
	    
	    tft.initR(INITR_BLACKTAB);  //I use a 1.8-inch display, so the initial screen size is 1.8-inch
	    
	    tft.fillScreen(ST7735_BLACK); //Areas not shown are indicated in black
	
	    //Change the smallest display cell to fill the entire screen
	    displayPixelWidth  = 1.33*tft.width() / 85;   
	    displayPixelHeight = 1.064*tft.height() / 85;
	    
	    bool status;
	    status = amg.begin();
	    if (!status) {
	        Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
	        while (1);
	    }
	    
	    Serial.println("-- Thermal Camera Test --");
	    delay(50); //Sensor intermittent delay
	
	}
	
	void loop() 
	{
	
	  //amg return data
	  amg.readPixels(pixels);
	  int hang;
	  int lie;
	  int x=-1;
	  
	  //One dimensional 64 variable two-dimensional 8 * 8
	    for(hang=0;hang<8;hang++)
	    {
	        for(lie=0;lie<8;lie++)
	        {
	            x=x+1;
	            arr[hang][lie]=pixels[x];
	        }
	    }
	
	  int a=-1;
	  float ku,kv;
	
	  //Interpolation calculation
	  //Insert 11 data points in the middle of each data point
	  for(hang=0;hang<85;hang++)
	  {
	      if(hang==0) {a=a+1;}
	      if(hang>2)
	      {
	        if(hang%12==1){a=a+1;}  
	      } 
	
	      if(hang%12==0){ku=0;}
	      if(hang%12==1){ku=0.0833;}
	      if(hang%12==2){ku=0.1666;}
	      if(hang%12==3){ku=0.2500;}
	      if(hang%12==4){ku=0.3333;}
	      if(hang%12==5){ku=0.4166;}
	      if(hang%12==6){ku=0.5000;}
	      if(hang%12==7){ku=0.5833;}
	      if(hang%12==8){ku=0.6666;}
	      if(hang%12==9){ku=0.7500;}
	      if(hang%12==10){ku=0.8333;}
	      if(hang%12==11){ku=0.9166;}
	      if(hang==12 || hang==24 || hang==36 || hang==48 || hang==60 || hang==72 || hang==84){ku=1;}
	      
	     int  b=-1;
	
	      for(lie=0;lie<85;lie++)
	      {
	          if(lie==0) {b=b+1;}
	          
	          if(lie>2)
	          {
	            if(lie%12==1){b=b+1;}  
	          }
	
	          if(lie%12==0){kv=0;}
	          if(lie%12==1){kv=0.0833;}
	          if(lie%12==2){kv=0.1666;}
	          if(lie%12==3){kv=0.2500;}
	          if(lie%12==4){kv=0.3333;}
	          if(lie%12==5){kv=0.4166;}
	          if(lie%12==6){kv=0.5000;}
	          if(lie%12==7){kv=0.5833;}
	          if(lie%12==8){kv=0.6666;}
	          if(lie%12==9){kv=0.7500;}
	          if(lie%12==10){kv=0.8333;}
	          if(lie%12==11){kv=0.9166;}
	          if(lie==12 || lie==24 || lie==36 || lie==48 || lie==60 || lie==72 || lie==84){kv=1;}
	          
	
	          pixels2[hang][lie] = (1-ku)*(1-kv)*arr[a][b]+(1-ku)*kv*arr[a][b+1]+ku*(1-kv)*arr[a+1][b]+ku*kv*arr[a+1][b+1];
	      }
	  }
	
	   //Two dimensional 85 * 85 variable one-dimensional 7225
	    int y=-1;
	    for (hang=0;hang<85;hang++)
	    {
	        for (lie=0;lie<85;lie++)
	        {
	            y=y+1;
	             pixels3[y]=pixels2[hang][lie];
	        }
	    }
	
	  //Display tft
	  for(int i=0; i<7225; i++)
	  {
	    float kk = 1;
	    uint8_t colorIndex = map(pixels3[i], MINTEMP, MAXTEMP, 0, 255);
	    colorIndex = constrain(colorIndex, 0, 255);
	
	    //tft.fillRect (x1,y1,x2,y2, filled content) 
	    //There are five quantities in this function
	    //x1 y1 is the coordinate of the upper left starting point of the filling rectangle
	    //x2 y2 is the coordinate of the lower right end point of the filled rectangle
	    //Finally, the color of the filling, which corresponds to the color with temperature
	    tft.fillRect(kk*displayPixelHeight * floor (i/85),kk*displayPixelWidth * (i%85),kk*displayPixelHeight, kk*displayPixelWidth, camColors[colorIndex]);
	  
	  }
	}

Posted by s2day on Fri, 26 Nov 2021 02:46:37 -0800