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

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

А протеус не??? Для avr протя = это просто бомба!!! 100% симуляции!!!

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

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

я в афиге. хорошо, что хоть не на бересте - берЁзки хоть уцелеют.

Посмотрим, сколько по времени вы будете “группой лиц” по(ра)скачивать эту тему. Лапти, чернила, перо и тепловой насос с инверторным приводом = скрепно)))

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

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

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

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

   Что делает программа:
   1. Читает температуру с 6 датчиков DS18B20
   2. Считает расход воды и электричества
   3. Управляет реле (компрессор, насос, вентилятор, клапан)
   4. Рисует графики на дисплее
   5. Защищает систему от ошибок
*/

// ========== 1. ПОДКЛЮЧАЕМ БИБЛИОТЕКИ ==========
#include <MCUFRIEND_kbv.h>  // Библиотека для работы с TFT дисплеем
MCUFRIEND_kbv tft;         // Создаём объект для управления дисплеем

#include <OneWire.h>        // Библиотека для работы с датчиками по протоколу 1-Wire
OneWire ds(21);            // Говорим, что датчики подключены к пину 21 Arduino

// ========== 2. НАСТРОЙКИ ПИНОВ ДЛЯ ДИСПЛЕЯ ==========
#define LCD_CS A3     // Пин выбора дисплея (Chip Select)
#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;  // 8-битное число (0-255), каждый бит управляет одним реле
// Бит 0: вентилятор
// Бит 1: 4-ходовой клапан
// Бит 2: компрессор
// Бит 3: насос

// ========== 6. АДРЕСА ДАТЧИКОВ ТЕМПЕРАТУРЫ ==========
// Каждый датчик DS18B20 имеет уникальный адрес (как серийный номер)
// Это массив из 6 датчиков, у каждого адрес из 8 байт
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}, // Дополнительный датчик 3
  {0x28, 0xEF, 0x8C, 0x76, 0x0, 0x0, 0x0, 0x58}, // Датчик разморозки
  {0x28, 0x8C, 0x3A, 0xB4, 0xE, 0x0, 0x0, 0xDB}  // Датчик испарителя
};

// ========== 7. МАССИВЫ ДЛЯ ХРАНЕНИЯ ГРАФИКОВ ==========
// 320 точек по горизонтали (ширина экрана), значения 0-255 по вертикали
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 - целое число от -32768 до 32767
// int32_t - целое число от -2147483648 до 2147483647
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;  // Флаг для шага 1 (запуск измерения)
boolean Flag2 = true;  // Флаг для шага 2 (чтение температур)
boolean Flag3 = true;  // Флаг для шага 3 (расчёты и логика)
boolean Flag4 = true;  // Флаг для шага 4 (управление реле)
uint8_t countGetGrafic = 9;  // Счётчик для обновления графиков
uint32_t Timer;               // Таймер для отслеживания времени

// ========== 11. МАССИВЫ ДЛЯ ГРАФИКОВ СОСТОЯНИЯ РЕЛЕ ==========
int16_t trend_fan[20];         // История включений вентилятора (20 ячеек по 16 бит)
int16_t trend_kompressor[20];  // История включений компрессора
int16_t trend_pump[20];        // История включений насоса
int16_t trend_4way_valve[20];  // История включений 4-ходового клапана

// ========== 12. ПЕРЕМЕННЫЕ ДЛЯ РАСХОДОМЕРА ВОДЫ ==========
uint32_t tmr;                // Таймер для защиты от дребезга контактов
boolean gWaterFlag = false;  // Флаг: идёт ли измерение
uint32_t WaterStartTimer;    // Время начала измерения
uint32_t WaterCountTimer;    // Длительность импульса

// ========== 13. ПЕРЕМЕННЫЕ ДЛЯ ЭЛЕКТРОСЧЁТЧИКА ==========
uint32_t tmr2;                // Таймер для защиты от дребезга
boolean ElectrFlag = false;   // Флаг: идёт ли измерение
uint32_t ElectrStartTimer;    // Время начала измерения
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) ==========
// CRC - это как контрольная сумма. Если данные повредились при передаче,
// CRC не совпадёт, и мы поймём, что данным нельзя доверять.
uint8_t dallas_crc8(const uint8_t *data, uint8_t len) {
  Serial.println("in 18");
  uint8_t crc = 0;  // Начальное значение CRC

  // Проходим по всем байтам данных
  for (uint8_t i = 0; i < len; i++) {
    uint8_t inbyte = data[i];  // Берём очередной байт

    // Обрабатываем каждый бит байта
    for (uint8_t j = 0; j < 8; j++) {
      // Проверяем, нужно ли делать XOR (операция "исключающее ИЛИ")
      uint8_t mix = (crc ^ inbyte) & 0x01;
      crc >>= 1;  // Сдвигаем CRC вправо

      // Если младший бит был 1, делаем XOR с полиномом
      if (mix) crc ^= 0x8C;

      inbyte >>= 1;  // Сдвигаем байт данных вправо
    }
  }
  return crc;  // Возвращаем посчитанный CRC
  Serial.println("out 18");
}

// ========== 19. ФУНКЦИЯ ЧТЕНИЯ ТЕМПЕРАТУРЫ С ДАТЧИКА ==========
// Возвращает температуру в десятых долях (например 156 = 15.6°C)
// Если ошибка - возвращает 0x7FFF (максимальное число)
int16_t readDS18B20(byte *addr) {
  Serial.println("in 19");
  uint8_t data[9];  // Массив для 9 байт данных от датчика

  // 1. Начинаем общение с датчиком
  ds.reset();              // Сброс шины 1-Wire
  ds.select(addr);         // Выбираем конкретный датчик по адресу
  ds.write(0xBE);          // Команда "прочитай мне данные"

  // 2. Читаем 9 байт от датчика
  for (uint8_t i = 0; i < 9; i++) {
    data[i] = ds.read();   // Читаем байт
  }

  // 3. Проверяем CRC (целостность данных)
  if (dallas_crc8(data, 8) != data[8]) {
    return 0x7FFF;  // Данные повреждены, возвращаем ошибку
  }

  // 4. Собираем температуру из двух байтов
  int16_t raw = (data[1] << 8) | data[0];  // Сдвигаем старший байт и объединяем
  return (raw * 10) >> 4;  // Преобразуем в десятые доли градуса
  Serial.println("out 19");
}

