因此,我正在尝试创建一个电度表设备,该设备将每分钟读取一次电能,然后使用MKR 1300 arduino每隔5分钟通过LoRa服务器发送一次电能。问题是,截至目前,硬件已将延迟减少了几毫秒,因此服务器中的时间最终变为p.e:
10:50:30
10:50:30
10:50:30
... 2小时后
10:50:29
10:50:29
...
10:49:59
代码如下:
#include <MKRWAN.h>
#include "EmonLib.h"
LoRaModem modem;
String appEui = "1234567891011121";
String appKey = "ffffffffffffffffffffffffffffffff";
EnergyMonitor emon1;
EnergyMonitor emon2;
EnergyMonitor emon3;
double totalWatt;
int time_running;
int sending;
int totalKW;
int DELAY = 60000; // millis
void setup() {
Serial.begin(115200);
if (!modem.begin(EU868)) {
Serial.println("Failed to start module");
while (1) {}
};
Serial.print("Your module version is: ");
Serial.println(modem.version());
Serial.print("Your device EUI is: ");
Serial.println(modem.deviceEUI());
Serial.println("Connecting");
int connected = modem.joinOTAA(appEui, appKey);
if (!connected) {
Serial.println("Something went wrong; are you indoor? Move near a window and retry");
while (1) {}
}
Serial.println("Connected");
modem.minPollInterval(60);
analogReadResolution(9);
emon1.current(1, 53);
emon2.current(2, 53);
emon3.current(3, 53);
time_running = 0;
randomSeed(analogRead(A4));
}
void loop() {
unsigned long StartTime = millis();
totalWatt = 0;
unsigned long delay_send = 0;
int sending = 0;
double Irms1 = emon1.calcIrms(600);
if (Irms1 < 0.3) Irms1 = 0;
double Watt1 = Irms1 * 230;
double Irms2 = emon2.calcIrms(600);
if (Irms2 < 0.3) Irms2 = 0;
double Watt2 = Irms2 * 230;
double Irms3 = emon3.calcIrms(600);
if (Irms3 < 0.3) Irms3 = 0;
double Watt3 = Irms3 * 230;
totalWatt = Watt1 + Watt2 + Watt3;
totalKW = totalKW + totalWatt/1000;
if (time_running == 5) { //15 para 15 mins
double IrmsTotal = Irms1 +Irms2 + Irms3;
String msg = "{\"id\":\"avac_aud1\",\"kW\":"+String(totalKW)+", \"current\":"+String(IrmsTotal)+"}";
int err;
modem.beginPacket();
modem.print(msg);
err = modem.endPacket(true);
if (err > 0) {
//message sent correctly
time_running = 0;
totalKW = 0;
} else {
Serial.println("ERR");
time_running = 0;
}
}
time_running = time_running + 1;
if ((millis() - StartTime) > DELAY){
delay(10);
return;
} else{
delay(DELAY-(millis() - StartTime));
return;
}
}
我尝试在代码中添加变量ARD_DELAY(上面未显示),以使最后的延迟会减去7到8毫秒来尝试解决此问题,但显然,这只会使情况变得更糟(现在每1秒删除1秒)小时,而不是2小时),所以今天我将尝试将这7到8毫秒相加,看看是否有效,但是我真的想知道为什么会发生这种情况,因为从我的代码中可以看到,延迟应该始终考虑处理时间,包括数据发送时间。
答案 0 :(得分:2)
问题是,您的时钟到底有多精确...
不过,我个人还是希望采用以下方法:
#define DELAY (5UL * 60UL * 1000UL) // or whatever is appropriate...
static unsigned long timestamp = millis();
if(millis() - timestamp > DELAY)
{
// adding a fix constant will prevent accumulating deviations over time
timestamp += DELAY;
// run the every-5-min task...
}
编辑:1分钟和5分钟的组合任务:
变种1:
#define DELAY_SHORT (1UL * 60UL * 1000UL)
#define DELAY_LONG (5UL * 60UL * 1000UL)
static unsigned long timestampS = millis();
static unsigned long timestampL = timestampS;
if(millis() - timestampS > DELAY_SHORT)
{
timestamp += DELAY_SHORT;
// run the every-1-min task...
}
if(millis() - timestampL > DELAY_LONG)
{
timestamp += DELAY_LONG;
// run the every-5-min task...
}
变种2:
#define DELAY_1M (1UL * 60UL * 1000UL)
static unsigned long timestamp = millis();
if(millis() - timestamp > DELAY)
{
// adding a fix constant will prevent accumulating deviations over time
timestamp += DELAY;
// run the every-1-min task...
static unsigned int counter = 0;
if(++counter == 5)
{
counter = 0;
// run the every-5-min task...
}
}
答案 1 :(得分:1)
您可以跟踪下一个周期的时间,而不必尝试测量开始时间并据此增加延迟。
unsigned long next_cycle = DELAY;
...
void loop() {
...
delay( next_cycle - millis() );
next_cycle += DELAY;
}
如果您还想在程序用于初始化或类似操作的任何时间进行调整,则可以next_cycle = millis() + DELAY;
,然后进入循环。