Брудер-автомат

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

Добрый день. Делюсь проектом умного брудера для цыплят-утят-перепелят и т.д. Брудер это специально обустроенная теплая клетка, куда сажают птенцов, вылупившихся из инкубатора. Тема берет свое начало из проекта "Умная Теплица", за который её автору низкий поклон. Итак, на сегодня автоматика умеет поддерживать температуру в 4-х брудерах, плавно снижая ее по дням "отсидки" каждой партии. День старта можно задавать произвольно из меню. Включение и отключение обогрева и освещения в брудерах будет осуществляться тумблерами, остальное делает программа. По железу - Uno, RTC на 1307, дисплей (пока 16х02). Управление нагревателями симисторное через опторазвязку. Термометры аналоговые LM35, выбраны исходя из стоимости. Ну, вроде пока все. Устройство пока собрано на макетке. Вот немножко видео. Вот код:

 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

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







#include <Wire.h>
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
//#include <DallasTemperature.h>

int dimmer = 180;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
float histeresis = 0.3;             //гистерезис в градусах между температурой включения и выключения нагревателя

unsigned int currentTime_day;      //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)

unsigned int memoryTime_day1;      //хранящийся в памяти день старта первого брудера
unsigned int memoryTime_day2;
unsigned int memoryTime_day3;
unsigned int memoryTime_day4;

const int button_minus_pin = 2;    //пин кнопки "минус"
const int button_plus_pin = 3;     //пин кнопки "плюс"
const int button_enter_pin = 4;    //пин кнопки "enter"

const int tempB1_pin = A0;         //пин термометра первого брудера
const int tempB2_pin = A1;
const int tempB3_pin = A2;
const int tempB4_pin = A3;

const int heater1 = 5;             //пин нагревателя брудера1
const int heater2 = 6;
const int heater3 = 9;
const int heater4 = 10;

/*const int start1 = 8;             //пин тумблера запуска брудера1
 const int start2 = 9;
 const int start3 = 10;
 const int start4 = 11;*/

int button_minus = 1;              // переменная для хранения состояния кнопки "минус"
int button_plus = 2;               // переменная для хранения состояния кнопки "плюс"
int button_enter = 3;              // переменная для хранения состояния кнопки "enter"

unsigned int days_count1;          //счетчик дней работы брудера1
unsigned int days_count2;
unsigned int days_count3;
unsigned int days_count4;

unsigned int day_bruder1;         //день работы программы в 1 брудере
unsigned int day_bruder2;
unsigned int day_bruder3;
unsigned int day_bruder4;




LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;


void setup() {

  //  Serial.begin(9600);  // Старт сериал-порта
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(button_minus_pin, INPUT); //задаем пины кнопок как входы
  pinMode(button_plus_pin, INPUT);
  pinMode(button_enter_pin, INPUT);

  pinMode(heater1, OUTPUT);         //задаем пины нагревателей как выходы
  pinMode(heater2, OUTPUT);
  pinMode(heater3, OUTPUT);
  pinMode(heater4, OUTPUT);

  DateTime now = RTC.now();  //получам текущее время из часов

//    EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 
//    EEPROM_write(3, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 
//    EEPROM_write(5, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 
//    EEPROM_write(7, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 

  EEPROM_read(1, memoryTime_day1); //читаем из памяти дату первого дня первого брудера
  EEPROM_read(3, memoryTime_day2); 
  EEPROM_read(5, memoryTime_day3); 
  EEPROM_read(7, memoryTime_day4); 



}

void loop() {

  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder1 = (currentTime_day - memoryTime_day1);
  day_bruder2 = (currentTime_day - memoryTime_day2);
  day_bruder3 = (currentTime_day - memoryTime_day3);
  day_bruder4 = (currentTime_day - memoryTime_day4);



  //печатаем на дисплей текущую дату и время
  thermostat1();  //вызываем функцию терморегулятора 1 брудера
  thermostat2();
  thermostat3();
  thermostat4();
  
  
  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }


}

void menu() {
  bruder1_setup();
  bruder2_setup();
  bruder3_setup();
  bruder4_setup();
  //climat_setup();
  //data_time_setup();
}

void button_read() {//функция проверки нажатия кнопки

  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
}

void bruder1_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER1 SETUP");
  delay (1000);
  lcd.clear();
  while (1) {
    button_read();
    EEPROM_read(1, memoryTime_day1);
    day_bruder1 = (currentTime_day - memoryTime_day1);
    lcd.setCursor(0, 0);
    lcd.print("1DayCnt = ");
    lcd.print(day_bruder1);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(1, memoryTime_day1 - 1);
      if (day_bruder1 > 100){      //проверяем, если прошло больше 100 дней
       DateTime now = RTC.now();  //получам текущее время из часов 
       EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, memoryTime_day1 + 1);
      lcd.clear();
    }
    delay(del);

  }
}



//-------------------------------------------------------------------------

