一、硬件组成

  1. esp32用作主控。(型号为:esp32_devkitc_v4)
  2. 一块串口屏用作显示。(型号为:TJC3224T024_011)
  3. Usb转ttl模块用作调试。

二、开发环境搭建(Arduino IDE)

  1. 进入Arduino官网 https://www.arduino.cc/en/software下载Arduino IDE。安装好后界面如下:
  2. 搭建esp32开发环境:点击文件/首选项:

        

esp32串口数据可视化 esp32串口屏_单片机

输入:https://dl.espressif.com/dl/package_esp32_index.json 保存并重启Arduino

esp32串口数据可视化 esp32串口屏_物联网_02

 选择工具/开发板管理器

esp32串口数据可视化 esp32串口屏_串口_03

搜索esp32并下载安装

esp32串口数据可视化 esp32串口屏_esp32串口数据可视化_04

完成后可以看到esp32

esp32串口数据可视化 esp32串口屏_android studio_05

三、向api接口发送HTTP请求并解析

        

1、在Arduino中安装所需要的库文件:点击工具/管理库 

esp32串口数据可视化 esp32串口屏_esp32串口数据可视化_06

        在搜索框输入 WiFi ,选中需要安装的库文件 

esp32串口数据可视化 esp32串口屏_单片机_07

             

 2、设备初始化代码

#include<WiFi.h>          //用于连接WiFi网络
#include<HTTPClient.h>    //用于向服务端请求数据信息
#include<ArduinoJson.h>   //用于解析返回的json数据

const char *dssid = "ssid";    //你的网络名称
const char *password = "password"; //你的网络密码

void setup() {            //做设备初始化
  Serial.begin(115200);   //初始化串口波特率为115200
  Serial.println("");    //打印空白行

  WiFi.begin(dssid,password);//连接指定wifi

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }                    //连接中返回.....

  Serial.println("WiFi connected!");//WiFi连接成功
  
  // put your setup code here, to run once:

}

3、请求数据并返回

void loop() {
  HTTPClient http;     //建立HTTPClient对象

  http.begin("https://lab.isaaclin.cn/nCoV/api/overall");//向该网址发送http数据请求
  int httpCode = http.GET();     //保存返回的状态码
  // put your main code here, to run repeatedly:
  if (httpCode > 0) // 如果状态码大于0说明请求过程无异常
  {
    if (httpCode == HTTP_CODE_OK) // 请求被服务器正常响应,等同于httpCode == 200
    {
      String payload = http.getString(); // 读取服务器返回的响应正文数据
      Serial.println(payload);           //串口打印返回的数据
    }
  }
  else
  { //未被响应返回错误码
    Serial.printf("[HTTP] GET... failed, error: %s\n",             
    http.errorToString(httpCode).c_str());
  }
  http.end(); // 结束当前连接

  delay(1200000);//两分钟发送一次请求,过于频繁可能导致ip被接口封掉
}

4、下载验证:开发板型号选择:

esp32串口数据可视化 esp32串口屏_单片机_08

PS:端口根据自身情况选择

串口打印结果如下:

 

esp32串口数据可视化 esp32串口屏_esp32串口数据可视化_09

返回数据为:

esp32串口数据可视化 esp32串口屏_串口_10

5、对返回数据做json解析: 定义结构体

struct ncov_data{         //该结构体用于保存数据
    long currentConfirmedCount;//现存确诊
    long currentConfirmedIncr;//较昨日
    long confirmedCount;//累计确诊
    long confirmedIncr;//较昨日
    long curedCount;//累计治愈
    long curedIncr;//较昨日
    long seriousCount;//现存无症状
    long seriousIncr;//较昨日
    long deadCount;//累计死亡
    long deadIncr;//较昨日
    String updateTime;//更新时间
};

Json初始化

ncov_data China_data;              //国内疫情数据
ncov_data World_data;              //国外疫情数据
DynamicJsonDocument doc(1000);     //创建DynamicJsonDocument对象
deserializeJson(doc, payload);     //反序列化数据
JsonObject results_0 = doc["results"][0];

解析出的数据赋值

