Контроллер солнечного коллектора / газовая горелка

Тема в разделе "Глядите, что я сделал", создана пользователем Dixon, 27 июл 2015.

?

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

  1. Куплю

    1 голосов
    14,3%
  2. Сделаю

    6 голосов
    85,7%
  1. Dixon

    Dixon Нуб

    Собрал контроллер для солнечного коллектора.
    Логическая схема такая:
    1) Если температура в коллекторе > 60
    или
    Температура в печи > 60
    PMP1 ON
    K6 ON (подаем напряжение чтобы открыть клапан)
    K4 ON (подаем напряжение чтобы закрыть клапан на горелке)

    Если T1>T2
    K2 ON

    иначе
    K3 ON

    2) Отключить насос, если температура ниже 60

    3) Набираем воду, если уровень L1 опустился на 50%
    Если L1 = 50%
    делать пока L1 не= FULL
    набирать воду
    K1 LOW
    4) Если температура дошла до критической (дома нет никого), начинаем сливаем в печь, до L2=FULL и набираем свеженькой холодной.

    5) Теперь зимой
    Если Т1<0
    Включаем циркуляцию
    K3 ON
    K5 ON
    PMP1 ON
    K7 OFF
    6) Вкл. откл. насоса в бане в ручную

    3-х контактный уровень сделал из центральной жилы телевизионного экранированного провода, остальную инф. выложу по мере поступления вопросов.

    Сейчас решаю такую проблему:
    Все клапаны на схеме нормально закрытые, срабатывают моментально.
    На горелке взял такой клапан: Клапан закрывается замыканием черного провода на ноль, закрывание происходит 15 сек.
    Образно можно сказать так: У меня 1 труба запитана с одной стороны горелкой, с другой стороны коллектором с насосом. Нельзя одновременно включать эти 2 устройства навстречу друг другу. А тут 1 клапан оочень медленный. Как это решить?
    Если я ставлю паузу так:
    delay(15000), у меня происходят зависания на каждые 15 сек. Сейчас изучаю проблему, возможно использую прерывания...
     

    Вложения:

    Последнее редактирование: 27 июл 2015
  2. 9xA59kK

    9xA59kK Гик

    Избавься от delay() зависания исчезнут, почитай тут и тут и в инете много примеров. Запрограммируй watchdog - сторожевой таймер- обязательно вот тут.
     
    Dixon нравится это.
  3. Dixon

    Dixon Нуб

    9xA59kK Спасибо за наводку. Выдалась минутка, попробовал прикрутить таймер по millis(), вывел функцию управления насосами в отдельный цикл
    Код (Text):
    void mode_collector(unsigned long pause ){
      static unsigned long prevTime = 0;

      if (temp_T1 > T1_max || temp_T2 > T1_max){
        digitalWrite(K4_pin, LOW); //Поскольку норм.открытый закрывает целых 15 сек...
     
        if(millis() - prevTime > pause) {
          prevTime = millis();
       
          if (temp_T1 > temp_T2) {
          digitalWrite(K6_pin, LOW);
          digitalWrite(PMP1_pin, LOW);
          digitalWrite(K2_pin, LOW);
          }
          else {
            digitalWrite(K6_pin, LOW);
            digitalWrite(PMP1_pin, LOW);
            digitalWrite(K3_pin, LOW);
        }
        }
      }
        else {
        digitalWrite(PMP1_pin, HIGH);
        digitalWrite(K4_pin, HIGH);
        digitalWrite(K6_pin, LOW);
        digitalWrite(K2_pin, HIGH);
        digitalWrite(K3_pin, HIGH);
        digitalWrite(K5_pin, HIGH);
        }
    }
    Но загарается только K4_pin, по истечении 15 сек ничего другого не загорается. Проверил, в цикл проверки времени моя программа не попадает... Приду домой, подумаю.
     

    Вложения:

  4. 9xA59kK

    9xA59kK Гик

    Странный у тебя кусок кода, особенно мне не понятна логика вот этого ---
    if (temp_T1 > temp_T2) {
    digitalWrite(K6_pin, LOW);
    digitalWrite(PMP1_pin, LOW);
    digitalWrite(K2_pin, LOW);
    }
    else {
    digitalWrite(K6_pin, LOW);
    digitalWrite(PMP1_pin, LOW);
    digitalWrite(K3_pin, LOW);
    }

    Это что, если Т1>T2 то включаем(или выключаем) что то, А ИНЧЕ делаем почти тоже самое только К3 появилась. Оно у тебя никогда не выключится(или не включится) по истечении паузы и привышении температуры Т1>T2.

    Отладку делай поэтапно , пока не разобрался как оно работать должно.
    Помигай релюхами отдельно, напиши маленький код чисто для этого куска и проверь как должна работать пауза вместе с Т1 и Т2.
    ======================================
    Этот способ с милис ты взял от мигания свтодиодом, то и этот код у тебя будет тоже мигать, поскольку завершения миганию или включения чего то нету. Никаких флагов или условий нету чтобы это прекратить.
    ================
    Если тебе нужен таймер отсчитывающий некоторое время после которого произойдет событие, то и собирай счетчик который начнет тикать(при условии.....), используя милис, а когда натикает нужное время, то и сработает что нужно и остановит таймер или сбросит, кому как.
     
    Последнее редактирование: 28 июл 2015
  5. 9xA59kK

    9xA59kK Гик

    -------------------------------------
    Про трубы с клапанами включенные навстречу. У тебя там стоят обратные клапаны? А то ведь у кого давление больше тот и выдавит другого - в некоторый момент. Если конечно между ними не будет тройник соединенный с атмосферой(без подпора).
     
  6. Dixon

    Dixon Нуб

    Там ничего странного, если посмотреть приложенную схему. Должен открыться либо клапан с печки, либо клапан с коллектора. В зависимости от того, где вода горячее. Пока температура воды выше установленной, не должно выключаться. Это все работает, вот с таймером сейчас разбираюсь.
    Что-то сложно все. У меня гораздо проще. Давление на трубу горячей воды может дать с одной стороны газовая горелка подключенная одним концом к холодной воде, выходом горячей воды в мою трубу. Давление горячей воды чуть меньше чем давление холодной воды. С другой стороны в эту же трубу смотрит бак на крыше / либо бак печки, каждый закрыт своим клапаном. Клапаны обычные, 12В, китайские по 3$. На горелке стоит клапан за 90$, писал ранее.
     
  7. Dixon

    Dixon Нуб

    1 проблема была в моей невнимательности, после исправления:
    pinMode(PMP1_pin, OUTPUT);
    pinMode(K1_pin, OUTPUT);
    pinMode(K2_pin, OUTPUT);
    pinMode(K3_pin, OUTPUT);
    pinMode(K4_pin, OUTPUT);
    pinMode(K5_pin, OUTPUT);
    pinMode(K6_pin, OUTPUT);
    Все нужные релюхи включились (но без задержки...) и держатся включенными пока температура не спадет.
    При этом начинается глюк с меню. Попадает в цикл изменения меню. Как будто Нажата кнопка энкодера. Меню постоянно перескакивают по пунктам, похоже в такт 15сек.
    Похоже не в правильном направлении копаем, товарищи. Надо разобраться с прерываниями.

    Задача тревиальна, дать паузу 1 раз при запуске.
     
    Последнее редактирование: 29 июл 2015
  8. Dixon

    Dixon Нуб

    УФФ! решил одну проблему, получил еще две!
    Итак по порядку:
    Задержка по времени заработала. Написал так:
    Код (Text):
    void mode_collector(unsigned long pause ) {
      static unsigned long prevTime = 0;
      static int valBut = 0;
        if (temp_T1 > T1_max || temp_T2 > T1_max) {
        digitalWrite(K4_pin, LOW); //Поскольку норм.открытый закрывает целых 15 сек...
          Serial.print ("millis-prevTime= ");Serial.println (millis()-prevTime);
         
          if(millis()-prevTime>=1 && digitalRead (K4_pin)==LOW) { // начинаем считать время включения
          Serial.print("PIN_ENCODER_SW= ");Serial.println(digitalRead(PIN_ENCODER_SW));
          Serial.print("prevTime= ");Serial.println(prevTime/1000);
          Serial.print("valBut= ");Serial.println(valBut);

          prevTime=millis();
          valBut++; // с каждой милисекундой увеличиваем значение valBut

            if(valBut>=pause/1000){ // как только значение valBut становиться равным WAIT_INTERVAL
         
              if (temp_T1 > temp_T2) {
              digitalWrite(K6_pin, LOW);
              digitalWrite(PMP1_pin, LOW);
              digitalWrite(K2_pin, LOW);
              Serial.print("K2_pin= ");Serial.println(digitalRead(K2_pin));
              Serial.print("PIN_ENCODER_SW= ");Serial.println(digitalRead(PIN_ENCODER_SW));
            }
            else {
              digitalWrite(K6_pin, LOW);
              digitalWrite(PMP1_pin, LOW);
              digitalWrite(K3_pin, LOW);
              Serial.print("K3_pin= ");Serial.println(digitalRead(K3_pin));
              Serial.print("PIN_ENCODER_SW= ");Serial.println(digitalRead(PIN_ENCODER_SW));
            }
            valBut=0;
          }

          }
          else // valBut становится равным 0
          { // это необходимо для защиты от срабатывания при частых и многократных включениях
          valBut=0;
          }
         
        }
        else {
        digitalWrite(PMP1_pin, HIGH);
        digitalWrite(K4_pin, HIGH);
        digitalWrite(K6_pin, LOW);
        digitalWrite(K2_pin, HIGH);
        digitalWrite(K3_pin, HIGH);
        digitalWrite(K5_pin, HIGH);
        }
      }
     
    Теперь включаются клапаны с задержкой, но появились глюки:
    1) При срабатывании проходит секунд 20 и на дисплее загорается меню. Как будто нажата кнопка PIN_ENCODER_SW Далее меню потихоньку начинает гулять по пунктам, пока температура не опустится и мы не выйдем из цикла mode_collector
    2) Касается самого меню. При сохранении значения T1_min отличного от 0, значение T1_max странным образом, само меняется на 65550
     

    Вложения:

  9. DrProg

    DrProg Вечный нерд

    То есть вы внутри функции делаете паузу по таймеру? Странно это ну да ладно. И еще сдается мне что вот так:
    Код (Text):
          valBut++; // с каждой милисекундой увеличиваем значение valBut

            if(valBut>=pause/1000){ // как только значение valBut становиться равным WAIT_INTERVAL
    делать таймер не верно, он считает не миллисекунды а кол-во циклов, цикл же длится непредсказуемое кол-во миллисекунд (чаще всего дольше), а значит событие будет происходить в непредсказуемое время. Правильно сравнивать сохраненный таймер с millis()
    Код (Text):
    if ((millis() - prevTime) >= 1000) { // для секунды например
    ....
    }
     
    Dixon нравится это.
  10. Dixon

    Dixon Нуб

    Может где-то ошибусь, не судите строго. Это мой первый проект.

    Если prevTime стартует с нуля, значит millis будет более 1000 изначально и не возникнет никакой паузы.

    Можно ей присвоить какое-то значение, но тогда он может "заморгать", что мне не нужно. Хотя я эксперементировал, она сразу включает, без паузы.
    Чтобы отслеживать запуск/остановку медленного клапана, надо завести некую переменную для проверки ее значений.
    Цикл действительно пробегает быстрей заданного времени, поэтому удвоил таймер. Мне главное результат, как лучше придумать паузу пока не придумал.
     
  11. DrProg

    DrProg Вечный нерд

    Прямо перед циклом:
    Код (Text):
    prevTime = millis();
     
  12. Dixon

    Dixon Нуб

    Если в таком виде, горят только K4_pin и K6_pin, millis()-prevTime каждый раз обнуляется
    Код (Text):

    void mode_collector(unsigned long pause ) {
      static unsigned long prevTime = millis();
      static int valBut = 0;
      if (temp_T1 > T1_max || temp_T2 > T1_max) {
      digitalWrite(K4_pin, LOW); //Поскольку норм.открытый закрывает целых 15 сек...
      prevTime = millis();
      if(millis()-prevTime>=pause && digitalRead (K4_pin)==LOW) { // если прошло время паузы и медленный включен
      Serial.print ("millis-prevTime= ");Serial.println (millis()-prevTime);
      Serial.print("prevTime= ");Serial.println(prevTime/1000);
      Serial.print("valBut= ");Serial.println(valBut);

      //prevTime=millis();
      //valBut++; // с каждой милисекундой увеличиваем значение valBut
      //if(valBut>=pause/1000){ // как только значение valBut становиться равным WAIT_INTERVAL
       
      if (temp_T1 > temp_T2) {
      digitalWrite(K6_pin, LOW);
      digitalWrite(PMP1_pin, LOW);
      digitalWrite(K2_pin, LOW);
      Serial.print("K2_pin= ");Serial.println(digitalRead(K2_pin));
      Serial.print("PIN_ENCODER_SW= ");Serial.println(digitalRead(PIN_ENCODER_SW));
      Serial.print("valBut= ");Serial.println(valBut);
      // valBut=0;  //Надо обнулять каждый раз
      prevTime = millis();
      }
      else {
      digitalWrite(K6_pin, LOW);
      digitalWrite(PMP1_pin, LOW);
      digitalWrite(K3_pin, LOW);
      Serial.print("K3_pin= ");Serial.println(digitalRead(K3_pin));
      Serial.print("PIN_ENCODER_SW= ");Serial.println(digitalRead(PIN_ENCODER_SW));
      Serial.print("valBut= ");Serial.println(valBut);
      prevTime = millis();
      }
       
      //  }

      }
      else // valBut становится равным 0
      { // это необходимо для защиты от срабатывания при частых и многократных включениях
      valBut=0;
      }
       
      }
      else {
      digitalWrite(PMP1_pin, HIGH);
      digitalWrite(K4_pin, HIGH);
      digitalWrite(K6_pin, LOW);
      digitalWrite(K2_pin, HIGH);
      digitalWrite(K3_pin, HIGH);
      digitalWrite(K5_pin, HIGH);
      }
      }
     
    если комментирую prevTime = millis();
    Пауза срабатывает, но только первый раз.
    Если повторно произошел нагрев, включаются все релюхи одновременно.
    "Скакание меню" в таком варианте пропало.
     
    Последнее редактирование: 31 июл 2015
  13. DrProg

    DrProg Вечный нерд

    Блин, после срабатывания необходимо снова сделать prevTime = millis(); тем самым сбросив таймер, это же очевидно!
     
  14. Dixon

    Dixon Нуб

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

    Вложения:

    • log.txt.zip
      Размер файла:
      1,5 КБ
      Просмотров:
      265
  15. DrProg

    DrProg Вечный нерд

    Пока нет возможности смотреть код. Меню от чего работает? От кнопок?
     
  16. Dixon

    Dixon Нуб

    Сейчас еще один "затык" вылез. Поставил разделяющий клапан К6, китайский. Оказалось китайские клапана держат только в одну сторону!!! В китайском находится резиновая прокладка, если подать давление с другой стороны, происходит открытие.
    Пришлось заказать полноценный, такой как на горелке К4, Gidrolock 12В

    Меню работает от энкодера. При долгом нажатии кнопки энкодера, попадает в одноуровневое меню.
    Думаю может насильно в цикле присваивать значение PIN_ENCODER_SW, что он сам начинает меняться...
     
  17. Dixon

    Dixon Нуб

    IMG_20150805_130304.jpg IMG_20150805_130328.jpg uroven.jpg
    Сегодня пришли 3 драйвера на 12В установил и сфоткал. 5В беру с импульсного БП 5В 2000мА.
    Ардуина питается по USB от БП или компьютера в случае программирования.
    На Фото-3 уровень, внутри спрятан датчик температуры. Жилы 4 антенных проводов выходят на разной глубине оголенными концами, 1 общий, 3 уровня (Empty, LOW, 50%, FULL). В центре оплетка силового кабеля. Чтобы придать устойчивость, в оплетку поместил общую жилу и залил все жидкими гвоздями и замотал все изолентой. Посмотрим на сколько хватит.
     
  18. Dixon

    Dixon Нуб

    Проблема скакания по меню во время срабатывания таймера решилась заменой БП на более мощный 5В 3А.
    Но таймер срабатывает только первый раз при первом включении. При 2-м срабатывании в переменной prevTime сидит старое значение и паузы не происходит.
     
  19. Dixon

    Dixon Нуб

    Разобрался с паузой, так правильно работает!
    Код (Text):
    void mode_collector(unsigned long pause ) {
        static unsigned long prevTime = millis();
        static int valBut = 0;
        if (temp_T1 > T1_max || temp_T2 > T1_max) {
            digitalWrite(K4_pin, LOW); //Поскольку норм.открытый закрывает целых 15 сек...
            if(millis()-prevTime>=pause) {
            //Serial.print ("millis()-prevTime = ");Serial.println (millis()-prevTime);
            //Serial.print("prevTime= ");Serial.println(prevTime);
     
              if (temp_T1 > temp_T2) {
              digitalWrite(K6_pin, LOW);
              digitalWrite(PMP1_pin, LOW);
              digitalWrite(K2_pin, LOW);
              prevTime = millis();
            }
            else {
              digitalWrite(K6_pin, LOW);
              digitalWrite(PMP1_pin, LOW);
              digitalWrite(K3_pin, LOW);
              Serial.print("K3_pin= ");Serial.println(digitalRead(K3_pin));
              Serial.print("PIN_ENCODER_SW= ");Serial.println(digitalRead(PIN_ENCODER_SW));
              prevTime = millis();
            }
          }
        }
        else {
        digitalWrite(PMP1_pin, HIGH);
        digitalWrite(K4_pin, HIGH);
        digitalWrite(K6_pin, LOW);
        digitalWrite(K2_pin, HIGH);
        digitalWrite(K3_pin, HIGH);
        digitalWrite(K5_pin, HIGH);
        prevTime = millis();
        }
      }
     
  20. Dixon

    Dixon Нуб

    Собрал все в реале, на реальном объекте.
    В общем все более менее работает, но есть грабли. Датчик уровня установленный на коллекторе заработал, но только первый день. с утра тупо писал FULL, и ничего не помогало, лампочки потухли. Поскольку схему я паял "навсегда", залил все термоклеем, схема оказалась не ремонтопригодной. Хотя на тесте все вроде бы работало. Пришлось заново спаять схемку, уже предусмотрел разбор с помощью компьютерных пинов, на схему загнаны все элементы (все резисторы и конденсаторы). Драйверы на 12В оказались ~ тока. Пришел адаптер на 5В 3А, вставил его внутрь, запитал свою схему и ардуину по USB IMG_20150818_154823.jpg IMG_20150818_162712.jpg IMG_20150818_154843.jpg IMG_20150818_175908.jpg
    С новой схемкой все заработало, но когда вода наливается до FULL, начинает понемногу переливаться. Причина - FULL прыгает то на 50% (на секунду вода начинает набираться), потом на FULL, стоит минуту-две, потом может скакнуть на LOW на секунду и вернуться в FULL. Реле набора воды постоянно щелкает, уж и не знаю что придумать, надо попробовать с таймерами поэксперементировать...
    Делал по этой схеме: arduino-water-level-sensor.jpg
    Сам уровень переделал, внутри находится металлический стержень (попался под руку масляный щуп от авто), т.к. при 100С все кроме металла превращается в гибкую колбасу:) IMG_20150815_100359.jpg

    Еще грабли: Оказалось китайские клапаны держут в одну сторону, но у меня давление может идти с двух сторон. Так например:
    1) вода с коллектора заливается в бак печи.
    2) Если не перекрыта газовая горелка, горелка выдавливает горячую воду в бак.
     
    Последнее редактирование: 20 авг 2015