void bruder2_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER2 SETUP");
  delay (1000);
  lcd.clear();
  while (1) {
    button_read();
    EEPROM_read(3, memoryTime_day2);
    day_bruder2 = (currentTime_day - memoryTime_day2);
    lcd.setCursor(0, 0);
    lcd.print("2DayCnt = ");
    lcd.print(day_bruder2);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(3, memoryTime_day2 - 1);
      if (day_bruder2 > 100){      //проверяем, если прошло больше 100 дней
       DateTime now = RTC.now();  //получам текущее время из часов 
       EEPROM_write(3, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, memoryTime_day2 + 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder3_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER3 SETUP");
  delay (1000);
  lcd.clear();
  while (1) {
    button_read();
    EEPROM_read(5, memoryTime_day3);
    day_bruder3 = (currentTime_day - memoryTime_day3);
    lcd.setCursor(0, 0);
    lcd.print("3DayCnt = ");
    lcd.print(day_bruder3);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(5, memoryTime_day3 - 1);
      if (day_bruder3 > 100){
       DateTime now = RTC.now();  //получам текущее время из часов 
       EEPROM_write(5, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(5, memoryTime_day3 + 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder4_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER4 SETUP");
  delay (1000);
  lcd.clear();
  while (1) {
    button_read();
    EEPROM_read(7, memoryTime_day4);
    day_bruder4 = (currentTime_day - memoryTime_day4);
    lcd.setCursor(0, 0);
    lcd.print("4DayCnt = ");
    lcd.print(day_bruder4);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(7, memoryTime_day4 - 1);
      if (day_bruder4 > 100){
       DateTime now = RTC.now();  //получам текущее время из часов 
       EEPROM_write(7, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(7, memoryTime_day4 + 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void thermostat1 (){

  float tempB1; 
  float temp_idealB1;

  tempB1 = analogRead(tempB1_pin); //читаем температуру первого брудера 
  tempB1 = (5.0 * tempB1 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder1 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB1 = map(day_bruder1,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB1 = temp_idealB1 / 10;

  if (tempB1 < temp_idealB1){            //если температура в 1 брудере ниже идеальной
    analogWrite (heater1, dimmer);
  }        //включаем обогрев
  else if (tempB1 > temp_idealB1+histeresis){ //если температура выше идеальной на величину гистерезиса
    analogWrite (heater1, dimmer);
  }   //то обогрев отключаем

  lcd.setCursor(0, 0);        //DEBUG
  lcd.print (day_bruder1);
  lcd.setCursor(3,0);
  lcd.print(temp_idealB1,1);    //DEBUG
}

//-------------------------------------------------------------------

void thermostat2 (){

  float tempB2; 
  float temp_idealB2;

  tempB2 = analogRead(tempB2_pin); //читаем температуру первого брудера 
  tempB2 = (5.0 * tempB2 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder2 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB2 = map(day_bruder2,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB2 = temp_idealB2 / 10;

  if (tempB2 < temp_idealB2){            //если температура в 1 брудере ниже идеальной
    analogWrite (heater2, dimmer);
  }        //включаем обогрев
  else if (tempB2 > temp_idealB2+histeresis){ //если температура выше идеальной на величину гистерезиса
    analogWrite (heater2, dimmer);
  }   //то обогрев отключаем

  lcd.setCursor(9, 0);        //DEBUG
  lcd.print (day_bruder2);
  lcd.setCursor(12,0);
  lcd.print(temp_idealB2,1);    //DEBUG
}

//-------------------------------------------------------------------

void thermostat3 (){

  float tempB3; 
  float temp_idealB3;

  tempB3 = analogRead(tempB3_pin); //читаем температуру первого брудера 
  tempB3 = (5.0 * tempB3 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder3 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB3 = map(day_bruder3,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB3 = temp_idealB3 / 10;

  if (tempB3 < temp_idealB3){            //если температура в 1 брудере ниже идеальной
    analogWrite (heater3, dimmer);
  }        //включаем обогрев
  else if (tempB3 > temp_idealB3+histeresis){ //если температура выше идеальной на величину гистерезиса
    analogWrite (heater3, 0);
  }   //то обогрев отключаем

  lcd.setCursor(0, 1);        //DEBUG
  lcd.print (day_bruder3);
  lcd.setCursor(3,1);
  lcd.print(temp_idealB3,1);    //DEBUG
}

//---------------------------------------------------------------------

void thermostat4 (){

  float tempB4; 
  float temp_idealB4;

  tempB4 = analogRead(tempB4_pin); //читаем температуру первого брудера 
  tempB4 = (5.0 * tempB4 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder4 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB4 = map(day_bruder4,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB4 = temp_idealB4 / 10;

  if (tempB4 < temp_idealB4){            //если температура в 1 брудере ниже идеальной
    analogWrite (heater4, dimmer);
  }        //включаем обогрев
  else if (tempB4 > temp_idealB4+histeresis){ //если температура выше идеальной на величину гистерезиса
    analogWrite (heater4, 0);
  }   //то обогрев отключаем

  lcd.setCursor(9, 1);        //DEBUG
  lcd.print (day_bruder4);
  lcd.setCursor(12,1);
  lcd.print(temp_idealB4,1);    //DEBUG
}

Да, разумеется, малышам нужен особый режим. Терморегуляции у птенцов своей еще нет. Температура в брудере с новорожденными должна быть 37 градусов и плавно снижаться до 20 градусов к 4-м неделям. Так же сетка на полу (если пол с сеткой) должна быть более мелкая, в стандартную они проваливаются. Поилки специальные, в поилках для взрослой птицы малыши тонут. Точнее намокают и замерзают. Ну и кормушки специальные, чтоб достать смогли и корм тоже для малышей свой. Перепелята вообще размером с майского жука рождаются, но очень подвижные. В любую щель выпрыгнут. Однако давайте лучше код обсудим. Программер из меня никакой, так что срадостью приму все советы и замечания. Спасибо. Да, в перспективе будет версия HOME для одного брудера.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну тогда предложение для начала руссифицировать меню

вот либа. не тестил правда

http://vk.com/away.php?to=http%3A%2F%2Fwww.freeduino.ru%2Farduino%2Ffiles%2FMCP23x17.zip

посмотрите в подпрограмме термостат 1 и 2.

например 334-338 строки. хоть температура ниже, хоть выше выполняется одно и тоже (включается обогрев), хотя в коментах выключается или выключается

в 3 и 4 вроде нормально

+ да и еще. у вас сделаны подпрограммы-функции. но это просто куски кода вынесли. если сделать одну функцию и просто загонять в нее данные по каждому каналу разве это не логичнее?

 

 

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

Спасибо, поправил код. Вот к чему копипаста приводит. Да, я хотел бы убрать кучу одинаковых функций и подставлять в код нужные значения, но не умею этого делать. Нужно использовать не void функцию и передавать в цикле значение переменной в функцию или можно и void использовать, но значения в функцию передавать, она же ничего не возвращает? Опыта нет в Си. Есть какой-нибудь пример понятный? За библиотеку отдельное спасибо, пошел читать.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

можете возвращать значения. в функцию значения нет проблем передать.

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

вот почитайте

http://arduino.ru/Reference/FunctionDeclaration

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

Тут повторяющиеся функции отличаются цыфрой в переменных только. Может в цикле просто разные переменные подставлять или цыфру в имя переменной, если так можно. В описании функций мало информации об этом. Мне бы на пример работающий посмотреть.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

так там вроде пример есть. что точнее вы хотите?

вот первая попавшаяся функция

//Вывод символа 13х24 в координаты XY
void simb13x24(char n, char x, char y){ // n это число которое нужно выводить, xy координаты куда
  char i;
  Goto_XY(x,y);
  for (i=0;i<13;i++){
    SendByte(1,pgm_read_byte(&(mass13x24[n][i])));
  }
  Goto_XY(x,y+1);
  for (i=13;i<26;i++){
    SendByte(1,pgm_read_byte(&(mass13x24[n][i])));
  }
  Goto_XY(x,y+2);
  for (i=26;i<39;i++){
    SendByte(1,pgm_read_byte(&(mass13x24[n][i])));
  }
}

хотя и эту функцию можно можно вставить функцию так как 3 куска повторяются

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

Пример не осилил. Как точнее объяснить что я хочу? Давайте я лучше расскажу как я это себе представляю. Мы пишем void функцию, пусть она пока будет черным ящиком. Затем передаем в нее циклом или еще как номер брудера для обработки его программы. А в самой функции по условию if или switch-case выбираем уже переменные и константы с нужным номером. Так? Но не получится ли тогда длина кода в функции сопоставимая с длиной кода четырех маленьких функций как мы имеем сейчас?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ладно не заморачивайтесь. скорость и объем неважен. оставьте как есть

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

Не, негоже так быстро сдаваться. Написать смог код, смогу и оптимизировать. Иначе не научусь ни чему.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

код на самом деле будет меньше. редактировать его станет проще, будет меньше ошибок копипаста.

вы можете создать массив. номер канала который вы будете передавать в функцию будет соответствовать на пример строке

в строке количество переменных соответствует количеству необходимых переменных (это столбцы)

в функции прописать что делать с каждым элементом в столбце, а строку - номер канала вы будете передавать в функцию

надеюсь понятно

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

Понятно, спасибо.

У меня сейчас другая проблема вылезла. ШИМ из analogWrite работает на частоте 470Гц. Сможет ли работать на такой частоте симистор? На опторазвязке с zero-cross точно ерунда получится. Снижать частоту таймеров, это получить проблемы с delay. Ломаю голову как просто реализовать низкочастотный ШИМ без delay. Чтобы (условно) полсекунды было включено digitalWrite, а полсекунды отключено. И чтобы эта скважность была переменной и могла меняться из меню. С одним каналом просто, а вот на четырех голову сломал. Понимаю что надо использовать в каждом канале millis(), но не придумаю как в них скважность регулировать. Может делал уже кто-нибудь подобное?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

вам наверно пригодится библиотека TimerOne

http://robocraft.ru/blog/arduino/614.html

"Когда программируешь для Arduino, иногда бывает нужно периодически выполнять какие-либо действия через определённые интервалы времени — скажем, 100 раз в секунду; или хочется иметь ШИМ с большим разрешением или другой частотой, чем позволяет стандартная функция analogWrite()"

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

Проблема решена.

#include <Wire.h>
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
//#include <DallasTemperature.h>

int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
float histeresis = 0.3;             //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 50;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;                //длина окна регулировки мощности

unsigned long windowStartTime;    //переменная для хранения начала цикла окна
 unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned int currentTime_day;      //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)


unsigned int memoryTime_day1;      //хранящийся в памяти день старта первого брудера
unsigned int memoryTime_day2;
unsigned int memoryTime_day3;
unsigned int memoryTime_day4;

const int button_minus_pin = 2;    //пин кнопки "минус"
const int button_plus_pin = 3;     //пин кнопки "плюс"
const int button_enter_pin = 4;    //пин кнопки "enter"

const int tempB1_pin = A0;         //пин термометра первого брудера
const int tempB2_pin = A1;
const int tempB3_pin = A2;
const int tempB4_pin = A3;

const int heater1 = 5;             //пин нагревателя брудера1
const int heater2 = 6;
const int heater3 = 9;
const int heater4 = 10;

/*const int start1 = 8;             //пин тумблера запуска брудера1
 const int start2 = 9;
 const int start3 = 10;
 const int start4 = 11;*/

int button_minus = 1;              // переменная для хранения состояния кнопки "минус"
int button_plus = 2;               // переменная для хранения состояния кнопки "плюс"
int button_enter = 3;              // переменная для хранения состояния кнопки "enter"

unsigned int days_count1;          //счетчик дней работы брудера1
unsigned int days_count2;
unsigned int days_count3;
unsigned int days_count4;

unsigned int day_bruder1;         //день работы программы в 1 брудере
unsigned int day_bruder2;
unsigned int day_bruder3;
unsigned int day_bruder4;





LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;


void setup() {

  //Serial.begin(9600);  // Старт сериал-порта
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(button_minus_pin, INPUT); //задаем пины кнопок как входы
  pinMode(button_plus_pin, INPUT);
  pinMode(button_enter_pin, INPUT);

  pinMode(heater1, OUTPUT);         //задаем пины нагревателей как выходы
  pinMode(heater2, OUTPUT);
  pinMode(heater3, OUTPUT);
  pinMode(heater4, OUTPUT);
  
   windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  DateTime now = RTC.now();  //получам текущее время из часов
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени

    
  //    EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 
  //    EEPROM_write(3, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 
  //    EEPROM_write(5, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 
  //    EEPROM_write(7, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день 

  EEPROM_read(1, memoryTime_day1); //читаем из памяти дату первого дня первого брудера
  EEPROM_read(3, memoryTime_day2); 
  EEPROM_read(5, memoryTime_day3); 
  EEPROM_read(7, memoryTime_day4); 



}

void loop() {

  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder1 = (currentTime_day - memoryTime_day1);
  day_bruder2 = (currentTime_day - memoryTime_day2);
  day_bruder3 = (currentTime_day - memoryTime_day3);
  day_bruder4 = (currentTime_day - memoryTime_day4);



  //печатаем на дисплей текущую дату и время
  thermostat1();  //вызываем функцию терморегулятора 1 брудера
  thermostat2();
  thermostat3();
  thermostat4();


  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }


}

void menu() {
  bruder1_setup();
  bruder2_setup();
  bruder3_setup();
  bruder4_setup();
  //climat_setup();
  //data_time_setup();
}

void button_read() {//функция проверки нажатия кнопки

  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
}

void bruder1_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER1 SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval){
      break;
    }

    button_read();
    EEPROM_read(1, memoryTime_day1);
    day_bruder1 = (currentTime_day - memoryTime_day1);
    lcd.setCursor(0, 0);
    lcd.print("1DayCnt = ");
    lcd.print(day_bruder1);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(1, memoryTime_day1 - 1);
      if (day_bruder1 > 100){      //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов 
        EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, memoryTime_day1 + 1);
      lcd.clear();
    }
    delay(del);

  }
}



//-------------------------------------------------------------------------

void bruder2_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER2 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval){
      break;
    } 

    button_read();
    EEPROM_read(3, memoryTime_day2);
    day_bruder2 = (currentTime_day - memoryTime_day2);
    lcd.setCursor(0, 0);
    lcd.print("2DayCnt = ");
    lcd.print(day_bruder2);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(3, memoryTime_day2 - 1);
      if (day_bruder2 > 100){      //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов 
        EEPROM_write(3, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, memoryTime_day2 + 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder3_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER3 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval){
      break;
    }  

    button_read();
    EEPROM_read(5, memoryTime_day3);
    day_bruder3 = (currentTime_day - memoryTime_day3);
    lcd.setCursor(0, 0);
    lcd.print("3DayCnt = ");
    lcd.print(day_bruder3);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(5, memoryTime_day3 - 1);
      if (day_bruder3 > 100){
        DateTime now = RTC.now();  //получам текущее время из часов 
        EEPROM_write(5, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(5, memoryTime_day3 + 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder4_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER4 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval){
      lcd.clear();
      break;
    }  

    button_read();
    EEPROM_read(7, memoryTime_day4);
    day_bruder4 = (currentTime_day - memoryTime_day4);
    lcd.setCursor(0, 0);
    lcd.print("4DayCnt = ");
    lcd.print(day_bruder4);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(7, memoryTime_day4 - 1);
      if (day_bruder4 > 100){
        DateTime now = RTC.now();  //получам текущее время из часов 
        EEPROM_write(7, now.unixtime() / 86400L);  //пишем в память сегодняшний день  
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(7, memoryTime_day4 + 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void thermostat1 (){

  float tempB1; 
  float temp_idealB1;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB1 = analogRead(tempB1_pin); //читаем температуру первого брудера 
  tempB1 = (5.0 * tempB1 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder1 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB1 = map(day_bruder1,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB1 = temp_idealB1 / 10;
  
  if(currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {                       
    windowStartTime += WindowSize;
    currentTime = millis(); 
  }

  if (tempB1 < temp_idealB1){     //если температура в 1 брудере ниже идеальной
    
    if (currentTime - windowStartTime < 10 * dimmer){
    digitalWrite(heater1, HIGH);
  }  
  else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
  {
    digitalWrite(heater1, LOW);
  }  
    
     
  }        //включаем обогрев
  else if (tempB1 > temp_idealB1+histeresis){ //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater1, 0);
  }   //то обогрев отключаем

  lcd.setCursor(0, 0);        //DEBUG
  lcd.print (day_bruder1);
  lcd.setCursor(3,0);
  lcd.print(temp_idealB1,1);    //DEBUG
}

//-------------------------------------------------------------------

void thermostat2 (){

  float tempB2; 
  float temp_idealB2;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB2 = analogRead(tempB2_pin); //читаем температуру первого брудера 
  tempB2 = (5.0 * tempB2 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder2 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB2 = map(day_bruder2,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB2 = temp_idealB2 / 10;
  
  if(currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {                       
    windowStartTime += WindowSize;
    currentTime = millis(); 
  }

  if (tempB2 < temp_idealB2){     //если температура в 1 брудере ниже идеальной
    
    if (currentTime - windowStartTime < 10 * dimmer){
    digitalWrite(heater2, HIGH);
  }  
  else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
  {
    digitalWrite(heater2, LOW);
  }  
    
     
  }        //включаем обогрев
  else if (tempB2 > temp_idealB2+histeresis){ //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater2, 0);
  }   //то обогрев отключаем

  lcd.setCursor(9, 0);        //DEBUG
  lcd.print (day_bruder2);
  lcd.setCursor(12,0);
  lcd.print(temp_idealB2,1);    //DEBUG
}
//-------------------------------------------------------------------

void thermostat3 (){

  float tempB3; 
  float temp_idealB3;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB3 = analogRead(tempB3_pin); //читаем температуру первого брудера 
  tempB3 = (5.0 * tempB3 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder3 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB3 = map(day_bruder3,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB3 = temp_idealB3 / 10;
  
  if(currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {                       
    windowStartTime += WindowSize;
    currentTime = millis(); 
  }

  if (tempB3 < temp_idealB3){     //если температура в 1 брудере ниже идеальной
    
    if (currentTime - windowStartTime < 10 * dimmer){
    digitalWrite(heater3, HIGH);
  }  
  else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
  {
    digitalWrite(heater3, LOW);
  }  
    
     
  }        //включаем обогрев
  else if (tempB3 > temp_idealB3+histeresis){ //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater3, 0);
  }   //то обогрев отключаем

  lcd.setCursor(0, 1);        //DEBUG
  lcd.print (day_bruder3);
  lcd.setCursor(3,1);
  lcd.print(temp_idealB3,1);    //DEBUG
}

//---------------------------------------------------------------------

void thermostat4 (){

   float tempB4; 
  float temp_idealB4;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB4 = analogRead(tempB4_pin); //читаем температуру первого брудера 
  tempB4 = (5.0 * tempB4 * 100.0)/1024.0;  //переводим ее в градусы Цельсия.
  if (day_bruder4 >= 24.0){   //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }     
  else (temp_idealB4 = map(day_bruder4,0,24,370,200)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  temp_idealB4 = temp_idealB4 / 10;
  
  if(currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {                       
    windowStartTime += WindowSize;
    currentTime = millis(); 
  }

  if (tempB4 < temp_idealB4){     //если температура в 1 брудере ниже идеальной
    
    if (currentTime - windowStartTime < 10 * dimmer){
    digitalWrite(heater4, HIGH);
  }  
  else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
  {
    digitalWrite(heater4, LOW);
  }  
    
     
  }        //включаем обогрев
  else if (tempB4 > temp_idealB4+histeresis){ //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater4, 0);
  }   //то обогрев отключаем

  lcd.setCursor(9, 1);        //DEBUG
  lcd.print (day_bruder4);
  lcd.setCursor(12,1);
  lcd.print(temp_idealB4,1);    //DEBUG
}

  

 

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

У вас в коде два раза по 4 одинаковых функции , можете сделать одну и вызывать её с необходимыми параметрами =) Код прошивки прилично похудеет. да и поднимется лэвл по cpp =)

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

Вот свежий код, после кучи правок. Не последний, но уже в железе работает.

#include <Wire.h>
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
//#include <DallasTemperature.h>

int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
int histeresis = 1;             //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 50;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;                //длина окна регулировки мощности

unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned int currentTime_day;      //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)


unsigned int memoryTime_day1;      //хранящийся в памяти день старта первого брудера
unsigned int memoryTime_day2;
unsigned int memoryTime_day3;
unsigned int memoryTime_day4;

const int button_minus_pin = 2;    //пин кнопки "минус"
const int button_plus_pin = 3;     //пин кнопки "плюс"
const int button_enter_pin = 4;    //пин кнопки "enter"

const int tempB1_pin = A0;         //пин термометра первого брудера
const int tempB2_pin = A1;
const int tempB3_pin = A2;
const int tempB4_pin = A3;

const int heater1 = 5;             //пин нагревателя брудера1
const int heater2 = 6;
const int heater3 = 9;
const int heater4 = 10;

/*const int start1 = 8;             //пин тумблера запуска брудера1
 const int start2 = 9;
 const int start3 = 10;
 const int start4 = 11;*/

int button_minus = 1;              // переменная для хранения состояния кнопки "минус"
int button_plus = 2;               // переменная для хранения состояния кнопки "плюс"
int button_enter = 3;              // переменная для хранения состояния кнопки "enter"

//unsigned int days_count1;          //счетчик дней работы брудера1
unsigned int days_count2;
unsigned int days_count3;
unsigned int days_count4;

unsigned int day_bruder1;         //день работы программы в 1 брудере
unsigned int day_bruder2;
unsigned int day_bruder3;
unsigned int day_bruder4;





LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;


void setup() {

  //Serial.begin(9600);  // Старт сериал-порта
  analogReference(INTERNAL);  //для повышения точности делаем опорное Напр. 1.1В
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(button_minus_pin, INPUT); //задаем пины кнопок как входы
  pinMode(button_plus_pin, INPUT);
  pinMode(button_enter_pin, INPUT);

  pinMode(heater1, OUTPUT);         //задаем пины нагревателей как выходы
  pinMode(heater2, OUTPUT);
  pinMode(heater3, OUTPUT);
  pinMode(heater4, OUTPUT);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  DateTime now = RTC.now();  //получам текущее время из часов
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени


  //    EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //    EEPROM_write(3, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //    EEPROM_write(5, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //    EEPROM_write(7, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день

  EEPROM_read(1, memoryTime_day1); //читаем из памяти дату первого дня первого брудера
  EEPROM_read(3, memoryTime_day2);
  EEPROM_read(5, memoryTime_day3);
  EEPROM_read(7, memoryTime_day4);



}

void loop() {

  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder1 = (currentTime_day - memoryTime_day1);
  day_bruder2 = (currentTime_day - memoryTime_day2);
  day_bruder3 = (currentTime_day - memoryTime_day3);
  day_bruder4 = (currentTime_day - memoryTime_day4);


  //печатаем на дисплей текущую дату и время
  thermostat1();  //вызываем функцию терморегулятора 1 брудера
  thermostat2();
  thermostat3();
  thermostat4();


  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }
  if (button_minus) {
    delay(del);
    lcd.clear();
    temp_ideal();
  }
  if (button_plus) {
    delay(del);
    lcd.clear();
    time_display();
  }
}
void menu() {
  bruder1_setup();
  bruder2_setup();
  bruder3_setup();
  bruder4_setup();
  dimmer_setup();
  //data_time_setup();
}

void button_read() {//функция проверки нажатия кнопки

  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
}

void bruder1_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER1 SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(1, memoryTime_day1);
    day_bruder1 = (currentTime_day - memoryTime_day1);
    lcd.setCursor(0, 0);
    lcd.print("1DayCnt = ");
    lcd.print(day_bruder1);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(1, memoryTime_day1 + 1);
      if (day_bruder1 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, memoryTime_day1 - 1);
      lcd.clear();
    }
    delay(del);

  }
}



//-------------------------------------------------------------------------

void bruder2_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER2 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(3, memoryTime_day2);
    day_bruder2 = (currentTime_day - memoryTime_day2);
    lcd.setCursor(0, 0);
    lcd.print("2DayCnt = ");
    lcd.print(day_bruder2);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(3, memoryTime_day2 + 1);
      if (day_bruder2 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(3, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, memoryTime_day2 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder3_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER3 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(5, memoryTime_day3);
    day_bruder3 = (currentTime_day - memoryTime_day3);
    lcd.setCursor(0, 0);
    lcd.print("3DayCnt = ");
    lcd.print(day_bruder3);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(5, memoryTime_day3 + 1);
      if (day_bruder3 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(5, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(5, memoryTime_day3 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder4_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER4 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(7, memoryTime_day4);
    day_bruder4 = (currentTime_day - memoryTime_day4);
    lcd.setCursor(0, 0);
    lcd.print("4DayCnt = ");
    lcd.print(day_bruder4);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(7, memoryTime_day4 + 1);
      if (day_bruder4 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(7, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(7, memoryTime_day4 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void thermostat1 () {

  float tempB1;
  float temp_idealB1;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB1 = analogRead(tempB1_pin); //читаем температуру первого брудера
  tempB1 = (tempB1 / 9.31); //переводим ее в градусы Цельсия.
  
  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 0);        //DEBUG
    lcd.print (day_bruder1);
    lcd.setCursor(3, 0);
    lcd.print(tempB1, 0);   //DEBUG

    windowStartTime += WindowSize;
    currentTime = millis();
  }

      
  if (tempB1 < temp_idealB1) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater1, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater1, LOW);
    }
  }        //включаем обогрев
  else if (tempB1 > (temp_idealB1 + histeresis)) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater1, LOW);
  }   //то обогрев отключаем

}

//-------------------------------------------------------------------

void thermostat2 () {

  float tempB2;
  float temp_idealB2;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB2 = analogRead(tempB2_pin); //читаем температуру первого брудера
  tempB2 = (tempB2 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(9, 0);        //DEBUG
    lcd.print (day_bruder2);
    lcd.setCursor(12, 0);
    lcd.print(tempB2, 0);   //DEBUG
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB2 < temp_idealB2) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater2, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater2, LOW);
    }


  }        //включаем обогрев
  else if (tempB2 > temp_idealB2 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater2, LOW);
  }   //то обогрев отключаем

}
//-------------------------------------------------------------------

void thermostat3 () {

  float tempB3;
  float temp_idealB3;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB3 = analogRead(tempB3_pin); //читаем температуру первого брудера
  tempB3 = (tempB3 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 1);        //DEBUG
    lcd.print (day_bruder3);
    lcd.setCursor(3, 1);
    lcd.print(tempB3, 0);   //DEBUG
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB3 < temp_idealB3) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater3, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater3, LOW);
    }


  }        //включаем обогрев
  else if (tempB3 > temp_idealB3 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater3, LOW);
  }   //то обогрев отключаем


}

//---------------------------------------------------------------------

void thermostat4 () {

  float tempB4;
  float temp_idealB4;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB4 = analogRead(tempB4_pin); //читаем температуру первого брудера
  tempB4 = (tempB4 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(9, 1);        //DEBUG
    lcd.print (day_bruder4);
    lcd.setCursor(12, 1);
    lcd.print(tempB4, 0);   //DEBUG
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB4 < temp_idealB4) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater4, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater4, LOW);
    }


  }        //включаем обогрев
  else if (tempB4 > temp_idealB4 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater4, LOW);
  }   //то обогрев отключаем


}

void dimmer_setup() {

  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(9, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 0);
    lcd.print("Dimmer% = ");
    lcd.print(dimmer);
    lcd.setCursor(0, 1);
    lcd.print("Dim-5 NEXT Dim+5");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 5;
      if (dimmer < 10) {
        dimmer = 10;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      dimmer = dimmer + 5;
      if (dimmer > 95) {
        dimmer = 95;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }
    delay(del);
  }
}

void temp_ideal() { //если нажата кнопка минус, выводим на дисплей идеальную температуру для брудеров
  //  в зависимости от дня отсидки

  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("TEMP-IDEAL");
  delay (1000);
  lcd.clear();

  float temp_idealB1;
  float temp_idealB2;
  float temp_idealB3;
  float temp_idealB4;

  lcd.clear();

  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  lcd.setCursor(0, 0);        //DEBUG
  lcd.print (day_bruder1);
  lcd.setCursor(3, 0);
  lcd.print(temp_idealB1, 0);   //DEBUG

  lcd.setCursor(9, 0);        //DEBUG
  lcd.print (day_bruder2);
  lcd.setCursor(12, 0);
  lcd.print(temp_idealB2, 0);   //DEBUG

  lcd.setCursor(0, 1);        //DEBUG
  lcd.print (day_bruder3);
  lcd.setCursor(3, 1);
  lcd.print(temp_idealB3, 0);   //DEBUG

  lcd.setCursor(9, 1);        //DEBUG
  lcd.print (day_bruder4);
  lcd.setCursor(12, 1);
  lcd.print(temp_idealB4, 0);   //DEBUG

  delay(4000);
  lcd.clear();
  return;
}

void time_display() {

  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("DATE-TIME");
  delay (1000);
  lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(6, 0);
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  lcd.setCursor(4, 1);
  lcd.print(now.day(), DEC);
  lcd.print(".");
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  delay(4000);
  lcd.clear();
  return;
}

Платы завтра выложу, забыл подтягивающие резисторы к кнопкам. Очень хочу убрать лишний код, но пока не до того. Отладка полным ходом идет на столе. А посколько рулит этим ПроМини, то приходится ее каждый раз выковыривать для прошивки. В общем не быстро, но продвигаемся.

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


#include <Wire.h>
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
//#include <DallasTemperature.h>

int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
int histeresis = 1;             //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 50;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;                //длина окна регулировки мощности

unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned int currentTime_day;      //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)


unsigned int memoryTime_day1;      //хранящийся в памяти день старта первого брудера
unsigned int memoryTime_day2;
unsigned int memoryTime_day3;
unsigned int memoryTime_day4;

const int button_minus_pin = 2;    //пин кнопки "минус"
const int button_plus_pin = 4;     //пин кнопки "плюс"
const int button_enter_pin = 3;    //пин кнопки "enter"

const int tempB1_pin = A0;         //пин термометра первого брудера
const int tempB2_pin = A1;
const int tempB3_pin = A2;
const int tempB4_pin = A3;

const int heater1 = 5;             //пин нагревателя брудера1
const int heater2 = 6;
const int heater3 = 9;
const int heater4 = 10;

/*const int start1 = 8;             //пин тумблера запуска брудера1
 const int start2 = 9;
 const int start3 = 10;
 const int start4 = 11;*/

int button_minus = 1;              // переменная для хранения состояния кнопки "минус"
int button_plus = 2;               // переменная для хранения состояния кнопки "плюс"
int button_enter = 3;              // переменная для хранения состояния кнопки "enter"

//unsigned int days_count1;          //счетчик дней работы брудера1
unsigned int days_count2;
unsigned int days_count3;
unsigned int days_count4;

unsigned int day_bruder1;         //день работы программы в 1 брудере
unsigned int day_bruder2;
unsigned int day_bruder3;
unsigned int day_bruder4;





LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;


void setup() {

  //Serial.begin(9600);  // Старт сериал-порта
  analogReference(INTERNAL);  //для повышения точности делаем опорное Напр. 1.1В
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(button_minus_pin, INPUT); //задаем пины кнопок как входы
  pinMode(button_plus_pin, INPUT);
  pinMode(button_enter_pin, INPUT);

  pinMode(heater1, OUTPUT);         //задаем пины нагревателей как выходы
  pinMode(heater2, OUTPUT);
  pinMode(heater3, OUTPUT);
  pinMode(heater4, OUTPUT);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  DateTime now = RTC.now();  //получам текущее время из часов
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени


  //    EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //    EEPROM_write(3, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //    EEPROM_write(5, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //    EEPROM_write(7, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день

  EEPROM_read(1, memoryTime_day1); //читаем из памяти дату первого дня первого брудера
  EEPROM_read(3, memoryTime_day2);
  EEPROM_read(5, memoryTime_day3);
  EEPROM_read(7, memoryTime_day4);



}

void loop() {

  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder1 = (currentTime_day - memoryTime_day1);
  day_bruder2 = (currentTime_day - memoryTime_day2);
  day_bruder3 = (currentTime_day - memoryTime_day3);
  day_bruder4 = (currentTime_day - memoryTime_day4);


  //печатаем на дисплей текущую дату и время
  thermostat1();  //вызываем функцию терморегулятора 1 брудера
  thermostat2();
  thermostat3();
  thermostat4();


  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }
  if (button_minus) {
    delay(del);
    lcd.clear();
    temp_ideal();
  }
  if (button_plus) {
    delay(del);
    lcd.clear();
    time_display();
  }
}
void menu() {
  bruder1_setup();
  bruder2_setup();
  bruder3_setup();
  bruder4_setup();
  dimmer_setup();
  //data_time_setup();
}

void button_read() {//функция проверки нажатия кнопки

  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
}

void bruder1_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER1 SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(1, memoryTime_day1);
    day_bruder1 = (currentTime_day - memoryTime_day1);
    lcd.setCursor(0, 0);
    lcd.print("1DayCnt = ");
    lcd.print(day_bruder1);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(1, memoryTime_day1 + 1);
      if (day_bruder1 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, memoryTime_day1 - 1);
      lcd.clear();
    }
    delay(del);

  }
}



//-------------------------------------------------------------------------

void bruder2_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER2 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(3, memoryTime_day2);
    day_bruder2 = (currentTime_day - memoryTime_day2);
    lcd.setCursor(0, 0);
    lcd.print("2DayCnt = ");
    lcd.print(day_bruder2);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(3, memoryTime_day2 + 1);
      if (day_bruder2 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(3, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, memoryTime_day2 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder3_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER3 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(5, memoryTime_day3);
    day_bruder3 = (currentTime_day - memoryTime_day3);
    lcd.setCursor(0, 0);
    lcd.print("3DayCnt = ");
    lcd.print(day_bruder3);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(5, memoryTime_day3 + 1);
      if (day_bruder3 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(5, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(5, memoryTime_day3 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder4_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER4 SETUP");
  delay (1000);
  lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(7, memoryTime_day4);
    day_bruder4 = (currentTime_day - memoryTime_day4);
    lcd.setCursor(0, 0);
    lcd.print("4DayCnt = ");
    lcd.print(day_bruder4);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(7, memoryTime_day4 + 1);
      if (day_bruder4 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(7, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(7, memoryTime_day4 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void thermostat1 () {

  float tempB1;
  float temp_idealB1;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB1 = analogRead(tempB1_pin); //читаем температуру первого брудера
  tempB1 = (tempB1 / 9.31); //переводим ее в градусы Цельсия.
  
  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 0);        //DEBUG
    lcd.print (day_bruder1);
    lcd.setCursor(3, 0);
    lcd.print(tempB1, 0);   //DEBUG

    windowStartTime += WindowSize;
    currentTime = millis();
  }

      
  if (tempB1 < temp_idealB1) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater1, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater1, LOW);
    }
  }        //включаем обогрев
  else if (tempB1 > (temp_idealB1 + histeresis)) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater1, LOW);
  }   //то обогрев отключаем

}

//-------------------------------------------------------------------

void thermostat2 () {

  float tempB2;
  float temp_idealB2;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB2 = analogRead(tempB2_pin); //читаем температуру первого брудера
  tempB2 = (tempB2 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(9, 0);        //DEBUG
    lcd.print (day_bruder2);
    lcd.setCursor(12, 0);
    lcd.print(tempB2, 0);   //DEBUG
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB2 < temp_idealB2) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater2, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater2, LOW);
    }


  }        //включаем обогрев
  else if (tempB2 > temp_idealB2 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater2, LOW);
  }   //то обогрев отключаем

}
//-------------------------------------------------------------------

void thermostat3 () {

  float tempB3;
  float temp_idealB3;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB3 = analogRead(tempB3_pin); //читаем температуру первого брудера
  tempB3 = (tempB3 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 1);        //DEBUG
    lcd.print (day_bruder3);
    lcd.setCursor(3, 1);
    lcd.print(tempB3, 0);   //DEBUG
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB3 < temp_idealB3) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater3, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater3, LOW);
    }


  }        //включаем обогрев
  else if (tempB3 > temp_idealB3 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater3, LOW);
  }   //то обогрев отключаем


}

