Управление обогревом комнаты при помощи Arduino и Dallas18B20

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Предвижу привычные вопросы по инкубации. Влажность измеряется психрометрическим методом по сухому и мокрому термометру. Датчики влажности существуют, знаю, они быстро пылью забиваются в инкубаторе, поэтому два термометра. Сама влажность не вычисляется (тогда не умел), но управляется по температуре влажного термометра. Насос слово условное, есть много способов повышения влажности. Часов там нет. Только таймеры. ПИД низкочастотный, с двухсекундной шириной окна. Корявок в коде много, и задержка на чтении температуры и влажности нет и меню с настройками не помешает и много ещё всего в планах. Вы на perepel.com заходите, мы там вопросы инкубации и автоматику обсасываем. На большую часть вопросов по инкубаторам там уже есть ответы. Не реклама, просто лениво писать одно и то же много раз. Спрашивайте что не понятно.

dachnik
Offline
Зарегистрирован: 26.07.2013

Всем привет, я год назад тоже делал термостат для комнаты. Управлял приточной вытяжкой при превышении температуру выше заданной и электрическим ковектором на 2кВт при понижении темп . Может будет кому интересен мой скеч... Что использовал: ардуино мини, хранение значений температурных пределов в eeprom, DHT11(свободного ds1820 не было), LCD2х16 I2C, три кнопки управления устройством, и пара твердотельных реле 40A из китая по 5$(вроде) каждая  с прикрученными к ним радиаторами от компьютерного процессора.

/* adress eeprom
 Темп
EEPROM 0 Минимальное значение температуры 
EEPROM 1 Максимальное значение темп

 Влажность
EEPROM 6 минимальная влажность
EEPROM 7 максимальная владность

*/

//LCD I2C 20x4
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2);
//LCD



//кнопка
// задаем константы кнопок и присваиваем им пины
const int buttonPin = 3;     // центральная кнопка
const int buttonPin_1 = 2;  //левая кнопка 
const int buttonPin_0 = 12;  //правая кнопка
const int ledPin =  13;      // номер выхода светодиода индикатора

// пины управления актуатором
const int rele_1 = 8; //охлаждение пином 
const int rele_2 = 11; //нагрев пином 
//const int rele_3 = 32; //Понижение влажности
//const int rele_4 = 33; //Повышение влажности


//
// глобальные переменные
int centreBtn = 0;         // переменная для хранения состояния центральной кнопки
int leftbtn = 0;     // переменная для хранения состояния левой кнопки
int rightbtn = 0;     // переменная для хранения состояния правой кнопки

int del = 500; // переменная ожидания между выборами меню(время горения ledpin в милисек)
//подсветка LCD

long previousMillis = 0;        // храним время
long interval_2 = 10000; //задержка подсветки

// интервал 
//переменные автовозврата в loop 
int interval = 50;    // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
//



