Использование логической функции "И", почему не работает.
- Войдите на сайт для отправки комментариев
Ср, 19/09/2018 - 01:20
Здравствуйте уважаемые форумчане, вопрос по поводу использования "И" для термостата теплого пола. Написал функцию сработки термостата по двум температурам, то есть если температура там и там больше заданых порогов то должно сработать реле. Выделил где использую логический оператор, может просто я записал данное сравнение не правильно, хотя пробовал много разных вариантов.
#include <EEPROM.h> #include <OneWire.h> #include <LiquidCrystal.h> #include <DallasTemperature.h> #define OUT1 2 // выходы для реле #define OUT2 3 #define ONE_WIRE_BUS_1 A1 #define ONE_WIRE_BUS_2 A2 #define ONE_WIRE_BUS_3 A3 OneWire oneWire_1(ONE_WIRE_BUS_1); OneWire oneWire_2(ONE_WIRE_BUS_2); OneWire oneWire_3(ONE_WIRE_BUS_3); DallasTemperature sensor_1(&oneWire_1); DallasTemperature sensor_2(&oneWire_2); DallasTemperature sensor_3(&oneWire_3); byte tempOUT1, tempOUT2, tempOUT3, tempOUT4; byte OUT3; byte tempOUT5 = 29; LiquidCrystal lcd(8, 9, 4, 5, 6, 7); byte gradus[8] = { 0b00110, 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }; byte bykvaPE [8] = { 0b00000, 0b00000, 0b11111, 0b10001, 0b10001, 0b10001, 0b10001, 0b00000 }; byte bykvaL[8] = { 0b00000, 0b00000, 0b01111, 0b00101, 0b00101, 0b10101, 0b01001, 0b00000 }; byte bykvaU[8] = { 0b00000, 0b00000, 0b10001, 0b10001, 0b11001, 0b10101, 0b11001, 0b00000 }; byte bykvaii[8] = { 0b00000, 0b01010, 0b00100, 0b10001, 0b10011, 0b10101, 0b11001, 0b00000 }; void outOff(){ // выключает выходы digitalWrite(OUT1, HIGH); // выключаем реле digitalWrite(OUT2, HIGH); } void erorr(){ // останавливает работу программы и сигнализирует ошибку outOff(); // выключаем выходы lcd.clear(); lcd.print("sensor error"); while(1){ // крутим бесконечный цикл analogWrite(10, 0); delay(500); analogWrite(10, 255); delay(500); } } byte key(){ //// для кнопок ЛСДшилда int val = analogRead(0); if (val < 50) return 5; else if (val < 150) return 3; else if (val < 350) return 4; else if (val < 500) return 2; else if (val < 800) return 1; else return 0; } //// void setMenu(){ // установка температуры byte pos; digitalWrite(OUT1, HIGH); // выключаем реле digitalWrite(OUT2, HIGH); lcd.clear(); lcd.setCursor(0, 0); // что нужно отрисовать один раз lcd.print("1B:"); lcd.setCursor(0, 1); lcd.print("2B:"); lcd.setCursor(8, 0); lcd.print("1H:"); lcd.setCursor(8, 1); lcd.print("2H:"); lcd.blink(); while(1){ // крутим бесконечный цикл byte KEY = key(); // читаем состояние кнопок lcd.setCursor(3, 0); // выводим на экран lcd.print(tempOUT1); lcd.write(1); lcd.print("C "); lcd.setCursor(3, 1); lcd.print(tempOUT2); lcd.write(1); lcd.print("C "); lcd.setCursor(11, 0); lcd.print(tempOUT3); lcd.write(1); lcd.print("C "); lcd.setCursor(11, 1); lcd.print(tempOUT4); lcd.write(1); lcd.print("C "); ////// обработка кнопок if (pos == 0){ // если в первой позиции lcd.setCursor(3, 0); // устанавливаем курсор if (KEY == 2) { // если нажата кнопка tempOUT1--; // изменяем значение EEPROM.write(1, tempOUT1); // сохраняем в еепром } else if (KEY == 5){ tempOUT1++; EEPROM.write(1, tempOUT1); } } if (pos == 1){ lcd.setCursor(3, 1); if (KEY == 2) { tempOUT2--; EEPROM.write(2, tempOUT2); } else if (KEY == 5){ tempOUT2++; EEPROM.write(2, tempOUT2); } } if (pos == 2){ // если в третей позиции lcd.setCursor(11, 0); // устанавливаем курсор if (KEY == 2) { // если нажата кнопка tempOUT1--; // изменяем значение EEPROM.write(3, tempOUT1); // сохраняем в еепром } else if (KEY == 5){ tempOUT3++; EEPROM.write(3, tempOUT3); } } if (pos == 3){ // если в четвертой позиции lcd.setCursor(11, 1); // устанавливаем курсор if (KEY == 2) { // если нажата кнопка tempOUT4--; // изменяем значение EEPROM.write(1, tempOUT4); // сохраняем в еепром } else if (KEY == 5){ tempOUT4++; EEPROM.write(4, tempOUT4); } } if (KEY == 3) pos--; // крутим позицию else if (KEY == 4) pos++; if (pos > 3) pos = 0; delay(200); } } void setup() { lcd.createChar(1, gradus); lcd.createChar(2, bykvaPE); lcd.createChar(3, bykvaL); lcd.createChar(4, bykvaU); lcd.createChar(5, bykvaii); lcd.begin(16, 2); lcd.print("Te"); lcd.write (2); lcd.write (3); lcd.write (4); lcd.write (5); lcd.print(" "); lcd.write (2); lcd.print("o"); lcd.write (3); lcd.setCursor(0, 1); lcd.print("AndryGladky 2018"); delay(10000); pinMode(OUT1, OUTPUT); pinMode(OUT2, OUTPUT); tempOUT1 = EEPROM.read(1); // читаем настройки tempOUT2 = EEPROM.read(2); // из еепром tempOUT3 = EEPROM.read(3); tempOUT4 = EEPROM.read(4); } void loop() { sensor_1.requestTemperatures();// читаем температуру 1 датчик sensor_2.requestTemperatures();// читаем температуру 2 датчик sensor_3.requestTemperatures();// читаем температуру 2 датчик if (key() == 1) setMenu(); // если нажата селект, уходим в меню else if (key() == 4) analogWrite(10, 0); // если вниз, глушим подсветку else if (key() == 3) digitalWrite(10, HIGH); float temperature1 = sensor_1.getTempCByIndex(0); float temperature2 = sensor_2.getTempCByIndex(0); float temperature3 = sensor_3.getTempCByIndex(0); if (temperature1 < -125) erorr (); if (temperature1 < -125) erorr (); if (temperature1 < -125) erorr (); // сверяем температуру и управляем выходами if (temperature1 < tempOUT3 && temperature3 > tempOUT5) digitalWrite(OUT1, LOW); else if (temperature1 > tempOUT1) digitalWrite(OUT1, HIGH); if (temperature2 < tempOUT4) digitalWrite(OUT2, LOW); else if (temperature2 > tempOUT2) digitalWrite(OUT2, HIGH); if (temperature3 > tempOUT5) OUT3 = LOW; else OUT3 = HIGH; lcd.setCursor(0, 0); /// вывод инфы на экран lcd.print(temperature3, 1); lcd.write(1); // показываем состояние выхода if (digitalRead(OUT1)) lcd.print(" OFF"); else lcd.print(" ON "); lcd.setCursor(0, 1); if (OUT3) lcd.print(" OFF"); else lcd.print(" ON "); if (digitalRead(OUT2)) lcd.print(" OFF"); else lcd.print(" ON "); lcd.setCursor(9, 0); // показываем температуру с датчика lcd.print("|"); lcd.print(temperature1, 1); lcd.write(1); lcd.print("C"); lcd.setCursor(9, 1); lcd.print("|"); lcd.print(temperature2, 1); lcd.write(1); lcd.print("C"); }
Словами Вы пишете "больше", а в сравнении фигурирует "<".
PS Лично я всегда забываю приоритет операций, поэтому везде ставлю скобки.
Вы сраниваете переменную типа byte c переменной float. Возможно проблема в этом. У меня что такое было. Привел оба чила к int и потом сравнил. Все заработало.
Попробовал две переменные написать float, два сравнения тоже написал в скобках.
Попробовал две переменные написать float, два сравнения тоже написал в скобках.
И?
Забыл написать и нечего не изменилось как работало так и работает, вторая температура в одном условии не влияет на включение или выключение реле
if
((temperature1 < tempOUT3) && (temperature3 > tempOUT5)){ digitalWrite(OUT1, LOW);}
if
(temperature1 > tempOUT1) {digitalWrite(OUT1, HIGH);}
как то так, но переменные у вас разные (все флоат чтоль сделайте, но я делал структуру и хранил отдельно целую и сотые части, вроде удобнее и общитывает без запятой), дополните выводом в сериал переменных и смотрите что получается, надо посмотреть какие там значениия и подумать как код работает
AndryGladky - во-первых, как вам уже сказали, приведите все переменные temperature1, 2 и 3 и все свои tempOUT к одному общему подходящему типу. Я сильно сомневаюсь, что тип byte тут подходит - надо либо float для работы плавающей точкой, либо, к примеру домножить все температуры на 10 или 100, чтобы работать с целыми - то есть 27.4 С это будет значение 274 (тип int)
Во-вторых, поскольку у вас три температуры и 6 температурных пределов - значит алгоритм кода нетривиальный, так что вполне вероятно, что ошибка у вас не в синтаксисе, а в логике программы. В этом вам нужно разобраться самому. Я бы посоветовал временно выкинуть из кода все, не относящееся к логике термостата - работу с дисплеем и прочее - и для начала добится, чтобы все условия отрабатывали правильно.
Спасибо буду пробовать, да и на счёт домножить на 10 я как то забыл, а раньше делал так.
Сброшу весь код может кому пригодится.
AndryGladky, что, меню "безвыходное" или я что-то проглядел? Сделать кнопку "выход", заодно по ней и записывать установленные значения в еепром, а не по каждому тыку в кнопки плюс/минус.
kalapanga, так паршиво спроектирована программа. Вот косяки ТС и проникли в программу.
Здравствуйте, при работе устройства возникли некоторые вопросы по программе. Хочу сделать выход с меню но не знаю как реализовать, подскажите или дайте ссылку где почитать. И еще одна проблема почему то при достижении температуры теплого пола установленного верхнего порога допустим 30 градусов при изменении температуры 29.9 - 30 щелкает реле туда сюда включая выключая насос, как сделать так что бы если температура достигла один раз 30 градусов насос выключился и больше не включался пока не опустится до нижнего порога. Я не могу понять почему так происходит, может условие как то по другому записать. Буду рад любым советам.
при достижении температуры теплого пола установленного верхнего порога допустим 30 градусов при изменении температуры 29.9 - 30 щелкает реле туда сюда включая выключая насос,
Это называется гистерезис.
Чтобы реле не щелкало в районе 30 градусов - нужно два условия. Одно для выключенного насоса - он не должен включатся, пока температура выше нижнего предела. Другое условие для включенного насоса - он не должен выключатся, пока температура не достигла верхнего предела.
Здравствуйте, при работе устройства возникли некоторые вопросы по программе. Хочу сделать выход с меню но не знаю как реализовать, подскажите или дайте ссылку где почитать.
Цикл http://arduino.ru/Reference/While . В качестве условия используете булев флаг, который изменяется внутри цикла по требуемому условию или таймауту.
qwone - как Вы изменились :) Полтора года назаД. когда я пришел на форум - вы каждому новичку тут же выдавали готовый код. Может не очень понятный, закрученный на классах - но работающий. Теперь - только порцию трепа... :)
Не принимайте к сердцу - шутка.
Да на счёт меню спасибо я понял, я много посмотрел примеров то там меню написано отдельно программа отдельно, но ладно для этого проекта мне и так сгодится. А на счёт цыкла while он проверяет значение пока не выполнится условие, а если температура прыгает 29.9 - 30 раз в пол секунды потому что бетонный пол не может резко нагрется, он будет работать етот цикл как триггер при одноразовом повышении до 30 градусов просто выключит насос, хоть и температура упадет на 29,9.
А на счёт цыкла while он проверяет значение пока не выполнится условие, а если температура прыгает 29.9 - 30 раз в пол секунды потому что бетонный пол не может резко нагрется, он будет работать етот цикл как триггер при одноразовом повышении до 30 градусов просто выключит насос, хоть и температура упадет на 29,9.
сами же пишете, что реле щелкает туда-сюда - значит ваш "триггер" нифига не работает. Вы бы не спорили, а слушали советы
Когда писал про While, вообще то имел в виду меню. В гистерезисе он и нах не нужен.
b707, вот вам ЕвгенийП целую тему консультацию по ЦА выделил. Так что в этой теме должны уже рулить. Так что объясните ТС, может тогда и сами поймете.
Есть такая программистакая штука как цифровой автомат. У вас ЦА на два состояния ВКЛ насос/ ВЫКЛ насос. А дальше надо прописать состояния перехода.
b707, вот вам ЕвгенийП целую тему консультацию по ЦА выделил. Так что в этой теме должны уже рулить. Так что объясните ТС, может тогда и сами поймете.
я уже ТС все обьяснил
Чтобы реле не щелкало в районе 30 градусов - нужно два условия. Одно для выключенного насоса - он не должен включатся, пока температура выше нижнего предела. Другое условие для включенного насоса - он не должен выключатся, пока температура не достигла верхнего предела.
Вот это простой автомат, но выраженый в коде
Плюс всего этого в том что это можно по размому модернизировать.
Попробуем переписать скетч который выше
А теперь к нему добавим условие что переключаться должно если температура держится к примеру 2 секунды.
Спасибо большое, я понял, буду разбиратся. Просто с более сложными программами как то не особо часто стыкаюсь, но как всегда надо стремиться учиться, спасибо вам большое за помощь.
Здравствуйте, изучил много прочитал статей про использование цифрового автомата переписал код под свою задачу но, почему то не работает, снова щелкает реле, не могу понять почему так происходит, вроде написал все правильно, но а почему то не работает. Может где ошибку какую допустил, не могу понять. Подскажите или ткните где не правильно. Где использовал функцию автомата, выделил строки.
похоже мало читали статей. Попробуйте увеличить объем прочитаных статей раз в 10. У вас (!!) две независимые задачи. 1- что бы устройство работало без человека и 2- а если человеку хочется , то дать ему возможность порулить. Их надо и разделить и главное не смешивать при написании кода.
Как минимум так
Согласен что должно быть отдельно, но устройством я управлять не хочу, а только задавать пороги срабатывания. Или это и есть разделение?