//---------------------------------------------------------------------

void thermostat4 () {

  float tempB4;
  float temp_idealB4;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB4 = analogRead(tempB4_pin); //читаем температуру первого брудера
  tempB4 = (tempB4 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(9, 1);        //DEBUG
    lcd.print (day_bruder4);
    lcd.setCursor(12, 1);
    lcd.print(tempB4, 0);   //DEBUG
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB4 < temp_idealB4) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater4, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater4, LOW);
    }


  }        //включаем обогрев
  else if (tempB4 > temp_idealB4 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater4, LOW);
  }   //то обогрев отключаем


}

void dimmer_setup() {

  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(9, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 0);
    lcd.print("Dimmer% = ");
    lcd.print(dimmer);
    lcd.setCursor(0, 1);
    lcd.print("Dim-5 NEXT Dim+5");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 5;
      if (dimmer < 10) {
        dimmer = 10;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      dimmer = dimmer + 5;
      if (dimmer > 95) {
        dimmer = 95;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }
    delay(del);
  }
}

void temp_ideal() { //если нажата кнопка минус, выводим на дисплей идеальную температуру для брудеров
  //  в зависимости от дня отсидки

  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("TEMP-IDEAL");
  delay (1000);
  lcd.clear();

  float temp_idealB1;
  float temp_idealB2;
  float temp_idealB3;
  float temp_idealB4;

  lcd.clear();

  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  lcd.setCursor(0, 0);        //DEBUG
  lcd.print (day_bruder1);
  lcd.setCursor(3, 0);
  lcd.print(temp_idealB1, 0);   //DEBUG

  lcd.setCursor(9, 0);        //DEBUG
  lcd.print (day_bruder2);
  lcd.setCursor(12, 0);
  lcd.print(temp_idealB2, 0);   //DEBUG

  lcd.setCursor(0, 1);        //DEBUG
  lcd.print (day_bruder3);
  lcd.setCursor(3, 1);
  lcd.print(temp_idealB3, 0);   //DEBUG

  lcd.setCursor(9, 1);        //DEBUG
  lcd.print (day_bruder4);
  lcd.setCursor(12, 1);
  lcd.print(temp_idealB4, 0);   //DEBUG

  delay(4000);
  lcd.clear();
  return;
}

void time_display() {

  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("DATE-TIME");
  delay (1000);
  lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(6, 0);
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  lcd.setCursor(4, 1);
  lcd.print(now.day(), DEC);
  lcd.print(".");
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  delay(4000);
  lcd.clear();
  return;
}

Свежий код. Работает приемлемо. Архив с печаткой в аттаче. Платы две, силовая и управления. Вторая в первую втыкается. В плату управления втыкаются ПроМини, часы, дисплей на 4-проводном шлейфе. Кнопки тактовые и светодиоды прямо на плате. Собран в железе, идет тестироване в реальных условиях. 

На очереди проект сольного брудера, на Даллас-термометрах и с энкодером.

https://docs.google.com/file/d/0B0vRuSZ7oRUeSUdobXhId2RxTU0/edit

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

вы освоили изготовление двухсторонних печатных плат или заказывать будете?

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

Могу, я же профессиональный р-техник. И лазерным утюгом и фоторезистом. Но это не двухсторонняя плата, это бутерброд из 2-х плат (зелененькая снизу, точки перехода голубые). Как Уно с шилдом примерно. Сделал так потому, что 220В на плате с микроконтроллером иметь не хочется и влияние помех от силовой части тоже нам не нужно, аналоговый термометр и так лагает здорово.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а понятно. вот только там одинокий штырек стоит. так и будете делать?

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

а так очень симпатично получается и удобно

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

Да, одинокий штырек это =12в (raw) для управления вентиляцией. Защита от перегрева. А вентиляторы в большинстве 12-вольтовые. Я не планировал вентиляцию делать, а двигать потом все дорожки лень было. Дело в том, что у LM35 даже с экранированным проводом иногда скачки показаний странные случаются, даже не иногда, а постоянно. Будет дергаться вентилятор без нужды. Я даже код не стал править под это дело, так, на будущее заготовка. Хотя можно перемычку до ближайшего разъема кинуть. Щас дорисую. А в сольной версии я хочу к DS18B20 вернуться, там вентиляцию можно ставить.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

у вас будут большие токи что понадобится вентилятор?

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

и библиотека есть под ардуино

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

Я применял в инкубаторе ПИД, работает. Даже визуализатор где-то нашел на Processing. Но для брудера это перебор имхо. Хватит и диммера. Перегрев не прибора я имел ввиду, а самого брудера и малышей в нем. Ну, летом солнце жарко греет и сами малыши как подрастают, занимают гораздо больший объем в маленькой клетке и горячие. У кур и перепелок температура тела 42 градуса! Ну или симистор пробъет и нагреватель на полную включится. Туда бы термопредохранитель вкрячить, да не нашел подходящего пока.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

так зачем симистор. можно же применить 12В компьютерные вентиляторы. а если так критично можно и систему вентиляции сделать автономную, в смысле отдельный блок управления хоть на тиньке13

а термопредохранитель какую функцию должен выполнять? выключать брудер при перегреве, или наоборот при определенной температуре включить?

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