China_data.currentConfirmedCount = results_0["currentConfirmedCount"].as<int>();
      China_data.currentConfirmedIncr = results_0["currentConfirmedIncr"].as<int>();
      China_data.confirmedCount = results_0["confirmedCount"].as<int>();
      China_data.confirmedIncr = results_0["confirmedIncr"].as<int>();
      China_data.curedCount = results_0["curedCount"].as<int>();
      China_data.curedIncr = results_0["curedIncr"].as<int>();
      China_data.deadCount = results_0["deadCount"].as<int>();
      China_data.deadIncr = results_0["deadIncr"].as<int>();
      China_data.seriousCount = results_0["seriousCount"].as<int>();
      China_data.seriousIncr = results_0["seriousIncr"].as<int>();

      World_data.currentConfirmedCount = results_0["globalStatistics"]["currentConfirmedCount"].as<long>();
      World_data.currentConfirmedIncr = results_0["globalStatistics"]["currentConfirmedIncr"].as<long>();
      World_data.confirmedCount = results_0["globalStatistics"]["confirmedCount"].as<long>();
      World_data.confirmedIncr = results_0["globalStatistics"]["confirmedIncr"].as<long>();
      World_data.curedCount = results_0["globalStatistics"]["curedCount"].as<long>();
      World_data.curedIncr = results_0["globalStatistics"]["curedIncr"].as<long>();
      World_data.deadCount = results_0["globalStatistics"]["deadCount"].as<long>();
      World_data.deadIncr = results_0["globalStatistics"]["deadIncr"].as<long>();

串口打印

Serial.println("");
      Serial.println("----------------国内疫情---------------");
      Serial.print("现存确诊: ");Serial.println(China_data.currentConfirmedCount);
      Serial.print("累计确诊: ");Serial.println(China_data.confirmedCount);
      Serial.print("累计治愈: ");Serial.println(China_data.curedCount);
      Serial.print("现存无症: ");Serial.println(China_data.seriousCount);
      Serial.print("累计死亡: ");Serial.println(China_data.deadCount);
      Serial.println("----------------国外疫情---------------");
      Serial.print("现存确诊: ");Serial.println(World_data.currentConfirmedCount);
      Serial.print("累计确诊: ");Serial.println(World_data.confirmedCount);
      Serial.print("累计治愈: ");Serial.println(World_data.curedCount);
      Serial.print("累计死亡: ");Serial.println(World_data.deadCount);

esp32串口数据可视化 esp32串口屏_单片机_11

四、发送数据到串口屏并显示

         1、下载USART HMI串口屏软件 start [USART HMI 资料中心] (tjc1688.com)  

               官网有创建工程和基本使用的详细教程

               本人在此创建了两个界面,通过按钮控件进行切换,并使用全局变量保存来自单片机的                   数据并显示。可根据个人喜好搭建自己的ui界面

                

esp32串口数据可视化 esp32串口屏_单片机_12

 

esp32串口数据可视化 esp32串口屏_esp32串口数据可视化_13

                

        2、Arduino代码:串口定义

#define TJC Serial2       //串口屏收发串口定义为串口2

 初始化

TJC.begin(115200);      //初始化收发串口波特率为115200
while (TJC.read() >= 0);//等待串口屏连接成功

字符串定义

char str1[20];
      char str2[20];
      char str3[20];
      char str4[20];
      char str5[20];
      char str6[20];
      char str7[20];
      char str8[20];
      char str9[20];
      char str10[20];

sprintf格式拼接

sprintf(str1, "n0.val=%d\xff\xff\xff", China_data.currentConfirmedCount);
      sprintf(str6, "n5.val=%d\xff\xff\xff", China_data.currentConfirmedIncr);
      sprintf(str2, "n1.val=%d\xff\xff\xff", China_data.confirmedCount);
      sprintf(str7, "n6.val=%d\xff\xff\xff", China_data.confirmedIncr);
      sprintf(str3, "n2.val=%d\xff\xff\xff", China_data.curedCount);
      sprintf(str8, "n7.val=%d\xff\xff\xff", China_data.curedIncr);
      sprintf(str4, "n3.val=%d\xff\xff\xff", China_data.deadCount);
      sprintf(str9, "n8.val=%d\xff\xff\xff", China_data.deadIncr);
      sprintf(str5, "n4.val=%d\xff\xff\xff", China_data.seriousCount);
      sprintf(str10, "n9.val=%d\xff\xff\xff", China_data.seriousIncr);

