Прошу помощи в отладке Arduino Mega 2560

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

ну и если есть время отдельно можно скорость порта увеличить… так как на уровне атомов я не знаю как работает программа))) но это более логичная причина не работы с монитором порта на мой взгляд…

Serial.begin(9600)

имеете в виду?

да, и более 115200 сделать вроде можно… а то и это мне кажется маловато…
так сразу не помню… это вообще маленькие скорости… можно наверняка еще поднять, или остановитесь на значении 115200

Ну,… судя по всему - код ушёл пока из подозрений.
Так что, по части теста кода- навертное, закончили.
А мои “тесты” вообще… - что-то я не вижу пока конца.

Наверное, всё же - при нормальной схемотехнике - оборудование должно успешно работать как при записи лога в “серийный порт”, так и без этой записи. Насколько я понимаю.
И если это действительно так - то для меня даже лучше, что ошибка прилетает быстро. Не надо долго ждать наблюдать и её выслеживать.
А вот если это взаимоисключающее - что от того, выводится ли лог в “серийный порт”, - происходит нарушение работы всей схемы. Вот в этом случае тогда, возможно - следует увеличивать скорость передачи… наверное.
Сплошные сомнения, в общем.

Похоже, “толстый” прав…
Я пока фото этой платы повнимательнее посмотрел


получается - что +5V от микроконтроллера проходит через резистор, потом через оптрон, потом через светодиод - и уходит на пин микроконтроллера… и действительно - реле управляется низким уровнем… и действительно, по логике тогда - GND вообще не должен в этой ситуации приходить от контроллера на плату реле!
Дома ещё раз уточню повнимательнее… но если я всё правильно понял - ничего резать на модуле реле - не нужно.

Пришёл домой, осмотрел с фонариком дорожки на модуле реле - и пришёл к выводу, что “толстый” был прав - не нужно при моём подключении соединять GND микроконтроллера и модуля реле. Полностью удалил проводок, соединявший ранее GND между Ардуиной и платой реле. Теперь блок питания Ардуины никак не связан с блоком питания всего остального. Оплётку (экран) провода от водомера и витой пары от датчиков температур - посадил на жёлто-зелёный провод.
Схема теперь получилась такая:

Спойлер

Загрузил в контроллер такой код

Спойлер
/*
   ПРОГРАММА ДЛЯ МОНИТОРИНГА ТЕПЛОВОГО НАСОСА
   ФИНАЛЬНАЯ ВЕРСИЯ СО ВСЕМИ ИСПРАВЛЕНИЯМИ
*/

// ========== 1. ПОДКЛЮЧАЕМ БИБЛИОТЕКИ ==========
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#include <OneWire.h>
OneWire ds(21);

// ========== 2. НАСТРОЙКИ ПИНОВ ДЛЯ ДИСПЛЕЯ ==========
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

// ========== 3. ЗАДАЁМ ЦВЕТА ==========
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define WHITEGREY  0xC638
#define DARKGREY  0x7BEF
#define DARKGREEN 0x0C80

// ========== 4. ПИНЫ ДЛЯ СЧЁТЧИКОВ ==========
#define pinVoda_tick   18
boolean stateCheck_voda;

#define pinElectr_tick  19
boolean stateCheck_electr;

// ========== 5. ПЕРЕМЕННАЯ ДЛЯ УПРАВЛЕНИЯ РЕЛЕ ==========
uint8_t relay;

// ========== 6. АДРЕСА ДАТЧИКОВ ТЕМПЕРАТУРЫ ==========
byte ADDR_DS18B20 [6][8] = {
  {0x28, 0xD5, 0x97, 0x76, 0x0, 0x0, 0x0, 0x76},
  {0x28, 0x4F, 0x9C, 0x73, 0x0, 0x0, 0x0, 0xF9},
  {0x28, 0xFC, 0xD1, 0x72, 0x0, 0x0, 0x0, 0x2D},
  {0x28, 0x95, 0x28, 0x75, 0x0, 0x0, 0x0, 0xAB},
  {0x28, 0xEF, 0x8C, 0x76, 0x0, 0x0, 0x0, 0x58},
  {0x28, 0x8C, 0x3A, 0xB4, 0xE, 0x0, 0x0, 0xDB}
};

// ========== 7. МАССИВЫ ДЛЯ ГРАФИКОВ ==========
uint8_t tIsparitel[320];
uint8_t tOverheat[320];
uint8_t tKompressor[320];
uint8_t tWaterIn[320];
uint8_t tWaterOut[320];
uint8_t tDefrost[320];
uint8_t heatPower[320];
uint8_t gWater[320];
uint8_t ElectrPow[320];
uint8_t COP[320];

// ========== 8. ТОЧНЫЕ ЗНАЧЕНИЯ ==========
int16_t tOverheatReal;
int32_t gWaterReal;
int32_t heatPowerReal;
int32_t ElectrPowReal;
int32_t COPreal;

int32_t gWaterRealPrew;
boolean FlagWater = false;
boolean FirstImpulsWater = false;
boolean SecondImpulsWater = false;

// ========== 9. СРЕДНИЕ ЗНАЧЕНИЯ ==========
int32_t countHeatAndElectr = 0;
int32_t countHeat = 0;
int32_t countElectr = 0;

// ========== 10. ФЛАГИ ЦИКЛА ==========
boolean Flag1 = true;
boolean Flag2 = true;
boolean Flag3 = true;
boolean Flag4 = true;
uint8_t countGetGrafic = 9;
uint32_t Timer;

// ========== 11. МАССИВЫ ДЛЯ ГРАФИКОВ СОСТОЯНИЯ РЕЛЕ ==========
int16_t trend_fan[20];
int16_t trend_kompressor[20];
int16_t trend_pump[20];
int16_t trend_4way_valve[20];

// ========== 12. ПЕРЕМЕННЫЕ ДЛЯ РАСХОДОМЕРА ВОДЫ ==========
uint32_t tmr;
boolean gWaterFlag = false;
uint32_t WaterStartTimer = 0;
uint32_t WaterCountTimer;

// ========== 13. ПЕРЕМЕННЫЕ ДЛЯ ЭЛЕКТРОСЧЁТЧИКА ==========
uint32_t tmr2;
boolean ElectrFlag = false;
uint32_t ElectrStartTimer = 0;
uint32_t ElectrCountTimer;

// ========== 14. ФЛАГИ РЕЖИМОВ РАБОТЫ ==========
boolean StartHeatFlag;
boolean StopFlag;
boolean HeatOptionFlag;
boolean HeatOptionPauseFlag;
boolean DefrostOptionFlag;

// ========== 15. СЧЁТЧИКИ ДЛЯ ЗАЩИТЫ ==========
uint8_t tKompressorCounter = 0;
uint8_t HeatOptionCout = 0;
uint8_t HeatOptionPauseCout = 0;
uint8_t defrostCount = 0;
uint8_t StopMaxTemp = 0;
uint8_t StopMaxElectr = 0;
uint8_t StopMinTempHeater = 0;
uint8_t StopNo4xvalve = 0;
uint8_t StopNoElectric = 0;

uint8_t StopKind = 0;
uint8_t MistakeTemp[6] = {};
boolean getMistakeFlag = false;

// ========== 16. ВРЕМЕННЫЕ МЕТКИ ==========
uint32_t HeatOptionPauseStartTime;
uint32_t StartHeatTime;
uint32_t StopTime;
uint32_t DefrostTime;

// ========== 17. МАССИВЫ ТЕМПЕРАТУР ==========
int16_t Temper[6] = {0, 0, 0, 0, 0, 0};
int16_t TemperPrev[6];

// ========== 18. ФУНКЦИЯ ПРОВЕРКИ CRC ==========
uint8_t dallas_crc8(const uint8_t *data, uint8_t len) {
  uint8_t crc = 0;
  for (uint8_t i = 0; i < len; i++) {
    uint8_t inbyte = data[i];
    for (uint8_t j = 0; j < 8; j++) {
      uint8_t mix = (crc ^ inbyte) & 0x01;
      crc >>= 1;
      if (mix) crc ^= 0x8C;
      inbyte >>= 1;
    }
  }
  return crc;
}

// ========== 19. ФУНКЦИЯ ЧТЕНИЯ ТЕМПЕРАТУРЫ С ДАТЧИКА (ИСПРАВЛЕНО) ==========
bool readDS18B20(byte *addr, int16_t *dest) {
  uint8_t data[9];
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);
  for (uint8_t i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
  if (dallas_crc8(data, 8) != data[8]) {
    return false;
  }
  int16_t raw = (int16_t)((data[1] << 8) | data[0]);
  *dest = (raw * 5) / 8;  // Правильная формула (работает с отрицательными)
  return true;
}

// ========== 20. ФУНКЦИЯ ЗАПУСКА ИЗМЕРЕНИЯ ТЕМПЕРАТУРЫ ==========
void resetTemp() {
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
}

// ========== 21. ФУНКЦИЯ ПОЛУЧЕНИЯ ТЕМПЕРАТУР ==========
void gettingTemp() {
  int16_t temp;
  for (uint8_t i = 0; i < 6; i++) {
    if (readDS18B20(ADDR_DS18B20[i], &temp)) {
      // CRC прошёл — данные достоверны
      Temper[i] = temp;
      TemperPrev[i] = temp;
      if (MistakeTemp[i] <= 6) MistakeTemp[i] = 0;
    } else {
      // CRC не прошёл — это ошибка!
      // Temper[i] не меняем (остаётся предыдущее значение)
      if (StopFlag == false) {
        MistakeTemp[i]++;
        if (MistakeTemp[i] > 6) {
          StopFlag = true;
          StopTime = millis();
          StopKind = 6;
        }
      }
    }
  }
}

// ========== 22. ПРОВЕРКА ГРАНИЦ ТЕМПЕРАТУР (ИСПРАВЛЕНО) ==========
void tempMistake(uint8_t a, int16_t b, int16_t c, int16_t d) {
  // Если значение в норме — сбрасываем счётчик ошибок
  if (Temper[a] >= b && Temper[a] <= c && abs(Temper[a] - TemperPrev[a]) <= d) {
    MistakeTemp[a] = 0;
    return;
  }

  // Ошибка! Откатываем на предыдущее значение
  Temper[a] = TemperPrev[a];

  if (StopFlag == false) {
    MistakeTemp[a]++;

    if (MistakeTemp[a] > 6) {
      StopFlag = true;
      StopTime = millis();
      StopKind = 6;
    }
  }
}

// ========== 23. ОБРАБОТЧИК ИМПУЛЬСОВ СЧЁТЧИКА ВОДЫ (ИСПРАВЛЕНО) ==========
void voda_tick() {
  //Serial.print("proverka");
  boolean current_status = digitalRead(pinVoda_tick);
  if (stateCheck_voda && !current_status) {
    tmr = millis();
    gWaterFlag = true;
    stateCheck_voda = current_status;
    return;
  }
  if (!stateCheck_voda && current_status) {
    stateCheck_voda = current_status;
    return;
  }
  if (current_status) {
    gWaterFlag = false;
    return;
  }
  if (!current_status && (millis() - tmr >= 1000) && gWaterFlag == true) {
    if (WaterStartTimer == 0) {
      WaterStartTimer = millis();
      gWaterFlag = false;
      return;
    }
    WaterCountTimer = millis() - WaterStartTimer;
    WaterStartTimer = millis();
    gWaterFlag = false;
    if (FirstImpulsWater == true) SecondImpulsWater = true;
    FirstImpulsWater = true;
  }
}

// ========== 24. ОБРАБОТЧИК ИМПУЛЬСОВ ЭЛЕКТРОСЧЁТЧИКА (ИСПРАВЛЕНО) ==========
void electr_tick() {
  //Serial.println("proverka");
  boolean current_status = digitalRead(pinElectr_tick);
  if (stateCheck_electr && !current_status) {
    tmr2 = millis();
    ElectrFlag = true;
    stateCheck_electr = current_status;
    return;
  }
  if (!stateCheck_electr && current_status) {
    stateCheck_electr = current_status;
    return;
  }
  if (current_status) {
    ElectrFlag = false;
    return;
  }
  if (!current_status && (millis() - tmr2 >= 50) && ElectrFlag == true) {
    if (ElectrStartTimer == 0) {
      ElectrStartTimer = millis();
      ElectrFlag = false;
      return;
    }
    ElectrCountTimer = millis() - ElectrStartTimer;
    ElectrStartTimer = millis();
    ElectrFlag = false;
  }
}

// ========== 25. ФУНКЦИИ ВЫВОДА ЧИСЕЛ НА ДИСПЛЕЙ ==========
void getDataInt100(int16_t a) {
  //Serial.println("proverka");
  if (a >= -9 && a < 0) {
    tft.print("-0.0"); tft.print(abs(a));
  } else if (a < 9 && a >= 0) {
    tft.print("0.0"); tft.print(a);
  } else if (a <= -10 && a > -100) {
    tft.print("-0."); tft.print(abs(a % 100));
  } else {
    tft.print(a / 100); tft.print(".");
    if (abs(a % 100) < 10) tft.print("0");
    tft.print(abs(a % 100));
  }
}

void getDataInt10(int16_t a) {
  if (a >= -9 && a < 0) {
    tft.print("-0."); tft.print(abs(a));
  } else if (a < 9 && a >= 0) {
    tft.print("0."); tft.print(a);
  } else {
    tft.print(a / 10); tft.print(".");
    tft.print(abs(a % 10));
  }
}

// ========== 26. ПРЕОБРАЗОВАНИЕ ЧИСЕЛ ДЛЯ ГРАФИКА ==========
int16_t getDataForUintMassiv(int16_t a) {
  //Serial.println("proverka");
  int16_t LastInMassive;
  if (a < -400) LastInMassive = 0;
  else if (a >= -400 && a < 500) LastInMassive = round((a + 400) / 5);
  else if (a >= 500 && a < 1250) LastInMassive = round(180 + (a - 500) / 10);
  else LastInMassive = 255;
  return LastInMassive;
}

int32_t getDataForUintMassiv32(int32_t a) {
  int32_t LastInMassive;
  if (a < -400) LastInMassive = 0;
  else if (a >= -400 && a < 0) LastInMassive = round((a + 400) / 10);
  else if (a >= 0 && a <= 160) LastInMassive = round(40 + a);
  else if (a > 160 && a < 710) LastInMassive = round(200 + (a - 160) / 10);
  else LastInMassive = 255;
  return LastInMassive;
}

// ========== 27. ОТРИСОВКА ГРАФИКОВ ==========
void getGraphics(uint16_t c, uint16_t d, uint8_t g[320]) {
  //Serial.println("proverka");
  int16_t oldX = 0;
  int16_t oldY = g[0];
  for (int16_t x = 1; x < 320; x++) {
    int16_t nxt_x = x;
    tft.drawLine(oldX, (c - oldY), nxt_x, (c - g[x]), d);
    oldY = g[x];
    oldX = nxt_x;
  }
}