//DHT SENSOR
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT11 //DHT11(синий датчик) DHT22(белый датчик)
DHT dht(DHTPIN, DHTTYPE); 
//DHT

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void setup() {
//LCD
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
lcd.init();   // initialize the lcd 
lcd.backlight();
//--LCD

// initialize the button pin as a input:

// initialize the LED as an output:
pinMode(ledPin, OUTPUT);


pinMode(rele_1, OUTPUT);
pinMode(rele_2, OUTPUT);

digitalWrite(rele_1, HIGH);
digitalWrite(rele_2, HIGH);




digitalWrite(ledPin, HIGH); 

    
// инициализируем пин, подключенный к кнопке, как вход
pinMode(buttonPin, INPUT);   
pinMode(buttonPin_0, INPUT);   
pinMode(buttonPin_1, INPUT);   


//DHT
dht.begin();
//DHT
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//#########################################################################################################
void loop() {

termostat();

lcd.setCursor(0,0);
  lcd.print("t= ");
//  lcd.print(temp_in());

//  lcd.print(" out= ");
  lcd.print(temp_out()); 
//  lcd.setCursor(0,1);
  lcd.print((char)223);
  lcd.print(" hum= "); 
  lcd.print(Humidity());
  lcd.print("%");  
//  lcd.print(end_irr_time);
  lcd.print("");  

  button_read(); //читаем кнопки // проверяем нажата ли кнопка
 
  if (centreBtn) {   // проверяем нажата ли кнопка если нажата, то 
//    LCD_LED = 1;
//    lcd.backlight();
    lcd.backlight();
    digitalWrite(ledPin, LOW);
    delay(del);// включаем светодиод   
    lcd.clear(); //очищаем экран
    digitalWrite(ledPin, HIGH);
    menu();
}

if (leftbtn) {   //включить подсветочку
   lcd.backlight(); 
     }     
if (rightbtn) {
    lcd.backlight(); 
//  heating(); 
} 

LCD_LED_OFF(); //таймер отключения подсветки



}
//##########################################################################################################33

void menu()
{
termostat_setup();
}

void termostat_setup()
{
int x =0;

  lcd.clear(); //очищаем экран

while(1){ // цикл 
x++;
if (x>interval){break;}

  button_read();

  lcd.setCursor(0,0);
//  lcd.print(" -=TERMOSTAT SETUP=- ");

  int t_mini = EEPROM.read(0);
//  lcd.setCursor(0,1);
  lcd.print("min = ");
  lcd.print(t_mini);
  lcd.print((char)223);

  int t_maxi = EEPROM.read(1);
  lcd.setCursor(11,1);
  lcd.print("max = ");
  lcd.print(t_maxi);
  lcd.print((char)223);                   

//  lcd.setCursor(0,2);
//  lcd.print("____________________");

//  lcd.setCursor(0,3);
//  lcd.print("T_MIN   NEXT   T_MAX");
  digitalWrite(ledPin, HIGH);
  
   
if (centreBtn) {   
 digitalWrite(ledPin, LOW);             
 delay(del);// включаем светодиод   
 lcd.clear(); //очищаем экран
 digitalWrite(ledPin, HIGH);
 break; }
                      
 if (leftbtn) {   
 digitalWrite(ledPin, LOW);             
   lcd.clear();
        t_min();
       delay(del);
       lcd.clear(); //очищаем экран
       x =0;   
       digitalWrite(ledPin, HIGH);            
       }       
    
if (rightbtn) {   
       digitalWrite(ledPin, LOW);             
       lcd.clear();
        t_max();
       delay(del);// включаем светодиод   
       lcd.clear(); //очищаем экран
       x =0;           
       digitalWrite(ledPin, HIGH);
      }  
  
 }}




//////--------------------------------------------------------------------------
//SUB MENU

void t_min()
{

lcd.clear(); //очищаем экран
delay(del);
while(1){ //бесконечный цикл 
button_read();

 lcd.setCursor(0,0);
 lcd.print(" TEMP MINIMUM SETUP");
 int t_min = EEPROM.read(0);
 lcd.setCursor(0,1);
 lcd.print("t = ");
 lcd.print(t_min);
 lcd.print((char)223);
 lcd.print("C");                   
 lcd.setCursor(0,3);
 lcd.print("t_min-1 NEXT t_min+1");
 lcd.setCursor(0,2);
 lcd.print("____________________");

 digitalWrite(ledPin, HIGH);
    if (centreBtn) {   
           digitalWrite(ledPin, LOW);             
           delay(del);// включаем светодиод   
           lcd.clear(); //очищаем экран
           digitalWrite(ledPin, HIGH);
           break;

           }
    
    if (rightbtn) {   
            delay(del);     
            digitalWrite(ledPin, LOW);             
            lcd.clear();
            EEPROM.write(0, t_min + 1);
            digitalWrite(ledPin, HIGH);            
           }       
        
    if (leftbtn) {   
          delay(del); 
          digitalWrite(ledPin, LOW);             
          lcd.clear();
          EEPROM.write(0, t_min - 1);
          digitalWrite(ledPin, HIGH);
          }  
 
 }
}

void t_max()
{

lcd.clear(); //очищаем экран
delay(del);
while(1){ //бесконечный цикл 
button_read();

 lcd.setCursor(0,0);
 lcd.print(" TEMP MAXIMUM SETUP");
 int t_max = EEPROM.read(1);
 lcd.setCursor(0,1);
 lcd.print("t = ");
 lcd.print(t_max);
 lcd.print((char)223);
 lcd.print("C");                   
 lcd.setCursor(0,3);
 lcd.print("t_max-1 NEXT t_max+1");
 lcd.setCursor(0,2);
 lcd.print("____________________");

 digitalWrite(ledPin, HIGH);
    if (centreBtn) {   
           digitalWrite(ledPin, LOW);             
           delay(del);// включаем светодиод   
           lcd.clear(); //очищаем экран
           digitalWrite(ledPin, HIGH);
           break;

           }
    
    if (rightbtn) {   
            delay(del);     
            digitalWrite(ledPin, LOW);             
            lcd.clear();
            EEPROM.write(1, t_max + 1);
            digitalWrite(ledPin, HIGH);            
           }       
        
    if (leftbtn) {   
          delay(del); 
          digitalWrite(ledPin, LOW);             
          lcd.clear();
          EEPROM.write(1, t_max - 1);
          digitalWrite(ledPin, HIGH);
          }  
 
 }
}


void button_read() //функция проверки нажатия кнопки
{
centreBtn = digitalRead(buttonPin); //запоминаем значение кнопки
rightbtn = digitalRead(buttonPin_0); //запоминаем значение кнопки
leftbtn = digitalRead(buttonPin_1); //запоминаем значение кнопки
}
void LCD_LED_OFF()//таймер отключения подсветки
{
  unsigned long currentMillis = millis();
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis - previousMillis > interval_2) {
   // сохраняем время последнего переключения
   previousMillis = currentMillis; 
 lcd.noBacklight();        
//  lcd.setCursor(0,3);
 // lcd.print("led");
 // if(r==0)
//      {lcd.print("led off"); r=1;  lcd.noBacklight();    } 
 // else if(r==1)//если кнопка НЕ нажата 
  //    {lcd.print("led on"); r=0;   lcd.backlight();     } 
}
}

