Установить длительность включенного состояния выхода

Тема в разделе "Arduino & Shields", создана пользователем MESS, 12 янв 2016.

  1. lerik2703

    lerik2703 Гик

    Код (C++):
    #include <OneWire.h>
    OneWire ds(8);

    #define OPEN_WINDOWS 1  // что означает цифра? для switch (arg)?
    #define CLOSE_WINOWS 2
    #define STOP_ENGINE  3
    #define MOTOR_PIN_ON 13 // выход для команды на открытие форточки
    #define MOTOR_PIN_OFF 10 // на закрытие форточки
    #define SECOND 1000
    bool WindowsPosition = false; //виртуальный концевик  так как у нас нет реального положения форточки(по умолчанию форточка закрыта)
    int  SetTimeRunMotor;//время в секундах делаем её видимой в пределах нашего скетча


    void setup() {

      pinMode(MOTOR_PIN_ON, OUTPUT); // назначение пина
      pinMode(MOTOR_PIN_OFF, OUTPUT);
      Serial.begin(9600);
    }
    //--================================================================================================================================--
    void loop() {

      float temperature = SensorGetTemperature ();//упаковываем в функцию должно работать)

      Serial.println(temperature);//смотрите пока температуру через терминал

      bool RunMotor = digitalRead(MOTOR_PIN_OFF) or digitalRead(MOTOR_PIN_ON);//проверяем работает ли у нас мотор

      if (!RunMotor) { //запрещаем переключение мотора до окончании его работы

        if (temperature >= 26.0 and !WindowsPosition)       //условие для OPEN_WINDOWS
        {
          WindowsPosition = true;//считаем что форточка открылась
          SetTimeRunMotor = 15; //установили желаемое время работы мотора
          EngineControl (OPEN_WINDOWS);  //открыть!



        }
        else if (temperature <= 24.0 and WindowsPosition)   // условие  для CLOSE_WINOWS
        {
          WindowsPosition = false;//считаем что форточка закрылась
          SetTimeRunMotor = 25;
          EngineControl (CLOSE_WINOWS);   // закрыть!


        }

      }


      if (RunMotor)//если мотор работает запускаем таймер. погрешность таймера напрямую связанно с время затратами на выполнение других задач ,
        RunMotorTime();      //  для уменьшения погрешности можно вызывать функцию из разных мест в пределах loop
      //и ещё подводный камень это переполнение счетчика приблизительно через 50 дней (функция  millis())
    }
    //--==================================================================================================--

    //   это альтернативный код, проверяет три объявленных case (строки 5,6и 7). Чувствую, что  правильно понял
    void EngineControl (byte arg) {  //  что за переменная  arg ( не та ли это цифра в строке 5)   как сказать?

      switch (arg) {      //оператор вычисляет (или проверяет?) переменную arg для  первого кейса OPEN_WINDOWS ?
        case OPEN_WINDOWS:  // первый кейс
          if (!digitalRead(MOTOR_PIN_OFF))//
            digitalWrite(MOTOR_PIN_ON, HIGH);
          break;  // команда выхода из оператора switch, если не та ццифра

        case CLOSE_WINOWS: //второй кейс
          if (!digitalRead(MOTOR_PIN_ON))
            digitalWrite(MOTOR_PIN_OFF, HIGH);
          break;

        case STOP_ENGINE:  // третий кейс
          digitalWrite(MOTOR_PIN_ON, LOW);
          digitalWrite(MOTOR_PIN_OFF, LOW);
          break;
      }
    }

    //--==================================================================================================--

    void RunMotorTime() {  // просьба, если можно,  пояснить эти строки  ниже


      static unsigned long lastTime; //локальные переменные видны только в этой функции
      static bool first_once;
      static int sec ;

      if (!first_once) {// это первый вызов или функция начинает отсчет времени
        first_once = true;
        lastTime = millis();//сохранили текущее время
      }

      if ((millis() - lastTime) >= SECOND ) {//ждем когда пойдет секунда
           ++sec;
       if (SetTimeRunMotor == sec) {
          sec = 0;
          first_once = false;
          EngineControl (STOP_ENGINE);
        }
        lastTime = millis();
      }
    }

    //--==================================================================================================--

    float SensorGetTemperature () {

      static byte addr[8];
      if ( !ds.search(addr)) {
        ds.reset_search();
      }
      ds.reset();
      ds.select(addr);
      ds.write(0x44);
      ds.reset(); //
      ds.select(addr);
      ds.write(0xBE);
      return (ds.read() | (ds.read() << 8)) / 16.0 ;
    }
     
    вот ещё вариант с изменением времени работы привода
     
    MESS нравится это.
  2. MESS

    MESS Гик

    Уважаемый lerik2703 !
    Наконец то выбрался из цейтнота и подготовил натурные испытания. Собрал девайс на пайке и разьемах для надежности, подключил двигатель. Все работает согласно алгоритму, никаких помех в течении суток не возникало. Температуру менял открытием окна- датчик был на подоконнике.
    Самый последний Ваш вариант с изменением времени работы привода, пока не заработал. Не выключает открытие вовсе. Не смог поправить. Еще раз большое Вам спасибо за терпение и помощь!
     
  3. lerik2703

    lerik2703 Гик

    обкатка вещь нужная)
    по первому скетчу? с библиотекой экрана?
    странно,диодик у меня выключался попробуйте вот этот посмотрите в терминале переменную sec
    кстати здесь решён вопрос с "миллениум"
    Код (C++):

    #include <OneWire.h>
    OneWire ds(8);

    #define OPEN_WINDOWS 1  // что означает цифра? для switch (arg)?
    #define CLOSE_WINOWS 2
    #define STOP_ENGINE  3
    #define MOTOR_PIN_ON 13 // выход для команды на открытие форточки
    #define MOTOR_PIN_OFF 10 // на закрытие форточки
    #define SECOND 1000
    bool WindowsPosition = false; //виртуальный концевик  так как у нас нет реального положения форточки(по умолчанию форточка закрыта)
    int  SetTimeRunMotor;//время в секундах делаем её видимой в пределах нашего скетча


    void setup() {
     
      pinMode(MOTOR_PIN_ON, OUTPUT); // назначение пина
      pinMode(MOTOR_PIN_OFF, OUTPUT);
      Serial.begin(9600);
    }
    //--================================================================================================================================--
    void loop() {

      float temperature =  SensorGetTemperature();//упаковываем в функцию должно работать)

      Serial.println(temperature);//смотрите пока температуру через терминал

      bool RunMotor = digitalRead(MOTOR_PIN_OFF) or digitalRead(MOTOR_PIN_ON);//проверяем работает ли у нас мотор

      if (!RunMotor) { //запрещаем переключение мотора до окончании его работы

        if (temperature >= 26.0 and !WindowsPosition)       //условие для OPEN_WINDOWS
        {
          WindowsPosition = true;//считаем что форточка открылась
          SetTimeRunMotor = 15; //установили желаемое время работы мотора
          EngineControl (OPEN_WINDOWS);  //открыть!
           Serial.println("OPEN_WINDOWS");


        }
        else if (temperature <= 24.0 and WindowsPosition)   // условие  для CLOSE_WINOWS
        {
          WindowsPosition = false;//считаем что форточка закрылась
          SetTimeRunMotor = 25;
          EngineControl (CLOSE_WINOWS);   // закрыть!
           Serial.println("CLOSE_WINOWS");

        }

      }


      if (RunMotor)//если мотор работает запускаем таймер. погрешность таймера напрямую связанно с время затратами на выполнение других задач ,
        RunMotorTime();      //  для уменьшения погрешности можно вызывать функцию из разных мест в пределах loop
    }
    //--==================================================================================================--

    //   это альтернативный код, проверяет три объявленных case (строки 5,6и 7). Чувствую, что  правильно понял
    void EngineControl (byte arg) {  //  что за переменная  arg ( не та ли это цифра в строке 5)   как сказать?

      switch (arg) {      //оператор вычисляет (или проверяет?) переменную arg для  первого кейса OPEN_WINDOWS ?
        case OPEN_WINDOWS:  // первый кейс
          if (!digitalRead(MOTOR_PIN_OFF))//
            digitalWrite(MOTOR_PIN_ON, HIGH);
          break;  // команда выхода из оператора switch, если не та ццифра

        case CLOSE_WINOWS: //второй кейс
          if (!digitalRead(MOTOR_PIN_ON))
            digitalWrite(MOTOR_PIN_OFF, HIGH);
          break;

        case STOP_ENGINE:  // третий кейс
          digitalWrite(MOTOR_PIN_ON, LOW);
          digitalWrite(MOTOR_PIN_OFF, LOW);
          Serial.println("STOP_ENGINE");
          break;
      }
    }

    //--==================================================================================================--

    void RunMotorTime() {  // просьба, если можно,  пояснить эти строки  ниже

     
      static unsigned long lastTime; //локальные переменные видны только в этой функции
      static bool first_once;
      static int sec ;

      if (!first_once) {// это первый вызов или функция начинает отсчет времени
        first_once = true;
        lastTime = millis()+SECOND;//сохранили текущее время
      }

      if ((long)(millis()-lastTime)>=0) {//ждем когда пойдет секунда
          Serial.print("sec => ");
          Serial.println(sec);
           ++sec;
       if (SetTimeRunMotor <= sec) {
          sec = 0;
          first_once = false;
          EngineControl (STOP_ENGINE);
        }
        lastTime +=SECOND;
      }
    }

    //--==================================================================================================--

    float SensorGetTemperature () {

      static byte addr[8];
      if ( !ds.search(addr)) {
        ds.reset_search();
      }
      ds.reset();
      ds.select(addr);
      ds.write(0x44);
      ds.reset(); //
      ds.select(addr);
      ds.write(0xBE);
      return (ds.read() | (ds.read() << 8)) / 16.0 ;
    }
     
  4. MESS

    MESS Гик

    Я не обращал внимание на подсчет времени. оказалось, что все таки интервал открыть -закрыть есть, но не 30сек, а 6минут. Я не дожидался отключения команды. теперь, отключив привод я понял что счет секунд неверен. Если ставлю 15000 (как 15 сек), то выдержка более минуты. продолжаю поиск правды. Последний Ваш скетч секунды показывает на мониторе, но пока не выполняет условия. ищу свой косяк
     
    Последнее редактирование: 29 янв 2016
  5. MESS

    MESS Гик

    Кажется все ок! Поменял порты и склеил Ваши скетчи. Мои трудности заключаются в том, что я не понимаю параметров времени. Благодаря отсчету сек на экране, увидел точное время отсчета.
    Не понимаю в чем различие lastTime = millis()+SECOND; и lastTime = millis(); и то и другое непрерывные отсчеты? переменные SECOND и sec?
    Код (C++):
     
    #include <OneWire.h>
    OneWire ds(8);
    #define OPEN_WINDOWS 1  // что означает цифра? для switch (arg)?
    #define CLOSE_WINOWS 2
    #define STOP_ENGINE  3
    #define MOTOR_PIN_ON 12 // выход для команды на открытие форточки
    #define MOTOR_PIN_OFF 11 // на закрытие форточки
    #define SECOND 1500
    bool WindowsPosition = false; //виртуальный концевик  так как у нас нет реального положения форточки(по умолчанию форточка закрыта)
    int  SetTimeRunMotor;//время в секундах делаем её видимой в пределах нашего скетча


    void setup() {

      pinMode(MOTOR_PIN_ON, OUTPUT); // назначение пина
      pinMode(MOTOR_PIN_OFF, OUTPUT);
      Serial.begin(9600);
    }
    //--================================================================================================================================--
    void loop() {

      float temperature = SensorGetTemperature ();//упаковываем в функцию должно работать)

      Serial.println(temperature);//смотрите пока температуру через терминал

      bool RunMotor = digitalRead(MOTOR_PIN_OFF) or digitalRead(MOTOR_PIN_ON);//проверяем работает ли у нас мотор

      if (!RunMotor) { //запрещаем переключение мотора до окончании его работы

        if (temperature >= 26.0 and !WindowsPosition)       //условие для OPEN_WINDOWS
        {
          WindowsPosition = true;//считаем что форточка открылась
          SetTimeRunMotor = 15; //установили желаемое время работы мотора
          EngineControl (OPEN_WINDOWS);  //открыть!



        }
        else if (temperature <= 23.0 and WindowsPosition)   // условие  для CLOSE_WINOWS
        {
          WindowsPosition = false;//считаем что форточка закрылась
          SetTimeRunMotor = 25;
          EngineControl (CLOSE_WINOWS);   // закрыть!


        }

      }


      if (RunMotor)//если мотор работает запускаем таймер. погрешность таймера напрямую связанно с время затратами на выполнение других задач ,
        RunMotorTime();      //  для уменьшения погрешности можно вызывать функцию из разных мест в пределах loop
      //и ещё подводный камень это переполнение счетчика приблизительно через 50 дней (функция  millis())
    }
    //--==================================================================================================--

    //   это альтернативный код, проверяет три объявленных case (строки 5,6и 7). Чувствую, что  правильно понял
    void EngineControl (byte arg) {  //  что за переменная  arg ( не та ли это цифра в строке 5)   как сказать?

      switch (arg) {      //оператор вычисляет (или проверяет?) переменную arg для  первого кейса OPEN_WINDOWS ?
        case OPEN_WINDOWS:  // первый кейс
          if (!digitalRead(MOTOR_PIN_OFF))//
            digitalWrite(MOTOR_PIN_ON, HIGH);
          break;  // команда выхода из оператора switch, если не та ццифра

        case CLOSE_WINOWS: //второй кейс
          if (!digitalRead(MOTOR_PIN_ON))
            digitalWrite(MOTOR_PIN_OFF, HIGH);
          break;

        case STOP_ENGINE:  // третий кейс
          digitalWrite(MOTOR_PIN_ON, LOW);
          digitalWrite(MOTOR_PIN_OFF, LOW);
          break;
      }
    }

    //--==================================================================================================--

    void RunMotorTime() {  // просьба, если можно,  пояснить эти строки  ниже


      static unsigned long lastTime; //локальные переменные видны только в этой функции
      static bool first_once;
      static int sec ;

      if (!first_once) {// это первый вызов или функция начинает отсчет времени
        first_once = true;
        lastTime = millis()+SECOND;//сохранили текущее время
        //lastTime = millis();//сохранили текущее время old
      }
    if ((long)(millis()-lastTime)>=0) {//ждем когда пойдет секунда
          Serial.print("sec => ");
          Serial.println(sec);
           ++sec;
       if (SetTimeRunMotor <= sec) {
          sec = 0;
          first_once = false;
          EngineControl (STOP_ENGINE);
          }
        lastTime +=SECOND;    
      }
    }

    //--==================================================================================================--

    float SensorGetTemperature () {

      static byte addr[8];
      if ( !ds.search(addr)) {
        ds.reset_search();
      }
      ds.reset();
      ds.select(addr);
      ds.write(0x44);
      ds.reset(); //
      ds.select(addr);
      ds.write(0xBE);
      return (ds.read() | (ds.read() << 8)) / 16.0 ;
    }
     
     
  6. MESS

    MESS Гик

    Дисплей не мешает работе. 20160129_202515.jpg Здорово, что Вы подсказали печатать время отсчета. значит можно автоматически устанавливать значение переменной "сек", для пропорционального открытия форточки, в зависимости от разности температур внутри - снаружи? Это будущая задача.
     
    Последнее редактирование: 29 янв 2016
    lerik2703 нравится это.
  7. lerik2703

    lerik2703 Гик

    давайте по порядку : SECOND не переменная это скорей литера ,правильнее наверно "звучало" бы milliseconds_at_second (миллисекунд в секунде) поэтому это больше информация для человека чем для компилятора (видимо я вас этим столку сбил,так как в прошлом скетче мы как раз для изменения времени меняли MINUTE, но это чтоб не ждать минуту) если бы написали так lastTime = millis()+1000 было бы одно и тоже,поэтому менять её не надо,а управляем временем только SetTimeRunMotor (SetTimeRunMotor <= sec здесь мы её сравниваем со временем с момента запуска функции(таймера)) , в секундах мин 1 секунда ! ,sec это рабочая переменная функции RunMotorTime() она только сохраняет время с момента запуска функции по совпадению обнуляется (при следующем вызове процесс повторяется )!
    выполняют они одну и туже функцию , в первом варианте решаться проблема с переполнением переменной (приблизительно через 50 дней и там уже как повезет)
    в каком то сообщении вы по % открытия уже писали,вот я и добавил в код время открытия (правда придеться переписать весь алгоритм откр-закр )
     
    MESS нравится это.
  8. lerik2703

    lerik2703 Гик

    а вы не используете 10 и 13?
     
  9. MESS

    MESS Гик

    Я раньше думал только об ограничении времени работы самодельного актуатора, чтобы была доп. защита от несрабатывания концевиков. Было такое. Но сейчас прикуплю фирменный актуатор от тарелки спутн.
    Спасибо за учебу! Буду пробовать пропорциональное открытие, но после монтажа девайса на парнике. Сейчас новую цель ставлю.
     
  10. MESS

    MESS Гик

    Чтобы исключить непонятки, я сменил порты на 11 и 12. К тому же плоский шлейф использовал для пайки. Удобнее так.
     
  11. lerik2703

    lerik2703 Гик

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

    MESS Гик

    Сие мне точно непонятно. Инстинктивно чувствую что разберусь. Пока не сталкивался.
     
  13. lerik2703

    lerik2703 Гик