热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于ESP32+AMG8833+微信小程序的可联网红外线感应仪

背景:在新冠疫情的时代大背景之下,保持安全距离,避免密集接触是环境所致,同时测量体温也是出入公共场合不可或缺的一环

背景:

在新冠疫情的时代大背景之下,保持安全距离,避免密集接触是环境所致,同时测量体温也是出入公共场合不可或缺的一环,所以实行非接触测温有很大的必要性。

本项目开发了一款在Arduino开发环境下基于esp32以及AMG8833的红外热成像感应仪,本项目可以实现新冠疫情下的非接触测温以及区域热成像功能,传感器收集信息后通过液晶屏能够实时显示热成像以及区域最高、最低温度、中心点温度,在低功耗模式下关闭红外成像模块可以实时显示全球疫情情况的数据。




项目效果:

点击查看展示视频(B站)

     低功耗模式下联网显示全球疫情数据

                                                                    红外成像效果

                         小程序界面(前四个按钮为蓝牙连接,后两个控制esp32切换模式)




 项目的技术栈:




系统流程:





全部代码:


一、Arduino代码

第一次用Arduino开发esp32请点这里配置基本环境

1-1 ESP32开发板与外设引脚连线


ESP32开发板

按键开关

TFT-LCD

AMG8833

3V3

+

VCC

23

SDA

26

RES

18

SCL

27

DC

5

CS

GND

GND

GND

21

SDA

22

SCL

5V

VIM

本项目采用的TFT屏幕尺寸为128×160,不同的屏幕需要在文件中设置屏幕尺寸以及引脚映射,可以参考TFT_eSPI库驱动ST7789


1.主文件(ino)

tips:本项目引用的"<>"格式的库文件都能通过直接在Arduino环境中添加库完成,不会请点这里;

除此之外还引用了两个自建的头文件“HanZi16.h”(负责存储要显示的汉字)

和"interpolation.h"(用插值算法将amg8833返回的8×8点阵拓展为32×32)


