#include <TM1637Display.h> // Библиотека для работы с индикатором
#include <EEPROM.h> // Библиотека для работы с энергонезависимой памятью
#include "GyverEncoder.h" // Библиотека для работы с энкодером
#include <OneWire.h> // Для работы с датчиком температуры
//#include "WiFi.h" // Библиотека работы с сетью вайфай
//#include <HTTPClient.h> // Библиотека для работы с http
#define CLK 2 // Пин clk первого индикатора
#define DIO 3 // Пин dio первого индикатора
#define CLK2 4 // Пин clk второго индикатора
#define DIO2 5 // Пин dio второго индикатора
#define ENCODER_A 6 // Пин энкодера A
#define ENCODER_B 7 // Пин энкодера B
#define ENCODER_BUTTON 8 // Пин энкодера кнопка
#define PUMP 9 // Пин помпы насоса
#define PULSE 10 // Пин счетчика импульсов
#define DIR_IN 11 // Пин направления вперед
#define DIR_OUT 12 // Пин направления назад
#define ON 13 // Пин кнопки разрешения налива
#define TEMP 14 // Пин датчика температуры
#define TAR_BUTTON 15 // Пин кнопки режима тарирования
// Для подключения сети wifi --------------------------------------------------------------------
//const char* ssid = "DIR-615"; // Логин для подключения к сети wifi TP-Link_B342
//const char* password = "0891395interne"; // Пароль для подключения к сети wifi 81894895
//bool wifi = false;// Состояние подключения wifi
// Для подключения к серверу --------------------------------------------------------------------
//String authUsername = "testEsp32USer"; // Логин для входа на сервер
//String authPassword = "testEsp32Pass"; // Пароль для входа на сервер
//const char* host = "http://";// Адрес сервера для отправки данных
const uint8_t SEG_o[] = {SEG_G, SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, SEG_G, 0}; // О - ошибка
const uint8_t SEG_h[] = {SEG_G, SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, SEG_G, 0}; // Н - наливание
const uint8_t SEG_p[] = {SEG_G, SEG_A | SEG_B | SEG_C | SEG_E | SEG_F, SEG_G, 0}; // П - пауза
const uint8_t SEG_v[] = {SEG_G, SEG_A | SEG_B | SEG_C | SEG_D | SEG_G | SEG_E | SEG_F, SEG_G, 0};// В - ввод
const uint8_t SEG_l[] = {SEG_G, SEG_D | SEG_E | SEG_F, SEG_G, SEG_G}; // L - тарирование
uint16_t ms_timer = 0; // Миллисекундный таймер функция
uint32_t count_value = 1; // Переменная заданного количества литров для наливания
uint32_t tar_count = 1; // Переменная для коэфициента тарирования
uint16_t koef = 25; // Коэфициент для тарирования - импульсов на литр
uint16_t temp_koef = 25; // Временный коэфициент для тарирования - импульсов на литр
uint16_t det_impulse = 1; // Расчитанное необходимое количество импульсов для наливания тары
uint8_t value0 = 0; // Значение 0 разраяда на индикаторе - черта
uint8_t value1 = 0; // Значение 1 разраяда на индикаторе - знак
uint8_t value2 = 0; // Значение 2 разраяда на индикаторе - черта
uint8_t value3 = 0; // Значение 3 разраяда на индикаторе
uint8_t value4 = 0; // Значение 4 разраяда на индикаторе
uint8_t value5 = 0; // Значение 5 разраяда на индикаторе
uint8_t value6 = 0; // Значение 6 разраяда на индикаторе
uint8_t value7 = 0; // Значение 7 разраяда на индикаторе
uint8_t value0_old = 0; // Старое значение 0 разраяда на индикаторе - черта
uint8_t value1_old = 0; // Старое значение 1 разраяда на индикаторе - знак
uint8_t value2_old = 0; // Старое значение 2 разраяда на индикаторе - черта
uint8_t value3_old = 0; // Старое значение 3 разраяда на индикаторе
uint8_t value4_old = 0; // Старое значение 4 разраяда на индикаторе
uint8_t value5_old = 0; // Старое значение 5 разраяда на индикаторе
uint8_t value6_old = 0; // Старое значение 6 разраяда на индикаторе
uint8_t value7_old = 0; // Старое значение 7 разраяда на индикаторе
unsigned int mode_encoder = 0;// Режим работы энкодера
// 0 - -****
// 1 - *-***
// 2 - **-**
// 3 - ***-*
// 4 - ****-
// 5 - не мигаем
unsigned int mode_work = 0; // Переменная режима работы
// 0 - ввод (В)
// 1 - налив (Н)
// 2 - таррирование(L)
// 3 - ошибка (Е)
// 4 - пауза (П)
unsigned int dir = 0; // Направление потока воды
// 0 - движения нет
// 1 - вперед
// 2 - назад
bool flag = false; // Флаг события
float temperature = 0; // Температура с датчика
uint16_t porog_temp = 60; // Пороговое значение температуры вградусах после которого будет уходить в режим ошибки
uint32_t porog_dir = 180000; // Пороговое значение времени 3 минуты - если нет потока при наливании уходит в режим ошибки
OneWire oneWire(TEMP); // Тип данных для работы с датчиком температуры
Encoder enc1(ENCODER_A, ENCODER_B, ENCODER_BUTTON); // Тип данных для работы с энкодером
void pulse_isr()// Функция по прерыванию счетчика -------------------------------------------------------------
{
flag = true;// Поднимаем флаг события
if(mode_work == 1)// Если в режиме наливания
{
if(dir == 1)// Если направление потока вперед
{
if(det_impulse > 0)
{
det_impulse--;// уменьшаем текущее расчитанное количество импульсов
count_value = det_impulse/koef;// Расчитываем количество литров для вывода на экран
flag = true;// Поднимаем флаг события
}
else
{
count_value = 0;
mode_work = 0;// Уходим в режим ввода
digitalWrite(PUMP, LOW);// Насос не работает
mode_encoder = 4;// Режим работы энкодера - разряд единицы
value3 = 0;
value4 = 0;
value5 = 0;
value6 = 0;
value7 = 0;
flag = true;// Поднимаем флаг события
}
}
else if(dir == 2)// Если поток назад
{
det_impulse++;// прибавляем текущее расчитанное количество импульсов
count_value = det_impulse/koef;// Расчитываем количество литров для вывода на экран
flag = true;// Поднимаем флаг события
}
else// Если потока нет
{
// Ничего не делаем
}
}
/*
if(mode_work == 1)// Если в режиме наливания
{
if(dir == 1)// Если направление потока вперед
{
if(count_value > 0)
{
if(temp_koef > 0)
{
temp_koef--;
}
else
{
count_value--;// уменьшаем текущее количество
temp_koef = koef;//
}
}
else
{
mode_work = 0;// Уходим в режим ввода
digitalWrite(PUMP, LOW);// Насос не работает
mode_encoder = 4;// Режим работы энкодера - разряд единицы
value3 = 0;
value4 = 0;
value5 = 0;
value6 = 0;
value7 = 0;
flag = true;// Поднимаем флаг события
}
}
else if(dir == 2)// Если поток назад
{
if(temp_koef > 0)
{
temp_koef--;
}
else
{
count_value++;// увеличиваем текущее количество
temp_koef = koef;//
}
}
else// Если потока нет
{
// Ничего не делаем
}
}
*/
if(mode_work == 2)// Если в режиме тарирования
{
if(dir == 2)// Если направление потока назад
{
if(tar_count > 1)
{
tar_count--;// уменьшаем текущее количество тары
}
}
else if(dir == 1)// Если поток вперед
{
tar_count++;// Увеличиваем текущее количество литров тары
}
else// Если потока нет
{
// Ничего не делаем
}
}
// Преобразуем ****************************
if(count_value > 0)
{
value3 = count_value/10000;
value4 = (count_value%10000)/1000;
value5 = (count_value%1000)/100;
value6 = (count_value%100)/10;
value7 = count_value%10;
}
}
TM1637Display display_1 = TM1637Display(CLK, DIO); // Определяем тип данных для работы с первым индикатором
TM1637Display display_2 = TM1637Display(CLK2, DIO2);// Определяем тип данных для работы с вторым индикатором
// *******************************************************************************************************************
// ************* Функция инициализации *******************************************************************************
// ******************************************************************************************************************
void setup() {
Serial.begin(9600); // Серийный порт для отладки
// Инициализация пинов ---------------------------------------------------------------------------------------------
pinMode(PUMP, OUTPUT); // Выход - реле помпа
pinMode(DIR_IN, INPUT); // Вход - пин направления потока воды вперед
pinMode(DIR_OUT, INPUT); // Вход - пин направления потока воды назад
pinMode(ON, INPUT_PULLUP); // Вход - пин кнопки разрешения налива
pinMode(ENCODER_BUTTON, INPUT_PULLUP);// Вход - пин кнопки энкодера
pinMode(ENCODER_A, INPUT_PULLUP); // Вход - пин сигнала энкодера а
pinMode(ENCODER_B, INPUT_PULLUP); // Вход - пин сигнала энкодера б
pinMode(PULSE, INPUT_PULLUP); // Вход - пин счетчика
pinMode(TAR_BUTTON, INPUT_PULLUP); // Вход - пин кнопки режима тарирования
// EEPROM.begin(300); // Память в резерв - размер 100
//EEPROM.commit(); // Готовим
int count_value_f = 0;
int koef_f = 0;
EEPROM.get(4, count_value_f); // Читаем из памяти адрес 4 количество для наливания
//EEPROM.commit(); // Готовим
EEPROM.get(8, koef_f); // Читаем из памяти адрес 6 коэфициент
//EEPROM.commit(); // Готовим
if((count_value_f != 0) && (count_value_f < 99999))
{
count_value = count_value_f;
}
if((koef_f != 0) && (koef_f < 99999))
{
koef = koef_f;
}
if(count_value > 0)
{
value3 = count_value/10000;
value4 = (count_value%10000)/1000;
value5 = (count_value%1000)/100;
value6 = (count_value%100)/10;
value7 = count_value%10;
}
display_1.clear(); // Чистим первый индикатор
display_1.setBrightness(7); // Определяем яркость первого индикатора
display_2.clear(); // Чистим второй индикатор
display_2.setBrightness(7); // Определяем яркость второй индикатора
display_1.clear();
display_1.setSegments(SEG_h,1,1);
display_1.showNumberDec(value3, false, 1, 3);// Выводим значение на первый индикатор
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на первый индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на первый индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на первый индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на первый индикатор
attachInterrupt(PULSE, pulse_isr, CHANGE); // Функция по прерыванию счетчика
attachInterrupt(ENCODER_A, isr, CHANGE); // Функция по прерыванию энкодера
/*
// Сеть WIFI ----------------------------------------------------------------------------
WiFi.begin(ssid, password);// Запуск подключения вайфай, логин и пароль сети
int count = 0;// Счетчик попыток
while(WiFi.status() != WL_CONNECTED)// Ожидание подключения к сети
{
count++;// Счетчик попыток прибавляем
delay(500);// Паузп между попытками подключения
Serial.println("Connecting to WiFi..");// Вывод отладочной информации в серийный порт
if(count == 10)// Счетчик попыток 10 раз
{
Serial.println("Connecting NO !!!!!!!!!!!");// Вывод отладочной информации в серийный порт
break;
}
}
*/
}
void isr()
{
enc1.tick(); // отработка в прерывании
}
// *******************************************************************************************************************
// ************* Функция основного цикла *****************************************************************************
// ******************************************************************************************************************
void loop()
{
// Раз в секунду проверяем температуру -----------------------------------------------------------------------------
if(ms_timer == 900)
{
temperature = readTemperature();
if (temperature != 0) // Проверяем, успешно ли удалось считать температуру
{
Serial.print("Температура: ");
Serial.print(temperature);
Serial.println("°C");
}
else
{
Serial.println("Ошибка при считывании температуры!");
temperature = 0;
}
if(temperature > porog_temp)// Если температура выше порога
{
mode_work = 3;// Уходим в режим ошибки
flag = true;// Поднимаем флаг события
}
}
// Контроль наличия потока воды -------------------------------------------------------------------------------
if((mode_work == 1) && (dir == 0))// Если наливаем а потока нет
{
if(porog_dir > 0)
{
porog_dir--;
}
else
{
porog_dir = 180000;// Возвращаем значение
mode_work = 3;// Уходим в режим ошибки
flag = true;// Поднимаем флаг события
}
}
else
{
porog_dir = 180000;// Возвращаем значение
}
/*
// ****************************************************************************************************
// ******** Работа с wifi сетью **********************************************************************
// ****************************************************************************************************
if(WiFi.status() == WL_CONNECTED)// Проверка подключения к сети wifi
{
wifi = true;// Флаг подключения
}
else
{
wifi = false;// Флаг подключения
WiFi.begin(ssid, password);// Повторный запуск подключения вайфай, логин и пароль сети
int count = 0;// Счетчик попыток
while(WiFi.status() != WL_CONNECTED)// Ожидание подключения к сети
{
count++;// Счетчик попыток прибавляем
Serial.println("Connecting to WiFi..");// Вывод отладочной информации в серийный порт
if(count == 5)// Счетчик попыток 5 раз
{
Serial.println("Connecting NO !!!!!!!!!!!");// Вывод отладочной информации в серийный порт
break;
}
delay(1000);// Пауза 1 секунда между попытками подключения
}
}
*/
/*
// ****************************************************************************************************
// ******** Отправка пакета **************************************************************************
// ****************************************************************************************************
if(wifi)// Если сеть подключена
{
HTTPClient http; // Объявить объект класса HttpClient
http.begin(host); // Адрес сервера для отправки запроса
http.addHeader("Content-Type", "text/plain");// Заголовок для текстовых данных
String auth = "test header";// Заголовок
http.addHeader("Authorization", "Basic " + auth);// Заголовок аутентификации
// Собираем данные в одно длинное строковое сообщение ---------------
String mess;// Переменная для строкового сообщения
mess = String(count_value);// Количество наливаемого
int httpCode = http.POST(mess);// Отправляем строку данных и получаем в ответ год
String payload = http.getString();// Получаем строку возрата
// Проверяем дошло ли сообщение и с какой командой ------------------------------------
switch{payload}
{
case 0;
{
// Действия при команде 0
}
break;
case 1;
{
// Действия при команде 1
}
break;
case 2;
{
// Действия при команде 2
}
break;
case 3;
{
// Действия при команде 3
}
break;
}
http.end(); // Закрывам соединение
}// Конец проверки подключения сети
// ############ Конец отправки пакета ################################################################
*/
if(value3 > 9){value3 = 0;}
if(value4 > 9){value4 = 0;}
if(value5 > 9){value5 = 0;}
if(value6 > 9){value6 = 0;}
if(value7 > 9){value7 = 0;}
enc1.tick(); // отработка в прерывании
// Смотрим направление потока воды **********************************************************************************************************
if((digitalRead(DIR_IN) == HIGH) && (digitalRead(DIR_OUT) == LOW))// Вода вперед
{
dir = 1;// Направление потока вперед
}
else if((digitalRead(DIR_IN) == LOW) && (digitalRead(DIR_OUT) == HIGH))// Вода назад
{
dir = 2;// Направление потока назад
}
else if((digitalRead(DIR_IN) == LOW) && (digitalRead(DIR_OUT) == LOW))// Вода стоп
{
dir = 0;// Потока нет
}
else// Другие положения ошибка
{
dir = 0;// Потока нет - ошибка
}
// Отрабатываем работу таймера *********************************************************************************************
if(ms_timer < 1000)
{
ms_timer++; // Прибавляем
delayMicroseconds(500); // Дискретность таймера
}
else
{
ms_timer = 0;// Сброс от переполнения
}
if(mode_work == 0)// если в режиме ввода - мигаем ***************************************************************
{
switch(mode_encoder)
{
case 0:
{
if (enc1.isRight()) value3++;
if (enc1.isLeft()) value3--;
if((value3 > 9) || (value3 < 0)){value3 = 0;}
if(ms_timer == 0)
{
display_1.clear();
display_1.setSegments(SEG_v,3,0);
display_1.showNumberDec(value3, false, 0, 3);// Выводим значение на первый индикатор
}
if(ms_timer == 500)
{
display_1.clear();
display_1.setSegments(SEG_v,3,0);
display_1.showNumberDec(value3, false, 1, 3);// Выводим значение на первый индикатор
}
}
break;
case 1:
{
if (enc1.isRight()) value4++;
if (enc1.isLeft()) value4--;
if((value4 > 9) || (value4 < 0)){value4 = 0;}
if(ms_timer == 0)
{
display_2.clear();
display_2.showNumberDec(value4, false, 0, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
if(ms_timer == 500)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
}
break;
case 2:
{
if (enc1.isRight()) value5++;
if (enc1.isLeft()) value5--;
if((value5 > 9) || (value5 < 0)){value5 = 0;}
if(ms_timer == 0)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 0, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
if(ms_timer == 500)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
}
break;
case 3:
{
if (enc1.isRight()) value6++;
if (enc1.isLeft()) value6--;
if((value6 > 9) || (value6 < 0)){value6 = 0;}
if(ms_timer == 0)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 0, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
if(ms_timer == 500)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
}
break;
case 4:
{
if (enc1.isRight()) value7++;
if (enc1.isLeft()) value7--;
if((value7 > 9) || (value7 < 0)){value7 = 0;}
if(ms_timer == 0)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 0, 3);// Выводим значение на второй индикатор
}
if(ms_timer == 500)
{
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
}
}
break;
}
// Обновляем значение основного числа
count_value = value7 + (value6*10) + (value5*100) + (value4*1000) + (value3*10000);
}// end если в режиме ввода - мигаем
if(enc1.isClick())// Отрабатываем смену разрядов *****************************************************************
{
flag = true;// Поднимаем флаг события
if(mode_encoder < 4)
{
mode_encoder++;
}
else
{
mode_encoder = 0;
}
}
// Выводим значения на индикаторы при каких либо изменениях *********************************************************************************************
if((flag == true) || (value0 != value0_old) || (value1 != value1_old) || (value2 != value2_old) || (value3 != value3_old) || (value4 != value4_old) || (value5 != value5_old) || (value6 != value6_old) || (value7 != value7_old))
{
if(mode_work != 3)// Не находится в режиме ошибки
{
// Вывод на индикаторы поразрядно
display_1.clear();
if(mode_work == 0)// Если в режиме ввода
{
display_1.setSegments(SEG_v,3,0);
}
else if(mode_work == 1)// Если в режиме наливания
{
display_1.setSegments(SEG_h,3,0);
}
else if(mode_work == 2)// Если в режиме тарирования
{
display_1.setSegments(SEG_l,3,0);
}
else if(mode_work == 4)// Если в режиме паузы
{
display_1.setSegments(SEG_p,3,0);
}
else
{
}
display_1.showNumberDec(value3, false, 1, 3);// Выводим значение на первый индикатор
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
// Обновляем старые значения
value0_old = value0;
value1_old = value1;
value2_old = value2;
value3_old = value3;
value4_old = value4;
value5_old = value5;
value6_old = value6;
value7_old = value7;
flag = false;// Сбрасываем флаг события
}
}// end вывод значения
// Смотрим кнопку налива *******************************************************************************************************************
if(digitalRead(ON) == LOW)// Если нажата
{
flag = true;// Поднимаем флаг события
// Обновляем значение основного числа
count_value = value7 + (value6*10) + (value5*100) + (value4*1000) + (value3*10000);
int temp = count_value;
EEPROM.put(4, temp);// Записываем в память в адрес 4 значение общего количества
//EEPROM.commit();
temp = koef;
EEPROM.put(8, temp); // Записываем в память в адрес 6 значение коефициента
//EEPROM.commit();
unsigned int time_button = 1; // Переменная время нажатия кнопки разрешения налива
for(int i = 0; i < 100000; i++)// До 100 секунд
{
if(digitalRead(ON) == HIGH)// Если кнопку отпустили то
{
break;// Выход из цикла
}
time_button++;
if(time_button > 5000)// Очень длинное нажатие - сброс всего !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{
count_value = 0;
tar_count = 1;
koef = 25;
value3 = count_value/10000;
value4 = (count_value%10000)/1000;
value5 = (count_value%1000)/100;
value6 = (count_value%100)/10;
value7 = count_value%10;
int temp = count_value;
EEPROM.put(4, temp);// Записываем в память в адрес 4 значение общего количества
//EEPROM.commit();
temp = koef;
EEPROM.put(8, temp); // Записываем в память в адрес 6 значение коефициента
//EEPROM.commit();
display_1.clear();
display_1.setSegments(SEG_v,3,0);
display_1.showNumberDec(value3, false, 1, 3);// Выводим значение на первый индикатор
display_2.clear();
display_2.showNumberDec(value4, false, 1, 0);// Выводим значение на второй индикатор
display_2.showNumberDec(value5, false, 1, 1);// Выводим значение на второй индикатор
display_2.showNumberDec(value6, false, 1, 2);// Выводим значение на второй индикатор
display_2.showNumberDec(value7, false, 1, 3);// Выводим значение на второй индикатор
break;// Выход из цикла
}
delay(1); // Пауза
}
// Отрабатываем в зависимости от длинны нажатия кнопки разрешения налива
if(time_button < 1000)// Короткое нажатие -------------
{
if((mode_work == 0) || (mode_work == 4))// Если в режиме ввода или паузы
{
// Обновляем значение основного числа
count_value = value7 + (value6*10) + (value5*100) + (value4*1000) + (value3*10000);
det_impulse = count_value * koef;// Необходимое количество импульсов = текущее заданное количество * расчитанный коэффициент
if(count_value != 0)// Если на экране что то есть
{
mode_work = 1;// В режим наливания
digitalWrite(PUMP, HIGH);// Насос работает
}
}
else
{
mode_work = 4;// В режим паузы
digitalWrite(PUMP, LOW);// Насос не работает
if(count_value > 0)
{
value3 = count_value/10000;
value4 = (count_value%10000)/1000;
value5 = (count_value%1000)/100;
value6 = (count_value%100)/10;
value7 = count_value%10;
}
}
}
else if((time_button > 1000) && (time_button < 5000))// Длинное нажатие в режим ввода -----------------------
{
mode_work = 0;// В режим ввода
digitalWrite(PUMP, LOW);// Насос не работает
}
else
{
}
delay(500);// Пауза от дребезга кнопки разрешения наливания
}
// Смотрим кнопку перехода в режим тарирования *******************************************************************************************************************
if(digitalRead(TAR_BUTTON) == LOW)// Если нажата
{
flag = true;// Поднимаем флаг события
if(mode_work != 2)// Если не в режиме тарирования то заходим в режим
{
mode_work = 2;// Уходим в режим тарирования
digitalWrite(PUMP, HIGH);// Насос работает
tar_count = 1;// Начинаем отсчет литров тары
}
else if(mode_work == 2)// Если в режиме тарирования то выходим из режима
{
// Расчитываем коэфициент
koef = tar_count/count_value;// Расчитываем импульсы на литр
if(koef < 1)
{
koef = 1;
}
tar_count = 1;// Сбрасываем счетчик тарирования
temp_koef = koef;// Временое значение заполняем
mode_work = 0;// Уходим в режим ввода
digitalWrite(PUMP, LOW);// Насос не работает
int temp = count_value;
EEPROM.put(4, temp);// Записываем в память в адрес 4 значение общего количества
//EEPROM.commit();
temp = koef;
EEPROM.put(8, temp); // Записываем в память в адрес 6 значение коефициента
//EEPROM.commit();
}
else
{
}
delay(500);// От дребезга
}
// Отрабатываем работу помпы ***************************************************************************************************************
if((mode_work == 1) || (mode_work == 2))// Если в режиме наливания или тарирования
{
if(count_value > 0)// Если есть что наливать
{
digitalWrite(PUMP, HIGH);// Насос работает
}
else// Если в других режимах
{
digitalWrite(PUMP, LOW);// Насос не работает
}
}
// Если в режиме ошибки ***************************************************************************************************************
if((mode_work == 3) && (ms_timer == 300))// Если в режиме ошибки И раз в секунду
{
if(temperature > 0)
{
display_1.clear();
display_1.setSegments(SEG_o,3,0);
display_1.showNumberDec(0, false, 1, 3);//
display_2.clear();
display_2.showNumberDec(0, false, 1, 0);//
display_2.showNumberDec(0, false, 1, 1);//
display_2.showNumberDec(int(temperature)/10, false, 1, 2);// Выводим значение температуры десятые
display_2.showNumberDec(int(temperature)%10, false, 1, 3);// Выводим значение температуры единицы
digitalWrite(PUMP, LOW);// Насос не работает
}
}
}
float readTemperature() // Функция для считывания температуры с датчика DS18B20 ********************************************************************
{
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
// Поиск подключенных датчиков DS18B20 на шине OneWire
if (!oneWire.search(addr)) {
//Serial.println("Датчики DS18B20 не найдены.");
// Сбрасываем поиск и возвращаем "NaN" (не число) в случае ошибки
oneWire.reset_search();
return NAN;
}
// Проверка целостности адреса датчика с помощью CRC
if (OneWire::crc8(addr, 7) != addr[7]) {
//Serial.println("CRC не совпадает!");
return NAN;
}
// Определение типа датчика на основе первого байта адреса
switch (addr[0]) {
case 0x10:
type_s = 1; // DS18S20 или DS1822
break;
case 0x28:
case 0x22:
type_s = 0; // DS18B20
break;
default:
Serial.println("Неизвестный тип датчика.");
return NAN;
}
// Сбрасываем шину и выбираем адрес конкретного датчика
oneWire.reset();
oneWire.select(addr);
// Запускаем измерение температуры на датчике
oneWire.write(0x44); // 0x44 - команда начать измерение
// Ожидание завершения измерения (время зависит от разрешения)
delay(500);
// Сбрасываем шину и выбираем адрес датчика для чтения данных
present = oneWire.reset();
oneWire.select(addr);
oneWire.write(0xBE); // 0xBE - команда чтения данных
// Считываем 9 байт данных температуры и CRC
for (i = 0; i < 9; i++) {
data[i] = oneWire.read();
}
// Преобразование считанных данных в температуру
int16_t raw = (data[1] << 8) | data[0];
float celsius = 0.0;
// Применяем разрешение и коррекцию для разных типов датчиков
if (type_s == 1)
{
//raw = raw << 3; // Увеличиваем разрешение до 12 бит
//if (data[7] == 0x10) {
// // Температура с высоким разрешением (DS18S20)
//raw = (raw & 0xFFF0) + 12 - data[6];
//}
} else {
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw & ~7; // Разрешение 9 бит, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // Разрешение 10 бит, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // Разрешение 11 бит, 375 ms
}
celsius = (float)raw / 16.0; // Преобразуем вещественное значение температуры и возвращаем
return celsius;
}