Я наверное не совсем понятно рассказываю. Симисторы для обогревателя. Он от сети 220 питается. А на вентиляторы MOSFET ключики. С них 12в выходит на пропеллеры. Термопредохранитель прямо в нагревательный элемент можно встроить, они биметаллические бывают и на разную температуру, например на 60 градусов. Самовосстанавливающиеся при остывании. С ними нагреватель не нагреется больше заданного предела и не зажарит малышей. Вот как-то так. Но вентилятор тоже не помешает. Когда жарко птички плохо кушают и много пьют, а значит в росте теряют. Если за первые 2 недели не наберут нужный вес, то могут так и остаться маленькими, ну в смысле в росте будут сильно отставать и дальше, при хорошем питании. Этот возраст самый важный пожалуй в жизни птицы. С вентиляцией лучше этой же программе работать, т.к. в первые сутки оптимальная температура для мальков 37, значит перегрев будет от 39 и выше, а в 20-е сутки уже 23 градуса нужно, значит перегрев можно при 26 включать. Тиньку кто этому обучит? Ей тогда тоже часы нужно.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

давайте посмотрим так. допустим стоит обогреватель, снаружи температура +20, внутри должно быть 37. стало быть включаем обогреватель.

тут ведь еще интересный момент. обогреватель какого типа: массивный радиатор долго остывающий, или "тонкий", быстроостывающий есть выключить, с вентилятором для улучшения теплообмена или нет, какая площать теплообмена.

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

таким из-за инерции нагрева/остывания будет немного сложнее поддерживать точную температуру например 37+-0,5градуса

а еще. если низкая площать теплообмена для обогрева он достаточно сильно будет нагреваться, может до 60-90 градусов (а может и выше), при этом нормально и правильно обогревать.

и при разной окружающей температуре при необходимой 37градусов будет например нагреваться от 50 до 120 градусов. надо проверять. и непонятно какой ставить термопредохранитель.

если на температуру нагревателя при самой низкой окружающей среде (например 120 градусов нагреватель, окружающая -10,), то при окружающей например +20, срабатывание термопредохранителя на 120 градусах бесполезно. циплятки уже сдохнут, температура поднимется наверно градусов до 50-60

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

и кстати можно поставить доп. защиту. схемотехническую. добавить узел например с транзитором, конденсаторами и резистором. подключить к ардуине. ардуина каждый раз прогоняя loop должна ненадолго подать на базу транзистора через конденсатор испульс. постоянку кондер не пропустит, так что постоянная 0 или 1 будет сигнализировать об аварии. транзистор отключит обогреватель и например подаст сигнал сброса на микроконтроллер (через конденсатор). ну и может дополнительно пищалка.

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

можно конечно ватчдогом, но если питание на ардуине пропало, ардуина сдохла ватчдог не поможет

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

Не, все гораздо проще. Брудер в помещении отапливаемом обычно стоит, у меня в перепелятнике. Перепелка птица перелетная и зимою без обогрева не выживет. Но птичек в клетках много, помещение маленькое и они сами неплохо греют, плюс дополнительная грелка электрическая висит с термостатом примитивным. Короче температура в помещении всегда близка к 20 градусам. Брудер это почти инкубатор, никто ведь инкубаторы под открытым небом не ставит. Ну вот свой брудер не выкладывал, но примерно такой вот принцып. 

Авария на перегрев может быть по двум причинам. Ардуино зависла или симистор пробился. Вочдог от зависания спасет, а от пробоя симистора нет. Там либо доп. реле ставить в цепь обогревателя, либо термопредохранитель в сам обогреватель. Обогреватель вот такой. http://www.youtube.com/watch?v=ydcrHtKhty8 точнее он и есть. Его задача имитировать курицу, то есть теплоемкий, инерционный, мощный, но не горячий. В идеале 40-45 градусов. Чтобы к нему малыши могли подойти близко и погреться, а когда жарко отходили. Значит должны быть зоны где теплее и холоднее. Зоны должны быть достаточными по площади, иначе подавят слабых когда толпиться будут. Ну это я по сути азбуку птицеводства рассказываю. Это в каждом брудере должно так быть. Обычно лампами греют или термопленкой продвинутые. Но у нас то умный брудер. В коде программы есть ШИМ низкочастотный постоянный, он в меню задается с шагом в 5%. Я на столе когда гонял блок с нагревателем, выяснил что при 30% мощности сам нагреватель греется до 55. Но это в комнате большой, в брудере будет иначе. Ну и термостат обычный, на релейном принцыпе (вкл-выкл) с гистерезисом в градус. Цыплята это не яйца в инкубаторе, им точность в 0,5 градусов не нужна. + - 3 вполне приемлемо, а если в помещении температура постоянная (летом еще и вентиляция включается), то не сложно будет подобрать мощность диммером (это кусок программы по сути, простой ШИМ с регулируемой скважностью. Это я его диммером зову как отдельное устройство), просто понаблюдать за хорошим  спиртовым термометром и самими квартирантами. Поэтому и термопредохранитель лучше в сам нагреватель встроить и на 50-60 градусов чтоб срабатывал. Тогда аварии не должно быть и никто не зажарится и ничего не загорится. Вот.

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

В сольной версии автоматики будет другой алгоритм. Возьмем два Далласа (DS18B20), один для воздуха в клетке, другой для самого обогревателя. И вентилятор для охлаждения. Тогда полную гибкость получим. Можно даже вентилятором заданную температуру поддерживать, а грелку все время теплую держать. Хотя под конец срока отсидки тогда будет постоянно жужжать вентилятор. Можно снижать планово температуру грелки. Короче обмозговать надо. Но защиту всеравно в виде термопредохранителя не помешает добавить. Я бы и сюда Далласы поставил, но 8 шт. (4 пары) это дорого, они медленные и вообще, у меня куча LM35 давно валяется без дела. 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

я бы предложил термореле. встроить в сам нагреватель. например такие на 50 или 560 градусов (не реклама, просто первое где нашел)

http://tda2000.ru/catalog/passiw_predoxranitel_fuse_rele/-464449/

http://tda2000.ru/catalog/passiw_predoxranitel_fuse_rele/-496378/

основательный вы птичник сделали

 

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

jeka_tm пишет:

я бы предложил термореле. встроить в сам нагреватель.

Ну, я про них и говорил. У китайцев еще дешевле. У меня есть несколько, но на другую температуру. А таких пока нету. Да, симистор 26-амперный, скорее провода сгорят, чем он. Но лучше перебдеть...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да лучше перебдеть

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


#include <Wire.h>
#include <OneWire.h> 
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>
#include <Encoder.h>

//EEPROM1 - день старта программы в брудере
//EEPROM2 - максимальная температура обогревателя
//EEPROM3 - диммер (мощность нагревателя в %)
//


int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
int histeresis = 1;               //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 100;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;                //длина окна регулировки мощности

unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned long loopTimeEncoder;    //переменная для опроса энкодера по таймеру
unsigned int currentTime_day;     //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)

unsigned char clockwise = 0;  //вращение энкодера по часовой стрелке
unsigned char counterclockwise = 0;   //вращение энкодера против часовой
unsigned char encoderButton = 0; //нажатие кнопки энкодера

unsigned int memoryTime_day;      //хранящийся в памяти день старта первого брудера
const int temp_pin = 1;           // К какому пину подключены Далласы
const int heater_pin = 5;         //пин нагревателя брудера
const int encoderButton_pin = 4;  //кнопка энкодера
unsigned int day_bruder;         //день работы программы в брудере
//float temp_to_bruder;
//unsigned int tempOfHeater;       //
long oldPosition  = 500;

LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;
OneWire oneWire(temp_pin);
DallasTemperature sensors(&oneWire);
Encoder myEnc(2, 3);


void setup() {

  Serial.begin(9600);  // Старт сериал-порта
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(encoderButton_pin, INPUT);
  digitalWrite(encoderButton_pin, HIGH);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  loopTimeEncoder = currentTime;
  sensors.begin();
  sensors.setResolution(12);    // установить разрешение (точность)
  sensors.setWaitForConversion(false);  // отключить ожидание

  DateTime now = RTC.now();  //получам текущее время из часов
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени
  //EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //EEPROM_write(3, 60); //максимальная температура нагревателя по умолчаню
}



