胡乱捣鼓02——AMG8833+Arduino+插值 实现DIY热成像

文章目录[隐藏]

1.效果

大家也知道AMG8833模块属于比较低端的红外温度采集传感器,探测精度也不高,距离条件也不是特别好,远一点就没有轮廓而是一团圆形了。所以这个是我目前做的个人认为比较不错的效果图了(其实也就那样),话不多说,我们先看效果吧。

以下是1.44寸tft屏幕的效果图:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
以下是1.8寸的tft的效果图:

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.原理

博主这里采用的是二次的线性插值。比方说一幅图由4个像素点y1,y2,Q21,Q22组成,那么在这四个像素点的中间插上与原始像素点(4个)加权过的插值像素点。具体的原理请看胡乱捣鼓01——基于AMG8833热成像模块的插值显示优化

在这里插入图片描述

3.设备

这里用到的主要设备有:

①AMG8833模块
在这里插入图片描述

②1.8寸的tft显示屏
在这里插入图片描述

③arduino due
在这里插入图片描述

为什么要用due呢?而不用uno、mega这种便宜一点的板子呢?因为我们插值的时候是用到芯片里面的SRAM资源的,芯片的计算能力决定了我们能做的插值的范围。简单的说,uno和nano的SRAM只有2k,经过我的测试,它顶天只能计算到11 * 11的数据,也就是说我们像素点的总个数超过11 * 11 = 121 点的时候,uno是无法再计算的,因此tft卡上也不会显示实时图像。所以这里选择了96k SRAM的due。当然我也用过mega,它的SRAM是8k的。可以做到28 * 28的像素显示。

当然会有人说可以用esp32,它有520k的内部SRAM,是的,esp32是完全可行的,只是博主目前没有太多时间去搞esp32,后续有时间会做胡乱捣鼓03,用esp32实现更好效果的热成像显示。

4.接线

我们先看AMG8833的接线。AMG8833和arduino采用的IIC通讯,也就4根引脚,VCC、GND、SDA、SCL。

VCC------------3.3V/5V
GND------------GND
SDA-------------SDA(20号引脚)
SCL-------------SCL(21号引脚)

再来看tft的接线。tft和due的接线有SPI通讯的四根以及显示引脚3根(代码定义了3根)

GND----------GND
VCC----------5V
SCL-----------SCK(下图红框)
SDA-----------MOSI(下图红框)
RES-----------引脚9
DC-------------引脚8
CS-------------引脚10

在这里插入图片描述

还有就是供电的线了,可以用5V的电源,可以用USB线,也可以用充电宝等等。

5.代码

下面就是aduino的代码
里面已经注释的非常的清楚了
目前还没有用参数实现N * N插值
但是看懂了修改自己想要的N * N数据也是完全没有问题的
使用代码前记得在aduino上面安装对应的库
记得点赞!

	//用到的库
	#include <Adafruit_GFX.h>    
	#include <Adafruit_ST7735.h> 
	#include <SPI.h>
	#include <Wire.h>
	#include <Adafruit_AMG88xx.h>
	#include <avr/pgmspace.h>
	
	//tft显示屏的引脚
	#define TFT_CS     10  
	#define TFT_RST    9                     
	#define TFT_DC     8
	
	
	//温度,对应颜色
	#define MINTEMP 40
	#define MAXTEMP 25
	
	//256种颜色
	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,};
	
	//创建tft显示对象
	Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
	
	//创建AMG对象
	Adafruit_AMG88xx amg;
	
	float pixels[AMG88xx_PIXEL_ARRAY_SIZE];   //一维数组 用来存放amg返回的64个温度数据
	
	uint16_t displayPixelWidth, displayPixelHeight; //tft显示屏的最小显示单元的长和宽
	
	float arr [8][8];                   //将64个温度数据放在8*8的二维数组中
	
	float pixels2[85][85];              //插值后的85*85的二维数组  
	
	float *pixels3 = new float[7225];   //将插值后的85*85二维数组放回到一维数组中,共7225个温度点  
	
	void setup() {
	  Serial.begin(9600);
	    Serial.println(F("AMG88xx thermal camera!"));
	    
	    tft.initR(INITR_BLACKTAB);  //我用的1.8寸的显示屏,所以初始化屏幕尺寸1.8寸
	    
	    tft.fillScreen(ST7735_BLACK); //没有显示的区域都用黑色表示
	
	    //改变显示最小单元来填满整个屏幕
	    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); //传感器间歇延时
	
	}
	
	void loop() 
	{
	
	  //amg返回数据
	  amg.readPixels(pixels);
	  int hang;
	  int lie;
	  int x=-1;
	  
	  //一维64变二维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;
	
	  //插值计算
	  //每个数据点中间插入11个数据点
	  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];
	      }
	  }
	
	   //二维85*85变一维7225
	    int y=-1;
	    for (hang=0;hang<85;hang++)
	    {
	        for (lie=0;lie<85;lie++)
	        {
	            y=y+1;
	             pixels3[y]=pixels2[hang][lie];
	        }
	    }
	
	  //显示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,填充的内容) 
	    //这个函数一共五个量
	    //x1 y1是填充矩形左上开始点的坐标
	    //x2 y2是填充矩形右下结束点的坐标
	    //最后就是填充的颜色,我们这用温度对应了颜色
	    tft.fillRect(kk*displayPixelHeight * floor (i/85),kk*displayPixelWidth * (i%85),kk*displayPixelHeight, kk*displayPixelWidth, camColors[colorIndex]);
	  
	  }
	}

版权声明:本文为CSDN博主「文斯莫克丶山治」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38502780/article/details/121535462

生成海报
点赞 0

文斯莫克丶山治

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

基于Arduino的显示测量环境数据设计

题目: 基于Arduino的显示测量环境数据设计 目录 基于Arduino的显示测量环境数据设计... 3 第一章 课题任务... 4 1.1课题任务... 4 1.2任务分工... 4 1.3设计条件... 4 第

Esp8266多功能点阵时钟(开源)

原文地址 多功能点阵时钟 更新 点阵时钟立创PCB工程已经完成,开源地址为: ESP8266多功能点阵时钟 - PCB制作分享 简介 很早就了解ESP8266了,当时也用这个搞过一些小demo,一直也没有想