Arduino编程增加毫秒延迟

时间:2018-12-17 11:04:48

标签: c++ arduino

因此,我正在尝试创建一个电度表设备,该设备将每分钟读取一次电能,然后使用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毫秒相加,看看是否有效,但是我真的想知道为什么会发生这种情况,因为从我的代码中可以看到,延迟应该始终考虑处理时间,包括数据发送时间。

2 个答案:

答案 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;,然后进入循环。