数据发送

TJC.print(str1);
      TJC.print(str2);
      TJC.print(str3);
      TJC.print(str4);
      TJC.print(str5);
      TJC.print(str6);
      TJC.print(str7);
      TJC.print(str8);
      TJC.print(str9);
      TJC.print(str10);

3、将esp32的rx、tx引脚分别和串口屏的tx、rx引脚相连

4、参考文章 :疫情监控三部曲——在STM32F103 MCU上实现(裸机版) - 云+社区 - 腾讯云 (tencent.com)

五、完整代码

#include<WiFi.h>          //用于连接WiFi网络
#include<HTTPClient.h>    //用于向服务端请求数据信息
#include<ArduinoJson.h>   //用于解析返回的json数据

#define TJC Serial2       //串口屏收发串口定义为串口2

const char *dssid = "DOG";    //你的网络名称
const char *password = "66666666"; //你的网络密码

struct ncov_data{         //该结构体用于保存数据
    long currentConfirmedCount;//现存确诊
    long currentConfirmedIncr;//较昨日
    long confirmedCount;//累计确诊
    long confirmedIncr;//较昨日
    long curedCount;//累计治愈
    long curedIncr;//较昨日
    long seriousCount;//现存无症状
    long seriousIncr;//较昨日
    long deadCount;//累计死亡
    long deadIncr;//较昨日
    String updateTime;//更新时间
};
void setup() {            //做设备初始化
  Serial.begin(115200);   //初始化串口波特率为115200
  TJC.begin(115200);      //初始化收发串口波特率为115200
  while (TJC.read() >= 0);//等待串口屏连接成功
  Serial.println("");    //打印空白行

  WiFi.begin(dssid,password);//连接指定wifi

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }                    //连接中返回.....

  Serial.println("WiFi connected!");//WiFi连接成功
  
  // put your setup code here, to run once:

}