void loop() {

  EEPROM_read(1, memoryTime_day);   //читаем из памяти дату первого дня брудера
  DateTime now = RTC.now();         //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder = (currentTime_day - memoryTime_day);
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  encoder(); //читаем энкодер 

  if (clockwise){     //если вращение по часовой стрелке, показываем дату-время
    delay(del);
    lcd.clear();
    display_time();
    clockwise = 0;
  }

  if (counterclockwise){ //если вращение против часовой, показываем идеальную температуру в брудере для текущего дня
    delay(del);
    lcd.clear();
    temp_ideal();
    counterclockwise = 0;
  }

  if (encoderButton){  //если нажата кнопка энкодера, то переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }

  termostat();    //выполняем функцию термостата

}//конец основного цикла.




void encoder(){

  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    if (newPosition >= oldPosition + 7){
      clockwise = 1;
    }
    if (newPosition <= oldPosition - 7){
      counterclockwise = 1;
    }
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  else {
    clockwise = 0;
    counterclockwise = 0;
  }

  if (digitalRead(encoderButton_pin) == LOW )  {
    delay(del);
    encoderButton = 1;
  }
  if (digitalRead(encoderButton_pin) == HIGH )  {
    delay(del);
    encoderButton = 0;
  }
}


void menu(){  //функция отображения меню

  dayOfBruder_setup();
  tempOfHeater_setup();
  dimmer_setup();
  alarm_setup();
}


void display_time(){  //функция отображения даты-времени в часах
  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("DATE-TIME");
  Serial.println("DATE-TIME");
  delay (1000);
  lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(6, 0);
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  lcd.setCursor(4, 1);
  lcd.print(now.day(), DEC);
  lcd.print(".");
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print("   ");
  Serial.print(now.day(), DEC);
  Serial.print(".");
  Serial.print(now.month(), DEC);
  Serial.print(".");
  Serial.println(now.year(), DEC);

  delay(4000);
  lcd.clear();
  Serial.println("done");
  return;
}



void temp_ideal(){  //функция отображения идеальной температуры для брудера
  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("TEMP-IDEAL");
  Serial.print("TEMP-IDEAL");

  delay (1000);
  lcd.clear();

  float temp_ideal; 
  if (day_bruder >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_ideal = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_ideal = map(day_bruder, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.

  lcd.setCursor(0, 0);      //печатаем на дисплей день в брудере  
  lcd.print (day_bruder);   // и идеальную температуру для этого дня
  Serial.println (day_bruder);
  lcd.setCursor(3, 0);
  lcd.print(temp_ideal, 1);
  Serial.println(temp_ideal, 1);
  delay(4000);              //ждем 4 секунды и возврат в основной экран.
  lcd.clear();
  Serial.println("done");
  return;
}


void termostat(){    //функция терморегулятора
  //Serial.print("requets temperature...");
  sensors.requestTemperatures(); 
  //Serial.println("complete");
  float temp_ideal;
  unsigned int tempHeater_max;
  float temp_to_bruder = sensors.getTempCByIndex(0);
  float temp_to_heater = sensors.getTempCByIndex(1);
  Serial.print("Temp into bruder: ");
  Serial.print(temp_to_bruder); 
  Serial.print("  Temp of heater: ");
  Serial.println(temp_to_heater); 
  EEPROM_read(3, tempHeater_max);

  if (day_bruder >= 24.0) {  //если программа в брудере работет 24 дней или больше
    temp_ideal = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_ideal = map(day_bruder, 0, 24, 37, 20)); //иначе преобразуем день работы в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(9, 1);        //DEBUG
    lcd.print (day_bruder);
    //Serial.println (day_bruder);
    lcd.setCursor(12, 1);
    lcd.print(temp_to_bruder, 1);   //DEBUG
    //Serial.println(temp_to_bruder, 1);
    windowStartTime += WindowSize;
    currentTime = millis();
  }
  if (temp_to_heater > tempHeater_max){
    digitalWrite(heater_pin, LOW);
  }

  if (temp_to_bruder < temp_ideal) {    //если температура в 1 брудере ниже идеальной

    if ((currentTime - windowStartTime < 10 * dimmer)&&(temp_to_heater < tempHeater_max)) {
      digitalWrite(heater_pin, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater_pin, LOW);
    }

  }        //включаем обогрев
  else if (temp_to_bruder > temp_ideal + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater_pin, LOW);
  }   //то обогрев отключаем                
}

void dayOfBruder_setup(){  // функция установки дня работы программы брудера
  lcd.clear();
  delay(del);
  lcd.setCursor(0, 0);
  lcd.print("BRUDER SETUP");
  Serial.println("BRUDER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {      //бесконечный цикл
    delay(del);
    x++;
    if (x > interval) { 
      Serial.println("timeout");
      break;
    }
    encoder();
    EEPROM_read(1, memoryTime_day);
    day_bruder = (currentTime_day - memoryTime_day);
    if (day_bruder > 100) {     //проверяем, если прошло больше 100 дней
      DateTime now = RTC.now();  //получам текущее время из часов
      EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      day_bruder = (currentTime_day - memoryTime_day); //читаем сегодня из памяти
    }
    lcd.setCursor(0, 0);
    lcd.print("DayCnt = ");
    Serial.print("DayCnt = ");
    lcd.print(day_bruder);
    Serial.println(day_bruder);
    lcd.setCursor(0, 1);
    lcd.print("Day-1 NEXT Day+1");

    if (encoderButton) {
      delay(del);
      lcd.clear(); //очищаем экран
      Serial.println("done");
      break;
    }
    if (clockwise) {
      delay(del);
      EEPROM_write(1, memoryTime_day + 1);
      lcd.clear();
    }

    if (counterclockwise) {
      delay(del);
      EEPROM_write(1, memoryTime_day - 1);
      lcd.clear();
    }
  } 
}

void tempOfHeater_setup(){ //установка максимальной температуры нагревателя.
  unsigned int tempHeater_max;    //
  EEPROM_read(3, tempHeater_max); // 
  lcd.clear();
  delay(del);
  lcd.setCursor(0, 0);
  lcd.print("MaxTempH. SETUP");
  Serial.println("MaxTempH. SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) { ////бесконечный цикл
    delay(del);
    x++;
    if (x > interval) { 
      Serial.println("timeout");
      break;
    }
    encoder();
    EEPROM_read(3, tempHeater_max); // 
    lcd.setCursor(0, 0);
    lcd.print("MaxTemp = ");
    Serial.print("MaxTemp = ");
    lcd.print(tempHeater_max);
    Serial.println(tempHeater_max);
    lcd.setCursor(0, 1);
    lcd.print("Temp-2 NEXT Temp+2");

    if (encoderButton) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (clockwise) {
      delay(del);
      EEPROM_write(3, tempHeater_max - 2);
      lcd.clear();
    }

    if (counterclockwise) {
      delay(del);
      EEPROM_write(3, tempHeater_max + 2);
      lcd.clear();
    }
  }
}

void dimmer_setup() {
  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  Serial.println("DIMMER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    delay(del);
    x++;
    if (x > interval) {
      lcd.clear();
      Serial.println("timeout");
      break;
    }

    encoder();
    EEPROM_read(5, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 0);
    lcd.print("Dimmer% = ");
    Serial.print("Dimmer% = ");
    lcd.print(dimmer);
    Serial.println(dimmer);
    lcd.setCursor(0, 1);
    lcd.print("Dim-5 NEXT Dim+5");

    if (encoderButton) {  //если кнопка энкодера, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (clockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 5;
      if (dimmer < 10) { //не ниже 10%
        dimmer = 10;
      }
      EEPROM_write(5, dimmer);
      lcd.clear();
    }

    if (counterclockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      dimmer = dimmer + 5;
      if (dimmer > 95) {  //не выше 95%
        dimmer = 95;
      }
      EEPROM_write(5, dimmer);
      lcd.clear();
    }
  }
}


void alarm_setup(){


}//

Дело движется. Набросал макет сольного брудера. В качестве термометров DS18B20. Управление меню энкодером. Один термометр в брудере, второй в (возле) нагревателе. Добавил в меню максимальную температуру нагревателя. Осталось аварийную вентиляцию и аварии добавить, правда не знаю какие. Пока дисплей едет, параметры впорт вывожу. Плату пока не рисовал. Вот свежий код, на макетке все работает.

 

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

Готов код сольного брудера. Управляется энкодером, дисплей двустрочный.

#include <Wire.h>
#include <OneWire.h> 
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>
#include <Encoder.h>

//EEPROM1 - день старта программы в брудере
//EEPROM3 - максимальная температура обогревателя
//EEPROM5 - диммер (мощность нагревателя в %)
//EEPROM7 - температура включения вентилятора.


int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
int histeresis = 1;               //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 100;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;             //длина окна регулировки мощности

int ventTemp;                    //Переменная для температуры вентиляции
unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned long loopTimeEncoder;    //переменная для опроса энкодера по таймеру
unsigned int currentTime_day;     //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)

unsigned char clockwise = 0;  //вращение энкодера по часовой стрелке
unsigned char counterclockwise = 0;   //вращение энкодера против часовой
unsigned char encoderButton = 0; //нажатие кнопки энкодера

unsigned int memoryTime_day;      //хранящийся в памяти день старта первого брудера
const int temp_pin = 2;           // К какому пину подключены Далласы
const int heater_pin = 13;         //пин нагревателя брудера
const int vent_pin = 9;          //Пин вентилятора
const int encoderButton_pin = 5;  //кнопка энкодера
unsigned int day_bruder;         //день работы программы в брудере
//float temp_to_bruder;
//unsigned int tempOfHeater;       //
long oldPosition  = 500;

LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;
OneWire oneWire(temp_pin);
DallasTemperature sensors(&oneWire);
Encoder myEnc(3, 4);


void setup() {

  Serial.begin(9600);  // Старт сериал-порта
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(encoderButton_pin, INPUT);
  digitalWrite(encoderButton_pin, HIGH);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  loopTimeEncoder = currentTime;
  sensors.begin();
  sensors.setResolution(12);    // установить разрешение (точность)
  sensors.setWaitForConversion(false);  // отключить ожидание

  DateTime now = RTC.now();  //получам текущее время из часов
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени
  //EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //EEPROM_write(3, 60); //максимальная температура нагревателя по умолчаню
}



void loop() {

  EEPROM_read(1, memoryTime_day);   //читаем из памяти дату первого дня брудера
  DateTime now = RTC.now();         //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder = (currentTime_day - memoryTime_day);
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  encoder(); //читаем энкодер 

  if (clockwise){     //если вращение по часовой стрелке, показываем дату-время
    delay(del);
    lcd.clear();
    display_time();
    clockwise = 0;
  }

  if (counterclockwise){ //если вращение против часовой, показываем идеальную температуру в брудере для текущего дня
    delay(del);
    lcd.clear();
    temp_ideal();
    counterclockwise = 0;
  }

  if (encoderButton){  //если нажата кнопка энкодера, то переходим в меню
    delay(del/2);
    lcd.clear();
    menu();
  }

  termostat();    //выполняем функцию термостата

}//конец основного цикла.




void encoder(){

  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    if (newPosition >= oldPosition + 7){
      clockwise = 1;
    }
    if (newPosition <= oldPosition - 7){
      counterclockwise = 1;
    }
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  else {
    clockwise = 0;
    counterclockwise = 0;
  }

  if (digitalRead(encoderButton_pin) == LOW )  {
    delay(del/2);
    encoderButton = 1;
  }
  if (digitalRead(encoderButton_pin) == HIGH )  {
    delay(del/2);
    encoderButton = 0;
  }
}


void menu(){  //функция отображения меню

  dayOfBruder_setup();
  tempOfHeater_setup();
  dimmer_setup();
  vent_setup();

}


void display_time(){  //функция отображения даты-времени в часах
  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("DATE-TIME");
  Serial.println("DATE-TIME");
  delay (1000);
  lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(6, 0);
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  lcd.setCursor(4, 1);
  lcd.print(now.day(), DEC);
  lcd.print(".");
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print("   ");
  Serial.print(now.day(), DEC);
  Serial.print(".");
  Serial.print(now.month(), DEC);
  Serial.print(".");
  Serial.println(now.year(), DEC);

  delay(4000);
  lcd.clear();
  Serial.println("done");
  return;
}



void temp_ideal(){  //функция отображения идеальной температуры для брудера
  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("TEMP-IDEAL");
  Serial.print("TEMP-IDEAL");

  //delay (1000);
  //lcd.clear();

  float temp_ideal; 
  if (day_bruder >= 24.0) {  //если программа в брудере работет 24 дней или больше
    temp_ideal = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_ideal = map(day_bruder, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.

  lcd.setCursor(0, 1);      //печатаем на дисплей день в брудере
  lcd.print("Day=");  
  lcd.print (day_bruder);   // и идеальную температуру для этого дня
  Serial.println (day_bruder);
  lcd.setCursor(7, 1);
  lcd.print("t.i=");
  lcd.print(temp_ideal, 1);
  lcd.print((char)223);
  Serial.println(temp_ideal, 1);
  delay(4000);              //ждем 4 секунды и возврат в основной экран.
  lcd.clear();
  Serial.println("done");
  return;
}


void termostat(){    //функция терморегулятора
  //Serial.print("requets temperature...");
  sensors.requestTemperatures(); 
  //Serial.println("complete");
  float temp_ideal;
  unsigned int tempHeater_max;
  float temp_to_bruder = sensors.getTempCByIndex(0);
  float temp_to_heater = sensors.getTempCByIndex(1);
  Serial.print("Temp into bruder: ");
  Serial.print(temp_to_bruder); 
  Serial.print("  Temp of heater: ");
  Serial.println(temp_to_heater); 
  EEPROM_read(3, tempHeater_max);

  if (day_bruder >= 24.0) {  //если программа в брудере работет 24 дней или больше
    temp_ideal = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_ideal = map(day_bruder, 0, 24, 37, 20)); //иначе преобразуем день работы в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    //DateTime now = RTC.now();
    lcd.setCursor(0, 0);
    lcd.print("h.=");
    lcd.print(temp_to_heater,0);
    lcd.print((char)223);
    //lcd.print(now.hour(), DEC);
    //lcd.print(":");
    //lcd.print(now.minute(), DEC);
    lcd.setCursor(9,0);
    lcd.print("i.=");
    lcd.print(temp_ideal,0);
    lcd.print((char)223);
    lcd.setCursor(0, 1);        //DEBUG
    lcd.print("Day=");
    lcd.print (day_bruder);
    //Serial.println (day_bruder);
    lcd.setCursor(9, 1);
    lcd.print("T=");
    lcd.print(temp_to_bruder, 0);   //DEBUG
    lcd.print((char)223);
    //Serial.println(temp_to_bruder, 1);
    windowStartTime += WindowSize;
    currentTime = millis();
  }
  if (temp_to_heater > tempHeater_max){
    digitalWrite(heater_pin, LOW);
  }

  if (temp_to_bruder < temp_ideal) {    //если температура в брудере ниже идеальной

    if ((currentTime - windowStartTime < 10 * dimmer)&&(temp_to_heater < tempHeater_max)) {
      digitalWrite(heater_pin, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater_pin, LOW);
    }

  }        //включаем обогрев
  else if (temp_to_bruder > temp_ideal + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater_pin, LOW);
  }   //то обогрев отключаем 
  if (temp_to_bruder > ventTemp){
    digitalWrite(vent_pin, HIGH);
  } 
  if (temp_to_bruder < ventTemp - 1){
    digitalWrite(vent_pin, LOW); 
  }
}

void dayOfBruder_setup(){  // функция установки дня работы программы брудера
  lcd.clear();
  delay(del);
  lcd.setCursor(2, 0);
  lcd.print("BRUDER SETUP");
  Serial.println("BRUDER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {      //бесконечный цикл
    delay(del);
    x++;
    if (x > interval) { 
      Serial.println("timeout");
      break;
    }
    encoder();
    EEPROM_read(1, memoryTime_day);
    day_bruder = (currentTime_day - memoryTime_day);
    if (day_bruder > 100) {     //проверяем, если прошло больше 100 дней
      DateTime now = RTC.now();  //получам текущее время из часов
      EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      day_bruder = (currentTime_day - memoryTime_day); //читаем сегодня из памяти
    }
    lcd.setCursor(2, 0);
    lcd.print("DayCnt = ");
    Serial.print("DayCnt = ");
    lcd.print(day_bruder);
    Serial.println(day_bruder);
    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {
      delay(del);
      lcd.clear(); //очищаем экран
      Serial.println("done");
      break;
    }
    if (clockwise) {
      delay(del);
      EEPROM_write(1, memoryTime_day + 1);
      lcd.clear();
    }

    if (counterclockwise) {
      delay(del);
      EEPROM_write(1, memoryTime_day - 1);
      lcd.clear();
    }
  } 
}

void tempOfHeater_setup(){ //установка максимальной температуры нагревателя.
  unsigned int tempHeater_max;    //
  EEPROM_read(3, tempHeater_max); // 
  lcd.clear();
  delay(del);
  lcd.setCursor(0, 0);
  lcd.print("MaxT.H. SETUP");
  Serial.println("MaxT.H. SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) { ////бесконечный цикл
    delay(del);
    x++;
    if (x > interval) { 
      Serial.println("timeout");
      break;
    }
    encoder();
    EEPROM_read(3, tempHeater_max); // 
    lcd.setCursor(0, 0);
    lcd.print("MaxTemp = ");
    Serial.print("MaxTemp = ");
    lcd.print(tempHeater_max);
    Serial.println(tempHeater_max);
    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (clockwise) {
      delay(del);
      if (tempHeater_max > 200){
        tempHeater_max = 32;
      }
      EEPROM_write(3, tempHeater_max - 2);
      lcd.clear();
    }

    if (counterclockwise) {
      delay(del);
      if (tempHeater_max < 30){
        tempHeater_max = 58;
      }
      EEPROM_write(3, tempHeater_max + 2);
      lcd.clear();
    }
  }
}

void dimmer_setup() {
  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  Serial.println("DIMMER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    delay(del);
    x++;
    if (x > interval) {
      lcd.clear();
      Serial.println("timeout");
      break;
    }

    encoder();
    EEPROM_read(5, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 0);
    lcd.print("Dimmer% = ");
    Serial.print("Dimmer% = ");
    lcd.print(dimmer);
    Serial.println(dimmer);
    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {  //если кнопка энкодера, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (clockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 5;
      if (dimmer < 10) { //не ниже 10%
        dimmer = 95;
      }
      EEPROM_write(5, dimmer);
      lcd.clear();
    }

    if (counterclockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      dimmer = dimmer + 5;
      if (dimmer > 95) {  //не выше 95%
        dimmer = 10;
      }
      EEPROM_write(5, dimmer);
      lcd.clear();
    }
  }
}


void vent_setup(){

  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("VENT. SETUP");
  Serial.println("VENT. SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    delay(del);
    x++;
    if (x > interval) {
      lcd.clear();
      Serial.println("timeout");
      break;
    }

    encoder();
    EEPROM_read(7, ventTemp);   //читаем из памяти уставку диммера
    if (ventTemp > 43 || ventTemp < 29){ //если там чушь, то включаем 1 режим.
      ventTemp = 39;
    }
    lcd.setCursor(0, 0);
    lcd.print("Vent.Temp = ");
    lcd.print(ventTemp);
    Serial.print("Vent.Temp = ");
    Serial.println(ventTemp);

    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {  //если кнопка энкодера, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (clockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      ventTemp --;
      if (ventTemp < 30) { //не ниже 10%
        ventTemp = 42;
      }
      EEPROM_write(7, ventTemp);
      lcd.clear();
    }

    if (counterclockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      ventTemp ++;
      if (ventTemp > 42) { //не ниже 10%
        ventTemp = 30;
      }
      EEPROM_write(7, ventTemp);
      lcd.clear();
    }
  }
}
//

Переписал код четырехствольного брудера под 20х4 дисплей.







 

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

Код четырехканального брудера переписал под дисплей 20х4 с I2C контроллером.

#include <Wire.h>
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
//#include <DallasTemperature.h>

int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
int histeresis = 1;             //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 50;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;                //длина окна регулировки мощности

unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned int currentTime_day;      //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)


unsigned int memoryTime_day1;      //хранящийся в памяти день старта первого брудера
unsigned int memoryTime_day2;
unsigned int memoryTime_day3;
unsigned int memoryTime_day4;

const int button_minus_pin = 2;    //пин кнопки "минус"
const int button_plus_pin = 3;     //пин кнопки "плюс"
const int button_enter_pin = 4;    //пин кнопки "enter"

const int tempB1_pin = A0;         //пин термометра первого брудера
const int tempB2_pin = A1;
const int tempB3_pin = A2;
const int tempB4_pin = A3;

const int heater1 = 5;             //пин нагревателя брудера1
const int heater2 = 6;
const int heater3 = 9;
const int heater4 = 10;

/*const int start1 = 8;             //пин тумблера запуска брудера1
 const int start2 = 9;
 const int start3 = 10;
 const int start4 = 11;*/

int button_minus = 0;              // переменная для хранения состояния кнопки "минус"
int button_plus = 0;               // переменная для хранения состояния кнопки "плюс"
int button_enter = 0;              // переменная для хранения состояния кнопки "enter"

//unsigned int days_count1;          //счетчик дней работы брудера1
unsigned int days_count2;
unsigned int days_count3;
unsigned int days_count4;

unsigned int day_bruder1;         //день работы программы в 1 брудере
unsigned int day_bruder2;
unsigned int day_bruder3;
unsigned int day_bruder4;





LiquidCrystal_I2C lcd(0x27, 20, 4); //инициализация библиотек
RTC_DS1307 RTC;


void setup() {

  //Serial.begin(9600);  // Старт сериал-порта
  analogReference(INTERNAL);  //для повышения точности делаем опорное Напр. 1.1В
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  
 
  lcd.init();          // Старт дисплея
  lcd.init();
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(button_minus_pin, INPUT); //задаем пины кнопок как входы
  pinMode(button_plus_pin, INPUT);
  pinMode(button_enter_pin, INPUT);

  pinMode(heater1, OUTPUT);         //задаем пины нагревателей как выходы
  pinMode(heater2, OUTPUT);
  pinMode(heater3, OUTPUT);
  pinMode(heater4, OUTPUT);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  DateTime now = RTC.now();  //получам текущее время из часов
  RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени


 //     EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
 //     EEPROM_write(3, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
 //     EEPROM_write(5, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
 //     EEPROM_write(7, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день

  EEPROM_read(1, memoryTime_day1); //читаем из памяти дату первого дня первого брудера
  EEPROM_read(3, memoryTime_day2);
  EEPROM_read(5, memoryTime_day3);
  EEPROM_read(7, memoryTime_day4);



}

void loop() {

  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder1 = (currentTime_day - memoryTime_day1);
  day_bruder2 = (currentTime_day - memoryTime_day2);
  day_bruder3 = (currentTime_day - memoryTime_day3);
  day_bruder4 = (currentTime_day - memoryTime_day4);


  //печатаем на дисплей текущую дату и время
  thermostat1();  //вызываем функцию терморегулятора 1 брудера
  thermostat2();
  thermostat3();
  thermostat4();


  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }
  if (button_minus) {
    delay(del);
    lcd.clear();
    temp_ideal();
  }
  if (button_plus) {
    delay(del);
    lcd.clear();
    time_display();
  }
}
void menu() {
  bruder1_setup();
  bruder2_setup();
  bruder3_setup();
  bruder4_setup();
  dimmer_setup();
  //data_time_setup();
}