// ========== 20. ФУНКЦИЯ ЗАПУСКА ИЗМЕРЕНИЯ ТЕМПЕРАТУРЫ ==========
// Говорим всем датчикам: "Начинайте измерять температуру!"
void resetTemp() {
  Serial.println("in 20");
  ds.reset();      // Сброс шины
  ds.write(0xCC);  // Команда "обратиться ко всем датчикам"
  ds.write(0x44);  // Команда "начать измерение температуры"
  Serial.println("out 20");
}

// ========== 21. ФУНКЦИЯ ПОЛУЧЕНИЯ ТЕМПЕРАТУР ==========
// Читаем температуру со всех 6 датчиков
void gettingTemp() {
  Serial.println("in 21");
  // Проходим по всем датчикам (от 0 до 5)
  for (uint8_t i = 0; i < 6; i++) {
    int16_t temp = readDS18B20(ADDR_DS18B20[i]);  // Читаем датчик

    if (temp != 0x7FFF) {
      // Данные достоверны - сохраняем
      Temper[i] = temp;          // Текущая температура
      TemperPrev[i] = temp;      // Запоминаем как предыдущую

      // Сбрасываем счётчик ошибок (если ошибок было меньше 6)
      if (MistakeTemp[i] <= 6) MistakeTemp[i] = 0;

    } else {
      // Данные повреждены (ошибка CRC)
      // Используем предыдущее значение вместо ошибочного
      Temper[i] = TemperPrev[i];

      // Увеличиваем счётчик ошибок, если система не остановлена
      if (StopFlag == false) {
        MistakeTemp[i]++;  // +1 к ошибкам

        // Если ошибок больше 6 - аварийная остановка
        if (MistakeTemp[i] > 6) {
          StopFlag = true;          // Включаем флаг остановки
          StopTime = millis();      // Запоминаем время остановки
          StopKind = 6;             // Причина: ошибка датчика
        }
      }
    }
  }
  Serial.println("out 21");
}

// ========== 22. ПРОВЕРКА ГРАНИЦ ТЕМПЕРАТУР ==========
// Проверяем, не выходит ли температура за разумные пределы
void tempMistake(uint8_t a, int16_t b, int16_t c, int16_t d) {
  Serial.println("in 22");
  // a - номер датчика (0-5)
  // b - минимально допустимая температура
  // c - максимально допустимая температура
  // d - максимально допустимое изменение за раз

  // Если уже есть ошибки CRC - пропускаем проверку
  if (MistakeTemp[a] > 0) return;

  // Проверяем три условия:
  // 1. Температура >= минимума
  // 2. Температура <= максимума
  // 3. Изменение не больше допустимого
  if (Temper[a] >= b && Temper[a] <= c && abs(Temper[a] - TemperPrev[a]) <= d) {
    // Всё нормально - ничего не делаем
  } else {
    // Ошибка! Используем предыдущее значение
    Temper[a] = TemperPrev[a];

    // Увеличиваем счётчик ошибок
    if (StopFlag == false) MistakeTemp[a]++;

    // Если ошибок больше 6 - аварийная остановка
    if (MistakeTemp[a] > 6 && StopFlag == false) {
      StopFlag = true;
      StopTime = millis();
      StopKind = 6;  // Ошибка показаний датчика
    }
  }
  Serial.println("out 22");
}

// ========== 23. ОБРАБОТЧИК ИМПУЛЬСОВ СЧЁТЧИКА ВОДЫ ==========
// Вызывается часто в loop() для отслеживания импульсов
void voda_tick() {
  Serial.println("in 23");
  // Читаем текущее состояние пина (HIGH или LOW)
  boolean current_status = digitalRead(pinVoda_tick);

  // Если сигнал изменился с HIGH на LOW (передний фронт импульса)
  if (stateCheck_voda && !current_status) {
    tmr = millis();         // Запоминаем время
    gWaterFlag = true;      // Ставим флаг: началось измерение
    stateCheck_voda = current_status;  // Запоминаем новое состояние
  }

  // Если сигнал изменился с LOW на HIGH (задний фронт)
  if (!stateCheck_voda && current_status) {
    stateCheck_voda = current_status;  // Запоминаем состояние
  }

  // Если сигнал HIGH - сбрасываем флаг измерения
  if (current_status) gWaterFlag = false;

  // Если прошло больше 1 секунды и флаг измерения активен
  // (защита от дребезга контактов - случайных ложных срабатываний)
  if (!current_status && millis() - tmr >= 1000 && gWaterFlag == true) {
    // Измеряем время между импульсами
    WaterCountTimer = millis() - WaterStartTimer;
    WaterStartTimer = millis();  // Запоминаем время этого импульса
    gWaterFlag = false;          // Сбрасываем флаг

    // Отмечаем, что были импульсы
    if (FirstImpulsWater == true) SecondImpulsWater = true;
    FirstImpulsWater = true;
  }
  Serial.println("out 23");
}

