// ЕСЛИ ПУТАЕТЕСЬ в понятиях, что такое переменная и тд - пишите в комментарии, сделаю видео лекбез по вашим вопросам. // Комментировать (исключить из выполнения программы) - это установить // в начале строки. Тогда строка исполнятся не будет //________________подключаем датчик температуры #include // используем библиотеку OneWire.h OneWire ds(2); // контакт DATA датчика подключен на PIN 2 unsigned long timing; // Переменная для хранения точки отсчета float T_real; //КОНЕЦ________________подключаем датчик температуры //________________подключаем реле int relayPin = 3; //подключаем реле на 3й пин //КОНЕЦ________________подключаем реле //________________подключаем дисплей #include // подключаем библиотеку LCD_1602_RUS.h LCD_1602_RUS lcd(0x027, 16, 2); // устанавливаем параметры дисплея 16 символов, 2 строки // 0x3F - адрес i2c адаптера, если на дисплее белая полоса, то ставим адрес 0x27 // если нет изображения нужно покрутить регулятор на i2c адаптере //КОНЕЦ________________подключаем дисплей//--------------- //----------блок переменных------------- // назначаем переменные boolean otbor_on = 0;// флаг начала отбора. 0- запрещено. 1 - разрешено float gisteresis=0.2; // разброс темперетуры, что бы отбор не прекращался из за незначительных колебаний термодатчика или погрешностей int T_open_klapan=25; //температура, при которой будет включен клапан отбора. Обычно заметно ниже спиртовой полки boolean button_flag = 0; // Флаг состояния кнопок. 0 или 1 кнопка отпущена или нажата float T_TMP=30;// стартовое значение температуры при введении float T_otbor=30;//стартовое значение рабочей температуры. Для простоты оно равно переменной выше float T_step=0;//назначаем переменную в которой будет установлен шаг изменения температуры. Шаг или 1 илли 0.1 int counter_arr=0;// счетчик кол-ва измеренных значений для определения реального int button_val;// сюда будем записывать измеренное напряжение (в относительных величинах) при нажатой кнопки int arr_max;//сюда будем записывать наибольшее значение из произведенных измерений int values[5];//Инициализируем массив для записи в него измеренных значений unsigned long time; // переменная для записи времени unsigned long start_time_pressed;// переменная для фиксации момента нажатия на кнопку (первый момент) int button_N;//в этой переменной храним номер нажатой кнопки //КОНЕЦ----------блок переменных------------- // установочные настройки void setup() { //инициализируем COM порт Serial.begin(9600); //____Инициализируем дисплей lcd.init(); // проводим инициализацию дисплея lcd.backlight(); // включаем подсветку lcd.print(L"УМНЫЕ МОДУЛИ"); // выводим надпись на русском языке lcd.setCursor(0, 1); // ставим курсор в начало второй строки lcd.print("SMDX.RU"); // выводим надпись на английском // инициализируем пин, подключенный к реле, как выход pinMode(relayPin, OUTPUT); } // КОНЕЦ установочные настройки // бесконечный цикл void loop() { //_______________БЛОК кнопок_______ button_val = analogRead(A0);// считываем показания time = millis();//записываем время в переменную. Время тут это миллисекунд с момента текущего запуска ардуино // справка millis() - Возвращает количество миллисекунд с момента начала выполнения текущей программы на плате Arduino. Это количество сбрасывается на ноль, в следствие переполнения значения, приблизительно через 50 дней //задаем шаг изменения температуры if (T_TMP>109 ) { // если устанавливаемое значение выше 109 градусов, то сбрасываем его до 0 градуса T_step=1; T_TMP=0;//шаг изменения установки температуры } else if (T_TMP>70 and T_TMP<90 ) { // в промежутке между этими значениями меняем значение с точностью до 0.1 градуса. T_step=0.1;//шаг изменения установки температуры. когда рядом со спиртовой полкой, повышаем точность установки } else { // во всех других случаях T_step=1;//шаг изменения установки температуры T_TMP=floor(T_TMP);// вне пределов вероятной спиртовой полки значения у нас идут кратны 1 градусу. } // КОНЕЦ задаем шаг изменения температуры // фиксируем событие нажатие кнопки if ( button_flag == 0 and time-start_time_pressed>30 and (button_val >200 or counter_arr >0) ) { // если скакнуло сопротивление или началось измерение // button_flag == 0 - Предыдущее положение кнопки было - "отжата". time-start_time_pressed>30 время с момента начала последнего нажатия кнопки больше 30 миллисекунд. (button_val >200 or counter_arr >0) Напряжение (в относительных величинах) скакнуло больше 200 И Замер нескольких значений началось. // оперетор "and" - синоним "И". оперетор "or" - синоним "ИЛИ" start_time_pressed=millis();// запоимнаем время нажатия кнопки // начинаем измерения напряжения. делаем 5 замеров подряд if (counter_arr >=0 and counter_arr<5 ) { values[counter_arr] = button_val; // записываем значения в массив //counter_arr=counter_arr+1; counter_arr++; //Увеличиваем значения счетчика замеров на 1. }else{// как только массив измерений заполнился при последнем цикле проанализировали - все обнуляем counter_arr=0;//обнуляем счетчик arr_max =0;//обнуляем максимально полученное значение }//end if // КОНЕЦ начинаем измерения напряжения. //когда массив полученных напряжений заполнен, анализируем. находим самое большое значение. if (counter_arr==5 ) { // после того как считали несколько значений в массив, находим самое большое. значение окажется в переменной arr_max for(int i = 1; i <= 5; i++){ // запускаем цикл, для обхода всех элементов массива arr_max = max(arr_max, values[i]); // работает только с 2мя числами }//end for // КОНЕЦ анализа if (arr_max < 201) { // защита от ложного срабатывания. очень маленькое значение по напряжению. button_N=0;// считаем что кнопка НЕ нажата }else if (arr_max < 380) { button_N=1;// нажатие первой кнопки // Первая кнопка отвечает за фиксацию (запоминание) введенных только что значений, как рабочих. T_otbor=T_TMP; Serial.print (" T_otbor: "); Serial.print (T_otbor); Serial.print (" T_TMP: "); Serial.println(T_TMP); }else if (arr_max < 650) {// нажатие второй кнопки //вторая кнопка уменьшает значение температуры button_N=2; T_TMP=T_TMP-T_step;//убавляем 1 или 0.1 } else if (arr_max < 1024) { //нажатие третьей кнопки //третья кнопка увеличивает значение температуры button_N=3; T_TMP=T_TMP+T_step;//прибавляем 1 или 0.1 }//end if if (button_N >0 ) {// ставим флаг, что нажатие зафиксировано и кнопка находится в нажатом состоянии button_flag = 1;// нажатие зафиксировано }//end if Serial.print("Кнопка N: "); Serial.print (button_N); Serial.print (" Значение T_TMP: "); Serial.println(T_TMP); }//end if //когда массив полученных напряжений заполнен, анализируем. находим самое большое. }//end if // КОНЕЦ фиксируем событие // обработка и удержание кнопок для ускоренного ввода данных // берем определение номера кнопки из кода выше. Кстати, нажатие выше одно зафисксировано if (button_val >200 and time-start_time_pressed>2000 ) { // button_flag = 0; Serial.println("==== PRESSED ====="); Serial.print("key: "); Serial.print(button_N); Serial.print(" start time: "); Serial.print(start_time_pressed); Serial.print("millis: "); Serial.println(millis()); //if (button_N==1 ) {// фиксируем введенные //}else if (button_N==2 ) { T_TMP=T_TMP-T_step;//убавляем 1 или 0.1 }else if (button_N==3 ) { T_TMP=T_TMP+T_step;//прибавляем 1 или 0.1 }//end if Serial.print (" T_TMP: "); Serial.println(T_TMP); } //end if КОНЕЦ обработка и удержание кнопок для ускоренного ввода данных // когда нет сигнала и флаг имел значение 1, что кнопка нажата (в предыдущем цикле), меняем значение флага, что кнопка отпущена. ставим 0 if (button_val < 200 and button_flag == 1) { button_flag = 0; // Serial.print(butt); // Serial.println(" -- Button released"); } // End if //КОНЕЦ_______________БЛОК кнопок_______ if (millis() - timing > 500){ // Вместо 10000 подставьте нужное вам значение паузы timing = millis(); /**/ //_____________Температура Отбора__________ byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; // перенес наверх float T_real; if (!ds.search(addr)) { Serial.println("Это последний адрес датчика"); Serial.println(); ds.reset_search(); ///////// delay(250); return; } // End if Serial.print("ROM ="); for( i = 0; i < 8; i++) { Serial.write(' '); Serial.print(addr[i], HEX); } // End for if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC неправильная!"); return; } // End if Serial.println(); // первый байт в ROM определяет тип датчика switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); // DS18S20 или старые DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); // DS18B20 type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); // DS1822 type_s = 0; break; default: Serial.println("Датчик не является DS18x20 серией"); return; } // End if ds.reset(); ds.select(addr); ds.write(0x44); // подключение по трем проводам // ds.write(0x44, 1); // подключение по двум проводам //delay(1000); // задержка считывания показаний present = ds.reset(); ds.select(addr); ds.write(0xBE); // читаем временную память Serial.print(" Data = "); Serial.print(present, HEX); Serial.print(" "); for ( i = 0; i < 9; i++) { // используем 9 байт data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } // End for Serial.print(" CRC="); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); // Преобразование полученных данных int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } // End if } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } // End if T_real = (float)raw / 16.0; // Вывод данных в консоль Serial.print(" Температура = "); Serial.print(T_real); Serial.print(" градусов по Цельсию, "); //КОНЕЦ_____________Температура Отбора__________ /**/ //if (round(time/10000.0f)*10000==time*10000/10000){ // Serial.println(" xxx 1 sec "); // } // End if Serial.println ("10 seconds"); } // End if // ____________задаем условия начала отбора____________ // условие 1: отбор происходит, если температура находится в рамках от заданной начальной температуры (напр. 60*) и температуры спиртовой полки T_otbor + температура гистерезиса обычно 0.1-0.2 градуса // условие 2: однако, если температура скакнула выше спиртовой полки - температуры отбора T_otbor, то отбор включиться должен ровно по температуре отбора, без учета гистерезиса //round(T_real*10)/10 if ( T_real>=T_open_klapan and T_otbor>=T_real-0.06){ // условие 1 otbor_on=1;//ставим флаг, всем модулям, что отбор разрешон // }else if ( T_real>=round(T_open_klapan*10)/10 and T_otbor+gisteresis>=T_real and otbor_on==1){ // условие 2 }else if ( T_real>=T_open_klapan and T_otbor+gisteresis>=T_real and otbor_on==1){ // условие 2 otbor_on=1;//ставим флаг, всем модулям, что отбор разрешон }else{ otbor_on=0;//отбор запрещен } // End if //КОНЕЦ ____________задаем условия начала отбора____________ //_____________Дисплей__________ lcd.setCursor(0, 0);// устанавливаем курсор на 1-ю строку 1-й символ // lcd.print("Т отбора: "); // пишем текст // lcd.print(T_otbor); // указываем температуру при которой начнется отбор lcd.print("То"); // пишем текст //T_otbor=round(T_otbor*100)/10; //float temp=36.67; //long buf; //buf=temp*10; //366 //temp=buf; //366.0 //temp=temp/10; //36.6 //T_otbor=10.2; //round(T_otbor*10)/10.0f; lcd.print(T_otbor); // указываем температуру при которой начнется отбор lcd.print(" ТУ"); // пишем текст lcd.print(T_TMP); // указываем температуру при которой начнется отбор lcd.print(" "); // на всякий случай, что бы лишние символы не появлялись, если минус поставить, а потом убрать lcd.setCursor(0, 1);// устанавливаем курсор на 2-й строку 1-й символ //lcd.print("Ставим Т: " );// пишем текст //lcd.print(T_TMP); // указываем температуру которую будем устанавливать lcd.print("Т реал " );// пишем текст lcd.print(T_real); // указываем температуру которую будем устанавливать if ( otbor_on==1 ){ // если флаг начала отбора =1 включаем клапан через реле lcd.print(" On " );// пишем текст }else{ lcd.print(" Off" );// пишем текст } // End if //КОНЕЦ_____________Дисплей__________ //_____________Реле__________ if ( otbor_on==1 ){ // если флаг начала отбора =1 включаем клапан через реле digitalWrite(relayPin, LOW); // Включаем или выключаем реле (смотря что пришло после инверсии) //digitalWrite(relayPin, HIGH); }else{ //digitalWrite(relayPin, LOW); digitalWrite(relayPin, HIGH); } // End if //КОНЕЦ_____________Реле__________ }// конец цикла