当前位置: 首页 > news >正文

ESP32 网络计时器,包含自动保存

简介

本代码是基于ESP32开发板实现的一个计时器功能,具备倒计时、计时器时长选择、显示当前时间、有源蜂鸣器报警等功能。代码中使用了WiFi网络连接、NTP时间同步、EEPROM存储等功能。通过按钮控制计时器的开始、停止和计时器时长的选择。

运行原理概述

在ESP32开发板上,使用了三个按钮,分别为开始计时按钮(BUTTON1)、停止计时按钮(BUTTON2)和计时器时长选择按钮。首先连接WiFi网络,同步NTP时间,并初始化OLED屏幕。

然后通过setdefaulttime()函数设置计时器默认时长,并初始化按钮引脚。

在主循环中通过checkTimerButtons()函数检测按钮状态,若按钮被按下,根据按钮类型执行相应的操作。如果开始计时按钮被按下,则开始计时,并在OLED屏幕上显示计时器倒计时时间。

如果停止计时按钮被按下,则停止计时,并根据按钮状态执行相应的操作。如果计时器时长选择按钮被按下,则切换计时器时长,并在OLED屏幕上显示新的计时器时长。

特色功能

1.具备倒计时功能,可以按照设定的计时器时长进行倒计时,到时后有报警提示。

2.计时器时长可以选择,用户可以根据需求选择不同的计时器时长。

3.通过WiFi网络连接和NTP时间同步功能,保证了计时器的时间准确性。

4.使用EEPROM存储功能,保存计时器时长选择的状态,即使重新上电,也能保留上一次的时长选择状态。

重要函数的解释

  1. void setdefaulttime()函数:设置计时器默认时长,并从EEPROM中读取上一次的时长选择状态。

  2. void checkTimerButtons()函数:检测按钮状态,并根据按钮类型执行相应的操作。

  3. void updateTimeDisplay()函数:更新OLED屏幕上的时间和计时器倒计时时间。

  4. bool saveIntToEEPROM(int value, int address)函数:将整数值存储到EEPROM中。

  5. int readIntFromEEPROM(int address)函数:从EEPROM中读取整数值。

ESP32开发板引脚硬件设备引脚连接方式
GPIO21OLED_SDAI2C数据线
GPIO22OLED_SCLI2C时钟线
GPIO35BUTTON1按钮输入
GPIO34BUTTON2按钮输入
GPIO32BUZZER_PIN有源蜂鸣器引脚
3.3VOLED_VCCOLED显示屏电源
GNDOLED_GNDOLED显示屏电源和地
3.3VBUTTON1按钮电源
3.3VBUTTON2按钮电源
GNDBUTTON1按钮电源和地
GNDBUTTON2按钮电源和地