void loop() {
  HTTPClient http;     //建立HTTPClient对象

  http.begin("https://lab.isaaclin.cn/nCoV/api/overall");//向该网址发送http数据请求
  int httpCode = http.GET();     //保存返回的状态码
  // put your main code here, to run repeatedly:
  if (httpCode > 0) // 如果状态码大于0说明请求过程无异常
  {
    if (httpCode == HTTP_CODE_OK) // 请求被服务器正常响应,等同于httpCode == 200
    {
      String payload = http.getString(); // 读取服务器返回的响应正文数据
      Serial.println(payload);           //串口打印返回的数据
      
      ncov_data China_data;              //国内疫情数据
      ncov_data World_data;              //国外疫情数据
      DynamicJsonDocument doc(1000);     //创建DynamicJsonDocument对象
      deserializeJson(doc, payload);     //反序列化数据
      JsonObject results_0 = doc["results"][0];

      //将解析出的数据赋值给结构体
      China_data.currentConfirmedCount = results_0["currentConfirmedCount"].as<int>();
      China_data.currentConfirmedIncr = results_0["currentConfirmedIncr"].as<int>();
      China_data.confirmedCount = results_0["confirmedCount"].as<int>();
      China_data.confirmedIncr = results_0["confirmedIncr"].as<int>();
      China_data.curedCount = results_0["curedCount"].as<int>();
      China_data.curedIncr = results_0["curedIncr"].as<int>();
      China_data.deadCount = results_0["deadCount"].as<int>();
      China_data.deadIncr = results_0["deadIncr"].as<int>();
      China_data.seriousCount = results_0["seriousCount"].as<int>();
      China_data.seriousIncr = results_0["seriousIncr"].as<int>();

      World_data.currentConfirmedCount = results_0["globalStatistics"]["currentConfirmedCount"].as<long>();
      World_data.currentConfirmedIncr = results_0["globalStatistics"]["currentConfirmedIncr"].as<long>();
      World_data.confirmedCount = results_0["globalStatistics"]["confirmedCount"].as<long>();
      World_data.confirmedIncr = results_0["globalStatistics"]["confirmedIncr"].as<long>();
      World_data.curedCount = results_0["globalStatistics"]["curedCount"].as<long>();
      World_data.curedIncr = results_0["globalStatistics"]["curedIncr"].as<long>();
      World_data.deadCount = results_0["globalStatistics"]["deadCount"].as<long>();
      World_data.deadIncr = results_0["globalStatistics"]["deadIncr"].as<long>();

      //字符串定义
      char str1[20];
      char str2[20];
      char str3[20];
      char str4[20];
      char str5[20];
      char str6[20];
      char str7[20];
      char str8[20];
      char str9[20];
      char str10[20];
      char str11[20];
      char str12[20];
      char str13[20];
      char str14[20];
      char str15[20];
      char str16[20];
      char str17[20];
      char str18[20];

      //使用sprintf进行格式拼接
      sprintf(str1, "n0.val=%d\xff\xff\xff", China_data.currentConfirmedCount);
      sprintf(str6, "n5.val=%d\xff\xff\xff", China_data.currentConfirmedIncr);
      sprintf(str2, "n1.val=%d\xff\xff\xff", China_data.confirmedCount);
      sprintf(str7, "n6.val=%d\xff\xff\xff", China_data.confirmedIncr);
      sprintf(str3, "n2.val=%d\xff\xff\xff", China_data.curedCount);
      sprintf(str8, "n7.val=%d\xff\xff\xff", China_data.curedIncr);
      sprintf(str4, "n3.val=%d\xff\xff\xff", China_data.deadCount);
      sprintf(str9, "n8.val=%d\xff\xff\xff", China_data.deadIncr);
      sprintf(str5, "n4.val=%d\xff\xff\xff", China_data.seriousCount);
      sprintf(str10, "n9.val=%d\xff\xff\xff", China_data.seriousIncr);
      //发送数据
      TJC.print(str1);
      TJC.print(str2);
      TJC.print(str3);
      TJC.print(str4);
      TJC.print(str5);
      TJC.print(str6);
      TJC.print(str7);
      TJC.print(str8);
      TJC.print(str9);
      TJC.print(str10);
      TJC.print("page 1\xff\xff\xff");
      
      sprintf(str11, "n10.val=%d\xff\xff\xff", World_data.currentConfirmedCount);
      sprintf(str12, "n11.val=%d\xff\xff\xff", World_data.currentConfirmedIncr);
      sprintf(str13, "n12.val=%d\xff\xff\xff", World_data.confirmedCount);
      sprintf(str14, "n13.val=%d\xff\xff\xff", World_data.confirmedIncr);
      sprintf(str15, "n14.val=%d\xff\xff\xff", World_data.curedCount);
      sprintf(str16, "n15.val=%d\xff\xff\xff", World_data.curedIncr);
      sprintf(str17, "n16.val=%d\xff\xff\xff", World_data.deadCount);
      sprintf(str18, "n17.val=%d\xff\xff\xff", World_data.deadIncr);
      
      TJC.print(str11);
      TJC.print(str12);
      TJC.print(str13);
      TJC.print(str14);
      TJC.print(str15);
      TJC.print(str16);
      TJC.print(str17);
      TJC.print(str18);
      TJC.print("page 0\xff\xff\xff");
      
      //串口打印
//      Serial.println("");
//      Serial.println("----------------国内疫情---------------");
//      Serial.print("现存确诊: ");Serial.println(China_data.currentConfirmedCount);
//      Serial.print("累计确诊: ");Serial.println(China_data.confirmedCount);
//      Serial.print("累计治愈: ");Serial.println(China_data.curedCount);
//      Serial.print("现存无症: ");Serial.println(China_data.seriousCount);
//      Serial.print("累计死亡: ");Serial.println(China_data.deadCount);
//      Serial.println("----------------国外疫情---------------");
//      Serial.print("现存确诊: ");Serial.println(World_data.currentConfirmedCount);
//      Serial.print("累计确诊: ");Serial.println(World_data.confirmedCount);
//      Serial.print("累计治愈: ");Serial.println(World_data.curedCount);
//      Serial.print("累计死亡: ");Serial.println(World_data.deadCount);
    }
  }
  else
  { //未被响应返回错误码
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end(); // 结束当前连接

  delay(1200000);//两分钟发送一次请求,过于频繁可能导致ip被接口封掉
}

六、效果展示

esp32串口数据可视化 esp32串口屏_android studio_14

esp32串口数据可视化 esp32串口屏_单片机_15