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

ИИ говорит вроде все норм… если он не галлюцинировал от такого количества информации…)))

Timer = 0

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

Да, товарищи,… это “треш”…
Загрузил вот такой код

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

// ========== 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("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");
    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;
  }
}

Долгие “танцы с бубнами” с Serial.print("proverka") - тупо перебором в разных местах, пока скетч не загрузился в МК без ошибки (я уже рассказывал про эту фигню).
Загрузил. Не впервой. Такие проблемы были и ранее.
Запускал этот код с параллельной трансляцией в серийный порт.
Подключал постепенно силовую часть.
Подключил насос - работает без замечаний 5 минут.
Подключил вентилятор - работает без замечаний 5 минут (с момента старта).
Подключил 4-ёх ходовой клапан… как только код доходит до момента срабатывания реле 4-х ходового клапана - перезагрузка МК. При этом - лог монитора порта останавливается. И при перезагрузке МК - лог монитора порта не начинает ничего писать. То есть - причину перезагрузки прочитать по монитору порта не удаётся. Значит - таким “макаром” я три раза подряд убедился - что МК перезагружается - именно в момент срабатывания реле 4-х ходового клапана.
Кто-нибудь - может мне объяснить - почему, практически тот же самый код, но без трансляции в монитор порта, мог работать часами? А теперь, по сути, добавляя лишь трансляцию (Serial.print) - я не могу пройти даже включение третьего реле?

а у вас через усб питается плата мега ? и если да, запитав ее через пины, решит проблему ?)))
но за не обычный и интересный случай спс что поделились

Когда вы инициализируете Serial порт, вы включаете прерывания. Он ведь не только на вывод работает, но и на вход. И не важно читаете порт или нет, он всё равно следит по входу за данными Попробуйте Rx подтянуть к питанию.

а может земля общая виновата ?)))

Использовать не древнюю версию IDE, а вторую версию или другую терминальную программу. Но и в этом случае можете ничего не узнать, т.к. ЕМНИП результативно прочитать регистр можно только на плате без загрузчика или с оптибутовским, но дополнительно там разкорячиваться надо. Можно и прямо сейчас проверить: нажать ресет и глянуть лог.

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


Красным крестиком я обозначил разрыв линии, подключающей компрессор. То есть - при срабатывании всех четырёх реле - должны запуститься все устройства, за исключением компрессора (чтобы не “дёргать” компрессор). Но, повторюсь - при срабатывании реле 4-х ходового клапана - МК стабильно уходил на перезагрузку.

И тут я вспомнил про разговор здесь ранее, где человек говорил - что можно отключить “GND” со стороны контроллера к модулю реле. И я сделал это. Схема стала выглядеть так:


Запустил контроллер, с отслеживанием через монитор порта - и о чудо! Контроллер прошёл включение реле 4-ёх ходового клапана и не ушёл в перезагрузку! Я сильно обрадовался и снова запустил всё. Снова - МК успешно прошёл срабатывание всех реле и не ушёл в перезагрузку. Затем я запустил в третий раз… и в этот раз - код даже не дошёл до включения второго реле - МК ушёл в перезагрузку… Расстроился.
После этого - я стал думать, что там с “GND” на стороне МК. Дело в том, что оплётка (экран) провода с датчиками температуры и провода от водомера - были всё это время подключены на “GND” микроконтроллера:

Я подумал, может это неправильно (может оно как-то влияет на МК). И переключил экраны (оплётки) на жёлто-зелёный провод заземления всей электросети дома (на обсадную трубу скважины):

и вот при таком подключении экрана (оплётки), я вернул подключение “GND” от МК к модулю реле, как в первоначальной схеме:

И запустил всё хозяйство… И о чудо! МК смог проходить включение реле 4-ёх ходового клапана без ухода на перезагрузку. То есть - в зависимости от подключения экранов (на GND либо PE) - у меня в первом случае МК уходил на перезагрузку при включении определённого реле (стабильно) - а во втором случае - стал без проблем проходить это самое включение реле и работать дальше…
В общем - что-то тут как-то надо порядок наводить… знать бы, как правильно это делать…

Плата Мега питается через контакт Vin от блока питания 12В.

Через резистор 10 кОм? Подтянуть к +5В?

Дождался варианта, когда код успешно прошёл включение всех 4-ёх реле, при бегущей записи лога в монитор порта. Нажал кнопку “reset” на плате микроконтроллера - лог остановился на мониторе порта и после перезагрузки МК так и остался в этом положении (старый лог). То есть - после перезагрузки МК, информацию о причине перезагрузке в таком варианте с лога монитора порта - не удаётся.

Что касается моих попыток запустить оборудование с работающим монитором порта. Мне не удаётся найти такого подключения, чтобы стабильно всё работало, с активной записью лога в мониторе порта при этом.
Ясно одно - подключение GND, подключение экранов проводов - влияют на это.

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

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

В общем - “подёргал” оборудование сегодня вечером. Дожидаясь чтобы хотя бы все 4 реле включились. А это - первая минута работы кода.
В итоге - к данному моменту у меня сложилось впечатление, что наиболее устойчивая работа - это в режиме когда экраны проводов (оплётка) на жёлто-зелёный провод всей проводки дома, а GND микроконтроллера не подключается к модулю реле. В таком варианте я даже в оконцовке подключил компрессор физически к реле и прогнал код. Прошло успешно - все 4 реле с нагрузкой включились, МК в перезагрузку не ушёл. При этом - шла запись лога в монитор порта. Правда, остановить пришлось принудительно (это плохо, т.к. при одновременном останове компрессора и 4-ёх ходового клапана - гидроудар). Но на ночь оставлять - ещё хуже… Надо разобраться.
Насколько корректно в моём подключении - отсоединять GND между МК и блоком реле. Ведь управляющие провода от пинов МК - заходят на блок реле… они должны “видеть” потенциал…

Именно.

Бокорезы?

1кОм к +5В

вам реально не надоело “меелафон теребонькать” ? )

Брать заводскую плату “модуль реле” и резаком резать дорожки на ней так, чтобы GND электропитания катушек реле нигде не соединялась с GND питания платы Ардуино?

Если я отделю по питанию только импульсные выходы - это будет верный путь решения?
То есть - выделю один блок питания для Ардуино и платы реле (при этом - GND у них будет общая). А для питания импульсных выходов - выделю бругой блок питания.
Просто, есть у меня предположение, что помеха - идёт от импульсных выходов (скорее всего - импульсного выхода водомера, т.к. до него длинный провод).

BABOS, вот эта вот часть кода, в void setup:

имеет целью - выяснение (фиксацию) причины перезагрузки?
Я правильно понял - что при моём варианте отслеживания через “монитор порта” эта часть кода не сработает? И тогда вопрос - нужно ли мне убрать эти строки из кода, - или пусть присутствуют, могут потом пригодиться?

В формат ELF или в любой другой с отладкой можешь скомпилить? Я в гидре посмотрю.