/*
Представляю свой вариант пивоварни на ардуино. Данная пивоварня полностью автоматизирует
процесс затирания. Доварить сусло можно либо на газу, либо в ручном режиме установив
температуру 100 градусов.
Поддержать проект можно:
1. На карту Сбербанк 5570 0000 5654 8372 Максим Сергеевич К
2. На карту Тинькофф 2200 7004 4399 5476
3. На карту ЮMoney 2204 1201 0998 8473
4. На кошелек ЮMoney 410018618410083
5. По ссылке https://yoomoney.ru/to/410018618410083
=================================================================================
MIT License
Copyright (c) 2023 Max
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==================================================================================
*/
#include <dht.h> //Удалить
#include <math.h> // математическая библиотека
#include <Wire.h> // Подключаем библиотеку для работы с шиной I2C
#include <EEPROM.h> // Подключаем библиотеку для работы с EEPROM
#include <LiquidCrystal_I2C.h> // Библиотека для работы с LCD
#include <microDS18B20.h> //библиотека датчика температуры
#include <EncButton.h> //библиотека энкодера
EncButton enc(2, 3, 4);
#define heater_pin 12 //пин управление тэн
#define buzzer_pin 11 // Пин подключения пассивной пищалки
#define EB_DEB 20 // дебаунс кнопки, мс по умолчанию 50
#define pump 10 // пин управление насосом
#define KEY_SAVE 1023 // адрес для хранения первого запуска
#define KEY 1 // ключ для первого запсука
#define DHT22_PIN 6 // удалить
dht DHT; // Удалить
LiquidCrystal_I2C lcd(0x27, 20, 4); //Подключаем дисплей с адрсеом 0x27
//MicroDS18B20<6> ds; //датчик температуры на 6 пин Раскоментировать
uint8_t main_ptr = 1; //Указатель главного меню
uint8_t program_ptr = 1; //Указатель меню выбора и редактирования программ
bool end_loop; //Флаг выхода из меню выбора и редактирования программ
float cur_temp = 0; //текущаяя температура
float data_pid[3]; // массив коэф пид
uint16_t activePeriod;
void setup() {
pinMode(buzzer_pin, OUTPUT);
pinMode(heater_pin, OUTPUT);
pinMode(pump, OUTPUT);
lcd.init(); // Инициируем работу с LCD дисплеем
lcd.backlight(); // Включаем подсветку LCD дисплея
Serial.begin(115200);
attachInterrupt(0, isr, CHANGE);
attachInterrupt(1, isr, CHANGE);
if (EEPROM.read(KEY_SAVE)!=KEY){
EEPROM.write(KEY_SAVE, KEY);
EEPROM.put(1, 0.0);
EEPROM.put(5, 0.0);
EEPROM.put(9, 0.0);
}
EEPROM.get(1, data_pid);
}
void isr() {
enc.tickISR(); // тикер в прерывании
// Не вызывает подключенные коллбэки внутри прерывания!!!
}
void loop() {
enc.tick();
lcd.setCursor(6, 0);
lcd.print("Main menu");
lcd.setCursor(3, 1);
lcd.print("Program selection");
lcd.setCursor(3, 2);
lcd.print("Program editing");
lcd.setCursor(3, 3);
lcd.print("Manual mode");
lcd.setCursor(0, main_ptr);
lcd.print("->");
if (enc.right()) {
lcd.setCursor(0, main_ptr);
lcd.print(" ");
main_ptr++;
if (main_ptr == 4) main_ptr = 1;
}
if (enc.left()) {
lcd.setCursor(0, main_ptr);
lcd.print(" ");
main_ptr--;
if (main_ptr == 0) main_ptr = 3;
}
if (enc.click()) {
if (main_ptr == 1) { Program_selection(); }
if (main_ptr == 2) { Program_editing(); }
if (main_ptr == 3) { Manual_mod(); }
}
}
void get_temp() {
static uint32_t temp_timer = 0;
if (millis() - temp_timer >= 1000) {
temp_timer = millis();
DHT.read22(DHT22_PIN); //Удалить
cur_temp = DHT.temperature; //Удалить
/*if (ds.readTemp()) { //Раскоментировать
cur_temp = ds.getTemp();
ds.requestTemp();
}*/ //Раскоментировать
}
}
void Program_selection() {
lcd.clear();
for (end_loop = false; !end_loop;) {
bool exit = false; // флаг выхода
bool edit_pump = false; // редактор насоса
bool alarm_temp = false; // выход за границы темп.режима
int8_t exit_ptr = 0; // указатели выхода
int8_t list = 0; // страница для переключения управлением насоса
lcd.setCursor(2, 0);
lcd.print("Program selection");
Program_menu();
if (enc.click()) {
int8_t data [3];
int8_t prev_temp;
EEPROM.get(program_ptr * 100, data);
int8_t amt = data[0];
bool prog_correct = false; //Проверка корректности записанной программы
if (amt > 0 && amt <10) prog_correct = true; // Количество пауз
for (int8_t i = 0; i <= amt && prog_correct; i++) {
if (i == 0) {
if (data [1] < 20 || data [1] > 100) prog_correct = false; // температура
if (data [2] < 10 || data [2] > 100) prog_correct = false; //мощность
}else{
EEPROM.get(program_ptr * 100 + i * 3, data);
if (data [0] < 1 || data [0] > 120) prog_correct = false; //длительность
if (data [1] < prev_temp || data [1] > 100) prog_correct = false; // температура
if (data [2] < 10 || data [2] > 100) prog_correct = false; //мощность
}
prev_temp = data [1];
} // Конец проверки корректности программы
if (prog_correct){
digitalWrite(pump, HIGH);
bool flag = false; // Флаг выхода на температурный режим
uint32_t Tmr_ms; //Таймер температурного режима
lcd.clear();
EEPROM.get(program_ptr * 100, data);
for(uint8_t pause_ptr = 0; pause_ptr <= amt + 1;){
get_temp();
heat(data[1], data[2]);
if ((cur_temp > data[1] - 0.5 || pause_ptr == amt + 1) && !flag){
flag = true;
Tmr_ms = millis();
}
if ( cur_temp - data[1] > 1.5 ) biper();
else digitalWrite(buzzer_pin, LOW);
// отображение меню
if ( list == 0 ) {
lcd.setCursor(1, 0);
lcd.print("Program ");
lcd.print(program_ptr);
}
else {
lcd.setCursor(1, 0);
if(digitalRead(pump)){
lcd.print("Pump ON ");
}
else {
lcd.print("Pump OFF ");
}
}
if (pause_ptr == 0){
lcd.print(" Heating");
}else if (pause_ptr == amt + 1){
lcd.print(" finished");
}else{
lcd.print(" Pause ");
lcd.print(pause_ptr);
}
lcd.setCursor(0, 1);
lcd.print("Set temp. ");
lcd.print(data[1]);
lcd.print(char(223));
lcd.print("C");
lcd.setCursor(0, 2);
lcd.print("Cur. temp. ");
lcd.print(cur_temp, 1);
lcd.print(char(223));
lcd.print("C");
if (cur_temp - data[1] > 1.5) lcd.print(char(171));
else lcd.print(" ");
if (exit && !(pause_ptr == amt + 1)){
lcd.setCursor(1, 3);
lcd.print("Exit");
lcd.setCursor(8, 3);
lcd.print("YES");
lcd.setCursor(15, 3);
lcd.print("NO");
}
if (exit_ptr < 1) { // прорисовка указателя
lcd.setCursor(0,0);
} else if (exit_ptr == 1) {
lcd.setCursor(14,3);
} else lcd.setCursor(7,3);
if (edit_pump && list == 1){
lcd.print("!");
} else {
lcd.print(">");
}
//
if (flag){
uint16_t Tmr_s = floor((millis() - Tmr_ms)/1000);
if(Tmr_s % 4 < 2 && Tmr_s < 10) analogWrite(buzzer_pin, 127); //Пищалка
if(Tmr_s % 4 > 1 && Tmr_s <= 10) digitalWrite(buzzer_pin, LOW);
lcd.setCursor(0, 3);
if (pause_ptr == 0 && !exit){
lcd.print("Add malt & press Ok");
enc.tick();
if (enc.click()){
pause_ptr++;
EEPROM.get(program_ptr * 100 + pause_ptr * 3, data);
flag = false;
lcd.clear();
digitalWrite(buzzer_pin, LOW);
}
} else if (pause_ptr == amt + 1) {
lcd.print((Tmr_s / 3600) % 10);
lcd.print(":");
lcd.print((Tmr_s / 600) % 6);
lcd.print((Tmr_s / 60) % 10);
lcd.print(":");
lcd.print((Tmr_s / 10) % 6);
lcd.print(Tmr_s % 10);
lcd.print(" Press Ok");
exit_ptr = 0;
exit = false;
enc.tick();
if (enc.click()){
pause_ptr++;
flag = false;
digitalWrite(buzzer_pin, LOW);
digitalWrite(pump, LOW);
lcd.clear();
}
} else{
if (!exit){
lcd.print("Timer ");
lcd.print(((data[0] * 60 - Tmr_s) / 3600) % 10);
lcd.print(":");
lcd.print(((data[0] * 60 - Tmr_s) / 600) % 6);
lcd.print(((data[0] * 60 - Tmr_s) / 60) % 10);
lcd.print(":");
lcd.print(((data[0] * 60 - Tmr_s) / 10) % 6);
lcd.print((data[0] * 60 - Tmr_s) % 10);
}
if (data[0] * 60 - Tmr_s <= 0){
pause_ptr++;
if (pause_ptr <= amt) {
EEPROM.get(program_ptr * 100 + pause_ptr * 3, data);
}
flag = false;
lcd.clear();
}
}
}
enc.tick();
if ( enc.hold() && !exit ){
edit_pump = false;
exit_ptr = 1;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
exit = !exit;
}
if (enc.right()){
if (exit) {
lcd.setCursor(7,3);
lcd.print(" ");
exit_ptr = 1;
}
else if (!edit_pump) list++;
if (list == 1 && edit_pump == true) digitalWrite(pump, LOW); // изменение переменных
}
if (enc.left()){
if (exit) {
lcd.setCursor(14,3);
lcd.print(" ");
exit_ptr = 2;
}
else if (!edit_pump) list--;
if (list == 1 && edit_pump == true) digitalWrite(pump, HIGH); // изменение переменных
}
if (enc.click()) {
if (list == 1) {
edit_pump = !edit_pump;
}
if (exit_ptr == 1){
lcd.setCursor(0, 3);
lcd.print(" ");
exit_ptr = 0;
exit = false;
} else if (exit_ptr == 2 ) {
lcd.clear();
digitalWrite(pump, LOW);
digitalWrite(buzzer_pin, LOW);
break;
}
}
list = constrain(list, 0, 1);
}
digitalWrite(heater_pin, LOW);
} else {
lcd.clear();
for(;;) {
enc.tick();
lcd.setCursor(1, 1);
lcd.print("Program incorrect");
lcd.setCursor(6, 3);
lcd.print("Press OK");
if (enc.click()) break;
}
Program_editing();
lcd.clear();
}
}
}
}
void Program_editing() {
lcd.clear();
for (end_loop = false; !end_loop;) {
lcd.setCursor(2, 0);
lcd.print("Program editing");
Program_menu();
if (enc.click()) {
lcd.clear();
int8_t data [3]; //Массив
EEPROM.get(program_ptr * 100, data);
uint8_t amt;
int8_t int_ptr = 1;
bool edit_flag = false;
for(int8_t pause_ptr = 0;;){
if (enc.click()) edit_flag = !edit_flag; // переход в режим редактирование
if (pause_ptr == 0){
data[0] = constrain(data[0], 1, 9);
amt = data[0];
lcd.setCursor(5, 0);
lcd.print("Program ");
lcd.print(program_ptr);
lcd.setCursor(1, 1);
lcd.print("Amt of pauses ");
lcd.print(data[0]);
lcd.setCursor(1, 2);
lcd.print("Pour temp. ");
} else {
data[0] = constrain(data[0], 1, 120);
lcd.setCursor(2, 0);
lcd.print("Program ");
lcd.print(program_ptr);
lcd.print(" Pause ");
lcd.print(pause_ptr);
lcd.setCursor(1, 1);
lcd.print("Duration ");
lcd.print(data[0]);
lcd.print("min ");
lcd.setCursor(1, 2);
lcd.print("Temperature ");
}
data[1] = constrain(data[1], 20, 80);
data[2] = constrain(data[2], 10, 100);
lcd.print(data[1]);
lcd.print(char(223));
lcd.print("C ");
lcd.setCursor(1, 3);
lcd.print("Heater power ");
lcd.print(data[2]);
lcd.print("% ");
lcd.setCursor(0, int_ptr);
if (!edit_flag) lcd.print(">");
else lcd.print("!");
enc.tick();
if (enc.hold()) {
EEPROM.put(program_ptr * 100 + pause_ptr * 3, data);
lcd.clear();
break;
}
if (enc.right()) {
if (!edit_flag){
lcd.setCursor(0, int_ptr);
lcd.print(" ");
int_ptr++;
if (int_ptr == 4) {
EEPROM.put(program_ptr * 100 + pause_ptr * 3, data);
pause_ptr++;
if(pause_ptr > amt) pause_ptr = 0;
EEPROM.get(program_ptr * 100 + pause_ptr * 3, data);
int_ptr = 1;
lcd.clear();
}
} else {
data[int_ptr - 1]++;
}
}
if (enc.left()) {
if (!edit_flag){
lcd.setCursor(0, int_ptr);
lcd.print(" ");
int_ptr--;
if (int_ptr == 0) {
EEPROM.put(program_ptr * 100 + pause_ptr * 3, data);
pause_ptr--;
if(pause_ptr < 0) pause_ptr = amt;
EEPROM.get(program_ptr * 100 + pause_ptr * 3, data);
int_ptr = 3;
lcd.clear();
}
} else {
data[int_ptr-1]--;
}
}
}
}
}
}
void Program_menu() {
enc.tick();
for (uint8_t i = 1; i <= 9; i++) { //Отрисовываем меню
if (i < 4) {
lcd.setCursor(3, i);
lcd.print("Pr");
lcd.print(i);
} else if (i > 6) {
lcd.setCursor(17, i - 6);
lcd.print("Pr");
lcd.print(i);
} else {
lcd.setCursor(10, i - 3);
lcd.print("Pr");
lcd.print(i);
}
}
if (program_ptr < 4) { //отрисовываем указатель
lcd.setCursor(0, program_ptr);
} else if (program_ptr > 6) {
lcd.setCursor(14, program_ptr - 6);
} else {
lcd.setCursor(7, program_ptr - 3);
}
lcd.print("->");
if (enc.right()) { //Поворот вправо
if (program_ptr < 4) {
lcd.setCursor(0, program_ptr);
} else if (program_ptr > 6) {
lcd.setCursor(14, program_ptr - 6);
} else {
lcd.setCursor(7, program_ptr - 3);
}
lcd.print(" ");
program_ptr++;
if (program_ptr == 10) program_ptr = 1;
}
if (enc.left()) { // Поворот влево
if (program_ptr < 4) {
lcd.setCursor(0, program_ptr);
} else if (program_ptr > 6) {
lcd.setCursor(14, program_ptr - 6);
} else {
lcd.setCursor(7, program_ptr - 3);
}
lcd.print(" ");
program_ptr--;
if (program_ptr == 0) program_ptr = 9;
}
if (enc.hold()) { // Долгое нажатие
lcd.clear();
end_loop = true;
}
}
void Manual_mod() { //Ручной режим
lcd.clear();
int8_t ptr = 1; // Указатель
bool flag = false; // Флаг выхода на температурный режим
uint32_t Tmr_ms; //Таймер температурного режима
static int8_t temp_pow[] = {50, 100}; // температура, мощность
bool heater_on = false; //Нагреватель выключен
bool end_flag = false; // Флаг окончания варки
bool hop_flag = false; // Флаг для внесения хмеля
bool save = false; // флаг для сохранения параметров
bool edit_flag = false; // флаг редактирование
int8_t itr = 0; // итератор для массива
int8_t list = 0; // Лист режима
int8_t amt_hop = 1; // кол-во охмеление
int8_t k_ptr = 0; // кэф итерации кэф пида
uint8_t alarm_time = 60; // аларм оконч.варки
uint8_t data[9] {0}; // массив для хранения времени внес. хмеля. нужно заранее выделять память под массив в С++
for (;;) {
get_temp();
switch (list){
case -1:
lcd.setCursor(3, 0);
lcd.print("Debug");
lcd.setCursor(1,1);
lcd.print("P=");
lcd.print(data_pid[0], 1);
lcd.print(" ");
lcd.setCursor(1,2);
lcd.print("I=");
lcd.print(data_pid[1], 1);
lcd.print(" ");
lcd.setCursor(1,3);
lcd.print("D=");
lcd.print(data_pid[2], 1);
lcd.print(" ");
lcd.setCursor(11, 1);
if (digitalRead(pump)) lcd.print("Pump ON ");
else lcd.print("Pump OFF ");
lcd.setCursor(11, 2);
lcd.print("pid++ ");
lcd.print(k_ptr);
lcd.setCursor(11, 3);
lcd.print("TEN ");
lcd.print(activePeriod/10);
lcd.print("% ");
break;
case 0:
lcd.setCursor(1, 0);
if (!end_flag && !hop_flag) lcd.print("Manual mode ");
else if (end_flag) lcd.print("Finish OK! ");
else if (hop_flag){
lcd.print("Add Hop");
lcd.print(itr);
lcd.print(" OK!");
}
lcd.setCursor(1, 1);
lcd.print("Set temp. ");
if (temp_pow[0] < 100) lcd.print(" ");
lcd.print(temp_pow [0]);
lcd.print(char(223));
lcd.print("C");
lcd.setCursor(1, 2);
lcd.print("Heater power ");
if (temp_pow[1] < 100) lcd.print(" ");
lcd.print(temp_pow [1]);
lcd.print("%");
lcd.setCursor(1, 3);
if (heater_on){
lcd.print("Heater ON ");
} else {
lcd.print("Heater OFF ");
}
if (cur_temp < 100) lcd.print(" ");
if (cur_temp < 10) lcd.print(" ");
lcd.print(cur_temp, 1);
lcd.print(char(223));
lcd.print("C");
break;
case 1: // Лист настройки таймера
lcd.setCursor(3, 0);
lcd.print("Time settings");
lcd.setCursor(2, 1);
lcd.print("Boil.time");
lcd.setCursor(15, 1);
lcd.print(alarm_time);
lcd.print("m ");
lcd.setCursor(2, 2);
lcd.print("Amt of hop.");
lcd.setCursor(15, 2);
lcd.print(amt_hop);
break;
default:
lcd.setCursor(3, 0);
lcd.print("Hops ");
lcd.print(list-1);
lcd.setCursor(2, 1);
lcd.print("Time of add.");
lcd.setCursor(15, 1);
lcd.print(data[list-2]);
lcd.print("m ");
}
if (cur_temp > temp_pow[0] - 0.5 && !flag && heater_on){
flag = true;
Tmr_ms = millis();
}
if (flag ){
uint16_t Tmr_s = floor((millis() - Tmr_ms)/1000);
if(list == 0 ) {
lcd.setCursor(13, 0);
lcd.print((Tmr_s / 3600) % 24);
lcd.print(":");
lcd.print((Tmr_s / 600) % 6);
lcd.print((Tmr_s / 60) % 10);
lcd.print(":");
lcd.print((Tmr_s / 10) % 6);
lcd.print(Tmr_s % 10);
}
if(Tmr_s % 4 < 2 && Tmr_s < 10) analogWrite(buzzer_pin, 127); //Пищалка
if(Tmr_s % 4 > 1 && Tmr_s <= 10) digitalWrite(buzzer_pin, LOW);
if (alarm_time*60 - Tmr_s <= 0 && alarm_time != 0) end_flag = true; // таймер варки
if (data[itr]*60 == Tmr_s && data[itr] != 0 && itr < amt_hop ){ // таймер хмеля
hop_flag = true;
itr++;
}
if (end_flag || hop_flag) {
if (round(millis()/1000) % 2 == 0) analogWrite(buzzer_pin, 127);
else digitalWrite(buzzer_pin, LOW);
}
}
if (ptr < 4) lcd.setCursor(0, ptr);
else lcd.setCursor(10, ptr - 3);
if (edit_flag) lcd.print("!"); // отоброжение курсора
else lcd.print(">");
if (heater_on) heat(temp_pow[0], temp_pow[1]); // управ ТЭН и выход из режима варки_
else if (!heater_on && list == 0){
itr = 0;
flag = false;
digitalWrite(heater_pin, LOW);
heater_on = false;
digitalWrite(buzzer_pin, LOW);
lcd.setCursor(13, 0);
lcd.print(" "); //Стираем часы
}
enc.tick(); // редакт перменных
if (enc.left()) {
if (edit_flag) {
switch (list) {
case -1:
if (ptr < 4) {
if (k_ptr == 0) {
data_pid[ptr-1] -= 0.1;
save = true;
} else if (k_ptr == 1) {
data_pid[ptr-1] -= 5.0;
save = true;
} else {
data_pid[ptr-1] -= 10.0;
save = true;}
} else if (ptr == 4){
digitalWrite(pump, LOW);
} else k_ptr--;
break;
case 0: // на первом листе
if (ptr < 3) {
temp_pow[ptr-1]--;
} else {
heater_on = !heater_on;
}
if(ptr == 1 && flag){
flag = false;
digitalWrite(buzzer_pin, LOW);
lcd.setCursor(13, 0);
lcd.print(" "); //Стираем часы
}
break;
case 1: // редакт на листе таймер сетингс
if (ptr == 1) {
if (!alarm_time==0) alarm_time--;
} else{
amt_hop--;
}
break;
default: // редакт. на листах ввода хмеля
data[list-2]--;
}
} else {
if (ptr < 4) lcd.setCursor(0, ptr);
else lcd.setCursor(10, ptr - 3);
lcd.print(" ");
ptr--;
switch (list){
case -1:
if (ptr == 0) ptr = 1;
break;
case 0:
if(ptr == 0 ){
lcd.clear();
list--;
ptr = 5;
}
break;
case 1:
if ( ptr == 0 ) {
lcd.clear();
list--;
ptr = 3;
}
break;
default:
if (list == 2 && ptr < 1){ // переход между 2 и 1 страницой
lcd.clear();
list--;
ptr = 2;
} else {
list--;
ptr = 1;
}
}
}
}
if (enc.right()) {
if (edit_flag){
switch (list) {
case -1:
if (ptr < 4) {
if (k_ptr == 0) {
data_pid[ptr-1] += 0.1;
save = true;
} else if (k_ptr == 1) {
data_pid[ptr-1] += 5.0;
save = true;
} else {
data_pid[ptr-1] += 10.0;
save = true;}
} else if (ptr == 4){
digitalWrite(pump, HIGH);
} else k_ptr++;
break;
case 0:
if (ptr < 3) {
temp_pow[ptr-1]++;
} else {
heater_on = !heater_on;
}
if(ptr == 1 && flag){
flag = false;
digitalWrite(buzzer_pin, LOW);
lcd.setCursor(13, 0);
lcd.print(" "); //Стираем часы
}
break;
case 1:
if (ptr == 1) {
alarm_time++;
} else{
amt_hop++;
}
break;
default:
data[list-2]++;
}
} else {
if (ptr < 4) lcd.setCursor(0, ptr);
else lcd.setCursor(10, ptr - 3);
lcd.print(" ");
ptr++;
switch (list) {
case -1:
if (ptr == 6){
lcd.clear();
list++;
ptr = 1;
}
break;
case 0:
if(ptr == 4 ) {
lcd.clear();
list++;
ptr = 1;
}
break;
case 1:
if ( ptr == 3 ) {
lcd.clear();
list++;
ptr = 1;
}
break;
default:
if ( ptr > 1) {
list ++;
ptr = 1;
}
}
}
}
if (enc.click()){ // выход из режима после финиша по клику
if (!end_flag && !hop_flag) edit_flag = !edit_flag;
if (end_flag) {
itr = 0;
flag = false;
heater_on = false;
activePeriod = 0;
digitalWrite(heater_pin, LOW);
digitalWrite(buzzer_pin, LOW);
lcd.setCursor(13, 0);
lcd.print(" "); //Стираем часы
end_flag = false;
}
if (hop_flag) {
digitalWrite(buzzer_pin, LOW);
hop_flag = false;
}
}
alarm_time = constrain(alarm_time, 0, 240);
amt_hop = constrain(amt_hop, 0, 9);
list = constrain(list, -1, amt_hop+1);
k_ptr = constrain(k_ptr, 0, 2);
temp_pow[0] = constrain(temp_pow[0], 20, 100);
temp_pow[1] = constrain(temp_pow[1], 10, 100);
if (enc.hold() && !heater_on ) {
if (save) EEPROM.put(1, data_pid);
break;
}
}
lcd.clear();
digitalWrite(heater_pin, LOW);
digitalWrite(buzzer_pin, LOW);
digitalWrite(pump, LOW);
}
void heat(int8_t set_temp, int8_t power){
static uint32_t pwm_tmr = 0;
if (millis() - pwm_tmr >= 1000) {
pwm_tmr = millis();
if (set_temp < 100){ // пид регулятор
float kp = data_pid[0];
float ki = data_pid[1];
float kd = data_pid[2];
static float integral = 0, prevErr = 0;
float err = set_temp - cur_temp; // Пропорциональная составляющая
integral = constrain(integral + err, (-2 - fabs(err) * 10), (2 + 10 * fabs(err))); //Интегральная составляющая
float D = err - prevErr; //Дифференциальная состовляющая
prevErr = err;
activePeriod = round(constrain(err * kp + integral * ki + D * kd, 0, power)) * 10;
} else {
activePeriod = power * 10;
}
}
if (millis() - pwm_tmr < activePeriod) digitalWrite(heater_pin, HIGH);
else {
digitalWrite(heater_pin, LOW);
}
}
void biper() {
if (round(millis()/1000) % 2 == 0) analogWrite(buzzer_pin, 127);
else digitalWrite(buzzer_pin, LOW);
}
bool timer(uint32_t t) {
static uint32_t temp_timer = 0;
if (millis() - temp_timer >= t) {
temp_timer = millis();
return true;
} else {
return false;
}
}
/* */