// ========== 24. ОБРАБОТЧИК ИМПУЛЬСОВ ЭЛЕКТРОСЧЁТЧИКА ==========
// Работает так же, как и счётчик воды
void electr_tick() {
  Serial.println("in 24");
  boolean current_status = digitalRead(pinElectr_tick);

  // Передний фронт импульса
  if (stateCheck_electr && !current_status) {
    tmr2 = millis();              // Запоминаем время
    ElectrFlag = true;            // Ставим флаг измерения
    stateCheck_electr = current_status;
  }

  // Задний фронт
  if (!stateCheck_electr && current_status) {
    stateCheck_electr = current_status;
  }

  if (current_status) ElectrFlag = false;

  // Если прошло 50 миллисекунд (защита от дребезга)
  if (!current_status && millis() - tmr2 >= 50 && ElectrFlag == true) {
    ElectrCountTimer = millis() - ElectrStartTimer;  // Измеряем период
    ElectrStartTimer = millis();  // Запоминаем время
    ElectrFlag = false;           // Сбрасываем флаг
  }
  Serial.println("out 24");
}

// ========== 25. ФУНКЦИИ ВЫВОДА ЧИСЕЛ НА ДИСПЛЕЙ ==========

// Вывод числа с точностью до сотых (например 1234 = 12.34)
void getDataInt100(int16_t a) {
  Serial.println("in 25");
  if (a >= -9 && a < 0) {
    // Для чисел от -0.09 до 0
    tft.print("-0.0");
    tft.print(abs(a));
  } else if (a < 9 && a >= 0) {
    // Для чисел от 0 до 0.09
    tft.print("0.0");
    tft.print(a);
  } else if (a <= -10 && a > -100) {
    // Для чисел от -0.99 до -0.10
    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));  // Дробная часть
  }
  Serial.println("out 25");
}

// Вывод числа с точностью до десятых (например 123 = 12.3) (функция 25_1)
void getDataInt10(int16_t a) {
  Serial.println("in 25_1");
  if (a >= -9 && a < 0) {
    // Для чисел от -0.9 до 0
    tft.print("-0.");
    tft.print(abs(a));
  } else if (a < 9 && a >= 0) {
    // Для чисел от 0 до 0.9
    tft.print("0.");
    tft.print(a);
  } else {
    // Для всех остальных чисел
    tft.print(a / 10);  // Целая часть
    tft.print(".");
    tft.print(abs(a % 10));  // Дробная часть
  }
  Serial.println("out 25_1");
}

// ========== 26. ПРЕОБРАЗОВАНИЕ ЧИСЕЛ ДЛЯ ГРАФИКА ==========
// Преобразует реальное значение (например -40°C) в позицию на экране (0-255)
int16_t getDataForUintMassiv(int16_t a) {
  Serial.println("in 26");
  int16_t LastInMassive;

  // Разбиваем на диапазоны для лучшего отображения
  if (a < -400) LastInMassive = 0;  // Всё что ниже -40°C - в самый низ
  else if (a >= -400 && a < 500) LastInMassive = round((a + 400) / 5);  // От -40°C до 50°C
  else if (a >= 500 && a < 1250) LastInMassive = round(180 + (a - 500) / 10);  // До 125°C
  else LastInMassive = 255;  // Всё что выше - в самый верх

  return LastInMassive;
  Serial.println("out 26");
}

// То же самое, но для больших чисел (мощности)
int32_t getDataForUintMassiv32(int32_t a) {
  Serial.println("in 26_1");
  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;
  Serial.println("out 26_1");
}

// ========== 27. ОТРИСОВКА ГРАФИКОВ ==========
// Рисует график по массиву значений
void getGraphics(uint16_t c, uint16_t d, uint8_t g[320]) {
  Serial.println("in 27");
  // c - базовая линия по Y (где находится "ноль" графика)
  // d - цвет линии
  // g - массив с данными (320 точек)

  int16_t oldX = 0;       // Предыдущая X координата
  int16_t oldY = g[0];    // Предыдущая Y координата

  // Рисуем линию, соединяя все точки графика
  for (int16_t x = 1; x < 320; x++) {
    int16_t nxt_x = x;    // Текущая X координата

    // Рисуем линию от предыдущей точки до текущей
    tft.drawLine(oldX, (c - oldY), nxt_x, (c - g[x]), d);

    oldY = g[x];  // Запоминаем текущую точку как предыдущую
    oldX = nxt_x;
  }
  Serial.println("out 27");
}

// ========== 28. ОТРИСОВКА ВСЕГО ЭКРАНА ==========
void getMainDisplay() {
  Serial.println("in 28");
  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:");

  Serial.println("out 28");
}

// ========== 29. НАЧАЛЬНАЯ НАСТРОЙКА (ВЫПОЛНЯЕТСЯ ОДИН РАЗ) ==========
void setup() {
  Serial.println("in 29");
  Serial.begin(9600);  // Запускаем Serial порт для отладки

  // Настраиваем дисплей
  tft.reset();          // Сбрасываем дисплей
  tft.begin(38022);     // Инициализируем с ID драйвера
  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;
  }

  // Настраиваем пины управления реле как выходы
  // И сразу выключаем все реле (HIGH - выключено)
  pinMode(48, OUTPUT); digitalWrite(48, HIGH);  // Вентилятор
  pinMode(49, OUTPUT); digitalWrite(49, HIGH);  // 4-ходовой клапан
  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();              // Запоминаем время для цикла

  delay(1000);  // Ждём 1 секунду для стабилизации
  Serial.println("out 29");
}

