Включение реле на 1 час без использования RTC

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

  1. Machineman

    Machineman Нуб

    У меня 3 параллельные задачи еще в коде работают с выводом на дисплей.
     
  2. ostrov

    ostrov Гуру

    Три условия на каждую задачу. На время, на кнопку, на что там еще. Для наглядности лучше в виде функций. В лупе список функций и все.
     
  3. Machineman

    Machineman Нуб

    У меня постоянный вывод на дисплей со сменой значений от разных функций, параллельно должен включаться вентилятор по условию на время N. Дилей , равно как и While вешает программу наглухо, значения на дисплее замирают, что в корне не соответствует моим требованиям к устройству.
    В данный момент вентилятор не отключается
    Код целиком
    Код (C++):
    #include <TM1637.h>
    #include <OneWire.h>
    #include "stDHT.h"

    OneWire  ds(10);  // пин 18b20

    #define CLK 3//pins definitions for the module and can be changed to other ports    
    #define DIO 2
    #define pinFoto  A0 //пин подключения фототранзистора

    TM1637 disp(CLK, DIO);
    DHT sens(DHT11); // Указать датчик DHT11, DHT21, DHT22

    unsigned long currentMillis_Vent; // = millis();
    long previousMillis_showFunc = 0;
    long previousMillis_Vent = 0;
    int hydro;          //переменная влажности
    float temp;         //темпреатура
    int foto = 0;       //переменная с фотодатчика
    bool showState = 0; //флаг состояния функций вывода на дисплей
    bool Vent = 0;      //флаг состояния вентилятолра


    void setup() {
      Serial.begin(9600);
      disp.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
      disp.init(D4056A);//D4056A is the type of the module
      pinMode(pinFoto, INPUT);//A0 с фототранзистором на вход
      pinMode(13, OUTPUT);// выход на реле вентилятора
      pinMode(6, INPUT); //пин подключения DHT11
    // digitalWrite(6, HIGH);
      digitalWrite(13, LOW);
      attachInterrupt(0, myFunc, RISING);
    }

    void loop() {
      //Serial.println(h);
      // Serial.println(temp);


      hydro = sens.readHumidity(6);    //запись в h значения с датчика
      temp  = getTemp();
      foto  = analogRead(pinFoto);

    //////////////////////////////////////////////////////////////////////
    //мигаем функциями температуры и влажности раз в 5 секунд.
    unsigned long currentMillis_showFunc = millis();
      if(currentMillis_showFunc - previousMillis_showFunc > 5000){
        previousMillis_showFunc = currentMillis_showFunc;
        if(showState == 0){
          showState = 1;
        }
        else
        showState = 0;    //флаг смены функций через заданное  заданное время
      }

      if(showState == 0){
        displayTermo();
      }

      if(showState == 1){
         displayHydro();
        }
    //////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////
    //работаем с вентилятором
    //if (Vent == 1) digitalWrite(13, HIGH);
    //if (Vent == 0) digitalWrite(13, LOW);


      if(foto > 500 || hydro > 80){
        digitalWrite(13, HIGH);
        Vent = 1;
     
        if(millis() - currentMillis_Vent > 3000){
          digitalWrite(13, LOW);
          Vent = 0;
          }
        }


    }

    void myFunc(){
      Vent = 1;
      currentMillis_Vent = millis();
    }

    ///////////////////////////////////////////////////////////////////////

    /////////////////////////////////////////////////////////////////////
    //функция вывода влажности на 1637
    void displayHydro() {
      disp.display(hydro * 100); //вывод значения влажности
      disp.display(2, {17});
      disp.display(3, {19}); //вывод знака H в 4й разряд
    }
    ///////////////////////////////////////////////////////////////////////



    //////////////////////////////////////////////////////////////////////
    //функция вывода температуры на 1637
    void displayTermo() {
      disp.display(temp); //вывод значения температуры
      disp.display(3, {18}); //вывод знака Цельсия в 4й разряд
    }
    //////////////////////////////////////////////////////////////////////



    float getTemp() {

      byte z;
      byte present = 0;
      byte type_s;
      byte data[12];
      byte addr[8];

      if ( !ds.search(addr)) {
        ds.reset_search();
        delay(250);
        return;
      }

      ds.reset();
      ds.select(addr);
      ds.write(0x44, 1);        // start conversion, with parasite power on at the end

      delay(2000);     // maybe 750ms is enough, maybe not
      // we might do a ds.depower() here, but the reset will take care of it.

      present = ds.reset();
      ds.select(addr);
      ds.write(0xBE);         // Read Scratchpad

      for ( z = 0; z < 9; z++) {           // we need 9 bytes
        data[z] = ds.read();
      }

      int16_t raw = (data[1] << 8) | data[0];

      if (type_s) {
        raw = raw << 3; // 9 bit resolution default
        if (data[7] == 0x10) {
          // "count remain" gives full 12 bit resolution
          raw = (raw & 0xFFF0) + 12 - data[6];
        }
      }

      else {
        byte cfg = (data[4] & 0x60);
        // at lower res, the low bits are undefined, so let's zero them
        if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
        else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
        else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
        //// default is 12 bit resolution, 750 ms conversion time
      }

    float  celsius = (float)raw / 16.0;
      return celsius;
    }
     
  4. ostrov

    ostrov Гуру

    Почему вешает дисплей? Данные отправили не ждем ничего.
     
  5. Machineman

    Machineman Нуб

    Ну если включать вентилятор на 10 минут по срабатыванию фотодатчика или по влажности с помощью delay или While, то 10 минут на дисплее будет последнее значение, а должно меняться каждые 5 секунд не зависимо ни от чего.
     
  6. ostrov

    ostrov Гуру

    Точно так же отправляем по таймеру каждые 5 сек.
     
  7. Machineman

    Machineman Нуб

    и что надо поменять в коде? я никак не соображу.
    Как можно отправлять что то на дисплей, если код стоит в delay?
     
    Последнее редактирование: 29 июл 2017
  8. ostrov

    ostrov Гуру

    Я же выше написал как. А delay выкинуть ото всюду. Список функций в лупе, каждая из которой начинается с проверки условия. Что то по таймеру, что то по событию.
     
  9. Machineman

    Machineman Нуб

    У меня и так список функций в лупе, условия для отображения мне не нужны- функция отображения стартует с подачей питания и никаким боком основной код не задевает. Проблема с включением вентилятора. Я хочу сделать так, чтоб он включался на определенной мной время и выключался и при этом не тормозил программу. Уверен, что это делается при помощи millis() и максимум 5 строк.
     
  10. ostrov

    ostrov Гуру

    Так и есть. Добавьте еще одну функцию с работой по таймеру. Не пойму а чем проблема. С millis() не разобрались?
     
  11. Machineman

    Machineman Нуб

    Дык я о том и говорю, что с миллис не разобрался. Мигать из примера получилось, а задержку делать нет. )
     
  12. Unixon

    Unixon Оракул Модератор

    А чего там разбираться? Запомнили момент времени и в цикле сравниваем разность между текущим значением времени и тем, что запомнили, с некоторой желаемой константой. Если условие выполняется, делаем, что хотели.
     
  13. ostrov

    ostrov Гуру

    Да, а после опять запомнили новое время и так бесконечно.
     
  14. Limoney

    Limoney Гик

    Включение и выключение вентилятора по времени без фотодатчика и влажности
    Код (C++):
    const byte VentPin = 13;
    byte VentState = LOW;
    unsigned long previousMillis = 0;
    const long interval = 60000; // минута
    boolean AlarmON = false; // срабатывание будильника
    byte minalarm; // время отсчета будильника в минутах

    void setup() {
      pinMode(VentPin, OUTPUT);
      minalarm = 1;
    }

    void loop() {
      static byte mincount;
      unsigned long currentMillis = millis();
      if ((currentMillis - previousMillis >= interval) && (AlarmON == false)) {
        mincount++;
        if (mincount >= minalarm) {
          mincount = 0;
          AlarmON = true; // будильник сработал
        }
        previousMillis = currentMillis;
      }

      // если будильник сработал
      if (AlarmON == true) {
        if (VentState == LOW) {
          VentState = HIGH;
          minalarm = 2;  // время работы вентилятора в минутах
        } else {
          VentState = LOW;
          minalarm = 1;  // время выключенного вентилятора в минутах
        }
        digitalWrite(VentPin, VentState);
        AlarmON = false; // включаем будильник для нового отсчета
      }

      // Другие полезные нужные функции

    }
    Кстати, в функции измерения температуры пауза на 2 сек, хотя для данной задачи не критично
     
    Последнее редактирование: 29 июл 2017
  15. Machineman

    Machineman Нуб

    Уфф.. Мозг сломал уже.. Написал примитивный пример.
    Короче получилось делать задержку по переднему фронту от кнопки, а теперь надо по заднему, т.е. после отпускания. Вроде просто все, а голова не соображает. Подскажите нубу пожалуйста)

    Код (C++):

    const int interval = 5000;  // задержка;
    long LastTime = 0;  //  время последнего запуска;
    bool button = 0; // кнопка
    bool ledState;  // состояние LED

    void setup () {
        pinMode(7, INPUT);
        pinMode(13, OUTPUT);
        digitalWrite(13, LOW);
    }
     
    void loop () {
       button =  digitalRead (7);
       digitalWrite(13, ledState);
     
        if(button == true){
           ledState = 1;        
         }

       if(button == false){
            // LastTime = millis();    
         if (millis() - LastTime > interval) {  // проверяем, прошел ли интервал с момента последнего выполнения условия;
            LastTime = millis();  // переприсваиваем в LastTime время текущего запуска;
             ledState = 0;
           }
         }
       }
     
  16. ostrov

    ostrov Гуру

    Так же, только ждать не 01, а 10, или наоборот, смотря куда давит кнопка.
     
  17. Machineman

    Machineman Нуб

    ВСЕ! разобрался! Засекать время надо было не при отпущенной кнопке а при нажатой, тогда последняя запись в LastTime произойдет в момент отпускания и условие с задержкой выполнится именно после отпускания. Ура! Радуюсь , как когда на двухколесном велосипеде первый раз поехал! :D
    Код (C++):
    if(button == true){
           ledState = 1;
           LastTime = millis();    
         }
    /*Задержка времени с отсчетом времени при отпускании кнопки*/
    Код (C++):
    const int interval = 5000;  // задержка в миллисекундах
    long LastTime = 0;  //  время последнего запуска;
    bool button = 0; // кнопка
    bool ledState;  // состояние LED

    void setup () {
        pinMode(7, INPUT);
        pinMode(13, OUTPUT);
        digitalWrite(13, LOW);
    }
     
    void loop () {
       button =  digitalRead (7);
       digitalWrite(13, ledState);
        if(button == true){     //если кнопка нажата
           ledState = 1;        //зажигаем светодиод
           LastTime = millis(); // записываем время отпускания кнопки ( потому что при удержании переменная постоянно переписывается)      
         }

       if(button == false){     //если кнопка отпущена
         if (millis() - LastTime > interval) {  //обнуляем счетчик и сравниваем со значением задержки
             ledState = 0;      // выключаем светодиод
           }
         }
    }
     
    Последнее редактирование: 31 июл 2017
  18. ostrov

    ostrov Гуру

    А еще есть одноколесный велосипед!
     
  19. qwone

    qwone Гик

    Какие велосипеды. Сейчас рулят АВТОМОБИЛИ
    Код (C++):
    /*
    */

    uint32_t mill;
    //----------- Cl_Led------------------------------------
    // класс светодиод
    class Cl_Led {
        const byte pin;
        const bool inv;
        bool led;
        byte stat; // 0 выкл / 1 вкл / 2 ждет откл
        uint32_t time;
        uint32_t past = 0;
      public:
        Cl_Led(byte _pin, bool _inv)
          : pin(_pin), inv(_inv) {}
        void setup() {
          pinMode(pin, OUTPUT);
          OFF();
        }
        void ON() {
          stat = led = 1;
          digitalWrite(pin, led ^ inv);
        }
        void ON(uint32_t _time) {
          time = _time;
          ON();
          stat = 2;
          past = mill;
        }
        void OFF() {
          stat = led = 0;
          digitalWrite(pin, led ^ inv);
        }
        void loop() {
          if (stat == 2 && mill - past >= time) {
            OFF();
          }
        }
    };
    //-------Cl_Btn----------------------------------------
    // класс кнопка
    class Cl_Btn {
        const byte pin;
        bool btn, btn_old;
        void (*Do)();
        uint32_t time;
        uint32_t past;
      public:
        Cl_Btn(byte _pin, void (*_Do)())
          : pin(_pin), Do(_Do) {}
        void setup() {
          pinMode(pin, INPUT);
          btn_old = digitalRead(pin);
        }
        void loop() {
          btn = digitalRead(pin);
          if (btn && !btn_old) {
            btn_old = 1;
            (*Do)();
          }
          if (!btn && btn_old) {
            btn_old = 0;
          }
        }
    };
    //---------------компоновка-----------------------------
    Cl_Led Led(/*пин*/13,/*инверсия*/0);
    const int time_1hour = 3600000;
    void Do_Btn() {
      Led.ON(time_1hour);
    }
    Cl_Btn Btn(/*пин*/2,/*обработчик*/ Do_Btn);
    //---------------main()--------------------------------
    void setup() {
      Led.setup();
      Btn.setup();
    }

    void loop() {
      mill = millis();
      Led.loop();
      Btn.loop();
    }
    /*Скетч использует 1302 байт (4%) памяти устройства. Всего доступно 32256 байт.
    Глобальные переменные используют 38 байт (1%) динамической памяти, оставляя 2010 байт для локальных переменных. Максимум: 2048 байт.
    */
     
  20. ostrov

    ostrov Гуру

    Зачем велосипеду колеса от КАМАЗа?