float temp_in()
 {
   sensors.requestTemperatures(); // Send the command to get temperatures
  float in_tempC = sensors.getTempCByIndex(0);
return in_tempC;
}
*/
float temp_out()
 {
//   sensors.requestTemperatures(); // Send the command to get temperatures
//float out_tempC = sensors.getTempCByIndex(1);
//return out_tempC;
float out_tempC = dht.readTemperature();
return out_tempC;
 }

String on_or_off (int on_off)
{
int z = EEPROM.read(on_off);
  String x;
 if (z == 1) {x="ON";}
 if (z == 0) {x="OFF";}
 return x;
}

int termostat ()
{
int start = 1;
int stop =0;
  int temp_min = EEPROM.read(0);
int temp_max = EEPROM.read(1);
  if (temp_out() > temp_max ){digitalWrite(rele_1, LOW);}
  if (temp_out() < temp_max ){digitalWrite(rele_1,HIGH);}

//  {
//    cooling();
//  }

  if (temp_out() < temp_min ){digitalWrite(rele_2, LOW);}
  if (temp_out() > temp_min ){digitalWrite(rele_2, HIGH);}  
//  {
//  heating();
//  }
}

int Humidity()
{
int h = dht.readHumidity();
return h;
}

 

Cecenas
Offline
Зарегистрирован: 25.10.2014

Здрасте, что делать, неопазнают библиотеку EEPROM2.h

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Посмотрите на последнюю строчку в первом сообщении. Тамм ссылка на эту библиотеку. http://freeduino.ru/arduino/sample_EEPROM.html

yucan
Offline
Зарегистрирован: 20.04.2015

Не могу никак избавиться от ошибки компиляции, подскажите пожалуйста - что не так?

NE_XT
NE_XT аватар
Offline
Зарегистрирован: 22.05.2012

delay(750);

yucan
Offline
Зарегистрирован: 20.04.2015

NE_XT пишет:

delay(750);

Пробовал разные значения времени задержки - это ничего не  менят

Alexander
Offline
Зарегистрирован: 25.04.2010

NE_XT говорит точку с запятой после delay() поставьте

yucan
Offline
Зарегистрирован: 20.04.2015

Да, ошибочку не заметил, прошу прощения...поставил - ошибок ещё больше стало

Alexander
Offline
Зарегистрирован: 25.04.2010

Просто до тех ошибок не доходило, ломалось на строке delay без точки с запятойОтладка

yucan
Offline
Зарегистрирован: 20.04.2015

На бибилитеки ругалась дуина. Поставил версию 1.0.6 - нормально откомпилировалось. Спасибо всем!

SONIC300077
Offline
Зарегистрирован: 15.10.2013

Всем здравствуйте! очень интересный пост, несколько раз очень выручал, и соответственно многое для меня открыл, и так сказать вот решил поделится своим результатом, очень хотелось видеть PID регулятор в этом скетче, не знаю насколько правильно мне удалось воткнуть в изначальный код этого поста PID регулятор, так сказать судите сами, в принципе все работает, дальше хочется сделать небольшое меню чтобы параметры PID регулятора можно было выставлять в реальном времени, кому интересно присоединяйтесь!!!

// Термометр будет подключен на Pin2
#include <EEPROM2.h> // Подключаем библиотеку для работы с ARDUINO EEPROM
#include <PID_v1.h>
#include <LiquidCrystal.h>
#include <OneWire.h> // Подключаем библиотеку для работы с шиной OneWire
#include <DallasTemperature.h>//Подключаем библиотеку для работы с термометром66

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

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

//Создаем переменные для работы с термометром
DeviceAddress tempDeviceAddress;  //переменная для хранения адреса датчика

float temp1=0; //переменная для текущего значения температуры
int setTmp=0; // переменная для заданного значения температуры

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, 100, 5, 50, DIRECT); //0.000006 0.03 40  10 0.1 5

int WindowSize = 2000;
unsigned long windowStartTime;



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

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

//Реле подключено к пину D11
#define RELAY_PIN 11

//Объявим переменную для хранения состояния реле
boolean relayStatus1=LOW;

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