// ========== 30. ГЛАВНЫЙ ЦИКЛ (ВЫПОЛНЯЕТСЯ БЕСКОНЕЧНО) ==========
void loop() {
  Serial.println("in 30");
  // Постоянно проверяем импульсы счётчиков
  voda_tick();      // Проверяем счётчик воды
  electr_tick();    // Проверяем электросчётчик

  // ===== ШАГ 1: ЗАПУСК ИЗМЕРЕНИЯ ТЕМПЕРАТУРЫ (3-5 секунд после старта) =====
  if (millis() - Timer >= 3000 && millis() - Timer < 5000 && Flag1 == true) {
    resetTemp();    // Говорим датчикам начать измерение
    Flag1 = false;  // Сбрасываем флаг, чтобы не повторять
  }

  // ===== ШАГ 2: ЧТЕНИЕ ТЕМПЕРАТУР (5-7 секунд) =====
  if (millis() - Timer >= 5000 && millis() - Timer < 7000 && Flag2 == true) {
    gettingTemp();  // Читаем все датчики
    Flag2 = false;  // Сбрасываем флаг
  }

  // ===== ШАГ 3: РАСЧЁТЫ И ЛОГИКА (7-9 секунд) =====
  if (millis() - Timer >= 7000 && millis() - Timer < 9000 && Flag3 == true) {

    // При первом запуске запоминаем температуры как предыдущие
    if (getMistakeFlag == false) {
      for (uint8_t i = 0; i < 6; i++) {
        TemperPrev[i] = Temper[i];
      }
      getMistakeFlag = true;
    }

    // Проверяем каждую температуру на разумные границы
    // Параметры: номер датчика, мин.темп, макс.темп, макс.изменение
    tempMistake(0, -100, 1200, 200);   // Компрессор: от -10°C до 120°C
    tempMistake(1, 0, 600, 100);       // Вода вход: от 0°C до 60°C
    tempMistake(2, 0, 900, 50);        // Вода выход: от 0°C до 90°C
    tempMistake(3, -400, 800, 400);    // Доп.датчик: от -40°C до 80°C
    tempMistake(4, -400, 600, 300);    // Разморозка: от -40°C до 60°C
    tempMistake(5, -400, 800, 200);    // Испаритель: от -40°C до 80°C

    // Считаем перегрев (разница между датчиками 3 и 5)
    tOverheatReal = (Temper[3] - Temper[5]);

    // ===== РАСЧЁТ РАСХОДА ВОДЫ =====
    if (digitalRead(51) == HIGH) {
      // Если насос выключен - расхода нет
      gWaterReal = 0;
      gWaterRealPrew = gWaterReal;
      FlagWater = false;

    } else if (digitalRead(51) == LOW && millis() - WaterStartTimer > 400000) {
      // Если насос включён, но импульсов нет больше 400 секунд - ошибка
      StopFlag = true;
      StopTime = millis();
      StopKind = 7;  // Нет расхода воды

    } else if (SecondImpulsWater == false) {
      // Ещё нет двух импульсов - используем предыдущее значение
      gWaterReal = gWaterRealPrew;
      FlagWater = true;

    } else {
      // Есть два импульса - считаем расход
      // Формула: 3600000 / время между импульсами
      gWaterReal = round(3600000 / WaterCountTimer);
      gWaterRealPrew = gWaterReal;
      FlagWater = false;
    }

    // ===== РАСЧЁТ ЭЛЕКТРИЧЕСКОЙ МОЩНОСТИ =====
    if (millis() - ElectrStartTimer > 60000) {
      // Если импульсов нет больше 60 секунд - мощность 0
      ElectrPowReal = 0;
    } else {
      // Считаем мощность: 72000 / время между импульсами
      ElectrPowReal = 72000 / ElectrCountTimer;
    }

    // ===== РАСЧЁТ ТЕПЛОВОЙ МОЩНОСТИ =====
    // Формула: разница температур * расход воды * 1163 / 10000
    heatPowerReal = ((int32_t)Temper[2] - (int32_t)Temper[1]) * gWaterReal * 1163 / 10000;

    // ===== РАСЧЁТ КОП (эффективности) =====
    if (ElectrPowReal < 10) {
      COPreal = 0;  // Если электричества почти нет - КОП = 0
    } else {
      // КОП = тепловая мощность / электрическая мощность * 100
      COPreal = 100 * heatPowerReal / ElectrPowReal;
    }

    // ===== СЧИТАЕМ СРЕДНИЕ ЗНАЧЕНИЯ =====
    countHeat = countHeat + heatPowerReal;
    countElectr = countElectr + ElectrPowReal;
    countHeatAndElectr++;  // Счётчик измерений

    // ===== УПРАВЛЕНИЕ ВЕНТИЛЯТОРОМ ПРИ ПЕРЕГРЕВЕ =====
    if (HeatOptionFlag == true && Temper[0] >= 850 && tOverheatReal >= 300 && digitalRead(48) == LOW) {
      // Если температура компрессора >= 85°C и перегрев >= 30°C
      tKompressorCounter++;  // Увеличиваем счётчик

      if (tKompressorCounter >= 4) {  // Если 4 раза подряд
        bitClear(relay, 0);  // Выключаем вентилятор (бит 0 = 0)
        tKompressorCounter = 0;
      }
    } else if (HeatOptionFlag == true && (Temper[0] <= 750 || tOverheatReal <= 200) && digitalRead(48) == HIGH) {
      // Если температура <= 75°C или перегрев <= 20°C
      tKompressorCounter++;

      if (tKompressorCounter >= 2) {  // Если 2 раза подряд
        bitSet(relay, 0);  // Включаем вентилятор (бит 0 = 1)
        tKompressorCounter = 0;
      }
    } else {
      tKompressorCounter = 0;  // Сбрасываем счётчик
    }

    // ===== ОКОНЧАНИЕ РЕЖИМА НАГРЕВА =====
    if (HeatOptionFlag == true && Temper[1] >= 360) {
      // Если вода на входе >= 36°C
      HeatOptionCout++;

      if (HeatOptionCout >= 6) {  // 6 раз подряд
        HeatOptionFlag = false;          // Выключаем нагрев
        HeatOptionPauseFlag = true;      // Включаем паузу
        HeatOptionCout = 0;
        HeatOptionPauseStartTime = millis();  // Запоминаем время
        bitClear(relay, 2);  // Выключаем компрессор
        bitClear(relay, 0);  // Выключаем вентилятор
      }
    } else {
      HeatOptionCout = 0;
    }

    // ===== ЛОГИКА ПАУЗЫ =====
    // Выключаем клапан через 2 минуты паузы
    if (HeatOptionPauseFlag == true && digitalRead(49) == LOW && millis() - HeatOptionPauseStartTime >= 120000) {
      bitClear(relay, 1);  // Выключаем 4-ходовой клапан
    }

    // Включаем насос на 16 минут если нет расхода воды
    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) {
      // Если вода остыла до 28°C
      HeatOptionPauseCout++;

      if (HeatOptionPauseCout >= 5) {  // 5 раз подряд
        HeatOptionPauseFlag = false;   // Выключаем паузу
        HeatOptionPauseCout = 0;
        StartHeatTime = millis();
        StartHeatFlag = true;          // Начинаем нагрев заново
      }
    } else {
      HeatOptionPauseCout = 0;
    }

    // ===== ЗАЩИТА: НЕТ КЛАПАНА =====
    if (HeatOptionFlag == true && digitalRead(49) == HIGH) {
      StopNo4xvalve++;

      if (StopNo4xvalve >= 3) {  // 3 раза подряд
        bitClear(relay, 2);  // Выключаем компрессор
        StopFlag = true;
        StopTime = millis();
        StopKind = 1;  // Причина: нет 4-ходового клапана
        StopNo4xvalve = 0;
      }
    } else {
      StopNo4xvalve = 0;
    }

    // ===== ЗАЩИТА: ПЕРЕГРЕВ КОМПРЕССОРА =====
    if ((StartHeatFlag == true || HeatOptionFlag == true || HeatOptionPauseFlag == true || DefrostOptionFlag == true) && Temper[0] >= 1000) {
      StopMaxTemp++;

      if (StopMaxTemp >= 5) {  // 5 раз подряд >= 100°C
        StopFlag = true;
        StopTime = millis();
        StopKind = 2;  // Причина: перегрев компрессора
        StopMaxTemp = 0;
      }
    } else {
      StopMaxTemp = 0;
    }

    // ===== ЗАЩИТА: ПРЕВЫШЕНИЕ ЭЛЕКТРИЧЕСКОЙ МОЩНОСТИ =====
    if ((StartHeatFlag == true || HeatOptionFlag == true || HeatOptionPauseFlag == true || DefrostOptionFlag == true) && ElectrPowReal >= 151) {
      StopMaxElectr++;

      if (StopMaxElectr >= 6) {  // 6 раз подряд >= 151
        StopFlag = true;
        StopTime = millis();
        StopKind = 3;  // Причина: превышение мощности
        StopMaxElectr = 0;
      }
    } else {
      StopMaxElectr = 0;
    }

    // ===== ЗАЩИТА: НИЗКАЯ ТЕМПЕРАТУРА НАГРЕВАТЕЛЯ =====
    if ((StartHeatFlag == true || HeatOptionFlag == true || HeatOptionPauseFlag == true) && Temper[4] <= 50) {
      StopMinTempHeater++;

      if (StopMinTempHeater >= 3) {  // 3 раза подряд <= 5°C
        StopFlag = true;
        StopTime = millis();
        StopKind = 4;  // Причина: низкая температура нагревателя
        StopMinTempHeater = 0;
      }
    } else {
      StopMinTempHeater = 0;
    }

    // ===== ЗАЩИТА: НЕТ ЭЛЕКТРИЧЕСТВА =====
    if (digitalRead(50) == LOW && ElectrPowReal <= 10) {
      StopNoElectric++;

      if (StopNoElectric >= 6) {  // 6 раз подряд
        StopFlag = true;
        StopTime = millis();
        StopKind = 5;  // Причина: нет электричества
        StopNoElectric = 0;
      }
    } else {
      StopNoElectric = 0;
    }

    // ===== ЛОГИКА СТАРТА НАГРЕВА =====
    // Через 20 секунд включаем насос
    if (StartHeatFlag == true && millis() - StartHeatTime >= 20000 && Temper[1] >= 50) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis();
        FirstImpulsWater = false;
        SecondImpulsWater = false;
      }
      bitSet(relay, 3);  // Включаем насос
    }

    // Через 30 секунд включаем вентилятор
    if (StartHeatFlag == true && digitalRead(51) == LOW && millis() - StartHeatTime >= 30000 && Temper[0] <= 850) {
      bitSet(relay, 0);  // Включаем вентилятор
    }

    // Через 40 секунд включаем клапан
    if (StartHeatFlag == true && digitalRead(51) == LOW && digitalRead(48) == LOW && millis() - StartHeatTime >= 40000) {
      bitSet(relay, 1);  // Включаем 4-ходовой клапан
    }

    // Через 45 секунд включаем компрессор
    if (StartHeatFlag == true && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(49) == LOW && millis() - StartHeatTime >= 45000) {
      bitSet(relay, 2);  // Включаем компрессор
    }

    // Когда всё включено - переходим в рабочий режим
    if (StartHeatFlag == true && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(50) == LOW && digitalRead(49) == LOW) {
      StartHeatFlag = false;     // Выключаем стартовый режим
      HeatOptionFlag = true;     // Включаем рабочий режим
    }

    // ===== АВАРИЙНАЯ ОСТАНОВКА =====
    if (StopFlag == true) {
      StartHeatFlag = false;
      HeatOptionFlag = false;
      HeatOptionPauseFlag = false;
      DefrostOptionFlag = false;
      bitClear(relay, 2);  // Выключаем компрессор сразу
      bitClear(relay, 0);  // Выключаем вентилятор сразу

      if (millis() - StopTime >= 120000) bitClear(relay, 1);  // Клапан через 2 минуты
      if (millis() - StopTime >= 180000) bitClear(relay, 3);  // Насос через 3 минуты
    }

    // ===== РЕЖИМ РАЗМОРОЗКИ =====
    if (DefrostOptionFlag == true) {
      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);  // Выключаем клапан через 2 минуты

      // Заканчиваем разморозку через 15 минут или при температуре >= 2°C
      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((MistakeTemp[0] > 0) ? CYAN : RED);
    getDataInt10(Temper[0]);  // Температура компрессора

    tft.setCursor(181, 0);
    tft.setTextColor((MistakeTemp[1] > 0) ? CYAN : YELLOW);
    getDataInt10(Temper[1]);  // Температура воды вход

    tft.setCursor(289, 0);
    tft.setTextColor((MistakeTemp[2] > 0) ? CYAN : GREEN);
    getDataInt10(Temper[2]);  // Температура воды выход

    tft.setCursor(74, 10);
    tft.setTextColor((MistakeTemp[3] > 0) ? CYAN : MAGENTA);
    getDataInt10(tOverheatReal);  // Перегрев

    tft.setCursor(181, 10);
    tft.setTextColor((MistakeTemp[4] > 0) ? CYAN : CYAN);
    getDataInt10(Temper[4]);  // Температура разморозки

    tft.setCursor(289, 10);
    tft.setTextColor((MistakeTemp[5] > 0) ? CYAN : RED);
    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(FlagWater ? CYAN : MAGENTA);
    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;  // Сбрасываем флаг шага 3
  }

  // ===== ШАГ 4: УПРАВЛЕНИЕ РЕЛЕ (9-10 секунд) =====
  if (millis() - Timer >= 9000 && millis() - Timer < 10000 && Flag4 == true) {
    // Применяем состояния реле к физическим пинам
    // LOW - включено, HIGH - выключено (инверсная логика)
    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) {
    Timer = millis();  // Сбрасываем таймер

    // Обновляем графики каждый 10-й цикл
    if (countGetGrafic >= 9) {

      // Сдвигаем все графики на 1 точку влево
      // (старые данные уходят, освобождая место для новых)
      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;
  }
  Serial.println("out 30");
}

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