void button_read() {//функция проверки нажатия кнопки

  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
}

void bruder1_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER1 SETUP");
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(1, memoryTime_day1);
    day_bruder1 = (currentTime_day - memoryTime_day1);
    lcd.setCursor(0, 1);
    lcd.print("1 DayCnt = ");
    lcd.print(day_bruder1);
    lcd.setCursor(0,2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(1, memoryTime_day1 + 1);
      if (day_bruder1 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, memoryTime_day1 - 1);
      lcd.clear();
    }
    delay(del);

  }
}



//-------------------------------------------------------------------------

void bruder2_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER2 SETUP");
  //delay (1000);
  //lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(3, memoryTime_day2);
    day_bruder2 = (currentTime_day - memoryTime_day2);
    lcd.setCursor(0, 1);
    lcd.print("2 DayCnt = ");
    lcd.print(day_bruder2);
    lcd.setCursor(0,2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(3, memoryTime_day2 + 1);
      if (day_bruder2 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(3, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, memoryTime_day2 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder3_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER3 SETUP");
  //delay (1000);
  //lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(5, memoryTime_day3);
    day_bruder3 = (currentTime_day - memoryTime_day3);
    lcd.setCursor(0, 1);
    lcd.print("3 DayCnt = ");
    lcd.print(day_bruder3);
    lcd.setCursor(0,2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(5, memoryTime_day3 + 1);
      if (day_bruder3 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(5, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(5, memoryTime_day3 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder4_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER4 SETUP");
  //delay (1000);
  //lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(7, memoryTime_day4);
    day_bruder4 = (currentTime_day - memoryTime_day4);
    lcd.setCursor(0, 1);
    lcd.print("4 DayCnt = ");
    lcd.print(day_bruder4);
    lcd.setCursor(0,2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(7, memoryTime_day4 + 1);
      if (day_bruder4 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(7, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(7, memoryTime_day4 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void thermostat1 () {

  float tempB1;
  float temp_idealB1;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB1 = analogRead(tempB1_pin); //читаем температуру первого брудера
  tempB1 = (tempB1 / 9.31); //переводим ее в градусы Цельсия.
  
  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 0);
    lcd.print("1 Day-");
    lcd.print (day_bruder1);
    lcd.setCursor(9, 0);
    lcd.print("r-");
    lcd.print(tempB1, 0);
    lcd.print((char)223);   
    lcd.setCursor(15, 0);
    lcd.print("i-");
    lcd.print(temp_idealB1, 0);
    lcd.print((char)223);   

    windowStartTime += WindowSize;
    currentTime = millis();
  }

      
  if (tempB1 < temp_idealB1) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater1, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater1, LOW);
    }
  }        //включаем обогрев
  else if (tempB1 > (temp_idealB1 + histeresis)) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater1, LOW);
  }   //то обогрев отключаем

}

//-------------------------------------------------------------------

void thermostat2 () {

  float tempB2;
  float temp_idealB2;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB2 = analogRead(tempB2_pin); //читаем температуру первого брудера
  tempB2 = (tempB2 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 1);
    lcd.print("2 Day-");
    lcd.print (day_bruder2);
    lcd.setCursor(9, 1);
    lcd.print("r-");
    lcd.print(tempB2, 0);
    lcd.print((char)223);  
    lcd.setCursor(15, 1);
    lcd.print("i-");
    lcd.print(temp_idealB2, 0);
    lcd.print((char)223);  
    
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB2 < temp_idealB2) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater2, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater2, LOW);
    }


  }        //включаем обогрев
  else if (tempB2 > temp_idealB2 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater2, LOW);
  }   //то обогрев отключаем

}
//-------------------------------------------------------------------

void thermostat3 () {

  float tempB3;
  float temp_idealB3;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB3 = analogRead(tempB3_pin); //читаем температуру первого брудера
  tempB3 = (tempB3 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 2);
    lcd.print("3 Day-");
    lcd.print (day_bruder3);
    lcd.setCursor(9, 2);
    lcd.print("r-");
    lcd.print(tempB3, 0);
    lcd.print((char)223);  
    lcd.setCursor(15, 2);
    lcd.print("i-");
    lcd.print(temp_idealB3, 0);
    lcd.print((char)223);  
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB3 < temp_idealB3) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater3, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater3, LOW);
    }


  }        //включаем обогрев
  else if (tempB3 > temp_idealB3 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater3, LOW);
  }   //то обогрев отключаем


}

//---------------------------------------------------------------------

void thermostat4 () {

  float tempB4;
  float temp_idealB4;

  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  tempB4 = analogRead(tempB4_pin); //читаем температуру первого брудера
  tempB4 = (tempB4 / 9.31); //переводим ее в градусы Цельсия.

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 3);
    lcd.print("4 Day-");
    lcd.print (day_bruder4);
    lcd.setCursor(9, 3);
    lcd.print("r-");
    lcd.print(tempB4, 0);
    lcd.print((char)223);  
    lcd.setCursor(15, 3);
    lcd.print("i-");
    lcd.print(temp_idealB4, 0);
    lcd.print((char)223);  
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB4 < temp_idealB4) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater4, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater4, LOW);
    }


  }        //включаем обогрев
  else if (tempB4 > temp_idealB4 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater4, LOW);
  }   //то обогрев отключаем


}

void dimmer_setup() {

  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(9, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 1);
    lcd.print("Dimmer% = ");
    lcd.print(dimmer);
    lcd.setCursor(0,2);
  lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Dim-5  NEXT  Dim+5");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 5;
      if (dimmer < 10) {
        dimmer = 10;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      dimmer = dimmer + 5;
      if (dimmer > 95) {
        dimmer = 95;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }
    delay(del);
  }
}

void temp_ideal() { //если нажата кнопка минус, выводим на дисплей идеальную температуру для брудеров
  //  в зависимости от дня отсидки

  delay(del);
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("TEMP-IDEAL");
  delay (1000);
  lcd.clear();

  float temp_idealB1;
  float temp_idealB2;
  float temp_idealB3;
  float temp_idealB4;

  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  lcd.setCursor(0, 0);
  lcd.print("1 Day-");
  lcd.print (day_bruder1);
  lcd.setCursor(9, 0);
  lcd.print("i-");
  lcd.print(temp_idealB1, 0);
  lcd.print((char)223);  
  

  lcd.setCursor(0, 1);
  lcd.print("2 Day-");
  lcd.print (day_bruder2);
  lcd.setCursor(9, 1);
  lcd.print("i-");
  lcd.print(temp_idealB2, 0);
  lcd.print((char)223);  

  lcd.setCursor(0, 2);
  lcd.print("3 Day-");
  lcd.print (day_bruder3);
  lcd.setCursor(9, 2);
  lcd.print("i-");
  lcd.print(temp_idealB3, 0);
  lcd.print((char)223);  

  lcd.setCursor(0, 3);
  lcd.print("4 Day-");
  lcd.print (day_bruder4);
  lcd.setCursor(9, 3);
  lcd.print("i-");
  lcd.print(temp_idealB4, 0);
  lcd.print((char)223);  

  delay(4000);
  lcd.clear();
  return;
}

void time_display() {

  delay(del);
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("DATE-TIME");
  //delay (1000);
  //lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(7, 1);
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  lcd.setCursor(5, 2);
  lcd.print(now.day(), DEC);
  lcd.print(".");
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  delay(4000);
  lcd.clear();
  return;
}

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

так все работает как надо? на цыплятках уже опробовано?

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

Не, на столе пока работает, а обогреватель под столом. Деталюшек не хватает на все каналы, а если так поставлю, то снимать уже не захочу, ждемс. И кнопки тактовые вчера рассыпались.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

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

https://www.youtube.com/watch?v=Z_G2tjX1TFI

Видео макета автоматики сольного брудера.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

аккуратненько. то я про оформление дисплея и вывод данных в терминал

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

Свежий код сольного брудера. В функции термостата не было чтения значения диммера из EEPROM, обогрев начинал работать только после меню настроек, а при сбросе всё работало, кроме команды на обогреватель. Не сразу нашел. Теперь все в порядке.



#include <Wire.h>
#include <OneWire.h> 
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>
#include <Encoder.h>

//EEPROM1 - день старта программы в брудере
//EEPROM3 - максимальная температура обогревателя
//EEPROM5 - диммер (мощность нагревателя в %)
//EEPROM7 - температура включения вентилятора.


int dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
int histeresis = 1;               //гистерезис в градусах между температурой включения и выключения нагревателя
int interval = 100;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;             //длина окна регулировки мощности

int ventTemp;                    //Переменная для температуры вентиляции
unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned long loopTimeEncoder;    //переменная для опроса энкодера по таймеру
unsigned int currentTime_day;     //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)

unsigned char clockwise = 0;  //вращение энкодера по часовой стрелке
unsigned char counterclockwise = 0;   //вращение энкодера против часовой
unsigned char encoderButton = 0; //нажатие кнопки энкодера

unsigned int memoryTime_day;      //хранящийся в памяти день старта первого брудера
const int temp_pin = 2;           // К какому пину подключены Далласы
const int heater_pin = 13;         //пин нагревателя брудера
const int vent_pin = 9;          //Пин вентилятора
const int encoderButton_pin = 5;  //кнопка энкодера
unsigned int day_bruder;         //день работы программы в брудере
//float temp_to_bruder;
//unsigned int tempOfHeater;       //
long oldPosition  = 500;

LiquidCrystal_I2C lcd(0x20, 16, 2); //инициализация библиотек
RTC_DS1307 RTC;
OneWire oneWire(temp_pin);
DallasTemperature sensors(&oneWire);
Encoder myEnc(3, 4);


void setup() {

  Serial.begin(9600);  // Старт сериал-порта
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов
  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(encoderButton_pin, INPUT);
  pinMode(heater_pin, OUTPUT);
  pinMode(vent_pin, OUTPUT);
  digitalWrite(encoderButton_pin, HIGH);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  loopTimeEncoder = currentTime;
  sensors.begin();
  sensors.setResolution(12);    // установить разрешение (точность)
  sensors.setWaitForConversion(false);  // отключить ожидание

  DateTime now = RTC.now();  //получам текущее время из часов
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени
  //EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //EEPROM_write(3, 60); //максимальная температура нагревателя по умолчаню
}



void loop() {

  EEPROM_read(1, memoryTime_day);   //читаем из памяти дату первого дня брудера
  DateTime now = RTC.now();         //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder = (currentTime_day - memoryTime_day);
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  encoder(); //читаем энкодер 

  if (clockwise){     //если вращение по часовой стрелке, показываем дату-время
    delay(del);
    lcd.clear();
    display_time();
    clockwise = 0;
  }

  if (counterclockwise){ //если вращение против часовой, показываем идеальную температуру в брудере для текущего дня
    delay(del);
    lcd.clear();
    temp_ideal();
    counterclockwise = 0;
  }

  if (encoderButton){  //если нажата кнопка энкодера, то переходим в меню
    delay(del/2);
    lcd.clear();
    menu();
  }

  termostat();    //выполняем функцию термостата

}//конец основного цикла.




void encoder(){

  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    if (newPosition >= oldPosition + 7){
      clockwise = 1;
    }
    if (newPosition <= oldPosition - 7){
      counterclockwise = 1;
    }
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  else {
    clockwise = 0;
    counterclockwise = 0;
  }

  if (digitalRead(encoderButton_pin) == LOW )  {
    delay(del/2);
    encoderButton = 1;
  }
  if (digitalRead(encoderButton_pin) == HIGH )  {
    delay(del/2);
    encoderButton = 0;
  }
}


void menu(){  //функция отображения меню

  dayOfBruder_setup();
  tempOfHeater_setup();
  dimmer_setup();
  vent_setup();

}


void display_time(){  //функция отображения даты-времени в часах
  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("DATE-TIME");
  Serial.println("DATE-TIME");
  delay (1000);
  lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(6, 0);
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  lcd.setCursor(4, 1);
  lcd.print(now.day(), DEC);
  lcd.print(".");
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print("   ");
  Serial.print(now.day(), DEC);
  Serial.print(".");
  Serial.print(now.month(), DEC);
  Serial.print(".");
  Serial.println(now.year(), DEC);

  delay(4000);
  lcd.clear();
  Serial.println("done");
  return;
}



void temp_ideal(){  //функция отображения идеальной температуры для брудера
  delay(del);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("TEMP-IDEAL");
  Serial.print("TEMP-IDEAL");

  //delay (1000);
  //lcd.clear();

  float temp_ideal; 
  if (day_bruder >= 24.0) {  //если программа в брудере работет 24 дней или больше
    temp_ideal = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_ideal = map(day_bruder, 0, 24, 37, 20)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.

  lcd.setCursor(0, 1);      //печатаем на дисплей день в брудере
  lcd.print("Day=");  
  lcd.print (day_bruder);   // и идеальную температуру для этого дня
  Serial.println (day_bruder);
  lcd.setCursor(7, 1);
  lcd.print("t.i=");
  lcd.print(temp_ideal, 0);
  lcd.print((char)223);
  Serial.println(temp_ideal, 1);
  delay(4000);              //ждем 4 секунды и возврат в основной экран.
  lcd.clear();
  Serial.println("done");
  return;
}


void termostat(){    //функция терморегулятора
  //Serial.print("requets temperature...");
  sensors.requestTemperatures(); 
  //Serial.println("complete");
  float temp_ideal;
  unsigned int tempHeater_max;
  float temp_to_bruder = sensors.getTempCByIndex(0);
  float temp_to_heater = sensors.getTempCByIndex(1);
  Serial.print("Temp into bruder: ");
  Serial.print(temp_to_bruder); 
  Serial.print("  Temp of heater: ");
  Serial.println(temp_to_heater); 
  EEPROM_read(3, tempHeater_max); //читаем из памяти максимальную температуру нагревателя
  EEPROM_read(5, dimmer);   //читаем из памяти уставку диммера

  if (day_bruder >= 24.0) {  //если программа в брудере работет 24 дней или больше
    temp_ideal = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_ideal = map(day_bruder, 0, 24, 37, 20)); //иначе преобразуем день работы в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    //DateTime now = RTC.now();
    lcd.setCursor(0, 0);
    lcd.print("h.=");
    lcd.print(temp_to_heater,0);
    lcd.print((char)223);
    //lcd.print(now.hour(), DEC);
    //lcd.print(":");
    //lcd.print(now.minute(), DEC);
    lcd.setCursor(9,0);
    lcd.print("i.=");
    lcd.print(temp_ideal,0);
    lcd.print((char)223);
    lcd.setCursor(0, 1);        //DEBUG
    lcd.print("Day=");
    lcd.print (day_bruder);
    //Serial.println (day_bruder);
    lcd.setCursor(9, 1);
    lcd.print("T=");
    lcd.print(temp_to_bruder, 0);   //DEBUG
    lcd.print((char)223);
    //Serial.println(temp_to_bruder, 1);
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (temp_to_bruder < temp_ideal) {    //если температура в брудере ниже идеальной
    if ((currentTime - windowStartTime < 10 * dimmer)&&(temp_to_heater < tempHeater_max)) {
      digitalWrite(heater_pin, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater_pin, LOW);
    }
  } 
  else if (temp_to_heater > tempHeater_max){
    digitalWrite(heater_pin, LOW);
  }

  else if (temp_to_bruder > temp_ideal + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater_pin, LOW);
  }   //то обогрев отключаем 

  if (temp_to_bruder > ventTemp){
    digitalWrite(vent_pin, HIGH);
  } 
  if (temp_to_bruder < ventTemp - 1){
    digitalWrite(vent_pin, LOW); 
  }
}

