Управление электрокотлом с тремя тэнами

XAM
Offline
Зарегистрирован: 01.03.2014

Прошу помощи новичку. Я переделал скетч с этого форума (http://arduino.ru/forum/proekty/upravlenie-obogrevom-komnaty-pri-pomoshchi-arduino-i-dallas18b20под нагревательный котел с 3 мя тэнами. При включений с интервалом в полсекунды включаюся 3 группы тэнов . При наборе заданной температуры выключаются. Как температура падает на 1 градус 1 тэн включается ,на 2-2 тэна ,на 3-3 тэна.И еще подцепил второй датчик для информаций улицы например.  Как ограничить возможную уставку температуры например от 15 до 75 и сделать шаг уставки 5. Как подцепить аналоговый вход чтоб при размыканий или замыканий выводил сообщение и отключал выходы. И еще можно как то убрать десятичные градусов в отображений?


// Подключаем библиотеку для работы с шиной OneWire
// Термометр будет подключен на Pin2
#include <OneWire.h>
OneWire oneWire(2);

//Подключаем библиотеку для работы с термометром
#include <DallasTemperature.h>

//Создаем объект sensors, подключенный по OneWire
DallasTemperature sensors(&oneWire);

//Создаем переменные для работы с термометром
DeviceAddress temp1DeviceAddress;//переменная для хранения адреса датчика
DeviceAddress temp2DeviceAddress; //второй информационный датчик 
float temp1=0; //переменная для текущего значения температуры 1
float temp2=0; //переменная для текущего значения температуры 2
int setTmp=0; // переменная для заданного значения температуры

//Подключаем LCD-дисплей
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//Подсветка управляется через пин D10
#define BACKLIGHT_PIN 10

//Создаем переменную для хранения состояния подсветки
boolean backlightStatus = 1;

// Подключаем библиотеку для работы с ARDUINO EEPROM
//Заданная температура будет храниться по адресу 0
#include <EEPROM2.h>

//Реле подключено к пину D11
#define RELAY1 11
#define RELAY2 12
#define RELAY3 13
//Объявим переменную для хранения состояния реле
boolean relayStatus1=LOW;
boolean relayStatus2=LOW;
boolean relayStatus3=LOW;

//Объявим переменные для задания задержки
long previousMillis1 = 0;
long interval1 = 2000; // интервал опроса датчиков температуры

//Аналоговая клавиатура подключена к пину A0
#define KEYPAD_PIN A0
//Определим значения на аналоговом входе для клавиатуры 
#define ButtonUp_LOW 140
#define ButtonUp_HIGH 145
#define ButtonDown_LOW 324
#define ButtonDown_HIGH 330
#define ButtonLeft_LOW 503
#define ButtonLeft_HIGH 509
#define ButtonRight_LOW 0
#define ButtonRight_HIGH 5
#define ButtonSelect_LOW 740
#define ButtonSelect_HIGH 745

void setup() {

//Настроим пин для управления реле
  pinMode(RELAY1,OUTPUT);
  pinMode(RELAY2,OUTPUT);
  pinMode(RELAY3,OUTPUT);
  digitalWrite(RELAY1,LOW);
  digitalWrite(RELAY2,LOW);
  digitalWrite(RELAY3,LOW);

//Считаем из постоянной памяти заданную температуру
  setTmp=EEPROM_read_byte(0);
  
//Инициализируем термодатчик и установим разрешающую способность 12 бит 
//(обычно она установлена по умолчанию, так что последнюю строчку 
//можно опустить)
  sensors.begin();
  sensors.getAddress(temp1DeviceAddress, 0);
  temp1=sensors.getTempC(temp1DeviceAddress);
  sensors.getAddress(temp2DeviceAddress, 1);
  temp2=sensors.getTempC(temp2DeviceAddress);

 // sensors.setResolution(12);
    
//Настроим подсветку дисплея
  pinMode(BACKLIGHT_PIN, OUTPUT);
  digitalWrite(BACKLIGHT_PIN, backlightStatus);

//Выведем на дисплей стартовое сообщение на 2 секунды
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Temp. Controller");
  lcd.setCursor(0, 1);
  lcd.print("      v1.1      ");
  delay(1500);

// выведем на дисплей заданное значение температуры на 2 секунды
  lcd.setCursor(0, 1);
  lcd.print("  Set temp:     ");
  lcd.setCursor(12,1);
  lcd.print(setTmp);
  delay(1500);

//Очистим дисплей
  lcd.begin(16, 2);
}

//Определим функцию для опроса аналоговой клавиатуры
//Функция опроса клавиатуры, принимает адрес пина, к которому 
//подключена клавиатура, и возвращает код клавиши:
// 1 - UP
// 2 - DOWN
// 3 - LEFT
// 4 - RIGHT
// 5 - SELECT

int ReadKey(int keyPin)
{
 int KeyNum=0;
 int KeyValue1=0;
 int KeyValue2=0;

//Читаем в цикле аналоговый вход, для подавления дребезга 
//и нестабильности читаем по два раза подряд, пока значения 
//не будут равны.
//Если значения равны 1023 – значит не была нажата ни  одна клавиша.

do {
KeyValue1=analogRead(keyPin);
 KeyValue2=analogRead(keyPin);
 } while (KeyValue1==KeyValue2&&KeyValue2!=1023);

//Интерпретируем полученное значение и определяем код нажатой клавиши
 if (KeyValue2<ButtonUp_HIGH&&KeyValue2>ButtonUp_LOW) {KeyNum=1;}//Up
 if (KeyValue2<ButtonDown_HIGH&&KeyValue2>ButtonDown_LOW) {KeyNum=2;}//Down
 if (KeyValue2<ButtonLeft_HIGH&&KeyValue2>ButtonLeft_LOW) {KeyNum=3;}//Left
 if (KeyValue2<ButtonRight_HIGH&&KeyValue2>ButtonRight_LOW) {KeyNum=4;}//Right
 if (KeyValue2<ButtonSelect_HIGH&&KeyValue2>ButtonSelect_LOW) {KeyNum=5;}//Select

//Возвращаем код нажатой клавиши
return KeyNum;
}

//Определим процедуру редактирования заданной температуры
//Вызывается по нажатию клавиши Select, отображает на дисплее 
//заданную температуру и позволяет изменять ее клавишами Up и Down

void setTemperature() 

{
 lcd.begin(16,2);
  int keyCode=0;

//выводим на дисплей заданное значение температуры  

  lcd.setCursor(0, 0);
  lcd.print("  Setting temp  ");
  lcd.setCursor(7, 1);
  lcd.print(setTmp);

//Опрашиваем клавиатуру, если нажата клавиша Up увеличиваем 
//значение на 1, если Down – уменьшаем на 1
//Если нажаты клавиши Select или Right – цикл опроса прерывается
//Задержки введены для борьбы с дребезгом, если клавиши срабатывают 
//четко – можно уменьшить время задержек или вообще их убрать
  do 
  {
  keyCode=ReadKey(KEYPAD_PIN);
  if (keyCode==1){setTmp++;delay(150);lcd.setCursor(7, 1);lcd.print(setTmp);}
  if (keyCode==2){setTmp--;delay(150);lcd.setCursor(7, 1);lcd.print(setTmp);}
  //lcd.begin(16,2);
} 
  while (keyCode!=5 && keyCode!=4);
  
  delay(200);
//lcd.begin(16, 2);
//По клавише Select – созраняем в EEPROM измененное значение
//По клавише Right – восстанавливаем старое значение
if (keyCode==5) {EEPROM_write_byte(0, setTmp);}
if (keyCode==4) {setTmp = EEPROM_read_byte(0);}
}

void loop() {

//Модуль опроса датчиков и получения сведений о температуре
//Вызывается 1 раз в секунду
  unsigned long currentMillis1 = millis();
if(currentMillis1 - previousMillis1 > interval1) {
    previousMillis1 = currentMillis1;  

//Запуск процедуры измерения температуры
 // sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  //sensors.setWaitForConversion(true);

//Delay(250) // задержка для обработки информации внутри термометра, 
//в данном случае можно не задавать

//Считывание значения температуры
  sensors.getAddress(temp1DeviceAddress, 0);
  temp1=sensors.getTempC(temp1DeviceAddress);
  sensors.getAddress(temp2DeviceAddress, 1);
  temp2=sensors.getTempC(temp2DeviceAddress);

// Вывод текущего значения температуры на дисплей
  lcd.setCursor(0, 0);
  lcd.print("Current");
  lcd.setCursor(0, 1);
  lcd.print("T=");
  lcd.print(temp1);
  lcd.print("C");
  lcd.setCursor(9, 1);
  lcd.print("Ty");
  lcd.print(temp2);

}

//Проверка условия включения/выключения нагревателя
if (temp1<setTmp&&relayStatus1==LOW)
{relayStatus1=HIGH; digitalWrite(RELAY1,HIGH);
lcd.setCursor(10, 0);
lcd.print("P= 35%");}
if (temp1>setTmp&&relayStatus1==HIGH)
{relayStatus1=LOW; digitalWrite(RELAY1,LOW);
lcd.setCursor(10, 0);
lcd.print("P=  0%");
}
delay(500);
if (temp1+1<setTmp&&relayStatus2==LOW)
{relayStatus2=HIGH; digitalWrite(RELAY2,HIGH);
lcd.setCursor(10, 0);
lcd.print("P= 70%");}
if (temp1>setTmp&&relayStatus2==HIGH)
{relayStatus2=LOW; digitalWrite(RELAY2,LOW);
//lcd.begin(10, 2);
}
delay(500);
if (temp1+2<setTmp&&relayStatus3==LOW)
{relayStatus3=HIGH; digitalWrite(RELAY3,HIGH);
lcd.setCursor(10, 0);
lcd.print("P=100%");}
if (temp1>setTmp&&relayStatus3==HIGH)
{relayStatus3=LOW; digitalWrite(RELAY3,LOW);
//lcd.begin(16, 2);
}
delay(200);
// Опрос клавиатуры 
int Feature = ReadKey(KEYPAD_PIN);

//Включение подсветки
if (Feature==1 ) 
{backlightStatus=1;digitalWrite(BACKLIGHT_PIN, backlightStatus);} 

//Отключение подсветки
if (Feature==2 ) 
{backlightStatus=0;digitalWrite(BACKLIGHT_PIN, backlightStatus);} 

 //Переход к редактированию заданной температуры
if (Feature==5 ) 
{delay(200);setTemperature();
}
}
XAM
Offline
Зарегистрирован: 01.03.2014

И ещё можно ли сделать чтоб тэны в случайном порядке включались. (типа по моточасам) А не молотил всегда первый иногда второй а третий почти не включался.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Сделать можно все, надо только уметь и хотеть.

По уставке надо найти место, где , под if  код нажатой кнопки меняет переменную. Скажем после 160 строки. Там надо вместо ++ ставить = переменная +5. Для декремента -5. Для ограничений - в эти же ифы доп условие по &&.

по выводу смотрите в районе 204 строки. Надо добавить после temp, признак соответствующего форматирования вывода.

случайный порядок тэнов- заменить в начале дефайны реле на назначенные переменные. Добавить их переназначение в основном цикле по таймеру от миллис.

по аналоговому входу и размыканий/замыканий непонятно, что Вам нужно.

konan38
Offline
Зарегистрирован: 20.07.2016

Довели до ума?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вопрос: И еще можно как то убрать десятичные градусов в отображений?

Ответ : Использовать операцию приведение типов. Банально привести к целому числу. (int)

// Вывод текущего значения температуры на дисплей
  lcd.setCursor(0, 0);
  lcd.print("Current");
  lcd.setCursor(0, 1);
  lcd.print("T=");
  lcd.print((int)temp1);
  lcd.print("C");
  lcd.setCursor(9, 1);
  lcd.print("Ty");
  lcd.print((int)temp2);
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вопрос:И ещё можно ли сделать чтоб тэны в случайном порядке включались. (типа по моточасам) А не молотил всегда первый иногда второй а третий почти не включался.

Можно: используй millis() http://arduino.ru/Reference/Millis   Тоже в некотором смысле генератор псевдослучайных чисел.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

Можно: используй millis() http://arduino.ru/Reference/Millis   Тоже в некотором смысле генератор псевдослучайных чисел.

О_о - не перестаю открывать для себя новое и интересное! С каких это пор функция с линейным возвращаемым значением у нас стала "в некотором смысле генератор псевдослучайных чисел"? Да там в любом смысле, как эти смыслы не крути - не проходит.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Мда. DIYMan. А вы точно учились программировать?  Это же классика. Любой счетчик это генератор псевдослучайных чисел. Ключевое слова ПСЕВДО. Проблема счетчиков случайных чисел в том что бы вероятность выпадания каждого числа была равновероятна. А если они выподают последовательно, то вероятность выпадания каждой одинакова. Разумеется если взять 1000 случаев. Теория вероятности вам поможет.  Теперь если всеже хочется более менее случайное число выбрать. То откиньте старшие с помощью % и младшие / ,округлите до целого. И вуаля.  В данном случае топик стартеру не надо совсем уж случайные числа.  Есть еще проще. Первые тысячу обращений к температуре работают тены 1,2, 3 . Вторая тысяча 2,3,1. Третья тысяча 3,1,2. И дальше по кругу. Износ тенов равномерен. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

Мда. DIYMan. А вы точно учились программировать?  Это же классика. Любой счетчик это генератор псевдослучайных чисел. Ключевое слова ПСЕВДО. Проблема счетчиков случайных чисел в том что бы вероятность выпадания каждого числа была равновероятна. А если они выподают последовательно, то вероятность выпадания каждой одинакова. Разумеется если взять 1000 случаев. Теория вероятности вам поможет.  Теперь если всеже хочется более менее случайное число выбрать. То откиньте старшие с помощью % и младшие / ,округлите до целого. И вуаля.  В данном случае топик стартеру не надо совсем уж случайные числа.  Есть еще проще. Первые тысячу обращений к температуре работают тены 1,2, 3 . Вторая тысяча 2,3,1. Третья тысяча 3,1,2. И дальше по кругу. Износ тенов равномерен. 

Ещё один, понятно. Отошлю-ка я вас в википедию, пожалуй: https://ru.wikipedia.org/wiki/%D0%93%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80_%D0%BF%D1%81%D0%B5%D0%B2%D0%B4%D0%BE%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D1%8B%D1%85_%D1%87%D0%B8%D1%81%D0%B5%D0%BB

И плз - больше никому не говорите, что линейная последовательность чисел - это генератор ПСЕВДОслучайных чисел. Я вам даже выделил ваше псевдо-, хотя оно тут и ни к чему было.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Отвечу. МНОГА БУКВ. МАЛО ТОЛКА.  В те времена, когда начинали учится только по Бейсику, так и выкручивались.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

Отвечу. МНОГА БУКВ. МАЛО ТОЛКА.  В те времена, когда начинали учится только по Бейсику, так и выкручивались.

Это вы про что сейчас? Я привёл ссылку на совершенно точное определение генератора псевдослучайных чисел, millis() под это определение не попадает никак, о чём я вам и написал. Имейте смелость признавать свои ошибки. Если я где впарываю - я признаю, поверьте. И не упорствую в невежестве.

ВН
Offline
Зарегистрирован: 25.02.2016

кончай тупить,  DIYMan

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Разумеется для шифрования даных в среде Интернета millis() не годится. Но как генератор случайных чисел в простых, даже не сетевых игр , может справлятся вполне. Или в данном случае(ПОДЧЕРКИВАЮ) вполне обойтись дешевым аналогом. В крайнем случает то на то выйдет. Только разве объем программы возрастет. 

ПС: Напоминаю , сейчас мы беседуем на Форуме посвященым Ардуино и ее среды. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

Разумеется для шифрования даных в среде Интернета millis() не годится. Но как генератор случайных чисел

Ещё раз: давайте не называть millis() генератором случайных чисел, ок? Это как назвать белое чёрным. Я согласен с вами, что для каких-то применений оно сгодится, но это, при всём желании - не генератор ни случайных, ни псевдослучайных чисел.

С этим вы согласны?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ВН пишет:

кончай тупить,  DIYMan

Тупишь тут только ты.

uno
Offline
Зарегистрирован: 16.06.2016

Может проще задать когда нужен 1 тен работает 1. если нужно 2 -работает 2-3. 1 отдыхает. Раз в год, два всеравно ревизию надо делать 1 с 2-3 меняем местами. хотя и так износ довольно равномерный должен получиться.

ВН
Offline
Зарегистрирован: 25.02.2016

 qwone  о сути дела написал справедливо и из-за особо прикапывающихся ко всяким синтаксисам, без понимания сути,  нет смысла отказываться от работающего алгоритма. 

konan38
Offline
Зарегистрирован: 20.07.2016

Извените что вмешиваюсь, а кто схему подключения может нарисовать? и правильный, поправленный скеч? Тоже хочеться управлять дома электрокотлом. Эта версия помоемому самая подходящая, и я правильно понимаю что тут используется Шильд LCD+Keypad от DFRobot?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Нарисовать я программу и схему могу. Но код будет кривоват, да надо будет ловить ошибки , что в схеме, что в программе.  Шилд у меня есть, а вот датчиков, электрокотла у меня нет. Так что код и схема будет на страх самого собравшего и запустившего.

konan38
Offline
Зарегистрирован: 20.07.2016

Добрый день!

Шилд, датчики все это есть, давайте попробую.

konan38
Offline
Зарегистрирован: 20.07.2016

Доброго времени суток!

Тема заглохла? А очень востребованна.

uno
Offline
Зарегистрирован: 16.06.2016

konan38 пишет:

Доброго времени суток!

Тема заглохла? А очень востребованна.

Надумано тут все. А почему сразу 3 не включить, не на минуту, а на 20 сек? Вот при мощности в обрез отслеживать какой ток потребляется остальными потребителями и вырубать лишнии тены ИМХО гораздо востребованей. чтобы не думать могу я влючить утюг, при работающей стиралке и потом по темноте идти включать автоматы.

konan38
Offline
Зарегистрирован: 20.07.2016

Да мне бы хотябы рабочую версию. Попробовать хочеться.

konan38
Offline
Зарегистрирован: 20.07.2016

Идея то очень замечательная.

uno
Offline
Зарегистрирован: 16.06.2016

konan38 пишет:

Идея то очень замечательная.

Тут есть простенькая схема http://vrtp.ru/index.php?showtopic=25364. В общемто управлять больше насосом нужно регулировать скорость циркуляцию теплоносителя. ставить 3 ходовой клапан который будет определять обратка пришла достаточно теплая чтобы пустить ее на второй круг циркуляции или к ней нужно подмешать теплой воды, а обратку пустить в котел. Идея не дает нужного эфекта не экономит электроинергию, не дает поддерживать стабильную температуру в комнате. точнее дает но очень неэффиктивно.

smax2004
Offline
Зарегистрирован: 11.09.2021

Может кто то подсказать,у меня по чему то при копировании текста и переносе в IDE  вылазит одна и таже ошибка ,  связанная c  EEprom

/Считаем из постоянной памяти заданную температуру
  setTmp=EEPROM_read_byte(1);//Температура
 
EEprom ('EEPROM_read_byte' was not declared in this scope).

Или в другой версии скетча вылезает ошибка 

if (keyCode==4) {setTmp = EEPROM_read_byte(0);}

{setTmp = EEPROM_read_byte(0);} was not declared in this scope
Копировал текст программы с разных источников , итог один.

 

 
ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

потому что 'EEPROM_read_byte' was not declared in this scope