#include <WiFi.h>
#include <NTPClient.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include <EEPROM.h>
#define OLED_ADDR 0x3C // OLED屏幕地址
#define OLED_SDA 21    // ESP32开发板上的SDA引脚
#define OLED_SCL 22    // ESP32开发板上的SCL引脚
#define BUTTON1 35     // 开始计时按钮
#define BUTTON2 34     // 停止计时按钮
#define BUZZER_PIN 32  // 有源蜂鸣器连接的引脚
#define MAXMENU 5
#define ADDR_1 1
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp.ntsc.ac.cn"); // NTP客户端
Adafruit_SSD1306 display(128, 64, &Wire, -1);   // OLED屏幕
int menuvalue = 1;
// 计时器相关变量
unsigned long startTime = 0; // 计时器开始时间
unsigned long stopTime = 0; // 计时器停止时间
bool timerRunning = false; // 是否正在计时
unsigned long duration = 0; // 计时器持续时间
unsigned long remainingTime = 0; // 剩余时间// 时间显示相关变量
String lastFormattedTime = ""; // 上次更新的时间
unsigned long lastUpdateTime = 0; // 上次更新时间的时间戳
// 默认倒计时时间
int defaulttime = 5*60*1000;
// 设置默认倒计时时间
void setdefaulttime();bool saveIntToEEPROM(int value, int address) {EEPROM.begin(16);EEPROM.put(address, value);bool success = EEPROM.commit();EEPROM.end();display.setCursor(0, 50);display.setTextSize(1);if(success){display.println("Save Success");}else {display.println("Failed");}Serial.print("save menuvalue:");Serial.println(value);return success;
}int readIntFromEEPROM(int address) {if (EEPROM.begin(16)) {int value;if (EEPROM.get(address, value)) {EEPROM.end();return value;} else {Serial.println("Failed to read from EEPROM");}} else {Serial.println("EEPROM initialization failed");}EEPROM.end();return 0;
}unsigned long timerDuration = 5 * 60 * 1000;  // 初始计时器长度为5分钟//frequency参数是需要发出的声音频率,单位为Hz;duration参数是发出声音的持续时间,单位为毫秒。
void buzz(int frequency, long duration)
{int period = 1000000 / frequency; // 计算周期int pulse = period / 2; // 计算脉冲时间for (long i = 0; i < duration * 1000L; i += period){digitalWrite(BUZZER_PIN, HIGH); // 发送高电平delayMicroseconds(pulse); // 持续脉冲时间的一半digitalWrite(BUZZER_PIN, LOW); // 发送低电平delayMicroseconds(pulse); // 持续脉冲时间的一半}
}
void checkTimerButtons()
{if (digitalRead(BUTTON1) == LOW && !timerRunning){// 开始计时器buzz(2000, 100);startTime = millis();timerRunning = true;}if (digitalRead(BUTTON2) == LOW){buzz(2000, 100);if (timerRunning){// 停止计时器stopTime = millis();timerRunning = false;remainingTime = timerDuration - (stopTime - startTime);while(digitalRead(BUTTON2) == LOW);delay(100);}else{// 切换计时器时间长度if (menuvalue == 1){timerDuration = 10 * 60 * 1000;menuvalue =2;}else if (menuvalue == 2){timerDuration = 30 * 60 * 1000;menuvalue=3;}else if (menuvalue==3){timerDuration = 60 * 60 * 1000;menuvalue=4;}else if (menuvalue ==4){timerDuration = 5 * 60 * 1000;menuvalue = 1;}remainingTime = timerDuration;defaulttime = timerDuration;saveIntToEEPROM(menuvalue,ADDR_1);while(digitalRead(BUTTON2) == LOW);}}
}void setdefaulttime()
{menuvalue = readIntFromEEPROM(ADDR_1);Serial.print("read menuvalue:");Serial.println(menuvalue);if (menuvalue>0&&menuvalue<=MAXMENU){switch(menuvalue){case 1:defaulttime = 5 * 60 * 1000;break;case 2:defaulttime = 10 * 60 * 1000;break;case 3:defaulttime = 30 * 60 * 1000;break;case 4:defaulttime = 60 * 60 * 1000;break;default:defaulttime = 5 * 60 * 1000;break;}}else{menuvalue = 1;saveIntToEEPROM(menuvalue,ADDR_1);defaulttime = 5 * 60 * 1000;}remainingTime = defaulttime;}
void updateTimeDisplay()
{timeClient.update();String formattedTime = timeClient.getFormattedTime();display.clearDisplay();display.setCursor(0, 0);display.setTextSize(2);display.setTextColor(WHITE);display.println(formattedTime);if (timerRunning){duration = millis() - startTime;remainingTime = timerDuration - duration;display.setCursor(0, 36);display.setTextSize(4);int minutes = remainingTime / 1000 / 60;int seconds = (remainingTime / 1000) % 60;if (minutes < 10){display.print("0");}display.print(minutes);display.print(":");if (seconds < 10){display.print("0");}display.println(seconds);}else{display.setCursor(0, 36);display.setTextSize(4);int _minutes = remainingTime / 1000 / 60;int _seconds = (remainingTime / 1000) % 60;if (_minutes < 10){display.print("0");}display.print(_minutes);display.print(":");if (_seconds < 10){display.print("0");}display.println(_seconds);}display.display();
}void setup()
{// 连接WiFi网络pinMode(BUZZER_PIN, OUTPUT);WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); Serial.begin(115200);Wire.begin(OLED_SDA, OLED_SCL);display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);display.clearDisplay();display.setCursor(0, 0);display.setTextSize(1);display.setTextColor(WHITE);display.println("Connecting to ");display.println("360WiFi-016C34");display.println("Password: ");display.println("wangjinxuan");display.display();WiFi.begin("360WiFi-016C34", "wangjinxuan");int i = 0;while (WiFi.status() != WL_CONNECTED && i < 10){delay(500);display.clearDisplay();display.setCursor(0, 0);display.print("Connecting");for (int j = 0; j < i; j++){display.print(".");}display.display();i++;}if (WiFi.status() != WL_CONNECTED){display.clearDisplay();display.setCursor(0, 0);display.println("Failed to connect.");display.display();while (true){// 连接失败,停止程序}}// 初始化OLED屏幕Wire.begin(OLED_SDA, OLED_SCL);display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);display.clearDisplay();//初始化数值setdefaulttime();// 初始化按钮引脚pinMode(BUTTON1, INPUT_PULLUP);pinMode(BUTTON2, INPUT_PULLUP);// 同步时间timeClient.begin();timeClient.setTimeOffset(28800); // 设置时区(这里为东八区)
}void loop()
{checkTimerButtons();updateTimeDisplay();if (timerRunning){duration = millis() - startTime;remainingTime = timerDuration - duration;if (remainingTime <= 0 || remainingTime>timerDuration){// 计时器已完成timerRunning = false;buzz(2000,1000);delay(800);buzz(2000,1000);delay(800);buzz(2000,1000);delay(800);remainingTime = timerDuration;// TODO: 执行计时器完成操作}}
}

相关文章:

ESP32 网络计时器,包含自动保存

简介 本代码是基于ESP32开发板实现的一个计时器功能&#xff0c;具备倒计时、计时器时长选择、显示当前时间、有源蜂鸣器报警等功能。代码中使用了WiFi网络连接、NTP时间同步、EEPROM存储等功能。通过按钮控制计时器的开始、停止和计时器时长的选择。 运行原理概述 在ESP32开…...

【ChatGPT】阿里版 ChatGPT 突然官宣意味着什么?

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 阿里版 ChatGPT 突然官宣 ​ ChatGPT 技术在 AI 领域的重要性 自然语言生成 上下文连续性 多语言支持 ChatGPT 未来可能的应用场景 社交领域 商业领域 ​编辑 医疗领域…...

IPEmotion控制模块-PID循环应用

IPEmotion专业版、开发版支持控制模块&#xff0c;并且该模块支持函数发生器、PID控制器、路由器、序列控制和序列控制块以及参考曲线生成器。本文主要针对PID&#xff08;P&#xff1a;Proportional control 比例控制&#xff1b;I&#xff1a;Integral control 积分控制&…...

【元分析研究方法】学习笔记2.检索文献(含100种学术文献搜索清单链接)

检索文献 该步骤的作用该步骤中需要注意的问题该步骤中部分知识点我的收获 参考来源&#xff1a;库珀 (Cooper, H. M. )., 李超平, & 张昱城. (2020). 元分析研究方法: A step-by step approach. 中国人民大学出版社. 该步骤的作用 1.识别相关文献的来源&#xff1b; 2.识别…...

题目:16版.自由落体

1、实验要求 本实验要求&#xff1a;模拟物体从10000米高空掉落后的反弹行为。 1-1. 创建工程并配置环境&#xff1a; 1-1.1. 限制1. 工程取名&#xff1a;SE_JAVA_EXP_E009。 1-1.2. 限制2. 创建包&#xff0c;取名&#xff1a;cn.campsg.java.experiment。 1-1.3. 限制3. 创建…...

视频可视化搭建项目,通过简单拖拽方式快速生产一个短视频

一、开源项目简介 《视搭》是一个视频可视化搭建项目。您可以通过简单的拖拽方式快速生产一个短视频&#xff0c;使用方式就像易企秀或百度 H5 等 h5 搭建工具一样的简单。目前行业内罕有关于视频可视化搭建的开源项目&#xff0c;《视搭》是一个相对比较完整的开源项目&#…...

network-1 4 layer internet model

4layer model applicationtransport tcp: transmission control protocol enable correct in-order delivery of data, running on top of the network layer service.udp: user datagram protocolnetwork packet&#xff1a;data、from、tonetwork->linkiplink source en…...

计算机网络笔记(横向)

该笔记也是我考研期间做的整理。一般网上的笔记是按照章节纪录的&#xff0c;我是按照知识点分类纪录的&#xff0c;大纲如下&#xff1a; 文章目录 1. 各报文1.1 各报文头部详解1.2 相关口诀 2. 各协议2.1 各应用层协议使用的传输层协议与端口2.2 各协议的过程2.2.1 数据链路层…...

0.redis-实践

1.redis内存设置多少,默认是0&#xff0c;不限制 2.如何配置&#xff0c;修改内存大小 1) 查看最大占用内存 # maxmeory <bytes> 或者 config get maxmemory 2) 默认内存多少可以用: 64位系统下不限制&#xff0c;32位下最多3G 3) 如何配置: 默认总内存的3/4 4) 如何修改…...

Redux的基本使用,从入门到入土

目录 一、初步使用Redux 1.安装Redux 2.配置状态机 二、Redux的核心概念 1.工作流程 2.工作流程 三、优化Redux 1.对action进行优化 2.type常量 3.reducer优化 四、react-redux使用 1.安装react-redux 2.全局注入store仓库 3.组件关联仓库 五、状态机的Hook 1.u…...

GDOUCTF2023-部分re复现

目录 [GDOUCTF 2023]Check_Your_Luck [GDOUCTF 2023]Tea [GDOUCTF 2023]doublegame [GDOUCTF 2023]Check_Your_Luck 打开题目是一串代码&#xff0c;明显的z3约束器求解 直接上脚本 import z3 from z3 import Reals z3.Solver() vReal(v) xReal(x) yReal(y) wReal(w) zRea…...

Java学习17(IO模型详解)

1、何为IO? I/O&#xff08;Input/Outpu&#xff09; 即输入&#xff0f;输出 。 从计算机结构的角度来解读一下 I/O。 根据冯.诺依曼结构&#xff0c;计算机结构分为 5 大部分&#xff1a;运算器、控制器、存储器、输入设备、输出设备。 输入设备&#xff08;比如键盘&am…...

Vue-全局过滤器以及进阶操作

前言 上篇文件讲述了&#xff0c;Vue全局过滤器的基本使用&#xff1a;Vue过滤器的基本使用 本篇将延续上文&#xff0c;讲述vue中过滤器的进阶操作 过滤器传参 如果有一天&#xff0c;多个地方使用过滤器&#xff0c;而且需要传递参数&#xff0c;那么可以这么写 多个过滤…...

财报解读:涅槃重生之后,新东方还想再造一个“文旅甄选”?

新东方逐渐走出了“微笑曲线”。 图源&#xff1a;新东方2023财年Q3财报 2023年4月19日&#xff0c;新东方披露了2023财年Q3财报&#xff08;截至2023年2月28日止&#xff09;&#xff0c;营收7.5亿美元&#xff0c;同比增长22.8%&#xff1b;归母净利润为8165万美元&#xff…...

华为OD机试 - 过滤组合字符串(Python)

题目描述 每个数字关联多个字母,关联关系如下: 0 关联 “a”,”b”,”c” 1 关联 “d”,”e”,”f” 2 关联 “g”,”h”,”i” 3 关联 “j”,”k”,”l” 4 关联 “m”,”n”,”o” 5 关联 “p”,”q”,”r” 6 关联 “s”,”t” 7 关联 “u”,”v” 8 关联 “w”,”x” 9 …...

maven简单使用

实验课的作业用一大堆框架/库&#xff0c;统统要用maven管理。 头一次用&#xff0c;真痛苦。 所幸得以解决&#xff0c;maven真香&#xff5e; 一步一步来。 1. maven 不是java人&#xff0c;只能说说粗浅的理解了。 简单来说&#xff0c;maven是一个管理项目的工具&…...

HTML学习笔记一

目录 HTML学习笔记 一、HTML标签 1、HTML语法规范 1.1标签的语法概述 1.2标签关系 2、HTML基本结构标签 2.1第一个HTML 2.2基本结构标签总结 3、开发工具 4、HTML常用标签 4.1标签的语义 4.2标题标签 4.3段落和换行标签 4.4文本格式化标签 4.5div和span标签 4.…...

人工智能十大流行算法,通俗易懂讲明白

人工智能是什么&#xff1f;很多人都知道&#xff0c;但大多又都说不清楚。 事实上&#xff0c;人工智能已经存在于我们生活中很久了。 比如我们常常用到的邮箱&#xff0c;其中垃圾邮件过滤就是依靠人工智能&#xff1b;比如每个智能手机都配备的指纹识别或人脸识别&#x…...

支持中英双语和多种插件的开源对话语言模型,160亿参数

一、开源项目简介 MOSS是一个支持中英双语和多种插件的开源对话语言模型&#xff0c;moss-moon系列模型具有160亿参数&#xff0c;在FP16精度下可在单张A100/A800或两张3090显卡运行&#xff0c;在INT4/8精度下可在单张3090显卡运行。MOSS基座语言模型在约七千亿中英文以及代码…...

SQL基础培训10-复杂查询原理

知识点: 1、SQL查询语句逻辑执行顺序 下面是一个查询语句的逻辑执行顺序(每段语句都标明了执行顺序号): 执行1:FROM 执行2:...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

Visual Studio Code 扩展

Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后&#xff0c;命令 changeCase.commands 可预览转换效果 EmmyLua…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...