Спойлер

сбросил.

Отключил питание сильноточных цепей. Залил новый скетч с входом/выходом из процедур. Залился сейчас - без дополнительных “бубнов” (о которых упоминал утром).
Посмотрел “монитор порта”

Спойлер

И знаете… такое впечатление, как будто я был не прав - считая ранее, что не все входы/выходы он сможет отследить… Активненько так фиксирует…
После этого подключил сильноточные цепи и дал “рестарт”. Оставил в работе с подключённым ноутбуком

Спойлер

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

А вот фиг!
Только отписался вам с предыдущим сообщением - пошёл к контроллеру и наблюдаю такую картину. На дисплее:

Спойлер

Надпись на дисплее “Stop minT Heater” - говорит о том, что якобы была ошибка связанная с тем, что теплообменник имел температуру ниже 5 град. С. Что по всей видимости - неправда.
Монитор порта остановился в таком состоянии

Спойлер

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

Спойлер
...
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 

Что с этим делать? Как поступать дальше?
Есть у меня подозрение, что контроллер, возможно, споткнулся так быстро из-за того, что передавал данные в “серийный порт”…

Вроде как - получается, что “споткнулся” в loop.
Посмотрел расход воды, посмотрел электронагрузку и после этого должен был написать “out 30” (скорее всего). Но почему-то “out” написал - а дальше уже ничего не написал…
Но странно то - что на дисплее при этом - как будто двигался цикл. “Блимканье” значений было

