【立创开源】ESP32_UV_BOX

ESP_UV_BOX

前言

🔗夏日征集令
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用于采集电压值,以及按键控制
image.png

自动下载

串口芯片使用CH340K
image.png

电源电路

电源切换电路

使用PMOS,当没有外部电源时使用电池供电,有外部电源输入时不使用电池供电
image.png

充电电路

电池管理使用TP4056,电路参考TP4056数据手册
image.png
充电电流如下,根据锂电池参数选择合适的电阻

Rprog(K) Ibat(mA)
1.2 1000
2.4 500
3.0 400
4.0 300
6.0 200
12.0 200

外设

按键

板载一个RESET和BOOT侧边按键,使用拨轮开关作为控制输入
image.png

TFT

使用1.8寸TFT屏幕插接,分辨率128x160,屏幕驱动ST7735,屏幕驱动电路参考屏幕原理图,可以通过BLK引脚控制屏幕亮度
image.png

UV

紫外线部分电路参考紫外线模块电路设计

image.png
通过采集电压,根据电压范围,得到紫外线强度

image.png

AHT20 BMP280

这两个器件,用烙铁不好焊,加热台方便些
AHT20可以检测环境温湿度
image.png
BMP280可以检测大气压,温度,以及海拔高度(由压力和温度计算得到)
image.png

面板

使用立创EDA设计简单的面板

3D外壳

1.8寸版本
本次使用SOLIDWORKS2023建模

立创EDA导出模型

image.png

image.png

SOLIDWORKS

使用SOLIDWORKS打开导出的step格式文件

image.png
打开后如下图所示,可以看到电路板模型缺少丝印图案

image.png
回到PCB工程,打开PCB的2D视图

image.png
导出上下面丝印图
如下图点击PCB上表面,选择外观

image.png
选择导出的顶层丝印图

image.png

image.png
还需要调整丝印的位置和大小,选择映射

image.png
根据实际情况,调整以下参数

image.png
之后便可以开始外壳的建模,最终效果如下
image.png

程序

详细代码见levi52@GitHub: ESP32_UV_BOX

页面结构

在主界面下设四个功能页,之后各级再设功能分页,主要结构如下
image.png

设计参考:
B站:黑人黑科技的视频DIY万能遥控器
OSHWHub: 黑人黑科技的开源工程ESP32 万能遥控器

主菜单.png

代码

开发工具:Visual Studio Code + PlatformIO
图标:iconfont-阿里巴巴
颜色:RGB COLOR PICKER
中文转换:中文转UNICODE
图片转换:FileToCArray

代码结构主要如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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/ 测试文件

界面

屏幕尺寸为1.8寸,分辨率是128x160,屏幕驱动是ST7735,使用TFT_eSPI库驱动屏幕,所有界面使用TFT_eSPI绘制

使用TFT_eSPI需要修改配置文件User_Setup.h,根据屏幕类型和显示情况修改内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define ST7735_DRIVER // 屏幕驱动
#define TFT_RGB_ORDER TFT_RGB // 颜色顺序
#define TFT_WIDTH 128 // 屏幕宽度
#define TFT_HEIGHT 160 // 屏幕高度
#define ST7735_GREENTAB2 // 仅ST7735
// #define TFT_INVERSION_ON // 黑白反转
// #define TFT_INVERSION_OFF
#define TFT_BL 17 // 背光引脚
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 5 // Chip select control pin
#define TFT_DC 2 // Data Command control pin
#define TFT_RST 4 // Reset pin (could connect to RST pin)
//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

使用ledc控制引脚输出PWM调节屏幕背光亮度

控制

使用mathertel/OneButton库来实现按键的控制,分别注册短按,双击和长按函数来实现不同的操作

上下短按为页面切换,中间短按为进入页面,中间长按为返回上一级

传感器

UV

使用S12SD传感器来检测紫外线,然后经过放大,使用ADC采集电压,根据电压范围判断紫外线指数等级

下图为紫外线模块
image.png
程序中使用此函数获取紫外线指数

1
uint8_t sensor_uv_data(void)

图中为Arduino对应的数值,详情见DFROBOT: UV Sensor
image.png

AHT20

使用dvarrel/AHT20库读取AHT20温湿度传感器的数据
主要为如下内容,AHT20数据结构体,初始化函数,以及数据读取函数(返回数据结构体)

1
2
3
4
5
6
7
struct AHT20Data
{
float temperature;
float humidity;
};
void sensor_aht20_init(void);
AHT20Data sensor_aht20_data(void);

BMP280

使用seeed-studio/Grove - Barometer Sensor BMP280库读取BMP280传感器的数据
主要为如下内容,BMP280数据结构体,初始化函数,以及数据读取函数(返回数据结构体)

1
2
3
4
5
6
7
8
struct BMP280Data
{
float temperature;
float pressure;
float altitude;
};
void sensor_bmp280_init(void);
BMP280Data sensor_bmp280_data(void);

在函数bool BMP280::init(void)中注释掉Wire.begin()
在主程序中上面两个传感器初始化前,要先使用Wire.begin(21, 22);来设置IIC引脚

网络

配网

初次使用时,会建立如下网络ESP_UV_BOX_WIFI
image.png
连接网络,浏览器打开网址192.168.1.1,会出现如下配网页面

页面代码参考: CSDN: 请收藏!分享一个ESP32/ESP8266高颜值WIFI配网页面代码-带下拉选择框和中英文版本。文末有arduino配网代码。

一共四个输入框,分别是WIFI SSID, WIFI PASSWORD, Private KEY, Location ID

相关链接:和风天气控制台城市 ID

image.png
点击保存后,芯片会重启连接网络

网络配置相关函数如下

1
2
3
4
5
6
7
8
9
10
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);

天气时钟

天气等数据使用和风天气API,免费订阅每天可以有1000次请求

订阅规则

1
2
3
4
5
void get_weather_now(void);
void get_weather_future(void);
void get_air(void);
void get_city_id(void);
String urlEncode(const String& text);

网络相关函数如下

1
2
void time_init(void);
void get_time(void);

天气预报

同上,使用和风天气API,屏幕显示未来六天天气状况

空气质量

同上,使用和风天气API,屏幕显示颗粒物PM10,颗粒物PM2.5,二氧化氮NO2,二氧化硫SO2,一氧化碳CO,臭氧O3

哔哩哔哩

通过如下API接口获得JSON格式的数据,使用ArduinoJson库解析获得关注数和粉丝数

1
https://api.bilibili.com/x/relation/stat?vmid=用户UID

可以使用官网提供的工具生成解析代码

1
2
3
4
5
6
7
8
9
10
11
12
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"mid": 378576508,
"following": 318,
"whisper": 0,
"black": 0,
"follower": 56
}
}

生成的解析代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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

灯光

使用fastled/FastLED库驱动板载的一颗WS2812灯珠,暂时只添加不同颜色灯切换功能

实物

PCB

image.png

页面

下图为部分页面
image.png
后续会上传B站视频

END

最后非常感谢立创🥰提供的机会和各种优惠券,帮助我们实现想法,做出实物,参加征集令活动收获颇多,未来继续努力😄

Typing SVG