// ========== 28. ОТРИСОВКА ВСЕГО ЭКРАНА ==========
void getMainDisplay() {
  //Serial.println("proverka");
  tft.fillScreen(BLACK);

  for (uint8_t i = 1; i < 8; i++) {
    tft.drawFastVLine((40 * i), 20, 190, DARKGREY);
    tft.drawFastVLine((40 * i), 230, 210, DARKGREY);
  }

  for (uint8_t i = 0; i < 11; i++) {
    if (i == 4 || i == 5 || i == 6 || i == 7 || i == 9 || i == 10)
      tft.drawFastHLine(0, (5 + 20 * i), 320, DARKGREEN);
    else if (i == 1 || i == 2 || i == 3 || i == 8)
      tft.drawFastHLine(0, (5 + 20 * i), 320, BLUE);
  }

  for (uint8_t i = 0; i < 5; i++)
    tft.drawFastHLine(0, (231 + 10 * i), 320, BLUE);

  tft.drawFastHLine(0, 275, 320, BLUE);

  for (uint8_t i = 0; i < 8; i++)
    tft.drawFastHLine(0, (295 + 20 * i), 320, DARKGREEN);

  tft.setTextSize(1);

  tft.setCursor(0, 22); tft.setTextColor(WHITE, BLACK); tft.print("90");
  tft.setCursor(0, 42); tft.print("70");
  tft.setCursor(0, 62); tft.print("50");
  tft.setCursor(0, 82); tft.print("40");
  tft.setCursor(0, 102); tft.print("30");
  tft.setCursor(0, 122); tft.print("20");
  tft.setCursor(0, 142); tft.print("10");
  tft.setCursor(0, 162); tft.print("0");
  tft.setCursor(0, 182); tft.print("-10");
  tft.setCursor(0, 202); tft.print("-20");

  tft.setCursor(0, 238); tft.print("5");
  tft.setCursor(0, 258); tft.print("3");
  tft.setCursor(0, 272); tft.print("1.6");
  tft.setCursor(0, 292); tft.print("1.4");
  tft.setCursor(0, 312); tft.print("1.2");
  tft.setCursor(0, 332); tft.print("1");
  tft.setCursor(0, 352); tft.print("0.8");
  tft.setCursor(0, 372); tft.print("0.6");
  tft.setCursor(0, 392); tft.print("0.4");
  tft.setCursor(0, 412); tft.print("0.2");
  tft.setCursor(0, 432); tft.print("0");

  tft.setCursor(0, 0); tft.setTextColor(RED); tft.print("Kompressor:");
  tft.setCursor(10, 10); tft.setTextColor(MAGENTA); tft.print("Overheat:");
  tft.setCursor(125, 10); tft.setTextColor(CYAN); tft.print("Defrost:");
  tft.setCursor(220, 10); tft.setTextColor(RED); tft.print("Isparitel:");
  tft.setCursor(120, 0); tft.setTextColor(YELLOW); tft.print("Water in:");
  tft.setCursor(220, 0); tft.setTextColor(GREEN); tft.print("Water out:");
  tft.setCursor(5, 210); tft.setTextColor(RED); tft.print("Heat power:");
  tft.setCursor(152, 210); tft.setTextColor(YELLOW); tft.print("COP:");
  tft.setCursor(218, 210); tft.setTextColor(GREEN); tft.print("Electr pow:");
  tft.setCursor(22, 220); tft.setTextColor(MAGENTA); tft.print("G water:");
}

// ========== 29. НАЧАЛЬНАЯ НАСТРОЙКА ==========
void setup() {
  Serial.begin(9600);
  //Serial.println("proverka");

  tft.reset();
  tft.begin(38022);
  tft.invertDisplay(true);

  pinMode(18, INPUT_PULLUP);
  stateCheck_voda = digitalRead(pinVoda_tick);

  pinMode(19, INPUT_PULLUP);
  stateCheck_electr = digitalRead(pinElectr_tick);

  for (int i = 0; i < 320; i++) {
    tIsparitel[i] = 80;
    tOverheat[i] = 80;
    tKompressor[i] = 80;
    tWaterIn[i] = 80;
    tWaterOut[i] = 80;
    tDefrost[i] = 80;
    heatPower[i] = 40;
    gWater[i] = 40;
    ElectrPow[i] = 40;
    COP[i] = 40;
  }

  pinMode(48, OUTPUT); digitalWrite(48, HIGH);
  pinMode(49, OUTPUT); digitalWrite(49, HIGH);
  pinMode(50, OUTPUT); digitalWrite(50, HIGH);
  pinMode(51, OUTPUT); digitalWrite(51, HIGH);

  StopFlag = false;
  HeatOptionFlag = false;
  HeatOptionPauseFlag = false;
  DefrostOptionFlag = false;
  StartHeatFlag = true;
  StartHeatTime = millis();
  Timer = millis();

  Serial.println("=== SETUP COMPLETE ===");
  delay(1000);
}

