Программирование Arduino с добавлением задержки в миллисекундах - PullRequest
0 голосов
/ 17 декабря 2018

Итак, я пытаюсь создать устройство учета электроэнергии, которое будет считывать мощность каждую минуту, а затем отправлять его каждые 5 минут через сервер LoRa, используя Arduino MKR 1300.Проблема заключается в том, что на данный момент аппаратное обеспечение удаляет задержку на несколько миллисекунд, и поэтому время на сервере заканчивается как:

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 голосов
/ 17 декабря 2018

Вместо того, чтобы пытаться измерить время начала и добавить задержку в зависимости от этого, вы можете отслеживать время для вашего следующего цикла.

unsigned long next_cycle = DELAY;

...

void loop() {
    ...

    delay( next_cycle - millis() );
    next_cycle += DELAY;
}

Если вы также хотите настроить программу в любое времятратит на инициализацию или подобное, вы можете next_cycle = millis() + DELAY;, прежде чем войти в ваш цикл.

0 голосов
/ 17 декабря 2018

Вопрос в том, насколько точны ваши часы вообще ...

Тем не менее, я лично предпочел бы использовать следующий подход:

#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...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...