#include <WiFi.h>
#include <Wire.h>
#include <Arduino.h>
//引入驱动OLED_0.96所需的库
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // 设置OLED宽度,单位:像素
#define SCREEN_HEIGHT 64 // 设置OLED高度,单位:像素
//自定义重置引脚,虽然教程未使用,但却是Adafruit_SSD1306库文件所必需的
#define OLED_RESET 4
//接线说明:oled的SCL-16 SDA-17 舵机信号线-15 按键一侧-GND另一侧-12
//功能描述:利用esp32的WIFI功能获取实时时间,并实现倒计时的功能,倒计时结束led闪烁并且舵机以180°来回旋转,led可替换为蜂鸣器,实现“闹钟”的功能
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int positionX=0;
const char *ssid = "ESP32"; //你的网络名称
const char *password = "88888888"; //你的网络密码
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;//用来修正时区的,该参数为东八区
const int daylightOffset_sec = 0;
int led=2;
int Key=12;
int Boot=0;
int state = 0;
int clk_sec=0;
int start_clk=0;
int cnt=0;
int time_up=0;
int led_state=0;
int freq = 50; // 频率(20ms周期)
int channel = 8; // 通道(高速通道(0 ~ 7)由80MHz时钟驱动,低速通道(8 ~ 15)由 1MHz 时钟驱动。)
int resolution = 8; // 分辨率
const int led1 = 15;
hw_timer_t * timer = NULL; //声明一个定时器
//舵机控制0-180度
int calculatePWM(int degree)
{
//20ms周期,高电平0.5-2.5ms,对应0-180度角度
const float deadZone = 6.4;//对应0.5ms(0.5ms/(20ms/256))
const float max = 32;//对应2.5ms
if (degree < 0)
degree = 0;
if (degree > 180)
degree = 180;
return (int)(((max - deadZone) / 180) * degree + deadZone);
}
void printLocalTime()
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo,"%F %T"); // 格式化输出
}
//中断服务函数
void IRAM_ATTR onTimer()
{
if(clk_sec!=0)
{
cnt++;
// 分钟为单位
// if(cnt==clk_sec*60)
// {
// state=2;
// }
// 秒为单位
if(cnt==clk_sec)
{
state=2;
}
}
if(state==2)
{
led_state = !led_state;
digitalWrite(led,led_state);
}
}
//时钟初始界面~年月日~时分秒
void oled()
{
struct tm timeinfo;
// 清除屏幕
display.clearDisplay();
// 设置字体颜色,白色可见
display.setTextColor(WHITE);
//设置字体大小
display.setTextSize(2.0);
//设置光标位置
display.setCursor(positionX,0);
display.print("Time:\n");
display.setCursor(positionX,22);
display.print(&timeinfo,"%F");
display.setCursor(positionX,45);
display.print(&timeinfo,"%T");
display.display();
}
//时钟设置界面
void time_set()
{
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2.0);
display.setCursor(positionX,0);
display.print("Clock: ");
display.setCursor(positionX,22);
display.print(clk_sec);
display.display();
}
//时钟响应界面
void oled_timer()
{
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2.0);
display.setCursor(positionX,22);
display.print("Time's up!");
display.display();
}
//获取键值
void key_value()
{
if(digitalRead(Boot)==0)
{
delay(5);
if(digitalRead(Boot)==0)
{
state=!state;
}
while(digitalRead(Boot)==0)
{
oled();
printLocalTime();//获取时间
}
}
if(state==1)
{
if(digitalRead(Key)==0)
{
delay(5);
if(digitalRead(Key)==0)
{
clk_sec++;
while(digitalRead(Key)==0)
{
time_set();
}
}
}
}
}
//初始化
void setup()
{
Serial.begin(115200);
Serial.println();
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!");
Wire.begin(/*SDA*/17,/*SCL*/16);
// 初始化OLED并设置其IIC地址为 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
pinMode(Key, INPUT_PULLUP);//将中断的引脚设置为输入PULLUP模式
pinMode(led,OUTPUT);
timer = timerBegin(0, 80, true); //初始化
timerAttachInterrupt(timer, &onTimer, true); //调用中断函数
timerAlarmWrite(timer, 1000000, true); //timerBegin的参数二 80位80MHZ,这里为1000000 意思为1秒
ledcSetup(channel, freq, resolution); // 设置通道
ledcAttachPin(led1, channel); // 将通道与对应的引脚连接
}
void loop()
{
key_value();
//显示本地时钟
if(state==0)
{
digitalWrite(led,!(led_state));
timerAlarmEnable(timer); //定时器使能
oled();
printLocalTime();//获取时间
}
//时钟设置界面
else if(state==1)
{
timerAlarmDisable(timer);
time_set();//设置时间
}
//时钟响应界面
else if(state==2)
{
timerAlarmEnable(timer); //定时器使能
oled_timer();
for (int d = 0; d <= 180; d +=180)
{
ledcWrite(channel, calculatePWM(d)); // 输出PWM
Serial.printf("value=%d,calcu=%d\n", d, calculatePWM(d));
delay(1000);
}
}
}
基于ESP32的实时时钟显示
最新推荐文章于 2025-06-11 16:14:25 发布