墨水屏显示温度

main.cpp

#include <Arduino.h>
#include "GxEPD2_BW.h"
#include "U8g2_for_Adafruit_GFX.h"
#include <Adafruit_AHTX0.h>
#include <Ticker.h>
#include <LinkedList.h>

int listSize = 144;
int flushTime = 60 * 20; // 刷新间隔时间(秒) 20 分钟刷新一次,否则需要更改横坐标
int samplingTime = 15; // 采样间隔时间(秒),每 15 秒采样一次温度数并记录
                       // 到刷新时间后计算全部采样数据平均值,减少单次采样时温度抖动的影响
LinkedList<float> myList = LinkedList<float>();
LinkedList<float> avgTemperatureList = LinkedList<float>(); // 临时存放温度,用于减少偏差

Adafruit_AHTX0 aht;
sensors_event_t humidity, temp;
Ticker time1;
Ticker time2;

GxEPD2_BW<GxEPD2_290_T5D, GxEPD2_290_T5D::HEIGHT> display(GxEPD2_290_T5D(/*CS*/ SS, /*DC*/ 10, /*RST*/ 3, /*BUSY*/ 2));
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;

void writeFont(int16_t cursorX, int16_t cursorY, String str, const uint8_t font[])
{
  u8g2Fonts.setFont(font);
  int16_t ta = u8g2Fonts.getFontAscent();
  int16_t td = u8g2Fonts.getFontDescent();
  int16_t th = ta - td;

  u8g2Fonts.setCursor(cursorX, cursorY + th);
  u8g2Fonts.print(str);
}

void printStack()
{
  float now;
  float max;
  float min;

  // 计算最大和最小温度,用于动态修改 x 坐标范围
  for (uint16_t i = 0; i < myList.size(); i++)
  {
    now = myList.get(i);
    if (i == 0)
    {
      max = now;
      min = now;
    }
    else
    {
      if (max < now)
      {
        max = now;
      }
      if (now < min)
      {
        min = now;
      }
    }
  }

  // 最大值往上取 5 的倍数 e.g. 17.1 -> 20.0  23.3 -> 25.0
  int temp = max / 5;
  max = (temp + 1) * 5;

  // 最小值往下取 5 的倍数 e.g. 17.1 -> 15.0  23.3 -> 20.0
  temp = min / 5;
  min = temp * 5;

  writeFont(110, 265, String(max), u8g2_font_t0_15_tf);
  writeFont(10, 265, String(min), u8g2_font_t0_15_tf);

  // 画温度
  for (uint16_t i = 0; i < myList.size(); i++)
  {
    now = myList.get(i);
    // Serial.println(now);
    // 计算 x   (max -now) * 100 / (max - min) + 10(距顶端偏移量)
    int x = (100 - (max - now) * 100 / (max - min)) + 10;
    // 计算 y
    int y = (myList.size() - i) * 2;
    display.fillRect(x, y, 2, 2, GxEPD_BLACK);
  }

  // 划分时间
  // 12h
  display.fillRect(10, 72, 100, 1, GxEPD_BLACK);
  writeFont(0, 72 - 16, "12h", u8g2_font_6x10_tf);
  // 24h
  display.fillRect(10, 144, 100, 1, GxEPD_BLACK);
  writeFont(0, 144 - 16, "24h", u8g2_font_6x10_tf);
  // 36h
  display.fillRect(10, 216, 100, 1, GxEPD_BLACK);
  writeFont(0, 216 - 16, "36h", u8g2_font_6x10_tf);

  // 上下横线
  display.fillRect(10, 0, 1, 270, GxEPD_BLACK);
  display.fillRect(110, 0, 1, 270, GxEPD_BLACK);
}

void addTemperature2AvgList()
{
  aht.getEvent(&humidity, &temp);
  avgTemperatureList.add(temp.temperature);
}

/*
 获取统计间隔的平均温度,防止温度抖动
*/
float getAvgTemperature()
{
  if (avgTemperatureList.size() == 0)
  {
    aht.getEvent(&humidity, &temp);
    return temp.temperature;
  }

  LinkedList<float> tempList = LinkedList<float>();
  // 存入临时变量,防止累加完后计算平均温度前增加了数据,导致温度异常
  for (uint16_t i = 0; i < avgTemperatureList.size(); i++)
  {
    tempList.add(avgTemperatureList.get(i));
  }

  float sum = 0.0;
  for (uint16_t i = 0; i < tempList.size(); i++)
  {
    sum += tempList.get(i);
  }

  float avgTemperature = sum / tempList.size();

  tempList.clear();
  avgTemperatureList.clear();
  return avgTemperature;
}

void flushPaper()
{
  aht.getEvent(&humidity, &temp);

  // 控制数组最大的长度
  if (myList.size() >= listSize)
  {
    myList.shift();
  }

  myList.add(getAvgTemperature());

  display.firstPage();
  do
  {
    // 当前的温度和湿度
    writeFont(112, 0, String(temp.temperature), u8g2_font_t0_15_tf);
    writeFont(112, 50, String(humidity.relative_humidity), u8g2_font_t0_15_tf);

    printStack();
  } while (display.nextPage());
  display.hibernate();
}

void setup()
{
  Serial.begin(115200);
  Serial.println("begin...");

  display.init(115200);
  display.setRotation(0);
  // display.setPartialWindow(0, 0, 128, 296); // 局部刷新
  display.setFullWindow(); // 全局刷新
  u8g2Fonts.begin(display);
  u8g2Fonts.setFontMode(0);
  u8g2Fonts.setFontDirection(1);
  u8g2Fonts.setForegroundColor(GxEPD_BLACK);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);

  if (!aht.begin())
  {
    Serial.println("Could not find AHT? Check wiring");

    display.firstPage();
    do
    {
      writeFont(50, 50, "Could not find AHT", u8g2_font_t0_15_tf);
    } while (display.nextPage());
    display.hibernate();
    return;
  }
  Serial.println("AHT10 or AHT20 found");

  time1.attach(flushTime, flushPaper);
  delay(1000);
  time2.attach(samplingTime, addTemperature2AvgList);
}

void loop()
{
}

platform.io

[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
board_build.flash_mode = dio
lib_ldf_mode = deep+
monitor_speed = 115200
lib_deps = 
	zinggjm/GxEPD2@^1.5.0
	olikraus/U8g2_for_Adafruit_GFX@^1.8.0
	olikraus/U8g2@^2.34.15
	adafruit/Adafruit AHTX0@^2.0.3
	ivanseidel/LinkedList@0.0.0-alpha+sha.dac3874d28
posted @ 2023-06-02 19:05  LiuChengloong  阅读(474)  评论(0编辑  收藏  举报