//Аналоговая клавиатура подключена к пину A0
#define KEYPAD_PIN A0
//Определим значения на аналоговом входе для клавиатуры 
#define ButtonUp_LOW 130
#define ButtonUp_HIGH 230
#define ButtonDown_LOW 300
#define ButtonDown_HIGH 360
#define ButtonLeft_LOW 480
#define ButtonLeft_HIGH 530
#define ButtonRight_LOW 0
#define ButtonRight_HIGH 80
#define ButtonSelect_LOW 730
#define ButtonSelect_HIGH 760

void setup() {
  
 windowStartTime = millis();
 
//Настроим пин для управления реле
  pinMode(RELAY_PIN,OUTPUT);
  digitalWrite(RELAY_PIN,LOW);


//Считаем из постоянной памяти заданную температуру
setTmp=EEPROM_read_byte(0); //Заданная температура будет храниться по адресу 0

//Инициализируем термодатчик и установим разрешающую способность 12 бит (обычно она установлена по умолчанию, так что последнюю строчку можно опустить)
  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(12);

  Setpoint = setTmp; //задаем температуру стабилизации

  myPID.SetOutputLimits(0, WindowSize); //задаем лимиты ширины ПИД-импульса от 0 до 1 секунды(full window size).
  myPID.SetMode(AUTOMATIC); //включаем ПИД-регулирование

//Настроим подсветку дисплея
 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.0      ");
  delay(2000);

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

//Очистим дисплей
  lcd.clear();//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() {

  int keyCode=0;

//выводим на дисплей заданное значение температуры  
  lcd.begin(16,2);
  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);}
} while (keyCode!=5 && keyCode!=4);
lcd.clear();
  delay(150);

//По клавише 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(750); // задержка для обработки информации внутри термометра, в данном случае можно не задавать

//Считывание значения температуры
  sensors.getAddress(tempDeviceAddress, 0);
  temp1=sensors.getTempC(tempDeviceAddress);
  Input =temp1;
// Вывод текущего значения температуры на дисплей
  lcd.setCursor(0, 0);
  lcd.print("  Current temp  ");
  lcd.setCursor(2, 1);
  lcd.print(temp1);
  lcd.print("  Set");
  lcd.setCursor(13, 1);
  lcd.print(setTmp);
}

//Проверка условия включения/выключения нагревателя
myPID.Compute();
unsigned long now = millis();

Setpoint = setTmp;
 /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  if (now - windowStartTime > WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
   //currentTime = millis(); 
  }
  if (Output > now - windowStartTime) digitalWrite(RELAY_PIN, HIGH);
 else digitalWrite(RELAY_PIN, LOW);

//if (temp1<setTmp&&relayStatus1==LOW){relayStatus1=HIGH; digitalWrite(RELAY_PIN,HIGH);}
//if (temp1>setTmp&&relayStatus1==HIGH){relayStatus1=LOW; digitalWrite(RELAY_PIN,LOW);}

// Опрос клавиатуры 
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(150);setTemperature();} //Переход к редактированию заданной температуры

}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

http://arduino.ru/forum/programmirovanie/termorezistor

Делал себе на дачу подобный девайс, только с ПИ законом. Работает с осени, проблем нет, под потери тепла подстраиваеться, сколько задал столько держит.
Датчик аналоговый, защита от перегрева заводская в конвекторе, а защиту по неисправности датчика пока не организовал.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Думаю что ПИД для отопления это слишком, ПИ достаточно.

agent01
Offline
Зарегистрирован: 29.10.2015

скажите а как сюда добавить 

DTH11 датчик

bwn
Offline
Зарегистрирован: 25.08.2014

agent01 пишет:

скажите а как сюда добавить 

DTH11 датчик

