Форум обсуждения систем  

Вернуться   Форум обсуждения систем "Умный дом", проектов Ардуино, OpenWRT и других DIY устройств > Форум умного дома > Сделай сам

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
Старый 27.03.2014, 21:48   #1
kirex
Member
 
Регистрация: 24.03.2014
Сообщений: 38
Вес репутации: 0
kirex is an unknown quantity at this point
По умолчанию Акваконтроллер

Что имеется:
Arduino Mega 2560
LCD Keypad Shield 1602 c 5-ю кропками
Блок реле (двухканальное)
Часы DS1307 Tiny RTC I2C module, 24C32 EEPROM
Датчик температуры DS18B20

LCD Keypad Shield подключен к пинам 4,5,6,7,8,9, кнопки к А0, подсветка к 10 пину.
Датчик температуры DS18B20 подключен к пину 53.
Блок реле к пинам 40,41
К пинам 3,11,12 подключены LED через мосфеты.

1). Реле будут включать обогрев (назовём Н1 и Н2), т.е. Н1 управляется по 40 пину, а Н2 - по 41.
При температуре 28 включаются оба нагревателя. При достижении температуры 28,3 нагреватель Н1 отключается. При 28,5 отключается Н2.

2). LED подсветка (назовём LR – pin3, LW – pin11 и LB – pin12) включается и выключается по времени. Т.е. например в 17:00 плавно в течении 3 минут включается LW и LR, далее в 21:55 начинает плавно гаснуть ( минуты), а в это время плавно включается LB. Затем в 23:00 плавно гаснет (3 минуты) LB.

Главный экран отображает:

Т=28,4° 14:53
Н1-Off H2-On

т.е. отображается текущая температура, текущее время и состояние нагревателей.

Что ещё нужно: возможность включения и выключения света LW и LR кнопками (UP-Вкл., DOWN-Выкл.), независимо от времени. А также возможность включения и выключения нагревателя Н2 кнопками (LEFT-Вкл., RIGHT-Выкл.), независимо от температуры.

Вот код:
Код HTML:
#include <Wire.h>                                                                           //Подключаем библиотеку для использования I2C интерфейса с модулем RTC 
#include "RTClib.h"                                                                         //Подключаем библиотеку для использования модуля часов реального времени RTC

#include <OneWire.h>
#include <DallasTemperature.h>

// библиотека экрана
#include "LiquidCrystal.h" 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

OneWire  ds(53);  // Подключаем датчик к 53 цифровому пину

int lcd_key     = 0;
int adc_key_in  = 0;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);      // read the value from the sensor 
 // my buttons when read are centered at these valies: 0, 142, 328, 504, 741
 // we add approx 50 to those values and check to see if we are close
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result

 if (adc_key_in < 50)   return btnRIGHT;  
 if (adc_key_in < 250)  return btnUP; 
 if (adc_key_in < 400)  return btnDOWN; 
 if (adc_key_in < 600)  return btnLEFT; 
 if (adc_key_in < 850)  return btnSELECT;  
 return btnNONE;  // when all others fail, return this...
}


#define PWM_LW_MIN 0                                                                            //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LW_MAX 128                                                                          //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LW_PIN 11                                                                         //Пин порта, где будет ШИМ LW

#define PWM_LR_MIN 0                                                                            //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LR_MAX 200                                                                          //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LR_PIN 3                                                                           //Пин порта, где будет ШИМ LR

#define PWM_LB_MIN 0                                                                            //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LB_MAX 235                                                                          //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LB_PIN 12                                                                           //Пин порта, где будет ШИМ LB

#define mn 60UL                                                                              //Дополнительные константы для удобства
#define hr 3600UL                                                                            //Отражают соответствующие количества секунд 
#define d 86400UL

int Relay_Off = HIGH;
int Relay_On = LOW;

RTC_DS1307 RTC;          

long sunrise_start = 17*hr+00*mn;                                                             //Начало восхода в 9 - 45 
long sunrise_duration = 3*mn;                                                                //Длительность восхода 30 минут     
long sunset_start = 22*hr+00*mn;                                                              //начало заката в 21-15
long sunset_duration = 3*mn;                                                                  //Длительность заката 30 минут 
long moonrise_start = 22*hr+00*mn ;                                                           //Начало луны в 9 - 45
long moonrise_duration = 3*mn;                                                                  //Длительность восхода
long moonset_start = 23*hr+00*mn;                                                               //Конец луны в 11
long moonset_duration = 3*mn;                                                                   //Длительность заката луны
//********************************************************************************************
void setup(){

Serial.begin(9600);
     lcd.begin(16, 2); // запускаем библиотеку экрана
  pinMode(40, OUTPUT);  // Включаем кипятильник
  pinMode(41, OUTPUT);
  digitalWrite(40, Relay_On);  
  digitalWrite(41, Relay_On);
  Wire.begin();                                                                               //Инициируем I2C интерфейс
  RTC.begin();                                                                                //Инициирум RTC модуль
  analogWrite(PWM_LW_PIN, PWM_LW_MIN);                                                        //Пишем в порт минимальное значение 
  analogWrite(PWM_LR_PIN, PWM_LR_MIN); 
  analogWrite(PWM_LB_PIN, PWM_LB_MIN);
  if (! RTC.isrunning()) {
           Serial.println("RTC is NOT running!");
           RTC.adjust(DateTime(2014, 7, 12, 22, 48, 1));
           }
                                                         //RTC.adjust(DateTime(__DATE__, __TIME__));
}                                                                                             // КОНЕЦ ИНИЦИАЛИЗАЦИИ

