智能喝水提醒器
本帖最后由 云天 于 2024-4-4 11:39 编辑【项目背景】
长时间在电脑前工作,不太容易想起来喝水,今天这个项目是用来定时提醒喝水。
【项目设计】
主控使用Beetle ESP32-c3,使用它的原因,一是因为体积小,有集成充电管理,支持Wi-Fi 。通过从网络时间服务器获取时间,并使用ESP32自带的RTC时钟保持时间更新,每半小时提醒一次。使用UART通讯控制电机及灯光驱动模块的PWM输出,调节LED柔性灯丝。
【硬件准备】
1.3V 260mm 柔性软灯丝
直径2mm,长度260mm的3V柔性软灯丝,可用于DIY灯光装饰,DIY灯泡球,360°全角度发光灯具等。
https://www.dfrobot.com.cn/data/video/1684745025162.mp4
2.灯光&电机驱动板
可以用Python代码控制、WINDOWS上位机控制、UART通讯编程控制、电位器手动控制共四种方式调节的PWM驱动器。用于直流电机调速、灯光调节等应用场景。本产品支持5V~24V宽电压输入,并具有10A的承载能力,能驱动50W左右的直流电机(由于电机端口极性固定,并不能控制电机方向)或者整卷5米左右的灯带。适用于水泵水量控制、散热风扇速度控制、灯光亮度调节、电动工具改造、电机灯带产品测试、电机速度自动化控制、灯光效果自动化控制等场景。
3.Beetle ESP32-C3
基于ESP32-C3的小体积主控,集成充电管理,适用于物联网项目
【硬件连接】
灯光&电机驱动板使用9V电池供电,柔性软灯丝接PWM OUT,通过UART与Beetle ESP32-c3的TX、RX引脚连接。Beetle ESP32-c3使用3.7V锂电池通过BAT引脚供电。
【编写程序】
柔性软灯丝发热较大,setPwmDuty(80);设置为80,如设置高了,时间长会烧毁灯丝。
#definePWM_ENABLE 0x01
#definePWM_DISENABLE 0x00
#defineDEV_ADDR 0x32
#defineDUTY_REG_ADDR 0x0006
#defineFREQ_REG_ADDR 0x0007
#definePWM_EN_REG_ADDR 0x0008
static uint16_t CheckCRC(uint8_t *data, uint8_t len){
uint16_t crc = 0xFFFF;
for(uint8_t pos = 0; pos < len; pos++){
crc ^= (uint16_t)data;
for(uint8_t i = 8; i != 0; i-- ){
if((crc & 0x0001) != 0){
crc >>= 1;
crc ^= 0xA001;
}else{
crc >>= 1;
}
}
}
crc = ((crc & 0x00FF) << 8) | ((crc & 0xFF00) >> 8);
return crc;
}
static void WriteRegValue(uint16_t regAddr, uint16_t value){
uint8_t tempData;
uint16_t crc;
tempData = DEV_ADDR;
tempData = 0x06;
tempData = (regAddr >> 8) & 0xFF;
tempData = regAddr & 0xFF;
tempData = (value >> 8) & 0xFF;
tempData =value & 0xFF;
crc = CheckCRC(tempData, 6);
tempData = (crc >> 8) & 0xFF;
tempData = crc & 0xFF;
for(uint8_t i = 0 ;i < 8; i++){
Serial.print((char)tempData);
}
Serial.flush();
}
static void setPwmDuty(uint8_t duty){
WriteRegValue(DUTY_REG_ADDR, (uint16_t)duty);
}
static void setPwmFreq(uint8_t freq){
WriteRegValue(FREQ_REG_ADDR, (uint16_t)freq);
}
static void setPwmEnable(uint8_t pwmStatus){
WriteRegValue(PWM_EN_REG_ADDR, (uint16_t)pwmStatus);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(1000);
setPwmFreq(10);
delay(50);
setPwmDuty(0);
delay(50);
setPwmEnable(PWM_ENABLE);
delay(50);
}
void loop() {
setPwmDuty(80);
delay(2000);
setPwmDuty(0);
delay(2000);
}
【定时设置】
连接WIFI,并从 "pool.ntp.org"网络时间服务器获取时间,当时间每到半小时(timeinfo.tm_min==30)亮灯提醒喝水。
#include <WiFi.h>
const char *ssid = "*******"; //WIFI名称
const char *password = "********"; //WIFI密码
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;
#definePWM_ENABLE 0x01
#definePWM_DISENABLE 0x00
#defineDEV_ADDR 0x32
#defineDUTY_REG_ADDR 0x0006
#defineFREQ_REG_ADDR 0x0007
#definePWM_EN_REG_ADDR 0x0008
static uint16_t CheckCRC(uint8_t *data, uint8_t len){
uint16_t crc = 0xFFFF;
for(uint8_t pos = 0; pos < len; pos++){
crc ^= (uint16_t)data;
for(uint8_t i = 8; i != 0; i-- ){
if((crc & 0x0001) != 0){
crc >>= 1;
crc ^= 0xA001;
}else{
crc >>= 1;
}
}
}
crc = ((crc & 0x00FF) << 8) | ((crc & 0xFF00) >> 8);
return crc;
}
static void WriteRegValue(uint16_t regAddr, uint16_t value){
uint8_t tempData;
uint16_t crc;
tempData = DEV_ADDR;
tempData = 0x06;
tempData = (regAddr >> 8) & 0xFF;
tempData = regAddr & 0xFF;
tempData = (value >> 8) & 0xFF;
tempData =value & 0xFF;
crc = CheckCRC(tempData, 6);
tempData = (crc >> 8) & 0xFF;
tempData = crc & 0xFF;
for(uint8_t i = 0 ;i < 8; i++){
Serial.print((char)tempData);
}
Serial.flush();
}
static void setPwmDuty(uint8_t duty){
WriteRegValue(DUTY_REG_ADDR, (uint16_t)duty);
}
static void setPwmFreq(uint8_t freq){
WriteRegValue(FREQ_REG_ADDR, (uint16_t)freq);
}
static void setPwmEnable(uint8_t pwmStatus){
WriteRegValue(PWM_EN_REG_ADDR, (uint16_t)pwmStatus);
}
void printLocalTime()
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain time");
return;
}
//Serial.println(&timeinfo, "%F %T %A"); // 格式化输出
//Serial.println(timeinfo.tm_sec);
if(timeinfo.tm_min==30 )
{
setPwmDuty(80);
}
else{
setPwmDuty(0);
}
}
void setup()
{
Serial.begin(9600);
delay(1000);
setPwmFreq(10);
delay(50);
setPwmDuty(0);
delay(50);
setPwmEnable(PWM_ENABLE);
delay(50);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected!");
// 从网络时间服务器上获取并设置时间
// 获取成功后芯片会使用RTC时钟保持时间的更新
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
Serial.println("WiFi disconnected!");
}
void loop()
{
//setPwmDuty(5);
printLocalTime();
//delay(2000);
//setPwmDuty(0);
delay(200);
}
【演示视频】
https://www.bilibili.com/video/BV1EZ421B7Zz/?share_source=copy_web
页:
[1]