Не надо его добавлять. Гадкий он.((((

Slaiterx
Offline
Зарегистрирован: 05.05.2016

я бы тоже добавил dht11 датчик температуру внутри помещения мерить и по нему запускать всю систему и еще одно реле для включения циркуляционного насоса

Slaiterx
Offline
Зарегистрирован: 05.05.2016

вот и мой скетч готов с датчиком DHT11 и реле управлени насосом и русским языком на дисплее

#include "DHT.h"
#include <OneWire.h>
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );

byte L[8] = {
  0b00111,
  0b01001,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b00000
};
byte on[8] = {
  0b00110,
  0b01111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11110,
  0b01100
};
byte P[8] = {
  0b11111,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b00000
};
byte D[8] = {
  0b00111,
  0b01001,
  0b01001,
  0b01001,
  0b01001,
  0b11111,
  0b10001,
  0b00000
};
byte G[8] = {
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};
byte IKR[8] = {
  0b10101,
  0b10001,
  0b10011,
  0b10101,
  0b10101,
  0b11001,
  0b10001,
  0b00000
};
byte GB[8] = {
  0b11111,
  0b10001,
  0b10000,
  0b10000,
  0b10000,
  0b10000,
  0b10000,
  0b00000
};
#define  RELAY_1            11
#define  RELAY_2            12
#define  RELAY_3            13
#define  RELAY_PUMP         15     //// пин А1

OneWire ds(2);
DHT dht;

///////////////////////////////////////////////////////////

long previousMillis = 0;

float temp;
float temp_kotel;
float Temp_kotel_max = 80.0;
float Temp_pump = 30.0;
float Temp_ten = 20.0;
byte alarm_state = 0;

byte flag = 0;
byte A = 0;
byte menu = 0;
byte pos = 1;
byte count = 0;

//////////////////   кнопки  //////////////////////////////

#define LCD_KEY_PIN          A0

#define  KEY_NONE            255
#define  KEY_RIGHT           0
#define  KEY_UP              1
#define  KEY_DOWN            2
#define  KEY_LEFT            3
#define  KEY_SELECT          4

#define  key_0_val           50
#define  key_1_val           180
#define  key_2_val           380
#define  key_3_val           550
#define  key_4_val           800

byte lcd_key;
byte key = KEY_NONE;
int analogValue;


int lcd_key_pressed()
{
  analogValue = analogRead(LCD_KEY_PIN);
  delay(5);
  if (5 < abs(analogRead(LCD_KEY_PIN) - analogValue)) {
    return KEY_NONE;
  }
  key = lcd_get_key(analogValue);
}

int lcd_get_key(unsigned int input) {

  if (input < key_0_val) {
    return 0;
  }
  else if (input < key_1_val) {
    return 1;
  }
  else if (input < key_2_val) {
    return 2;
  }
  else if (input < key_3_val) {
    return 3;
  }
  else if (input < key_4_val) {
    return 4;
  }
  else {
    return KEY_NONE;
  }
}


void setup()

{
  Wire.begin();

  dht.setup(3);

  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT);
  pinMode(RELAY_3, OUTPUT);
  pinMode(RELAY_PUMP, OUTPUT);
   
   lcd.createChar(1, L);//Л
   lcd.createChar(2, on);//Знак включения
   lcd.createChar(3, P);//П
   lcd.createChar(4, D);//Д
   lcd.createChar(5, G);//Знак градуса
   lcd.createChar(6, IKR);//Й
   lcd.createChar(7, GB);//Г
   
   Temp_ten = EEPROM_float_read(10);
   Temp_pump = EEPROM_float_read(30);
   Temp_kotel_max = EEPROM_float_read(40);
  
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  EFIM DESIGN");
  lcd.setCursor(0, 1);
  lcd.print("   TEPMOCTAT   ");
  delay(5000);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("  ver 1.1 2016   ");
  delay(1500);
  lcd.clear();
  A = 0;
}

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 3000)
  {
    temp = dht.getTemperature();
    temp_kotel = getTemp();
    previousMillis = currentMillis;
  }
  if (alarm_state == 0)
  {
    if (A == 0)
    {
      if (menu == 0)
      {
        lcd.setCursor(0, 0);
        lcd.write(2);
        lcd.setCursor(0, 1);
        lcd.print(" ");
      }
      else if (menu == 1)
      {
        lcd.setCursor(0, 0);
        lcd.print(" ");
        lcd.setCursor(0, 1);
        lcd.write(2);
      }
      lcd.setCursor(1, 0);
      lcd.write(4);
      lcd.setCursor(2, 0);
      lcd.print("OM");
      lcd.setCursor(7, 0);
      lcd.print(temp, 1);
      lcd.setCursor(11, 0);
      lcd.write(5);
      lcd.setCursor(13, 0);
      lcd.print("H");
      lcd.setCursor(1, 1);
      lcd.print("KOTE");
      lcd.setCursor(5, 1);
      lcd.write(1);
      lcd.setCursor(7, 1);
      lcd.print(temp_kotel, 1);
      lcd.setCursor(11, 1);
      lcd.write(5);
      lcd.setCursor(13, 1);
      lcd.print("");
      lcd.setCursor(14, 1);
      lcd.print("");
      lcd.setCursor(15, 1);
      lcd.print("");
      if (temp >= Temp_ten - 1.0)
      {
        lcd.setCursor(13, 1);
        lcd.print(" ");
      }
      if (temp >= Temp_ten - 2.0)
      {
        lcd.setCursor(14, 1);
        lcd.print(" ");
      }
      if (temp >= Temp_ten - 3.0)
      {
        lcd.setCursor(15, 1);
        lcd.print(" ");
      }
      if (temp_kotel >= Temp_pump)
      {
        lcd.setCursor(15, 0);
        lcd.write(2);
      }
      else if (temp_kotel < Temp_pump)
      {
        lcd.setCursor(15, 0);
        lcd.print(" ");
      }
    }
    else if (A == 1)
    {
      lcd.setCursor(1, 0);
      lcd.print("TEM");
      lcd.setCursor(4, 0);
      lcd.write(3);
      lcd.setCursor(6, 0);
      lcd.print("BK");
      lcd.setCursor(8, 0);
      lcd.write(1);
      lcd.setCursor(10, 0);
      lcd.print("KOT");
      lcd.setCursor(13, 0);
      lcd.write(1);
      lcd.setCursor(14, 0);
      lcd.print("A");
      lcd.setCursor(6, 1);
      lcd.print(Temp_ten, 1);
      lcd.setCursor(10, 1);
      lcd.write(5);
    }
    else if (A == 2)
    {
      lcd.setCursor(0, 0);
      lcd.print("HACOC");
      lcd.setCursor(9, 0);
      lcd.print("KOTE");
      lcd.setCursor(13, 0);
      lcd.write(1);
      lcd.setCursor(1, 1);
      lcd.print(Temp_pump, 1);
      lcd.setCursor(5, 1);
      lcd.write(5);
      lcd.setCursor(10, 1);
      lcd.print(Temp_kotel_max, 1);
      lcd.setCursor(14, 1);
      lcd.write(5);

      if (pos == 1)
      {
        lcd.setCursor(0, 1);
        lcd.write(2);
        lcd.setCursor(9, 1);
        lcd.print(" ");
      }
      else if (pos == 10)
      {
        lcd.setCursor(0, 1);
        lcd.print(" ");
        lcd.setCursor(9, 1);
        lcd.write(2);
      }
    }
  }
  else if (alarm_state == 1)
  {
    digitalWrite(RELAY_1, LOW);
    digitalWrite(RELAY_2, LOW);
    digitalWrite(RELAY_3, LOW);
    Alarm();
  }



 

Slaiterx
Offline
Зарегистрирован: 05.05.2016

кто захочет выложу код целиком 

SONIC300077
Offline
Зарегистрирован: 15.10.2013

Slaiterx пишет:

кто захочет выложу код целиком 

Конечно выкладывай, для меня очень актуально !!

Slaiterx
Offline
Зарегистрирован: 05.05.2016

вечером буду дома залью на яндекс  диск

Slaiterx
Offline
Зарегистрирован: 05.05.2016
Slaiterx
Offline
Зарегистрирован: 05.05.2016

https://yadi.sk/d/kZBXIk5VsUpyv

с русским меню

Slaiterx
Offline
Зарегистрирован: 05.05.2016

https://yadi.sk/d/3dxrPRzbsUsAS

вот библиотеки

Slaiterx
Offline
Зарегистрирован: 05.05.2016

извиняйте что долго небыло времени

 

SONIC300077
Offline
Зарегистрирован: 15.10.2013

Спасибо за труд !

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

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

А нельзя выложить схему подключения? И мне нужно управление на  3 реле ( 3 фазы - котел + НАСОС).

Buldakov
Offline
Зарегистрирован: 17.01.2016

А почему нельзя купить специальный контроллер для нагревателя по цене платы?

Например такой:

http://ru.aliexpress.com/af/w1209.html?ltype=wholesale&d=y&origin=n&isVi...

Slaiterx
Offline
Зарегистрирован: 05.05.2016

по тому что наши руки не для скуки да и я себе зделал контролер котла с тремя тэнами и циркуляционным насосом где вы купите такую системму за 200р.

YURY_s
Offline
Зарегистрирован: 08.09.2016

Автору проэкта обогрев дачного домика pencraft.

Использовал ваш скетч ,  температуру показывает, а

кнопки не работают. Подскажите пожалуйста.

Slaiterx
Offline
Зарегистрирован: 05.05.2016

Кнопки резистивный нужно сканировать и прописывать свои параметры как показывает практика на одинаковых шилдах сопротивление на кнопках показывает разное

Slaiterx
Offline
Зарегистрирован: 05.05.2016

Да сейчас готова прошивка 1.2 скоро выложу изменения установлен более точный датчик dht22 и изменен порог включения тэн по личным ощущениям в доме стало комфортнее перепады температур ура свелись практически к нулю

Slaiterx
Offline
Зарегистрирован: 05.05.2016

В прошивке 1.3 будет добавлен датчик температуры на улице

Slaiterx
Offline
Зарегистрирован: 05.05.2016

схемма подключения прописана в скетче мой термостат как-раз расчитан на три тэна и насос

YURY_s
Offline
Зарегистрирован: 08.09.2016

Slaiterx пишет:
Кнопки резистивный нужно сканировать и прописывать свои параметры как показывает практика на одинаковых шилдах сопротивление на кнопках показывает разное

Здравствуйте. при сканировании нет нажатия-1023 Right-0 Up-133 Down-311 Left-484 Select-724

тогда как быть с этим:

01 #define ButtonUp_LOW 90
02 #define ButtonUp_HIGH 100
03 #define ButtonDown_LOW 240
04 #define ButtonDown_HIGH 280
05 #define ButtonLeft_LOW 390
06 #define ButtonLeft_HIGH 450
07 #define ButtonRight_LOW 0
08 #define ButtonRight_HIGH 50
09 #define ButtonSelect_LOW 620
10

#define ButtonSelect_HIGH 650

 

 

Slaiterx
Offline
Зарегистрирован: 05.05.2016

А почему вы думаете что оно должно быть все кнопки у вас просканировались записывайте свои данные по кнопкам и будет вам счастье

YURY_s
Offline
Зарегистрирован: 08.09.2016

в том то и проблемма, что ни какой реакции от кнопок кроме ресет. запускал проверочные скетчи, всё работает.

проблемма где-то в скетче. опыта не хватает. все равно надо разбираться.

Slaiterx
Offline
Зарегистрирован: 05.05.2016

специально для YURY_s https://drive.google.com/file/d/0B2PzzjsXTSYMV2NRWFdCempZaEU/view?usp=sharing с прописанными кнопками

Slaiterx
Offline
Зарегистрирован: 05.05.2016

https://drive.google.com/file/d/0B2PzzjsXTSYMUk9GTWZRX2V1SzA/view?usp=sharing версия 1.2 с датчиком DHT22 и улучшенным алгоритмом включения тэн

Slaiterx
Offline
Зарегистрирован: 05.05.2016

Нужно наверное создавать свою тему

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Я бы написал функцию колибровки кнопок. Допустим если при включении питания зажата любая кнопка (значения с АЦП менее 1023) то переходим к колибровке (поочередно просим пользователя нажимать кнопки соответствующие выводимым значениям (UP, DN, SET, и т.д.)  по окончании сохраняем в EEPROM. Для повторяимости девайса очень полезная былабы функция.

Slaiterx
Offline
Зарегистрирован: 05.05.2016

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

YURY_s
Offline
Зарегистрирован: 08.09.2016

Доброго времени! Спасибо за участие. Как уже писал , опыт пока маленький и логика в изначальном скетче мне не понятна. То что вы прислали, тут уже могу ориентироваться. немного ранее нашел вот это

// термостат, один датчик DS18B20, два выхода
// подробнее http://youtu.be/y62Ps_D9B1M
//
//  v 0.1 beta
 
#include <EEPROM.h>
#include <OneWire.h>
#include <LiquidCrystal.h>
 
#define OUT1 2 // выходы для реле 
#define OUT2 3
 
byte tempOUT1, tempOUT2;
 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
OneWire  ds(11); // 11 вход датчика 18b20
 
byte gradus[8] = {
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};
 
 
void erorr(){ // останавливает работу программы и сигнализирует ошибку
  digitalWrite(OUT1, LOW); // выключаем реле
  digitalWrite(OUT2, LOW);
    while(1){ // крутим бесконечный цикл
      digitalWrite(13, !digitalRead(13));
      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, LOW); // выключаем реле
  digitalWrite(OUT2, LOW);
 
  lcd.clear(); 
  lcd.setCursor(0, 0); // что нужно отрисовать один раз
  lcd.print("OUT1: ");
  lcd.setCursor(0, 1);
  lcd.print("OUT2: ");
  lcd.blink();
  
  while(1){ // крутим бесконечный цикл      
    byte KEY = key(); // читаем состояние кнопок
    
    lcd.setCursor(6, 0); // выводим на экран
    lcd.print(tempOUT1);
    lcd.write(1);
    lcd.print("C  ");
    lcd.setCursor(6, 1);
    lcd.print(tempOUT2);    
    lcd.write(1);
    lcd.print("C  ");
    
     ////// обработка кнопок 
    if (pos == 0){  // если в первой позиции
      lcd.setCursor(5, 0); // устанавливаем курсор
      if (KEY == 2) { // если нажата кнопка
        tempOUT1--;   // изменяем значение
        EEPROM.write(1, tempOUT1); // сохраняем в еепром
      }
      else if (KEY == 5){
        tempOUT1++;
        EEPROM.write(1, tempOUT1);     
      }    
    }
    if (pos == 1){ 
      lcd.setCursor(5, 1);
      if (KEY == 2) {
        tempOUT2--;
        EEPROM.write(2, tempOUT2);
      }
      else if (KEY == 5){
        tempOUT2++;
        EEPROM.write(2, tempOUT2);     
      }    
    }
    
    if (KEY == 3) pos--; // крутим позицию
    else if (KEY == 4) pos++;    
    if (pos > 1) pos = 0; 
 
   delay(200);
  }
}
 
float getTemp(){   // возвращает температуру с датчика
  byte data[12];   // и останавливает программу на секунду
  byte addr[8];  
  
  if (!ds.search(addr)) {
    lcd.clear();
    lcd.print("No sensor."); 
    erorr(); 
  }
  
  ds.reset_search(); 
 
  if (OneWire::crc8(addr, 7) != addr[7]) {
    lcd.clear();
    lcd.print("Sensor CRC erorr");
    erorr();   
  }
  
  ds.reset();            
  ds.select(addr);        
  ds.write(0x44);      
  delay(1000);   
  
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);          
 
  for (int i = 0; i < 9; i++) data[i] = ds.read(); 
  int raw = (data[1] << 8) | data[0]; // Переводим в температуру   
  if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];  
  
  return raw / 16.0;
}
 
void setup() {
//  Serial.begin(9600); 
  lcd.createChar(1, gradus);
  lcd.begin(16, 2);
  lcd.clear();
  
  pinMode(13, OUTPUT); 
  pinMode(OUT1, OUTPUT);
  pinMode(OUT2, OUTPUT);
  
  tempOUT1 = EEPROM.read(1); // читаем настройки 
  tempOUT2 = EEPROM.read(2); // из еепром
}
 
void loop() {  
  if (key() == 1) setMenu(); // если нажата селект, уходим в меню
  else if (key() == 4) analogWrite(10, 20); // если вниз, глушим подсветку
  else if (key() == 3) digitalWrite(10, HIGH);
  
  float temperature = getTemp(); // читаем температуру
 
  if (temperature < tempOUT1) digitalWrite(OUT1, HIGH); // сверяем температуру 
  else digitalWrite(OUT1, LOW);                         // и управляем выходами
  if (temperature < tempOUT2) digitalWrite(OUT2, HIGH);
  else digitalWrite(OUT2, LOW);
      
  lcd.setCursor(0, 0); /// вывод инфы на экран
  lcd.print("1:");
  lcd.print(tempOUT1);
  lcd.write(1);
//  lcd.print("C");
    if (digitalRead(OUT1)) lcd.print(" ON "); // показываем состояние выхода
    else lcd.print(" OFF");
  lcd.setCursor(0, 1);
  lcd.print("2:");
  lcd.print(tempOUT2);
  lcd.write(1);
    if (digitalRead(OUT2)) lcd.print(" ON ");
    else lcd.print(" OFF");    
    
  lcd.setCursor(9, 0); // показываем температуру с датчика
  lcd.print("|"); 
  lcd.print(temperature, 1);
  lcd.write(1);
  lcd.print("C");
  lcd.setCursor(9, 1);     
  lcd.print("|");  
}
Все прекрасно работает.  Памяти занимает 22%.  Надо только убрать точность датчика до градуса, без десяток. Хотя и так нормально. Вода обладает инерцией. 
надо наверно вот здесь  return raw / 16.0;  поставить  return raw / 16; 
Правильно думаю? Сейчас проверить не могу. Плата в работе , а отключать сейчас не охота.
А вообще мужики спасибо.
Slaiterx
Offline
Зарегистрирован: 05.05.2016
  lcd.setCursor(9, 0); // показываем температуру с датчика
  lcd.print("|"); 
  lcd.print(temperature, 1);//чтобы было без десятых нужно убрать еденицу
  lcd.write(1);
  lcd.print("C");
  lcd.setCursor(9, 1);     
  lcd.print("|");  
}
  lcd.setCursor(9, 0); // показываем температуру с датчика
  lcd.print("|"); 
  lcd.print(temperature);//получится так
  lcd.write(1);
  lcd.print("C");
  lcd.setCursor(9, 1);     
  lcd.print("|");  
}

 

YURY_s
Offline
Зарегистрирован: 08.09.2016

Спасибо!

Slaiterx
Offline
Зарегистрирован: 05.05.2016

Всегда пожалуйста

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

Slaiterx пишет:

https://yadi.sk/d/kZBXIk5VsUpyv

с русским меню

Добрый день!

Поставил Ваш скеч, но немогу ничего менять в настройках. Т.е выставить параметры, насос котел ит.д. хотя в них захожу. И еще непонятно вот эта строка "сначала загрузить этот код.

 выставив настройки и сохранив их (кнопка select)
 в сетапе раскомментировать кусок кода  и перезагрузить программу
 */
///////////////////////////////////////////////////
"
И еще , ставил 1.2.2 там температура сразустоавиться в 200 дома. правда у меня нкет DHT22 только 11.
Slaiterx
Offline
Зарегистрирован: 05.05.2016

Под dht11 надо менять и сканируйте кнопки на лсд шилде

Slaiterx
Offline
Зарегистрирован: 05.05.2016

Ничего уже раскоментировать не надо забыл убрать

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

Slaiterx пишет:
Под dht11 надо менять и сканируйте кнопки на лсд шилде

Извеяюсь, это как? Мои познания пока не очень глубокие.