Самодельный ардуино контролер отопления

Тема в разделе "Силовая электроника", создана пользователем mednagolov, 25 окт 2022.

  1. mednagolov

    mednagolov Гик

    Приветствую любителей попаять-полудить, и СИкод за IDешить...)))
    Кратко о проекте .
    Управление температурой электрокотла по температуре на улице и в помещении.
    Написать скетч для ардуино.
    Сделать плату в Sprint-Layout и изготовить её не ЛУТом.
    Ну и запустить всё это на реальной системе отопления домом.
     
    Airbus нравится это.
  2. mednagolov

    mednagolov Гик

    Я новичок в АРДУИНО, поэтому буду рад советам опытных , и так же интересующихся этой темой товарищей.
     
    Airbus нравится это.
  3. mednagolov

    mednagolov Гик

    Хочу собрать всё на Atmega 328.
     
    Airbus нравится это.
  4. Airbus

    Airbus Радиохулиган Модератор

    Разрешаю! Действуйте! А готовых проектов в Сети нема? Или на нашем Форуме?
     
  5. mednagolov

    mednagolov Гик

    Хочется своего.... самодельного-доморощеного....))). Ну и ардуино-камень грысть-постигать как бы с пользой.
     
  6. mednagolov

    mednagolov Гик

    2022-10-25 23.47.04.jpg И так технически думаю это должно быть как то так-
    схема общ.jpg
    Материально сегодня вдолбал в стену коробку ( бокс под автоматы ШРВ-П-4) в которой будет ,, жить ,, контроллер и дисплей с кнопками и модулем связи, в кабель каналах будут провода на датчики и управление нагрузкой в силовой шкаф ( он с права за стеной , на улице)
     

    Вложения:

  7. mednagolov

    mednagolov Гик

    Начало скетча мыслю примерно так...
    /*
    кнопки подтянуты к +5 v. ,,INPUT_PULLUP ,,
    резисторы по 2,4 кОм последовательно.
    */

    //**************************************************************************************
    #include <LiquidCrystal_I2C.h> // библиотека для LCD 1602
    LiquidCrystal_I2C lcd(0x27,16,2); // присваиваем имя дисплею
    //**************************** пины ардуино и переменные *********************************************************
    const int pin_but = A0; // pin на кнопки
    const int bip = 3 ; // зуммер подключен к D3
    int x=0; // координата вывода текста на дисплей
    int y=0; // координата вывода текста на дисплей
    int M=0; // переменная для меню
    //int X = 0;
    int sek=0; // секунда
    int mint=0; // минута
    int ch=0; // час
    int but=0; // Создаем переменную для нопок
    int s=0; // секунда для таймера возврата
    uint32_t myTimer1 , myTimer2, myTimer3 ; // для таймера на millis()
    boolean selekt = false; // флаг кнопки селект
    boolean Up = false; // флаг кнопки верх
    boolean Down = false; // флаг кнопки низ
    boolean Rait = false; // флаг кнопки право
    boolean but_flag = false; // если кнопки не нажаты

    void setup(){
    Serial.begin(9600); // запускаем монитор порта
    lcd.init(); // инициализация дисплея
    lcd.backlight(); // включение подсветки дисплея
    //pinMode(pin_but,INPUT); // пин кнопок на чтение
    pinMode(bip,OUTPUT); //пин на бипер
    pinMode(pin_but, INPUT_PULLUP); //пин на блок кнопок
    ////////////// заставка //////////////////////////////////////////////
    tone(bip,1000,100);
    lcd.setCursor(0, 0); lcd.print( " Atmega-328 -OK" );
    delay (1000);
    tone(bip,1500,300);
    lcd.clear();
    }
    void loop() {
    if (millis() - myTimer1 >= 1000 ) // таймер на millis()
    { myTimer1 = millis(); sek++; s++;}
    if (sek>=60){mint++; sek=0;} //считает секунды
    if (mint>=60){ch++; mint=0;} // считает минуты
    if (ch>=24){ch=0;} // считает часы
    if (millis() - myTimer2 >= 300 ) // таймер на millis() каждые 300 Мсек.
    { myTimer2 = millis(); // опрашивает блок кнопок
    but = analogRead (A0); // пин ардуино A0 считывает блок кнопок
    if (but < 20){ // Если нажата кнопка СЕЛЕКТ
    Serial.print("Value A0 ‘Select’ is :");// Вывести текст на М.П.
    Serial.println(x,DEC); // Вывести значение переменной x на манитор порта
    M++; if (M>3){M=0;}
    //selekt=true; s=0;
    tone(bip,1500,300);

    }
    else if (but < 100) { // Если нажата кнопка В ПРАВО
    //lcd.print ("Rait "); // Вывести текст на экранчик
    Serial.print("Value A0 ‘Right’ is :"); // Вывести текст на М.П.
    Serial.println(x,DEC); // Вывести значение переменной x на М.П.
    Rait = true; // поднимаем флаг В ПРАВО
    tone(bip,2000,300);

    }
    else if (but < 150) { // Если нажата кнопка В ВЕРХ
    //lcd.print ("Up "); // Вывести текст на экранчик
    Serial.print("Value A0 ‘UP’ is :"); // Вывести текст на М.П.
    Serial.println(x,DEC); // Вывести значение переменной x на М.П.
    Up = true; // поднимаем флаг В ВЕРХ
    tone(bip,2000,300);

    }
    else if (but < 200){ // Если нажата кнопка В НИЗ
    //lcd.print ("Down "); // Вывести текст на экранчик
    Serial.print("Value A0 ‘Down’ is :"); // Вывести текст на М.П.
    Serial.println(x,DEC); // Вывести значение переменной x на М.П.
    Down = true; // поднимаем флаг В НИЗ
    tone(bip,2000,300);

    }
    /* else if (but < 600){ // Если нажата кнопка В ЛЕВО
    lcd.print ("Left "); // Вывести текст
    Serial.print("Value A0 ‘Left’ is :"); // Вывести текст
    Serial.println(x,DEC); // Вывести значение переменной x
    }*/
    }
    if (but < 900){ lcd.clear(); s=0;} // если нажата любая кнопка сброс таймера возврата в меню №0
    if(M==0){
    x=11; y=0;
    lcd.setCursor(x, y);
    if(ch<10){lcd.print("0");}// всегда 2 цифры
    lcd.print( ch );
    if(sek%2){lcd.print(":");}
    else {lcd.print(" ");}
    if(mint<10){lcd.print("0");}// всегда 2 цифры
    lcd.print(mint);
    }
    if(M==1){
    lcd.setCursor(0,0); lcd.print ("LOAD CLOK");
    //if (sek%2){ lcd.print ("1");}
    //else {lcd.print(" ");}

    x=11; y=1;
    lcd.setCursor(x, y);
    if(ch<10){lcd.print("0");}// всегда 2 цифры
    lcd.print( ch );
    //if(sek%2) {lcd.print( ch ); }
    //else { lcd.setCursor(x, y); lcd.print(" ");}
    lcd.print(":");
    if(mint<10){lcd.print("0");}// всегда 2 цифры
    lcd.print(mint);
    if(Up == true){ch++;} // кнопка в верх, увеличивает часы
    if(Down == true){mint++;} // кнопка в низ, увеличивает минуты
    if(Rait == true){M=0;} // кнопка в право, запомнить и возвеат в меню №0
    if( s>10){ lcd.clear(); M=0;} // если кнопки не нажимаются 10 сек. возврат в меню №0
    }
    if(M==2){
    //lcd.setCursor(3,0); lcd.print ("NASTROIKA -2");
    //lcd.setCursor(0,0); lcd.print ("M-2");
    //if (sek%2){ lcd.setCursor(2,0); lcd.print (" ");}
    //if (selekt==true){M++;lcd.clear();} // if (M>3){M=0;}
    }
    if(M==3){
    //lcd.setCursor(3,0); lcd.print ("NASTROIKA -3");
    //if (selekt==true){M++;lcd.clear();} //if (M>3){M=0;}
    }
    //сброс флагов кнопок
    but_flag=false;
    selekt=false;
    Up=false;
    Down=false;
    Rait =false;
    noTone( bip); // не пищать!
    }
    [/code]
     
  8. mednagolov

    mednagolov Гик

    Это файл с этим же кодом, но для таких же пионеров как я с подробными пояснениями...
     

    Вложения:

  9. DetSimen

    DetSimen Гуру

    Иначе как говнокодом это не назовёшь. И зачем это выкладывать? Славы хочется?
    Да и учебник по русскому проштудировать не мешало бы. Заадно.
     
  10. mednagolov

    mednagolov Гик

    блок коррекции часов, не получается мигание разрядом.
     
  11. mednagolov

    mednagolov Гик

    Силовая часть думаю будет выглядеть так-
    схема 380 в.jpg
    итого имеем 4 режима обогрева,
    первый- включен К3 - это 1 Квт.
    второй- включен К1 -это 2 Квт.
    третий- включен К1 и К3 -это 3 Квт.
    четвёртый- включен К1 и К2 -это 4 Квт.
     
  12. mednagolov

    mednagolov Гик

    До первой декады октября, мне вполне хватало первой режима, сейчас -днём первая и к вечеру и на ночь вторая ступень.
    Далие будет холоднее так дойдёт дело и до повышенных передач ...
    Котел самодельный, типа труба 72 в которую вкручен блок из двух ТЭН, безовсякой термоавтоматики.
    На фабричных котлах да , установлена термоавтоматика. Но у меня котёл установлен в подвале и ,,самотягом,, гонит теплоноситель, и каждый раз бегать в подвал крутить на нём регулировки напряжно как то.
    Поэтому ТЭНы котла выведены в щиток как на схеме, только пока вместо К1-К3 стоят автоматики 10 А.
    Щелкать автоматиками конечно в разы удобнее чем лазать каждый раз в подвал, но вот и хочу научить Ардуинку чтоб управляла отопленинм.
     
  13. mednagolov

    mednagolov Гик

    Конечно хотелось бы вместо К1-К3 поставить силовые ключи типа этого-
    2022-10-21 14.02.06.jpg
    и типа шикарно ШИМить ТЭНы безовсяких ,,ступеней,, но я пробовал открывать этот ключ от блока питания ТВантены, чёта не работает, наверное ключ дохлый. Тогда на АВИТО взял по 250 руб. три релюшки на 30 А с катушками 220В. (тип- NT90TPN) , Эти релейки и стоят в фирменых ЭЛкотлах на термоавтоматике. Буду значит ступенчатую терморегулировку мастырить.
     
  14. mednagolov

    mednagolov Гик

    Сэр, какие конкретно Ваши предложения, Сэррр... ?
     
  15. mednagolov

    mednagolov Гик

    И так далие.... из сугубо экономических соображений мыслю так - с 8часов до 17вечера с ПН-ПТ , мы все на работе так пусть температура в доме будет ну скажем 10-15 градусов, а к возвращению домой пусть нагреет до 22-23 градуса, Мыслю неплохая экономия киловатт получится, да ещё и двух тарифный счётчик поможет в благостной экономии...
     
  16. mednagolov

    mednagolov Гик

    Тааак.... в блок *часов* надо добавить счётчик дней недели.....
     
  17. ИгорьК

    ИгорьК Гуру

  18. mednagolov

    mednagolov Гик

    Дописал дни недели, и далас 18b20 который меряет температуру в помещении.


    Код (C++):
    /*
    кнопки подтянуты к +5 v. ,,INPUT_PULLUP ,,
    резисторы по 2,4 кОм последовательно.
    */


    //**************************************************************************************  
    #include <LiquidCrystal_I2C.h> // библиотека для LCD 1602
    LiquidCrystal_I2C lcd(0x27,16,2);  // присваиваем имя дисплею
    //**************************** пмны ардуино и переменные *********************************************************
    const int pin_but = A0;      // pin на кнопки
    const int bip = 3 ;         // зумер подключен к D3
    int x=0;               // координата вывода текста на дисплей
    int y=0;              // координата вывода текста на дисплей
    int M=0;                   // переменная для меню        
    //int X = 0;
    int sek=0;                   // секунда
    int mint=0;                 // минута
    int ch=0;                  // час
    int Ned=0 ;               // дни недели

    int but=0;                  // Создаем переменную для нопок
    int s=0;                   // секунда для таймера возврата
    uint32_t myTimer1 ,  myTimer2, myTimer3 ;      // для таймера на millis()
    boolean selekt = false;    // флаг кнопки селект
    boolean Up = false;       // флаг кнопки верх
    boolean Down = false;    // флаг кнопки низ
    boolean Rait = false;   // флаг кнопки право
    boolean but_flag = false;  // если кнопки не нажаты
    // подкл.библиотеки для DS18B20
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #define ONE_WIRE_BUS A1 //обьявляем ONE_WIRE_BUS к пину (A1)
    // Настройте oneWire для связи с любыми устройствами OneWire
    //  (а не только с микросхемами температуры Maxim / Dallas)
    OneWire oneWire(A1); // вход датчиков 18b20
    DallasTemperature ds(&oneWire);
    DeviceAddress sensor_pom = {0x28, 0xFF, 0x46, 0x9C, 0x30, 0x17, 0x3, 0x70};// адрес моего датчика
    float T_pom=0;     //переменная для температуры в помещении сейчас
    float T_ul=0;     //переменная для температуры на улице сейчас

    void setup(){
    Serial.begin(9600);     // запускаем монитор порта
      lcd.init();           // инициализация дисплея
      lcd.backlight();     // включение подсветки дисплея
    ds.begin();            // инициализация термодатчика  DS18B20
           // устанавливаем разрешение датчика 11 бит (может быть 9, 10, 11, 12)
        // на точность измерения температуры показатель не влияет.
         ds.setResolution(sensor_pom , 11);

    //pinMode(pin_but,INPUT);    // пин кнопок на чтение
    pinMode(bip,OUTPUT);        //пин на бипер
    pinMode(pin_but, INPUT_PULLUP);   //пин на блок кнопок
    ////////////// заставка //////////////////////////////////////////////
    tone(bip,1000,100);
    lcd.setCursor(0, 0); lcd.print( " Atmega-328 -OK" );
    delay (1000);
    tone(bip,1500,300);
    lcd.clear();
    }
    void loop() {
    if (millis() - myTimer1 >= 1000  )    // таймер на millis()
    {  myTimer1 = millis();  sek++;  s++;}
    if (sek>=60){mint++; sek=0;}            //считает секунды
    if (mint>=60){ch++; mint=0;}           // считает минуты
    if (ch>=24){ch=0;Ned++ ;}             // считает часы
    if (Ned > 7){Ned = 0;}               // считает день недели

    if (millis() - myTimer3 >= 5000  )
      {  myTimer3 = millis();    // таймер на millis()
    ds.requestTemperatures(); // считываем температуру с датчиков
       T_pom=ds.getTempC(sensor_pom); // присваиваем показания датчика температуры переменной T_pom
      }
        if (millis() - myTimer2 >= 300  )  // таймер на millis() каждые 300 Мсек.
         {  myTimer2 = millis();           //  опрашивает блок кнопок
    but = analogRead (A0);   // пин ардуино A0 считывает блок кнопок
    // работа с датчиком температуры

    if (but < 20){   // Если нажата кнопка СЕЛЕКТ
         Serial.print("Value A0 ‘Select’ is  :");// Вывести текст на М.П.
         Serial.println(x,DEC);  // Вывести значение переменной x на манитор порта
    M++; if (M>3){M=0;}    
    //selekt=true; s=0;
    tone(bip,1500,300);
     
    }
      else if (but < 100) {  // Если нажата кнопка В ПРАВО
      //lcd.print ("Rait ");                   // Вывести текст на экранчик
           Serial.print("Value A0 ‘Right’ is  :"); // Вывести текст на М.П.
           Serial.println(x,DEC);                  // Вывести значение переменной x на М.П.
    Rait = true;          // поднимаем флаг В ПРАВО
    tone(bip,2000,300);

    }
      else if (but < 150) {  // Если нажата кнопка В ВЕРХ
      //lcd.print ("Up    ");                   // Вывести текст на экранчик
            Serial.print("Value A0 ‘UP’ is  :");    // Вывести текст на М.П.
            Serial.println(x,DEC);                  // Вывести значение переменной x на М.П.
    Up = true;                // поднимаем флаг В ВЕРХ
    tone(bip,2000,300);

    }
      else if (but < 200){    // Если нажата кнопка В НИЗ
      //lcd.print ("Down  ");                   // Вывести текст на экранчик
      Serial.print("Value A0 ‘Down’ is  :");  // Вывести текст на М.П.
      Serial.println(x,DEC);                  // Вывести значение переменной x на М.П.
    Down = true;              // поднимаем флаг В НИЗ
    tone(bip,2000,300);

    }
    /* else if (but < 600){     //  Если нажата кнопка В ЛЕВО
      lcd.print ("Left  ");                   // Вывести текст
      Serial.print("Value A0 ‘Left’ is  :");  // Вывести текст
      Serial.println(x,DEC);                  // Вывести значение переменной x
    }*/

    }
    if (but < 900){ lcd.clear(); s=0;} // если нажата любая кнопка сброс таймера возврата в меню №0
    if(M==0){ // МЕНЮ №0
           // рисуем часы
    x=8; y=0;
    lcd.setCursor(x, y);
    if(ch<10){lcd.print("0");}// всегда 2 цифры
    lcd.print( ch );
            if(sek%2){lcd.print(":");}
            else {lcd.print(" ");}
    if(mint<10){lcd.print("0");}// всегда 2 цифры
    lcd.print(mint);
             lcd.print("-");
              lcd.print(Ned);
    x=0; y=0;lcd.setCursor(x, y);
    lcd.print( T_pom );     // показать температуру в помещении
    lcd.print(" C");    
    }
    if(M==1){
    lcd.setCursor(0,0); lcd.print ("LOAD CLOK");
    //if (sek%2){  lcd.print ("1");}
    //else {lcd.print(" ");}
          // рисуем часы
    x=8; y=1;
    lcd.setCursor(x, y);
    if(ch<10){lcd.print("0");}// всегда 2 цифры
    lcd.print( ch );
    //if(sek%2) {lcd.print( ch );   }
    //else { lcd.setCursor(x, y); lcd.print("  ");}
               lcd.print(":");
    if(mint<10){lcd.print("0");}// всегда 2 цифры
    lcd.print(mint);
               lcd.print("-");
              lcd.print(Ned);
          if(Up == true){ch++;}       // кнопка в верх,увеличивает часы
          if(Down == true){mint++;}  // кнопка в низ,увеличивает минуты
          if(Rait == true){Ned++;}    // кнопка в право,запомнить и возвеат в меню №0
    if( s>10){ lcd.clear(); M=0;}  // если кнопки не нажимаются 10 сек. возврат в меню №0
    }
    if(M==2){
    //lcd.setCursor(3,0); lcd.print ("NASTROIKA -2");
    //lcd.setCursor(0,0); lcd.print ("M-2");
    //if (sek%2){ lcd.setCursor(2,0); lcd.print (" ");}
    //if (selekt==true){M++;lcd.clear();} // if (M>3){M=0;}
    }
    if(M==3){
    //lcd.setCursor(3,0); lcd.print ("NASTROIKA -3");
    //if (selekt==true){M++;lcd.clear();}  //if (M>3){M=0;}
    }
    //сброс флагов кнопок
    but_flag=false;
    selekt=false;
    Up=false;
    Down=false;
    Rait =false;
    noTone( bip);  // не пищать!
    }
     
  19. mednagolov

    mednagolov Гик

    Чета не могу сообразить как уличный далас сюда прикомпазитить...
    OneWire oneWire(A1); // вход датчиков 18b20
    -- указать пин А2 ?
    DallasTemperature ds(&oneWire);
    --указать- ds_ul ?
    соответственно его ID -- DeviceAddress sensor_ul = { его адрес }

    и всё чтоли ?
    чего то не то .....не ехает однако....
     
  20. mednagolov

    mednagolov Гик

    Термозащиту думаю сделать так...
    последовательно соединить терморезистор и термопредохранитель и прикрепить их к корпусу котла.
    терморезистор выколупал из старой Ni-Cd батареи от шуруповерта, термопредохранитель скомуниздил из старого термоспота.
    Принцип работы таков - чем горячее котел тем больше сопротивление терморезистора, ардуинка его следит и пишет в критическом перегоеве термопредахранитель разорвёт цепь и по нулевому сопротивлению *цепи защиты* ардуинка уйдет в *алярм* .... отключит котел вообще, и выдаст надпись *алярм* и зумер.
    термозащита.jpg