我正在为 Arduino 编写一个定时器/调度程序简单程序。
这是一个 C 程序,带有一次又一次运行的“主”循环。 Arduino 连接有 DS3231 RTC 模块,提供当前星期几、小时、分钟、秒等。
我需要实现的是通过串行端口发送特定的字符串,但与许多有关“在特定时间点亮 LED”的示例相比 - 我不能允许代码运行多次。 因此,如果正常的“在特定时间点亮 LED”只是一次又一次循环“if”检查,并根据它设置数字输出“高”或“低”(一次又一次) - 我无法使用这种方法。
我现在使用的并且有效的方法是这样的: 我用想要的时间和每次的“操作代码”创建了一个数组 - 它们都是整数,如下所示:
const int A = 6; // Action Array Size
int ActionTimes[A][4] = {
{6,18,37,1},
{6,18,38,2},
{5,15,20,11},
{5,16,35,51},
{5,16,40,52},
{5,23,55,15}
};
然后,从主循环中,我调用一个“Check”函数,该函数运行一个“for”循环来检查是否存在应在当前时间运行的操作:
int i;
for ( i = 0; i < A; i++ ) {
if ((dt.DayOfWeek()==ActionTimes[i][0]) && (dt.Hour()==ActionTimes[i][1]) && (dt.Minute()==ActionTimes[i][2]) && (dt.Second() < 2)) {
RunMyAction(ActionTimes[i][3]);
}
然后 - 我有“action”函数来运行实际需要的代码,如下所示:
void RunMyAction(const int& MyActionCode)
{
switch(MyActionCode) {
case 1:
digitalWrite(2, LOW); // Turn the LED on by making the voltage LOW
Serial.println("S041ONE");
break;
case 2:
digitalWrite(2, HIGH); // Turn the LED off by making the voltage HIGH
Serial.println("S017ONE");
break;
case 11: //Before Knissat Shabat - Full status update.
Serial.println("S01D00000D00ES02D01001100ES03D00101101ES04D1100D0DDES05D10011DDDE");
delay(1000);
break;
case 15: //Last GoodNight Shabat - Full status update.
Serial.println("S01D00000000ES02D00000000ES03D00000100ES04D1000D00DES05D00011DDDE");
delay(1500);
break;
case 51:
Serial.println("S036OFE");
delay(1500);
break;
case 52:
Serial.println("S047OFES036ONE");
delay(1500);
break;
}
}
这对我有用并且“完成工作”,但我觉得(从算法上来说)也许这不是最好的编写方式。
例如 - 所有操作和所需时间都硬编码到程序本身中。对于任何添加的操作 - 我必须手动更改数组大小的常量,手动更改数组定义,并向 switch 函数添加其他代码。
(考虑过用excel制作的#include文件合并到数组部分和switch函数中,但这也必须为每次/ Action 更改重新编译程序)。
对于如何以更专业、更有效的方式看待它的任何见解,我们将不胜感激。
非常感谢!
最佳答案
为了避免连续执行相同的操作两次,我添加一个全局变量来保存最近执行的操作的 ActionTImes[] 中的索引,然后在 if 语句中测试该变量。
int latestActionIndex = -1; // -1 so on startup we don't think we've executed ActionTimes[0].
然后在 For 循环中:
if ((dt.DayOfWeek()==ActionTimes[i][0])
&& (dt.Hour()==ActionTimes[i][1])
&& (dt.Minute()==ActionTimes[i][2]
&& latestActionIndex != i)) {
latestActionIndex = i; // note that we've run this action
RunMyAction(ActionTimes[i][3]);
}
我从 if 语句中删除了 (dt.Second() < 2),因为该操作可能会在 dt.second() == 0 的一秒左右内执行,并且新变量使 RunMyAction() 无法执行被多次处决。
关于c - 寻找好的算法在给定时间运行特定代码。 (Arduino C 程序),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59521598/