Т.е. надо образно говоря подать 6,6В ?
Я не знаю, это не моя схема. Моя выше.
А что будет с Вашей схемой если зависание произойдёт во время “Четкий импульс 10 мс”?
Со схемой ничего не будет ))
А вот для надёжности, наверное, нужно ещё одну схему городить - обратную первой по логике работы входного сигнала ))
Зависнет безвозвратно, только вероятность попадоса в тот момент когда ничего не происходит (срабатывания клапанов, моторов и т.д.) в течении 0,01 сек. невероятно мала.
Это как будет выглядеть?
Зависание продлится до скончания веков)) Я уже устал это повторять.
До меня дошло почему у ТС все работает( МК перезапускаетс)! Да потому что во время сброса собаки МК ничего не делает 10 мс! Нет никаких коммутаций, и соответственно нет помех и причин для зависания. Но стоит прилететь помехе извне в эти 10 мс, как МК зависнет и перезапуска не произойдет.
PS. ТС и сам это написал выше.
Ну так может прислушаетесь к советам и поставите конденсатор, и подавать меандр, что бы отслеживать не уровень, а изменение, не?
Да я рад бы был, но зависалово происходило один раз в несколько суток при непрерывной работе. Как его поймать?
Подскажите!!! Мне тоже городить огород не очень хочется. Но ведь не зря пишут что МК иногда зависает так, что и RESET не срабатывает.
Я готов на многое ради ЖЕЛЕЗОБЕТОННОЙ работы контроллеров, которые я мучу. Иногда конечно они выполняют короткие циклические программы, а иногда месяц с отслеживанием параметров и поддержания режимов.
А в какой теме обсуждался код, в котором неверно работает wdt?
Дай ссылку (желательно сразу на пост с последней версией кода).
Выложить код для инкубатора, с которым у меня проблемы? Это сделать?
Или то что касается непосредственно wdt ?
Лучше всё, а то выкинешь ещё что-то не заметив.
И не в этой теме, а в той где это обсуждали.
Так вроде тут и обсуждали.
Пост #12. Только там одна строчка.
Ну давай тогда сюда ))
Только правильно код вставить не забудь.
#include "avr/wdt.h"
#include <EEPROM.h> // Библиотека резервирования в ПЗУ
#include <OneWire.h> // Подключаем библиотеку для взаимодействия с устройствами, работающими на шине и по протоколу 1-Wire
#include <microDS18B20.h>
#include <LiquidCrystal_I2C.h> // Подключаем библиотеку дисплея
#include <I2CKeyPad.h> // Подключаем библиотеку матричной клавиатуры
#include <GyverHX711.h> // Подключаем библиотеку измерения давления
#include <Adafruit_AHTX0.h> // Подключаем библиотеку Adafruit_AHTX0
Adafruit_AHTX0 aht; // Создаём объект для работы с библиотекой датчика влажности и температуры
#include "Adafruit_SHT4x.h" // Библиотека датчика влажности SHT-41
Adafruit_SHT4x sht4 = Adafruit_SHT4x(); // Подключаем Библиотеку датчика влажности SHT-41
const uint8_t PCF_ADDR = 0x20; // Константа: адрес расширителя на шине I2C
char keymap[] = "A321B654C987D#0*"; // Массив символов: карта кнопок (16 кнопок)
I2CKeyPad keyPad(PCF_ADDR); // Создание объекта keyPad для работы с клавиатурой
byte vr = 0, tr = 5, vl = 10, prv = 15; // Номера ячеек памяти для времени, температуры, влажности
float t_ust = 37.5; // Устанавливаем начальную температуру в инкубаторе
float t_ust_sk = 37.8; // Устанавливаем предельную температуру на скорлупе
byte vlag_ust = 70; // Устанавливаем влажность в инкубаторе
unsigned long time_INC, time_INC1; // Создаем переменную для таймеа инкубации и резерва
float time_del;
float vlaga_SHT, temp_SHT;
long sutki_Inc, hour_Inc, hour_Inc1, min_Inc, min_Inc_D, min_Inc1; // и контрольные переменные в сутках, часах и в минутах
unsigned long disp; // Переменная для переодической очистки экрана
byte sutki = 35; // Переменная устанавливающая длительность инкубации в сутках
float k_act = 120; // Время поворота лотков 120 или 240 минут
char cod = 'A', regim = 'A';
boolean R0_temp = 1, R1_temp = 1, R_vlag = 0, R_prov = 0; // Переменные для управления РЕЛЕ ТЭНОВ, Влажности и проветривания 0 или 1
boolean R_actuator; // Переменная для актуатора
// Определяем пины под датчики температуры
// MicroDS18B20<10> sensor1; // датчик 1
MicroDS18B20<2> sensor2; // датчик 2
MicroDS18B20<3> sensor3; // датчик 3
LiquidCrystal_I2C lcd(0x27, 20, 4); // Определяем ID и тип дисплея
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.setClock(10000); // Понижение скорости шины I2C до 50 кГц
Wire.setWireTimeout(10000, true); // Сброс шины I2C при ошибке длительностью 10 миллисекунд
if (!keyPad.begin()) {
Serial.println("PCF8574 не найден!"); // Вывод ошибки в монитор порта
while (1)
; // Остановка программы: бесконечный пустой цикл
}
// ********* Настройка сенсора влажности и температуры ******************
Serial.println("Adafruit SHT4x test");
if (!sht4.begin()) {
Serial.println("Couldn't find SHT4x sensor");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
// Настройка точности (High, Medium, Low)
sht4.setPrecision(SHT4X_HIGH_PRECISION);
// Настройка нагревателя (если не нужен, можно пропустить)
sht4.setHeater(SHT4X_NO_HEATER);
// *********************************************************************
lcd.init(); // Инициализация экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очищаем экран
/* ******************* Сенсор АНТ-10 *******************
if (!aht.begin()) // Инициализация датчика влажности и температуры
{
Serial.println("Could not find AHT? Check wiring"); // Отправка сообщения
while (1) delay(10); // Зацикливаем программу
}
****************************************************************
*/
// Определяем пины под управление реле
pinMode(5, OUTPUT); // ТЭН №1 220В
pinMode(6, OUTPUT); // ТЭН №2 220В
pinMode(7, OUTPUT); // Вентилятор влажности 12В
pinMode(8, OUTPUT); // Вентилятор проветривания 12В
pinMode(4, OUTPUT); // Актуатор 12В
EEPROM.get(vr, time_INC1); // Читаем из ПЗУ ячейку vr переменную time_INC1 (текущее время инкубации)
EEPROM.get(tr, t_ust); // Читаем из ПЗУ ячейку tr переменную t_ust (установочную температуру)
EEPROM.get(vl, vlag_ust); // Читаем из ПЗУ ячейку vl переменную vlag_ust (установочную влажность)
EEPROM.get(prv, k_act); // Читаем из ПЗУ ячейку prv переменную vlag_ust (переодичность переворота лотков)
if (t_ust == 0) { t_ust = 37.5; }
if (vlag_ust == 0) { vlag_ust = 70; }
}
void loop() {
wdt_reset();
sensors_event_t humidity, temp;
// Чтение данных
static uint32_t tmr41;
if (millis() - tmr41 >= 2500) {
tmr41 = millis();
sht4.getEvent(&humidity, &temp);
vlaga_SHT = humidity.relative_humidity;
temp_SHT = temp.temperature;
}
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("% rH");
if (sutki != 0) { // ОСНОВНОЙ ЦИКЛ ЗАВЕРШЕНИЯ ИНКУБАЦИИ
// min_Inc1 = min_Inc;
// конструкция программного таймера на 2500 мс для опроса датчика каждые 2,5 секунды
static uint32_t tmr;
if (millis() - tmr >= 2500) {
tmr = millis();
// читаем прошлое значение
if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
else Serial.println("error2");
if (sensor3.readTemp()) Serial.println(sensor3.getTemp());
else Serial.println("error3");
Serial.println();
// запрашиваем новое измерение датчиков температуры
// sensor1.requestTemp();
sensor2.requestTemp();
sensor3.requestTemp();
}
// Раздел работы с датчиком влажности и температуры
// sensors_event_t humidity, temp; // Создаём объект для работы с библиотекой
// aht.getEvent(&humidity, &temp); // Считваем показания
// Раздел для определения дней, часов и минут
sutki_Inc = time_INC / 1000 / 60 / 60 / 24;
hour_Inc = time_INC / 1000 / 60 / 60 - sutki_Inc * 24;
min_Inc = time_INC / 1000 / 60;
// Раздел работы с клавиатурой
// ОПЕРАТОР IF: проверяет условие (нажата ли любая кнопка)
if (keyPad.isPressed()) {
// Вызов метода .getKey(), который возвращает индекс нажатой кнопки (число от 0 до 15)
uint8_t index = keyPad.getKey();
// Проверка, что индекс находится в рамках нашего массива (0-15)
if (index < 16) {
Serial.print("Нажато: "); // Вывод текста без переноса строки
Serial.println(keymap[index]); // Вывод символа из массива по индексу с переносом
cod = keymap[index];
}
// ЦИКЛ WHILE: "замораживает" программу, пока кнопка удерживается
// Это нужно, чтобы одно нажатие не превратилось в бесконечный поток символов
while (keyPad.isPressed()) {
delay(10); // Короткая пауза 10 мс для стабильности
}
}
// Присваеваем переменной "regim"(режим) значение нажатой клавиши, если она Влага
// равна A, B, C, или D
if (cod == 'A') {
regim = cod;
lcd.clear();
cod = '2';
}
if (cod == 'B') {
if (cod != regim) { lcd.clear(); }
regim = cod;
}
if (cod == 'C') {
if (cod != regim) { lcd.clear(); }
regim = cod;
}
if (cod == 'D') {
regim = cod;
lcd.clear();
cod = '2';
}
// РЕЖИМ А
if (regim == 'A') {
// Очищаем экран
// УСТАНОВКА ВРЕМЕНИ ИНКУБАЦИИ
if (cod == '1') {
sutki = sutki - 1;
cod = '2';
}
if (cod == '3') {
sutki = sutki + 1;
cod = '2';
}
// }
// Индикация времени c начала инкубации
lcd.setCursor(0, 1); // Определяем положение курсора (позиция,строка)
lcd.print("INCUB ");
lcd.setCursor(7, 1);
min_Inc_D = time_INC / 1000 / 60 - sutki_Inc * 24 * 60 - hour_Inc * 60;
lcd.print(sutki_Inc);
lcd.print("d "); // Во второй строке выводим количество суток который идет инкубация
lcd.print(hour_Inc);
lcd.print("h "); // следом выводим часы инкубации
lcd.print(min_Inc_D);
lcd.print("m"); // следом выводим минуты инкубации
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print("Time INCUB "); // Выводим на дисплей символьное значение
lcd.setCursor(11, 0); // Определяем положение курсора (позиция,строка)
lcd.print(sutki); // Выводим заданное время инкубации в сутках
lcd.print(" d");
lcd.setCursor(0, 2); // Определяем положение курсора (позиция,строка)
lcd.print("Temp ");
lcd.print(temp_SHT, 1);
lcd.print("'C ");
lcd.print(t_ust, 1);
lcd.print("'C"); // Выводим на дисплей температуру
lcd.setCursor(0, 3); // Определяем положение курсора (позиция,строка)
lcd.print("Vlagnost ");
lcd.print(vlaga_SHT, 0);
lcd.print("% ");
lcd.print(vlag_ust);
lcd.print("%"); // Выводим на дисплей влажность
Serial.print("t_ust ");
Serial.println(t_ust);
Serial.print("vlag_ust ");
Serial.println(vlag_ust);
delay(50); // Пауза
// УСТАНОВКА ПРЕДЕЛЬНОЙ ТЕМПЕРАТУРЫ В ИНКУБАТОРЕ
//if (customKey) {
if (cod == '4') {
t_ust = t_ust - 0.1;
cod = '5';
}
if (cod == '6') {
t_ust = t_ust + 0.1;
cod = '5';
}
// УСТАНОВКА ПРЕДЕЛЬНОЙ ВЛАЖНОСТИ В ИНКУБАТОРЕ
//if (customKey) {
if (cod == '7') {
vlag_ust = vlag_ust - 1;
cod = '8';
}
if (cod == '9') {
vlag_ust = vlag_ust + 1;
cod = '8';
}
}
// РЕЖИМ B
// (Температурные показатели датчиков)
if (regim == 'B') {
// lcd.clear(); // Очищаем экран
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print("TEMP-1 ");
lcd.print(temp_SHT);
lcd.print(" 'C");
lcd.setCursor(0, 1); // Определяем положение курсора (позиция,строка)
lcd.print("TEMP-2 ");
lcd.print(sensor2.getTemp() + 0.3);
lcd.print(" 'C");
lcd.setCursor(0, 2); // Определяем положение курсора (позиция,строка)
lcd.print("TEMP-3 ");
lcd.print(sensor3.getTemp() + 0.25);
lcd.print(" 'C");
lcd.setCursor(0, 3); // Определяем положение курсора (позиция,строка)
lcd.print("VLAGA ");
lcd.print(vlaga_SHT, 0);
lcd.print(" %");
}
// Режим С это режимы работы устройств
if (regim == 'C') {
if (cod == '1') {
t_ust_sk = t_ust_sk - 0.1;
cod = '2';
}
if (cod == '3') {
t_ust_sk = t_ust_sk + 0.1;
cod = '2';
}
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print(" SCORLUPA"); // Выводим на дисплей символьное значение
lcd.setCursor(11, 0);
lcd.print(t_ust_sk);
lcd.print("'C");
if (cod == '7') {
k_act = k_act - 60;
cod = '8';
}
if (cod == '9') {
k_act = k_act + 60;
cod = '8';
}
lcd.setCursor(0, 2); // Определяем положение курсора (позиция,строка)
lcd.print("ACTUATOR "); // Выводим на дисплей символьное значение
if (R_actuator == 0) {
lcd.print("-45'");
} else {
lcd.print("+45'");
}
lcd.setCursor(0, 3); // Определяем положение курсора (позиция,строка)
lcd.print("POVOROT ");
lcd.print(k_act);
lcd.print(" min "); // Выводим на дисплей символьное значение
}
// РЕЖИМ D Управление и индикация окончанием инкубации
if (regim == 'D') {
if (cod == '0') {
sutki = 0; // Условие окончания инкубации
EEPROM.put(vr, 0); // Вначале номер ячейки, затем значение вписанное в эту ячейку
time_INC = 0;
EEPROM.put(tr, 37.5); // Читаем из ПЗУ ячейку 2 переменную t_ust (установочную температуру)
EEPROM.put(vl, 65); // Читаем из ПЗУ ячейку 3 переменную vlag_ust (установочную влажность)
lcd.clear();
lcd.setCursor(4, 1); // Определяем положение курсора (позиция,строка)
lcd.print(" F I N I S H !!! "); // Выводим на дисплей символьное значение
} // Условие окончания инкубации
else {
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print(" STOP INCUBACIYA "); // Выводим на дисплей символьное значение
lcd.setCursor(0, 1); // Определяем положение курсора (позиция,строка)
lcd.print(" YES - 0 / NO - A "); // Выводим на дисплей символьное значение
}
}
time_INC = millis() + time_INC1;
Serial.println();
delay(50);
// Блок управления устройствами
// Температура. Управление ТЭНами
if (sensor2.getTemp() + 0.3 > t_ust_sk || sensor3.getTemp() + 0.25 > t_ust_sk) {
R0_temp = 1;
digitalWrite(5, 1);
R1_temp = 1;
digitalWrite(6, 1);
} else {
if (temp.temperature < t_ust) {
R0_temp = 0;
digitalWrite(5, R0_temp);
} else {
R0_temp = 1;
digitalWrite(5, R0_temp);
}
if (temp.temperature < t_ust) {
R1_temp = 0;
digitalWrite(6, R1_temp);
} else {
R1_temp = 1;
digitalWrite(6, R1_temp);
}
}
// Влажность. Управление вентилятором увлажнения
if (vlaga_SHT <= vlag_ust - 1) {
R_vlag = 0;
digitalWrite(7, R_vlag);
} else {
if (vlaga_SHT <= vlag_ust) {
R_vlag = 0;
digitalWrite(7, R_vlag);
} else {
R_vlag = 1;
digitalWrite(7, R_vlag);
}
}
// Проветривание. Управление вентилятором улиткой
if (vlaga_SHT > vlag_ust + 2) {
R_prov = 0;
} else {
R_prov = 1;
}
if (sensor2.getTemp() + 0.3 > t_ust_sk + 0.2 || sensor3.getTemp() + 0.25 > t_ust_sk + 0.2) { R_prov = 0; }
digitalWrite(8, R_prov);
// Управление актуатором
time_del = min_Inc;
if (time_del == 0) {
digitalWrite(4, 1);
} else {
if (time_del / (k_act * 2) == floor(time_del / (k_act * 2))) {
R_actuator = 1;
Serial.println("прошел 1");
} else if (time_del / (k_act) == floor(time_del / (k_act))) {
R_actuator = 0;
Serial.println("прошел 0");
}
}
digitalWrite(4, R_actuator);
// Блок резервной памяти
Serial.print(" Влага ");
Serial.println(vlaga_SHT);
//Serial.print(" min_Inc1 1 "); Serial.println(min_Inc1); // delay(1000);
if (floor(min_Inc) > floor(min_Inc1) + 9.0) // "плюс" показывает через сколько минут записывать
{
// Serial.print(" min_Inc 2 "); Serial.println(min_Inc);
// Serial.print(" min_Inc1 2 "); Serial.println(min_Inc1); //delay(1000);
min_Inc1 = min_Inc;
EEPROM.put(vr, time_INC); // Записываем в ПЗУ ячейку 0 переменную time_INC
EEPROM.put(tr, t_ust); // Записываем в ПЗУ ячейку 2 переменную t_ust (установочную температуру)
EEPROM.put(vl, vlag_ust); // Записываем в ПЗУ ячейку 3 переменную vlag_ust (установочную влажность)
EEPROM.put(prv, k_act); // Записываем в ПЗУ ячейку prv переменную vlag_ust (переодичность переворота лотков)
Serial.print(" min_Inc 3 ");
Serial.println(min_Inc);
Serial.print(" min_Inc1 3 ");
Serial.println(min_Inc1);
delay(1000);
lcd.init(); // Инициализация экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очищаем экран
lcd.setCursor(3, 1); // Определяем положение курсора (позиция,строка)
lcd.print("S A V E");
Serial.println(" ЗАПИСЬ ");
Serial.println(" ЗАПИСЬ ");
Serial.println(" ЗАПИСЬ ");
// Serial.println(time_INC);
delay(1000);
}
// Блок переодической перезагрузки экрана
if (millis() - disp >= 30000) {
disp = millis();
lcd.init(); // Инициализация экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очищаем экран
}
delay(50);
} else {
time_INC = 0;
time_INC1 = 0;
EEPROM.put(vr, time_INC1); // Записываем в ПЗУ ячейку 0
EEPROM.put(tr, 37.5); // Читаем из ПЗУ ячейку 2 переменную t_ust (установочную температуру)
EEPROM.put(vl, 70); // Читаем из ПЗУ ячейку 3 переменную vlag_ust (установочную влажность)
lcd.clear();
lcd.setCursor(1, 1); // Определяем положение курсора (позиция,строка)
lcd.print("T I M E O F F !!! "); // Выводим на дисплей символьное значение
//Serial.print(" time_INC 8 "); Serial.println(time_INC);
// Serial.print(" time_INC1 8 "); Serial.println(time_INC1); delay(3000);
}
wdt_enable(WDTO_8S); // Таймер сброса микроконтроллера через 8 сек. после зависания
} // КОНЕЦ ВСЕГО ЦИКЛА ПРОГРАММЫ
#include "avr/wdt.h"
#include <EEPROM.h> // Библиотека резервирования в ПЗУ
#include <OneWire.h> // Подключаем библиотеку для взаимодействия с устройствами, работающими на шине и по протоколу 1-Wire
#include <microDS18B20.h>
#include <LiquidCrystal_I2C.h> // Подключаем библиотеку дисплея
#include <I2CKeyPad.h> // Подключаем библиотеку матричной клавиатуры
#include <GyverHX711.h> // Подключаем библиотеку измерения давления
#include <Adafruit_AHTX0.h> // Подключаем библиотеку Adafruit_AHTX0
Adafruit_AHTX0 aht; // Создаём объект для работы с библиотекой датчика влажности и температуры
#include "Adafruit_SHT4x.h" // Библиотека датчика влажности SHT-41
Adafruit_SHT4x sht4 = Adafruit_SHT4x(); // Подключаем Библиотеку датчика влажности SHT-41
const uint8_t PCF_ADDR = 0x20; // Константа: адрес расширителя на шине I2C
char keymap[] = "A321B654C987D#0*"; // Массив символов: карта кнопок (16 кнопок)
I2CKeyPad keyPad(PCF_ADDR); // Создание объекта keyPad для работы с клавиатурой
byte vr = 0, tr = 5, vl = 10, prv = 15; // Номера ячеек памяти для времени, температуры, влажности
float t_ust = 37.5; // Устанавливаем начальную температуру в инкубаторе
float t_ust_sk = 37.8; // Устанавливаем предельную температуру на скорлупе
byte vlag_ust = 70; // Устанавливаем влажность в инкубаторе
unsigned long time_INC, time_INC1; // Создаем переменную для таймеа инкубации и резерва
float time_del;
float vlaga_SHT, temp_SHT;
long sutki_Inc, hour_Inc, hour_Inc1, min_Inc, min_Inc_D, min_Inc1; // и контрольные переменные в сутках, часах и в минутах
unsigned long disp; // Переменная для переодической очистки экрана
byte sutki = 35; // Переменная устанавливающая длительность инкубации в сутках
float k_act = 120; // Время поворота лотков 120 или 240 минут
char cod = 'A', regim = 'A';
boolean R0_temp = 1, R1_temp = 1, R_vlag = 0, R_prov = 0; // Переменные для управления РЕЛЕ ТЭНОВ, Влажности и проветривания 0 или 1
boolean R_actuator; // Переменная для актуатора
// Определяем пины под датчики температуры
// MicroDS18B20<10> sensor1; // датчик 1
MicroDS18B20<2> sensor2; // датчик 2
MicroDS18B20<3> sensor3; // датчик 3
LiquidCrystal_I2C lcd(0x27, 20, 4); // Определяем ID и тип дисплея
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.setClock(10000); // Понижение скорости шины I2C до 50 кГц
Wire.setWireTimeout(10000, true); // Сброс шины I2C при ошибке длительностью 10 миллисекунд
if (!keyPad.begin()) {
Serial.println("PCF8574 не найден!"); // Вывод ошибки в монитор порта
while (1)
; // Остановка программы: бесконечный пустой цикл
}
// ********* Настройка сенсора влажности и температуры ******************
Serial.println("Adafruit SHT4x test");
if (!sht4.begin()) {
Serial.println("Couldn't find SHT4x sensor");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
// Настройка точности (High, Medium, Low)
sht4.setPrecision(SHT4X_HIGH_PRECISION);
// Настройка нагревателя (если не нужен, можно пропустить)
sht4.setHeater(SHT4X_NO_HEATER);
// *********************************************************************
lcd.init(); // Инициализация экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очищаем экран
/* ******************* Сенсор АНТ-10 *******************
if (!aht.begin()) // Инициализация датчика влажности и температуры
{
Serial.println("Could not find AHT? Check wiring"); // Отправка сообщения
while (1) delay(10); // Зацикливаем программу
}
****************************************************************
*/
// Определяем пины под управление реле
pinMode(5, OUTPUT); // ТЭН №1 220В
pinMode(6, OUTPUT); // ТЭН №2 220В
pinMode(7, OUTPUT); // Вентилятор влажности 12В
pinMode(8, OUTPUT); // Вентилятор проветривания 12В
pinMode(4, OUTPUT); // Актуатор 12В
EEPROM.get(vr, time_INC1); // Читаем из ПЗУ ячейку vr переменную time_INC1 (текущее время инкубации)
EEPROM.get(tr, t_ust); // Читаем из ПЗУ ячейку tr переменную t_ust (установочную температуру)
EEPROM.get(vl, vlag_ust); // Читаем из ПЗУ ячейку vl переменную vlag_ust (установочную влажность)
EEPROM.get(prv, k_act); // Читаем из ПЗУ ячейку prv переменную vlag_ust (переодичность переворота лотков)
if (t_ust == 0) { t_ust = 37.5; }
if (vlag_ust == 0) { vlag_ust = 70; }
}
void loop() {
wdt_reset();
sensors_event_t humidity, temp;
// Чтение данных
static uint32_t tmr41;
if (millis() - tmr41 >= 2500) {
tmr41 = millis();
sht4.getEvent(&humidity, &temp);
vlaga_SHT = humidity.relative_humidity;
temp_SHT = temp.temperature;
}
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("% rH");
if (sutki != 0) { // ОСНОВНОЙ ЦИКЛ ЗАВЕРШЕНИЯ ИНКУБАЦИИ
// min_Inc1 = min_Inc;
// конструкция программного таймера на 2500 мс для опроса датчика каждые 2,5 секунды
static uint32_t tmr;
if (millis() - tmr >= 2500) {
tmr = millis();
// читаем прошлое значение
if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
else Serial.println("error2");
if (sensor3.readTemp()) Serial.println(sensor3.getTemp());
else Serial.println("error3");
Serial.println();
// запрашиваем новое измерение датчиков температуры
// sensor1.requestTemp();
sensor2.requestTemp();
sensor3.requestTemp();
}
// Раздел работы с датчиком влажности и температуры
// sensors_event_t humidity, temp; // Создаём объект для работы с библиотекой
// aht.getEvent(&humidity, &temp); // Считваем показания
// Раздел для определения дней, часов и минут
sutki_Inc = time_INC / 1000 / 60 / 60 / 24;
hour_Inc = time_INC / 1000 / 60 / 60 - sutki_Inc * 24;
min_Inc = time_INC / 1000 / 60;
// Раздел работы с клавиатурой
// ОПЕРАТОР IF: проверяет условие (нажата ли любая кнопка)
if (keyPad.isPressed()) {
// Вызов метода .getKey(), который возвращает индекс нажатой кнопки (число от 0 до 15)
uint8_t index = keyPad.getKey();
// Проверка, что индекс находится в рамках нашего массива (0-15)
if (index < 16) {
Serial.print("Нажато: "); // Вывод текста без переноса строки
Serial.println(keymap[index]); // Вывод символа из массива по индексу с переносом
cod = keymap[index];
}
// ЦИКЛ WHILE: "замораживает" программу, пока кнопка удерживается
// Это нужно, чтобы одно нажатие не превратилось в бесконечный поток символов
while (keyPad.isPressed()) {
delay(10); // Короткая пауза 10 мс для стабильности
}
}
// Присваеваем переменной "regim"(режим) значение нажатой клавиши, если она Влага
// равна A, B, C, или D
if (cod == 'A') {
regim = cod;
lcd.clear();
cod = '2';
}
if (cod == 'B') {
if (cod != regim) { lcd.clear(); }
regim = cod;
}
if (cod == 'C') {
if (cod != regim) { lcd.clear(); }
regim = cod;
}
if (cod == 'D') {
regim = cod;
lcd.clear();
cod = '2';
}
// РЕЖИМ А
if (regim == 'A') {
// Очищаем экран
// УСТАНОВКА ВРЕМЕНИ ИНКУБАЦИИ
if (cod == '1') {
sutki = sutki - 1;
cod = '2';
}
if (cod == '3') {
sutki = sutki + 1;
cod = '2';
}
// }
// Индикация времени c начала инкубации
lcd.setCursor(0, 1); // Определяем положение курсора (позиция,строка)
lcd.print("INCUB ");
lcd.setCursor(7, 1);
min_Inc_D = time_INC / 1000 / 60 - sutki_Inc * 24 * 60 - hour_Inc * 60;
lcd.print(sutki_Inc);
lcd.print("d "); // Во второй строке выводим количество суток который идет инкубация
lcd.print(hour_Inc);
lcd.print("h "); // следом выводим часы инкубации
lcd.print(min_Inc_D);
lcd.print("m"); // следом выводим минуты инкубации
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print("Time INCUB "); // Выводим на дисплей символьное значение
lcd.setCursor(11, 0); // Определяем положение курсора (позиция,строка)
lcd.print(sutki); // Выводим заданное время инкубации в сутках
lcd.print(" d");
lcd.setCursor(0, 2); // Определяем положение курсора (позиция,строка)
lcd.print("Temp ");
lcd.print(temp_SHT, 1);
lcd.print("'C ");
lcd.print(t_ust, 1);
lcd.print("'C"); // Выводим на дисплей температуру
lcd.setCursor(0, 3); // Определяем положение курсора (позиция,строка)
lcd.print("Vlagnost ");
lcd.print(vlaga_SHT, 0);
lcd.print("% ");
lcd.print(vlag_ust);
lcd.print("%"); // Выводим на дисплей влажность
Serial.print("t_ust ");
Serial.println(t_ust);
Serial.print("vlag_ust ");
Serial.println(vlag_ust);
delay(50); // Пауза
// УСТАНОВКА ПРЕДЕЛЬНОЙ ТЕМПЕРАТУРЫ В ИНКУБАТОРЕ
//if (customKey) {
if (cod == '4') {
t_ust = t_ust - 0.1;
cod = '5';
}
if (cod == '6') {
t_ust = t_ust + 0.1;
cod = '5';
}
// УСТАНОВКА ПРЕДЕЛЬНОЙ ВЛАЖНОСТИ В ИНКУБАТОРЕ
//if (customKey) {
if (cod == '7') {
vlag_ust = vlag_ust - 1;
cod = '8';
}
if (cod == '9') {
vlag_ust = vlag_ust + 1;
cod = '8';
}
}
// РЕЖИМ B
// (Температурные показатели датчиков)
if (regim == 'B') {
// lcd.clear(); // Очищаем экран
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print("TEMP-1 ");
lcd.print(temp_SHT);
lcd.print(" 'C");
lcd.setCursor(0, 1); // Определяем положение курсора (позиция,строка)
lcd.print("TEMP-2 ");
lcd.print(sensor2.getTemp() + 0.3);
lcd.print(" 'C");
lcd.setCursor(0, 2); // Определяем положение курсора (позиция,строка)
lcd.print("TEMP-3 ");
lcd.print(sensor3.getTemp() + 0.25);
lcd.print(" 'C");
lcd.setCursor(0, 3); // Определяем положение курсора (позиция,строка)
lcd.print("VLAGA ");
lcd.print(vlaga_SHT, 0);
lcd.print(" %");
}
// Режим С это режимы работы устройств
if (regim == 'C') {
if (cod == '1') {
t_ust_sk = t_ust_sk - 0.1;
cod = '2';
}
if (cod == '3') {
t_ust_sk = t_ust_sk + 0.1;
cod = '2';
}
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print(" SCORLUPA"); // Выводим на дисплей символьное значение
lcd.setCursor(11, 0);
lcd.print(t_ust_sk);
lcd.print("'C");
if (cod == '7') {
k_act = k_act - 60;
cod = '8';
}
if (cod == '9') {
k_act = k_act + 60;
cod = '8';
}
lcd.setCursor(0, 2); // Определяем положение курсора (позиция,строка)
lcd.print("ACTUATOR "); // Выводим на дисплей символьное значение
if (R_actuator == 0) {
lcd.print("-45'");
} else {
lcd.print("+45'");
}
lcd.setCursor(0, 3); // Определяем положение курсора (позиция,строка)
lcd.print("POVOROT ");
lcd.print(k_act);
lcd.print(" min "); // Выводим на дисплей символьное значение
}
// РЕЖИМ D Управление и индикация окончанием инкубации
if (regim == 'D') {
if (cod == '0') {
sutki = 0; // Условие окончания инкубации
EEPROM.put(vr, 0); // Вначале номер ячейки, затем значение вписанное в эту ячейку
time_INC = 0;
EEPROM.put(tr, 37.5); // Читаем из ПЗУ ячейку 2 переменную t_ust (установочную температуру)
EEPROM.put(vl, 65); // Читаем из ПЗУ ячейку 3 переменную vlag_ust (установочную влажность)
lcd.clear();
lcd.setCursor(4, 1); // Определяем положение курсора (позиция,строка)
lcd.print(" F I N I S H !!! "); // Выводим на дисплей символьное значение
} // Условие окончания инкубации
else {
lcd.setCursor(0, 0); // Определяем положение курсора (позиция,строка)
lcd.print(" STOP INCUBACIYA "); // Выводим на дисплей символьное значение
lcd.setCursor(0, 1); // Определяем положение курсора (позиция,строка)
lcd.print(" YES - 0 / NO - A "); // Выводим на дисплей символьное значение
}
}
time_INC = millis() + time_INC1;
Serial.println();
delay(50);
// Блок управления устройствами
// Температура. Управление ТЭНами
if (sensor2.getTemp() + 0.3 > t_ust_sk || sensor3.getTemp() + 0.25 > t_ust_sk) {
R0_temp = 1;
digitalWrite(5, 1);
R1_temp = 1;
digitalWrite(6, 1);
} else {
if (temp.temperature < t_ust) {
R0_temp = 0;
digitalWrite(5, R0_temp);
} else {
R0_temp = 1;
digitalWrite(5, R0_temp);
}
if (temp.temperature < t_ust) {
R1_temp = 0;
digitalWrite(6, R1_temp);
} else {
R1_temp = 1;
digitalWrite(6, R1_temp);
}
}
// Влажность. Управление вентилятором увлажнения
if (vlaga_SHT <= vlag_ust - 1) {
R_vlag = 0;
digitalWrite(7, R_vlag);
} else {
if (vlaga_SHT <= vlag_ust) {
R_vlag = 0;
digitalWrite(7, R_vlag);
} else {
R_vlag = 1;
digitalWrite(7, R_vlag);
}
}
// Проветривание. Управление вентилятором улиткой
if (vlaga_SHT > vlag_ust + 2) {
R_prov = 0;
} else {
R_prov = 1;
}
if (sensor2.getTemp() + 0.3 > t_ust_sk + 0.2 || sensor3.getTemp() + 0.25 > t_ust_sk + 0.2) { R_prov = 0; }
digitalWrite(8, R_prov);
// Управление актуатором
time_del = min_Inc;
if (time_del == 0) {
digitalWrite(4, 1);
} else {
if (time_del / (k_act * 2) == floor(time_del / (k_act * 2))) {
R_actuator = 1;
Serial.println("прошел 1");
} else if (time_del / (k_act) == floor(time_del / (k_act))) {
R_actuator = 0;
Serial.println("прошел 0");
}
}
digitalWrite(4, R_actuator);
// Блок резервной памяти
Serial.print(" Влага ");
Serial.println(vlaga_SHT);
//Serial.print(" min_Inc1 1 "); Serial.println(min_Inc1); // delay(1000);
if (floor(min_Inc) > floor(min_Inc1) + 9.0) // "плюс" показывает через сколько минут записывать
{
// Serial.print(" min_Inc 2 "); Serial.println(min_Inc);
// Serial.print(" min_Inc1 2 "); Serial.println(min_Inc1); //delay(1000);
min_Inc1 = min_Inc;
EEPROM.put(vr, time_INC); // Записываем в ПЗУ ячейку 0 переменную time_INC
EEPROM.put(tr, t_ust); // Записываем в ПЗУ ячейку 2 переменную t_ust (установочную температуру)
EEPROM.put(vl, vlag_ust); // Записываем в ПЗУ ячейку 3 переменную vlag_ust (установочную влажность)
EEPROM.put(prv, k_act); // Записываем в ПЗУ ячейку prv переменную vlag_ust (переодичность переворота лотков)
Serial.print(" min_Inc 3 ");
Serial.println(min_Inc);
Serial.print(" min_Inc1 3 ");
Serial.println(min_Inc1);
delay(1000);
lcd.init(); // Инициализация экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очищаем экран
lcd.setCursor(3, 1); // Определяем положение курсора (позиция,строка)
lcd.print("S A V E");
Serial.println(" ЗАПИСЬ ");
Serial.println(" ЗАПИСЬ ");
Serial.println(" ЗАПИСЬ ");
// Serial.println(time_INC);
delay(1000);
}
// Блок переодической перезагрузки экрана
if (millis() - disp >= 30000) {
disp = millis();
lcd.init(); // Инициализация экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очищаем экран
}
delay(50);
} else {
time_INC = 0;
time_INC1 = 0;
EEPROM.put(vr, time_INC1); // Записываем в ПЗУ ячейку 0
EEPROM.put(tr, 37.5); // Читаем из ПЗУ ячейку 2 переменную t_ust (установочную температуру)
EEPROM.put(vl, 70); // Читаем из ПЗУ ячейку 3 переменную vlag_ust (установочную влажность)
lcd.clear();
lcd.setCursor(1, 1); // Определяем положение курсора (позиция,строка)
lcd.print("T I M E O F F !!! "); // Выводим на дисплей символьное значение
//Serial.print(" time_INC 8 "); Serial.println(time_INC);
// Serial.print(" time_INC1 8 "); Serial.println(time_INC1); delay(3000);
}
wdt_enable(WDTO_8S); // Таймер сброса микроконтроллера через 8 сек. после зависания
} // КОНЕЦ ВСЕГО ЦИКЛА ПРОГРАММЫ
Скетч конечно корявый в плане построения, много нагромождений. Но писал его поэтапно. Можно сказать в процессе изучения.
А почему два?
Стерео!
@Evgeniy73 Логичнее взвести таймер один раз в сетапе, а скидывать в конце лупа и в длительных функциях.
так надежней, как и с NE555))
Чего два ?