ни одного входа в шаги 1-5. Это означает, что ни одно из условий по времени не срабатывает.

Посмотрите на свой код шага 5 — место, где сбрасывается таймер:

if (millis() - Timer >= 10000) {
    Timer = millis();  // Сбрасываем таймер
    // ... обновление графиков ...
    Flag1 = true;
    Flag2 = true;
    Flag3 = true;
    Flag4 = true;
}

надо добавить и проверить

void loop() {
  Serial.print("millis=");
  Serial.println(millis());

если millis() всегда показывает 0 или одно и то же число — проблема в этом
еще можно добавить
void setup() {
Timer = 0; // ЯВНО обнуляем таймер

сейчас новый код скину потестировать если у вас есть время…

/*
   ПРОГРАММА ДЛЯ МОНИТОРИНГА ТЕПЛОВОГО НАСОСА

   Что делает программа:
   1. Читает температуру с 6 датчиков DS18B20
   2. Считает расход воды и электричества
   3. Управляет реле (компрессор, насос, вентилятор, клапан)
   4. Рисует графики на дисплее
   5. Защищает систему от ошибок
*/

// ========== 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;
// Бит 0: вентилятор
// Бит 1: 4-ходовой клапан
// Бит 2: компрессор
// Бит 3: насос

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

// ========== 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;
uint32_t WaterCountTimer;

// ========== 13. ПЕРЕМЕННЫЕ ДЛЯ ЭЛЕКТРОСЧЁТЧИКА ==========
uint32_t tmr2;
boolean ElectrFlag = false;
uint32_t ElectrStartTimer;
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. ФУНКЦИЯ ЧТЕНИЯ ТЕМПЕРАТУРЫ С ДАТЧИКА ==========
// Возвращает true, если CRC прошёл, и записывает температуру в *dest
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; // Правильная формула для int16_t
  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] не меняется
    }
  }
}