void dayOfBruder_setup(){  // функция установки дня работы программы брудера
  lcd.clear();
  delay(del);
  lcd.setCursor(2, 0);
  lcd.print("BRUDER SETUP");
  Serial.println("BRUDER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {      //бесконечный цикл
    delay(del);
    x++;
    if (x > interval) { 
      Serial.println("timeout");
      break;
    }
    encoder();
    EEPROM_read(1, memoryTime_day);
    day_bruder = (currentTime_day - memoryTime_day);
    if (day_bruder > 100) {     //проверяем, если прошло больше 100 дней
      DateTime now = RTC.now();  //получам текущее время из часов
      EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      day_bruder = (currentTime_day - memoryTime_day); //читаем сегодня из памяти
    }
    lcd.setCursor(2, 0);
    lcd.print("DayCnt = ");
    Serial.print("DayCnt = ");
    lcd.print(day_bruder);
    Serial.println(day_bruder);
    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {
      delay(del);
      lcd.clear(); //очищаем экран
      Serial.println("done");
      break;
    }
    if (clockwise) {
      delay(del);
      EEPROM_write(1, memoryTime_day + 1);
      lcd.clear();
    }

    if (counterclockwise) {
      delay(del);
      EEPROM_write(1, memoryTime_day - 1);
      lcd.clear();
    }
  } 
}

void tempOfHeater_setup(){ //установка максимальной температуры нагревателя.
  unsigned int tempHeater_max;    //
  EEPROM_read(3, tempHeater_max); // 
  lcd.clear();
  delay(del);
  lcd.setCursor(0, 0);
  lcd.print("MaxT.H. SETUP");
  Serial.println("MaxT.H. SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) { ////бесконечный цикл
    delay(del);
    x++;
    if (x > interval) { 
      Serial.println("timeout");
      break;
    }
    encoder();
    EEPROM_read(3, tempHeater_max); // 
    lcd.setCursor(0, 0);
    lcd.print("MaxTempH = ");
    Serial.print("MaxTempH = ");
    lcd.print(tempHeater_max);
    Serial.println(tempHeater_max);
    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (clockwise) {
      delay(del);
      if (tempHeater_max > 200){
        tempHeater_max = 32;
      }
      EEPROM_write(3, tempHeater_max - 2);
      lcd.clear();
    }

    if (counterclockwise) {
      delay(del);
      if (tempHeater_max < 30){
        tempHeater_max = 58;
      }
      EEPROM_write(3, tempHeater_max + 2);
      lcd.clear();
    }
  }
}

void dimmer_setup() {
  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  Serial.println("DIMMER SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    delay(del);
    x++;
    if (x > interval) {
      lcd.clear();
      Serial.println("timeout");
      break;
    }

    encoder();
    EEPROM_read(5, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 0);
    lcd.print("Dimmer% = ");
    Serial.print("Dimmer% = ");
    lcd.print(dimmer);
    Serial.println(dimmer);
    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {  //если кнопка энкодера, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (clockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 5;
      if (dimmer < 10) { //не ниже 10%
        dimmer = 95;
      }
      EEPROM_write(5, dimmer);
      lcd.clear();
    }

    if (counterclockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      dimmer = dimmer + 5;
      if (dimmer > 95) {  //не выше 95%
        dimmer = 10;
      }
      EEPROM_write(5, dimmer);
      lcd.clear();
    }
  }
}


void vent_setup(){

  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("VENT. SETUP");
  Serial.println("VENT. SETUP");
  delay (1000);
  lcd.clear();
  int x = 0;
  while (1) {
    delay(del);
    x++;
    if (x > interval) {
      lcd.clear();
      Serial.println("timeout");
      break;
    }

    encoder();
    EEPROM_read(7, ventTemp);   //читаем из памяти уставку диммера
    if (ventTemp > 43 || ventTemp < 29){ //если там чушь, то включаем 1 режим.
      ventTemp = 39;
    }
    lcd.setCursor(0, 0);
    lcd.print("Vent.Temp = ");
    lcd.print(ventTemp);
    Serial.print("Vent.Temp = ");
    Serial.println(ventTemp);

    lcd.setCursor(1, 1);
    lcd.print("-<-- NEXT -->+");

    if (encoderButton) {  //если кнопка энкодера, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (clockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      ventTemp --;
      if (ventTemp < 30) { //не ниже 10%
        ventTemp = 42;
      }
      EEPROM_write(7, ventTemp);
      lcd.clear();
    }

    if (counterclockwise) {  //если по часовой, то прибавляем мощность на 5%
      delay(del);
      ventTemp ++;
      if (ventTemp > 42) { //не ниже 10%
        ventTemp = 30;
      }
      EEPROM_write(7, ventTemp);
      lcd.clear();
    }
  }
}
//


 

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

Добрый день, давно я сюда не заходил. Работы проведено много, количество правок кода и не вспомню. Теперь в блоке настраиваются стартовая и финишная температура. Можно корректировать дату и время. Добавлено усреднение значений. Добавлено управление вентиляторами по перегреву. Что-то еще добавлено. Изготовлены тестовые образцы плат на заводе в Китае. Вот так оно выглядит примерно.

Исходники программы и печатной платы лежат тут https://drive.google.com/folderview?id=0B0vRuSZ7oRUeelhOUTV4dnBMS1k&usp=docslist_api&ddrp=1#

Вот свежий код, может захочет кто повторить. Работает вроде без багов с июня.

#include <Wire.h>
#include "RTClib.h"
#include <EEPROM2.h>
#include <LiquidCrystal_I2C.h>
//#include <DallasTemperature.h>

#define button_minus_pin 2    //пин кнопки "минус"
#define button_plus_pin 3     //пин кнопки "плюс"
#define button_enter_pin 4    //пин кнопки "enter"
#define jumper_pin 21        //пин перемычки БРУДЕР/ИНКУБАТОР

#define tempB1_pin A0         //пин термометра первого брудера
#define tempB2_pin A1
#define tempB3_pin A2
#define tempB4_pin A3

#define heater1 9            //пин нагревателя брудера1
#define heater2 8
#define heater3 7
#define heater4 6

#define fan1_pin 10             //пин вентилятора 1.
#define fan2_pin 11
#define fan3_pin 12
#define fan4_pin 13

byte dimmer = 10;                   //количество подаваемой мощности в нагреватели (0-254)
int del = 200;                     // переменная ожидания между выборами меню
byte histeresis = 1;             //гистерезис в градусах между температурой включения и выключения нагревателя
byte interval = 50;                // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
int WindowSize = 1000;                //длина окна регулировки мощности

unsigned long windowStartTime;    //переменная для хранения начала цикла окна
unsigned long currentTime;        // текущее время в миллисекундах от старта программы
unsigned int currentTime_day;      //текущий день в юникс-формате (сколько дней минуло с 1 января 1970)


int memoryTime_day1;      //хранящийся в памяти день старта первого брудера
int memoryTime_day2;
int memoryTime_day3;
int memoryTime_day4;

boolean button_minus = 0;              // переменная для хранения состояния кнопки "минус"
boolean button_plus = 0;               // переменная для хранения состояния кнопки "плюс"
boolean button_enter = 0;              // переменная для хранения состояния кнопки "enter"

int day_bruder1;         //день работы программы в 1 брудере
int day_bruder2;
int day_bruder3;
int day_bruder4;
byte startTemp;      //стартовая температура для первого дня в брудерах
byte endTemp;      //финишная температура для первого дня в брудерах



LiquidCrystal_I2C lcd(0x27, 20, 4); //инициализация библиотек
RTC_DS1307 RTC;


void setup() {

  Serial.begin(9600);  // Старт сериал-порта
  analogReference(INTERNAL);  //для повышения точности делаем опорное Напр. 1.1В
  Wire.begin();        // старт I2C
  RTC.begin();         // Старт часов

  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея

  pinMode(button_minus_pin, INPUT); //задаем пины кнопок как входы
  pinMode(button_plus_pin, INPUT);
  pinMode(button_enter_pin, INPUT);
  pinMode(jumper_pin, INPUT);
  digitalWrite(jumper_pin, HIGH);

  pinMode(heater1, OUTPUT);         //задаем пины нагревателей как выходы
  pinMode(heater2, OUTPUT);
  pinMode(heater3, OUTPUT);
  pinMode(heater4, OUTPUT);

  windowStartTime = millis();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы

  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени
  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);

  //     EEPROM_write(1, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //     EEPROM_write(3, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //     EEPROM_write(5, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день
  //     EEPROM_write(7, now.unixtime() / 86400L);  //ОТЛАДКА: пишем в память сегодняшний день

  EEPROM_read(1, memoryTime_day1); //читаем из памяти дату первого дня первого брудера
  if (memoryTime_day1 >= 65534) EEPROM_write(1, currentTime_day);
  EEPROM_read(3, memoryTime_day2);
  if (memoryTime_day2 >= 65534) EEPROM_write(3, currentTime_day);
  EEPROM_read(5, memoryTime_day3);
  if (memoryTime_day3 >= 65534) EEPROM_write(5, currentTime_day);
  EEPROM_read(7, memoryTime_day4);
  if (memoryTime_day4 >= 65534) EEPROM_write(7, currentTime_day);
  EEPROM_read(9, dimmer);
  if (dimmer >= 110) EEPROM_write(9, 10);
  EEPROM_read(11, startTemp);
  if (startTemp >= 50) EEPROM_write(11, 35);
  EEPROM_read(13, endTemp);
  if (endTemp >= 50) EEPROM_write(13, 20);
  //  Serial.print("memoryTime_day1= ");
  //  Serial.println(memoryTime_day1);
  //  Serial.print("memoryTime_day2= ");
  //  Serial.println(memoryTime_day2);
  //  Serial.print("memoryTime_day3= ");
  //  Serial.println(memoryTime_day3);
  //  Serial.print("memoryTime_day4= ");
  //  Serial.println(memoryTime_day4);
  //  Serial.print("dimmer= ");
  //  Serial.println(dimmer);
  //  Serial.print("startTemp= ");
  //  Serial.println(startTemp);
  //  Serial.print("endTemp= ");
  //  Serial.println(endTemp);




}

void loop() {

  if (! RTC.isrunning()) {                      //Если часы остановились,
    RTC.adjust(DateTime(2014, 1, 1, 12, 0, 1)); //то устанавливаем 01.1.2014 и запускаем их.
  }
  DateTime now = RTC.now();  //получам текущее время из часов
  currentTime_day = (now.unixtime() / 86400L);
  day_bruder1 = (currentTime_day - memoryTime_day1);
  day_bruder2 = (currentTime_day - memoryTime_day2);
  day_bruder3 = (currentTime_day - memoryTime_day3);
  day_bruder4 = (currentTime_day - memoryTime_day4);
  EEPROM_read(11, startTemp);

  //печатаем на дисплей текущую дату и время
  thermostat1();  //вызываем функцию терморегулятора 1 брудера
  thermostat2();
  thermostat3();
  thermostat4();


  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }
  if (button_minus && button_plus) {
    delay(del);
    lcd.clear();
    dataTime_setup();
  }
  if (button_minus) {
    delay(del);
    lcd.clear();
    temp_ideal();
  }
  if (button_plus) {
    delay(del);
    lcd.clear();
    time_display();
  }
}
void menu() {
  digitalWrite(heater1, LOW);  //Отключаем нагреватели при входе в меню.
  digitalWrite(heater2, LOW);
  digitalWrite(heater3, LOW);
  digitalWrite(heater4, LOW);
  dimmer_setup();
  bruder1_setup();
  bruder2_setup();
  bruder3_setup();
  bruder4_setup();
  startTemp_setup();
  endTemp_setup();
  //data_time_setup();
}

void button_read() {//функция проверки нажатия кнопки

  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
}

void bruder1_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER1 SETUP");
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(1, memoryTime_day1);
    day_bruder1 = (currentTime_day - memoryTime_day1);
    lcd.setCursor(0, 1);
    lcd.print("1 DayCnt = ");
    lcd.print(day_bruder1);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(1, memoryTime_day1 + 1);
      if (day_bruder1 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(1, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, memoryTime_day1 - 1);
      lcd.clear();
    }
    delay(del);

  }
}



//-------------------------------------------------------------------------

void bruder2_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER2 SETUP");
  //delay (1000);
  //lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(3, memoryTime_day2);
    day_bruder2 = (currentTime_day - memoryTime_day2);
    lcd.setCursor(0, 1);
    lcd.print("2 DayCnt = ");
    lcd.print(day_bruder2);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(3, memoryTime_day2 + 1);
      if (day_bruder2 > 100) {     //проверяем, если прошло больше 100 дней
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(3, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, memoryTime_day2 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder3_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER3 SETUP");
  //delay (1000);
  //lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(5, memoryTime_day3);
    day_bruder3 = (currentTime_day - memoryTime_day3);
    lcd.setCursor(0, 1);
    lcd.print("3 DayCnt = ");
    lcd.print(day_bruder3);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(5, memoryTime_day3 + 1);
      if (day_bruder3 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(5, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(5, memoryTime_day3 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void bruder4_setup() {

  lcd.clear();
  delay(del);

  button_read();
  lcd.setCursor(0, 0);
  lcd.print("BRUDER4 SETUP");
  //delay (1000);
  //lcd.clear();

  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(7, memoryTime_day4);
    day_bruder4 = (currentTime_day - memoryTime_day4);
    lcd.setCursor(0, 1);
    lcd.print("4 DayCnt = ");
    lcd.print(day_bruder4);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Day-1  NEXT  Day+1");

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {
      EEPROM_write(7, memoryTime_day4 + 1);
      if (day_bruder4 > 100) {
        DateTime now = RTC.now();  //получам текущее время из часов
        EEPROM_write(7, now.unixtime() / 86400L);  //пишем в память сегодняшний день
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(7, memoryTime_day4 - 1);
      lcd.clear();
    }
    delay(del);

  }
}

//----------------------------------------------------------------

void thermostat1 () {

  float tempB1;
  float temp_idealB1;
  boolean fan1_state = LOW;

  DateTime now = RTC.now();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  //tempB1 = analogRead(tempB1_pin); //читаем температуру первого брудера
  //tempB1 = (tempB1 / 9.31); //переводим ее в градусы Цельсия.
  tempB1 = analogReadOversampled(tempB1_pin);

  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 0);
    lcd.print("1 Day-");
    lcd.print (day_bruder1);
    Serial.println(day_bruder1);
    lcd.setCursor(9, 0);
    lcd.print("r-");
    lcd.print(tempB1, 0);
    lcd.print((char)223);
    lcd.print(" ");
    lcd.setCursor(15, 0);
    lcd.print("i-");
    lcd.print(temp_idealB1, 0);
    lcd.print((char)223);

    windowStartTime += WindowSize;
    currentTime = millis();
  }


  if (tempB1 < temp_idealB1) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater1, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater1, LOW);
    }
  }        //включаем обогрев
  else if (tempB1 > (temp_idealB1 + histeresis)) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater1, LOW);
  }   //то обогрев отключаем

  if (digitalRead (jumper_pin) == HIGH) {
    if (tempB1 > (temp_idealB1 + 2)) {     // если температура в брудере на 2 градуса выше идеальной, то включаем продувку.
      digitalWrite (fan1_pin, HIGH);       // если остудили на градус ниже идеальной, то продувку отключаем.
    }
    if (tempB1 < (temp_idealB1 - 1)) {
      digitalWrite (fan1_pin, LOW);
    }
  }

  if (digitalRead (jumper_pin) == LOW) {
    if (now.minute() == 59 && now.second() == 59) {
      fan1_state = !fan1_state;
      digitalWrite(fan1_pin, fan1_state);
      delay(1000);
    }
  }
}

