本帖最后由 云天 于 2024-4-4 11:39 编辑
【项目背景】
长时间在电脑前工作,不太容易想起来喝水,今天这个项目是用来定时提醒喝水。
【项目设计】
主控使用Beetle ESP32-c3,使用它的原因,一是因为体积小,有集成充电管理,支持Wi-Fi 。通过从网络时间服务器获取时间,并使用ESP32自带的RTC时钟保持时间更新,每半小时提醒一次。使用UART通讯控制电机及灯光驱动模块的PWM输出,调节LED柔性灯丝。
【硬件准备】
1.3V 260mm 柔性软灯丝
直径2mm,长度260mm的3V柔性软灯丝,可用于DIY灯光装饰,DIY灯泡球,360°全角度发光灯具等。
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,如设置高了,时间长会烧毁灯丝。
-
- #define PWM_ENABLE 0x01
- #define PWM_DISENABLE 0x00
- #define DEV_ADDR 0x32
- #define DUTY_REG_ADDR 0x0006
- #define FREQ_REG_ADDR 0x0007
- #define PWM_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[pos];
- 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[8];
- uint16_t crc;
- tempData[0] = DEV_ADDR;
- tempData[1] = 0x06;
- tempData[2] = (regAddr >> 8) & 0xFF;
- tempData[3] = regAddr & 0xFF;
- tempData[4] = (value >> 8) & 0xFF;
- tempData[5] = value & 0xFF;
- crc = CheckCRC(tempData, 6);
- tempData[6] = (crc >> 8) & 0xFF;
- tempData[7] = crc & 0xFF;
- for(uint8_t i = 0 ;i < 8; i++){
- Serial.print((char)tempData[i]);
- }
- 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;
- #define PWM_ENABLE 0x01
- #define PWM_DISENABLE 0x00
- #define DEV_ADDR 0x32
- #define DUTY_REG_ADDR 0x0006
- #define FREQ_REG_ADDR 0x0007
- #define PWM_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[pos];
- 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[8];
- uint16_t crc;
- tempData[0] = DEV_ADDR;
- tempData[1] = 0x06;
- tempData[2] = (regAddr >> 8) & 0xFF;
- tempData[3] = regAddr & 0xFF;
- tempData[4] = (value >> 8) & 0xFF;
- tempData[5] = value & 0xFF;
- crc = CheckCRC(tempData, 6);
- tempData[6] = (crc >> 8) & 0xFF;
- tempData[7] = crc & 0xFF;
- for(uint8_t i = 0 ;i < 8; i++){
- Serial.print((char)tempData[i]);
- }
- 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);
- }
复制代码
【演示视频】
|