ESP_UV_BOX
前言
以前买了个紫外线模块,一直放着吃灰😶,偶然看到夏日征集令,想着可以试试(又要白嫖立创🥰),然后就有了这个项目。
复刻别的项目剩了块ESP32-WROOM-32D,所以就选择了它作为主控;紫外线部分直接用加热台把模块拆了,所以没有单独买元件;做灯板剩了些WS2812灯珠,所以加上一颗,以下为制作过程记录
ESP_UV_BOX
前言
🔗夏日征集令
ESP32-WROOM-32D-N8主控,通过GUVA-S12SD紫外线传感器获取环境紫外线强度;AHT20温湿度传感器获取环境温湿度;BMP280气压传感器获取环境压强;使用拨轮开关切换页面。
以下为制作过程记录
功能
- 紫外线指数
- 环境温湿度
- 气压海拔
- 简易照明
- 天气时钟(网络) +
- .
成本
这里只列出了主要的器件,详情见BOM
+成本
这里只列出了主要的器件,详情见🔗腾讯文档:BOM_ESP_UV_BOX
UI初始化
删去之前LVGL官方案例的内容,添加如下代码
ui_init(); |
lvgl显示
+void lvgl_task(void *pt) |
setup()
中创建任务
xTaskCreatePinnedToCore(lvgl_task, "lvgl display", 1024 * 15, NULL, 2, NULL, 1); |
编译下载
END
前言
以前买了个紫外线模块,一直放着吃灰😶,偶然看到夏日征集令,想着可以试试(又要白嫖立创🥰),然后就有了这个项目。
复刻别的项目剩了块ESP32-WROOM-32D,所以就选择了它作为主控;紫外线部分直接用加热台把模块拆了,所以没有单独买元件;做灯板剩了些WS2812灯珠,所以加上一颗,以下为制作过程记录
功能
-
-
- 紫外线指数 -
- 环境温湿度 -
- 气压海拔 -
- 简易照明 -
- 天气时钟(网络) -
成本
这里只列出了主要的器件,详情见BOM
-主要元件 | -价格 | -
---|---|
ESP32-WROOM-32D(8MB) | -15 | -
紫外线模块 | -7.05 | -
AHT20 | -1.62 | -
BMP280 | -1.04 | -
四脚拨轮开关 | -0.85 | -
CH340K | -1.4 | -
硬件
--硬件设计见立创开源硬件平台
-
原理图
--存在问题:下载完程序,可以运行,但是板子上电不运行,需要按复位,>去除BOOT0按键的电容<,解决问题
-
贴片开关的质量也不太行,开关手柄会断🙃
侧边按键质量似乎也不太好,按复位有时也没用🙃
主控电路
主控
主控选择ESP32-WROOM-32D-N8,外围电路参考官方技术规格书。
引出SPI用于控制屏幕,IIC用于控制AHT20和BMP280,ADC用于采集电压值,以及按键控制
自动下载
串口芯片使用CH340K
电源电路
电源切换电路
使用PMOS,当没有外部电源时使用电池供电,有外部电源输入时不使用电池供电
充电电路
电池管理使用TP4056,电路参考TP4056数据手册
充电电流如下,根据锂电池参数选择合适的电阻
Rprog(K) | -Ibat(mA) | -
---|---|
1.2 | -1000 | -
2.4 | -500 | -
3.0 | -400 | -
4.0 | -300 | -
6.0 | -200 | -
12.0 | -200 | -
外设
按键
板载一个RESET和BOOT侧边按键,使用拨轮开关作为控制输入
TFT
使用1.8寸TFT屏幕插接,分辨率128x160,屏幕驱动ST7735,屏幕驱动电路参考屏幕原理图,可以通过BLK引脚控制屏幕亮度
UV
紫外线部分电路参考紫外线模块电路设计
-
通过采集电压,根据电压范围,得到紫外线强度
AHT20 BMP280
这两个器件,用烙铁不好焊,加热台方便些
AHT20可以检测环境温湿度
BMP280可以检测大气压,温度,以及海拔高度(由压力和温度计算得到)
面板
使用立创EDA设计简单的面板
-3D外壳
1.8寸版本
本次使用SOLIDWORKS2023建模
立创EDA导出模型
- -SOLIDWORKS
使用SOLIDWORKS打开导出的step
格式文件
打开后如下图所示,可以看到电路板模型缺少丝印图案
回到PCB工程,打开PCB的2D视图
导出上下面丝印图
如下图点击PCB上表面,选择外观
选择导出的顶层丝印图
还需要调整丝印的位置和大小,选择映射
根据实际情况,调整以下参数
之后便可以开始外壳的建模,最终效果如下
程序
- --
页面结构
在主界面下设四个功能页,之后各级再设功能分页,主要结构如下
-- -设计参考:
-
B站:黑人黑科技的视频DIY万能遥控器
OSHWHub: 黑人黑科技的开源工程ESP32 万能遥控器
代码
-开发工具:Visual Studio Code + PlatformIO
+
图标:iconfont-阿里巴巴
颜色:RGB COLOR PICKER
中文转换:中文转UNICODE
图片转换:FileToCArrayESP32S3N8R8 + lvgl测试官方案例 +/posts/2c4e27ec/ +说明 ++-硬件:立创ESP32S3R8N8开发板 + 2.8寸TFT显示屏(ST7789) + 电容触摸(GT911)
软件:Visual Studio Code + PlatformIO
代码:百度网盘:ESP32S3_GT911TOUCH(提取码:levi)
视频:bilibili: 【ESP32】2.8寸电容触摸屏(ST7789+GT911) lvgl 案例测试
博客:CSDN: 【ESP32】立创ESP32S3R8N8开发板+2.8寸TFT电容触摸屏ST7789+GT911+PlatformIO代码结构主要如下
-+
ESP32_UV_BOX
│ clearBuildDir.bat build文件删除
│ default_8MB.csv 存储分区
│ LICENSE 开源协议
│ platformio.ini 开发配置
│ README.md 说明文档
├─assets/ 静态文件
├─include
│ README
├─lib 外部库
│ │ README
│ └─ArduinoZlib
├─src 主要文件
│ │ button.cpp 按键控制
│ │ button.h
│ │ main.cpp 主程序
│ │ network.cpp 网络请求
│ │ network.h
│ │ sensor.cpp 传感器
│ │ sensor.h
│ │ ui.cpp 界面
│ │ ui.h
│ ├─font/ 字体文件
│ └─img/ 图片文件
└─test/ 测试文件新建工程
+
+- +
点击侧边
+PlatformIO
插件,新建工程- +
依次设置工程名,开发板,框架
+屏幕测试
添加TFT_eSPI
+
+- +
添加屏幕驱动库
+TFT_eSPI
,按如下图顺序- +
添加TFT_eSPI到工程
+- +
打开配置文件,可以看到已成功添加库
+修改TFT_eSPI
+
+- +
打开
+.pio\libdeps\esp32-s3-devkitc-1\TFT_eSPI\User_Setup.h
文件- +
根据屏幕驱动芯片解注释
+-
// Only define one driver, the other ones must be commented out
// #define ILI9341_DRIVER // Generic driver for common displays
//#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
//#define ST7735_DRIVER // Define additional parameters below for this display
//#define ILI9163_DRIVER // Define additional parameters below for this display
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
//#define R61581_DRIVER
//#define RM68140_DRIVER
//#define ST7796_DRIVER
//#define SSD1351_DRIVER
//#define SSD1963_480_DRIVER
//#define SSD1963_800_DRIVER
//#define SSD1963_800ALT_DRIVER
//#define ILI9225_DRIVER
//#define GC9A01_DRIVER界面
屏幕尺寸为1.8寸,分辨率是128x160,屏幕驱动是ST7735,使用TFT_eSPI库驱动屏幕,所有界面使用
-TFT_eSPI
绘制使用
-TFT_eSPI
需要修改配置文件User_Setup.h
,根据屏幕类型和显示情况修改内容+
// #define TFT_INVERSION_ON // 黑白反转
// #define TFT_INVERSION_OFF
//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST+
+- 根据屏幕大小设置宽高
+-
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
// #define TFT_WIDTH 80
// #define TFT_WIDTH 128
// #define TFT_WIDTH 172 // ST7789 172 x 320
// #define TFT_WIDTH 170 // ST7789 170 x 320
// #define TFT_HEIGHT 160
// #define TFT_HEIGHT 128
// #define TFT_HEIGHT 240 // ST7789 240 x 240
// #define TFT_HEIGHT 240 // GC9A01 240 x 240使用
-ledc
控制引脚输出PWM调节屏幕背光亮度控制
使用
-mathertel/OneButton
库来实现按键的控制,分别注册短按,双击和长按函数来实现不同的操作上下短按为页面切换,中间短按为进入页面,中间长按为返回上一级
-传感器
UV
使用S12SD传感器来检测紫外线,然后经过放大,使用ADC采集电压,根据电压范围判断紫外线指数等级
-下图为紫外线模块
-
程序中使用此函数获取紫外线指数+
uint8_t sensor_uv_data(void)+
+- 根据连线设置引脚
+-
// ### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###
// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins
//#define TFT_MISO 19
//#define TFT_RST 4 // Reset pin (could connect to RST pin)--图中为Arduino对应的数值,详情见DFROBOT: UV Sensor
-AHT20
使用
-dvarrel/AHT20
库读取AHT20温湿度传感器的数据
主要为如下内容,AHT20数据结构体,初始化函数,以及数据读取函数(返回数据结构体)+
struct AHT20Data
{
float temperature;
float humidity;
};
void sensor_aht20_init(void);
AHT20Data sensor_aht20_data(void);修改main.cpp
在屏幕上从上到下分别显示红绿蓝三色,以及白色文字,用来测试屏幕颜色显示是否正常。
+-
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
void setup() {
tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_GREY);
tft.setTextColor(TFT_WHITE, TFT_GREY); // Adding a background colour erases previous text automatically
tft.fillRect(0,0,240,50,TFT_RED);
tft.fillRect(0,50,240,50,TFT_GREEN);
tft.fillRect(0,100,240,50,TFT_BLUE);
tft.drawCentreString("Time flies",120,260,4);
}
void loop() {
// put your main code here, to run repeatedly:
}BMP280
使用
-seeed-studio/Grove - Barometer Sensor BMP280
库读取BMP280传感器的数据
主要为如下内容,BMP280数据结构体,初始化函数,以及数据读取函数(返回数据结构体)+
struct BMP280Data
{
float temperature;
float pressure;
float altitude;
};
void sensor_bmp280_init(void);
BMP280Data sensor_bmp280_data(void);下载调试
+
+- +
编译下载
+- +
根据屏幕显示情况修改
+User_Setup.h
文件如果颜色反转(白色显示为黑色),如下图所示,则取消下一个注释,尝试两个选项,其中一个选项应该纠正反转。
++
// If colours are inverted (white shows as black) then uncomment one of the next
// 2 lines try both options, one of the options should correct the inversion.
// #define TFT_INVERSION_ON修改后,如下图所示,白色正常显示,但是RGB顺序存在问题
+仅对于ST7735, ST7789和ILI9341,如果显示器上的蓝色和红色交换,则定义颜色顺序,一次尝试一个选项来找到显示的正确颜色顺序
++
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
// Try ONE option at a time to find the correct colour order for your display
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
修改后,如下图所示,RGB顺序正常
+LVGL测试
添加LVGL
+
+- +
根据实际情况,选择lvgl版本
+
![](lvglinstall.png” style=”zoom:67%;” >- +
添加lvgl到工程
+
![](lvglinstalled.png” style=”zoom:67%;” >修改LVGL
+
+- +
打开
+.pio\libdeps\esp32-s3-devkitc-1\lvgl\lv_conf_template.h
文件将此文件重命名为
+lv_conf.h
![](lvconf.png” style=”zoom:67%;” >
++
+- 使能lvgl
+-
/* clang-format off */在函数
-bool BMP280::init(void)
中注释掉Wire.begin()
在主程序中上面两个传感器初始化前,要先使用Wire.begin(21, 22);
来设置IIC
引脚网络
配网
初次使用时,会建立如下网络
-ESP_UV_BOX_WIFI
,
连接网络,浏览器打开网址192.168.1.1
,会出现如下配网页面--页面代码参考: CSDN: 请收藏!分享一个ESP32/ESP8266高颜值WIFI配网页面代码-带下拉选择框和中英文版本。文末有arduino配网代码。
-一共四个输入框,分别是
-WIFI SSID
,WIFI PASSWORD
,Private KEY
,Location ID
- ---
点击保存后,芯片会重启连接网络网络配置相关函数如下
-+
bool wifi_scan(void);
void wifi_connect(int timeOut_s);
void wifi_disconnect(void);
void ap_init(void);
void server_init(void);
void handleRoot(void);
void handleConfigWifi(void);
void handleNotFound(void);
void doClient(void);
void wifiConfigBySoftAP(void);+
+- 设置周期
+默认显示刷新周期。LVG将重新绘制改变的区域与这个周期时间
+
输入设备读取周期毫秒-
/*Default display refresh period. LVG will redraw changed areas with this period time*/
/*Input device read period in milliseconds*/天气时钟
天气等数据使用和风天气API,免费订阅每天可以有1000次请求
-- --
+- 实时天气数据使用和风天气的API,具体代码参考B站:大聪明的二手脑袋的视频Dudu天气时钟版本更新,全面对接和风天气,2.0版本继续开源
-- 时间数据使用
+arduino-libraries/NTPClient
库获取网络时间
网络天气相关函数如下- 心跳使能
++ +
/*Use a custom tick source that tells the elapsed time in milliseconds.
*It removes the need to manually update the tick with `lv_tick_inc()`)*/+
+- 使能测试案例
++ +
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */+
+- +
更改文件路径
+将
+.pio\libdeps\esp32-s3-devkitc-1\lvgl\demos
文件夹移动至.pio\libdeps\esp32-s3-devkitc-1\lvgl\src\demos
- +
修改main.cpp
+将
+.pio\libdeps\esp32-s3-devkitc-1\lvgl\examples\arduino\LVGL_Arduino\LVGL_Arduino.ino
文件内容复制+
+- 设置头文件
++ +
+
+- 设置宽高
++ +
static const uint16_t screenWidth = 320;
static const uint16_t screenHeight = 240;+
+- 修改类型
++
lv_disp_t
修改为lv_disp_drv_t
+
lv_indev_t
修改为lv_indev_drv_t
+
+- 注释掉触摸部分
+修改完成
最终
+main.cpp
文件内容如下+
/*Change to your screen resolution*/
static const uint16_t screenWidth = 320;
static const uint16_t screenHeight = 240;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * 10 ];
TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */
/* Display flushing */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
}
/*Read the touchpad*/
// void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
// {
// uint16_t touchX, touchY;
// bool touched = tft.getTouch( &touchX, &touchY, 600 );
// if( !touched )
// {
// data->state = LV_INDEV_STATE_REL;
// }
// else
// {
// data->state = LV_INDEV_STATE_PR;
// /*Set the coordinates*/
// data->point.x = touchX;
// data->point.y = touchY;
// Serial.print( "Data x " );
// Serial.println( touchX );
// Serial.print( "Data y " );
// Serial.println( touchY );
// }
// }
void setup()
{
Serial.begin( 115200 ); /* prepare for possible serial debug */
String LVGL_Arduino = "Hello Arduino! ";
LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println( LVGL_Arduino );
Serial.println( "I am LVGL_Arduino" );
lv_init();
tft.begin(); /* TFT init */
tft.setRotation( 3 ); /* Landscape orientation, flipped */
/*Set the touchscreen calibration data,
the actual data for your display can be acquired using
the Generic -> Touch_calibrate example from the TFT_eSPI library*/
uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
// tft.setTouch( calData );
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 );
/*Initialize the display*/
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
/*Change the following line to your display resolution*/
disp_drv.hor_res = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
/*Initialize the (dummy) input device driver*/
static lv_indev_drv_t indev_drv;
lv_indev_drv_init( &indev_drv );
indev_drv.type = LV_INDEV_TYPE_POINTER;
// indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &indev_drv );
/* Create simple label */
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, LVGL_Arduino.c_str() );
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
lv_demo_widgets(); // OK
Serial.println( "Setup done" );
}
void loop()
{
lv_timer_handler(); /* let the GUI do its work */
delay( 5 );
}编译下载
显示效果如下图
+触摸测试
添加
+bb_captouch
修改
main.cpp
+
-- +
添加头文件
++
- +
设置触摸芯片引脚
++
// These defines are for a low cost ESP32 LCD board with the GT911 touch controller- +
设置参数
++
BBCapTouch bbct;
const char *szNames[] = {"Unknown", "FT6x36", "GT911", "CST820"};- +
初始化
++
bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);修改
+my_touchpad_read
函数这里的x,y坐标需要根据实际情况修改
+ +
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{
TOUCHINFO ti;
if(bbct.getSamples(&ti))
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = screenWidth - ti.y[0];
data->point.y = ti.x[0];
Serial.print( "Data x " );
Serial.println( screenWidth - ti.y[0] );
Serial.print( "Data y " );
Serial.println( ti.x[0] );
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}- -
void get_weather_now(void);
void get_weather_future(void);
void get_air(void);
void get_city_id(void);
String urlEncode(const String& text);网络相关函数如下
-- -
void time_init(void);
void get_time(void);天气预报
同上,使用和风天气API,屏幕显示未来六天天气状况
-空气质量
同上,使用和风天气API,屏幕显示颗粒物PM10,颗粒物PM2.5,二氧化氮NO2,二氧化硫SO2,一氧化碳CO,臭氧O3
-哔哩哔哩
通过如下API接口获得JSON格式的数据,使用ArduinoJson库解析获得关注数和粉丝数
-- -
https://api.bilibili.com/x/relation/stat?vmid=用户UID可以使用官网提供的工具生成解析代码
-- -
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"mid": 378576508,
"following": 318,
"whisper": 0,
"black": 0,
"follower": 56
}
}生成的解析代码如下
-+
// String input;
JsonDocument doc;
DeserializationError error = deserializeJson(doc, input);
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
int code = doc["code"]; // 0
const char* message = doc["message"]; // "0"
int ttl = doc["ttl"]; // 1
JsonObject data = doc["data"];
long data_mid = data["mid"]; // 378576508
int data_following = data["following"]; // 318
int data_whisper = data["whisper"]; // 0
int data_black = data["black"]; // 0
int data_follower = data["follower"]; // 56修改完成
最终
+main.cpp
文件内容如下-
// These defines are for a low cost ESP32 LCD board with the GT911 touch controller
BBCapTouch bbct;
const char *szNames[] = {"Unknown", "FT6x36", "GT911", "CST820"};
/*Change to your screen resolution*/
static const uint16_t screenWidth = 320;
static const uint16_t screenHeight = 240;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * 10 ];
TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */
/* Display flushing */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
}
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{
// uint16_t touchX, touchY;
TOUCHINFO ti;
if(bbct.getSamples(&ti))
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = screenWidth - ti.y[0];
data->point.y = ti.x[0];
Serial.print( "Data x " );
Serial.println( screenWidth - ti.y[0] );
Serial.print( "Data y " );
Serial.println( ti.x[0] );
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
void setup()
{
Serial.begin( 115200 ); /* prepare for possible serial debug */
String LVGL_Arduino = "Hello Arduino! ";
LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println( LVGL_Arduino );
Serial.println( "I am LVGL_Arduino" );
lv_init();
tft.begin(); /* TFT init */
tft.setRotation( 3 ); /* Landscape orientation, flipped */
bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);
int iType = bbct.sensorType();
Serial.printf("Sensor type = %s\n", szNames[iType]);
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 );
/*Initialize the display*/
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
/*Change the following line to your display resolution*/
disp_drv.hor_res = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
/*Initialize the (dummy) input device driver*/
static lv_indev_drv_t indev_drv;
lv_indev_drv_init( &indev_drv );
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &indev_drv );
/* Create simple label */
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, LVGL_Arduino.c_str() );
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
// uncomment one of these demos
lv_demo_widgets(); // OK
Serial.println( "Setup done" );
}
void loop()
{
lv_timer_handler(); /* let the GUI do its work */
delay( 5 );
}灯光
使用
-fastled/FastLED
库驱动板载的一颗WS2812灯珠,暂时只添加不同颜色灯切换功能实物
PCB
-页面
下图为部分页面
-
后续会上传B站视频END
最后非常感谢立创🥰提供的机会和各种优惠券,帮助我们实现想法,做出实物,参加征集令活动收获颇多,未来继续努力😄
- -]]>编译下载
触摸显示效果如下图所示
+END
2024 Levi5 +]]>
Quick Start
Create a new post
$ hexo new "My New Post" |
More info: Writing
+Run server
$ hexo server |
More info: Server
+Generate static files
$ hexo generate |
More info: Generating
+Deploy to remote sites
$ hexo deploy |
More info: Deployment
+]]>前言
🔗夏日征集令
ESP32-WROOM-32D-N8主控,通过GUVA-S12SD紫外线传感器获取环境紫外线强度;AHT20温湿度传感器获取环境温湿度;BMP280气压传感器获取环境压强;使用拨轮开关切换页面。
以下为制作过程记录
功能
-
+
- 紫外线指数 +
- 环境温湿度 +
- 气压海拔 +
- 简易照明 +
- 天气时钟(网络) +
- . +
成本
这里只列出了主要的器件,详情见🔗腾讯文档:BOM_ESP_UV_BOX
+主要元件 | +价格 | +
---|---|
ESP32-WROOM-32D(8MB) | +15 | +
紫外线模块 | +7.05 | +
AHT20 | +1.62 | +
BMP280 | +1.04 | +
四脚拨轮开关 | +0.85 | +
CH340K | +1.4 | +
硬件
++硬件设计见立创开源硬件平台
+
原理图
++存在问题:下载完程序,可以运行,但是板子上电不运行,需要按复位,>去除BOOT0按键的电容<,解决问题
+
贴片开关的质量也不太行,开关手柄会断🙃
侧边按键质量似乎也不太好,按复位有时也没用🙃
主控电路
主控
主控选择ESP32-WROOM-32D-N8,外围电路参考官方技术规格书。
引出SPI用于控制屏幕,IIC用于控制AHT20和BMP280,ADC用于采集电压值,以及按键控制
自动下载
串口芯片使用CH340K
电源电路
电源切换电路
使用PMOS,当没有外部电源时使用电池供电,有外部电源输入时不使用电池供电
充电电路
电池管理使用TP4056,电路参考TP4056数据手册
充电电流如下,根据锂电池参数选择合适的电阻
Rprog(K) | +Ibat(mA) | +
---|---|
1.2 | +1000 | +
2.4 | +500 | +
3.0 | +400 | +
4.0 | +300 | +
6.0 | +200 | +
12.0 | +200 | +
外设
按键
板载一个RESET和BOOT侧边按键,使用拨轮开关作为控制输入
TFT
使用1.8寸TFT屏幕插接,分辨率128x160,屏幕驱动ST7735,屏幕驱动电路参考屏幕原理图,可以通过BLK引脚控制屏幕亮度
UV
紫外线部分电路参考紫外线模块电路设计
+
通过采集电压,根据电压范围,得到紫外线强度
AHT20 BMP280
这两个器件,用烙铁不好焊,加热台方便些
AHT20可以检测环境温湿度
BMP280可以检测大气压,温度,以及海拔高度(由压力和温度计算得到)
面板
使用立创EDA设计简单的面板
+3D外壳
1.8寸版本
本次使用SOLIDWORKS2023建模
立创EDA导出模型
+ +SOLIDWORKS
使用SOLIDWORKS打开导出的step
格式文件
打开后如下图所示,可以看到电路板模型缺少丝印图案
回到PCB工程,打开PCB的2D视图
导出上下面丝印图
如下图点击PCB上表面,选择外观
选择导出的顶层丝印图
还需要调整丝印的位置和大小,选择映射
根据实际情况,调整以下参数
之后便可以开始外壳的建模,最终效果如下
程序
+ ++
页面结构
在主界面下设四个功能页,之后各级再设功能分页,主要结构如下
++ +设计参考:
+
B站:黑人黑科技的视频DIY万能遥控器
OSHWHub: 黑人黑科技的开源工程ESP32 万能遥控器
代码
++开发工具:Visual Studio Code + PlatformIO
+
图标:iconfont-阿里巴巴
颜色:RGB COLOR PICKER
中文转换:中文转UNICODE
图片转换:FileToCArray
代码结构主要如下
+ESP32_UV_BOX |
界面
屏幕尺寸为1.8寸,分辨率是128x160,屏幕驱动是ST7735,使用TFT_eSPI库驱动屏幕,所有界面使用TFT_eSPI
绘制
使用TFT_eSPI
需要修改配置文件User_Setup.h
,根据屏幕类型和显示情况修改内容
|
使用ledc
控制引脚输出PWM调节屏幕背光亮度
控制
使用mathertel/OneButton
库来实现按键的控制,分别注册短按,双击和长按函数来实现不同的操作
上下短按为页面切换,中间短按为进入页面,中间长按为返回上一级
+传感器
UV
使用S12SD传感器来检测紫外线,然后经过放大,使用ADC采集电压,根据电压范围判断紫外线指数等级
+下图为紫外线模块
程序中使用此函数获取紫外线指数
uint8_t sensor_uv_data(void) |
++图中为Arduino对应的数值,详情见DFROBOT: UV Sensor
+
AHT20
使用dvarrel/AHT20
库读取AHT20温湿度传感器的数据
主要为如下内容,AHT20数据结构体,初始化函数,以及数据读取函数(返回数据结构体)
struct AHT20Data |
BMP280
使用seeed-studio/Grove - Barometer Sensor BMP280
库读取BMP280传感器的数据
主要为如下内容,BMP280数据结构体,初始化函数,以及数据读取函数(返回数据结构体)
struct BMP280Data |
在函数bool BMP280::init(void)
中注释掉Wire.begin()
在主程序中上面两个传感器初始化前,要先使用Wire.begin(21, 22);
来设置IIC
引脚
网络
配网
初次使用时,会建立如下网络ESP_UV_BOX_WIFI
,
连接网络,浏览器打开网址192.168.1.1
,会出现如下配网页面
++页面代码参考: CSDN: 请收藏!分享一个ESP32/ESP8266高颜值WIFI配网页面代码-带下拉选择框和中英文版本。文末有arduino配网代码。
+
一共四个输入框,分别是WIFI SSID
, WIFI PASSWORD
, Private KEY
, Location ID
+ ++
点击保存后,芯片会重启连接网络
网络配置相关函数如下
+bool wifi_scan(void); |
天气时钟
天气等数据使用和风天气API,免费订阅每天可以有1000次请求
++ ++
-
+
- 实时天气数据使用和风天气的API,具体代码参考B站:大聪明的二手脑袋的视频Dudu天气时钟版本更新,全面对接和风天气,2.0版本继续开源 +
- 时间数据使用
arduino-libraries/NTPClient
库获取网络时间
网络天气相关函数如下
+
void get_weather_now(void); |
网络相关函数如下
+void time_init(void); |
天气预报
同上,使用和风天气API,屏幕显示未来六天天气状况
+空气质量
同上,使用和风天气API,屏幕显示颗粒物PM10,颗粒物PM2.5,二氧化氮NO2,二氧化硫SO2,一氧化碳CO,臭氧O3
+哔哩哔哩
通过如下API接口获得JSON格式的数据,使用ArduinoJson库解析获得关注数和粉丝数
+https://api.bilibili.com/x/relation/stat?vmid=用户UID |
可以使用官网提供的工具生成解析代码
+{ |
生成的解析代码如下
+// String input; |
灯光
使用fastled/FastLED
库驱动板载的一颗WS2812灯珠,暂时只添加不同颜色灯切换功能
实物
PCB
+页面
下图为部分页面
后续会上传B站视频
END
最后非常感谢立创🥰提供的机会和各种优惠券,帮助我们实现想法,做出实物,参加征集令活动收获颇多,未来继续努力😄
+ +]]>--硬件:立创ESP32S3R8N8开发板 + 2.8寸TFT显示屏(ST7789) + 电容触摸(GT911)
-
软件:Visual Studio Code + PlatformIO+ Squareline Studio
代码:百度网盘:ESP32S3_SQ(提取码:levi)
代码:百度网盘:ESP32S3_SERVO(提取码:levi)
视频:bilibili: 【ESP32】初试Squareline Studio设计 简单控制屏幕亮度
视频:bilibili: 【ESP32】Squareline Studio新增界面+移植过程 - 简单控制舵机
博客:CSDN: 【ESP32】立创ESP32S3N8R8开发板+2.8寸TFT电容触摸屏+Squareline Studio+PlatformIO
Squareline Studio
设计UI
-导出文件
-
-
工程设置
-
按如下所示设置工程,Project Export Root
和UI Files Export Path
路径可以选择为LVGL工程目录下新建的export
文件夹
-Export
-
-
PlatformIO
文件结构
-
-
导出文件
-
以下为Squareline Studio导出的文件
-移植文件
-
资源文件复制到src/lvgl_gui
-
LVGL
-
-
- 修改lvgl
修改lvgl_conf.h,如下所示,关闭案例编译
-
main
-
-
添加头文件
-
-UI初始化
-
删去之前LVGL官方案例的内容,添加如下代码- -ui_init();
-lvgl显示
-void lvgl_task(void *pt)
{
while(1)
{
lv_timer_handler(); /* let the GUI do its work */
vTaskDelay(5);
}
}
-
-setup()
中创建任务xTaskCreatePinnedToCore(lvgl_task, "lvgl display", 1024 * 15, NULL, 2, NULL, 1);
-
编译下载
END
--硬件:立创ESP32S3R8N8开发板 + 2.8寸TFT显示屏(ST7789) + 电容触摸(GT911)
-
软件:Visual Studio Code + PlatformIO
代码:百度网盘:ESP32S3_GT911TOUCH(提取码:levi)
视频:bilibili: 【ESP32】2.8寸电容触摸屏(ST7789+GT911) lvgl 案例测试
博客:CSDN: 【ESP32】立创ESP32S3R8N8开发板+2.8寸TFT电容触摸屏ST7789+GT911+PlatformIO
新建工程
-
-
点击侧边
-PlatformIO
插件,新建工程
-依次设置工程名,开发板,框架
-
-
屏幕测试
添加TFT_eSPI
-
-
添加屏幕驱动库
-TFT_eSPI
,按如下图顺序
-添加TFT_eSPI到工程
-
-打开配置文件,可以看到已成功添加库
-
-
修改TFT_eSPI
-
-
打开
-.pio\libdeps\esp32-s3-devkitc-1\TFT_eSPI\User_Setup.h
文件
-根据屏幕驱动芯片解注释
-
-
// Only define one driver, the other ones must be commented out |
-
-
- 根据屏幕大小设置宽高 -
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation |
-
-
- 根据连线设置引脚 -
// ### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ### |
修改main.cpp
在屏幕上从上到下分别显示红绿蓝三色,以及白色文字,用来测试屏幕颜色显示是否正常。
-
|
下载调试
-
-
编译下载
-
-根据屏幕显示情况修改
-User_Setup.h
文件
-
如果颜色反转(白色显示为黑色),如下图所示,则取消下一个注释,尝试两个选项,其中一个选项应该纠正反转。
// If colours are inverted (white shows as black) then uncomment one of the next |
修改后,如下图所示,白色正常显示,但是RGB顺序存在问题
仅对于ST7735, ST7789和ILI9341,如果显示器上的蓝色和红色交换,则定义颜色顺序,一次尝试一个选项来找到显示的正确颜色顺序
-// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display |
修改后,如下图所示,RGB顺序正常
LVGL测试
添加LVGL
-
-
根据实际情况,选择lvgl版本
-
![](lvglinstall.png” style=”zoom:67%;” >
-添加lvgl到工程
-
![](lvglinstalled.png” style=”zoom:67%;” >
-
修改LVGL
-
-
打开
-.pio\libdeps\esp32-s3-devkitc-1\lvgl\lv_conf_template.h
文件将此文件重命名为
-lv_conf.h
-
![](lvconf.png” style=”zoom:67%;” >
--
-
- 使能lvgl -
/* clang-format off */ |
-
-
- 设置周期 -
默认显示刷新周期。LVG将重新绘制改变的区域与这个周期时间
输入设备读取周期毫秒
/*Default display refresh period. LVG will redraw changed areas with this period time*/ |
-
-
- 心跳使能 -
/*Use a custom tick source that tells the elapsed time in milliseconds. |
-
-
- 使能测试案例 -
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */ |
-
-
更改文件路径
-将
-.pio\libdeps\esp32-s3-devkitc-1\lvgl\demos
文件夹移动至.pio\libdeps\esp32-s3-devkitc-1\lvgl\src\demos
-修改main.cpp
-将
-.pio\libdeps\esp32-s3-devkitc-1\lvgl\examples\arduino\LVGL_Arduino\LVGL_Arduino.ino
文件内容复制-
-
- 设置头文件 -
- --
-
- 设置宽高 -
- -static const uint16_t screenWidth = 320;
static const uint16_t screenHeight = 240;-
-
- 修改类型 -
-lv_disp_t
修改为lv_disp_drv_t
-lv_indev_t
修改为lv_indev_drv_t
-
-
- 注释掉触摸部分 -
-
修改完成
最终main.cpp
文件内容如下
|
编译下载
显示效果如下图
触摸测试
添加bb_captouch
-修改main.cpp
-
-
添加头文件
--
-设置触摸芯片引脚
--// These defines are for a low cost ESP32 LCD board with the GT911 touch controller
-设置参数
--BBCapTouch bbct;
const char *szNames[] = {"Unknown", "FT6x36", "GT911", "CST820"};
-初始化
--bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);
-修改
-my_touchpad_read
函数这里的x,y坐标需要根据实际情况修改
- -/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{
TOUCHINFO ti;
if(bbct.getSamples(&ti))
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = screenWidth - ti.y[0];
data->point.y = ti.x[0];
Serial.print( "Data x " );
Serial.println( screenWidth - ti.y[0] );
Serial.print( "Data y " );
Serial.println( ti.x[0] );
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
-
修改完成
最终main.cpp
文件内容如下
|
编译下载
触摸显示效果如下图所示
END
Quick Start
Create a new post
$ hexo new "My New Post" |
More info: Writing
-Run server
$ hexo server |
More info: Server
-Generate static files
$ hexo generate |
More info: Generating
-Deploy to remote sites
$ hexo deploy |
More info: Deployment
-]]>