//-------------------------------------------------------------------

void thermostat2 () {

  float tempB2;
  float temp_idealB2;
  boolean fan2_state = LOW;

  DateTime now = RTC.now();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  //tempB2 = analogRead(tempB2_pin); //читаем температуру первого брудера
  //tempB2 = (tempB2 / 9.31); //переводим ее в градусы Цельсия.
  tempB2 = analogReadOversampled(tempB2_pin);

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 1);
    lcd.print("2 Day-");
    lcd.print (day_bruder2);
    Serial.println(day_bruder2);
    lcd.setCursor(9, 1);
    lcd.print("r-");
    lcd.print(tempB2, 0);
    lcd.print((char)223);
    lcd.print(" ");
    lcd.setCursor(15, 1);
    lcd.print("i-");
    lcd.print(temp_idealB2, 0);
    lcd.print((char)223);

    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB2 < temp_idealB2) {    //если температура в 2 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater2, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater2, LOW);
    }
  }        //включаем обогрев
  else if (tempB2 > temp_idealB2 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater2, LOW);
  }   //то обогрев отключаем


  if (digitalRead (jumper_pin) == HIGH) {
    if (tempB2 > (temp_idealB2 + 2)) {     // если температура в брудере на 2 градуса выше идеальной, то включаем продувку.
      digitalWrite (fan2_pin, HIGH);       // если остудили на градус ниже идеальной, то продувку отключаем.
    }
    if (tempB2 < (temp_idealB2 - 1)) {
      digitalWrite (fan2_pin, LOW);
    }
  }

  if (digitalRead (jumper_pin) == LOW) {
    if (now.minute() == 59 && now.second() == 59) {
      fan2_state = !fan2_state;
      digitalWrite(fan2_pin, fan2_state);
      delay(1000);
    }
  }

}
//-------------------------------------------------------------------

void thermostat3 () {

  float tempB3;
  float temp_idealB3;
  boolean fan3_state = LOW;

  DateTime now = RTC.now();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  //tempB3 = analogRead(tempB3_pin); //читаем температуру первого брудера
  //tempB3 = (tempB3 / 9.31); //переводим ее в градусы Цельсия.
  tempB3 = analogReadOversampled(tempB3_pin);

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 2);
    lcd.print("3 Day-");
    lcd.print (day_bruder3);
    Serial.println(day_bruder3);
    lcd.setCursor(9, 2);
    lcd.print("r-");
    lcd.print(tempB3, 0);
    lcd.print((char)223);
    lcd.print(" ");
    lcd.setCursor(15, 2);
    lcd.print("i-");
    lcd.print(temp_idealB3, 0);
    lcd.print((char)223);
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB3 < temp_idealB3) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * dimmer) {
      digitalWrite(heater3, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater3, LOW);
    }


  }        //включаем обогрев
  else if (tempB3 > temp_idealB3 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater3, LOW);
  }   //то обогрев отключаем


  if (digitalRead (jumper_pin) == HIGH) {
    if (tempB3 > (temp_idealB3 + 2)) {     // если температура в брудере на 2 градуса выше идеальной, то включаем продувку.
      digitalWrite (fan3_pin, HIGH);       // если остудили на градус ниже идеальной, то продувку отключаем.
    }
    if (tempB3 < (temp_idealB3 - 1)) {
      digitalWrite (fan3_pin, LOW);
    }
  }

  if (digitalRead (jumper_pin) == LOW) {
    if (now.minute() == 59 && now.second() == 59) {
      fan3_state = !fan3_state;
      digitalWrite(fan3_pin, fan3_state);
      delay(1000);
    }
  }

}

//---------------------------------------------------------------------

void thermostat4 () {

  float tempB4;
  float temp_idealB4;
  boolean fan4_state = LOW;

  DateTime now = RTC.now();
  currentTime = millis();  // считываем время, прошедшее с момента запуска программы
  //tempB4 = analogRead(tempB4_pin); //читаем температуру первого брудера
  //tempB4 = (tempB4 / 9.31); //переводим ее в градусы Цельсия.
  tempB4 = analogReadOversampled(tempB4_pin);

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  if (currentTime - windowStartTime > WindowSize) //время для перещелкивания периода окна
  {
    lcd.setCursor(0, 3);
    lcd.print("4 Day-");
    lcd.print (day_bruder4);
    Serial.println(day_bruder4);
    lcd.setCursor(9, 3);
    lcd.print("r-");
    lcd.print(tempB4, 0);
    lcd.print((char)223);
    lcd.print(" ");
    lcd.setCursor(15, 3);
    lcd.print("i-");
    lcd.print(temp_idealB4, 0);
    lcd.print((char)223);
    windowStartTime += WindowSize;
    currentTime = millis();
  }

  if (tempB4 < temp_idealB4) {    //если температура в 1 брудере ниже идеальной

    if (currentTime - windowStartTime < 10 * (dimmer + 3)) {
      digitalWrite(heater4, HIGH);
    }
    else  // Rest des Intervalls Heizung aus остаток интервала нагрев отключён
    {
      digitalWrite(heater4, LOW);
    }


  }        //включаем обогрев
  else if (tempB4 > temp_idealB4 + histeresis) { //если температура выше идеальной на величину гистерезиса
    digitalWrite (heater4, LOW);
  }   //то обогрев отключаем


  if (digitalRead (jumper_pin) == HIGH) {
    if (tempB4 > (temp_idealB4 + 2)) {     // если температура в брудере на 2 градуса выше идеальной, то включаем продувку.
      digitalWrite (fan4_pin, HIGH);       // если остудили на градус ниже идеальной, то продувку отключаем.
    }
    if (tempB4 < (temp_idealB4 - 1)) {
      digitalWrite (fan4_pin, LOW);
    }
  }

  if (digitalRead (jumper_pin) == LOW) {
    if (now.minute() == 59 && now.second() == 59) {
      fan4_state = !fan4_state;
      digitalWrite(fan4_pin, fan4_state);
      delay(1000);
    }
  }
}

void dimmer_setup() {

  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("DIMMER SETUP");
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(9, dimmer);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 1);
    lcd.print("Dimmer% = ");
    lcd.print(dimmer);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Dim-1  NEXT  Dim+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      dimmer = dimmer - 1;
      if (dimmer < 10) {
        dimmer = 10;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      dimmer = dimmer + 1;
      if (dimmer > 95) {
        dimmer = 95;
      }
      EEPROM_write(9, dimmer);
      lcd.clear();
    }
    delay(del);
  }
}

void temp_ideal() { //если нажата кнопка минус, выводим на дисплей идеальную температуру для брудеров
  //  в зависимости от дня отсидки

  delay(del);
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("TEMP-IDEAL");
  delay (1000);
  lcd.clear();

  float temp_idealB1;
  float temp_idealB2;
  float temp_idealB3;
  float temp_idealB4;

  if (day_bruder1 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB1 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB1 = map(day_bruder1, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB1 = temp_idealB1 / 10;

  if (day_bruder2 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB2 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB2 = map(day_bruder2, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB2 = temp_idealB2 / 10;

  if (day_bruder3 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB3 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB3 = map(day_bruder3, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB3 = temp_idealB3 / 10;

  if (day_bruder4 >= 24.0) {  //если программа в 1 брудере работет 24 дней или больше
    temp_idealB4 = 20.0;      //то идеальная температура стабилизации равна 20 градусам
  }
  else (temp_idealB4 = map(day_bruder4, 0, 24, startTemp, endTemp)); //иначе преобразуем день работы Б1 в диапазон температур 37-20 по дням.
  //temp_idealB4 = temp_idealB4 / 10;

  lcd.setCursor(0, 0);
  lcd.print("1 Day-");
  lcd.print (day_bruder1);
  lcd.setCursor(9, 0);
  lcd.print("i-");
  lcd.print(temp_idealB1, 0);
  lcd.print((char)223);


  lcd.setCursor(0, 1);
  lcd.print("2 Day-");
  lcd.print (day_bruder2);
  lcd.setCursor(9, 1);
  lcd.print("i-");
  lcd.print(temp_idealB2, 0);
  lcd.print((char)223);

  lcd.setCursor(0, 2);
  lcd.print("3 Day-");
  lcd.print (day_bruder3);
  lcd.setCursor(9, 2);
  lcd.print("i-");
  lcd.print(temp_idealB3, 0);
  lcd.print((char)223);

  lcd.setCursor(0, 3);
  lcd.print("4 Day-");
  lcd.print (day_bruder4);
  lcd.setCursor(9, 3);
  lcd.print("i-");
  lcd.print(temp_idealB4, 0);
  lcd.print((char)223);

  delay(4000);
  lcd.clear();
  return;
}

void time_display() {

  delay(del);
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("DATE-TIME");
  //delay (1000);
  //lcd.clear();

  DateTime now = RTC.now();
  lcd.setCursor(8, 1);
  if (now.hour() < 10) lcd.print(" ");
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  if (now.minute() < 10)lcd.print(0);
  lcd.print(now.minute(), DEC);
  lcd.setCursor(5, 2);
  if (now.day() < 10)lcd.print(" ");
  lcd.print(now.day(), DEC);
  lcd.print(".");
  if (now.month() < 10)lcd.print(0);
  lcd.print(now.month(), DEC);
  lcd.print(".");
  lcd.print(now.year(), DEC);

  delay(4000);
  lcd.clear();
  return;
}

unsigned int analogReadOversampled(byte analogChannel)  {  //алгоритм усреднения показаний термометров
  unsigned int aSum = 0;   // сумма аналоговых выборок
  for (byte i = 0; i < 16; i++)
    aSum += (analogRead(analogChannel) / 9.31); // Суммируем 16 выборок температуры
  return aSum >> 4;   // сдвигаем вправо на 4 что равно делению на 16 без остатка
}

void startTemp_setup() {
  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("t.START SETUP");
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(11, startTemp);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 1);
    lcd.print("t.Start = ");
    lcd.print(startTemp);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Temp-1  NEXT  Temp+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      startTemp = startTemp - 1;
      if (startTemp < 25) {
        startTemp = 25;
      }
      EEPROM_write(11, startTemp);
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      startTemp = startTemp + 1;
      if (startTemp > 38) {
        startTemp = 38;
      }
      EEPROM_write(11, startTemp);
      lcd.clear();
    }
    delay(del);
  }
}

void endTemp_setup() {
  delay(del);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("t.END SETUP");
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    button_read();
    EEPROM_read(13, endTemp);   //читаем из памяти уставку диммера
    lcd.setCursor(0, 1);
    lcd.print("t.End = ");
    lcd.print(endTemp);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Temp-1  NEXT  Temp+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      endTemp = endTemp - 1;
      if (endTemp < 20) {
        endTemp = 20;
      }
      EEPROM_write(13, endTemp);
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      endTemp = endTemp + 1;
      if (endTemp > 39) {
        endTemp = 39;
      }
      EEPROM_write(13, endTemp);
      lcd.clear();
    }
    delay(del);
  }
}

void dataTime_setup(){
 clock_setup();
 date_setup();
 year_setup();
}


void clock_setup() {
  delay(del);
  lcd.clear();
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    DateTime now = RTC.now();  //получам текущее время из часов
    button_read();
    lcd.setCursor(6, 0);
    lcd.print("CLOCK SETUP");
    lcd.setCursor(8, 1);
    if (now.hour() < 10) lcd.print(" ");
    lcd.print(now.hour(), DEC);
    lcd.print(":");
    if (now.minute() < 10)lcd.print(0);
    lcd.print(now.minute(), DEC);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Min+1  NEXT  Hour+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      if(now.minute() < 59) RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute() + 1, 0));
      else RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), 0, 0));
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      if(now.hour() < 23) RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() + 1, now.minute(), 0));
      else RTC.adjust(DateTime(now.year(), now.month(), now.day(), 0, now.minute(), 0));
      lcd.clear();
    }
    delay(del);
  }
}

void year_setup() {
  delay(del);
  lcd.clear();
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    DateTime now = RTC.now();  //получам текущее время из часов
    button_read();
    lcd.setCursor(6, 0);
    lcd.print("YEAR SETUP");
    lcd.setCursor(8, 1);
    lcd.print(now.year(), DEC);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("YEAR-1  NEXT  YEAR+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      RTC.adjust(DateTime(now.year()-1, now.month(), now.day(), now.hour(), now.minute(), 0));
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      RTC.adjust(DateTime(now.year()+1, now.month(), now.day(), now.hour(), now.minute(), 0));
      
      lcd.clear();
    }
    delay(del);
  }
}

void date_setup() {
  delay(del);
  lcd.clear();
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    DateTime now = RTC.now();  //получам текущее время из часов
    button_read();
    lcd.setCursor(6, 0);
    lcd.print("DATE SETUP");
    lcd.setCursor(8, 1);
    if (now.day() < 10) lcd.print("0");
    lcd.print(now.day(), DEC);
    lcd.print(":");
    if (now.month() < 10)lcd.print(0);
    lcd.print(now.month(), DEC);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("DAY+1  NEXT  MON+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      if(now.day() < 31) RTC.adjust(DateTime(now.year(), now.month(), now.day()+1, now.hour(), now.minute(), 0));
      else RTC.adjust(DateTime(now.year(), now.month(), 0, now.hour(), now.minute(), 0));
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      if(now.month() < 12) RTC.adjust(DateTime(now.year(), now.month()+1, now.day(), now.hour(), now.minute(), 0));
      else RTC.adjust(DateTime(now.year(), 1, now.day(), now.hour(), now.minute(), 0));
      lcd.clear();
    }
    delay(del);
  }
}
  

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

прикольно. а корпус есть?

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

Свой в электрокоробку упаковал, а род заказ без корпуса делаю. Я ровно не выпилю, а халтуру делать не хочется. Да и блоки такого уровня любят электрошкаф, клеммники, автоматы... А это всего лишь модуль. Вот как-то так я рассуждаю. Был бы лазер или ЧПУ, тогда другое дело, а у меня только Дремель.

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

Не совсем про Ардуино, в версии с одним датчиком на брудер, где его расположили? Спасибо.

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

На задней стенке в центре "камеры". 

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

А на температуру относительно нагревателя просто коэффициент вводили?

olegmak3
Offline
Зарегистрирован: 09.10.2014

Umka пишет:
а род заказ без корпуса делаю.

Как с Вами связаться?

Моя почта olegmak3@rambler.ru

Angbor
Angbor аватар
Offline
Зарегистрирован: 26.10.2015

класс

на следующий год понадобится и мне :)

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

На сайте http://u-m.biz есть мои координаты.

Angbor
Angbor аватар
Offline
Зарегистрирован: 26.10.2015

спасибо, но я по большей части любитель и сам попаять ;)