#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <OneWire.h>
OneWire ds(21); // выбор пина ардуино, на котором висит шина 1-wire
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
// Assign human-readable names to some common 16-bit color values:
#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
#define pinVoda_tick 18 //счетчик воды
boolean stateCheck_voda;
#define pinElectr_tick 19 //счетчик электричества
boolean stateCheck_electr;
boolean n = 0;//для получения температуры
//адреса для датчиков температуры
//0xDB00000EB43A8C28, {0x28, 0x8C, 0x3A, 0xB4, 0xE, 0x0, 0x0, 0xDB} //1 (оригинал)
//0x3A00000076A76F28, {0x28, 0x6F, 0xA7, 0x76, 0x0, 0x0, 0x0, 0x3A} //2
//0xAB00000075289528, {0x28, 0x95, 0x28, 0x75, 0x0, 0x0, 0x0, 0xAB} //3
//0x2900000072CDFF28, {0x28, 0xFF, 0xCD, 0x72, 0x0, 0x0, 0x0, 0x29} //4
//0xF9000000739C4F28, {0x28, 0x4F, 0x9C, 0x73, 0x0, 0x0, 0x0, 0xF9} //5
//0xAC00000072FB2C28, {0x28, 0x2C, 0xFB, 0x72, 0x0, 0x0, 0x0, 0xAC} //6
//0x2D00000072D1FC28, {0x28, 0xFC, 0xD1, 0x72, 0x0, 0x0, 0x0, 0x2D} //7
//0x760000007697D528, {0x28, 0xD5, 0x97, 0x76, 0x0, 0x0, 0x0, 0x76} //8
//0x5F00000072E5EA28, {0x28, 0xEA, 0xE5, 0x72, 0x0, 0x0, 0x0, 0x5F} //9
//0x58000000768CEF28, {0x28, 0xEF, 0x8C, 0x76, 0x0, 0x0, 0x0, 0x58} //10
//0xC400000077899C28, {0x28, 0x9C, 0x89, 0x77, 0x0, 0x0, 0x0, 0xC4} //11
//массивы для графиков
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];
//для отображения точных значений с датчиков
int16_t tOverheatReal;
int32_t gWaterReal;
int32_t heatPowerReal;
int32_t ElectrPowReal;
int32_t COPreal;
int32_t gWaterRealPrew;//для фиксирования предыдущего показания для отображения при сбоях
boolean FlagWater = false;//флаг для фиксирования сбоев показаний водомера
//для подсчёта тепла и электричества
int32_t countHeatAndElectr = 0;
int32_t countHeat = 0;
int32_t countElectr = 0;
uint32_t myTimer1; //для таймера цикла
boolean Flag1 = true;
uint8_t countGetGrafic = 34;
uint8_t tKompressorCounter = 0;//для подсчёта количества корректных замеров перед отключением и включением вентилятора
int16_t trend_fan[20]; //массив для отображения графика работы вентилятора
int16_t trend_kompressor[20]; //массив для отображения графика работы компрессора
int16_t trend_pump[20]; //массив для отображения графика работы насоса
int16_t trend_4way_valve[20]; //массив для отображения графика работы четырёхходового клапана
//для водомера
uint32_t tmr;
boolean gWaterFlag = false; //флаг для водомера при прерывании
uint32_t WaterStartTimer; //засечка времени старта отсчёта времени для водомера
uint32_t WaterCountTimer; //сколько времени прошло между срабатываниями
//для электросчётчика
uint32_t tmr2;
boolean ElectrFlag = false; //флаг для электросчётчика при прерывании
uint32_t ElectrStartTimer; //засечка времени старта отсчёта времени для электросчётчика
uint32_t ElectrCountTimer; //сколько времени прошло между срабатываниями
uint32_t HeatOptionPauseStartTime;//для отсчёта времени и прокрутки насоса в режиме паузы прогрева
//для контроля режимов
uint32_t StartHeatTime;//для фиксации времени начала режима работы "нагрев"
uint32_t StopTime;//для фиксации времени останова
boolean StartHeatFlag = false;//флаг для активации и окончания перехода в режим "нагрев"
boolean StopFlag = false;//флаг для перехода в режим "останов"
boolean HeatOption = false;//флаг о том что в работе режим "нагрев"
boolean HeatOptionPause = false;//режим приостанова нагрева
uint8_t HeatOptionCout = 0; //счётчик для смены режима на приостанов нагрева
uint8_t HeatOptionPauseCout = 0; //счётчик для смены режима окончания приостанова нагрева
uint8_t defrostCount = 0; //счётчик для перехода в режим Defrost
boolean DefrostOption = false; //флаг о начале работы режима Defrost
uint32_t DefrostTime;//для фиксации времени начала режима работы Defrost
// ниже перечисление температур
typedef enum Temper_enum
{
KompressorC, //0
WaterInC, //1
WaterOutC, //2
temp3C, //3
DefrostC, //4
IsparitelC, //5
size_array_Temp //6 size
} Temper_ENUM;
// ниже сами переменные температур, изначально ставим 0*С
int16_t Temper[size_array_Temp] =
{
0, //KompressorC 0
0, //WaterInC 1
0, //WaterOutC 2
0, //temp3C 3
0, //DefrostC 4
0 //IsparitelC 5
};
// например, чтобы использовать переменную температуры на улице, пишем так: Temper[UlicaC] =
// ниже соответствие адресов датчиков определённым температурам
byte ADDR_DS18B20 [size_array_Temp][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
};
//расход воды без прерывания
void voda_tick() {
//Serial.println("proverka");
boolean current_status = digitalRead(pinVoda_tick);
if (stateCheck_voda and !current_status) {
tmr = millis(); //зафиксировали время срабатывания прерывания
gWaterFlag = true;
stateCheck_voda = current_status;
}
if (!stateCheck_voda and current_status)stateCheck_voda = current_status;
if (current_status)gWaterFlag = false;
if (!current_status and millis() - tmr >= 1000 and gWaterFlag == true)
{
WaterCountTimer = millis() - WaterStartTimer;
WaterStartTimer = millis();
gWaterFlag = false;
}
}
//электрическая мощность без прерывания
void electr_tick() {
//Serial.println("proverka");
boolean current_status = digitalRead(pinElectr_tick);
if (stateCheck_electr and !current_status) {
tmr2 = millis(); //зафиксировали время срабатывания прерывания
ElectrFlag = true;
stateCheck_electr = current_status;
}
if (!stateCheck_electr and current_status)stateCheck_electr = current_status;
if (current_status)ElectrFlag = false;
if (!current_status and millis() - tmr2 >= 50 and ElectrFlag == true)
{
ElectrCountTimer = millis() - ElectrStartTimer;
ElectrStartTimer = millis();
ElectrFlag = false;
}
}
void getDataInt100(int16_t a)//вывод значений на дисплей у которых делится на 100
{
//Serial.println("proverka");
if (a >= -9 and a < 0)
{
tft.print("-0.0");
tft.print(abs(a));
}
else if (a<9 and a >= 0)
{
tft.print("0.0");
tft.print(a);
}
else if (a <= -10 and 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)//вывод значений на дисплей у которых делится на 10
{
//Serial.println("proverka");
if (a >= -9 and a < 0)
{
tft.print("-0.");
tft.print(abs(a));
}
else if (a<9 and a >= 0)
{
tft.print("0.");
tft.print(a);
}
else
{
tft.print(a / 10);
tft.print(".");
tft.print(abs(a % 10));
}
}
int16_t getDataForUintMassiv(int16_t a)//границы для последнего значения в массиве для графиков, типа uint8_t
{
//Serial.println("proverka");
int16_t LastInMassive;//ввожу временную переменную для вычисления последнего значения массива для графиков
if (a < -400)
LastInMassive = 0;
else if (a >= -400 and a < 500)
LastInMassive = round ((a + 400) / 5);
else if (a >= 500 and a < 1250)
LastInMassive = round (180 + (a - 500) / 10);
else if (a >= 1250)
LastInMassive = 255;
return LastInMassive;
}
int32_t getDataForUintMassiv32(int32_t a)//границы для последнего значения в массиве для графиков, типа uint8_t
{
//Serial.println("proverka");
int32_t LastInMassive;//ввожу временную переменную для вычисления последнего значения массива для графиков
if (a < -400)
LastInMassive = 0;
else if (a >= -400 and a < 0)
LastInMassive = round ((a + 400) / 10);
else if (a >= 0 and a < 430)
LastInMassive = round (40 + a / 2);
else if (a >= 430)
LastInMassive = 255;
return LastInMassive;
}
void getGraphics(uint16_t c, uint16_t d, uint8_t g[320]) //процедура построения графиков
{
//Serial.print("proverka");
int16_t oldX = 0;
int16_t oldY = g[0];
for (int16_t x = 1; x < 320; x++)
{
int16_t nxt_x = x;
tft.drawLine(oldX, (c - oldY), nxt_x, (c - g[x]), d);
oldY = g[x];
oldX = nxt_x;
}
}
void getMainDisplay()//вычерчивание основного дисплея
{
Serial.println("proverka");
tft.fillScreen(BLACK);
//сетка по времени:
for (uint8_t i = 0; i < 13; i++)
{
tft.drawFastVLine((9 + 24 * i), 20, 190, DARKGREY);
tft.drawFastVLine((9 + 24 * i), 230, 210, DARKGREY);
}
//сетка по шкале температур:
for (uint8_t i = 0; i < 11; i++)
{
if (i == 4 or i == 5 or i == 6 or i == 7 or i == 9 or i == 10)
tft.drawFastHLine(0, (5 + 20 * i), 320, DARKGREEN);
else if (i == 1 or i == 2 or i == 3 or i == 8)
tft.drawFastHLine(0, (5 + 20 * i), 320, BLUE);
}
for (uint8_t i = 0; i < 11; i++)
tft.drawFastHLine(0, (235 + 20 * i), 320, BLUE);
//подписи по вертикали на графиках
tft.setCursor(0, 22); // Устанавливаем курсор (X = , Y = )
tft.setTextSize(1); // Указываем размер символов в строке от 1 до 3
tft.setTextColor(WHITE, BLACK); // Указываем цвет текста
tft.print("90");
tft.setCursor(0, 42); // Устанавливаем курсор (X = , Y = )
tft.print("70");
tft.setCursor(0, 62); // Устанавливаем курсор (X = , Y = )
tft.print("50");
tft.setCursor(0, 82); // Устанавливаем курсор (X = , Y = )
tft.print("40");
tft.setCursor(0, 102); // Устанавливаем курсор (X = , Y = )
tft.print("30");
tft.setCursor(0, 122); // Устанавливаем курсор (X = , Y = )
tft.print("20");
tft.setCursor(0, 142); // Устанавливаем курсор (X = , Y = )
tft.print("10");
tft.setCursor(0, 162); // Устанавливаем курсор (X = , Y = )
tft.print("0");
tft.setCursor(0, 182); // Устанавливаем курсор (X = , Y = )
tft.print("-10");
tft.setCursor(0, 202); // Устанавливаем курсор (X = , Y = )
tft.print("-20");
tft.setCursor(0, 232); // Устанавливаем курсор (X = , Y = )
tft.print("4");
tft.setCursor(0, 252); // Устанавливаем курсор (X = , Y = )
tft.print("3.6");
tft.setCursor(0, 272); // Устанавливаем курсор (X = , Y = )
tft.print("3.2");
tft.setCursor(0, 292); // Устанавливаем курсор (X = , Y = )
tft.print("2.8");
tft.setCursor(0, 312); // Устанавливаем курсор (X = , Y = )
tft.print("2.4");
tft.setCursor(0, 332); // Устанавливаем курсор (X = , Y = )
tft.print("2");
tft.setCursor(0, 352); // Устанавливаем курсор (X = , Y = )
tft.print("1.6");
tft.setCursor(0, 372); // Устанавливаем курсор (X = , Y = )
tft.print("1.2");
tft.setCursor(0, 392); // Устанавливаем курсор (X = , Y = )
tft.print("0.8");
tft.setCursor(0, 412); // Устанавливаем курсор (X = , Y = )
tft.print("0.4");
tft.setCursor(0, 432); // Устанавливаем курсор (X = , Y = )
tft.print("0");
//надписи назначения измерений датчиков
tft.setCursor(0, 0); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
tft.print("Kompressor:");
tft.setCursor(10, 10); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(MAGENTA); // Указываем цвет текста
tft.print("Overheat:");
tft.setCursor(125, 10); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(CYAN); // Указываем цвет текста
tft.print("Defrost:");
tft.setCursor(220, 10); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
tft.print("Isparitel:");
tft.setCursor(120, 0); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(YELLOW); // Указываем цвет текста
tft.print("Water in:");
tft.setCursor(220, 0); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(GREEN); // Указываем цвет текста
tft.print("Water out:");
tft.setCursor(5, 210); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
tft.print("Heat power:");
tft.setCursor(152, 210); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(YELLOW); // Указываем цвет текста
tft.print("COP:");
tft.setCursor(218, 210); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(GREEN); // Указываем цвет текста
tft.print("Electr pow:");
tft.setCursor(22, 220); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(MAGENTA); // Указываем цвет текста
tft.print("G water:");
}
void setup()
{ // put your setup code here, to run once:
//Serial.println("proverka");
Serial.begin(9600);
tft.reset();
tft.begin(38022); //указание модели экрана
tft.invertDisplay(true); //инверсия цветов - т.к. по умолчанию инвертирует цвета
//tft.setRotation(1); //поворот экрана на 90 градусов
//для водомера
pinMode(18, INPUT_PULLUP);// подключили импульсный выход на D18 и +5
stateCheck_voda = digitalRead(pinVoda_tick);
//для электросчётчика
pinMode(19, INPUT_PULLUP);// подключили импульсный выход на D19 и +5
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);//управление насосом
//инициирую режим "нагрев" при старте микроконтроллера
StartHeatTime = millis();//фиксация времени начала перехода в режим "нагрев"
StartHeatFlag = true;//поднят флаг о том, что начался переход в режим "нагрев"
delay(1000); //задержка 1 сек
myTimer1=millis();
}
void loop()// put your main code here, to run repeatedly:
{
voda_tick();//переход на процедуру по подсчёту расхода воды
electr_tick();//переход на процедуру по подсчёту электрической мощности
//код управления режимами
if (StartHeatFlag == true and millis() - StartHeatTime >= 20000 and Temper[WaterInC] >= 50)//если начат переход в режим "нагрев" и при этом прошло время после старта перехода и температура воды перед ППТО более 5 град.
digitalWrite(51, LOW);//включить насос
if (StartHeatFlag == true and millis() - StartHeatTime >= 30000 and Temper[KompressorC] <= 850)//если начат переход в режим "нагрев" и при этом прошло время после старта перехода и температура компрес. менее 85 град.
digitalWrite(48, LOW);//включить вентилятор
if (StartHeatFlag == true and millis() - StartHeatTime >= 40000)//если начат переход в режим "нагрев" и при этом прошло время после старта перехода
digitalWrite(49, LOW);//переключить четырёхходовой клапан в режим "нагрев"
if (StartHeatFlag == true and millis() - StartHeatTime >= 45000 and digitalRead(51) == LOW and digitalRead(49) == LOW)//если начат переход в режим "нагрев" и при этом прошло время после старта перехода и включён насос и четырёхходовой клапан в режим "нагрев"
digitalWrite(50, LOW);//включить компрессор
if (StartHeatFlag == true and digitalRead(51) == LOW and digitalRead(48) == LOW and digitalRead(50) == LOW and digitalRead(49) == LOW)//если начат переход в режим "нагрев" и все требуемые для этого устройства включены
{
StartHeatFlag = false;//окончен переход в режим "нагрев"
HeatOption = true;//действует режим "нагрев"
}
if (HeatOption == true and (digitalRead(49) == HIGH or Temper[DefrostC] <= 50 ))
{
digitalWrite(50, HIGH);//остановить компрессор
HeatOption = false;//отключить режим "обогрев"
StopFlag = true;//переход в режим останов
StopTime = millis();
}
if (StopFlag == true)
{
digitalWrite(50, HIGH);//остановить компрессор
digitalWrite(48, HIGH);//остановить вентилятор
if (millis() - StopTime >= 120000)
digitalWrite(49, HIGH);//перевести четырёхходовой клапан в штатное положение (режим "охлаждение")
}
if (DefrostOption == true)
{
digitalWrite(51, LOW);//включить насос
digitalWrite(50, HIGH);//остановить компрессор
digitalWrite(48, HIGH);//остановить вентилятор
if (millis() - DefrostTime >= 120000)
digitalWrite(49, HIGH);//перевести четырёхходовой клапан в штатное положение (режим "охлаждение")
if (millis() - DefrostTime >= 1200000 and Temper[IsparitelC] >= 20)
{
DefrostOption = false;
StartHeatTime = millis();
StartHeatFlag = true;
}
}
//первый шаг выполнения по таймеру
if (millis() - myTimer1 >= 2000 and Flag1 == true and countGetGrafic < 36)
{
//****************************измерение температуры***************************************
// флаг работы: запрос температуры или её чтение
n = !n;
if (n) {
ds.reset(); // сброс шины
ds.write(0xCC);//обращение ко всем датчикам
ds.write(0x44);// начать преобразование (без паразитного питания)
}
else {
for (uint8_t i = 0; i < size_array_Temp; i++) { // цикл фор перебирает все датчики t
int16_t Temper_ = 200;
uint8_t buff[9];
ds.reset();
ds.select(ADDR_DS18B20[i]); //выбор адреса DS18B20
ds.write(0xBE); // Read Scratchpad (чтение регистров)
for (uint8_t j = 0; j < 9; j++) buff[j] = ds.read(); //читаем все 9 байт от датчика
ds.reset();
if (OneWire::crc8(buff, 8) == buff[8]) { // если CRC верна
Temper_ = buff[0] | (buff[1] << 8); // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
Temper_ = (Temper_ * 10) >> 4; //целое в десятых *C (214=>21,4*C)
if (Temper_ < 1500 && Temper_ > -500 && Temper_ != 850 && Temper_ != -1270) // ещё раз перестраховываемся от дерьмовых значений
{
Temper[i] = (int16_t) Temper_;// всё, тут уже пишем температуру в переменную
}
}
}
}
//****************************измерение температуры***************************************
//вычисляю перегрев
tOverheatReal = (Temper[temp3C] - Temper[IsparitelC]);
//расчёт расхода воды
if (millis() - WaterStartTimer > 300000 or digitalRead(51) == HIGH) //если в течение 5 мин не пришёл сигнал с водомера либо выключен насос
{
gWaterReal = 0;
//Serial.println(millis()-WaterStartTimer);
FlagWater = false;//сброшен флаг подсветки значения
}
else if (3600000 / WaterCountTimer > 200)//если пришло нереально большое значение
{
gWaterReal = gWaterRealPrew;
FlagWater = true;//поднят флаг для подсветки значения расхода
}
else
{
//Serial.println("vhod");
gWaterReal = (3600000 / WaterCountTimer); //итоговое значение в м3/ч умноженные на 100
gWaterRealPrew = gWaterReal;
FlagWater = false;//сброшен флаг подсветки значения
//Serial.println(FlagWater);
}
//расчёт электрической мощности
if (millis() - ElectrStartTimer > 60000) //если нет данных с счётчика в течение 1 мин.
ElectrPowReal = 0;
else
ElectrPowReal = 72000 / ElectrCountTimer; //значение в кВт умноженные на 100
//Serial.println(ElectrCountTimer);
//Serial.println(ElectrPowReal);
heatPowerReal = ((int32_t)Temper[WaterOutC] - (int32_t)Temper[WaterInC]) * gWaterReal * 1163 / 10000; //тепловая мощность на теплообменнике в кВт умноженная на 100
//Serial.println(tWaterOutReal);
//Serial.println(tWaterInReal);
//Serial.println(gWaterReal);
//Serial.println(heatPowerReal);
if (ElectrPowReal < 10)
COPreal = 0;
else
COPreal = 100 * heatPowerReal / ElectrPowReal; //вычисление COP, умноженное на 100
//Serial.println(heatPowerReal);
//Serial.println(ElectrPowReal);
//Serial.println(COPreal);
//подсчёт средней тепловой мощности и электроэнергии
countHeat = countHeat + heatPowerReal;
countElectr = countElectr + ElectrPowReal;
countHeatAndElectr++;
//останов вентилятора при перегреве компрессора
if (HeatOption == true and Temper[KompressorC] >= 850 and tOverheatReal >= 300 and digitalRead(48) == LOW)//если высокая температура на выходе из компрессора и перегрев с запасом и вентилятор включён
{
tKompressorCounter++;
if (tKompressorCounter >= 5)//если сработал счётчик
{
digitalWrite(48, HIGH);//отключить вентилятор
tKompressorCounter = 0;
}
}
else if (HeatOption == true and (Temper[KompressorC] <= 750 or tOverheatReal <= 200) and digitalRead(48) == HIGH)//если остыл компрессор или перегрев мал и вентилятор выключен
{
tKompressorCounter++;
if (tKompressorCounter >= 3)//если сработал счётчик
{
digitalWrite(48, LOW);//включить вентилятор
tKompressorCounter = 0;
}
}
else
tKompressorCounter = 0;
//смена режимов
if (HeatOption == true and Temper[WaterInC] >= 360)//если температура воды перед теплообменником достигла 36 град.
{
HeatOptionCout++;
if (HeatOptionCout >= 10)//если устоялся режим
{
HeatOption = false;
HeatOptionPause = true;
HeatOptionCout = 0;
HeatOptionPauseStartTime = millis();
digitalWrite(50, HIGH);//остановить компрессор
digitalWrite(48, HIGH);//остановить вентилятор
}
}
else
HeatOptionCout = 0;
if (HeatOptionPause == true and digitalRead(49) == LOW and millis() - HeatOptionPauseStartTime >= 120000) //если началась пауза обогрева и 4х ход. клапан включён и вышло время
digitalWrite(49, HIGH);//перевести четырёхходовой клапан в штатное положение (режим "охлаждение")
if (HeatOptionPause == true and digitalRead(51) == HIGH and millis() - HeatOptionPauseStartTime >= 960000) //если прошло время 15 мин. после остановки насоса
{
digitalWrite(51, LOW);//включить насос
HeatOptionPauseStartTime = millis();
}
if (HeatOptionPause == true and digitalRead(51) == LOW and millis() - HeatOptionPauseStartTime >= 60000) //если прошло время 1 мин. после включения насоса
{
digitalWrite(51, HIGH);//выключить насос
HeatOptionPauseStartTime = millis();
}
if (HeatOptionPause == true and Temper[WaterInC] <= 280)//если в режиме паузы обогрева температура воды перед теплообменником низкая
{
HeatOptionPauseCout++;
if (HeatOptionPauseCout >= 10)//если устоялся режим
{
HeatOptionPause = false;
HeatOptionPauseCout = 0;
StartHeatTime = millis();//фиксация времени начала перехода в режим "нагрев"
StartHeatFlag = true;//поднят флаг о том, что начался переход в режим "нагрев"
}
}
else
HeatOptionPauseCout = 0;
//режим разморозки
if (HeatOption == true and Temper[IsparitelC] < -100)
defrostCount++;
else
defrostCount = 0;
if (HeatOption == true and Temper[IsparitelC] < -100 and defrostCount >= 10)
{
HeatOption = false;
DefrostOption = true;
DefrostTime = millis();
}
Flag1 = false;
}
//второй шаг выполнения по таймеру
if (millis() - myTimer1 >= 5000)
{
//вычерчивание чёрных прямоугольников для закрашивания предыдущих значений с датчиков
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); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
getDataInt10(Temper[KompressorC]);
tft.setCursor(181, 0); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(YELLOW); // Указываем цвет текста
getDataInt10(Temper[WaterInC]);
tft.setCursor(289, 0); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(GREEN); // Указываем цвет текста
getDataInt10(Temper[WaterOutC]);
tft.setCursor(74, 10); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(MAGENTA); // Указываем цвет текста
getDataInt10(tOverheatReal);
tft.setCursor(181, 10); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(CYAN); // Указываем цвет текста
getDataInt10(Temper[DefrostC]);
tft.setCursor(289, 10); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
getDataInt10(Temper[IsparitelC]);
tft.setCursor(74, 210); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
getDataInt100(heatPowerReal);
tft.setCursor(181, 210); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(YELLOW); // Указываем цвет текста
getDataInt100(COPreal);
tft.setCursor(289, 210); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(GREEN); // Указываем цвет текста
getDataInt100(ElectrPowReal);
tft.setCursor(74, 220); // Устанавливаем курсор (X = , Y = )
if (FlagWater == true)
tft.setTextColor(CYAN, MAGENTA); // Указываем цвет текста
else
tft.setTextColor(MAGENTA); // Указываем цвет текста
getDataInt100(gWaterReal);
tft.setCursor(100, 470); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
getDataInt100(countHeat / countHeatAndElectr);
tft.setCursor(200, 470); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(GREEN); // Указываем цвет текста
getDataInt100(countElectr / countHeatAndElectr);
tft.setCursor(152, 220); // Устанавливаем курсор (X = , Y = )
tft.setTextColor(RED); // Указываем цвет текста
if (StopFlag == true)//если режим "останов" активен
tft.print("Stop");
else if (StartHeatFlag == true)
tft.print("Start heat");
else if (HeatOption == true)
tft.print("Heat option");
else if (HeatOptionPause == true)
tft.print("Pause heat");
else if (DefrostOption == true)
tft.print("Defrost");
//надписи для линий "включено_выключено"
tft.setCursor(0, 440); // Устанавливаем курсор (X = , Y = )
if (digitalRead(50) == LOW)
tft.setTextColor(RED); // Указываем цвет текста
else
tft.setTextColor(BLUE); // Указываем цвет текста
tft.print("Kompressor");
tft.setCursor(0, 450); // Устанавливаем курсор (X = , Y = )
if (digitalRead(51) == LOW)
tft.setTextColor(RED); // Указываем цвет текста
else
tft.setTextColor(BLUE); // Указываем цвет текста
tft.print("Pump");
tft.setCursor(0, 460); // Устанавливаем курсор (X = , Y = )
if (digitalRead(49) == LOW)
tft.setTextColor(RED); // Указываем цвет текста
else
tft.setTextColor(BLUE); // Указываем цвет текста
tft.print("4 way valve");
tft.setCursor(0, 470); // Устанавливаем курсор (X = , Y = )
if (digitalRead(48) == LOW)
tft.setTextColor(RED); // Указываем цвет текста
else
tft.setTextColor(BLUE); // Указываем цвет текста
tft.print("Fan");
countGetGrafic++;//для подсчёта времени между вывода графика
myTimer1 = millis();
Flag1 = true;
}
//первый шаг выполнения по таймеру (график периодически)
if (millis() - myTimer1 >= 2000 and Flag1 == true and countGetGrafic >= 36)
{
//перенос значений в массиве
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[KompressorC]);
tWaterIn[319] = (uint8_t)getDataForUintMassiv(Temper[WaterInC]);
tWaterOut[319] = (uint8_t)getDataForUintMassiv(Temper[WaterOutC]);
tOverheat[319] = (uint8_t)getDataForUintMassiv(tOverheatReal);
tDefrost[319] = (uint8_t)getDataForUintMassiv(Temper[DefrostC]);
tIsparitel[319] = (uint8_t)getDataForUintMassiv(Temper[IsparitelC]);
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; 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, !digitalRead(48));
bitWrite(trend_kompressor[19], 0, !digitalRead(50));
bitWrite(trend_pump[19], 0, !digitalRead(51));
bitWrite(trend_4way_valve[19], 0, !digitalRead(49));
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; //для подсчёта времени между выводами графика
Flag1 = false;
}
}