esp32笔记[12]-使用串口屏显示时间和温湿度
摘要
使用esp32驱动陶晶驰串口屏显示NTP时间和温湿度信息.
关键信息
- 开发环境:Arduino IDE
原理简介
NTP时间源简介
[https://www.bdsytime.com/baike/6165.html]
NTP(Network Time Protocol)时间服务器是一种网络设备,用于提供准确的时间同步服务。它的作用是在计算机网络中确保各个设备的时间保持同步,从而保证网络中的数据传输、日志记录等操作能够准确地进行。
NTP时间服务器可以连接到可靠的时间源,如GPS卫星、原子钟等,通过接收这些时间源的信号,并将其传输给其他设备,为整个网络提供准确的时间源服务。这对于没有直接访问可靠时间源的设备来说尤为重要,因为它们可以通过连接到NTP时间服务器,从而获得准确的时间信息。
组态串口屏
[https://www.elecfans.com/emb/danpianji/202302212013881.html]
很早以前,工业现场有时需要HMI,为工作人员提供便捷的操作环境,但不同的应用现场有不同的操作界面,有组态软件经验的厂商就想到了用嵌入式板卡跑WinCE的方案,这样很容易将Windows中的代码移植过来,用户只需要在Windows端的组态工具根据现场应用进行组态,然后将生产的工程文件,对象文件,数据库等文件下载到WinCE对应的板卡中即可实现所见即所得的显示开发过程。
串口屏对比LVGL开发
[https://whycan.com/t_9350.html]
[https://www.elecfans.com/emb/danpianji/202302212013881.html]
串口屏是一种带有串口的显示设备,它可以通过PC端设计屏幕显示界面,并通过串口修改屏幕显示内容。串口屏的核心功能是显示,显示的数据源来自串口的对端设备。串口屏的价格通常较低,但其串口通常是协议的从设备,一般仅支持一种协议,用户需要通过外部MCU作为串口的主,并实现相关协议去修改显示画面的数据内容。
LVGL是一个开源的、轻量级的图形库,它可以用来创建各种类型的图形界面,包括但不限于仪表盘、状态栏、菜单、列表等。LVGL提供了丰富的图形元素和布局选项,使得开发者可以轻松地设计和实现复杂的用户界面。LVGL可以与各种微控制器(MCU)和操作系统(OS)集成,使其成为嵌入式系统开发的一个非常有用的工具。
在某些情况下,例如需要自定义的用户界面或者需要支持多种协议的场景,LVGL可能更适合。然而,如果预算有限,或者只需要基本的显示功能,那么串口屏可能是更好的选择。
实现
核心代码
/*
硬件:
- esp32-c3
- dht11
- 陶晶驰串口屏
连接:
- dht11_dat:io13
- usb_d-:io18
- usb_d+:io19
- rs485_rx:uart0_tx
- rs485_tx:uart0_rx
- led_d4:io12(high)
- led_d5:io13
- tjc_rx:io0
- tjc_tx:io1
依赖库:
- DHT sensor library
*/
/* start 引入 */
#include <stdio.h>
#include "DHT.h"
#include <DHT_U.h>
#include <WiFi.h>
#include "time.h" // 时间相关
#include "sntp.h" // 时间相关
/* end 引入 */
/* start 全局变量 */
const int led_d4_pin = 12;
const int tjc_rx_pin = 0;
const int tjc_tx_pin = 1;
const int dht11_dat_pin = 13;
// DHT11
#define DHTTYPE DHT11
uint32_t g_delay_ms;
sensor_t g_sensor;
sensors_event_t g_event;
// WIFI
const char* g_wifi_ssid = "wifi";
const char* g_wifi_password = "wifi";
// 时间NTP相关
const char* g_ntp_server1 = "ntp.aliyun.com";
const char* g_ntp_server2 = "stdtime.gov.hk";
const char* g_time_zone = "CST-8"; // TimeZone rule for China Standard Time (UTC+8)
/* end 全局变量 */
/* start 函数原型 */
void timeAvailable(struct timeval *t);
void printLocalTime(void);
void printDHT11(void);
/* end 函数原型 */
/* start 自定义类 */
class tjcScreen {
private:
Stream& serial;
public:
tjcScreen(Stream& s) : serial(s) {
// serial.begin(115200);
}
// 封装结束符并写入串口屏
void write(const char* command) {
serial.print(command);
serial.write(0xFF);
serial.write(0xFF);
serial.write(0xFF);
}
// t12
void set_version(const char* version) {
char command[30];
snprintf(command, sizeof(command), "t12.txt=\"%s\"", version);
write(command);
}
// t17
void set_humidity(const char* humidity) {
char command[30];
snprintf(command, sizeof(command), "t17.txt=\"%s\"", humidity);
write(command);
}
// t15
void set_temperature(const char* temperature) {
char command[30];
snprintf(command, sizeof(command), "t15.txt=\"%s\"", temperature);
write(command);
}
// t13
void set_power_input(const char* power) {
char command[30];
snprintf(command, sizeof(command), "t13.txt=\"%s\"", power);
write(command);
}
// t14
void set_power_output(const char* power) {
char command[30];
snprintf(command, sizeof(command), "t14.txt=\"%s\"", power);
write(command);
}
// t19
void set_power_total(const char* power) {
char command[30];
snprintf(command, sizeof(command), "t19.txt=\"%s\"", power);
write(command);
}
// t5
void set_time(const char* time) {
char command[40];
// 2024-1-31 19:20:21
snprintf(command, sizeof(command), "t5.txt=\"%s\"", time);
write(command);
}
// t8
void set_connection_status(const char* status) {
char command[32];
snprintf(command, sizeof(command), "t8.txt=\"%s\"", status);
write(command);
}
};
/* end 自定义类 */
/* start 头部声明 */
DHT_Unified g_dht(dht11_dat_pin, DHTTYPE);
tjcScreen g_screen(Serial1);
/* end 头部声明 */
/* start 主函数 */
void setup(){
Serial.begin(115200);
Serial.println(F("DHT11 test!"));
pinMode(dht11_dat_pin,INPUT);
digitalWrite(dht11_dat_pin,LOW);
pinMode(led_d4_pin,OUTPUT);
// 初始化DHT11
g_dht.begin();
g_dht.temperature().getSensor(&g_sensor);
g_dht.humidity().getSensor(&g_sensor);
g_delay_ms = g_sensor.min_delay / 1000;
g_dht.temperature().getEvent(&g_event);
g_dht.humidity().getEvent(&g_event);
// 初始化串口屏
// begin(unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112) -> void
Serial1.begin(115200,SERIAL_8N1,tjc_tx_pin,tjc_rx_pin);
// 初始化USB
// 初始化WIFI
WiFi.begin(g_wifi_ssid, g_wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("wifi connecting...\n");
}
Serial.println("wifi connected.");
// 初始化NTP服务器
sntp_set_time_sync_notification_cb(timeAvailable); // 配置时间获取回调
configTzTime(g_time_zone, g_ntp_server1, g_ntp_server2);
}
void loop(){
delay(1000);
// 翻转led_d4电平
auto flipLevel = [](int pin) {
int currentLevel = digitalRead(pin); // 读取当前引脚的状态
int newLevel = !currentLevel; // 计算相反的电平
digitalWrite(pin, newLevel); // 设置引脚为新的电平
};
flipLevel(led_d4_pin); // 调用lambda函数翻转电平
// 获取DHT11数据
printDHT11();
// NTP打印本地时间
printLocalTime(); // 同步需要一些时间
}
/* end 主函数 */
/* start 函数本体 */
// 打印本地时间
void printLocalTime(void){
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("No time available (yet)");
return;
}
Serial.println(&timeinfo, "%Y-%m-%d %H:%M:%S");
// 更新显示屏
char s_time[40];
// 2024-1-31 19:20:21
strftime(s_time, sizeof(s_time), "%Y-%m-%d %H:%M:%S", &timeinfo);
g_screen.set_time(s_time);
}
// 时间获取回调
void timeAvailable(struct timeval *t){
Serial.println("Got time adjustment from NTP!");
printLocalTime();
}
// 打印DHT11数据
void printDHT11(void){
String s_message;
g_dht.temperature().getEvent(&g_event);
s_message += String(g_event.temperature);
s_message += "°C;";
// 更新显示屏
g_screen.set_temperature(String(g_event.temperature).c_str());
g_dht.humidity().getEvent(&g_event);
s_message += String(g_event.relative_humidity);
s_message += "%;";
Serial.println(s_message);
// 更新显示屏
g_screen.set_humidity(String(g_event.relative_humidity).c_str());
}
/* end 函数本体 */
效果
显示温湿度和时间 |
---|
![]() |