#include // ST7735 or ST7735S驱动
#include
#include "HanZi16.h"
TFT_eSPI tft = TFT_eSPI();
#include
#include
#include
#include
#include
#include
#include
#include
#include "interpolation.h"
BLECharacteristic *pCharacteristic;
bool deviceCOnnected= false;
uint32_t buff =0;
char time1[30]={0};
char quezhen1[30]={0};
char quezhen2[30]={0};
char siwang1[30]={0};
char siwang2[30]={0};
char zhiyu1[30]={0};
char zhiyu2[30]={0};
char yin[30]="100636";
char ba[30]="66017";
char ge[30]="28971";
uint32_t cnt = 0;#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"/*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,};//low range of the sensor (this will be blue on the screen)
#define MINTEMP 14
//high range of the sensor (this will be red on the screen)
#define MAXTEMP 30/*32*32为优化后的分辨率,不宜太高,提升分辨率修改此处即可*/
#define INTERPOLATED_COLS 32
#define INTERPOLATED_ROWS 32
#define AMG_COLS 8
#define AMG_ROWS 8Adafruit_AMG88xx amg;
unsigned long delayTime;
float pixels[AMG_COLS * AMG_ROWS];
uint16_t displayPixelWidth, displayPixelHeight;
uint16_t displayPixelX, displayPixelY;class MyServerCallbacks: public BLEServerCallbacks {void onConnect(BLEServer* pServer) {deviceCOnnected= true;};void onDisconnect(BLEServer* pServer) {deviceCOnnected= false;}
};class MyCallbacks: public BLECharacteristicCallbacks {void onWrite(BLECharacteristic *pCharacteristic) {std::string rxValue = pCharacteristic->getValue();if (rxValue.length() > 0) {buff=1;Serial.print("------>Received Value: ");if(rxValue[0]==&#39;a&#39;){for (int i = 1; i };/* 画热成像素点 */
void drawpixels(float *p, uint8_t rows, uint8_t cols, uint8_t boxWidth, uint8_t boxHeight, boolean showVal) {int colorTemp;float curMax = get_point(p, rows, cols, 0, 0), curMin = get_point(p, rows, cols, 0, 0), curMid = get_point(p, rows, cols, cols/2, rows/2);uint16_t colorMax = camColors[0], colorMin = camColors[0],colorMid = camColors[0]; //画热成像for (int y=0; y= 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!tft.fillRect( boxWidth * x, displayPixelY + boxHeight * y, boxWidth, boxHeight, camColors[colorIndex]);//取最大值if(val >= curMax){ curMax = val;colorMax = camColors[colorIndex];} //取最小值 if(val <= curMin){curMin = val;colorMin = camColors[colorIndex];}//取中心点if(y == rows/2 && x == cols/2){colorMid = camColors[colorIndex];}if (showVal) {tft.setCursor(boxWidth * y + boxWidth/2 - 12, 40 + boxHeight * x + boxHeight/2 - 4);tft.setTextSize(1);tft.setTextColor(TFT_WHITE);tft.print(val,1);}} }//画中心点十字uint8_t midX = cols*boxWidth/2;uint8_t midY = displayPixelY+rows*boxHeight/2;tft.drawLine(midX-5, midY, midX+5, midY, TFT_WHITE);tft.drawLine(midX, midY-5, midX, midY+5, TFT_WHITE);char temp[7];tft.setTextSize(1);tft.setTextColor(TFT_WHITE);//显示最高温度tft.drawLine(128, 10, 159, 10, TFT_WHITE);tft.drawLine(128, 40, 159, 40, TFT_WHITE);tft.drawLine(128, 10, 128, 40, TFT_WHITE);tft.drawLine(159, 10, 159, 40, TFT_WHITE);tft.setTextDatum(TL_DATUM);tft.drawString(F("max"), tft.width()-28, 0); tft.fillRect(129, 11, 30, 29, colorMax); tft.setTextDatum(CL_DATUM);memset(temp, 0, sizeof(temp));sprintf(temp, "%0.1f", curMax);tft.drawString(String(temp), tft.width()-28, 25);//显示最低温度tft.drawLine(128, 10+40, 159, 10+40, TFT_WHITE);tft.drawLine(128, 40+40, 159, 40+40, TFT_WHITE);tft.drawLine(128, 10+40, 128, 40+40, TFT_WHITE);tft.drawLine(159, 10+40, 159, 40+40, TFT_WHITE);tft.setTextDatum(TL_DATUM);tft.drawString(F("min"), tft.width()-28, 40); tft.fillRect(129, 51, 30, 29, colorMin); tft.setTextDatum(CL_DATUM); memset(temp, 0, sizeof(temp));sprintf(temp, "%0.1f", curMin);tft.drawString(String(temp), tft.width()-28, 65);//显示中心点温度tft.drawLine(128, 10+40+40, 159, 10+40+40, TFT_WHITE);tft.drawLine(128, 40+40+40, 159, 40+40+40, TFT_WHITE);tft.drawLine(128, 10+40+40, 128, 40+40+40, TFT_WHITE);tft.drawLine(159, 10+40+40, 159, 40+40+40, TFT_WHITE);tft.setTextDatum(TL_DATUM);tft.drawString(F("center"), tft.width()-32, 80); tft.fillRect(129, 91, 30, 29, colorMid); tft.setTextDatum(CL_DATUM);memset(temp, 0, sizeof(temp));sprintf(temp, "%0.1f", curMid);tft.drawString(String(temp), tft.width()-28, 105);}void setup() {// put your setup code here, to run once:Serial.begin(115200);tft.init();tft.setRotation(1);tft.fillScreen(TFT_BLACK);displayPixelWidth = tft.height() / 8;displayPixelHeight = tft.height() / 8;displayPixelX = (tft.width() - displayPixelWidth*8)/2;displayPixelY = (tft.height() - displayPixelHeight*8)/2;//drawTemperateBar();bool status;// default settingsstatus = amg.begin();if (!status) {Serial.println("Could not find a valid AMG8833 sensor, check wiring!");while (1);}Serial.println("-- Thermal Camera Test --");delay(100); // let sensor boot up// Create the BLE DeviceBLEDevice::init("红外成像仪"); // Create the BLE ServerBLEServer *pServer = BLEDevice::createServer();pServer->setCallbacks(new MyServerCallbacks());// Create the BLE ServiceBLEService *pService = pServer->createService(SERVICE_UUID);// Create a BLE CharacteristicpCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);pCharacteristic->addDescriptor(new BLE2902());BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);pCharacteristic->setCallbacks(new MyCallbacks());// Start the servicepService->start();// Start advertisingpServer->getAdvertising()->start();Serial.println("Waiting a client connection to notify...");tft.init();tft.setRotation(1);tft.fillScreen(TFT_BLACK);}
void drawquezhen(){tft.init();tft.setTextColor(TFT_BLACK, TFT_DARKGREEN); // 新字体不画背景色 Note: the new fonts do not draw the background colourtft.fillRoundRect(8, 8, 144, 112, 8, TFT_DARKGREEN);char str[] = "全球疫情数据";drawHanziS(32, 16, str, TFT_LIGHTGREY);tft.fillRoundRect(20, 48, 128, 64, 4, TFT_LIGHTGREY);char str1[] = "累计确诊";drawHanziS(48, 50, str1, TFT_YELLOW);char str2[] = "较昨日";drawHanziS(20, 92, str2, TFT_YELLOW); tft.setTextSize(1);tft.setTextColor(TFT_BLACK, TFT_DARKGREEN);tft.drawString(String(time1), 14, 36);tft.setTextSize(2);tft.setTextColor(TFT_MAROON, TFT_LIGHTGREY);tft.drawString(String(quezhen1), 24, 72);tft.setTextSize(2);tft.setTextColor(TFT_RED, TFT_LIGHTGREY);tft.drawString(String(quezhen2), 70, 92);}void drawsiwang(){tft.init();
tft.setTextColor(TFT_BLACK, TFT_DARKGREEN); // 新字体不画背景色 Note: the new fonts do not draw the background colourtft.fillRoundRect(8, 8, 144, 112, 8, TFT_DARKGREEN);char str[] = "全球疫情数据";drawHanziS(32, 16, str, TFT_LIGHTGREY);tft.fillRoundRect(20, 48, 128, 64, 4, TFT_LIGHTGREY);char str1[] = "累计死亡";drawHanziS(48, 50, str1, TFT_YELLOW);char str2[] = "较昨日";drawHanziS(20, 92, str2, TFT_YELLOW); tft.setTextSize(1);tft.setTextColor(TFT_BLACK, TFT_DARKGREEN);tft.drawString(String(time1), 14, 36);tft.setTextSize(2);tft.setTextColor(TFT_BLACK, TFT_LIGHTGREY);tft.drawString(String(siwang1), 24, 72);tft.setTextSize(2);tft.setTextColor(TFT_DARKGREY, TFT_LIGHTGREY);tft.drawString(String(siwang2), 70, 92); }void drawzhiyu(){tft.init();tft.setTextColor(TFT_BLACK, TFT_DARKGREEN); // 新字体不画背景色 Note: the new fonts do not draw the background colourtft.fillRoundRect(8, 8, 144, 112, 8, TFT_DARKGREEN);char str[] = "全球疫情数据";drawHanziS(32, 16, str, TFT_LIGHTGREY);tft.fillRoundRect(20, 48, 128, 64, 4, TFT_LIGHTGREY);char str1[] = "累计治愈";drawHanziS(48, 50, str1, TFT_YELLOW);char str2[] = "较昨日";drawHanziS(20, 92, str2, TFT_YELLOW); tft.setTextSize(1);tft.setTextColor(TFT_BLACK, TFT_DARKGREEN);tft.drawString(String(time1), 14, 36);tft.setTextSize(2);tft.setTextColor(TFT_DARKGREEN, TFT_LIGHTGREY);tft.drawString(String(zhiyu1), 24, 72);tft.setTextSize(2);tft.setTextColor(TFT_GREEN , TFT_LIGHTGREY);tft.drawString(String(zhiyu2), 70, 92); }void drawguojia(){tft.init();tft.fillRoundRect(8, 8, 144, 112, 8, TFT_DARKGREY);tft.setTextSize(2);tft.setTextColor(TFT_LIGHTGREY , TFT_DARKGREY);tft.drawString(String("TOP3"), 50, 16);tft.setTextSize(1);tft.setTextDatum(TL_DATUM);tft.setTextColor(TFT_LIGHTGREY , TFT_DARKGREY);tft.drawString(String(time1), 14, 36); char str[] = "印度";drawHanziS(16, 60, str, TFT_LIGHTGREY);tft.setTextColor(TFT_LIGHTGREY , TFT_RED);//tft.drawString(String(yin), 80, 60);tft.fillRect(80, 60, 64, 16, TFT_RED); char str1[] = "巴西";drawHanziS(16, 80, str1, TFT_LIGHTGREY);tft.setTextColor(TFT_LIGHTGREY , TFT_RED);//tft.drawString(String(ba), 80, 80);tft.fillRect(80, 80, 50, 16, TFT_RED); char str2[] = "哥伦比亚";drawHanziS(16, 100, str2, TFT_LIGHTGREY);tft.setTextColor(TFT_LIGHTGREY , TFT_RED);//tft.drawString(String(ge), 80, 100);tft.fillRect(80, 100, 25, 16, TFT_RED); tft.setTextSize(1);tft.setTextDatum(TL_DATUM);}
void loop() {amg.readPixels(pixels);float dest_2d[INTERPOLATED_ROWS * INTERPOLATED_COLS];//int32_t t = millis();interpolate_image(pixels, AMG_ROWS, AMG_COLS, dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);uint16_t boxsize = min(tft.width() / INTERPOLATED_COLS, tft.height() / INTERPOLATED_COLS);if (buff) {tft.fillScreen(TFT_BLACK);drawquezhen(); delay(5000);};if(buff){tft.fillScreen(TFT_BLACK);drawsiwang();delay(5000);};if(buff){tft.fillScreen(TFT_BLACK);drawzhiyu();delay(5000);};if(buff){tft.fillScreen(TFT_BLACK);drawguojia();delay(10000);};if(!buff){drawpixels(dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS, boxsize, boxsize, false);};
}
void drawHanzi(int32_t x, int32_t y, const char c[3], uint32_t color) { //显示单一汉字for (int k = 0; k <25; k++)if (hanzi16[k].Index[0] == c[0] && hanzi16[k].Index[1] == c[1] && hanzi16[k].Index[2] == c[2]){ tft.drawBitmap(x, y, hanzi16[k].hz16_Id, hanzi16[k].hz_width, 16, color);}
}
void drawHanziS(int32_t x, int32_t y, const char str[], uint32_t color) { //显示整句汉字,字库目前有限,比较简单,没有换行功能,上下输出,左右输出是在函数内实现int y0 = y;int x0 = x;for (int i = 0; i }

2.HanZi16.h代码

#include

PROGMEM const unsigned char hz16_1[] =
{0x01,0x00,0x01,0x00,0x02,0x80,0x04,0x40,0x08,0x20,0x10,0x10,0x2F,0xE8,0xC1,0x06,
0x01,0x00,0x01,0x00,0x1F,0xF0,0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x00,0x00
};
PROGMEM const unsigned char hz16_2[] =
{0x00,0x28,0x00,0x24,0xFC,0x24,0x10,0x20,0x13,0xFE,0x10,0x20,0x11,0x20,0x7C,0xB2,
0x10,0xB4,0x10,0x68,0x10,0xA8,0x11,0x24,0x1E,0x22,0xE0,0x20,0x40,0xA0,0x00,0x40
};
PROGMEM const unsigned char hz16_3[] =
{
0x00,0x80,0x00,0x40,0x1F,0xFE,0x10,0x00,0x93,0xF0,0x52,0x10,0x52,0x10,0x14,0x0E,
0x38,0x00,0x57,0xF8,0x92,0x08,0x11,0x10,0x20,0xA0,0x20,0x40,0x41,0xB0,0x8E,0x0E};
PROGMEM const unsigned char hz16_4[] =
{
0x10,0x40,0x10,0x40,0x17,0xFC,0x10,0x40,0x1B,0xF8,0x54,0x40,0x57,0xFE,0x50,0x00,
0x93,0xF8,0x12,0x08,0x13,0xF8,0x12,0x08,0x13,0xF8,0x12,0x08,0x12,0x28,0x12,0x10};
PROGMEM const unsigned char hz16_5[] =
{
0x08,0x20,0x49,0x20,0x2A,0x20,0x08,0x3E,0xFF,0x44,0x2A,0x44,0x49,0x44,0x88,0xA4,
0x10,0x28,0xFE,0x28,0x22,0x10,0x42,0x10,0x64,0x28,0x18,0x28,0x34,0x44,0xC2,0x82
};
PROGMEM const unsigned char hz16_6[] =
{
0x20,0x00,0x23,0xFC,0x22,0x04,0x22,0x04,0xFB,0xFC,0x22,0x20,0x22,0x20,0x2B,0xFE,
0x32,0x20,0xE2,0x20,0x22,0xFC,0x22,0x84,0x22,0x84,0x24,0x84,0xA4,0xFC,0x48,0x84
};
PROGMEM const unsigned char hz16_7[] =
{
0x00,0x00,0x3F,0xF8,0x21,0x08,0x3F,0xF8,0x21,0x08,0x3F,0xF8,0x02,0x00,0x04,0x20,
0x1F,0xC0,0x01,0x80,0x06,0x10,0x3F,0xF8,0x01,0x08,0x11,0x20,0x25,0x10,0x42,0x08
};
PROGMEM const unsigned char hz16_8[] =
{
0x00,0x40,0x20,0x40,0x10,0x40,0x10,0x40,0x00,0x40,0x00,0x40,0xF7,0xFE,0x10,0x40,
0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x14,0x40,0x18,0x40,0x10,0x40,0x00,0x40
};
PROGMEM const unsigned char hz16_9[] =
{
0x00,0x40,0x00,0x40,0xFC,0x7C,0x10,0x84,0x11,0x08,0x22,0xFE,0x3C,0x92,0x64,0x92,
0x64,0xFE,0xA4,0x92,0x24,0x92,0x24,0xFE,0x3C,0x92,0x25,0x12,0x21,0x0A,0x02,0x04
};
PROGMEM const unsigned char hz16_10[] =
{
0x00,0x40,0x40,0x40,0x20,0xA0,0x21,0x10,0x02,0x08,0x04,0x26,0xE0,0x40,0x20,0x80,
0x23,0x10,0x20,0x20,0x20,0x40,0x28,0x88,0x33,0x10,0x20,0x20,0x00,0xC0,0x07,0x00};
PROGMEM const unsigned char hz16_11[] =
{
0x20,0x40,0x20,0x20,0x20,0x20,0xFD,0xFE,0x40,0x00,0x50,0x88,0x91,0x04,0xFE,0x02,
0x10,0x88,0x10,0x88,0x1C,0x50,0xF0,0x50,0x50,0x20,0x10,0x50,0x10,0x88,0x13,0x06};
PROGMEM const unsigned char hz16_12[] =
{
0x01,0x00,0x01,0x00,0x79,0x00,0x49,0xFE,0x4A,0x80,0x4A,0x80,0x4C,0x80,0x78,0xF8,
0x48,0x80,0x48,0x80,0x48,0x80,0x48,0xFC,0x78,0x80,0x48,0x80,0x00,0x80,0x00,0x80};
PROGMEM const unsigned char hz16_13[] =
{
0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10};
PROGMEM const unsigned char hz16_14[] =
{
0x00,0x00,0xFF,0xFC,0x10,0x80,0x10,0x80,0x10,0x84,0x1E,0x88,0x22,0x90,0x22,0xA0,
0x52,0xC0,0x8C,0x80,0x04,0x80,0x08,0x84,0x08,0x84,0x10,0x84,0x20,0x7C,0x40,0x00};
PROGMEM const unsigned char hz16_15[] =
{
0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0xFF,0xFE,0x10,0x00,0x10,0x00,0x10,0x00,
0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x1F,0xFC,0x00,0x00};
PROGMEM const unsigned char hz16_16[] =
{
0x00,0x40,0x20,0x40,0x10,0x80,0x11,0x10,0x82,0x08,0x47,0xFC,0x40,0x04,0x10,0x00,
0x13,0xF8,0x22,0x08,0xE2,0x08,0x22,0x08,0x22,0x08,0x22,0x08,0x23,0xF8,0x02,0x08};
PROGMEM const unsigned char hz16_17[] =
{
0x01,0x00,0x02,0x80,0x0C,0x60,0x37,0xD8,0xC0,0x06,0x3E,0x08,0x22,0x48,0x3E,0x48,
0x22,0x48,0x3E,0x48,0x22,0x08,0x26,0x18,0x01,0x00,0x48,0x84,0x48,0x12,0x87,0xF2};
PROGMEM const unsigned char hz16_18[] =
{
0x00,0x00,0x06,0x00,0x78,0xFC,0x40,0x84,0x40,0x84,0x40,0x84,0x7E,0x84,0x40,0x84,
0x40,0x84,0x40,0x84,0x40,0x84,0x4E,0xA8,0x70,0x90,0x00,0x80,0x00,0x80,0x00,0x80};
PROGMEM const unsigned char hz16_19[] =
{
0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20,
0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E};
PROGMEM const unsigned char hz16_20[] =
{
0x00,0x00,0x3F,0xF8,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,
0x20,0x08,0x20,0x00,0x20,0x00,0x20,0x02,0x20,0x02,0x20,0x02,0x1F,0xFE,0x00,0x00
};
PROGMEM const unsigned char hz16_21[] =
{
0x00,0x00,0xFF,0xFE,0x04,0x40,0x04,0x40,0x04,0x40,0x3F,0xF8,0x24,0x48,0x24,0x48,
0x24,0x48,0x24,0x48,0x28,0x38,0x30,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x20,0x08};
PROGMEM const unsigned char hz16_22[] =
{
0x00,0x00,0x7F,0xFC,0x00,0x10,0x1F,0x90,0x10,0x90,0x10,0x90,0x1F,0x90,0x00,0x00,
0xFF,0xFE,0x00,0x10,0x1F,0x90,0x10,0x90,0x10,0x90,0x1F,0x90,0x00,0x50,0x00,0x20};
PROGMEM const unsigned char hz16_23[] =
{
0x08,0x40,0x08,0x40,0x08,0xA0,0x10,0xA0,0x11,0x10,0x32,0x08,0x34,0x06,0x51,0x10,
0x91,0x20,0x11,0x40,0x11,0x80,0x11,0x00,0x11,0x04,0x11,0x04,0x10,0xFC,0x10,0x00};
PROGMEM const unsigned char hz16_24[] =
{
0x00,0x80,0x20,0x80,0x20,0x80,0x20,0x84,0x20,0x88,0x20,0x90,0x3E,0xA0,0x20,0xC0,
0x20,0x80,0x20,0x80,0x20,0x80,0x20,0x82,0x26,0x82,0x38,0x82,0x20,0x7E,0x00,0x00};
PROGMEM const unsigned char hz16_25[] =
{
0x00,0x00,0x7F,0xFC,0x04,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x44,0x44,0x24,0x44,
0x24,0x48,0x14,0x48,0x14,0x50,0x04,0x40,0x04,0x40,0x04,0x40,0xFF,0xFE,0x00,0x00};struct FNT_HZ16 // 汉字字模数据结构
{char Index[4]; // 汉字内码索引,存放内码,如"中",在UTF-8编码下,每个汉字占3个字节,第四个是结束符0const unsigned char* hz16_Id; // 点阵码数据 存放内码后对应的 点阵序列 每个字需要32个字节的点阵序列unsigned char hz_width;
};PROGMEM const FNT_HZ16 hanzi16[] =
{{"全", hz16_1,16}, {"球", hz16_2,16}, {"疫", hz16_3,16}, {"情", hz16_4,16}, {"数", hz16_5,16}, {"据", hz16_6,16},{"累", hz16_7,16},{"计", hz16_8,16},{"确", hz16_9,16},{"诊", hz16_10,16},{"较", hz16_11,16},{"昨", hz16_12,16},{"日", hz16_13,16},{"死", hz16_14,16},{"亡", hz16_15,16},{"治", hz16_16,16},{"愈", hz16_17,16},{"印", hz16_18,16},{"度", hz16_19,16},{"巴", hz16_20,16},{"西", hz16_21,16},{"哥", hz16_22,16},{"伦", hz16_23,16},{"比", hz16_24,16},{"亚", hz16_25,16}
};


3.interpolation.h代码

#ifndef __INTERPOLATION__H__
#define __INTERPOLATION__H__
#include float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f);
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
float cubicInterpolate(float p[], float x);
float bicubicInterpolate(float p[], float x, float y);
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols, float *dest, uint8_t dest_rows, uint8_t dest_cols);#endif


二、微信小程序代码


1.js代码

tips:本项目通过爬取腾讯云全球疫情信息来实时获取疫情数据的,详细方法点这里

// pages/lanyatest/lanyatest.js
Page({/*** 页面的初始数据*/data: {info:"未初始化蓝牙适配器",connectedDeviceId:"",deviceId:"",services:"",servicesUUID:"6E400001-B5A3-F393-E0A9-E50E24DCCA9E",serviceId:"",notifyCharacteristicsId:"",writeCharacteristicsId: "",sendmsg:"",res:"",foreignData:{},countryListLength: 0,nation: 0,addConfirm: 0,num: 0,rateSum:0.0},lanyatest1(event){var that = this;wx.openBluetoothAdapter({success: function (res) {console.log(&#39;初始化蓝牙适配器成功&#39;)//页面日志显示that.setData({info: &#39;初始化蓝牙适配器成功&#39;})},fail: function (res) {console.log(&#39;请打开蓝牙和定位功能&#39;)that.setData({info: &#39;请打开蓝牙和定位功能&#39;})}})wx.getBluetoothAdapterState({success: function (res) {//打印相关信息console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available);that.setData({info: JSON.stringify(res.errMsg) +"\n蓝牙是否可用:" + res.available})},fail: function (res) {//打印相关信息console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available);that.setData({info: JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available})}})wx.startBluetoothDevicesDiscovery({//services: [&#39;FEE7&#39;], //如果填写了此UUID,那么只会搜索出含有这个UUID的设备,建议一开始先不填写或者注释掉这一句//services: [&#39;00001801-0000-1000-8000-00805F9B34FB&#39;,&#39;00001800-0000-1000-8000-00805F9B34FB&#39;,&#39;6E400001-B5A3-F393-E0A9-E50E24DCCA9E&#39;], //如果填写了此UUID,那么只会搜索出含有这个UUID的设备,建议一开始先不填写或者注释掉这一句success: function (res) {that.setData({info: "搜索设备" + JSON.stringify(res),})console.log(&#39;搜索设备返回&#39; + JSON.stringify(res))}})wx.getBluetoothDevices({success: function (res) {that.setData({info: "设备列表\n" + JSON.stringify(res.devices),devices: res.devices})console.log(&#39;搜设备数目:&#39; + res.devices.length)console.log(&#39;设备信息:\n&#39; + JSON.stringify(res.devices)+"\n")}})},lanyaconnect(event){var that = this;wx.createBLEConnection({deviceId: event.currentTarget.id,success: function (res) {console.log(&#39;调试信息:&#39; + res.errMsg);that.setData({connectedDeviceId: event.currentTarget.id,info: "MAC地址:" + event.currentTarget.id + &#39; 调试信息:&#39; + res.errMsg,})},fail: function () {console.log("连接失败");},})},lanyatest6(event){var that = this;wx.stopBluetoothDevicesDiscovery({success: function (res) {console.log("停止搜索" + JSON.stringify(res.errMsg));that.setData({info: "停止搜索" + JSON.stringify(res.errMsg),})}})this.lanyatest7();},lanyatest7(event){var that = this;wx.getBLEDeviceServices({// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取deviceId: that.data.connectedDeviceId,success: function (res) {console.log(&#39;services UUID:\n&#39;, JSON.stringify(res.services));for (var i = 0; i strToHexCharCode(str) {if (str === "") {return "";} else {var hexCharCode = [];//hexCharCode.push("0x");for (var i = 0; i },//获取输入框的数据getmsg(event){this.setData({sendmsg:event.detail.value})},lanyatest12(event){var that = this;wx.closeBLEConnection({deviceId: that.data.connectedDeviceId,success: function (res) {that.setData({connectedDeviceId: "",})console.log(&#39;断开蓝牙设备成功:&#39; + res.errMsg)},fail:function(res){console.log(&#39;断开蓝牙设备失败:&#39; + res.errMsg)}})},onLoad: function (options) {// this.chinaMessage();this.foreignMessage();},//中国chinaMessage(){var that=this;wx.request({url: &#39;https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5&#39;,method: &#39;GET&#39;,dataType: &#39;json&#39;,success: function (res) {// console.log(res) //json字符串转Json对象that.setData({eare: JSON.parse(res.data.data)});console.log("111")console.log(that.data.eare)}})},//国外foreignMessage() {var that=this;wx.request({url: &#39;https://view.inews.qq.com/g2/getOnsInfo?name=disease_foreign&#39;,method: &#39;GET&#39;,dataType: &#39;json&#39;,success: function (res) {that.setData({foreignData: JSON.parse(res.data.data)});console.log("222")console.log(that.data.foreignData.continentStatis[0].statis.亚洲)that.countryAddConfirmRankList_fun()}})},sendsomething(num,event){var that = thisvar hex=this.strToHexCharCode(num+event)//console.log(hex1)//var hex = that.data.sendmsg //要发送的信息console.log(&#39;要发送的信息是:&#39;+hex)var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {return parseInt(h, 16)}))console.log(typedArray)var buffer1 = typedArray.bufferwx.writeBLECharacteristicValue({deviceId: that.data.connectedDeviceId,serviceId: that.data.servicesUUID,characteristicId: that.data.writeCharacteristicsId,// 这里的value是ArrayBuffer类型value: buffer1,success: function (res) {console.log(&#39;写入成功&#39;)},fail(res){console.log(&#39;写入失败&#39;)}})},senttime(){console.log(this.data.foreignData.globalStatis.lastUpdateTime)var that = thisthis.sendsomething("a",this.data.foreignData.globalStatis.lastUpdateTime)this.sendsomething("b",this.data.foreignData.globalStatis.confirm)this.sendsomething("c",this.data.foreignData.globalStatis.confirmAdd)this.sendsomething("d",this.data.foreignData.globalStatis.dead)this.sendsomething("e",this.data.foreignData.globalStatis.deadAdd)this.sendsomething("f",this.data.foreignData.globalStatis.heal)this.sendsomething("g",this.data.foreignData.globalStatis.healAdd)this.sendsomething("h",this.data.foreignData.globalStatis.countryAddConfirmRankList[0].addConfirm)this.sendsomething("i",this.data.foreignData.globalStatis.countryAddConfirmRankList[1].addConfirm)this.sendsomething("j",this.data.foreignData.globalStatis.countryAddConfirmRankList[2].addConfirm)this.sendsomething("k","k")},senttime2(){this.sendsomething("k","k")},countryAddConfirmRankList_fun(){console.log(this.data.foreignData)var num1=0;var num2=0.0;for (var i = 0; i function ab2hex(buffer) {var hexArr = Array.prototype.map.call(new Uint8Array(buffer),function (bit) {return (&#39;00&#39; + bit.toString(16)).slice(-2)})return hexArr.join(&#39;,&#39;);
}


2.wxml代码





3.wxss代码

/* pages/lanyatest/lanyatest.wxss */
.vertical{display: flex;flex-direction: column;
}/**index.wxss**/
.horizontal{display: flex;flex-direction: row;
}.btinfo{height:100px;
}.contentview {
margin: 0 10px;
}.button {
margin: 5px;
}.myview{height:200px;word-break:break-all;/* 自动换行 */
}
/**index.wxss**/page {padding: 0;margin: 0;
}.head {width: 94%;background-color: #00b26a;border-radius: 18rpx;margin-left: 3%;display: flex;flex-direction: column;
}.head .title {width: 100%;height: 60rpx;text-align: center;line-height: 60rpx;font-size: 35rpx;margin-top: 10rpx;
}.head .updateTime {width: 100%;height: 40rpx;font-size: 25rpx;line-height: 40rpx;margin-left: 10rpx;margin-bottom: 10rpx;overflow: hidden;border-left: solid yellow 6rpx;padding-left: 5rpx;
}.head .globalStatis {display: flex;flex-direction: row;justify-content: space-around;
}.head .globalStatis .confirm, .head .globalStatis .dead,
.head .globalStatis .heal, .head .globalStatis .nowConfirm {width: 24%;height: 110rpx;border-radius: 5rpx;display: flex;flex-direction: column;justify-content: space-around;align-items: center;opacity: 0.7;margin-bottom: 25rpx;
}.head .globalStatis .confirm .text, .head .globalStatis .dead .text,
.head .globalStatis .heal .text, .head .globalStatis .nowConfirm .text {font-size: 25rpx;margin-top: 5rpx;
}.head .globalStatis .confirm .add, .head .globalStatis .dead .add,
.head .globalStatis .heal .add, .head .globalStatis .nowConfirm .add {font-size: 22rpx;display: flex;flex-direction: row;justify-content: center;margin-bottom: 5rpx;
}.head .globalStatis .confirm .num, .head .globalStatis .dead .num,
.head .globalStatis .heal .num, .head .globalStatis .nowConfirm .num {font-size: 25rpx;font-weight: bold;
}.head .globalStatis .confirm {background-color: rgb(255, 240, 241);margin-left: 5rpx;
}.head .globalStatis .dead {background-color: rgb(242, 246, 247);
}.head .globalStatis .heal {background-color: rgb(240, 248, 244);
}.head .globalStatis .nowConfirm {background-color: rgb(255, 240, 241);margin-right: 5rpx;
}.head .globalStatis .confirm .num, .head .globalStatis .confirm .add-num,
.head .globalStatis .nowConfirm .num, .head .globalStatis .nowConfirm .add-num {color: red;
}.head .globalStatis .heal .num, .head .globalStatis .heal .add-num {color: rgb(0, 178, 106);
}.countryAddConfirmRankList {width: 94%;height: 480rpx;margin-left: 3%;background-color: rgb(240, 240, 240);margin-top: 20rpx;display: flex;flex-direction: column;border-radius: 12rpx;}.countryAddConfirmRankList swiper{width: 100%;height: 100%;
}.countryAddConfirmRankList .title {width: 100%;height: 60rpx;text-align: left;line-height: 60rpx;font-size: 35rpx;margin-top: 10rpx;border-left: solid 10rpx yellow;padding-left: 5rpx;
}.countryAddConfirmRankList .countryList {width: 100%;margin-top: 5rpx;display: flex;flex-direction: row;font-size: 25rpx;
}.countryAddConfirmRankList .countryList .nation {width: 150rpx;margin-right: 10rpx;text-align: right;
}.countryAddConfirmRankList .countryList .rank {background-color: red;
}.countryAddConfirmRankList .countryList .addConfirm {width: 150rpx;margin-left: 10rpx;
}.continentStatis {width: 94%;margin-left: 3%;background-color: rgb(240, 240, 240);margin-top: 20rpx;overflow: hidden;white-space: nowrap;border-radius: 12rpx;height: 500rpx;
}.continentStatis scroll-view {height: 400rpx;width: auto;overflow: hidden;
}.continentStatis .title {width: 100%;height: 60rpx;text-align: left;line-height: 60rpx;font-size: 35rpx;margin-top: 10rpx;border-left: solid 10rpx yellow;padding-left: 5rpx;
}.continentStatis .first {display: block;font-size: 30rpx;
}.continentStatis .first .lastData {width: 150rpx;display: inline-block;text-align: center;
}.continentStatis .first .zhou {display: inline-block;
}.continentStatis .first .zhou .zh{width: 200rpx;display: inline-block;text-align: center;
}.continentStatis .first .zongji {width: 200rpx;display: inline-block;text-align: center;
}.continentStatis .first .bg{width: 100%;
}



引用与拓展学习:

本项目在做的过程中主要引用了下面几个博客,大家可以参考一下:

基于ESP32+AMG8833的物联网红外成像测温枪

ESP32 TTGO 1.14寸液晶屏使用 TFT_eSPI库驱动

微信小程序连接蓝牙ble教程(目录)ESP32 小程序与蓝牙通信/蓝牙配网/低功率蓝牙通信/Bluetooth


推荐阅读
  • ZABBIX 3.0 配置监控NGINX性能【OK】
    1.在agent端查看配置:nginx-V查看编辑时是否加入状态监控模块:--with-http_stub_status_module--with-http_gzip_stat ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • 目录1、将mysql数据导出到SQL文件中(数据库存在的情况)2、将现有的sql文件数据导入到数据库中(前提数据库存在) 3、利用Navicat导出SQL文件和导入SQL文件1)从 ... [详细]
  • Annotation的大材小用
    为什么80%的码农都做不了架构师?最近在开发一些通用的excel数据导入的功能,由于涉及到导入的模块很多,所以开发了一个比较通用的e ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
author-avatar
笼-中鸟
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有