项目介绍和创意介绍
本项目参加2025贸泽电子M-Design创意设计竞赛,参加其中的方向二:安全检测。本项目基于ESP32-C3设计了一款低功耗温湿度监测设备,通过AHT20传感器采集环境温湿度数据,并在墨水屏上实时显示。系统以18650锂电池供电,结合低功耗线性稳压器和深度睡眠技术,实现20分钟循环监测。本项目充电一次可以用1个月。可以用来检测药品或其他食品的温度。
硬件介绍
1. ESP32-C3:
其实我选择esp32-c3最大的原因是我会ESP32程序的编写,并且他的深度睡眠模式(Deep-Sleep)只有5ua,并且可以设置定时器唤醒,符合我对这个项目的要求,板载天线,支持蓝牙和WIFI如果后期有上云需求可以直接编写程序,不动硬件电路。
2. AHT20:
相较于常用的DHT11和DHT22我更倾向于AHT20首先是他的价格比DHT11还低,但他的精度比DHT22还高。温度范围为: 测量范围为-40℃~+ 85℃ 精度±0.3℃。湿度范围为:测量范围为0% - 100%精度为±2%RH,采用I2C的接口方式,这个通信协议很简单,我感觉相较于DHT11的单总线协议更加的稳定可靠。
3. 墨水屏
为什么要用墨水屏呢,我看中他最大的特性是断电可以保留,休眠模式功耗为几微安,非常适合这种低功耗的场所。并且之前没有尝试过,想多学习一下这个显示模块。
4.ME6211C33M5G
ME6211C33M5G他相较于最常见的ams1117-3.3最大的优点是压差极低,AMS1117-3.3的压差为1.3v左右, 锂电池输出约3.7v~4.2V的直流电,因为使用的线性稳压器AMS1117-3.3的输入电压和输出电压的压差至少要1.3V,输入电压至少要3.3V+1.3V=4.6V才能正常工作,而3.7V的锂电池就算是充满电也只有4.2V,远达不到4.6V。所以使用ME6211C33M5G就可以不进行升压直接将锂电池输出电压降至3.3v,供给单片机和外设使用。
5.18650锂电池
采用1000mah的锂电池,可以使用1个月。
方案框图和项目设计思路介绍
方案框图:
设计思路:
ESP32-C3采集温湿度检测模块的AHT20温度和湿度并在墨水屏上显示,后ESP32-C3和墨水屏进入深度睡眠模式,20分钟后定时器自动唤醒,进入下一轮循环。
原理图和PCB介绍
软件流程图和关键代码介绍
软件流程图
关键代码
#include <Arduino.h>
#if 1 //2.6寸墨水屏
#include "DEV_Config.h"
#include "EPD.h"
#include "GUI_Paint.h"
#include <Wire.h>
#include <AHT20.h>
#include <esp_sleep.h>
#include <stdlib.h>
#define us_s 1000000 //将微秒转化为秒的系数
#define second 1200 //睡眠20分钟
AHT20 aht20;
float temperature;
int t=0;
float humidity;
int h=0;
int v=0;
double v_3=0;
void setup()
{
pinMode(0,OUTPUT);
digitalWrite(0,HIGH);
pinMode(10,OUTPUT);
digitalWrite(10,HIGH);
delay(100);
digitalWrite(10,LOW);
Wire.begin(2,1); //Join I2C bus
if (aht20.begin() == false)
{
while (1);
}
DEV_Module_Init();
EPD_2IN9B_V3_Init();
EPD_2IN9B_V3_Clear();
esp_sleep_enable_timer_wakeup(second * us_s);
DEV_Delay_ms(500);
//Create a new image cache named IMAGE_BW and fill it with white
UBYTE *BlackImage, *RYImage; // Red or Yellow
UWORD Imagesize = ((EPD_2IN9B_V3_WIDTH % 8 == 0)? (EPD_2IN9B_V3_WIDTH / 8 ): (EPD_2IN9B_V3_WIDTH / 8 + 1)) * EPD_2IN9B_V3_HEIGHT;
if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
printf("Failed to apply for black memory...\r\n");
while(1);
}
if((RYImage = (UBYTE *)malloc(Imagesize)) == NULL) {
printf("Failed to apply for red memory...\r\n");
while(1);
}
//printf("NewImage:BlackImage and RYImage\r\n");
Paint_NewImage(BlackImage, EPD_2IN9B_V3_WIDTH, EPD_2IN9B_V3_HEIGHT, 270, WHITE);
Paint_NewImage(RYImage, EPD_2IN9B_V3_WIDTH, EPD_2IN9B_V3_HEIGHT, 270, WHITE);
#if 1 // Drawing on the image
/*Horizontal screen*/
//1.Draw black image
Paint_SelectImage(BlackImage);
Paint_Clear(WHITE);
//Paint_DrawString_EN(10, 0, "waveshare", &Font16, BLACK, WHITE);
#if 1
Paint_DrawString_CN(30, 20, "温度", &Font24CN, BLACK, WHITE);
Paint_DrawString_EN(94, 30, ":", &Font24, WHITE,BLACK );
if(temperature<0){
temperature=-temperature;
Paint_DrawString_EN(100, 30, "-", &Font24, WHITE,BLACK );
}
if((int)temperature==0)
Paint_DrawString_EN(110, 30, "0", &Font24, WHITE,BLACK );
else
Paint_DrawNum(110, 30, (int)temperature, &Font24, BLACK, WHITE);
t=(int)(temperature*10)%10;
Paint_DrawString_EN(140, 30, ".", &Font24, WHITE,BLACK );
if(t==0)
Paint_DrawString_EN(150, 30, "0", &Font24, WHITE,BLACK );
else
Paint_DrawNum(150, 30,t, &Font24, BLACK, WHITE);
Paint_DrawString_CN(30, 60, "湿度", &Font24CN, BLACK, WHITE);
Paint_DrawString_EN(94, 70, ":", &Font24, WHITE,BLACK );
Paint_DrawNum(110, 70, (int)humidity, &Font24, BLACK, WHITE);
h=(int)(humidity*10)%10;
Paint_DrawString_EN(140, 70, ".", &Font24, WHITE,BLACK );
if(h==0)
Paint_DrawString_EN(150, 70, "0", &Font24, WHITE,BLACK );
else
Paint_DrawNum(150, 70,h, &Font24, BLACK, WHITE);
#endif
//2.Draw red image
Paint_SelectImage(RYImage);
Paint_Clear(WHITE);
Paint_DrawString_CN(160, 20, "℃", &Font24CN, BLACK, WHITE);
Paint_DrawString_CN(165, 60, "%", &Font24CN, BLACK,WHITE );
printf("EPD_Display\r\n");
EPD_2IN9B_V3_Display(BlackImage, RYImage);
#endif
//printf("Clear...\r\n");
//EPD_2IN9B_V3_Clear();
printf("Goto Sleep...\r\n");
EPD_2IN9B_V3_Sleep();
DEV_Delay_ms(200);
free(BlackImage);
free(RYImage);
BlackImage = NULL;
RYImage = NULL;
#if 0
EPD_2IN9B_V3_Init();
DEV_Delay_ms(500);
Paint_SelectImage(BlackImage);
Paint_DrawNum(10, 70, 1234567, &Font16, BLACK, WHITE);
EPD_2IN9B_V3_Display(BlackImage, RYImage);
printf("Goto Sleep...\r\n");
EPD_2IN9B_V3_Sleep();
DEV_Delay_ms(2000);
free(BlackImage);
free(RYImage);
BlackImage = NULL;
RYImage = NULL;
#endif
}
/* The main loop -------------------------------------------------------------*/
void loop()
{
esp_deep_sleep_start(); //ESP32开始进入深度睡眠
}
功能展示图及说明
采用墨水屏,及时将电池拿下依然可以显示。显示温度和湿度,精确到小数点后一位。
发现采用纽扣电池电流输出太小,设备一直重启。
采用18650电池供电。PCB与原理图已修改为锂电池供电。
设计中遇到的难题和解决方法
之前寻思使用纽扣电池来进行供电,但是我直接用纽扣电池供电的时候发现,电池在输出电流大的时候它会降低输出电压,都能降到2.6伏以下,然后的单片机它就会直接重启。在网上找到了解释:大电流会通过增加温度以及减少电解质的方式变相的造成电池内阻的增加。从而增大内阻所分去的电压,减小电池两端的电压,当电池两端电压小于MCU的工作电压时,就会导致MCU重启,这也就是为什么电池电量较低时,设备会不断重启的原因,之后我又通过在电源直接并联电容和加电荷泵来进行升压,还是不行。所以改至使用18650锂电池供电,这样问题就解决了。
对本次竞赛的心得体会
- 低功耗设计启示:
- 系统级功耗优化比单一器件选型更重要
- 改进方向:
- 增加太阳能充电模块(TP4056芯片)
- 通过ESP-NOW协议实现多节点组网
- 在PCB设计阶段预留电流测量焊盘(便于功耗分析)