#include <Lm335.h> // Библиотека аналогового датчика температуры https://g...content-available-to-author-only...b.com/Leo-NVKZ/Lm335
#include <Wire.h> // Библиотека шины
#include <LiquidCrystal_I2C.h> // Библиотека дисплея
#include <OneWire.h> // Библиотека цифрового датчика температуры
#include <EEPROM.h> // Библиотека памяти
LiquidCrystal_I2C lcd(0x3F, 16, 2); // Установка адреса и размерности дисплея
byte i; // для цифрового датчика температуры
byte DataDig[12]; // Данные для цифрового датчика температуры
byte AddrDig[8] = {0x28, 0xFF, 0xA3, 0x40, 0x62, 0x16, 0x3, 0x9B}; // Адрес для цифрового датчика температуры
int TempDig; // Переменная температуры цифрового датчика
int TempSens; // Переменная температуры выбранного датчика
int TempSensMin; // Границы рабочей зоны выбранного датчика
int TempSensMax;
int Sett = 0; // Включаем нумерацию настроечных параметров
int nz = 0; // Переменная отсчета задержек для меню.
int memread = 0; // Ключ для чтения данных из EEPROM
int KluchPauza = 0; // Ключ для паузы
int NParam; // Переменная для выбора параметра
const int KolNactr = 4; // Количество элементов массивов настроек
// (количество настраиваемых параметров)
int Parametr[KolNactr]; // Массив для значений параметров настроек
/*
"""Настройки"""
0. Температура включения реле цифрового датчика
1. Температура выключения реле цифрового датчика
2. Температура включения реле аналогового датчика
3. Температура выключения реле аналогового датчика
*/
// Массив названий параметров, названия можно писать свои в количестве, указанном выше,
// длиной до 10 символов включительно. Язык английский.
String NameParametr[KolNactr] =
{
"TempOnDig",
"TempOffDig",
"TempOnAn ",
"TempOffAn "
};
boolean DigitalSens; // Переменная значений по отключению Цифрового датчика
//boolean AnalogSens; // Переменная значений по отключению аналогового датчика
unsigned long timezad; // Переменная значений по отключению аналогового датчика
OneWire ds(2); // Устанока пина 2 для цифрового датчика температуры
int const Left = 3; // Кнопка настроек влево
int const Esc = 4; // Кнопка настроек выход
int const Enter = 5; // Кнопка настроек ввод
int const Right = 6; // Кнопка настроек вправо
int const Upravl = 7; // номер пина для управления симистором
int const LedOn = 9; // номер пина светодиод включения процесса основного режима работы
int const LedNagr = 10; // номер пина светодиод включения нагрева
int const Muz = 11; // номер пина динамик
const int datchik_1 = 0; // Определяем аналоговый пин для подключения датчикa
int temper_out; // Температура, округленная до целых значений, градусов по Цельсию
double U_vcc = 5.02; // Здесь указываем точное напряжение питания датчика
double volt; // Напряжение на датчике - для его настройки, В
double temper;
// Создаем объект для аналогового датчика
Lm335 lm3351(datchik_1, U_vcc); // Создаем объект для датчика 1
void setup() {
pinMode (Left, INPUT); // Кнопка настроек влево
pinMode (Esc, INPUT); // Кнопка настроек выход
pinMode (Enter, INPUT); // Кнопка настроек ввод
pinMode (Right, INPUT); // Кнопка настроек вправо
pinMode (Upravl, OUTPUT); // пин управления симистором
pinMode (LedOn, OUTPUT); // пин светодиода запущенного процесса
pinMode (LedNagr, OUTPUT); // пин светодиода запущенного процесса
pinMode (Muz, OUTPUT); // пин динамика
digitalWrite (Upravl, 0); // отключаем симистор
digitalWrite (LedOn, 0); // светодиод работы отключен
digitalWrite (LedNagr, 0); // светодиод нагрева отключен
noTone(Muz); //Звук отключен
lcd.init(); // Инициализация дисплея
lcd.backlight(); // Подсветка дисплея
// данные самодельных символов для дисплея:
byte lcd_gradus[8] = {0x00, 0x10, 0x06, 0x09, 0x08, 0x09, 0x06, 0x00};
// Создание самодельных символов для дисплея
lcd.createChar(0, lcd_gradus); // градус
Wire.begin();
//Serial.begin(9600);
}
void loop() {
if (KluchPauza == 0) // Пауза перед запуском программы
{
Serial.println("pause");
delay (500);
Musik();
KluchPauza = 1;
}
if (memread == 0) // Один раз считываем данные настроек из памяти и выводим неизменяемые символы на дисплей
{
Serial.println("memread");
for (int i = 0; i < KolNactr; ++i) // Цикл считывания данных из EEPROM
{
Parametr[i] = EEPROM.read(i);
}
DigitalSens = EEPROM.read(KolNactr);
memread = 1;
DisplayConst();
}
if (digitalRead(Enter) == 1) // Если кнопка ввода нажата
{
beep(700, 200);
beep(800, 200);
beep(900, 200);
noTone(Muz);
Nastroyka(); // Переходим в меню настройки
}
DatchikDig (); // Работаем с датчиками температуры
// Начинаем выводить данные на дисплей
lcd.setCursor(3, 0);
lcd.print(TempDig);
lcd.setCursor(3, 1);
lcd.print(temper_out);
lcd.setCursor(11, 0);
lcd.print(Parametr[0]);
lcd.setCursor(14, 0);
lcd.print(Parametr[1]);
lcd.setCursor(11, 1);
lcd.print(Parametr[2]);
lcd.setCursor(14, 1);
lcd.print(Parametr[3]);
if (DigitalSens == false)
{
lcd.setCursor(7, 0);
lcd.print("OFF");
lcd.setCursor(7, 1);
lcd.print(" ON");
}
else
{
lcd.setCursor(7, 0);
lcd.print(" ON");
lcd.setCursor(7, 1);
lcd.print("OFF");
}
if (digitalRead(Left) == 1) // Запускаем режим работы
{
beep(700, 100);
beep(700, 100);
beep(800, 100);
beep(800, 100);
beep(900, 200);
noTone(Muz);
work ();
}
}
void DatchikDig () // Функция получения данных с датчиков температуры
{
byte present = 0;
ds.reset(); // Очищаем цифровой датчик
ds.select(AddrDig);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(AddrDig); // выбираем цифровой датчик
ds.write(0xBE); // Считываем данные с цифрового датчика
for ( i = 0; i < 9; i++) // Записываем данные с цифрового датчика
{
DataDig[i] = ds.read();
}
int16_t raw = (DataDig[1] << 8) | DataDig[0]; // Извлекаем данные о температуре с цифрового датчика
raw = raw & ~7; // Определяем точность для температуры 0,5 градусов
TempDig = (int)raw / 16.0; // Пересчитываем в градусы Цельсия
lm3351.datchikVozdAnalog(); // Вызов метода определения параметров для аналогового датчика
temper_out = lm3351.temp335_out; // Получаем температуру, округленную до целых значений
temper = lm3351.temp335; // Получаем температуру с датчика 1
}
void Nastroyka() // Функция выбора меню на дисплее
{
lcd.clear(); // Очистка дисплея
while (nz < 5) // Цикл ожидания, выполняется 1 раз при входе
{
delay (200);
++nz;
}
int Kluch_5 = 1;
int menu = 0;
while (Kluch_5 = 1)
{
lcd.setCursor(0, 0);
lcd.print("Parametrs");
lcd.setCursor(0, 1);
lcd.print("Datchik");
delay (100);
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода из режима выбора настроек
{
// Serial.println("Esc");
beep(900, 200);
beep(800, 200);
beep(700, 200);
noTone(Muz);
lcd.clear(); // Очистка дисплея
Kluch_5 = 0;
nz = 0;
memread = 0;
break;
}
if (menu == 0)
{
lcd.setCursor(10, 0);
lcd.print("<");
lcd.setCursor(10, 1);
lcd.print(" ");
}
else
{
lcd.setCursor(10, 1);
lcd.print("<");
lcd.setCursor(10, 0);
lcd.print(" ");
}
if (digitalRead(Right) == 1) // Если кнопка вправо нажата
{
menu = 1;
}
if (digitalRead(Left) == 1) // Если кнопка влево нажата
{
menu = 0;
}
Serial.println(menu);
if (digitalRead(Enter) == 1) // Если кнопка ввода нажата
{
if (menu == 1)
{
Datchik ();
}
else
{
Nastr_Parametr ();
}
}
}
}
void Nastr_Parametr () // Функция настройки параметров с кнопок и сохранения их в EEPROM
{
lcd.clear(); // Очистка дисплея
int Kluch = 1; // Задаем значение, не позволяющее покинуть функцию без команды
int nastr = 0; // Включаем нумерацию настроечных параметров
int nastr_d = nastr + 1;
int nz = 0; // Счетчик для циклов ожидания, выполняющихся 1 раз
while (Kluch = 1) // Цикл выбора параметра
{
while (nz < 5) // Цикл ожидания, выполняется 1 раз при входе
{
delay (100);
++nz;
}
delay (100); // Ожидание - выполняется каждый раз
if (digitalRead(Right) == 1) // Изменяем значение номера выбираемого параметра:
{
++nastr; // увеличиваем
}
if (digitalRead(Left) == 1)
{
--nastr; // уменьшаем
}
if (nastr < 0) // Ограничиваем выбор настроек заданным их количеством
{
nastr = KolNactr - 1;
}
if (nastr > KolNactr - 1)
{
nastr = 0;
}
nastr_d = nastr + 1;
if (nastr == KolNactr - 1)
{
nastr_d = 0;
}
lcd.setCursor(0, 0); // Вывод на экран названия настройки
lcd.print(NameParametr[nastr]); // в соответствии с ее номером в массиве названий
lcd.setCursor(10, 0);
lcd.print("<");
lcd.setCursor(0, 1);
lcd.print(NameParametr[nastr_d]);
lcd.setCursor(12, 0);
if (Parametr[nastr] < 10) // Прописываем пустое место перед единицами
{
lcd.print(" ");
}
if (Parametr[nastr] >= 10 && Parametr[nastr] < 100) // Пустое место перед десятками
{
lcd.print(" ");
}
lcd.print(Parametr[nastr]); // выводим значение сохраненного параметра
lcd.setCursor(12, 1);
if (Parametr[nastr_d] < 10) // Прописываем пустое место перед единицами
{
lcd.print(" ");
}
if (Parametr[nastr_d] >= 10 && Parametr[nastr_d] < 100) // Пустое место перед десятками
{
lcd.print(" ");
}
lcd.print(Parametr[nastr_d]);
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода из режима выбора настроек
{
lcd.clear(); // Очистка дисплея
Kluch = 0;
nz = 0;
break;
}
if (digitalRead(Enter) == 1) // Если нажата кнопка выбора настроечного параметра
{
int Kluch_2 = 1; // Задаем значение, не позволяющее покинуть цикл без команды
nz = 0; // Обнуляем счетчик цикла ожидания
lcd.setCursor(10, 0);
lcd.print(" ");
lcd.setCursor(15, 0);
lcd.print("<");
while (Kluch_2 == 1) // Цикл выбора значения параметра
{
lcd.setCursor(12, 0);
if (Parametr[nastr] < 10) // Прописываем пустое место перед единицами
{
lcd.print(" ");
}
if (Parametr[nastr] >= 10 && Parametr[nastr] < 100) // Пустое место перед десятками
{
lcd.print(" ");
}
lcd.print(Parametr[nastr]); // выводим значение сохраненного параметра
while (nz < 5) // Цикл ожидания, выполняется 1 раз
{
delay (100);
++nz;
}
delay (100); // Ожидание, отвечает за скорость смены значений
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Parametr[nastr];
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Parametr[nastr];
}
if (Parametr[nastr] < 50) // Задаем границы для значений параметров, в том числе
{ // обусловленные возможностями ячейки памяти (256)
Parametr[nastr] = 100;
}
if (Parametr[nastr] > 100)
{
Parametr[nastr] = 50;
}
if (digitalRead(Enter) == 1) // Если в этом режиме нажата кнопка Ввод,
{ // сохраняем значение параметра в EEPROM
EEPROM.write(nastr, Parametr[nastr]);
lcd.setCursor(15, 0);
lcd.print("+");
delay (500);
lcd.setCursor(15, 0);
lcd.print(" "); // Стираем значок
Kluch_2 = 0;
nz = 0;
memread = 0;
continue;
}
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода, выходим в предыдущее меню
{ // выбора номера параметра,
lcd.setCursor(15, 0);
lcd.print(" "); // попутно стирая на дисплее значок
Kluch_2 = 0;
nz = 0;
continue;
}
}
}
delay (200);
}
}
void Datchik () // Функция отключения датчиков
{
lcd.clear(); // Очистка дисплея
while (nz < 7) // Цикл ожидания, выполняется 1 раз при входе
{
delay (200);
++nz;
}
int Kluch_6 = 1;
//int menu = 0;
while (Kluch_6 = 1)
{
lcd.setCursor(0, 0);
if (DigitalSens == false)
{
lcd.print("Analog");
}
else
{
lcd.print("Digital");
}
if (timezad + 1000 < millis())
{
//lcd.setCursor(14, 1);
// lcd.print(" ");
lcd.setCursor(14, 0);
lcd.print(" ");
}
delay (300);
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода из режима выбора настроек
{
lcd.clear(); // Очистка дисплея
Kluch_6 = 0;
nz = 0;
memread = 0;
break;
}
if ((digitalRead(Right) == 1) || (digitalRead(Left) == 1)) // Если кнопка вправо или влево нажата
{
DigitalSens = !DigitalSens;
}
if (digitalRead(Enter) == 1) // Если кнопка ввода нажата
{
lcd.setCursor(14, 0);
lcd.print("+");
timezad = millis();
EEPROM.write(KolNactr, DigitalSens);
memread = 0;
}
}
}
void work()
{
int kluch_7 = 1;
while (kluch_7 == 1)
{
digitalWrite (LedOn, 1); // Светодиод основного режима включен
DatchikDig (); // считываем данные с датчиков температуры
lcd.setCursor(3, 0); // Выводим данные о температуре на дисплей
lcd.print(TempDig);
lcd.setCursor(3, 1);
lcd.print(temper_out);
if (DigitalSens == false) // Если выбран аналоговый датчик, работаем с ним
{
TempSens = temper_out;
TempSensMin = Parametr[2];
TempSensMax = Parametr[3];
}
else
{
TempSens = TempDig;
TempSensMin = Parametr[0];
TempSensMax = Parametr[1];
}
if (TempSens <= TempSensMin)
{
digitalWrite (Upravl, 1); // включаем симистор
digitalWrite (LedNagr, 1); // светодиод нагрева включен
}
if (TempSens >= TempSensMax)
{
digitalWrite (Upravl, 0); // выключаем симистор
digitalWrite (LedNagr, 0); // светодиод нагрева выключен
}
if (TempSens >= (TempSensMax + 5))
{
Alarm();
}
if (digitalRead(Right) == 1)
{
digitalWrite (Upravl, 0); // выключаем симистор
digitalWrite (LedNagr, 0); // светодиод нагрева выключен
digitalWrite (LedOn, 0); // Светодиод основного режима отключен
beep(900, 100);
beep(900, 100);
beep(800, 100);
beep(800, 100);
beep(700, 200);
noTone(Muz);
break;;
}
}
}
void DisplayConst()
{
// Выводим на дисплей неизменяемые символы.
lcd.setCursor(0, 0);
lcd.print("D: ");
lcd.setCursor(5, 0);
lcd.write(byte(0));
lcd.print(" ");
lcd.setCursor(10, 0);
lcd.print(" ");
lcd.setCursor(13, 0);
lcd.print("-");
lcd.setCursor(0, 1);
lcd.print("A: ");
lcd.setCursor(5, 1);
lcd.write(byte(0));
lcd.print(" ");
lcd.setCursor(10, 1);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.print("-");
}
void beep(int ton, int time)
{
tone(Muz, ton, time);
delay(time + 20);
}
void Musik()
{
beep(440, 500);
beep(440, 500);
beep(440, 500);
beep(349, 350);
beep(523, 150);
beep(440, 500);
beep(349, 350);
beep(523, 150);
beep(440, 650);
noTone(Muz);
}
void Alarm ()
{
beep(700, 400);
beep(900, 400);
noTone(Muz);
}