[РЕШЕНО] Пример скетча для попеременной работы нагрузки

Тема в разделе "Arduino & Shields", создана пользователем savdm, 28 янв 2015.

  1. savdm

    savdm Нерд

    Решение и пример скетча с условиями температуры


    Подскажите пожалуйста. Нужно чтобы две нагрузки попеременно работали. Включается одна по температуре --> отработала час выключилась --> включилась другая --> отработала час выключилась --> включилась первая....
    Код (Text):

    void Rele_Control(){ //Функция управления двух реле по температуре
    if(TempR>=Temp1 && TempR>=Temp2){//оба реле замыкаются, если температура датчика соответствует двум условиям, температуры заданные ранее Temp 1 и Temp 2. TempR с термистора
    digitalWrite(Rele1, HIGH); digitalWrite(Rele2, HIGH); //подается сигнал на включение
    }
    else if(TempR>=Temp1 || TempR>=Temp2){//одно реле запускается
    digitalWrite(Rele1, HIGH);
    Millis = millis();
    if(Millis >0 && (millis()-Millis >= interval)){ //interval - время между включения нагрузок
    digitalWrite(Rele1, LOW);
    digitalWrite(Rele2, HIGH);
    Millis = millis();
    }

    }
    Всё это работает пока температура соответствует.
    Так понимаю надо с millis() писать
     
    Последнее редактирование: 2 фев 2015
  2. X-Dron

    X-Dron Гик

    Алгоритм понятен, но реализация крайне не верна.
    Использование в функциях глобальных переменных - не комильфо. На уроках программирования этому отучают на первых занятиях.
    Millis >0 это условие выполняется всегда
    millis()-Millis >= interval, если речь идет о интервале времени час, не будет работать никогда. Так как здесь написано millis()-Millis это интервал между заходами в функцию Rele_Control. Это микро или миллисекунды.
    Возможно, к вечеру напишу пробный, но сразу предупреждаю будут использована эта библиотека.
    http://forum.amperka.ru/threads/Таймеры-и-программный-антидребезг-входов.4280/
    Rele_Control будет классом, а не функцией.
    Какое реле выключать, после того, как оба были включены? По хорошему, если не вести подсчет выработки, то то, которое включилось первым. В этом режиме так же есть тонкости с подсчетом времени.
     
  3. X-Dron

    X-Dron Гик

    У меня получилось вот-что
    Код (Text):
        #include <DI.h>        //подключаем библиотеку DI - обработка дискретного входа из набора библиотек от X-Dron
        #include <Timer_P.h>    //подключаем библиотеку Timer_P - работа с таямерами из набора библиотек от X-Dron

        #define T1_PIN 2
        #define T2_PIN 3
        #define Relay1_PIN 7
        #define Relay2_PIN 8

        class TCtrl
        {
          private:
            boolean Relay1, Relay2, NewCycle, T1_mode_old, RelayKeep;
            long Duration;
            Timer_P Cycle;
          public:
            TCtrl(long Duration);
            void Ctrl(boolean T1, boolean T2);
            boolean GetRelay1();
            boolean GetRelay2();
        };

        // Создание объектов типа "Дистретный вход" они посажены описанные выше пины. Фильтр антидребезга 10мс.
        DI T1(T1_PIN, 10);        
        DI T2(T2_PIN, 10);
        TCtrl MyTCtrl(5000);    //Создаем объект класса TCtrl 5000 - длительность работы реле в режиме переключения в мс. Здесь 5сек

        void setup() {
          //Режимы выходов
          pinMode(Relay1_PIN, OUTPUT);
          pinMode(Relay2_PIN, OUTPUT);
          //делать pinMode для входов не нужно. Они инициализируются при создании объекта класса DI
          //при работе со входами используется INPUT_PULLUP-режим. Значения входов нормализовываются во время обработки класса.
          //замкнутая кнопка - логическая 1.
        }

        void loop() {
          // Обновляем значение дискретных входов
          // Производится их считывание с пинов и фильтрация через внутреннюю переменную класса.
          T1.DI_Refresh();
          T2.DI_Refresh();

          MyTCtrl.Ctrl(T1.DI_Read(), T2.DI_Read());

          digitalWrite(Relay1_PIN, MyTCtrl.GetRelay1());
          digitalWrite(Relay2_PIN, MyTCtrl.GetRelay2());
        }


      TCtrl::TCtrl(long Duration)
      {
        this->Duration = Duration;
      }

      boolean TCtrl::GetRelay1()
      {
        return this->Relay1;
      }

      boolean TCtrl::GetRelay2()
      {
        return this->Relay2;
      }

      void TCtrl::Ctrl(boolean T1, boolean T2)
      {
        if (this->Relay1 and !this->Relay2) this->RelayKeep = true;
        if (this->Relay2 and !this->Relay1) this->RelayKeep = false;
        this->NewCycle = this->Cycle.Timer_P::Timer(!(this->NewCycle) && (this->Relay1 || this->Relay2) && !(this->Relay1 && this->Relay2), 0, 2, this->Duration);

        if (!T1 && !T2)
            {
              this->Relay1 = false;
              this->Relay2 = false;
            }

        if ((T1 && T2) || T2)
            {
              this->Relay1 = true;
              this->Relay2 = true;
            }

        if (T1 && !T2)
            {
              if ((this->NewCycle || ! T1_mode_old) && !this->RelayKeep)
                {
                  this->Relay1 = true;
                  this->Relay2 = false;
                }
              if ((this->NewCycle || ! T1_mode_old) && this->RelayKeep)
                {
                  this->Relay1 = false;
                  this->Relay2 = true;
                }
            }
          T1_mode_old = (T1 && !T2);
        }
    Видео:



    Логика такая (предположим, что работаем на охлаждение):
    Есть 2 температурных датчика. Уровень срабатывания 1-го ниже уровня срабатывания 2-го. Если сработает второй, то и 1-й должен быть сработавшим. Например 1-й 30град, второй 40град.
    Температурные уровни имитирую кнопками.
    Если нет ни одного уровня - оба реле выключены.
    Если есть 1-й уровень, то включается одно реле, если до истечения интервала переключения уровень 1 уйдет, то в следующий раз включится другое реле. Если уровень 1 держится дольше интервала переключения, то реле переключаются.
    Если появится 2-ой уровень, то включится и второе реле. При уходе 2-го уровня отключится то реле, которое было включено первым.
    Применительно к Вашему скетчу MyTCtrl.Ctrl вызывать
    Код (Text):
    MyTCtrl.Ctrl(TempR>=Temp1, TempR>=Temp2)
    Temp2 > Temp1.
    Все что связано с T1 и T2 вне void TCtrl::Ctrl(boolean T1, boolean T2) удалить.
     
    Последнее редактирование: 28 янв 2015
  4. savdm

    savdm Нерд

    Буду разбираться, спасибо за помощь. Планируется что будет все работать от одного терморезистора, и его значения будут сравниваться с заданными, а выполнение условия будет запускать реле. О millis - это счетчик который стартует при запуске МК доходит до опред значения и сбрасывается в ноль. Вот интересует как с ним работать чтобы реле запустилось и пошла проверка на время, одновременно и температуру. Планировал вот так : при запуске реле пишем значение в переменную Millis допустим "Millis()=40000" после этого при каждом круге loop сравниваем выражение с интервалом millis()-Millis >= interval почему не будет работать?
     
    Последнее редактирование: 29 янв 2015
  5. X-Dron

    X-Dron Гик

    Засечка времени с Millis() делается так:
    if (фронт условия начала отсчета) Millis=Millis()+interval;
    if (Millis()>Millis) { действия по истечению времени}

    В первом условии обязательно должен быть фронт события. Если поставить просто событие, то Millis будет каждый раз высчитываться заново и второе условие не сработает никогда.

    Подчищенный скетч без кнопок.
    Код (Text):
        #include <Timer_P.h>    //подключаем библиотеку Timer_P - работа с таямерами из набора библиотек от X-Dron
        #define Relay1_PIN 7
        #define Relay2_PIN 8

        class TCtrl
        {
          private:
            boolean Relay1, Relay2, NewCycle, T1_mode_old, RelayKeep;
            long Duration;
            Timer_P Cycle;
          public:
            TCtrl(long Duration);
            void Ctrl(boolean T1, boolean T2);
            boolean GetRelay1();
            boolean GetRelay2();
        };
       
        TCtrl MyTCtrl(5000);    //Создаем объект класса TCtrl 5000 - длительность работы реле в режиме переключения в мс. Здесь 5сек

        void setup() {
          //Режимы выходов
          pinMode(Relay1_PIN, OUTPUT);
          pinMode(Relay2_PIN, OUTPUT);
        }

        void loop() {
          // Обработка терморезистора, значение на его выходе TempR
          //Temp1, Temp2 уставки срабатывания

          MyTCtrl.Ctrl(TempR>=Temp1, TempR>=Temp2)
         
          digitalWrite(Relay1_PIN, MyTCtrl.GetRelay1());
          digitalWrite(Relay2_PIN, MyTCtrl.GetRelay2());
        }


      TCtrl::TCtrl(long Duration)
      {
        this->Duration = Duration;
      }

      boolean TCtrl::GetRelay1()
      {
        return this->Relay1;
      }

      boolean TCtrl::GetRelay2()
      {
        return this->Relay2;
      }

      void TCtrl::Ctrl(boolean T1, boolean T2)
      {
        if (this->Relay1 and !this->Relay2) this->RelayKeep = true;
        if (this->Relay2 and !this->Relay1) this->RelayKeep = false;
        this->NewCycle = this->Cycle.Timer_P::Timer(!(this->NewCycle) && (this->Relay1 || this->Relay2) && !(this->Relay1 && this->Relay2), 0, 2, this->Duration);

        if (!T1 && !T2)
            {
              this->Relay1 = false;
              this->Relay2 = false;
            }

        if ((T1 && T2) || T2)
            {
              this->Relay1 = true;
              this->Relay2 = true;
            }

        if (T1 && !T2)
            {
              if ((this->NewCycle || ! T1_mode_old) && !this->RelayKeep)
                {
                  this->Relay1 = true;
                  this->Relay2 = false;
                }
              if ((this->NewCycle || ! T1_mode_old) && this->RelayKeep)
                {
                  this->Relay1 = false;
                  this->Relay2 = true;
                }
            }
          T1_mode_old = (T1 && !T2);
        }
     
    savdm нравится это.
  6. savdm

    savdm Нерд

    Для моего восприятия слишком сложно читать этот код:))))))))) Буду разбираться)
     
  7. savdm

    savdm Нерд

    Спасибо, пока разобрался в этих классах и функциях в классе и указаниях this :) всё позабыл совсем :(
     
  8. X-Dron

    X-Dron Гик

    В конце моего скетча лучше подправить
    Код (Text):
        if (T1 && !T2)
            {
              if ((this->NewCycle || !this->T1_mode_old) && !this->RelayKeep)
                {
                  this->Relay1 = true;
                  this->Relay2 = false;
                }
              if ((this->NewCycle || !this->T1_mode_old) && this->RelayKeep)
                {
                  this->Relay1 = false;
                  this->Relay2 = true;
                }
            }
          this->T1_mode_old = (T1 && !T2);
        }
    T1_mode_old тоже должен быть с "this->"
     
  9. savdm

    savdm Нерд

    this-> не совсем пойму:(
    и вот сейчас
    Засечка времени с Millis() делается так:
    if (фронт условия начала отсчета) Millis=Millis()+interval;
    if (Millis()>Millis) { действия по истечению времени}
    Почему с часами не получится? на примере 2х светодиодов
     
  10. savdm

    savdm Нерд

    Код (Text):

    const int ledPin1 =  3;
    const int ledPin2 =  2;

    unsigned long previousMillis = 0;  
    const long interval = 5000;

    void setup() {
      pinMode(ledPin1, OUTPUT);
    pinMode(ledPin2, OUTPUT);
    Serial.begin(9600);
    }
    void loop()
    {
      if((millis()-previousMillis) > interval){
      long delta = interval-millis()+previousMillis;
      previousMillis=delta;
      Serial.println(1);

      }
        else {
              if(previousMillis + interval <= millis()){
              if(digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==LOW){
              digitalWrite(ledPin1,HIGH);
              previousMillis = millis();
              Serial.println(2);
              }
                else if (digitalRead(ledPin1)==HIGH&&digitalRead(ledPin2)==LOW){
                digitalWrite(ledPin1,LOW);
                digitalWrite(ledPin2,HIGH);
                previousMillis = millis();
                Serial.println(3);
                }
                  else {
                        digitalWrite(ledPin1,HIGH);
                        digitalWrite(ledPin2,LOW);
                        previousMillis = millis();
                        Serial.println(4);
                        }
                                                        }
              }
    }
     
    Если установится максимальное значение для миллис и произойдет сброс, будет работать.
     
    Последнее редактирование: 2 фев 2015
  11. savdm

    savdm Нерд

    и вот если разместить Serial.println(millis()) то кроме первого условия ничего не выполняется. из-за чего?:confused: