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

Тема в разделе "Arduino & Shields", создана пользователем Viacon, 25 окт 2016.

  1. Igor68

    Igor68 Гуру

    Вы не поняли.
    Надо как было:
    if(temp>needTemp) decTemp();
    if(temp<needTemp) incTemp();

    В этом смысл того самого "гистерезиса" и отсутствии необходимости в:
    // для чего? не нашел применение
    int lastTemp=0;

    и
    ну или что-то подобное и автор хотел "усреднять" с предыдущим значением температуры. По крайней мере не нашёл.
     
    Viacon нравится это.
  2. Igor68

    Igor68 Гуру

    Да нет, я про другое определение:
    boolean enabled=false;
     
  3. Viacon

    Viacon Нуб

    как надо в моем случае?
     
  4. Igor68

    Igor68 Гуру

    Я уже говорил:
    if(temp>needTemp) decTemp();
    if(temp<needTemp) incTemp();

    А в том ... я обсуждал назначение(предположительного) нигде не применяемое:
    // для чего? не нашел применение
    int lastTemp=0;
     
  5. Viacon

    Viacon Нуб

    ясно, и про кнопки:
    Да, это не кнопка, а питание на подсветку дисплея газовой колонки - оно является сигналом для включения устройства на ардуино
    // создать переменную "enablePin" для включения Ардуино
    // на порт 8
    int enablePin=8;

    //устанавливаем режимы портов:
    pinMode(enablePin,INPUT); // установить "enablePin" на приём
    // данных (вход)
     
  6. qwone

    qwone Гик

    Ну я код перевел так
    Код (C++):
    /*https://geektimes.ru/post/252796/
    серва                     -> 9 (servo_pin)
    датчик температуры        ->A5 (termalPin)
    тумблер "ВКЛ"             ->8 (enablePin) 1 - регулировка разрешена / 0 нет
    светодиод                 ->7 (enablePin)
    */


    const int termalPin = A5; // пин датчика температуры
    static int needTemp = 40; // нужная температура в колонке
    int temp; // температура на датчике
    int lastTemp = 0;

    const int enablePin = 8;  // пин определящий вкл колонка или нет
    boolean enabled = 0; // режим 0 разогрев / 1 регулирование нужной температуры
    const int ledPin = 7; // пин светодиода 1 горит (бойлер нагрет) / 0 нет
    #include <Servo.h>
    const int servo_pin = 9; // пин сервы
    Servo myservo;
    static int minAngle = 5;
    static int maxAngle = 100;

    // повысить температуру в колонке
    void incTemp()  {
      int p = needTemp - temp; // разница температуры
      Serial.print("raise the temp. P=");
      Serial.println(p);
      int pos = myservo.read();
      int newpos = pos - p;
      for (int i = pos; i >= newpos; i--)  {
        if (i > minAngle) myservo.write(i);
        if (i < minAngle) myservo.write(minAngle);
        delay(50);
      }
      if (p > 5)delay(p * 1000);
      else {
        if (p <= 3) delay(p * 3000);
        else delay(p * 2000);
      }
    }
    // понизить температуру в колонке
    void decTemp() {
      int p = temp - needTemp;
      Serial.print("lower the temp. P=");
      Serial.println(p);
      int pos = myservo.read();
      int newpos = pos + p;
      for (int i = pos; i <= newpos; i++) {
        if (i < maxAngle) myservo.write(i);
        if (i > maxAngle) myservo.write(maxAngle);
        delay(50);
      }
      if (p > 5) delay(p * 1000);
      else {
        if (p <= 3) delay(p * 3000);
        else delay(p * 2000);
      }
    }

    void setup() {
      Serial.begin(9600);  //включаем сериал
      pinMode(enablePin, INPUT);  //подключаем тублер "ВКЛ"
      pinMode(ledPin, OUTPUT); //
    }

    void loop() {
      temp = map(analogRead(termalPin), 800, 635, 31, 51); // измеряем температуру 800 это 31 градус 636 это 51
      if (digitalRead(enablePin)) { // если тублер включен
        if (!enabled) { // если колонка не разогрета , то разогреваем
          myservo.attach(servo_pin);//атачим серву
          myservo.write(50);//ставим на середину
          Serial.println("WARMING UP BOILER.");      //ждем пока колонка разогреется
          delay(10000); // пауза 10 секунд
        }
        enabled = 1;
        //режим регулирования
        digitalWrite(ledPin, 1); //светодиод - "Режим регулирования"
        Serial.print("BOILER ONLINE. CURRENT TEMP: ");
        Serial.print(temp);
        Serial.println(" C");
        if (temp > needTemp) decTemp();     //смотрим на температуру и куда ее крутить
        if (temp < needTemp) incTemp();
        delay(300);
      }
      else {  // если тублер выключен
        if (enabled) {      //выключение
          Serial.println("BOILER OFFLINE. GOOD LUCK!");
          myservo.write(50);       //ставим серву посредине
          myservo.detach();      //детачим чтоб не жужжала
          enabled = 0;
        }
        digitalWrite(ledPin, 0);    //гасим лампочку
      }
    }

     
    ПС: По мне архитектура программы очень ужасна.
     
  7. Viacon

    Viacon Нуб

    нет это не тумблер, вот цитата из его темы:
    Далее, я сделал так чтобы при включении колонки — включался весь процесс, незачем пытатся повысить температуру когда колонка выключена. Для этого монитрю провод питания экранчика(который работает только при включеной колонке) на предмет напряжения. И если оно есть — запускаю процесс.

    И по-моему 7 пин на светодиод - только индикация режима "включено" работы ардуино для отладки.
    Это не бойлер, а газовая колонка и нет режима "бойлер нагрет"...
     
    Последнее редактирование: 28 окт 2016
  8. qwone

    qwone Гик

    Подачу питания на экран обеспечивает переключатель. у которого есть 2 фиксированых положения. А не кнопка у которого одно подожение, другое если палец нажат. Светодиод горит только тогда когда колонка вышла на режим регулирования. И автор скеча всегда упоминает BOILER -бойлер.
    ПС: Повторяю . автор статьи больше практик. И программа скорее накручена кучей переборов. Ну удивлюсь если температуру меряют термосопротивлением или термоспаем.
     
  9. Viacon

    Viacon Нуб

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

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

    Бойлер - это по английски - колонка, он не стал делать русский, т.к. это только для отладки, далее вывод текста не нужен.

    Хотя про диод это - кому как нравиться... (я тож практик, механик) мне это решение понравилось...
     
    Последнее редактирование: 29 окт 2016
  10. qwone

    qwone Гик

    Вы может рассуждать как хотите. Но в программе нет датчика наличия воды, нет управления электроподжигом, даже нет датчика огня. Банально обрезаный полуавтомат, который следит за температурой воды. А все остальное делает человек на свой страх и риск.
     
  11. Viacon

    Viacon Нуб

    делает сама колонка, в которой есть всё необходимое для работы и защиты
     
  12. Viacon

    Viacon Нуб

    именно это мне и надо :)

    Я рассказал как работает колонка - у меня такая-же. И в случае пропадания давления воды - сработает эл. клапан подачи газа в самой колонке, и перекроет газ.
    все это есть в самой колонке, дополняем регулятором уровня пламени - и всё.
     
    Последнее редактирование: 29 окт 2016
  13. qwone

    qwone Гик

    Нарисовал программу.
    Код (C++):
    /*http://geektimes.ru/post/252796/
    питание с подсветки экрана   ->8 (Enable_pin) 1 - нагрев вкл / 0 откл
    датчик температуры           ->A5 (temperature_sensor_pin)
    светодиод                    ->7 (led_pin)
    серва                        -> 9 (servo_pin)
    */

    //#1
    const int Enable_pin = 8;  // пин питание с подсветки экрана
    uint8_t Enable; // 1 работа / 0 нет
    const int temperature_sensor_pin = A5; // пин датчика температуры
    float temperature; // текущая температура
    const int right_temperature = 40; // нужная температура в колонке
    //#2
    const int led_pin = 7;  // пин светодиода
    #include <Servo.h>
    Servo myservo;
    const int servo_pin = 9; // пин сервы
    uint8_t Enable_servo;// 1 вкл сервы/ 0 откл сервы
    uint8_t pause = 0; // пауза для прогрева 0-50
    uint8_t Angle; // позиция сервы
    const int minAngle = 5;
    const int maxAngle = 100;

    void setup() {
      Serial.begin(9600);  //включаем сериал
      //#1
      pinMode(Enable_pin, INPUT);  //подключаем пин питание с подсветки экрана
      //#2
      pinMode(led_pin, OUTPUT);
      digitalWrite(led_pin, Enable_servo =0);    //гасим лампочку
    }

    void loop() {
      static uint32_t MILLIS ;
      MILLIS = millis() ;
      //#1
      static uint32_t future1 = 0 ;
      if (MILLIS >= future1) {
        future1 = MILLIS + 200 ;
        Enable = digitalRead(Enable_pin);
        temperature = map(analogRead(temperature_sensor_pin), 800, 635, 31, 51); // измеряем температуру
        Serial.print("Temperature =");
        Serial.println(temperature);
      }
      //#2  200 миллисекунд управление сервой.
      static uint32_t future2 = 0 ;
      if (MILLIS >= future2) {
        future2 = MILLIS + 200 ;
        switch (Enable_servo * 2 + Enable) {
          case 1:    // Enable_servo==0 Enable==1  ВКЛ сервы
            if (pause == 0) {
              myservo.attach(servo_pin);  //атачим серву
              myservo.write(50);      //ставим на середину
              Serial.println("BOILER ON");
            }
            pause++; if (pause > 50) {  // делаем паузу 50*200=10000 или 10 секунд
              pause = 0;
              digitalWrite(led_pin, Enable_servo =1);    //вкл лампочку
            }
            break;
          case 2:    // Enable_servo==1 Enable==0  ОТКЛ сeрвы
            myservo.write(50);     //ставим серву посредине
            myservo.detach();      //детачим чтоб не жужжала
            Serial.println("BOILER OFF");
            digitalWrite(led_pin, Enable_servo =0);    //гасим лампочку
            break;
          case 3:    // Enable_servo==1 Enable==1   РЕГУЛИРОВКА ТЕМПЕРАТУРЫ
            if (temperature < right_temperature) {
              Angle = myservo.read();
              Angle += 2; // 2 скорость регулировки
              if (Angle > maxAngle ) Angle = maxAngle;
              myservo.write(Angle);
            }
            else if ( temperature > right_temperature) {
              Angle = myservo.read();
              Angle -= 2; //  2 скорость регулировки
              if (Angle < minAngle ) Angle = maxAngle;
              myservo.write(Angle);
            }
            break;
        }
      }
    }
     
    Последнее редактирование: 29 окт 2016
    Spazma и Viacon нравится это.
  14. Viacon

    Viacon Нуб

    Для меня новичка его скетч более понятен, я так понял, Вы модифицировали программу, и изменили алгоритм регулировки (у Вас 2 скорости регулировки, у него 3 шага регулировок, в зависимости от количества градусов разницы температур).
    По-сути исходные данные остаются теми-же.
    Я завёл тему в связи с тем, что у меня другие исходные данные -
    у меня вместо термистора будет стоять датчик температуры DS18B20.
    Также я планирую регулировать в некоторых пределах температуру на выходе.

    Для первого нашел такую конструкцию:
    //источник: http://arduino-project.net/podklyuchenie-ds18b20-arduino/
    #include <OneWire.h>
    OneWire ds(9);

    void setup() {
    Serial.begin(9600);
    }

    void loop() {

    byte data[2];
    ds.reset();
    ds.write(0xCC);
    ds.write(0x44);
    delay(750);
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    int Temp = (data[1]<< 8)+data[0];
    Temp = Temp>>4;
    Serial.println(Temp);
    }
    Для второго планирую мапить показания потенциометра:
    needTemp = map(analogRead(posPotenz),0,1023,30,50); примерно так
    и третье: меня устраивает алгоритм регулировки в оригинале, т.к. автор допиливал его с практической стороны.

    PS ну и попалась такая тема по поводу: Усреднение значений с потенциометра, думаю, может использовать.
     
    Последнее редактирование: 29 окт 2016
  15. qwone

    qwone Гик

    Код (C++):
    /*http://geektimes.ru/post/252796/
    питание с подсветки экрана   ->8 (Enable_pin) 1 - нагрев вкл / 0 откл
    датчик DS18B20             -> 2    (One_wire_bas_pin)
    светодиод                    ->7 (led_pin)
    серва                        -> 9 (servo_pin)
    */

    //#1
    const int Enable_pin = 8;  // пин питание с подсветки экрана
    uint8_t Enable = 0; // 1 работа / 0 нет

    #include <OneWire.h>
    const int One_wire_bas_pin = 2 ; // пин на шину OneWire
    OneWire oneWire(One_wire_bas_pin);
    #include <DallasTemperature.h>
    DallasTemperature sensors(&oneWire); // подключаем  датчик DS18B20 на шину OneWire

    float temperature; // текущая температура
    const int right_temperature = 40; // нужная температура в колонке
    //#2
    const int led_pin = 7;  // пин светодиода
    #include <Servo.h>
    Servo myservo;
    const int servo_pin = 9; // пин сервы
    uint8_t Enable_servo = 0; // 1 вкл сервы/ 0 откл сервы
    uint8_t pause = 0; // пауза для прогрева 0-50
    uint8_t Angle; // позиция сервы
    const int minAngle = 5;
    const int maxAngle = 100;

    void setup() {
      Serial.begin(9600);  //включаем сериал
      //#1
      pinMode(Enable_pin, INPUT);  //подключаем пин питание с подсветки экрана
      sensors.begin();
      //#2
      pinMode(led_pin, OUTPUT);
      digitalWrite(led_pin, Enable_servo = 0);    //гасим лампочку
    }

    void loop() {
      static uint32_t MILLIS ;
      MILLIS = millis() ;
      //#1
      static uint32_t future1 = 0 ;
      if (MILLIS >= future1) {
        future1 = MILLIS + 200 ;
        Enable = digitalRead(Enable_pin);
        sensors.requestTemperatures(); // послать команду измерить температуру
        temperature = sensors.getTempCByIndex(0);// получить температуру с 1 датчика(0)
        Serial.print("Temperature =");
        Serial.println(temperature);
      }
      //#2  200 миллисекунд управление сервой.
      static uint32_t future2 = 0 ;
      if (MILLIS >= future2) {
        future2 = MILLIS + 200 ;
        switch (Enable_servo * 2 + Enable) {
          case 1:    // Enable_servo==0 Enable==1  ВКЛ сервы
            if (pause == 0) {
              myservo.attach(servo_pin);  //атачим серву
              myservo.write(50);      //ставим на середину
              Serial.println("BOILER ON");
            }
            pause++;
            if (pause > 50) {  // делаем паузу 50*200=10000 или 10 секунд
              pause = 0;
              digitalWrite(led_pin, Enable_servo = 1);    //вкл лампочку
            }
            break;
          case 2:    // Enable_servo==1 Enable==0  ОТКЛ сeрвы
            myservo.write(50);     //ставим серву посредине
            myservo.detach();      //детачим чтоб не жужжала
            Serial.println("BOILER OFF");
            digitalWrite(led_pin, Enable_servo = 0);    //гасим лампочку
            break;
          case 3:    // Enable_servo==1 Enable==1   РЕГУЛИРОВКА ТЕМПЕРАТУРЫ
            if (temperature < right_temperature) {
              Angle = myservo.read();
              Angle += 2; // 2 скорость регулировки
              if (Angle > maxAngle ) Angle = maxAngle;
              myservo.write(Angle);
            }
            else if ( temperature > right_temperature) {
              Angle = myservo.read();
              Angle -= 2; //  2 скорость регулировки
              if (Angle < minAngle ) Angle = maxAngle;
              myservo.write(Angle);
            }
            break;
        }
      }
    }
     
    Spazma и Viacon нравится это.
  16. qwone

    qwone Гик

    Код (C++):
    /*http://geektimes.ru/post/252796/
    питание с подсветки экрана   ->8 (Enable_pin) 1 - нагрев вкл / 0 откл
    датчик DS18B20             -> 2    (One_wire_bas_pin)
    резистор уст нужной температуры ->A5 (R1_pin) 0-1023 => 31- 51
    светодиод                    ->7 (led_pin)
    серва                        -> 9 (servo_pin)
    */

    //#1
    const int Enable_pin = 8;  // пин питание с подсветки экрана
    uint8_t Enable = 0; // 1 работа / 0 нет

    #include <OneWire.h>
    const int One_wire_bas_pin = 2 ; // пин на шину OneWire
    OneWire oneWire(One_wire_bas_pin);
    #include <DallasTemperature.h>
    DallasTemperature sensors(&oneWire); // подключаем  датчик DS18B20 на шину OneWire

    float temperature; // текущая температура
    const int R1_pin = A5;  // пин на потенциометр уст температуры
    float right_temperature ; // нужная температура в колонке уст потенциометром
    //#2
    const int led_pin = 7;  // пин светодиода
    #include <Servo.h>
    Servo myservo;
    const int servo_pin = 9; // пин сервы
    uint8_t Enable_servo = 0; // 1 вкл сервы/ 0 откл сервы
    uint8_t pause = 0; // пауза для прогрева 0-50
    uint8_t Angle; // позиция сервы
    const int minAngle = 5;
    const int maxAngle = 100;

    void setup() {
      Serial.begin(9600);  //включаем сериал
      //#1
      pinMode(Enable_pin, INPUT);  //подключаем пин питание с подсветки экрана
      sensors.begin();
      //#2
      pinMode(led_pin, OUTPUT);
      digitalWrite(led_pin, Enable_servo = 0);    //гасим лампочку
    }

    void loop() {
      static uint32_t MILLIS ;
      MILLIS = millis() ;
      //#1
      static uint32_t future1 = 0 ;
      if (MILLIS >= future1) {
        future1 = MILLIS + 200 ;
        Enable = digitalRead(Enable_pin);
        right_temperature = map(analogRead( R1_pin), 0, 1023, 31, 51); // выставляем температуру 31 - 51  градусов
         Serial.print("Right_temperature =");
        Serial.println(right_temperature);  
        sensors.requestTemperatures(); // послать команду измерить температуру
        temperature = sensors.getTempCByIndex(0);// получить температуру с 1 датчика(0)
        Serial.print("Temperature =");
        Serial.println(temperature);
      }
      //#2  200 миллисекунд управление сервой.
      static uint32_t future2 = 0 ;
      if (MILLIS >= future2) {
        future2 = MILLIS + 200 ;
        switch (Enable_servo * 2 + Enable) {
          case 1:    // Enable_servo==0 Enable==1  ВКЛ сервы
            if (pause == 0) {
              myservo.attach(servo_pin);  //атачим серву
              myservo.write(50);      //ставим на середину
              Serial.println("BOILER ON");
            }
            pause++;
            if (pause > 50) {  // делаем паузу 50*200=10000 или 10 секунд
              pause = 0;
              digitalWrite(led_pin, Enable_servo = 1);    //вкл лампочку
            }
            break;
          case 2:    // Enable_servo==1 Enable==0  ОТКЛ сeрвы
            myservo.write(50);     //ставим серву посредине
            myservo.detach();      //детачим чтоб не жужжала
            Serial.println("BOILER OFF");
            digitalWrite(led_pin, Enable_servo = 0);    //гасим лампочку
            break;
          case 3:    // Enable_servo==1 Enable==1   РЕГУЛИРОВКА ТЕМПЕРАТУРЫ
            if (temperature < right_temperature) {
              Angle = myservo.read();
              Angle += 2; // 2 скорость регулировки
              if (Angle > maxAngle ) Angle = maxAngle;
              myservo.write(Angle);
            }
            else if ( temperature > right_temperature) {
              Angle = myservo.read();
              Angle -= 2; //  2 скорость регулировки
              if (Angle < minAngle ) Angle = maxAngle;
              myservo.write(Angle);
            }
            break;
        }
      }
    }
    ПС: сюда еще индикатор показывающий температуру в колонке и установленую резистором показать
     
    Spazma и Viacon нравится это.
  17. Viacon

    Viacon Нуб

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

    PS посмотри выше мои письмена по поводу алгоритма
     
    Последнее редактирование: 29 окт 2016
  18. Viacon

    Viacon Нуб

    спасибо, придет ардуинка, буду пробовать :)
     
  19. Vitakill

    Vitakill Нуб

    Viacon, уважаемый, как у вас там все получилось? Так сложилось, что я наткнулся на статью на Robocraft`е, но ровно за неделю до создания данной темы. Паять и кодить немного кривенько умею. К исходнику добавил:
    - Регулировку желаемой температуры потенциометром, пытался сделать кнопками, получилось не очень, буду пробовать позже.
    - LCD экранчик 20*01 (PC2001), просто потому что он был (он великоват, подсветка адово греется, зато нахаляву и поддерживает кириллицу). На него выводится текущее / желаемое значение температуры, P и положение сервы. Заказал экран 16*02, его буду встраивать вместе с nano в окончательный вариант.
    - TM1627, 4-х значный LED индикатор, на него тоже выводятся показания температуры, установлю в ванной.

    Сегодня дособирал тестовый образец на китайском Uno. Немного погонял. Нарисовались проблемы:
    - Даже совсем небольшой люфт тяг значительно увеличивает колебания системы, буду искать пружинку.
    - Питание родного термометра 2,3 вольта, на цифровом входе работает нестабильно, переставил на аналоговый вход. Так и не понял нужен ли подтягивающий резистор, работает и с ним и без него.
    - При запуске колонки, из-за помех от высоковольтных цепей поджига, иногда глючит дисплей, контроллер при этом продолжает работать.
    - Термистор с делителем напряжения и функцией map работает очень криво, буду заказывать цифровой датчик. Колебания в 1-2 градуса хорошо чувствуются кожей, нужно работать над стабильностью
    В ближайшие дни буду допиливать, если кому интересно пишите.
     
  20. Viacon

    Viacon Нуб

    Жду цифровой датчик температуры, поднимая тему не думал, что так долго идут комплектующие из Китая, сборку пока не делал.
    Про пружинку знаю (механик по образованию).
    Спасибо за "2,3 вольта на цифровом входе " - запомню.
    Дополнительных экранов не планирую, мне этого достаточно.
    Потенциометр считаю более практичным вариантом по сравнению с кнопками (по-моему кнопки в данном варианте больше похоже на "понты" - мне этого не надо), да и код усложняется - чем проще, тем лучше (я так думаю).
    Про термистор - по этому и заказал цифровой датчик температуры DS18B20