// ========== 30. ГЛАВНЫЙ ЦИКЛ ==========
void loop() {

  // ===== ДИАГНОСТИКА ВРЕМЕНИ =====
  Serial.print("lm=");
  Serial.print(millis());
  Serial.print(" T=");
  Serial.println(Timer);
  // ================================

  voda_tick();
  electr_tick();

  // Шаг 1: запуск конвертации (3-5 сек)
  if (millis() - Timer >= 3000 && millis() - Timer < 5000 && Flag1 == true) {
    Serial.println(">>> Step 1: resetTemp");
    //Serial.println("proverka");
    resetTemp();
    Flag1 = false;
  }

  // Шаг 2: чтение температур (5-7 сек)
  if (millis() - Timer >= 5000 && millis() - Timer < 7000 && Flag2 == true) {
    Serial.println(">>> Step 2: gettingTemp");
    Serial.println("proverka");
    gettingTemp();
    Flag2 = false;
  }

  // Шаг 3: расчёты и логика (7-9 сек)
  if (millis() - Timer >= 7000 && millis() - Timer < 9000 && Flag3 == true) {
    Serial.println(">>> Step 3 START");

    if (getMistakeFlag == false) {
      for (uint8_t i = 0; i < 6; i++) TemperPrev[i] = Temper[i];
      getMistakeFlag = true;
    }

    tempMistake(0, -100, 1200, 200);
    tempMistake(1, 0, 600, 100);
    tempMistake(2, 0, 900, 50);
    tempMistake(3, -400, 800, 400);
    tempMistake(4, -400, 600, 300);
    tempMistake(5, -400, 800, 200);

    tOverheatReal = (Temper[3] - Temper[5]);

    // Расход воды
    if (digitalRead(51) == HIGH) {
      gWaterReal = 0;
      gWaterRealPrew = gWaterReal;
      FlagWater = false;
    } else if (digitalRead(51) == LOW && millis() - WaterStartTimer > 400000) {
      StopFlag = true; StopTime = millis(); StopKind = 7;
    } else if (SecondImpulsWater == false) {
      gWaterReal = gWaterRealPrew; FlagWater = true;
    } else {
      gWaterReal = round(3600000 / WaterCountTimer);
      gWaterRealPrew = gWaterReal; FlagWater = false;
    }

    // Электрическая мощность
    if (millis() - ElectrStartTimer > 60000) ElectrPowReal = 0;
    else ElectrPowReal = 72000 / ElectrCountTimer;

    // Тепловая мощность и COP
    heatPowerReal = ((int32_t)Temper[2] - (int32_t)Temper[1]) * gWaterReal * 1163 / 10000;
    if (ElectrPowReal < 10) COPreal = 0;
    else COPreal = 100 * heatPowerReal / ElectrPowReal;

    countHeat = countHeat + heatPowerReal;
    countElectr = countElectr + ElectrPowReal;
    countHeatAndElectr++;

    // Управление вентилятором при перегреве
    if (HeatOptionFlag == true && Temper[0] >= 850 && tOverheatReal >= 300 && digitalRead(48) == LOW) {
      tKompressorCounter++;
      if (tKompressorCounter >= 4) {
        bitClear(relay, 0);
        tKompressorCounter = 0;
      }
    } else if (HeatOptionFlag == true && (Temper[0] <= 750 || tOverheatReal <= 200) && digitalRead(48) == HIGH) {
      tKompressorCounter++;
      if (tKompressorCounter >= 2) {
        bitSet(relay, 0);
        tKompressorCounter = 0;
      }
    } else tKompressorCounter = 0;

    // Режимы нагрева
    if (HeatOptionFlag == true && Temper[1] >= 360) {
      HeatOptionCout++;
      if (HeatOptionCout >= 6) {
        HeatOptionFlag = false; HeatOptionPauseFlag = true; HeatOptionCout = 0;
        HeatOptionPauseStartTime = millis(); bitClear(relay, 2); bitClear(relay, 0);
      }
    } else HeatOptionCout = 0;

    if (HeatOptionPauseFlag == true && digitalRead(49) == LOW && millis() - HeatOptionPauseStartTime >= 120000)
      bitClear(relay, 1);

    if (HeatOptionPauseFlag == true && digitalRead(51) == HIGH && millis() - HeatOptionPauseStartTime >= 960000) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis(); FirstImpulsWater = false; SecondImpulsWater = false;
      }
      bitSet(relay, 3); HeatOptionPauseStartTime = millis();
    }

    if (HeatOptionPauseFlag == true && digitalRead(51) == LOW && millis() - HeatOptionPauseStartTime >= 60000) {
      bitClear(relay, 3); HeatOptionPauseStartTime = millis();
    }

    if (HeatOptionPauseFlag == true && Temper[1] <= 280) {
      HeatOptionPauseCout++;
      if (HeatOptionPauseCout >= 5) {
        HeatOptionPauseFlag = false; HeatOptionPauseCout = 0;
        StartHeatTime = millis(); StartHeatFlag = true;
      }
    } else HeatOptionPauseCout = 0;

    // Defrost
    if (HeatOptionFlag == true && Temper[5] < -100) {
      defrostCount++;
      if (defrostCount >= 6) {
        HeatOptionFlag = false; DefrostOptionFlag = true; DefrostTime = millis(); defrostCount = 0;
      }
    } else defrostCount = 0;

    // Защиты
    if (HeatOptionFlag == true && digitalRead(49) == HIGH) {
      StopNo4xvalve++;
      if (StopNo4xvalve >= 3) {
        bitClear(relay, 2); StopFlag = true; StopTime = millis(); StopKind = 1; StopNo4xvalve = 0;
      }
    } else StopNo4xvalve = 0;

    if ((StartHeatFlag || HeatOptionFlag || HeatOptionPauseFlag || DefrostOptionFlag) && Temper[0] >= 1000) {
      StopMaxTemp++;
      if (StopMaxTemp >= 5) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 2;
        StopMaxTemp = 0;
      }
    } else StopMaxTemp = 0;

    if ((StartHeatFlag || HeatOptionFlag || HeatOptionPauseFlag || DefrostOptionFlag) && ElectrPowReal >= 151) {
      StopMaxElectr++;
      if (StopMaxElectr >= 6) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 3;
        StopMaxElectr = 0;
      }
    } else StopMaxElectr = 0;

    if ((StartHeatFlag || HeatOptionFlag || HeatOptionPauseFlag) && Temper[4] <= 50) {
      StopMinTempHeater++;
      if (StopMinTempHeater >= 3) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 4;
        StopMinTempHeater = 0;
      }
    } else StopMinTempHeater = 0;

    if (digitalRead(50) == LOW && ElectrPowReal <= 10) {
      StopNoElectric++;
      if (StopNoElectric >= 6) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 5;
        StopNoElectric = 0;
      }
    } else StopNoElectric = 0;

    // Start heat
    if (StartHeatFlag && millis() - StartHeatTime >= 20000 && Temper[1] >= 50) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis(); FirstImpulsWater = false; SecondImpulsWater = false;
      }
      bitSet(relay, 3);
    }
    if (StartHeatFlag && digitalRead(51) == LOW && millis() - StartHeatTime >= 30000 && Temper[0] <= 850) bitSet(relay, 0);
    if (StartHeatFlag && digitalRead(51) == LOW && digitalRead(48) == LOW && millis() - StartHeatTime >= 40000) bitSet(relay, 1);
    if (StartHeatFlag && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(49) == LOW && millis() - StartHeatTime >= 45000) bitSet(relay, 2);
    if (StartHeatFlag && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(50) == LOW && digitalRead(49) == LOW) {
      StartHeatFlag = false; HeatOptionFlag = true;
    }

    // Stop
    if (StopFlag) {
      StartHeatFlag = false; HeatOptionFlag = false; HeatOptionPauseFlag = false; DefrostOptionFlag = false;
      bitClear(relay, 2); bitClear(relay, 0);
      if (millis() - StopTime >= 120000) bitClear(relay, 1);
      if (millis() - StopTime >= 180000) bitClear(relay, 3);
    }

    // Defrost
    if (DefrostOptionFlag) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis(); FirstImpulsWater = false; SecondImpulsWater = false;
      }
      bitSet(relay, 3); bitClear(relay, 2); bitSet(relay, 0);
      if (millis() - DefrostTime >= 120000) bitClear(relay, 1);
      if (millis() - DefrostTime >= 900000 && Temper[5] >= 20) {
        DefrostOptionFlag = false; StartHeatTime = millis(); StartHeatFlag = true;
      }
    }

    // Вывод на дисплей
    tft.fillRect(74, 0, 30, 20, BLACK);
    tft.fillRect(181, 0, 30, 20, BLACK);
    tft.fillRect(289, 0, 30, 20, BLACK);
    tft.fillRect(74, 210, 30, 20, BLACK);
    tft.fillRect(181, 210, 30, 10, BLACK);
    tft.fillRect(289, 210, 30, 10, BLACK);
    tft.fillRect(152, 220, 60, 10, BLACK);
    tft.fillRect(100, 470, 30, 8, BLACK);
    tft.fillRect(200, 470, 30, 8, BLACK);

    tft.setCursor(74, 0);
    tft.setTextColor(RED, (MistakeTemp[0] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[0]);

    tft.setCursor(181, 0);
    tft.setTextColor(YELLOW, (MistakeTemp[1] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[1]);

    tft.setCursor(289, 0);
    tft.setTextColor(GREEN, (MistakeTemp[2] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[2]);

    tft.setCursor(74, 10);
    tft.setTextColor(MAGENTA, (MistakeTemp[3] > 0) ? WHITE : BLACK);
    getDataInt10(tOverheatReal);

    tft.setCursor(181, 10);
    tft.setTextColor(CYAN, (MistakeTemp[4] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[4]);

    tft.setCursor(289, 10);
    tft.setTextColor(RED, (MistakeTemp[5] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[5]);

    tft.setCursor(74, 210); tft.setTextColor(RED); getDataInt100(heatPowerReal);
    tft.setCursor(181, 210); tft.setTextColor(YELLOW); getDataInt100(COPreal);
    tft.setCursor(289, 210); tft.setTextColor(GREEN); getDataInt100(ElectrPowReal);
    tft.setCursor(74, 220);
    tft.setTextColor(MAGENTA, FlagWater ? WHITE : BLACK);
    getDataInt100(gWaterReal);

    tft.setCursor(100, 470); tft.setTextColor(RED);
    getDataInt100(countHeat / countHeatAndElectr);
    tft.setCursor(200, 470); tft.setTextColor(GREEN);
    getDataInt100(countElectr / countHeatAndElectr);

    tft.setCursor(152, 220); tft.setTextColor(RED);
    if (StopFlag == true) {
      tft.print("Stop");
      switch (StopKind) {
        case 1: tft.print(" No 4x valve"); break;
        case 2: tft.print(" maxT Kompr"); break;
        case 3: tft.print(" maxW Electr"); break;
        case 4: tft.print(" minT Heater"); break;
        case 5: tft.print(" No Electr"); break;
        case 6: tft.print(" Err Temp"); break;
        case 7: tft.print(" No G_water"); break;
        case 8: tft.print(" No Option"); break;
      }
    } else if (StartHeatFlag == true) {
      tft.print("Start heat");
    } else if (HeatOptionFlag == true) {
      tft.print("Heat option");
    } else if (HeatOptionPauseFlag == true) {
      tft.print("Pause heat");
    } else if (DefrostOptionFlag == true) {
      tft.print("Defrost");
    } else {
      StopFlag = true; StopTime = millis(); StopKind = 8;
    }

    tft.setCursor(0, 440);
    tft.setTextColor(bitRead(relay, 2) ? RED : BLUE); tft.print("Kompressor");
    tft.setCursor(0, 450);
    tft.setTextColor(bitRead(relay, 3) ? RED : BLUE); tft.print("Pump");
    tft.setCursor(0, 460);
    tft.setTextColor(bitRead(relay, 1) ? RED : BLUE); tft.print("4 way valve");
    tft.setCursor(0, 470);
    tft.setTextColor(bitRead(relay, 0) ? RED : BLUE); tft.print("Fan");

    Flag3 = false;
    Serial.println(">>> Step 3 END");
  }

  // Шаг 4: управление реле (9-10 сек)
  if (millis() - Timer >= 9000 && millis() - Timer < 10000 && Flag4 == true) {
    Serial.println(">>> Step 4: Relays");
    digitalWrite(48, bitRead(relay, 0) ? LOW : HIGH);
    digitalWrite(49, bitRead(relay, 1) ? LOW : HIGH);
    digitalWrite(50, bitRead(relay, 2) ? LOW : HIGH);
    digitalWrite(51, bitRead(relay, 3) ? LOW : HIGH);
    Flag4 = false;
  }

  // Шаг 5: обновление графиков (каждые 10 сек)
  if (millis() - Timer >= 10000) {
    Serial.println(">>> Step 5: Graphics reset, Cycle END");
    Timer = millis();

    if (countGetGrafic >= 9) {
      //Serial.println("proverka");
      for (uint16_t x = 0; x < 319; x++) {
        tIsparitel[x] = tIsparitel[x + 1];
        tOverheat[x] = tOverheat[x + 1];
        tKompressor[x] = tKompressor[x + 1];
        tWaterIn[x] = tWaterIn[x + 1];
        tWaterOut[x] = tWaterOut[x + 1];
        gWater[x] = gWater[x + 1];
        heatPower[x] = heatPower[x + 1];
        ElectrPow[x] = ElectrPow[x + 1];
        COP[x] = COP[x + 1];
        tDefrost[x] = tDefrost[x + 1];
      }

      tKompressor[319] = (uint8_t)getDataForUintMassiv(Temper[0]);
      tWaterIn[319] = (uint8_t)getDataForUintMassiv(Temper[1]);
      tWaterOut[319] = (uint8_t)getDataForUintMassiv(Temper[2]);
      tOverheat[319] = (uint8_t)getDataForUintMassiv(tOverheatReal);
      tDefrost[319] = (uint8_t)getDataForUintMassiv(Temper[4]);
      tIsparitel[319] = (uint8_t)getDataForUintMassiv(Temper[5]);
      heatPower[319] = (uint8_t)getDataForUintMassiv32(heatPowerReal);
      COP[319] = (uint8_t)getDataForUintMassiv32(COPreal);
      ElectrPow[319] = (uint8_t)getDataForUintMassiv32(ElectrPowReal);
      gWater[319] = (uint8_t)getDataForUintMassiv32(gWaterReal);

      for (uint8_t i = 0; i < 19; i++) {
        trend_fan[i] = trend_fan[i] << 1;
        bitWrite(trend_fan[i], 0, bitRead(trend_fan[i + 1], 15));
        trend_kompressor[i] = trend_kompressor[i] << 1;
        bitWrite(trend_kompressor[i], 0, bitRead(trend_kompressor[i + 1], 15));
        trend_pump[i] = trend_pump[i] << 1;
        bitWrite(trend_pump[i], 0, bitRead(trend_pump[i + 1], 15));
        trend_4way_valve[i] = trend_4way_valve[i] << 1;
        bitWrite(trend_4way_valve[i], 0, bitRead(trend_4way_valve[i + 1], 15));
      }
      bitWrite(trend_fan[19], 0, bitRead(relay, 0));
      bitWrite(trend_kompressor[19], 0, bitRead(relay, 2));
      bitWrite(trend_pump[19], 0, bitRead(relay, 3));
      bitWrite(trend_4way_valve[19], 0, bitRead(relay, 1));

      getMainDisplay();

      getGraphics(245, RED, tKompressor);
      getGraphics(245, YELLOW, tWaterIn);
      getGraphics(245, GREEN, tWaterOut);
      getGraphics(245, MAGENTA, tOverheat);
      getGraphics(245, CYAN, tDefrost);
      getGraphics(245, RED, tIsparitel);
      getGraphics(475, RED, heatPower);
      getGraphics(475, YELLOW, COP);
      getGraphics(475, GREEN, ElectrPow);
      getGraphics(475, MAGENTA, gWater);

      for (uint8_t i = 0; i < 20; i++) {
        for (uint8_t j = 0; j < 16; j++) {
          if (bitRead(trend_fan[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 479, YELLOW);
          if (bitRead(trend_kompressor[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 449, YELLOW);
          if (bitRead(trend_pump[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 459, YELLOW);
          if (bitRead(trend_4way_valve[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 469, YELLOW);
        }
      }

      countGetGrafic = 0;
    }

    countGetGrafic++;
    Flag1 = true;
    Flag2 = true;
    Flag3 = true;
    Flag4 = true;
  }
}

Подключил все сильноточные цепи и запустил систему с записью лога в монитор порта.
К моему удивлению - всё работало стабильно в течение долгого времени. Перед уходом на ужин я сделал фото дисплея

Спойлер

кстати, BABOS - может, поможете мне понять, почему тренд состояния реле (жёлтые линии снизу) - имеет только один пиксель и не двигается влево?
Придя после ужина и взглянув на дисплей - я понял, что была перезагрузка (цикл на дисплее при этом двигался, оборудование в работе)
Посмотрел на лог монитора порта. Он был в застывшем состоянии. Я скопировал его. Вот последние его записи:

Спойлер
lm=2524083 T=2514103
lm=2524105 T=2514103
>>> Step 5: Graphics reset, Cycle END
lm=2524169 T=2524166
lm=2524192 T=2524166
lm=2524215 T=2524166
lm=2524237 T=2524166
lm=2524261 T=2524166
lm=2524283 T=2524166
lm=2524306 T=2524166
lm=2524329 T=2524166
lm=2524352 T=2524166
lm=2524375 T=2524166
lm=2524398 T=2524166
lm=2524421 T=2524166
lm=2524443 T=2524166
lm=2524467 T=2524166
lm=2524489 T=2524166
lm=2524512 T=2524166
lm=2524535 T=2524166
lm=2524558 T=2524166
lm=2524580 T=2524166
lm=2524604 T=2524166
lm=2524626 T=2524166
lm=2524649 T=2524166
lm=2524673 T=2524166
lm=2524695 T=2524166
lm=2524718 T=2524166
lm=2524741 T=2524166
lm=2524764 T=2524166
lm=2524787 T=2524166
lm=2524810 T=2524166
lm=2524832 T=2524166
lm=2524856 T=2524166
lm=2524878 T=2524166
lm=2524901 T=2524166
lm=2524924 T=2524166
lm=2524947 T=2524166
lm=2524969 T=2524166
lm=2524993 T=2524166
lm=2525016 T=2524166
lm=2525038 T=2524166
lm=2525062 T=2524166
lm=2525084 T=2524166
lm=2525107 T=2524166
lm=2525130 T=2524166
lm=2525153 T=2524166
lm=2525175 T=2524166
lm=2525199 T=2524166
lm=2525221 T=2524166
lm=2525244 T=2524166
lm=2525267 T=2524166
lm=2525290 T=2524166
lm=2525313 T=2524166
lm=2525336 T=2524166
lm=2525359 T=2524166
lm=2525381 T=2524166
lm=2525405 T=2524166
lm=2525427 T=2524166
lm=2525450 T=2524166
lm=2525473 T=2524166
lm=2525496 T=2524166
lm=2525519 T=2524166
lm=2525542 T=2524166
lm=2525564 T=2524166
lm=2525588 T=2524166
lm=2525611 T=2524166
lm=2525633 T=2524166
lm=2525657 T=2524166
lm=2525679 T=2524166
lm=2525702 T=2524166
lm=2525725 T=2524166
lm=2525748 T=2524166
lm=2525770 T=2524166
lm=2525794 T=2524166
lm=2525816 T=2524166
lm=2525839 T=2524166
lm=2525862 T=2524166
lm=2525885 T=2524166
lm=2525907 T=2524166
lm=2525931 T=2524166
lm=2525954 T=2524166
lm=2525976 T=2524166
lm=2526000 T=2524166
lm=2526022 T=2524166
lm=2526045 T=2524166
lm=2526068 T=2524166
lm=2526091 T=2524166
lm=2526113 T=2524166
lm=2526137 T=2524166
lm=2526159 T=2524166
lm=2526182 T=2524166
lm=2526205 T=2524166
lm=2526228 T=2524166
lm=2526252 T=2524166
lm=2526274 T=2524166
lm=2526297 T=2524166
lm=2526320 T=2524166
lm=2526343 T=2524166
lm=2526365 T=2524166
lm=2526389 T=2524166
lm=2526411 T=2524166
lm=2526434 T=2524166
lm=2526457 T=2524166
lm=2526480 T=2524166
lm=2526502 T=2524166
lm=2526526 T=2524166
lm=2526548 T=2524166
lm=2526571 T=2524166
lm=2526595 T=2524166
lm=2526617 T=2524166
lm=2526640 T=2524166
lm=2526663 T=2524166
lm=2526686 T=2524166
lm=2526708 T=2524166
lm=2526732 T=2524166
lm=2526754 T=2524166
lm=2526777 T=2524166
lm=2526800 T=2524166
lm=2526823 T=2524166
lm=2526845 T=2524166
lm=2526869 T=2524166
lm=2526892 T=2524166
lm=2526914 T=2524166
lm=2526938 T=2524166
lm=2526960 T=2524166
lm=2526984 T=2524166
lm=2527006 T=2524166
lm=2527029 T=2524166
lm=2527052 T=2524166
lm=2527075 T=2524166
lm=2527097 T=2524166
lm=2527121 T=2524166
lm=2527143 T=2524166
lm=2527166 T=2524166
>>> Step 1: resetTemp
lm=2527213 T=2524166
lm=2527236 T=2524166
lm=2527259 T=2524166
lm=2527282 T=2524166
lm=2527304 T=2524166
lm=2527328 T=2524166
lm=2527350 T=2524166
lm=2527373 T=2524166
lm=2527396 T=2524166
lm=2527419 T=2524166
lm=2527441 T=2524166
lm=2527465 T=2524166
lm=2527488 T=2524166
lm=2527510 T=2524166
lm=2527534 T=2524166
lm=2527556 T=2524166
lm=2527579 T=2524166
lm=2527602 T=2524166
lm=2527625 T=2524166
lm=2527648 T=2524166
lm=2527671 T=2524166
lm=2527693 T=2524166
lm=2527717 T=2524166
lm=2527739 T=2524166
lm=2527762 T=2524166
lm=2527785 T=2524166
lm=2527808 T=2524166
lm=2527831 T=2524166
lm=2527854 T=2524166
lm=2527877 T=2524166
lm=2527899 T=2524166
lm=2527923 T=2524166
lm=2527945 T=2524166
lm=2527968 T=2524166
lm=2527991 T=2524166
lm=2528014 T=2524166
lm=2528036 T=2524166
lm=2528060 T=2524166
lm=2528082 T=2524166
lm=2528105 T=2524166
lm=2528129 T=2524166
lm=2528151 T=2524166
lm=2528174 T=2524166
lm=2528197 T=2524166
lm=2528220 T=2524166
lm=2528242 T=2524166
lm=2528266 T=2524166
lm=2528288 T=2524166
lm=2528311 T=2524166
lm=2528334 T=2524166
lm=2528357 T=2524166
lm=2528380 T=2524166
lm=2528403 T=2524166
lm=2528425 T=2524166
lm=2528449 T=2524166
lm=2528472 T=2524166
lm=2528494 T=2524166
lm=2528518 T=2524166
lm=2528540 T=2524166
lm=2528563 T=2524166
lm=2528586 T=2524166
lm=2528609 T=2524166
lm=2528631 T=2524166
lm=2528655 T=2524166
lm=2528677 T=2524166
lm=2528700 T=2524166
lm=2528723 T=2524166
lm=2528746 T=2524166
lm=2528769 T=2524166
lm=2528792 T=2524166
lm=2528815 T=2524166
lm=2528837 T=2524166
lm=2528861 T=2524166
lm=2528883 T=2524166
lm=2528906 T=2524166
lm=2528929 T=2524166
lm=2528952 T=2524166
lm=2528974 T=2524166
lm=2528998 T=2524166
lm=2529020 T=2524166
lm=2529043 T=2524166
lm=2529067 T=2524166
lm=2529089 T=2524166
lm=2529113 T=2524166
lm=2529135 T=2524166
lm=2529158 T=2524166
>>> Step 2: gettingTemp
proverka
lm=2529282 T=2524166
lm=2529283 T=2524166
lm=2529284 T=2524166
lm=2529286 T=2524166
lm=2529309 T=2524166
lm=2529332 T=2524166
lm=2529354 T=2524166
lm=2529378 T=2524166
lm=2529400 T=2524166
lm=2529424 T=2524166
lm=2529446 T=2524166
lm=2529469 T=2524166
lm=2529492 T=2524166
lm=2529515 T=2524166
lm=2529538 T=2524166
lm=2529561 T=2524166
lm=2529584 T=2524166
lm=2529606 T=2524166
lm=2529630 T=2524166
lm=2529652 T=2524166
lm=2529675 T=2524166
lm=2529698 T=2524166
lm=2529721 T=2524166
lm=2529743 T=2524166
lm=2529767 T=2524166
lm=2529789 T=2524166
lm=2529812 T=2524166
lm=2529836 T=2524166
lm=2529858 T=2524166
lm=2529881 T=2524166
lm=2529904 T=2524166
lm=2529927 T=2524166
lm=2529949 T=2524166
lm=2529973 T=2524166
lm=2529995 T=2524166
lm=2530018 T=2524166
lm=2530041 T=2524166
lm=2530064 T=2524166
lm=2530086 T=2524166
lm=2530110 T=2524166
lm=2530132 T=2524166
lm=2530156 T=2524166
lm=2530179 T=2524166
lm=2530201 T=2524166
lm=2530225 T=2524166
lm=2530247 T=2524166
lm=2530270 T=2524166
lm=2530293 T=2524166
lm=2530316 T=2524166
lm=2530338 T=2524166
lm=2530362 T=2524166
lm=2530384 T=2524166
lm=2530407 T=2524166
lm=2530430 T=2524166
lm=2530453 T=2524166
lm=2530476 T=2524166
lm=2530499 T=2524166
lm=2530522 T=2524166
lm=2530544 T=2524166
lm=2530568 T=2524166
lm=2530590 T=2524166
lm=2530613 T=2524166
lm=2530636 T=2524166
lm=2530659 T=2524166
lm=2530681 T=2524166
lm=2530705 T=2524166
lm=2530727 T=2524166
lm=2530750 T=2524166
lm=2530774 T=2524166
lm=2530796 T=2524166
lm=2530819 T=2524166
lm=2530842 T=2524166
lm=2530865 T=2524166
lm=2530888 T=2524166
lm=2530911 T=2524166
lm=2530933 T=2524166
lm=2530957 T=2524166
lm=2530979 T=2524166
lm=2531002 T=2524166
lm=2531025 T=2524166
lm=2531048 T=2524166
lm=2531070 T=2524166
lm=2531094 T=2524166
lm=2531117 T=2524166
lm=2531139 T=2524166
lm=2531163 T=2524166
>>> Step 3 START
>>> Step 3 END
lm=2531427 T=2524166
lm=2531427 T=2524166
lm=2531428 T=2524166
lm=2531447 T=2524166
lm=2531470 T=2524166
lm=2531492 T=2524166
lm=2531516 T=2524166
lm=2531538 T=2524166
lm=2531561 T=2524166
lm=2531585 T=2524166
lm=2531607 T=2524166
lm=2531631 T=2524166
lm=2531653 T=2524166
lm=2531676 T=2524166
lm=2531699 T=2524166
lm=2531722 T=2524166
lm=2531744 T=2524166
lm=2531768 T=2524166
lm=2531790 T=2524166
lm=2531813 T=2524166
lm=2531836 T=2524166
lm=2531859 T=2524166
lm=2531881 T=2524166
lm=2531905 T=2524166
lm=2531928 T=2524166
lm=2531950 T=2524166
lm=2531974 T=2524166
lm=2531996 T=2524166
lm=2532019 T=2524166
lm=2532042 T=2524166
lm=2532065 T=2524166
lm=2532087 T=2524166
lm=2532111 T=2524166
lm=2532133 T=2524166
lm=2532156 T=2524166
lm=2532179 T=2524166
lm=2532202 T=2524166
lm=2532225 T=2524166
lm=2532248 T=2524166
lm=2532271 T=2524166
lm=2532293 T=2524166
lm=2532317 T=2524166
lm=2532339 T=2524166
lm=2532363 T=2524166
lm=2532385 T=2524166
lm=2532408 T=2524166
lm=2532431 T=2524166
lm=2532454 T=2524166
lm=2532476 T=2524166
lm=2532500 T=2524166
lm=2532523 T=2524166
lm=2532545 T=2524166
lm=2532569 T=2524166
lm=2532591 T=2524166
lm=2532614 T=2524166
lm=2532637 T=2524166
lm=2532660 T=2524166
lm=2532682 T=2524166
lm=2532706 T=2524166
lm=2532728 T=2524166
lm=2532751 T=2524166
lm=2532774 T=2524166
lm=2532797 T=2524166
lm=2532819 T=2524166
lm=2532843 T=2524166
lm=2532866 T=2524166
lm=2532888 T=2524166
lm=2532912 T=2524166
lm=2532934 T=2524166
lm=2532957 T=2524166
lm=2532980 T=2524166
lm=2533003 T=2524166
lm=2533025 T=2524166
lm=2533049 T=2524166
lm=2533071 T=2524166
lm=2533095 T=2524166
lm=2533117 T=2524166
lm=2533140 T=2524166
lm=2533164 T=2524166
>>> Step 4: Relays
lm=2533207 T=2524166
lm=2533230 T=2524166
lm=2533253 T=2524166
lm=2533275 T=2524166
lm=2533299 T=2524166
lm=2533321 T=2524166
lm=2533344 T=2524166
lm=2533367 T=2524166
lm=2533390 T=2524166
lm=2533412 T=2524166
lm=2533436 T=2524166
lm=2533458 T=2524166
lm=2533481 T=2524166
lm=2533505 T=2524166
lm=2533527 T=2524166
lm=2533550 T=2524166
lm=2533573 T=2524166
lm=2533596 T=2524166
lm=2533618 T=2524166
lm=2533642 T=2524166
lm=2533664 T=2524166
lm=2533687 T=2524166
lm=2533710 T=2524166
lm=2533733 T=2524166
lm=2533755 T=2524166
lm=2533779 T=2524166
lm=2533801 T=2524166
lm=2533824 T=2524166
lm=2533848 T=2524166
lm=2533870 T=2524166
lm=2533894 T=2524166
lm=2533916 T=2524166
lm=2533939 T=2524166
lm=2533962 T=2524166
lm=2533985 T=2524166
lm=2534007 T=2524166
lm=2534031 T=2524166
lm=2534053 T=2524166
lm=2534076 T=2524166
lm=2534099 T=2524166
lm=2534122 T=2524166
lm=2534145 T=2524166
lm=2534168 T=2524166
>>> Step 5: Graphics reset, Cycle END
lm=2534232 T=2534228
lm=2534254 T=2534228
lm=2534277 T=2534228
lm=2534300 T=2534228
lm=2534323 T=2534228
lm=2534345 T=2534228
lm=2534369 T=2534228
lm=2534391 T=2534228
lm=2534414 T=2534228
lm=2534437 T=2534228
lm=2534460 T=2534228
lm=2534482 T=2534228
lm=2534506 T=2534228
lm=2534529 T=2534228
lm=2534551 T=2534228
lm=2534575 T=2534228
lm=2534597 T=2534228
lm=2534620 T=2534228
lm=2534643 T=2534228
lm=2534666 T=2534228
lm=2534688 T=2534228
lm=2534712 T=2534228
lm=2534734 T=2534228
lm=2534758 T=2534228
lm=2534780 T=2534228
lm=2534803 T=2534228
lm=2534827 T=2534228
lm=2534849 T=2534228
lm=2534872 T=2534228
lm=2534895 T=2534228
lm=2534918 T=2534228
lm=2534940 T=2534228
lm=2534964 T=2534228
lm=2534986 T=2534228
lm=2535009 T=2534228
lm=2535032 T=2534228
lm=2535055 T=2534228
lm=2535077 T=2534228
lm=2535101 T=2534228
lm=2535123 T=2534228
lm=2535146 T=2534228
lm=2535170 T=2534228
lm=2535192 T=2534228
lm=2535215 T=2534228
lm=2535238 T=2534228
lm=2535261 T=2534228
lm=2535283 T=2534228
lm=2535307 T=2534228
lm=2535329 T=2534228
lm=2535352 T=2534228
lm=2535375 T=2534228
lm=2535398 T=2534228
lm=2535420 T=2534228
lm=2535444 T=2534228
lm=2535467 T=2534228
lm=2535490 T=2534228
lm=2535513 T=2534228
lm=2535535 T=2534228
lm=2535559 T=2534228
lm=2535581 T=2534228
lm=2535604 T=2534228
lm=2535627 T=2534228
lm=2535650 T=2534228
lm=2535672 T=2534228
lm=2535696 T=2534228
lm=2535718 T=2534228
lm=2535741 T=2534228
lm=2535764 T=2534228
lm=2535787 T=2534228
lm=2535810 T=2534228
lm=2535833 T=2534228
lm=2535856 T=2534228
lm=2535878 T=2534228
lm=2535902 T=2534228
lm=2535924 T=2534228
lm=2535947 T=2534228
lm=2535970 T=2534228
lm=2535993 T=2534228
lm=2536015 T=2534228
lm=2536039 T=2534228
lm=2536061 T=2534228
lm=2536084 T=2534228
lm=2536108 T=2534228
lm=2536130 T=2534228
lm=2536153 T=2534228
lm=2536176 T=2534228
lm=2536199 T=2534228
lm=2536222 T=2534228
lm=2536245 T=2534228
lm=2536267 T=2534228
lm=2536291 T=2534228
lm=2536313 T=2534228
lm=2536336 T=2534228
lm=2536359 T=2534228
lm=2536382 T=2534228
lm=2536404 T=2534228
lm=2536428 T=2534228
lm=2536451 T=2534228
lm=2536473 T=2534228
lm=2536497 T=2534228
lm=2536519 T=2534228
lm=2536542 T=2534228
lm=2536565 T=2534228
lm=2536588 T=2534228
lm=2536610 T=2534228
lm=2536634 T=2534228
lm=2536656 T=2534228
lm=2536679 T=2534228
lm=2536702 T=2534228
lm=2536725 T=2534228
lm=2536748 T=2534228
lm=2536771 T=2534228
lm=2536794 T=2534228
lm=2536816 T=2534228
lm=2536840 T=2534228
lm=2536862 T=2534228
lm=2536885 T=2534228
lm=2536908 T=2534228
lm=2536931 T=2534228
lm=2536954 T=2534228
lm=2536977 T=2534228
lm=2536999 T=2534228
lm=2537023 T=2534228
lm=2537046 T=2534228
lm=2537068 T=2534228
lm=2537092 T=2534228
lm=2537114 T=2534228
lm=2537137 T=2534228
lm=2537160 T=2534228
lm=2537183 T=2534228
lm=2537205 T=2534228
lm=2537229 T=2534228
>>> Step 1: resetTemp
lm=2537275 T=2534228
lm=2537298 T=2534228
lm=2537321 T=2534228
lm=2537344 T=2534228
lm=2537367 T=2534228
lm=2537390 T=2534228
lm=2537412 T=2534228
lm=2537436 T=2534228
lm=2537458 T=2534228
lm=2537481 T=2534228
lm=2537504 T=2534228
lm=2537527 T=2534228
lm=2537549 T=2534228
lm=2537573 T=2534228
lm=2537595 T=2534228
lm=2537618 T=2534228
lm=2537641 T=2534228
lm=2537664 T=2534228
lm=2537688 T=2534228
lm=2537710 T=2534228
lm=2537733 T=2534228
lm=2537756 T=2534228
lm=2537779 T=2534228
lm=2537801 T=2534228
lm=2537825 T=2534228
lm=2537847 T=2534228
lm=2537870 T=2534228
lm=2537893 T=2534228
lm=2537916 T=2534228
lm=2537938 T=2534228
lm=2537962 T=2534228
lm=2537985 T=2534228
lm=2538007 T=2534228
lm=2538031 T=2534228
lm=2538053 T=2534228
lm=2538076 T=2534228
lm=2538099 T=2534228
lm=2538122 T=2534228
lm=2538144 T=2534228
lm=2538168 T=2534228
lm=2538190 T=2534228
lm=2538213 T=2534228
lm=2538236 T=2534228
lm=2538259 T=2534228
lm=2538281 T=2534228
lm=2538305 T=2534228
lm=2538328 T=2534228
lm=2538350 T=2534228
lm=2538374 T=2534228
lm=2538396 T=2534228
lm=2538420 T=2534228
lm=2538442 T=2534228
lm=2538465 T=2534228
lm=2538488 T=2534228
lm=2538511 T=2534228
lm=2538533 T=2534228
lm=2538557 T=2534228
lm=2538579 T=2534228
lm=2538602 T=2534228
lm=2538626 T=2534228
lm=2538648 T=2534228
lm=2538671 T=2534228
lm=2538694 T=2534228
lm=2538717 T=2534228
lm=2538739 T=2534228
lm=2538763 T=2534228
lm=2538785 T=2534228
lm=2538808 T=2534228
lm=2538831 T=2534228
lm=2538854 T=2534228
lm=2538876 T=2534228
lm=2538900 T=2534228
lm=2538923 T=2534228
lm=2538945 T=2534228
lm=2538969 T=2534228
lm=2538991 T=2534228
lm=2539014 T=2534228
lm=2539037 T=2534228
lm=2539060 T=2534228
lm=2539082 T=2534228
lm=2539106 T=2534228
lm=2539128 T=2534228
lm=2539152 T=2534228
lm=2539174 T=2534228
lm=2539197 T=2534228
lm=2539220 T=2534228
>>> Step 2: gettingTemp
proverka
lm=2539344 T=2534228
lm=2539344 T=2534228
lm=2539345 T=2534228
lm=2539348 T=2534228
lm=2539371 T=2534228
lm=2539395 T=2534228
lm=2539417 T=2534228
lm=2539440 T=2534228
lm=2539463 T=2534228
lm=2539486 T=2534228
lm=2539508 T=2534228
lm=2539532 T=2534228
lm=2539554 T=2534228
lm=2539577 T=2534228
lm=2539600 T=2534228
lm=2539623 T=2534228
lm=2539645 T=2534228
lm=2539669 T=2534228
lm=2539692 T=2534228
lm=2539714 T=2534228
lm=2539738 T=2534228
lm=2539760 T=2534228
lm=2539783 T=2534228
lm=2539806 T=2534228
lm=2539829 T=2534228
lm=2539851 T=2534228
lm=2539875 T=2534228
lm=2539897 T=2534228
lm=2539920 T=2534228
lm=2539943 T=2534228
lm=2539966 T=2534228
lm=2539988 T=2534228
lm=2540012 T=2534228
lm=2540035 T=2534228
lm=2540057 T=2534228
lm=2540081 T=2534228
lm=2540103 T=2534228
lm=2540127 T=2534228
lm=2540149 T=2534228
lm=2540172 T=2534228
lm=2540195 T=2534228
lm=2540218 T=2534228
lm=2540240 T=2534228
lm=2540264 T=2534228
lm=2540286 T=2534228
lm=2540309 T=2534228
lm=2540333 T=2534228
lm=2540355 T=2534228
lm=2540378 T=2534228
lm=2540401 T=2534228
lm=2540424 T=2534228
lm=2540446 T=2534228
lm=2540470 T=2534228
lm=2540492 T=2534228
lm=2540515 T=2534228
lm=2540538 T=2534228
lm=2540561 T=2534228
lm=2540583 T=2534228
lm=2540607 T=2534228
lm=2540630 T=2534228
lm=2540652 T=2534228
lm=2540676 T=2534228
lm=2540698 T=2534228
lm=2540721 T=2534228
lm=2540744 T=2534228
lm=2540767 T=2534228
lm=2540789 T=2534228
lm=2540813 T=2534228
lm=2540835 T=2534228
lm=2540859 T=2534228
lm=2540881 T=2534228
lm=2540904 T=2534228
lm=2540928 T=2534228
lm=2540950 T=2534228
lm=2540973 T=2534228
lm=2540996 T=2534228
lm=2541019 T=2534228
lm=2541041 T=2534228
lm=2541065 T=2534228
lm=2541087 T=2534228
lm=2541110 T=2534228
lm=2541133 T=2534228
lm=2541156 T=2534228
lm=2541178 T=2534228
lm=2541202 T=2534228
lm=2541224 T=2534228
>>> Step 3 START
>>> Step 3 END
lm=2541489 T=2534228
lm=2541490 T=2534228
lm=2541491 T=2534228
lm=2541509 T=2534228
lm=2541533 T=2534228
lm=2541555 T=2534228
lm=2541578 T=2534228
lm=2541601 T=2534228
lm=2541624 T=2534228
lm=2541647 T=2534228
lm=2541670 T=2534228
lm=2541692 T=2534228
lm=2541716 T=2534228
lm=2541739 T=2534228
lm=2541761 T=2534228
lm=2541785 T=2534228
lm=2541807 T=2534228
lm=2541830 T=2534228
lm=2541853 T=2534228
lm=2541876 T=2534228
lm=2541898 T=2534228
lm=2541922 T=2534228
lm=2541944 T=2534228
lm=2541967 T=2534228
lm=2541990 T=2534228
lm=2542013 T=2534228
lm=2542035 T=2534228
lm=2542059 T=2534228
lm=2542082 T=2534228
lm=2542104 T=2534228
lm=2542128 T=2534228
lm=2542150 T=2534228
lm=2542173 T=2534228
lm=2542196 T=2534228
lm=2542219 T=2534228
lm=2542241 T=2534228
lm=2542265 T=2534228
lm=2542287 T=2534228
lm=2542310 T=2534228
lm=2542333 T=2534228
lm=2542356 T=2534228
lm=2542380 T=2534228
lm=2542402 T=2534228
lm=2542425 T=2534228
lm=2542448 T=2534228
lm=2542471 T=2534228
lm=2542493 T=2534228
lm=2542517 T=2534228
lm=2542539 T=2534228
lm=2542562 T=2534228
lm=2542585 T=2534228
lm=2542608 T=2534228
lm=2542630 T=2534228
lm=2542654 T=2534228
lm=2542676 T=2534228
lm=2542699 T=2534228
lm=2542723 T=2534228
lm=2542745 T=2534228
lm=2542768 T=2534228
lm=2542791 T=2534228
lm=2542814 T=2534228
lm=2542836 T=2534228
lm=2542860 T=2534228
lm=2542882 T=2534228
lm=2542905 T=2534228
lm=2542928 T=2534228
lm=2542951 T=2534228
lm=2542973 T=2534228
lm=2542997 T=2534228
lm=2543020 T=2534228
lm=2543042 T=2534228
lm=2543066 T=2534228
lm=2543088 T=2534228
lm=2543112 T=2534228
lm=2543134 T=2534228
lm=2543157 T=2534228
lm=25431

Получается, контроллер отработал более 40 минут, при этом ведя трансляцию в монитор порта. Это уже достижение, на мой взгляд.

Параллельно вопрос: почему “loop millis” насчитал 2543157, а таймер 2534228. Куда делась разница? Ведь я на графике - визуально делаю вывод о прошедшем времени по количеству загруженных пикселей. Получается - я не прав, что между двумя вертикальными чертами на графике проходит 1 час?
Наверное - разница - это 10 секунд цикла… они же в какой-то момент сравниваются. Но вопрос всё равно меня волнует - между вертикальными линиями на дисплее разница по времени 1 час?

Судя по логу из монитора порта, сбой прошёл в тот момент, когда должно было наступить время передачи команды от контроллера на блок реле.

а ТЗ то не будет ?))) не понял зачем, и какой код писать на esp

На первом этапе пусть будет проект ТСа. Что имеем = 6 датчиков 18в20 и 6 релюшек. Аналоговые входы (если есть) оставь пока свободными и вЫводы с функцией PWM то-же. Пригодятся потом.

Это для начала.

Уже на чекушку написали, а воз и нынче там! @PPeterr вам в самых первых первых сообщениях писали об исключении физических датчиков - вы это сделали? Убедились, что проблема не в них? Может перестать уже действовать наобум и разбить поиск на части?
Сначала исключить кривость данных со входов: скетч чисто на сбор данных(температура, счётчики и тд), вывод на экран и в лог.
Затем исключить влияние выходных цепей: также скетч только на вкл/выкл реле в разных комбинациях с выводом на экран и в лог.
Потом “совместить эти два скейтча”.
А уже потом искать ошибки в логике работы основной программы. И сторожевой таймер в финальную версию ещё впендюрить.

Либо я не так понял. Либо подумал - что “фигня”, всё у меня само заработает. Теперь готов возвращаться.
Физически отключить датчики - это значит поубирать провода из Ардуино, идущие от DS18B20 и импульсных выходов? А что при этом должно быть в загружаемом скетче тогда?
Без датчиков - я не смогу “дёргать” сильноточные цепи. Если насос туда-сюда включать/отключать ещё можно - то с компрессором так лучше не делать, думаю.
Если подскажите - как именно организовать “физически отключить датчики и погонять” - сделаю, с удовольствием. Но мне как бы ясно это не видно -как организовывать такое.

У меня всего там - сбор данных идёт от 6-ти датчиков DS18B20 и двух импульсных выходов. Всё. Но если датчики - могут без всяких - передавать температуру, то чтобы заработали импульсные выходы - мне надо гонять насос (импульсы с водомера) и какую-то электрическую нагрузку (импульс с электросчётчика). Думаю, и то и то - можно в принципе организовать “извернувшись”… если действительно - правильный ход действий именно такой.

Что есть “сторожевой таймер”?
Это вот этот код:

// Детектор причины перезагрузки
  Serial.print("MCUSR=0x");
  Serial.println(MCUSR, HEX);
  if (MCUSR & (1 << PORF)) Serial.println("RESET: Power-on reset");
  if (MCUSR & (1 << EXTRF)) Serial.println("RESET: External reset (пин RESET)");
  if (MCUSR & (1 << BORF)) Serial.println("RESET: Brown-out (просадка питания)");
  if (MCUSR & (1 << WDRF)) Serial.println("RESET: Watchdog (зависание)");
  MCUSR = 0;

?

Подскажите пожалуйста, как вывести битовую маску (или, как оно правильно называется) - переменной relay в монитор порта? Ну, чтобы в мониторе порта печаталось значение relay в виде восьми цифр из ноликлов либо единичек. Так как значение relay формируется раньше, чем срабатывает реле - я хотя бы по логу монитора порта смогу отследить - на включение (либо выключение) какого реле пришла команда перед аварийным остановом работы контроллера.

Посмотрел. Вроде бы, когда работало, было

      for (uint8_t i; i < 20; i++)
      {
        trend_fan[i] = trend_fan[i] << 1;
        bitWrite(trend_fan[i], 0, bitRead(trend_fan[i + 1], 15));
        trend_kompressor[i] = trend_kompressor[i] << 1;
        bitWrite(trend_kompressor[i], 0, bitRead(trend_kompressor[i + 1], 15));
        trend_pump[i] = trend_pump[i] << 1;
        bitWrite(trend_pump[i], 0, bitRead(trend_pump[i + 1], 15));
        trend_4way_valve[i] = trend_4way_valve[i] << 1;
        bitWrite(trend_4way_valve[i], 0, bitRead(trend_4way_valve[i + 1], 15));
      }
      bitWrite(trend_fan[19], 0, bitRead(relay, 0));
      bitWrite(trend_kompressor[19], 0, bitRead(relay, 2));
      bitWrite(trend_pump[19], 0, bitRead(relay, 3));
      bitWrite(trend_4way_valve[19], 0, bitRead(relay, 1));

сейчас:

      for (uint8_t i = 0; i < 19; i++) {
        trend_fan[i] = trend_fan[i] << 1;
        bitWrite(trend_fan[i], 0, bitRead(trend_fan[i + 1], 15));
        trend_kompressor[i] = trend_kompressor[i] << 1;
        bitWrite(trend_kompressor[i], 0, bitRead(trend_kompressor[i + 1], 15));
        trend_pump[i] = trend_pump[i] << 1;
        bitWrite(trend_pump[i], 0, bitRead(trend_pump[i + 1], 15));
        trend_4way_valve[i] = trend_4way_valve[i] << 1;
        bitWrite(trend_4way_valve[i], 0, bitRead(trend_4way_valve[i + 1], 15));
      }
      bitWrite(trend_fan[19], 0, bitRead(relay, 0));
      bitWrite(trend_kompressor[19], 0, bitRead(relay, 2));
      bitWrite(trend_pump[19], 0, bitRead(relay, 3));
      bitWrite(trend_4way_valve[19], 0, bitRead(relay, 1));

видимо, сейчас не двигает нолики и единички в 19-ом значении.
Попробую дома изменить текущий код на for (uint8_t i = 0; i < 20; i++) . Посмотрю, может решится вопрос.

Единственная возможность - это файл протокола (log-файл). Картинка такую возможность не предоставляет. В принципе, такую возможность можно было бы реализовать, если заменить единственную картинку на видео (последовательность картинок), но такую возможность Вы сами отвергли.

Ситуация похожа на следующую: Вам нужно прибить одну доску к другой, но у Вас нет ни гвоздей, ни молотка, ни умения пользоваться тем и другим. Заменить гвозди клеем Вы также не соглашаетесь.
Это - тупик.
Сначала Вам следует научиться вести файлы протокола и только после этого возвращаться к отладке своей программы.

Но Ваши попытки не приводят к успеху.
Может, пора прислушаться к тому, что Вам советуют, а не упорствовать в своих “этого я не умею”, “этого у меня нет и вообще воспринимаю предложение как шутку или стеб”. Отложите текущий проект, учитесь, обзаводитесь необходимым для отладки оборудованием и только когда освоите это все, возвращайтесь к проекту.

Сэр когда-нибудь слышал такое слово как “штатив”?

“Серийный” (на самом деле “последовательный”) порт принимает по одному байту. А на более высоком уровне уже работает некоторая программа. Если передача прервется в процессе передачи байта, этот байт будет принят с ошибкой. Заметит ли программа эту ошибку - зависит от настроек порта, а как отреагирует программа на обнаруженную ошибку - зависит от программы.
В Ардуино по умолчанию обнаружение ошибок отключено, поэтому будет просто принят ошибочный байт.

  1. Титце, Шенк, Полупроводниковая схемотехника.
  2. Хоровиц, Хилл, Искусство схемотехники.
  3. Керниган, Ритчи, Язык программирования Си.
  4. Шилдт - любая книжка по Си++.

Так надо в файл писать, а не на экран выводить.

Это одна из причин, по которой нужно отлаживаться на макете, а не на "живой установке.

Для начала - научиться писать в лог-файл осмысленную информацию (т.е. такую, с которой потом знаете, что делать). Начать хотя бы с того, чтобы строка в лог-файле начиналась с имени процедуры, в которой происходит действие.

Поэтому и рекомендуют лог-файл, это работает намного быстрее.

Причин может быть несколько:
Первая - последовательный порт - не очень быстрое устройство. В файл пишется быстрее.
Вторая - нехватка памяти. При работе с портом расходуется дополнительная память и, если ее вдруг где-то не хватает, происходит конфликт.

А почему Вы решили, что она бессмысленная?
Только потому, что Вы не умеете ее использовать?

Вообще-то это одно и то же.
Ну и специально для @BOOM : вот одно из применений значений millis - проверить, хватает ли скорости порта.

Уже было сказано: отлаживаться не на “живой” установке, а на макете. В макет должен входить отдельный блок на другом МК, который по потребности эмулирует данные, приходящие с датчиков.
То есть всего Вам нужно не менее трех МК:
Первый - постоянно работает с установкой.
Второй - для отладки Вашей основной программы.
Третий - для эмуляции датчиков и, возможно, исполнительных устройств.
Когда очередной этап отладки завершен, прошиваете отлаженный при помощи 2-го и 3-го результат в первый МК.

То что я умею организовать запись в монитор порта - это является аналогом “вести файлы протокола”?

Да. Но мне кажется - отчасти, - удалось продвинуться в направлении к успеху. Не без помощи этого форума.

Здесь проблема в том - что я занимаюсь, только лишь пока мне интересно. Обзаводиться необходимым оборудованием, осваивать это всё - мне кажется менее интересным. И боюсь, если я попытаюсь всерьёз заняться этим - то вообще, брошу всё (потеряю интерес).

Думаю, организовав передачу в монитр порта записей из кода - я тем самым заменил вариант “камера на штативе”, и даже - более того.
Отдельное спаибо за ссылку на литературу. Возможно, в какой-то момент времени я вернусь к этому перечню и попытаюсь что-то прочитать, осмыслить. Но в данный момент - мне кажется, что весь мой интерес “держится на ниточке” и попытка действительно углубиться, так сказать “более профессионально” - лишь приведёт к потере интереса. Вряд ли я в состоянии “постичь”.

Как это делается по-простому? Если не очень удобне тут отвечать - может ссылку подскажите, может в интернете где кратко написано? Только - чтобы просто, с помощью IDE.

На такие подвиги - пока не готов…

Достал варистор. Планирую присоединить его параллельно катушке индуктивности (приводу 4-ёх ходового клапана) и снова попытаться отследить, где “споткнётся” контроллер.

Почему ты так боишься сделать правильно? Боишься бросить? - бросай сразу.
Причем тут “Ардуино ИДЕ” и его сериал монитор? Ведь программ для записи из компорта в файл - множество:

Или открой любой ИИ, который доступен в РФ, я не знаю какие у вас доступны, и попроси написать скрипт для сохранения логов в файл. Вот прямо так и попроси, обычным русским языком. ИИ напишет тебе такой. И жить сразу станет проще.
Это реально три строчки кода. Ну 10, если все считать.
Вот просто пример на Питоне, чтоб не боялся. будет писать в файл. Порт, имя и скорость задаёшь и запускаешь.

Спойлер
import serial
from datetime import datetime

PORT = "COM3"
BAUD = 115200
LOGFILE = "arduino_log.txt"

with serial.Serial(PORT, BAUD, timeout=1) as ser:
    print(f"Logging {PORT} at {BAUD} baud to {LOGFILE}")

    while True:
        data = ser.readline()
        if not data:
            continue

        text = data.decode(errors="replace").rstrip()

        timestamp = datetime.now().strftime("%H:%M:%S")
        line = f"{timestamp}  {text}"

        print(line)

        with open(LOGFILE, "a", encoding="utf-8") as f:
            f.write(line + "\n")
            f.flush()

Залез во внутрь внешнего блока, вставил варистор FNR 10k431 в клеммы, куда втыкается катушка электромагнита привода 4-ёх ходового клапана


По наводке WladDrakula, загрузил на ноутбук PuTTY, разобрался, как сделать так, чтобы она писала лог в файл. Поначалу - совершенно не понял разницы, между чёрным её окошком и монитором порта IDE. Но позже обнаружил - что если перезагрузить контроллер - то PuTTY продолжает запись, в то время как IDE у меня - останавливается. Увидев это - я вернул в код // Детектор причины перезагрузки и принудительно попробовал перезагрузить МК. К сожалению - при новом старте - причину перезагрузки не увидел.
Наладил отображение жёлтых трендов состояния реле, прописал чтобы в порт печаталось состояние реле, непосредственно перед их срабатыванием. Код загрузил такой:

Спойлер
/*
   ПРОГРАММА ДЛЯ МОНИТОРИНГА ТЕПЛОВОГО НАСОСА
   ФИНАЛЬНАЯ ВЕРСИЯ СО ВСЕМИ ИСПРАВЛЕНИЯМИ
*/

// ========== 1. ПОДКЛЮЧАЕМ БИБЛИОТЕКИ ==========
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#include <OneWire.h>
OneWire ds(21);

// ========== 2. НАСТРОЙКИ ПИНОВ ДЛЯ ДИСПЛЕЯ ==========
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

// ========== 3. ЗАДАЁМ ЦВЕТА ==========
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define WHITEGREY  0xC638
#define DARKGREY  0x7BEF
#define DARKGREEN 0x0C80

// ========== 4. ПИНЫ ДЛЯ СЧЁТЧИКОВ ==========
#define pinVoda_tick   18
boolean stateCheck_voda;

#define pinElectr_tick  19
boolean stateCheck_electr;

// ========== 5. ПЕРЕМЕННАЯ ДЛЯ УПРАВЛЕНИЯ РЕЛЕ ==========
uint8_t relay;

// ========== 6. АДРЕСА ДАТЧИКОВ ТЕМПЕРАТУРЫ ==========
byte ADDR_DS18B20 [6][8] = {
  {0x28, 0xD5, 0x97, 0x76, 0x0, 0x0, 0x0, 0x76},
  {0x28, 0x4F, 0x9C, 0x73, 0x0, 0x0, 0x0, 0xF9},
  {0x28, 0xFC, 0xD1, 0x72, 0x0, 0x0, 0x0, 0x2D},
  {0x28, 0x95, 0x28, 0x75, 0x0, 0x0, 0x0, 0xAB},
  {0x28, 0xEF, 0x8C, 0x76, 0x0, 0x0, 0x0, 0x58},
  {0x28, 0x8C, 0x3A, 0xB4, 0xE, 0x0, 0x0, 0xDB}
};

// ========== 7. МАССИВЫ ДЛЯ ГРАФИКОВ ==========
uint8_t tIsparitel[320];
uint8_t tOverheat[320];
uint8_t tKompressor[320];
uint8_t tWaterIn[320];
uint8_t tWaterOut[320];
uint8_t tDefrost[320];
uint8_t heatPower[320];
uint8_t gWater[320];
uint8_t ElectrPow[320];
uint8_t COP[320];

// ========== 8. ТОЧНЫЕ ЗНАЧЕНИЯ ==========
int16_t tOverheatReal;
int32_t gWaterReal;
int32_t heatPowerReal;
int32_t ElectrPowReal;
int32_t COPreal;

int32_t gWaterRealPrew;
boolean FlagWater = false;
boolean FirstImpulsWater = false;
boolean SecondImpulsWater = false;

// ========== 9. СРЕДНИЕ ЗНАЧЕНИЯ ==========
int32_t countHeatAndElectr = 0;
int32_t countHeat = 0;
int32_t countElectr = 0;

// ========== 10. ФЛАГИ ЦИКЛА ==========
boolean Flag1 = true;
boolean Flag2 = true;
boolean Flag3 = true;
boolean Flag4 = true;
uint8_t countGetGrafic = 9;
uint32_t Timer;

// ========== 11. МАССИВЫ ДЛЯ ГРАФИКОВ СОСТОЯНИЯ РЕЛЕ ==========
int16_t trend_fan[20];
int16_t trend_kompressor[20];
int16_t trend_pump[20];
int16_t trend_4way_valve[20];

// ========== 12. ПЕРЕМЕННЫЕ ДЛЯ РАСХОДОМЕРА ВОДЫ ==========
uint32_t tmr;
boolean gWaterFlag = false;
uint32_t WaterStartTimer = 0;
uint32_t WaterCountTimer;

// ========== 13. ПЕРЕМЕННЫЕ ДЛЯ ЭЛЕКТРОСЧЁТЧИКА ==========
uint32_t tmr2;
boolean ElectrFlag = false;
uint32_t ElectrStartTimer = 0;
uint32_t ElectrCountTimer;

// ========== 14. ФЛАГИ РЕЖИМОВ РАБОТЫ ==========
boolean StartHeatFlag;
boolean StopFlag;
boolean HeatOptionFlag;
boolean HeatOptionPauseFlag;
boolean DefrostOptionFlag;

// ========== 15. СЧЁТЧИКИ ДЛЯ ЗАЩИТЫ ==========
uint8_t tKompressorCounter = 0;
uint8_t HeatOptionCout = 0;
uint8_t HeatOptionPauseCout = 0;
uint8_t defrostCount = 0;
uint8_t StopMaxTemp = 0;
uint8_t StopMaxElectr = 0;
uint8_t StopMinTempHeater = 0;
uint8_t StopNo4xvalve = 0;
uint8_t StopNoElectric = 0;

uint8_t StopKind = 0;
uint8_t MistakeTemp[6] = {};
boolean getMistakeFlag = false;

// ========== 16. ВРЕМЕННЫЕ МЕТКИ ==========
uint32_t HeatOptionPauseStartTime;
uint32_t StartHeatTime;
uint32_t StopTime;
uint32_t DefrostTime;

// ========== 17. МАССИВЫ ТЕМПЕРАТУР ==========
int16_t Temper[6] = {0, 0, 0, 0, 0, 0};
int16_t TemperPrev[6];

// ========== 18. ФУНКЦИЯ ПРОВЕРКИ CRC ==========
uint8_t dallas_crc8(const uint8_t *data, uint8_t len) {
  uint8_t crc = 0;
  for (uint8_t i = 0; i < len; i++) {
    uint8_t inbyte = data[i];
    for (uint8_t j = 0; j < 8; j++) {
      uint8_t mix = (crc ^ inbyte) & 0x01;
      crc >>= 1;
      if (mix) crc ^= 0x8C;
      inbyte >>= 1;
    }
  }
  return crc;
}

// ========== 19. ФУНКЦИЯ ЧТЕНИЯ ТЕМПЕРАТУРЫ С ДАТЧИКА (ИСПРАВЛЕНО) ==========
bool readDS18B20(byte *addr, int16_t *dest) {
  uint8_t data[9];
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);
  for (uint8_t i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
  if (dallas_crc8(data, 8) != data[8]) {
    return false;
  }
  int16_t raw = (int16_t)((data[1] << 8) | data[0]);
  *dest = (raw * 5) / 8;  // Правильная формула (работает с отрицательными)
  return true;
}

// ========== 20. ФУНКЦИЯ ЗАПУСКА ИЗМЕРЕНИЯ ТЕМПЕРАТУРЫ ==========
void resetTemp() {
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
}

// ========== 21. ФУНКЦИЯ ПОЛУЧЕНИЯ ТЕМПЕРАТУР ==========
void gettingTemp() {
  int16_t temp;
  for (uint8_t i = 0; i < 6; i++) {
    if (readDS18B20(ADDR_DS18B20[i], &temp)) {
      // CRC прошёл — данные достоверны
      Temper[i] = temp;
      TemperPrev[i] = temp;
      if (MistakeTemp[i] <= 6) MistakeTemp[i] = 0;
    } else {
      // CRC не прошёл — это ошибка!
      // Temper[i] не меняем (остаётся предыдущее значение)
      if (StopFlag == false) {
        MistakeTemp[i]++;
        if (MistakeTemp[i] > 6) {
          StopFlag = true;
          StopTime = millis();
          StopKind = 6;
        }
      }
    }
  }
}

// ========== 22. ПРОВЕРКА ГРАНИЦ ТЕМПЕРАТУР (ИСПРАВЛЕНО) ==========
void tempMistake(uint8_t a, int16_t b, int16_t c, int16_t d) {
  // Если значение в норме — сбрасываем счётчик ошибок
  if (Temper[a] >= b && Temper[a] <= c && abs(Temper[a] - TemperPrev[a]) <= d) {
    MistakeTemp[a] = 0;
    return;
  }

  // Ошибка! Откатываем на предыдущее значение
  Temper[a] = TemperPrev[a];

  if (StopFlag == false) {
    MistakeTemp[a]++;

    if (MistakeTemp[a] > 6) {
      StopFlag = true;
      StopTime = millis();
      StopKind = 6;
    }
  }
}

// ========== 23. ОБРАБОТЧИК ИМПУЛЬСОВ СЧЁТЧИКА ВОДЫ (ИСПРАВЛЕНО) ==========
void voda_tick() {
  //Serial.print("proverka");
  boolean current_status = digitalRead(pinVoda_tick);
  if (stateCheck_voda && !current_status) {
    tmr = millis();
    gWaterFlag = true;
    stateCheck_voda = current_status;
    return;
  }
  if (!stateCheck_voda && current_status) {
    stateCheck_voda = current_status;
    return;
  }
  if (current_status) {
    gWaterFlag = false;
    return;
  }
  if (!current_status && (millis() - tmr >= 1000) && gWaterFlag == true) {
    if (WaterStartTimer == 0) {
      WaterStartTimer = millis();
      gWaterFlag = false;
      return;
    }
    WaterCountTimer = millis() - WaterStartTimer;
    WaterStartTimer = millis();
    gWaterFlag = false;
    if (FirstImpulsWater == true) SecondImpulsWater = true;
    FirstImpulsWater = true;
  }
}

// ========== 24. ОБРАБОТЧИК ИМПУЛЬСОВ ЭЛЕКТРОСЧЁТЧИКА (ИСПРАВЛЕНО) ==========
void electr_tick() {
  //Serial.println("proverka");
  boolean current_status = digitalRead(pinElectr_tick);
  if (stateCheck_electr && !current_status) {
    tmr2 = millis();
    ElectrFlag = true;
    stateCheck_electr = current_status;
    return;
  }
  if (!stateCheck_electr && current_status) {
    stateCheck_electr = current_status;
    return;
  }
  if (current_status) {
    ElectrFlag = false;
    return;
  }
  if (!current_status && (millis() - tmr2 >= 50) && ElectrFlag == true) {
    if (ElectrStartTimer == 0) {
      ElectrStartTimer = millis();
      ElectrFlag = false;
      return;
    }
    ElectrCountTimer = millis() - ElectrStartTimer;
    ElectrStartTimer = millis();
    ElectrFlag = false;
  }
}

// ========== 25. ФУНКЦИИ ВЫВОДА ЧИСЕЛ НА ДИСПЛЕЙ ==========
void getDataInt100(int16_t a) {
  //Serial.println("proverka");
  if (a >= -9 && a < 0) {
    tft.print("-0.0"); tft.print(abs(a));
  } else if (a < 9 && a >= 0) {
    tft.print("0.0"); tft.print(a);
  } else if (a <= -10 && a > -100) {
    tft.print("-0."); tft.print(abs(a % 100));
  } else {
    tft.print(a / 100); tft.print(".");
    if (abs(a % 100) < 10) tft.print("0");
    tft.print(abs(a % 100));
  }
}

void getDataInt10(int16_t a) {
  if (a >= -9 && a < 0) {
    tft.print("-0."); tft.print(abs(a));
  } else if (a < 9 && a >= 0) {
    tft.print("0."); tft.print(a);
  } else {
    tft.print(a / 10); tft.print(".");
    tft.print(abs(a % 10));
  }
}

// ========== 26. ПРЕОБРАЗОВАНИЕ ЧИСЕЛ ДЛЯ ГРАФИКА ==========
int16_t getDataForUintMassiv(int16_t a) {
  //Serial.println("proverka");
  int16_t LastInMassive;
  if (a < -400) LastInMassive = 0;
  else if (a >= -400 && a < 500) LastInMassive = round((a + 400) / 5);
  else if (a >= 500 && a < 1250) LastInMassive = round(180 + (a - 500) / 10);
  else LastInMassive = 255;
  return LastInMassive;
}

int32_t getDataForUintMassiv32(int32_t a) {
  int32_t LastInMassive;
  if (a < -400) LastInMassive = 0;
  else if (a >= -400 && a < 0) LastInMassive = round((a + 400) / 10);
  else if (a >= 0 && a <= 160) LastInMassive = round(40 + a);
  else if (a > 160 && a < 710) LastInMassive = round(200 + (a - 160) / 10);
  else LastInMassive = 255;
  return LastInMassive;
}

// ========== 27. ОТРИСОВКА ГРАФИКОВ ==========
void getGraphics(uint16_t c, uint16_t d, uint8_t g[320]) {
  //Serial.println("proverka");
  int16_t oldX = 0;
  int16_t oldY = g[0];
  for (int16_t x = 1; x < 320; x++) {
    int16_t nxt_x = x;
    tft.drawLine(oldX, (c - oldY), nxt_x, (c - g[x]), d);
    oldY = g[x];
    oldX = nxt_x;
  }
}

// ========== 28. ОТРИСОВКА ВСЕГО ЭКРАНА ==========
void getMainDisplay() {
  //Serial.println("proverka");
  tft.fillScreen(BLACK);

  for (uint8_t i = 1; i < 8; i++) {
    tft.drawFastVLine((40 * i), 20, 190, DARKGREY);
    tft.drawFastVLine((40 * i), 230, 210, DARKGREY);
  }

  for (uint8_t i = 0; i < 11; i++) {
    if (i == 4 || i == 5 || i == 6 || i == 7 || i == 9 || i == 10)
      tft.drawFastHLine(0, (5 + 20 * i), 320, DARKGREEN);
    else if (i == 1 || i == 2 || i == 3 || i == 8)
      tft.drawFastHLine(0, (5 + 20 * i), 320, BLUE);
  }

  for (uint8_t i = 0; i < 5; i++)
    tft.drawFastHLine(0, (231 + 10 * i), 320, BLUE);

  tft.drawFastHLine(0, 275, 320, BLUE);

  for (uint8_t i = 0; i < 8; i++)
    tft.drawFastHLine(0, (295 + 20 * i), 320, DARKGREEN);

  tft.setTextSize(1);

  tft.setCursor(0, 22); tft.setTextColor(WHITE, BLACK); tft.print("90");
  tft.setCursor(0, 42); tft.print("70");
  tft.setCursor(0, 62); tft.print("50");
  tft.setCursor(0, 82); tft.print("40");
  tft.setCursor(0, 102); tft.print("30");
  tft.setCursor(0, 122); tft.print("20");
  tft.setCursor(0, 142); tft.print("10");
  tft.setCursor(0, 162); tft.print("0");
  tft.setCursor(0, 182); tft.print("-10");
  tft.setCursor(0, 202); tft.print("-20");

  tft.setCursor(0, 238); tft.print("5");
  tft.setCursor(0, 258); tft.print("3");
  tft.setCursor(0, 272); tft.print("1.6");
  tft.setCursor(0, 292); tft.print("1.4");
  tft.setCursor(0, 312); tft.print("1.2");
  tft.setCursor(0, 332); tft.print("1");
  tft.setCursor(0, 352); tft.print("0.8");
  tft.setCursor(0, 372); tft.print("0.6");
  tft.setCursor(0, 392); tft.print("0.4");
  tft.setCursor(0, 412); tft.print("0.2");
  tft.setCursor(0, 432); tft.print("0");

  tft.setCursor(0, 0); tft.setTextColor(RED); tft.print("Kompressor:");
  tft.setCursor(10, 10); tft.setTextColor(MAGENTA); tft.print("Overheat:");
  tft.setCursor(125, 10); tft.setTextColor(CYAN); tft.print("Defrost:");
  tft.setCursor(220, 10); tft.setTextColor(RED); tft.print("Isparitel:");
  tft.setCursor(120, 0); tft.setTextColor(YELLOW); tft.print("Water in:");
  tft.setCursor(220, 0); tft.setTextColor(GREEN); tft.print("Water out:");
  tft.setCursor(5, 210); tft.setTextColor(RED); tft.print("Heat power:");
  tft.setCursor(152, 210); tft.setTextColor(YELLOW); tft.print("COP:");
  tft.setCursor(218, 210); tft.setTextColor(GREEN); tft.print("Electr pow:");
  tft.setCursor(22, 220); tft.setTextColor(MAGENTA); tft.print("G water:");
}

// ========== 29. НАЧАЛЬНАЯ НАСТРОЙКА ==========
void setup() {
  Serial.begin(9600);
  Serial.print("proverka");

    // Детектор причины перезагрузки
  Serial.print("MCUSR=0x");
  Serial.println(MCUSR, HEX);
  if (MCUSR & (1 << PORF)) Serial.println("RESET: Power-on reset");
  if (MCUSR & (1 << EXTRF)) Serial.println("RESET: External reset (пин RESET)");
  if (MCUSR & (1 << BORF)) Serial.println("RESET: Brown-out (просадка питания)");
  if (MCUSR & (1 << WDRF)) Serial.println("RESET: Watchdog (зависание)");
  MCUSR = 0;

  tft.reset();
  tft.begin(38022);
  tft.invertDisplay(true);

  pinMode(18, INPUT_PULLUP);
  stateCheck_voda = digitalRead(pinVoda_tick);

  pinMode(19, INPUT_PULLUP);
  stateCheck_electr = digitalRead(pinElectr_tick);

  for (int i = 0; i < 320; i++) {
    tIsparitel[i] = 80;
    tOverheat[i] = 80;
    tKompressor[i] = 80;
    tWaterIn[i] = 80;
    tWaterOut[i] = 80;
    tDefrost[i] = 80;
    heatPower[i] = 40;
    gWater[i] = 40;
    ElectrPow[i] = 40;
    COP[i] = 40;
  }

  pinMode(48, OUTPUT); digitalWrite(48, HIGH);
  pinMode(49, OUTPUT); digitalWrite(49, HIGH);
  pinMode(50, OUTPUT); digitalWrite(50, HIGH);
  pinMode(51, OUTPUT); digitalWrite(51, HIGH);

  StopFlag = false;
  HeatOptionFlag = false;
  HeatOptionPauseFlag = false;
  DefrostOptionFlag = false;
  StartHeatFlag = true;
  StartHeatTime = millis();
  Timer = millis();

  Serial.println("=== SETUP COMPLETE ===");
  delay(1000);
}

// ========== 30. ГЛАВНЫЙ ЦИКЛ ==========
void loop() {

  // ===== ДИАГНОСТИКА ВРЕМЕНИ =====
  Serial.print("lm=");
  Serial.print(millis());
  Serial.print(" T=");
  Serial.println(Timer);
  // ================================

  voda_tick();
  electr_tick();

  // Шаг 1: запуск конвертации (3-5 сек)
  if (millis() - Timer >= 3000 && millis() - Timer < 5000 && Flag1 == true) {
    Serial.println(">>> Step 1: resetTemp");
    //Serial.println("proverka");
    resetTemp();
    Flag1 = false;
  }

  // Шаг 2: чтение температур (5-7 сек)
  if (millis() - Timer >= 5000 && millis() - Timer < 7000 && Flag2 == true) {
    Serial.println(">>> Step 2: gettingTemp");
    //Serial.println("proverka");
    gettingTemp();
    Flag2 = false;
  }

  // Шаг 3: расчёты и логика (7-9 сек)
  if (millis() - Timer >= 7000 && millis() - Timer < 9000 && Flag3 == true) {
    Serial.println(">>> Step 3 START");

    if (getMistakeFlag == false) {
      for (uint8_t i = 0; i < 6; i++) TemperPrev[i] = Temper[i];
      getMistakeFlag = true;
    }

    tempMistake(0, -100, 1200, 200);
    tempMistake(1, 0, 600, 100);
    tempMistake(2, 0, 900, 50);
    tempMistake(3, -400, 800, 400);
    tempMistake(4, -400, 600, 300);
    tempMistake(5, -400, 800, 200);

    tOverheatReal = (Temper[3] - Temper[5]);

    // Расход воды
    if (digitalRead(51) == HIGH) {
      gWaterReal = 0;
      gWaterRealPrew = gWaterReal;
      FlagWater = false;
    } else if (digitalRead(51) == LOW && millis() - WaterStartTimer > 400000) {
      StopFlag = true; StopTime = millis(); StopKind = 7;
    } else if (SecondImpulsWater == false) {
      gWaterReal = gWaterRealPrew; FlagWater = true;
    } else {
      gWaterReal = round(3600000 / WaterCountTimer);
      gWaterRealPrew = gWaterReal; FlagWater = false;
    }

    // Электрическая мощность
    if (millis() - ElectrStartTimer > 60000) ElectrPowReal = 0;
    else ElectrPowReal = 72000 / ElectrCountTimer;

    // Тепловая мощность и COP
    heatPowerReal = ((int32_t)Temper[2] - (int32_t)Temper[1]) * gWaterReal * 1163 / 10000;
    if (ElectrPowReal < 10) COPreal = 0;
    else COPreal = 100 * heatPowerReal / ElectrPowReal;

    countHeat = countHeat + heatPowerReal;
    countElectr = countElectr + ElectrPowReal;
    countHeatAndElectr++;

    // Управление вентилятором при перегреве
    if (HeatOptionFlag == true && Temper[0] >= 850 && tOverheatReal >= 300 && digitalRead(48) == LOW) {
      tKompressorCounter++;
      if (tKompressorCounter >= 4) {
        bitClear(relay, 0);
        tKompressorCounter = 0;
      }
    } else if (HeatOptionFlag == true && (Temper[0] <= 750 || tOverheatReal <= 200) && digitalRead(48) == HIGH) {
      tKompressorCounter++;
      if (tKompressorCounter >= 2) {
        bitSet(relay, 0);
        tKompressorCounter = 0;
      }
    } else tKompressorCounter = 0;

    // Режимы нагрева
    if (HeatOptionFlag == true && Temper[1] >= 360) {
      HeatOptionCout++;
      if (HeatOptionCout >= 6) {
        HeatOptionFlag = false; HeatOptionPauseFlag = true; HeatOptionCout = 0;
        HeatOptionPauseStartTime = millis(); bitClear(relay, 2); bitClear(relay, 0);
      }
    } else HeatOptionCout = 0;

    if (HeatOptionPauseFlag == true && digitalRead(49) == LOW && millis() - HeatOptionPauseStartTime >= 120000)
      bitClear(relay, 1);

    if (HeatOptionPauseFlag == true && digitalRead(51) == HIGH && millis() - HeatOptionPauseStartTime >= 960000) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis(); FirstImpulsWater = false; SecondImpulsWater = false;
      }
      bitSet(relay, 3); HeatOptionPauseStartTime = millis();
    }

    if (HeatOptionPauseFlag == true && digitalRead(51) == LOW && millis() - HeatOptionPauseStartTime >= 60000) {
      bitClear(relay, 3); HeatOptionPauseStartTime = millis();
    }

    if (HeatOptionPauseFlag == true && Temper[1] <= 280) {
      HeatOptionPauseCout++;
      if (HeatOptionPauseCout >= 5) {
        HeatOptionPauseFlag = false; HeatOptionPauseCout = 0;
        StartHeatTime = millis(); StartHeatFlag = true;
      }
    } else HeatOptionPauseCout = 0;

    // Defrost
    if (HeatOptionFlag == true && Temper[5] < -100) {
      defrostCount++;
      if (defrostCount >= 6) {
        HeatOptionFlag = false; DefrostOptionFlag = true; DefrostTime = millis(); defrostCount = 0;
      }
    } else defrostCount = 0;

    // Защиты
    if (HeatOptionFlag == true && digitalRead(49) == HIGH) {
      StopNo4xvalve++;
      if (StopNo4xvalve >= 3) {
        bitClear(relay, 2); StopFlag = true; StopTime = millis(); StopKind = 1; StopNo4xvalve = 0;
      }
    } else StopNo4xvalve = 0;

    if ((StartHeatFlag || HeatOptionFlag || HeatOptionPauseFlag || DefrostOptionFlag) && Temper[0] >= 1000) {
      StopMaxTemp++;
      if (StopMaxTemp >= 5) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 2;
        StopMaxTemp = 0;
      }
    } else StopMaxTemp = 0;

    if ((StartHeatFlag || HeatOptionFlag || HeatOptionPauseFlag || DefrostOptionFlag) && ElectrPowReal >= 151) {
      StopMaxElectr++;
      if (StopMaxElectr >= 6) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 3;
        StopMaxElectr = 0;
      }
    } else StopMaxElectr = 0;

    if ((StartHeatFlag || HeatOptionFlag || HeatOptionPauseFlag) && Temper[4] <= 50) {
      StopMinTempHeater++;
      if (StopMinTempHeater >= 3) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 4;
        StopMinTempHeater = 0;
      }
    } else StopMinTempHeater = 0;

    if (digitalRead(50) == LOW && ElectrPowReal <= 10) {
      StopNoElectric++;
      if (StopNoElectric >= 6) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 5;
        StopNoElectric = 0;
      }
    } else StopNoElectric = 0;

    // Start heat
    if (StartHeatFlag && millis() - StartHeatTime >= 20000 && Temper[1] >= 50) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis(); FirstImpulsWater = false; SecondImpulsWater = false;
      }
      bitSet(relay, 3);
    }
    if (StartHeatFlag && digitalRead(51) == LOW && millis() - StartHeatTime >= 30000 && Temper[0] <= 850) bitSet(relay, 0);
    if (StartHeatFlag && digitalRead(51) == LOW && digitalRead(48) == LOW && millis() - StartHeatTime >= 40000) bitSet(relay, 1);
    if (StartHeatFlag && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(49) == LOW && millis() - StartHeatTime >= 45000) bitSet(relay, 2);
    if (StartHeatFlag && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(50) == LOW && digitalRead(49) == LOW) {
      StartHeatFlag = false; HeatOptionFlag = true;
    }

    // Stop
    if (StopFlag) {
      StartHeatFlag = false; HeatOptionFlag = false; HeatOptionPauseFlag = false; DefrostOptionFlag = false;
      bitClear(relay, 2); bitClear(relay, 0);
      if (millis() - StopTime >= 120000) bitClear(relay, 1);
      if (millis() - StopTime >= 180000) bitClear(relay, 3);
    }

    // Defrost
    if (DefrostOptionFlag) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis(); FirstImpulsWater = false; SecondImpulsWater = false;
      }
      bitSet(relay, 3); bitClear(relay, 2); bitSet(relay, 0);
      if (millis() - DefrostTime >= 120000) bitClear(relay, 1);
      if (millis() - DefrostTime >= 900000 && Temper[5] >= 20) {
        DefrostOptionFlag = false; StartHeatTime = millis(); StartHeatFlag = true;
      }
    }

    // Вывод на дисплей
    tft.fillRect(74, 0, 30, 20, BLACK);
    tft.fillRect(181, 0, 30, 20, BLACK);
    tft.fillRect(289, 0, 30, 20, BLACK);
    tft.fillRect(74, 210, 30, 20, BLACK);
    tft.fillRect(181, 210, 30, 10, BLACK);
    tft.fillRect(289, 210, 30, 10, BLACK);
    tft.fillRect(152, 220, 60, 10, BLACK);
    tft.fillRect(100, 470, 30, 8, BLACK);
    tft.fillRect(200, 470, 30, 8, BLACK);

    tft.setCursor(74, 0);
    tft.setTextColor(RED, (MistakeTemp[0] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[0]);

    tft.setCursor(181, 0);
    tft.setTextColor(YELLOW, (MistakeTemp[1] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[1]);

    tft.setCursor(289, 0);
    tft.setTextColor(GREEN, (MistakeTemp[2] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[2]);

    tft.setCursor(74, 10);
    tft.setTextColor(MAGENTA, (MistakeTemp[3] > 0) ? WHITE : BLACK);
    getDataInt10(tOverheatReal);

    tft.setCursor(181, 10);
    tft.setTextColor(CYAN, (MistakeTemp[4] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[4]);

    tft.setCursor(289, 10);
    tft.setTextColor(RED, (MistakeTemp[5] > 0) ? WHITE : BLACK);
    getDataInt10(Temper[5]);

    tft.setCursor(74, 210); tft.setTextColor(RED); getDataInt100(heatPowerReal);
    tft.setCursor(181, 210); tft.setTextColor(YELLOW); getDataInt100(COPreal);
    tft.setCursor(289, 210); tft.setTextColor(GREEN); getDataInt100(ElectrPowReal);
    tft.setCursor(74, 220);
    tft.setTextColor(MAGENTA, FlagWater ? WHITE : BLACK);
    getDataInt100(gWaterReal);

    tft.setCursor(100, 470); tft.setTextColor(RED);
    getDataInt100(countHeat / countHeatAndElectr);
    tft.setCursor(200, 470); tft.setTextColor(GREEN);
    getDataInt100(countElectr / countHeatAndElectr);

    tft.setCursor(152, 220); tft.setTextColor(RED);
    if (StopFlag == true) {
      tft.print("Stop");
      switch (StopKind) {
        case 1: tft.print(" No 4x valve"); break;
        case 2: tft.print(" maxT Kompr"); break;
        case 3: tft.print(" maxW Electr"); break;
        case 4: tft.print(" minT Heater"); break;
        case 5: tft.print(" No Electr"); break;
        case 6: tft.print(" Err Temp"); break;
        case 7: tft.print(" No G_water"); break;
        case 8: tft.print(" No Option"); break;
      }
    } else if (StartHeatFlag == true) {
      tft.print("Start heat");
    } else if (HeatOptionFlag == true) {
      tft.print("Heat option");
    } else if (HeatOptionPauseFlag == true) {
      tft.print("Pause heat");
    } else if (DefrostOptionFlag == true) {
      tft.print("Defrost");
    } else {
      StopFlag = true; StopTime = millis(); StopKind = 8;
    }

    tft.setCursor(0, 440);
    tft.setTextColor(bitRead(relay, 2) ? RED : BLUE); tft.print("Kompressor");
    tft.setCursor(0, 450);
    tft.setTextColor(bitRead(relay, 3) ? RED : BLUE); tft.print("Pump");
    tft.setCursor(0, 460);
    tft.setTextColor(bitRead(relay, 1) ? RED : BLUE); tft.print("4 way valve");
    tft.setCursor(0, 470);
    tft.setTextColor(bitRead(relay, 0) ? RED : BLUE); tft.print("Fan");

    Flag3 = false;
    Serial.print("relay");
    Serial.println(relay, BIN);
    Serial.println(">>> Step 3 END");
  }

  // Шаг 4: управление реле (9-10 сек)
  if (millis() - Timer >= 9000 && millis() - Timer < 10000 && Flag4 == true) {
    Serial.println(">>> Step 4: Relays");
    digitalWrite(48, bitRead(relay, 0) ? LOW : HIGH);
    digitalWrite(49, bitRead(relay, 1) ? LOW : HIGH);
    digitalWrite(50, bitRead(relay, 2) ? LOW : HIGH);
    digitalWrite(51, bitRead(relay, 3) ? LOW : HIGH);
    Flag4 = false;
  }

  // Шаг 5: обновление графиков (каждые 10 сек)
  if (millis() - Timer >= 10000) {
    Serial.println(">>> Step 5: Graphics reset, Cycle END");
    Timer = millis();

    if (countGetGrafic >= 9) {
      //Serial.println("proverka");
      for (uint16_t x = 0; x < 319; x++) {
        tIsparitel[x] = tIsparitel[x + 1];
        tOverheat[x] = tOverheat[x + 1];
        tKompressor[x] = tKompressor[x + 1];
        tWaterIn[x] = tWaterIn[x + 1];
        tWaterOut[x] = tWaterOut[x + 1];
        gWater[x] = gWater[x + 1];
        heatPower[x] = heatPower[x + 1];
        ElectrPow[x] = ElectrPow[x + 1];
        COP[x] = COP[x + 1];
        tDefrost[x] = tDefrost[x + 1];
      }

      tKompressor[319] = (uint8_t)getDataForUintMassiv(Temper[0]);
      tWaterIn[319] = (uint8_t)getDataForUintMassiv(Temper[1]);
      tWaterOut[319] = (uint8_t)getDataForUintMassiv(Temper[2]);
      tOverheat[319] = (uint8_t)getDataForUintMassiv(tOverheatReal);
      tDefrost[319] = (uint8_t)getDataForUintMassiv(Temper[4]);
      tIsparitel[319] = (uint8_t)getDataForUintMassiv(Temper[5]);
      heatPower[319] = (uint8_t)getDataForUintMassiv32(heatPowerReal);
      COP[319] = (uint8_t)getDataForUintMassiv32(COPreal);
      ElectrPow[319] = (uint8_t)getDataForUintMassiv32(ElectrPowReal);
      gWater[319] = (uint8_t)getDataForUintMassiv32(gWaterReal);

      for (uint8_t i = 0; i < 20; i++) {
        trend_fan[i] = trend_fan[i] << 1;
        bitWrite(trend_fan[i], 0, bitRead(trend_fan[i + 1], 15));
        trend_kompressor[i] = trend_kompressor[i] << 1;
        bitWrite(trend_kompressor[i], 0, bitRead(trend_kompressor[i + 1], 15));
        trend_pump[i] = trend_pump[i] << 1;
        bitWrite(trend_pump[i], 0, bitRead(trend_pump[i + 1], 15));
        trend_4way_valve[i] = trend_4way_valve[i] << 1;
        bitWrite(trend_4way_valve[i], 0, bitRead(trend_4way_valve[i + 1], 15));
      }
      bitWrite(trend_fan[19], 0, bitRead(relay, 0));
      bitWrite(trend_kompressor[19], 0, bitRead(relay, 2));
      bitWrite(trend_pump[19], 0, bitRead(relay, 3));
      bitWrite(trend_4way_valve[19], 0, bitRead(relay, 1));

      getMainDisplay();

      getGraphics(245, RED, tKompressor);
      getGraphics(245, YELLOW, tWaterIn);
      getGraphics(245, GREEN, tWaterOut);
      getGraphics(245, MAGENTA, tOverheat);
      getGraphics(245, CYAN, tDefrost);
      getGraphics(245, RED, tIsparitel);
      getGraphics(475, RED, heatPower);
      getGraphics(475, YELLOW, COP);
      getGraphics(475, GREEN, ElectrPow);
      getGraphics(475, MAGENTA, gWater);

      for (uint8_t i = 0; i < 20; i++) {
        for (uint8_t j = 0; j < 16; j++) {
          if (bitRead(trend_fan[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 479, YELLOW);
          if (bitRead(trend_kompressor[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 449, YELLOW);
          if (bitRead(trend_pump[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 459, YELLOW);
          if (bitRead(trend_4way_valve[i], j) == 1) tft.drawPixel((i * 16 + (15 - j)), 469, YELLOW);
        }
      }

      countGetGrafic = 0;
    }

    countGetGrafic++;
    Flag1 = true;
    Flag2 = true;
    Flag3 = true;
    Flag4 = true;
  }
}

Подключил всю силовую часть. Запустил из программы PuTTY. Пошла запись в файл. Контроллер начал свою программу.
Пока работает, полчаса. Думаю - оставить на ночь.

Не… всё закончилось раньше.
Зайдя в очередной раз посмотреть - увидел такое:


мои предположения, что “PuTTY” сможет писать лог без остановки - не оправдались. Контроллер был в работе, а запись лога остановилась.
Последние строчки из файла лога:

Спойлер
lm=3391975 T=3387098
lm=3391997 T=3387098
lm=3392021 T=3387098
lm=3392044 T=3387098
lm=3392066 T=3387098
lm=3392090 T=3387098
>>> Step 2: gettingTemp
lm=3392203 T=3387098
lm=3392203 T=3387098
lm=3392204 T=3387098
lm=3392207 T=3387098
lm=3392230 T=3387098
lm=3392253 T=3387098
lm=3392276 T=3387098
lm=3392299 T=3387098
lm=3392322 T=3387098
lm=3392345 T=3387098
lm=3392367 T=3387098
lm=3392391 T=3387098
lm=3392413 T=3387098
lm=3392436 T=3387098
lm=3392459 T=3387098
lm=3392482 T=3387098
lm=3392504 T=3387098
lm=3392528 T=3387098
lm=3392550 T=3387098
lm=3392573 T=3387098
lm=3392596 T=3387098
lm=3392619 T=3387098
lm=3392642 T=3387098
lm=3392665 T=3387098
lm=3392688 T=3387098
lm=3392710 T=3387098
lm=3392734 T=3387098
lm=3392756 T=3387098
lm=3392779 T=3387098
lm=3392802 T=3387098
lm=3392825 T=3387098
lm=3392847 T=3387098
lm=3392871 T=3387098
lm=3392893 T=3387098
lm=3392916 T=3387098
lm=3392940 T=3387098
lm=3392962 T=3387098
lm=3392986 T=3387098
lm=3393008 T=3387098
lm=3393031 T=3387098
lm=3393054 T=3387098
lm=3393077 T=3387098
lm=3393099 T=3387098
lm=3393123 T=3387098
lm=3393145 T=3387098
lm=3393168 T=3387098
lm=3393191 T=3387098
lm=3393214 T=3387098
lm=3393236 T=3387098
lm=3393260 T=3387098
lm=3393283 T=3387098
lm=3393305 T=3387098
lm=3393329 T=3387098
lm=3393351 T=3387098
lm=3393374 T=3387098
lm=3393397 T=3387098
lm=3393420 T=3387098
lm=3393442 T=3387098
lm=3393466 T=3387098
lm=3393488 T=3387098
lm=3393511 T=3387098
lm=3393534 T=3387098
lm=3393557 T=3387098
lm=3393580 T=3387098
lm=3393603 T=3387098
lm=3393626 T=3387098
lm=3393648 T=3387098
lm=3393672 T=3387098
lm=3393694 T=3387098
lm=3393718 T=3387098
lm=3393740 T=3387098
lm=3393763 T=3387098
lm=3393786 T=3387098
lm=3393809 T=3387098
lm=3393831 T=3387098
lm=3393855 T=3387098
lm=3393878 T=3387098
lm=3393900 T=3387098
lm=3393924 T=3387098
lm=3393946 T=3387098
lm=3393969 T=3387098
lm=3393992 T=3387098
lm=3394015 T=3387098
lm=3394037 T=3387098
lm=3394061 T=3387098
lm=3394083 T=3387098
>>> Step 3 START
relay1010
>>> Step 3 END
lm=3394347 T=3387098
lm=3394348 T=3387098
lm=3394356 T=3387098
lm=3394378 T=3387098
lm=3394402 T=3387098
lm=3394424 T=3387098
lm=3394447 T=3387098
lm=3394470 T=3387098
lm=3394493 T=3387098
lm=3394515 T=3387098
lm=3394539 T=3387098
lm=3394562 T=3387098
lm=3394584 T=3387098
lm=3394608 T=3387098
lm=3394630 T=3387098
lm=3394653 T=3387098
lm=3394676 T=3387098
lm=3394699 T=3387098
lm=3394721 T=3387098
lm=3394745 T=3387098
lm=3394767 T=3387098
lm=3394790 T=3387098
lm=3394813 T=3387098
lm=3394836 T=3387098
lm=3394859 T=3387098
lm=3394882 T=3387098
lm=3394905 T=3387098
lm=3394927 T=3387098
lm=3394951 T=3387098
lm=3394973 T=3387098
lm=3394996 T=3387098
lm=3395019 T=3387098
lm=3395042 T=3387098
lm=3395064 T=3387098
lm=3395088 T=3387098
lm=3395110 T=3387098
lm=3395134 T=3387098
lm=3395156 T=3387098
lm=3395179 T=3387098
lm=3395203 T=3387098
lm=3395225 T=3387098
lm=3395248 T=3387098
lm=3395271 T=3387098
lm=3395294 T=3387098
lm=3395316 T=3387098
lm=3395340 T=3387098
lm=3395362 T=3387098
lm=3395385 T=3387098
lm=3395408 T=3387098
lm=3395431 T=3387098
lm=3395453 T=3387098
lm=3395477 T=3387098
lm=3395500 T=3387098
lm=3395522 T=3387098
lm=3395546 T=3387098
lm=3395568 T=3387098
lm=3395591 T=3387098
lm=3395614 T=3387098
lm=3395637 T=3387098
lm=3395659 T=3387098
lm=3395683 T=3387098
lm=3395705 T=3387098
lm=3395728 T=3387098
lm=3395751 T=3387098
lm=3395774 T=3387098
lm=3395796 T=3387098
lm=3395820 T=3387098
lm=3395843 T=3387098
lm=3395866 T=3387098
lm=3395889 T=3387098
lm=3395911 T=3387098
lm=3395935 T=3387098
lm=3395957 T=3387098
lm=3395980 T=3387098
lm=3396003 T=3387098
lm=3396026 T=3387098
lm=3396048 T=3387098
lm=3396072 T=3387098
lm=3396094 T=3387098
>>> Step 4: Relays
lm=3396139 T=3387098
lm=3396161 T=3387098
lm=3396184 T=3387098
lm=3396207 T=3387098
lm=3396230 T=3387098
lm=3396252 T=3387098
lm=3396276 T=3387098
lm=3396298 T=3387098
lm=3396321 T=3387098
lm=3396344 T=3387098
lm=3396367 T=3387098
lm=3396389 T=3387098
lm=3396413 T=3387098
lm=3396435 T=3387098
lm=3396458 T=3387098
lm=3396482 T=3387098
lm=3396504 T=3387098
lm=3396527 T=3387098
lm=3396550 T=3387098
lm=3396573 T=3387098
lm=3396595 T=3387098
lm=3396619 T=3387098
lm=3396641 T=3387098
lm=3396665 T=3387098
lm=3396687 T=3387098
lm=3396710 T=3387098
lm=3396733 T=3387098
lm=3396756 T=3387098
lm=3396779 T=3387098
lm=3396802 T=3387098
lm=3396825 T=3387098
lm=3396847 T=3387098
lm=3396871 T=3387098
lm=3396893 T=3387098
lm=3396916 T=3387098
lm=3396939 T=3387098
lm=3396962 T=3387098
lm=3396984 T=3387098
lm=3397008 T=3387098
lm=3397030 T=3387098
lm=3397053 T=3387098
lm=3397076 T=3387098
lm=3397099 T=3387098
>>> Step 5: Graphics reset, Cycle END
lm=3397163 T=3397159
lm=3397185 T=3397159
lm=3397209 T=3397159
lm=3397231 T=3397159
lm=3397254 T=3397159
lm=3397277 T=3397159
lm=3397300 T=3397159
lm=3397322 T=3397159
lm=3397346 T=3397159
lm=3397368 T=3397159
lm=3397391 T=3397159
lm=3397414 T=3397159
lm=3397437 T=3397159
lm=3397459 T=3397159
lm=3397483 T=3397159
lm=3397506 T=3397159
lm=3397529 T=3397159
lm=3397552 T=3397159
lm=3397574 T=3397159
lm=3397598 T=3397159
lm=3397620 T=3397159
lm=3397643 T=3397159
lm=3397666 T=3397159
lm=3397689 T=3397159
lm=3397711 T=3397159
lm=3397735 T=3397159
lm=3397757 T=3397159
lm=3397780 T=3397159
lm=3397804 T=3397159
lm=3397826 T=3397159
lm=3397849 T=3397159
lm=3397872 T=3397159
lm=3397895 T=3397159
lm=3397917 T=3397159
lm=3397941 T=3397159
lm=3397963 T=3397159
lm=3397986 T=3397159
lm=3398009 T=3397159
lm=3398032 T=3397159
lm=3398054 T=3397159
lm=3398078 T=3397159
lm=3398100 T=3397159
lm=3398123 T=3397159
lm=3398147 T=3397159
lm=3398169 T=3397159
lm=3398192 T=3397159
lm=3398215 T=3397159
lm=3398238 T=3397159
lm=3398261 T=3397159
lm=3398284 T=3397159
lm=3398306 T=3397159
lm=3398330 T=3397159
lm=3398352 T=3397159
lm=3398375 T=3397159
lm=3398398 T=3397159
lm=3398421 T=3397159
lm=3398444 T=3397159
lm=3398467 T=3397159
lm=3398490 T=3397159
lm=3398512 T=3397159
lm=3398536 T=3397159
lm=3398558 T=3397159
lm=3398581 T=3397159
lm=3398604 T=3397159
lm=3398627 T=3397159
lm=3398649 T=3397159
lm=3398673 T=3397159
lm=3398695 T=3397159
lm=3398718 T=3397159
lm=3398742 T=3397159
lm=3398764 T=3397159
lm=3398787 T=3397159
lm=3398810 T=3397159
lm=3398833 T=3397159
lm=3398855 T=3397159
lm=3398879 T=3397159
lm=3398901 T=3397159
lm=3398924 T=3397159
lm=3398947 T=3397159
lm=3398970 T=3397159
lm=3398993 T=3397159
lm=3399016 T=3397159
lm=3399038 T=3397159
lm=3399062 T=3397159
lm=3399085 T=3397159
lm=3399107 T=3397159
lm=3399131 T=3397159
lm=3399153 T=3397159
lm=3399176 T=3397159
lm=3399199 T=3397159
lm=3399222 T=3397159
lm=3399244 T=3397159
lm=3399268 T=3397159
lm=3399290 T=3397159
lm=3399313 T=3397159
lm=3399336 T=3397159
lm=3399359 T=3397159
lm=3399382 T=3397159
lm=3399405 T=3397159
lm=3399428 T=3397159
lm=3399450 T=3397159
lm=3399474 T=3397159
lm=3399496 T=3397159
lm=3399519 T=3397159
lm=3399542 T=3397159
lm=3399565 T=3397159
lm=3399587 T=3397159
lm=3399611 T=3397159
lm=3399633 T=3397159
lm=3399656 T=3397159
lm=3399680 T=3397159
lm=3399702 T=3397159
lm=3399726 T=3397159
lm=3399748 T=3397159
lm=3399771 T=3397159
lm=3399794 T=3397159
lm=3399817 T=3397159
lm=3399839 T=3397159
lm=3399863 T=3397159
lm=3399885 T=3397159
lm=3399908 T=3397159
lm=3399931 T=3397159
lm=3399954 T=3397159
lm=3399976 T=3397159
lm=3400000 T=3397159
lm=3400023 T=3397159
lm=3400045 T=3397159
lm=3400069 T=3397159
lm=3400091 T=3397159
lm=3400114 T=3397159
lm=3400137 T=3397159
lm=3400160 T=3397159
>>> Step 1: resetTemp
lm=3400207 T=3397159
lm=3400229 T=3397159
lm=3400252 T=3397159
lm=3400275 T=3397159
lm=3400298 T=3397159
lm=3400321 T=3397159
lm=3400344 T=3397159
lm=3400367 T=3397159
lm=3400389 T=3397159
lm=3400413 T=3397159
lm=3400435 T=3397159
lm=3400459 T=3397159
lm=3400481 T=3397159
lm=3400504 T=3397159
lm=3400527 T=3397159
lm=3400550 T=3397159
lm=3400572 T=3397159
lm=3400596 T=3397159
lm=3400619 T=3397159
lm=3400641 T=3397159
lm=3400665 T=3397159
lm=3400687 T=3397159
lm=3400710 T=3397159
lm=3400733 T=3397159
lm=3400756 T=3397159
lm=3400778 T=3397159
lm=3400802 T=3397159
lm=3400824 T=3397159
lm=3400847 T=3397159
lm=3400870 T=3397159
lm=3400893 T=3397159
lm=3400915 T=3397159
lm=3400939 T=3397159
lm=3400962 T=3397159
lm=3400984 T=3397159
lm=3401008 T=3397159
lm=3401030 T=3397159
lm=3401053 T=3397159
lm=3401076 T=3397159
lm=3401099 T=3397159
lm=3401121 T=3397159
lm=3401145 T=3397159
lm=3401167 T=3397159
lm=3401191 T=3397159
lm=3401213 T=3397159
lm=3401236 T=3397159
lm=3401260 T=3397159
lm=3401282 T=3397159
lm=3401305 T=3397159
lm=3401328 T=3397159
lm=3401351 T=3397159
lm=3401373 T=3397159
lm=3401397 T=3397159
lm=3401419 T=3397159
lm=3401442 T=3397159
lm=3401465 T=3397159
lm=3401488 T=3397159
lm=3401510 T=3397159
lm=3401534 T=3397159
lm=3401556 T=3397159
lm=3401579 T=3397159
lm=3401603 T=3397159
lm=3401625 T=3397159
lm=3401648 T=3397159
lm=3401671 T=3397159
lm=3401694 T=3397159
lm=3401716 T=3397159
lm=3401740 T=3397159
lm=3401762 T=3397159
lm=3401785 T=3397159
lm=3401808 T=3397159
lm=3401831 T=3397159
lm=3401853 T=3397159
lm=3401877 T=3397159
lm=3401900 T=3397159
lm=3401923 T=3397159
lm=3401946 T=3397159
lm=3401968 T=3397159
lm=3401992 T=3397159
lm=3402014 T=3397159
lm=3402037 T=3397159
lm=3402060 T=3397159
lm=3402083 T=3397159
lm=3402105 T=3397159
lm=3402129 T=3397159
lm=3402151 T=3397159
>>> Step 2: gettingTemp
lm=3402265 T=3397159
lm=3402266 T=3397159
lm=3402266 T=3397159
lm=3402269 T=3397159
lm=3402292 T=3397159
lm=3402315 T=3397159
lm=3402338 T=3397159
lm=3402360 T=3397159
lm=3402384 T=3397159
lm=3402406 T=3397159
lm=3402429 T=3397159
lm=3402452 T=3397159
lm=3402475 T=3397159
lm=3402498 T=3397159
lm=3402521 T=3397159
lm=3402544 T=3397159
lm=3402567 T=3397159
lm=3402590 T=3397159
lm=3402612 T=3397159
lm=3402636 T=3397159
lm=3402658 T=3397159
lm=3402681 T=3397159
lm=3402704 T=3397159
lm=3402727 T=3397159
lm=3402749 T=3397159
lm=3402773 T=3397159
lm=3402796 T=3397159
lm=3402818 T=3397159
lm=3402842 T=3397159
lm=3402864 T=3397159
lm=3402887 T=3397159
lm=3402910 T=3397159
lm=3402933 T=3397159
lm=3402955 T=3397159
lm=3402979 T=3397159
lm=3403001 T=3397159
lm=3403024 T=3397159
lm=3403047 T=3397159
lm=3403070 T=3397159
lm=3403092 T=3397159
lm=3403116 T=3397159
lm=3403139 T=3397159
lm=3403161 T=3397159
lm=3403185 T=3397159
lm=3403207 T=3397159
lm=3403230 T=3397159
lm=3403253 T=3397159
lm=3403276 T=3397159
lm=3403299 T=3397159
lm=3403322 T=3397159
lm=3403344 T=3397159
lm=3403368 T=3397159
lm=3403390 T=3397159
lm=3403413 T=3397159
lm=3403437 T=3397159
lm=3403459 T=3397159
lm=3403482 T=3397159
lm=3403505 T=3397159
lm=3403528 T=3397159
lm=3403550 T=3397159
lm=3403574 T=3397159
lm=3403596 T=3397159
lm=3403619 T=3397159
lm=3403642 T=3397159
lm=3403665 T=3397159
lm=3403687 T=3397159
lm=3403711 T=3397159
lm=3403734 T=3397159
lm=3403756 T=3397159
lm=3403780 T=3397159
lm=3403802 T=3397159
lm=3403825 T=3397159
lm=3403848 T=3397159
lm=3403871 T=3397159
lm=3403893 T=3397159
lm=3403917 T=3397159
lm=3403939 T=3397159
lm=3403962 T=3397159
lm=3403985 T=3397159
lm=3404008 T=3397159
lm=3404032 T=3397159
lm=3404054 T=3397159
lm=3404077 T=3397159
lm=3404100 T=3397159
lm=3404123 T=3397159
lm=3404145 T=3397159
>>> Step 3 START
relay10
>>> Step 3 END
lm=3404412 T=3397159
lm=3404413 T=3397159
lm=3404420 T=3397159
lm=3404442 T=3397159
lm=3404466 T=3397159
lm=3404488 T=3397159
lm=3404511 T=3397159
lm=3404534 T=3397159
lm=3404557 T=3397159
lm=3404579 T=3397159
lm=3404603 T=3397159
lm=3404625 T=3397159
lm=3404648 T=3397159
lm=3404672 T=3397159
lm=3404694 T=3397159
lm=3404718 T=3397159
lm=3404740 T=3397159
lm=3404763 T=3397159
lm=3404786 T=3397159
lm=3404809 T=3397159
lm=3404831 T=3397159
lm=3404855 T=3397159
lm=3404877 T=3397159
lm=3404900 T=3397159
lm=3404923 T=3397159
lm=3404946 T=3397159
lm=3404968 T=3397159
lm=3404992 T=3397159
lm=3405015 T=3397159
lm=3405037 T=3397159
lm=3405061 T=3397159
lm=3405083 T=3397159
lm=3405106 T=3397159
lm=3405129 T=3397159
lm=3405152 T=3397159
lm=3405174 T=3397159
lm=3405198 T=3397159
lm=3405220 T=3397159
lm=3405243 T=3397159
lm=3405266 T=3397159
lm=3405289 T=3397159
lm=3405312 T=3397159
lm=3405335 T=3397159
lm=3405358 T=3397159
lm=3405380 T=3397159
lm=3405404 T=3397159
lm=3405426 T=3397159
lm=3405450 T=3397159
lm=3405472 T=3397159
lm=3405495 T=3397159
lm=3405518 T=3397159
lm=3405541 T=3397159
lm=3405563 T=3397159
lm=3405587 T=3397159
lm=3405609 T=3397159
lm=3405632 T=3397159
lm=3405656 T=3397159
lm=3405678 T=3397159
lm=3405701 T=3397159
lm=3405724 T=3397159
lm=3405747 T=3397159
lm=3405769 T=3397159
lm=3405793 T=3397159
lm=3405815 T=3397159
lm=3405838 T=3397159
lm=3405861 T=3397159
lm=3405884 T=3397159
lm=3405906 T=3397159
lm=3405930 T=3397159
lm=3405953 T=3397159
lm=3405975 T=3397159
lm=3405999 T=3397159
lm=3406021 T=3397159
lm=3406044 T=3397159
lm=3406067 T=3397159
lm=3406090 T=3397159

Ну что можно сказать… Примерно 56 минут проработал МК до сбоя.
Судя по значению параметра “relay” как раз в момент останова - на реле должна была прийти команда “relay10” а до этого было “relay1010”… по всей видимости - пришла команда bitClear(relay,2) - это останов компрессора. То есть, по всей видимости - ошибка пришла в момент отключения компрессора…
Хотя, я там с этими битами не уверен… во-первых печатает не все 8 чисел… а во-вторых, там вроде, нулевой бит - самый правый. Поэтому - подскажите пожалуйста, какой бит стал равен нулю при переходе от “1010” к “10”.

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

Только тогда кончатся ваши мучения. А я бы заменил все релюхи. Данная схема управляет как переменным током, так и постоянным с напряжением 1-250 вольт. Только транзисторы берите с ёмкостью не менее 1000 рF (по даташиту >1400, а лучше больше) на рынке много перемаркированных полевиков. Если 12 вольт нет, то ставьте преобразователь B0512S-1W. Оптопара 817 или 814 подойдет.

Подскажите, а модуль с твердотельными реле “зеро-кросс” подойдёт для решения моей проблемы?