问题
您想在代码中使用当天的时间(小时,分钟和秒),而且您不想连接外部硬件。
解决方案
此代码使用Time库来显示当天的时间。可以使用Arduino库管理器安装Time库(如果您无法找到它,请尝试在Arduino库管理器中搜索“timekeeping”):
/*
* 时间示例
*/
#include <TimeLib.h>
void setup()
{
Serial.begin(9600);
setTime(12,0,0,1,1,2020); // 将时间设置为2020年1月1日中午12点
}
void loop()
{
digitalClockDisplay();
delay(1000);
}
// 使用前导0填充数字
String padDigits(int digit)
{
String str = String("0") digit; // 在数字前加0
return str.substring(str.length() - 2); // 删除除最后两个字符外的所有字符
}
void digitalClockDisplay(){
String timestr = String(hour()) ":" padDigits(minute()) ":" padDigits(second());
Serial.println(timestr);
String datestr = String(year()) "-" padDigits(month()) "-" padDigits(day());
Serial.println(datestr);
}
Time库使您能够跟踪日期和时间。许多Arduino板使用石英晶体进行计时,每天精度为几秒,但它没有电池来在断电时记忆时间。因此,每次启动程序时时间都会从0开始,因此您需要使用setTime函数设置时间。
该程序在每次启动时将时间设置为2020年1月1日中午12点。 Time库使用Unix时间标准(也称为POSIX时间或纪元时间)。这些值表示自1970年1月1日以来经过的秒数。有经验的C程序员可能会认识到,这与用于存储时间值的ISO标准C库中使用的time_t相同。
当然,将时间设置为您当前的本地时间而不是固定值更加有用。以下草图从串口获取数字时间值(自1970年1月1日以来经过的秒数),以设置时间。您可以使用串行监视器输入值(当前的Unix时间可以在许多网站上找到,包括Epoch Converter):
#include <TimeLib.h>
#define TIME_HEADER 'T' // 串行时间同步消息的头标签
void setup()
{
Serial.begin(9600);
Serial.println("Waiting for time sync message");
}
void loop()
{
if (Serial.available())
{
processSyncMessage();
}
if (timeStatus() != timeNotSet)
{
// 显示时间和日期
digitalClockDisplay();
}
delay(1000);
}
// 带前导零的数字填充
String padDigits(int digit)
{
String str = String("0") digit; // 在数字前面加上零
return str.substring(str.length() - 2); // 只保留最后两个字符
}
void digitalClockDisplay()
{
String timestr = String(hour()) ":" padDigits(minute())
":" padDigits(second());
Serial.println(timestr);
String datestr = String(year()) "-" padDigits(month())
"-" padDigits(day());
Serial.println(datestr);
}
// 解析时间消息
void processSyncMessage()
{
time_t pctime = 0;
if (Serial.find(TIME_HEADER))
{
pctime = Serial.parseInt();
setTime(pctime); // 将时钟设置为从串口接收到的时间
}
}
显示时间和日期的代码与以前相同,但现在草图等待从串口接收时间。
Time库示例中包含一个名为SyncArduinoClock的Processing Sketch(在Time/Examples/Processing/SyncArduinoClock文件夹中)。这个Processing Sketch可以在单击鼠标时将当前时间从计算机发送到Arduino。在Processing中运行SyncArduinoClock,确保串口是连接到Arduino的串口(第4章描述了如何运行与Arduino通信的Processing Sketch)。你应该会看到Arduino发送的消息“Waiting for time sync message”显示在Processing文本区域中(Processing IDE底部的黑色文本消息区域)。单击Processing应用程序窗口(它是一个200像素的灰色正方形),你应该可以看到Arduino Sketch打印的时间在文本区域中显示出来。
如果你可以获取当前的Unix时间,也可以通过串行监视器设置时钟;Epoch Converter是提供此格式时间的许多网站之一。确保你使用的转换器配置为微秒(至少为10位数字,直到2286年);如果配置为毫秒,则该数字将大1000倍。复制指示为当前Unix时间的10位数字,将其粘贴到串行监视器发送窗口中。在数字前加上字母T,然后单击“Send”。例如,如果你发送以下内容:
T1282041639
Arduino应该会每秒显示时间:
10:40:49 17 8 2019
10:40:50 17 8 2019
10:40:51 17 8 2019
10:40:52 17 8 2019
10:40:53 17 8 2019
10:40:54 17 8 2019
. . .
你也可以使用按钮或其他输入设备(如倾斜传感器、操纵杆或旋转编码器)来设置时间。
以下草图使用两个按钮向前或向后移动时钟的“指针”。下图显示了连接方式:
/*
AdjustClockTime sketch
buttons on pins 2 and 3 adjust the time
*/
#include <TimeLib.h>
const int btnForward = 2; // 按钮向前移动时间
const int btnBack = 3; // 按钮向后移动时间
unsigned long prevtime; // 上次显示时钟的时间
void setup()
{
pinMode(btnForward, INPUT_PULLUP); // 启用内部上拉电阻
pinMode(btnBack, INPUT_PULLUP);
setTime(12, 0, 0, 1, 1, 2020); // 开始时间设置为2020年1月1日中午12点
Serial.begin(9600);
}
void loop()
{
prevtime = now(); // 记录时间
while (prevtime == now()) // 一直在这个循环中直到秒数改变
{
// 检查是否在等待秒数翻转时按下设置按钮
if (checkSetTime())
prevtime = now(); // 时间已改变,重置开始时间
}
digitalClockDisplay();
}
// 函数检查是否应调整时间
// 如果时间已更改,则返回true
bool checkSetTime()
{
int step; // 要移动的秒数(如果为负数,则向后移动)
bool isTimeAdjusted = false; // 如果已调整时间,则设置为true
step = 1; // 准备向前移动
while (digitalRead(btnForward) == LOW)
{
adjustTime(step);
isTimeAdjusted = true; // 告诉用户时间已更改
step = step 1; // 下一步将更大
digitalClockDisplay(); // 更新时钟
delay(100);
}
step = -1; // 负数向后移动
while (digitalRead(btnBack) == LOW)
{
adjustTime(step);
isTimeAdjusted = true; // 告诉用户时间已更改
step = step - 1; // 下一步将更大的负数
digitalClockDisplay(); // 更新时钟
delay(100);
}
return isTimeAdjusted; // 告诉用户是否已调整时间
}
// 使用前导0填充数字
String padDigits(int digit)
{
String str = String("0") digit; // 在数字前面加上0
return str.substring(str.length() - 2); // 删除所有但最后两个字符
}
void digitalClockDisplay()
{
String timestr = String(hour()) ":" padDigits(minute())
12.4 Using Arduino as a Clock | 459
":" padDigits(second());
Serial.println(timestr);
String datestr = String(year()) "-" padDigits(month())
"-" padDigits(day());
Serial.println(datestr);
}
上图使用两个按钮调整时间。
这个示例使用到上面定义的digitalClockDisplay和printDigits函数,因此在运行此示例之前请先复制这些函数。 这是一个变种,它使用可变电阻的位置来确定在按下开关时调整时间的方向和速率:
#include <TimeLib.h>
const int potPin = A0; // 用于确定方向和速度的电位器
const int buttonPin = 2; // 按钮启用时间调整
unsigned long prevtime; // 上次显示时钟的时间
void setup()
{
digitalWrite(buttonPin, HIGH); // 启用内部上拉电阻
setTime(12, 0, 0, 1, 1, 2020); // 从2020年1月1日中午12点开始
Serial.begin(9600);
}
void loop()
{
prevtime = now(); // 记录时间
while (prevtime == now()) // 一直循环,直到秒数变化
{
// 检查是否在等待秒数翻转期间按下设置按钮
if (checkSetTime())
prevtime = now(); // 时间已经改变,重置起始时间
}
digitalClockDisplay();
}
// 函数用于检查是否应该调整时间
// 如果时间已经改变则返回true
bool checkSetTime()
{
int value; // 从电位器读取的值
int step; // 要移动的秒数(如果是负数则向后移动)
bool isTimeAdjusted = false; // 如果时间已经调整则设置为true
while (digitalRead(buttonPin) == LOW)
{
// 按钮按下时执行此处代码
value = analogRead(potPin); // 读取电位器的值
step = map(value, 0, 1023, 10, -10); // 将值映射到所需范围
if (step != 0)
{
adjustTime(step);
isTimeAdjusted = true; // 告诉用户时间已经改变
digitalClockDisplay(); // 更新时钟
delay(100);
}
}
return isTimeAdjusted;
}
下图显示了可变电阻和开关的连接方式。如果您使用的是不支持5伏特的3.3伏特板,请将可变电阻的正极连接到3.3V而不是5V。 所有这些示例都打印到串行端口,但您也可以将输出打印到LED或LCD上。在12.9节中涵盖的图形LCD的下载包含了使用在LCD上绘制的模拟时钟显示来显示和设置时间的示例。Time库包含方便的函数,用于将各种时间格式进行转换。例如,您可以找出从一天开始已经过去了多少时间,以及到当天结束还有多少时间。
个可变电阻用于调节时间
你可以查看位于libraries文件夹中的TimeLib.h获取完整的函数列表。
dayOfWeek(now()); //返回星期几(星期日为第1天)
elapsedSecsToday(now()); //返回从今天开始到现在经过的秒数
nextMidnight(now()); //距离今天结束还有多少时间
elapsedSecsThisWeek(now()); //从本周开始到现在经过的时间
你也可以打印出星期和月份的文本字符串。以下是一种基于数字时钟显示代码的变体,它打印出星期和月份的名称:
void digitalClockDisplay()
{
String timestr = String(hour()) ":" padDigits(minute())
":" padDigits(second());
Serial.println(timestr);
String datestr = String(dayStr(weekday())) ", "
String(monthShortStr(month())) " " String(year());
Serial.println(datestr);
}
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved