Arduino-UNO. WatchDog

Здравствуйте!
Бывает так, что программа зависает (подвисает) или наоборот - строки 22,23 отрабатывают с огромной скоростью.
Похоже, что портится переменная moment. (Скетч1)
Почему она портится - задам вопрос в новой теме, где выложу полный скетч.

Скетч1
bool trigger;
int st;

void setup()
{
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  static uint32_t period = 500;
  static uint32_t moment;

  if (millis() - moment >= period)
  {
    moment = moment + period; // благословенная строка
    trigger = !trigger;
    // далее бывает вот что:
    // 1. диод мерцает, вывод в порт с огромной скоростью
    // 2. диод светится или погашен, вывода в порт НЕТ
    digitalWrite(13, trigger);
    Serial.println(st);
  }
}

Так вот. Если по какой-то причине программа зависла, то с помощью WatchDog легко организоавать ее перезагрузку.
А можно ли организовать перезагрузку следующим образом (Скетч2), если строки 22,23 отрабатывают с огромной скоростью?

Скетч2
#include <avr/wdt.h>

bool trigger;
int st;
unsigned long t1, t2;
bool flag = true; // разрешается wdt_reset()

void setup()
{

  pinMode(13, OUTPUT);
  Serial.begin(9600);

  t1 = millis();
  t2 = t1 + 5000;

  wdt_enable (WDTO_8S);
}

int timer = 0;

void loop()
{
  static uint32_t period = 500;
  static uint32_t moment;

  if (millis() - moment >= period)
  {
    moment = moment + period; // благословенная строка
    trigger = !trigger;

    // далее бывает вот что:
    // 1. диод мерцает, вывод в порт с огромной скоростью
    // 2. диод светится или погашен, вывода в порт НЕТ
    digitalWrite(13, trigger);
    Serial.println(st);

    // определение времени между соседними проходами
    t2 = millis();
    if (t2 - t1 < 250) // если это время меньше period, запрет wdt_reset()
    {
      flag = false;
    }
    else
    {
      t1 = millis(); // все нормально
    }

    if (flag)
    {
      wdt_reset();
    }
  }
}

Спасибо!

если у вас “испортился миллис” в одном месте, почему вы думаете, что он будет продолжать работать в другом?

Для меня это что-то новое.
А почему millis() может портиться?

А точно он портится?

1 лайк

MMM такое не исключает. #2.

If the transmit buffer is full then Serial.write() will block until there is enough space in the buffer.

Легко можно представить себе как именно приведенная в первопосте программа поведет себя так как описано если сперва забьёт буфер серийного порта и замрёт на Serial.println, а когда связь возобновится начнёт “частить” догоняя миллисы в каждой итерации в ускоренном темпе.
В таких вещах дьяволы в деталях любят прятаться.

Похоже, что МММ прав. millis() портится скорре всего из-за того, что эта схема собрана на макетной плате с использованием проводов, у некоторых папа тонкий и мама широкая.
В течение 3-4-х часов на Master не общается с ESP, не общается со Slave.
И начинает вести себя так, что millis() прыгает в соторону переполнения, тогда moment=moment+period; пытается его догнать, и вывод в порт с огромной скоростью. Либо наоборот: millis() прыгает в соторону нуля. В этом случае программа под это условие не заходит. Спасает только WatchDog.

вынеси в глобальные и сделай волатильной, может в этом дело?

1 лайк

Когда в глобальных было: unsigned long moment; была такая же поблема.
Затем в глобальных я сделал так: static uint32_t moment;, сказали, что такт НЕЛЬЗЯ. Что это надо писать в loop().

3-4 часа работает без общения с ESP, без общения со Slave. И потом начинается. Что за это время может испортится - не знаю. Говорят, что радиоэлектроника - наука о контактах. Все-таки, наука о “соплях”.

Вопрос решен.