// ========== 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() {
  boolean current_status = digitalRead(pinVoda_tick);

  if (stateCheck_voda && !current_status) {
    tmr = millis();
    gWaterFlag = true;
    stateCheck_voda = current_status;
  }

  if (!stateCheck_voda && current_status) {
    stateCheck_voda = current_status;
  }

  if (current_status) gWaterFlag = false;

  if (!current_status && millis() - tmr >= 1000 && gWaterFlag == true) {
    WaterCountTimer = millis() - WaterStartTimer;
    WaterStartTimer = millis();
    gWaterFlag = false;
    if (FirstImpulsWater == true) SecondImpulsWater = true;
    FirstImpulsWater = true;
  }
}

// ========== 24. ОБРАБОТЧИК ИМПУЛЬСОВ ЭЛЕКТРОСЧЁТЧИКА ==========
void electr_tick() {
  boolean current_status = digitalRead(pinElectr_tick);

  if (stateCheck_electr && !current_status) {
    tmr2 = millis();
    ElectrFlag = true;
    stateCheck_electr = current_status;
  }

  if (!stateCheck_electr && current_status) {
    stateCheck_electr = current_status;
  }

  if (current_status) ElectrFlag = false;

  if (!current_status && millis() - tmr2 >= 50 && ElectrFlag == true) {
    ElectrCountTimer = millis() - ElectrStartTimer;
    ElectrStartTimer = millis();
    ElectrFlag = false;
  }
}

// ========== 25. ФУНКЦИИ ВЫВОДА ЧИСЕЛ НА ДИСПЛЕЙ ==========

void getDataInt100(int16_t a) {
  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) {
  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]) {
  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() {
  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;
  
  // ===== ПРИНУДИТЕЛЬНЫЙ СБРОС ТАЙМЕРА =====
  Timer = 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();

  delay(1000);
}

// ========== 30. ГЛАВНЫЙ ЦИКЛ ==========
void loop() {
  // ===== ДИАГНОСТИКА ВРЕМЕНИ =====
  Serial.print("loop millis=");
  Serial.print(millis());
  Serial.print(" Timer=");
  Serial.println(Timer);
  // ================================

  voda_tick();
  electr_tick();

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

    // Тепловая мощность
    heatPowerReal = ((int32_t)Temper[2] - (int32_t)Temper[1]) * gWaterReal * 1163 / 10000;

    // COP
    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 == true || HeatOptionFlag == true || HeatOptionPauseFlag == true || DefrostOptionFlag == true) && Temper[0] >= 1000) {
      StopMaxTemp++;
      if (StopMaxTemp >= 5) {
        StopFlag = true;
        StopTime = millis();
        StopKind = 2;
        StopMaxTemp = 0;
      }
    } else {
      StopMaxTemp = 0;
    }

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

    if ((StartHeatFlag == true || HeatOptionFlag == true || HeatOptionPauseFlag == true) && 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 == true && millis() - StartHeatTime >= 20000 && Temper[1] >= 50) {
      if (digitalRead(51) == HIGH) {
        WaterStartTimer = millis();
        FirstImpulsWater = false;
        SecondImpulsWater = false;
      }
      bitSet(relay, 3);
    }

    if (StartHeatFlag == true && digitalRead(51) == LOW && millis() - StartHeatTime >= 30000 && Temper[0] <= 850)
      bitSet(relay, 0);

    if (StartHeatFlag == true && digitalRead(51) == LOW && digitalRead(48) == LOW && millis() - StartHeatTime >= 40000)
      bitSet(relay, 1);

    if (StartHeatFlag == true && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(49) == LOW && millis() - StartHeatTime >= 45000)
      bitSet(relay, 2);

    if (StartHeatFlag == true && digitalRead(51) == LOW && digitalRead(48) == LOW && digitalRead(50) == LOW && digitalRead(49) == LOW) {
      StartHeatFlag = false;
      HeatOptionFlag = true;
    }

    // Stop
    if (StopFlag == true) {
      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 == true) {
      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((MistakeTemp[0] > 0) ? CYAN : RED);
    getDataInt10(Temper[0]);

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

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

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

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

    tft.setCursor(289, 10);
    tft.setTextColor((MistakeTemp[5] > 0) ? CYAN : RED);
    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(FlagWater ? CYAN : MAGENTA);
    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) {
      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;
  }
}

p.s. пацаны, хватит опять меня вспоминать плохими словами, а то икается… я не знаю через что вы читаете форум, но если кликать перемотку не по месту где код, а по месту где его нет, то проматывает нормально, но если помогло, не говорите про этот лайф хак другим, пусть страдают!

Да, ожидаю.
На всякий случай, что было по “логу” раньше по времени, до того как лишь один loop циклился

Спойлер
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
in 22
out 22
in 22
out 22
in 22
out 22
in 22
out 22
in 22
out 22
in 22
out 22
in 25_1
out 25_1
in 25_1
out 25_1
in 25_1
out 25_1
in 25_1
out 25_1
in 25_1
out 25_1
in 25_1
out 25_1
in 25
out 25
in 25
out 25
in 25
out 25
in 25
out 25
in 25
out 25
in 25
out 25
out 30
in 30
in 23
out 23
in 24
out 24
out 30
in 30
in 23
out 23
in 24
out 24
out 30

там хотя бы пробежали 22, 25, 25_1

уже скинул, отредактировал сообщение, обновите если что страницу

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

Спойлер
C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\Peter\Documents\Arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -ide-version=10803 -build-path C:\Users\Peter\AppData\Local\Temp\arduino_build_975191 -warnings=none -build-cache C:\Users\Peter\AppData\Local\Temp\arduino_cache_835757 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avrdude.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avr-gcc.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -verbose D:\Петя\Строительство\Автоматика Arduino котельной\Mega\Mega\Mega.ino\Mega.ino.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\Peter\Documents\Arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -ide-version=10803 -build-path C:\Users\Peter\AppData\Local\Temp\arduino_build_975191 -warnings=none -build-cache C:\Users\Peter\AppData\Local\Temp\arduino_cache_835757 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avrdude.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avr-gcc.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -verbose D:\Петя\Строительство\Автоматика Arduino котельной\Mega\Mega\Mega.ino\Mega.ino.ino
Using board 'mega' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Using core 'arduino' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Detecting libraries used...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp" -o "nul"
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega" "-IC:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp" -o "nul"
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega" "-IC:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv" "-IC:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp" -o "nul"
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega" "-IC:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv" "-IC:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master" "-IC:\Users\Peter\Documents\Arduino\libraries\OneWire-master" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp" -o "nul"
Using cached library dependencies for file: C:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv\MCUFRIEND_kbv.cpp
Using cached library dependencies for file: C:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master\Adafruit_GFX.cpp
Using cached library dependencies for file: C:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master\glcdfont.c
Using cached library dependencies for file: C:\Users\Peter\Documents\Arduino\libraries\OneWire-master\OneWire.cpp
Generating function prototypes...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega" "-IC:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv" "-IC:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master" "-IC:\Users\Peter\Documents\Arduino\libraries\OneWire-master" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp" -o "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\preproc\ctags_target_for_gcc_minus_e.cpp"
"C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\preproc\ctags_target_for_gcc_minus_e.cpp"
Компиляция скетча...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega" "-IC:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv" "-IC:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master" "-IC:\Users\Peter\Documents\Arduino\libraries\OneWire-master" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp" -o "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp.o"
Compiling libraries...
Compiling library "Mcufriend_kbv"
Используем предварительно скомпилированный файл: C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\Mcufriend_kbv\MCUFRIEND_kbv.cpp.o
Compiling library "Adafruit-GFX-Library-master"
Используем предварительно скомпилированный файл: C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\Adafruit-GFX-Library-master\glcdfont.c.o
Используем предварительно скомпилированный файл: C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\Adafruit-GFX-Library-master\Adafruit_GFX.cpp.o
Compiling library "OneWire-master"
Используем предварительно скомпилированный файл: C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\OneWire-master\OneWire.cpp.o
Compiling core...
Using precompiled core
Linking everything together...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections,--relax -mmcu=atmega2560  -o "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.elf" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\sketch\Mega.ino.ino.cpp.o" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\Mcufriend_kbv\MCUFRIEND_kbv.cpp.o" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\Adafruit-GFX-Library-master\glcdfont.c.o" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\Adafruit-GFX-Library-master\Adafruit_GFX.cpp.o" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191\libraries\OneWire-master\OneWire.cpp.o" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/..\arduino_cache_835757\core\core_arduino_avr_mega_cpu_atmega2560_0c812875ac70eb4a9b385d8fb077f54c.a" "-LC:\Users\Peter\AppData\Local\Temp\arduino_build_975191" -lm
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0  "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.elf" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.eep"
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-objcopy" -O ihex -R .eeprom  "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.elf" "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.hex"
Используем библиотеку Mcufriend_kbv в папке: C:\Users\Peter\Documents\Arduino\libraries\Mcufriend_kbv (legacy)
Используем библиотеку Adafruit-GFX-Library-master версии 1.1.3 из папки: C:\Users\Peter\Documents\Arduino\libraries\Adafruit-GFX-Library-master 
Используем библиотеку OneWire-master версии 2.3.3 из папки: C:\Users\Peter\Documents\Arduino\libraries\OneWire-master 
Скетч использует 23824 байт (9%) памяти устройства. Всего доступно 253952 байт.
Глобальные переменные используют 4479 байт (54%) динамической памяти, оставляя 3713 байт для локальных переменных. Максимум: 8192 байт.
C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega2560 -cwiring -PCOM5 -b115200 -D -Uflash:w:C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.hex:i 

avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : wiring
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega2560
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
           flash         65    10   256    0 yes    262144  256   1024  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Wiring
         Description     : Wiring
         Programmer Model: AVRISP
         Hardware Version: 15
         Firmware Version Master : 2.10
         Vtarget         : 0.0 V
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9801 (probably m2560)
avrdude: reading input file "C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.hex"
avrdude: writing flash (23824 bytes):

Writing | ################################################## | 100% 3.62s

avrdude: 23824 bytes of flash written
avrdude: verifying flash memory against C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.hex:
avrdude: load data flash data from input file C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.hex:
avrdude: input file C:\Users\Peter\AppData\Local\Temp\arduino_build_975191/Mega.ino.ino.hex contains 23824 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 2.80s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x4000
         0xff != 0x8f
avrdude: verification error; content mismatch

выбранный последовательный порт 
 не существует или плата не подключена к нему
avrdude done.  Thank you.

вы прошиваете всю плату в вашей схеме ? или отключаете при прошивке ?

При прошивке - я отключаю питание (разрываю фазу от ИПБ, блоки питания отключаются). Ну и - тупо вставляю шнур от USB. Загорается только дисплей… Из разъёмов (пинов) Ардуино при этом - провода не вынимаю. Как при управлении установкой они…

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

не сложно. Попробую. Там на винтиках все присоединения

удалось прошить ?

Повытаскивал все проводки из контроллера. Контроллер подключён только через USB шнур к ноутбуку.
Загрузить код в контроллер без ошибок - не удаётся.
Код - загружается, в принципе. Но в конце выдаёт ошибку.
При этом, после загрузки кода - дисплей ведёт себя так, как будто выполняется только прорисовка дисплея с выводом графика, один за другим (быстро)

но сам дисплей - соединен с контроллером…
щас ещё попробую прошить без дисплея

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