//********************************************************************************************
void loop()                                                                                   // ПРОГРАММЫй безусловный ЦИКЛ 
{
  analogWrite(10, 100);
  lcd.setCursor(0, 1);
    long pwm_LW;
   long pwm_LR;
  long pwm_LB; 
    DateTime myTime = RTC.now();                                                              //Читаем данные времени из RTC при каждом выполнении цикла
    long Day_time = myTime.unixtime() % 86400;                                                //сохраняем в переменную - время в формате UNIX
 lcd.setCursor(11,0);
 if(myTime.hour()<10)lcd.print(0);
 lcd.print(myTime.hour(),DEC);
 lcd.print(":"); 
 if(myTime.minute()<10)lcd.print(0);
 lcd.print(myTime.minute(),DEC);

//*********************************************************************************************
//           обработка интервала до восхода и после заката
//*********************************************************************************************
    if ((Day_time<sunrise_start) ||                                                           //Если с начала суток меньше чем начало восхода 
        (Day_time>=sunset_start+sunset_duration)) {                                           //Или больше чем начало заката + длительность
                  pwm_LW = PWM_LW_MIN;                                                                    //Величина для записи в порт равна минимуму  
                  pwm_LR = PWM_LR_MIN;

//*********************************************************************************************
//           обработка интервала восхода 
//*********************************************************************************************
    }else if ((Day_time>=sunrise_start) &&                                                    //Если с начала суток больше чем начало восхода
              (Day_time<sunrise_start+sunrise_duration)){                                     //И меньше чем начало восхода + длительность 

                  pwm_LW =  ((Day_time - sunrise_start)*(PWM_LW_MAX-PWM_LW_MIN)) / sunrise_duration;   //Вычисляем для рассвета величину для записи в порт ШИМ
                  pwm_LR =  ((Day_time - sunrise_start)*(PWM_LR_MAX-PWM_LR_MIN)) / sunrise_duration;

//*********************************************************************************************
//           обработка интервала заката 
//*********************************************************************************************
    }else if ((Day_time>=sunset_start) &&                                                     //Если  начала суток больше чем начало заката и меньше чем  
              (Day_time<sunset_start+sunset_duration)){                                       //начало заката плюс длительность

                  pwm_LW = ((sunset_start+sunset_duration - Day_time)*(PWM_LW_MAX-PWM_LW_MIN)) / sunrise_duration;    //Вычисляем для заката величину для записи в порт ШИМ
                  pwm_LR = ((sunset_start+sunset_duration - Day_time)*(PWM_LR_MAX-PWM_LR_MIN)) / sunrise_duration;
 
//********************************************************************************************
//           обработка интервала от конца рассвета и до начала заката,
//           когда свет должен быть включен на максимальную яркость 
//********************************************************************************************
    }else {
                  pwm_LW = PWM_LW_MAX;                                                              //Устанавливаем максимальную величину для записи в порт ШИМ 
                  pwm_LR = PWM_LR_MAX;
    }
    
    analogWrite(PWM_LW_PIN, pwm_LW);            //Пишем в порт вычисленное значение      
    analogWrite(PWM_LR_PIN, pwm_LR);    
   
  //           обработка интервала до восхода луны и после заката
//*********************************************************************************************
    if ((Day_time<moonrise_start) ||                                                           //Если с начала суток меньше чем начало восхода 
        (Day_time>=moonset_start+moonset_duration)) {                                           //Или больше чем начало заката + длительность
                  pwm_LB = PWM_LB_MIN;                                                                    //Величина для записи в порт равна минимуму  

//*********************************************************************************************
//           обработка интервала восхода луны
//*********************************************************************************************
    }else if ((Day_time>=moonrise_start) &&                                                    //Если с начала суток больше чем начало восхода
              (Day_time<moonrise_start+moonrise_duration)){                                     //И меньше чем начало восхода + длительность 

                  pwm_LB =  ((Day_time - moonrise_start)*(PWM_LB_MAX-PWM_LB_MIN)) / moonrise_duration;   //Вычисляем для рассвета величину для записи в порт ШИМ

//*********************************************************************************************
//           обработка интервала заката луны
//*********************************************************************************************
    }else if ((Day_time>=moonset_start) &&                                                     //Если  начала суток больше чем начало заката и меньше чем  
              (Day_time<moonset_start+moonset_duration)){                                       //начало заката плюс длительность

                  pwm_LB = ((moonset_start+moonset_duration - Day_time)*(PWM_LB_MAX-PWM_LB_MIN)) / moonrise_duration;    //Вычисляем для заката величину для записи в порт ШИМ
 
//********************************************************************************************
//           обработка интервала от конца рассвета и до начала заката луны,
//           когда свет должен быть включен на максимальную яркость 
//********************************************************************************************
    }else {
                  pwm_LB = PWM_LB_MAX;                                                              //Устанавливаем максимальную величину для записи в порт ШИМ 
    }
    
    analogWrite(PWM_LB_PIN, pwm_LB);            //Пишем в порт вычисленное значение 
  
byte i;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  // Ищем алрес датчика
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  // Проверяем не было ли помех при передаче
  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // Определяем серию датчика
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();            
  ds.select(addr);       // Выбираем адрес
  ds.write(0x44, 1);     // Производим замер, в режиме паразитного питания
  delay(750);    
  
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Считываем оперативную память датчика

  for ( i = 0; i < 9; i++) {           
    data[i] = ds.read();  // Заполняем массив считанными данными
  }

  // Данные о температуре содержатся в первых двух байтах, переведем их в одно значение и преобразуем в шестнадцатиразрядное число
  unsigned int raw = (data[1] << 8) | data[0];
  // Переводим температуру в шкалы по Цельсию и Фаренгейту  
  if (type_s) 
  {
    raw = raw << 3; 
  }
  if (data[7] == 0x10) 
  {
    raw = (raw & 0xFFF0) + 12 - data[6];
  } else {
    byte cfg =  (data[4] & 0x60);
    if (cfg == 0x00) 
      raw = raw << 3; 
    else if  (cfg == 0x20) 
      raw = raw << 2; 
    else if  (cfg == 0x40) \
      raw = raw << 1;
  }  
  
  // Вывод текущего значения температуры на дисплей
  celsius = (float)raw / 16.0;
  lcd.setCursor(0, 0);
  lcd.print("T=");
  lcd.setCursor(2, 0);
  lcd.print(celsius);
  
  delay (10);
  
  celsius =  (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("Temp = ");
  Serial.print(celsius);
  Serial.print(" C, ");
  Serial.print(fahrenheit);
  Serial.println(" F");
  
  // Если температура достигает 28,3 (с погрешностью), отключаем кипятильник 
  if (celsius > 28.3)
  {
     digitalWrite(40, Relay_Off); 
  lcd.setCursor(0, 1);
  lcd.print("H1-Off");   
  }
  if (celsius < 28.0)
  {
     digitalWrite(40, Relay_On); 
  lcd.setCursor(0, 1);
  lcd.print("H1-On ");
       digitalWrite(41, Relay_On); 
  lcd.setCursor(7, 1);
  lcd.print("H2-On ");
  }

// Если температура достигает 28,5 (с погрешностью), отключаем кипятильник 
  if (celsius > 28.5)
  {
     digitalWrite(41, Relay_Off); 
  lcd.setCursor(7, 1);
  lcd.print("H2-Off");
  }

lcd_key = read_LCD_buttons();  // read the buttons

switch (lcd_key)               // depending on which button was pushed, we perform an action
 {
   case btnRIGHT:
     {
     digitalWrite(41, Relay_Off); 
  lcd.setCursor(7, 1);
  lcd.print("H2-Off");
     break;
     }
   case btnLEFT:
     {
     digitalWrite(41, Relay_On); 
  lcd.setCursor(7, 1);
  lcd.print("H2-On ");
     break;
     }
   case btnUP:
     {
     lcd.print("UP    ");
     break;
     }
   case btnDOWN:
     {
     lcd.print("DOWN  ");
     break;
     }
   }
}//------------Конец ЦИКЛА-----------------------------

Последний раз редактировалось kirex; 27.03.2014 в 21:50.
kirex вне форума   Ответить с цитированием
Старый 27.03.2014, 22:21   #2
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,616
Вес репутации: 9820
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Акваконтроллер

Для простого варианта реализации кнопки, можно использовать прерывания
Admin вне форума   Ответить с цитированием
Старый 27.03.2014, 22:39   #3
kirex
Member
 
Регистрация: 24.03.2014
Сообщений: 38
Вес репутации: 0
kirex is an unknown quantity at this point
По умолчанию Re: Акваконтроллер

Цитата:
Сообщение от Admin Посмотреть сообщение
Для простого варианта реализации кнопки, можно использовать прерывания
Извините, а можно поподробнее. И кнопки хотелось бы использовать те которые на LCD Keypad Shield 1602

Последний раз редактировалось kirex; 27.03.2014 в 22:46.
kirex вне форума   Ответить с цитированием
Старый 27.03.2014, 23:19   #4
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,616
Вес репутации: 9820
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Акваконтроллер

А куда они подключены? К каким пинам?
Admin вне форума   Ответить с цитированием
Старый 27.03.2014, 23:28   #5
kirex
Member
 
Регистрация: 24.03.2014
Сообщений: 38
Вес репутации: 0
kirex is an unknown quantity at this point
По умолчанию Re: Акваконтроллер

Цитата:
Сообщение от Admin Посмотреть сообщение
А куда они подключены? К каким пинам?
Кнопки подключены к одному пину А0, т.е. через резистивный делитель.

В моём коде пока кнопку держу реле срабатывает, отпускаю - возвращается в первоначальное положение.

Последний раз редактировалось kirex; 27.03.2014 в 23:34.
kirex вне форума   Ответить с цитированием
Старый 28.03.2014, 03:01   #6
stD
Senior Member
 
Аватар для stD
 
Регистрация: 02.04.2012
Адрес: Питер
Сообщений: 1,125
Вес репутации: 1310
stD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant future
По умолчанию Re: Акваконтроллер

Если не нажата, то нажимаем и держим, если нажата, то отпускаем.
stD вне форума   Ответить с цитированием
Старый 28.03.2014, 11:10   #7
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,616
Вес репутации: 9820
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Акваконтроллер

Вот функция в которой читаются нажатия кнопок

PHP код:
int read_LCD_buttons()
{
 
adc_key_in analogRead(0);
 if (
adc_key_in 1000) return btnNONE;

 if (
adc_key_in 50)   return btnRIGHT;  
 if (
adc_key_in 250)  return btnUP
 if (
adc_key_in 400)  return btnDOWN
 if (
adc_key_in 600)  return btnLEFT
 if (
adc_key_in 850)  return btnSELECT;  
 return 
btnNONE;  

Функция возвращает значения присвоенные каждой кнопке
PHP код:
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5 
Admin вне форума   Ответить с цитированием
Старый 28.03.2014, 12:06   #8
kirex
Member
 
Регистрация: 24.03.2014
Сообщений: 38
Вес репутации: 0
kirex is an unknown quantity at this point
По умолчанию Re: Акваконтроллер

Цитата:
Сообщение от mebitek Посмотреть сообщение
Если не нажата, то нажимаем и держим, если нажата, то отпускаем.
Извините, а что вы хотели этим сказать?
kirex вне форума   Ответить с цитированием
Старый 28.03.2014, 12:08   #9
kirex
Member
 
Регистрация: 24.03.2014
Сообщений: 38
Вес репутации: 0
kirex is an unknown quantity at this point
По умолчанию Re: Акваконтроллер

Цитата:
Сообщение от Admin Посмотреть сообщение
Вот функция в которой читаются нажатия кнопок

PHP код:
int read_LCD_buttons()
{
 
adc_key_in analogRead(0);
 if (
adc_key_in 1000) return btnNONE;

 if (
adc_key_in 50)   return btnRIGHT;  
 if (
adc_key_in 250)  return btnUP
 if (
adc_key_in 400)  return btnDOWN
 if (
adc_key_in 600)  return btnLEFT
 if (
adc_key_in 850)  return btnSELECT;  
 return 
btnNONE;  

Функция возвращает значения присвоенные каждой кнопке
PHP код:
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5 
Да это всё понятно. Как мне организовать то, что мне надо? Вот в чём проблема.
kirex вне форума   Ответить с цитированием
Старый 28.03.2014, 14:40   #10
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Акваконтроллер

Цитата:
Сообщение от kirex Посмотреть сообщение
Что ещё нужно: возможность включения и выключения света LW и LR кнопками (UP-Вкл., DOWN-Выкл.), независимо от времени. А также возможность включения и выключения нагревателя Н2 кнопками (LEFT-Вкл., RIGHT-Выкл.), независимо от температуры.
этого мало - я уже ранее писал -да написания программы нужно продумать алгоритм действий. Его ты так и не описал. Допустим у тебя нагреватели включаются и выключаются по температуре. Кнопкой ты принудительно его включаешь - а дальше что? когда автомат снова должен включиться?
Bulatovor вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 4 (пользователей: 0 , гостей: 4)
 
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 11:40. Часовой пояс GMT +3.


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Яндекс.Метрика