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

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


то загрузка кода проходит без сообщения об ошибке, но при этом - на дисплее можно наблюдать сбои, наподобие того, что буквы могут иметь некорректные координаты (расположение на дисплее).
Я уже приловчился, случайно нашёл способ обходить эту проблему. Заметил, что если добавить строчку “Serial.println(…)” - то ошибка при загрузке эта - уходит. Иногда помогает не “Serial.println(…)”, а “Serial.print(…)”. Также - зависит от того, в какой процедуре это находится.
В общем, чтобы загрузить вчерашний код без ошибки, мне понадобилось добавить “Serial.println(“proverka”)” в пункте 27 “ОТРИСОВКА ГРАФИКОВ”

Спойлер
/*
 * ПРОГРАММА ДЛЯ МОНИТОРИНГА ТЕПЛОВОГО НАСОСА
 * 
 * Что делает программа:
 * 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) {
  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
}

// ========== 19. ФУНКЦИЯ ЧТЕНИЯ ТЕМПЕРАТУРЫ С ДАТЧИКА ==========
// Возвращает температуру в десятых долях (например 156 = 15.6°C)
// Если ошибка - возвращает 0x7FFF (максимальное число)
int16_t readDS18B20(byte *addr) {
  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;  // Преобразуем в десятые доли градуса
}

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

// ========== 21. ФУНКЦИЯ ПОЛУЧЕНИЯ ТЕМПЕРАТУР ==========
// Читаем температуру со всех 6 датчиков
void gettingTemp() {
  // Проходим по всем датчикам (от 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;             // Причина: ошибка датчика
        }
      }
    }
  }
}

// ========== 22. ПРОВЕРКА ГРАНИЦ ТЕМПЕРАТУР ==========
// Проверяем, не выходит ли температура за разумные пределы
void tempMistake(uint8_t a, int16_t b, int16_t c, int16_t d) {
  // 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;  // Ошибка показаний датчика
    }
  }
}

// ========== 23. ОБРАБОТЧИК ИМПУЛЬСОВ СЧЁТЧИКА ВОДЫ ==========
// Вызывается часто в loop() для отслеживания импульсов
void voda_tick() {
  // Читаем текущее состояние пина (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;
  }
}

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

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

// Вывод числа с точностью до сотых (например 1234 = 12.34)
void getDataInt100(int16_t a) {
  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));  // Дробная часть
  }
}

// Вывод числа с точностью до десятых (например 123 = 12.3)
void getDataInt10(int16_t a) {
  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));  // Дробная часть
  }
}

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

// То же самое, но для больших чисел (мощности)
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]) {
  // c - базовая линия по Y (где находится "ноль" графика)
  // d - цвет линии
  // g - массив с данными (320 точек)

  Serial.println("proverka");
  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;
  }
}

// ========== 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 порт для отладки
  
  // Настраиваем дисплей
  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 секунду для стабилизации
}

// ========== 30. ГЛАВНЫЙ ЦИКЛ (ВЫПОЛНЯЕТСЯ БЕСКОНЕЧНО) ==========
void loop() {
  // Постоянно проверяем импульсы счётчиков
  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;
  }
}

при этом, предыдущий код, из из сообщения 58 загружался без появления подобной ошибки.
Когда загружается код без “плясок” наподобие добавления “Serial.println(“proverka”)” - мне радостно на душе. Вчера вот - не получилось этого. Подумал, следует сообщить. Вдруг это что-то значит.
Далее. После загрузки нового кода, некоторое время простоял рядом, понаблюдал


код отработал штатно. Никаких ошибок не наблюдал. По прошествии 1,5 часа его работы - сделал это фото дисплея и пошёл спать (было уже поздно). В голове созрел вопрос: почему в предыдущем варианте кода - я неоднократно наблюдал “вылетевшие” значения по “G water”, а теперь, с этим вариантом кода они отсутствовали? Это просто случайность, “так сошлись звёзды”, или же что-то в этом направлении было изменено в коде?
Утром пошёл смотреть. Прошло 9 часов с момента загрузки кода и запуска. Наблюдаю такую картину:

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