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

Тема в разделе "Arduino & Shields", создана пользователем АлексейЭтоЯ, 30 окт 2017.

  1. Про millis написано много, НО.... помигать и помигать, а мне нужно такой алгоритм. Нажал на кнопку запустился таймер скажем на 5 минут, потом, в идеале тон на 5 - 10сек, или хотя бы мигание светодиода.
    И самое главное никаких Delay, тут 3 потока c #include <Thread.h> и только Я пытаюсь в цикле извлечь звук, естественно с завершением его по времени, всё виснет. Если кто может, помогите. Только ссылки на millis с миганием по кругу не кидайте Я это уже перечитал, это не то.
    Пытался ставить 2й таймер за этим, по отработке outtimerPin, но 2й таймер после отработки повторяет всё периодически, а мне надо разовая отработка, до следующего нажатия на кнопку. Спасибо всем заранее.

    Код (C++):
    //**************************************************************************
    // Таймер //
    boolean flagFirstKeyPressed = 0;
    unsigned long momentKeyPressed = 2^32 - 1; // максимальное значение счетчика
    unsigned long previousMillis = 0;
    //**************************************************************************
    -
    /////////////////  Таймер  //////////////////// // Поток 3
    void timer_() {

     /////////////////  Таймер  ////////////////////
      // если кнопка нажата впервые
      if((digitalRead(key5Pin) == HIGH) && !flagFirstKeyPressed) {
      flagFirstKeyPressed = 1; // устанавливаем флаг при первом нажатии  
      momentKeyPressed = millis(); // запоминаем момент времени
      digitalWrite(outtimerPin, HIGH); // включаем светодиод  
      }
       // если прошло время
      if (millis() - momentKeyPressed >= 60000) {  ///////// 1 мин //////////
      flagFirstKeyPressed = 0; // сбрасываем флаг
      momentKeyPressed = 2^32 - 1; // устанавливаем максимальное значение
      digitalWrite(outtimerPin, LOW); // выключаем светодиод        
     }
    }
     // Поток 2
    void pir_() {
    //***************key1**************************//
    if(digitalRead(key1Pin)==HIGH&&key1==0)            
    {
    delay(250);//защита от дребезга      
    key1++;                                        
    digitalWrite(outpirPin, !digitalRead(outpirPin));            
    }
    if(digitalRead(key1Pin)==LOW&&key1==1)              
    {
    key1=0;    

     
     
    Последнее редактирование: 30 окт 2017
  2. ostrov

    ostrov Гуру

    То есть как работать с millis() вы не разобрались, но вам это точно не понравилось.
     
  3. Как происходит задержка Я понял, но как сделать 2е подряд с разовой отработкой, и с тоном в придачу и всё без Delay
    .... Нет
     
  4. rkit

    rkit Гуру

    Три раза перечитал код, который нельзя написать без delay, но так и не нашел delay.
     
  5. Так там их сейчас нигде и нет, но и таймера какого хочу - тоже нет ))) Но всё работает в таком виде отлично.
     
  6. Вот нашел отрывок, как его привязать к условию таймера, который сверху поста?
    Код (C++):
    //void sound() {
    //    static int ton = 300;  // тональность звука, Гц
    //    tone(soundPin, ton);  // включаем сирену на "ton" Гц
    //    if (ton <= 900) {  // до частоты 900 Гц
    //        ton += 20;  // увеличиваем тональность сирены
    //    }
    //    else {  // по достижении 500 Гц
    //        ton = 300;  // сбрасываем тональность до 300 Гц
    //    }
    //}
    И что б он работал не вечно, а 5 - 10 сек, то следующего вызова кнопки
     
  7. akl

    akl Гуру

    чтобы писк работал не вечно, его надо в нужное время выключить функцией noTone(pin)
     
  8. Если перед этим не будет паузы, то писка вообще не будет, если по коду выше, как эту паузу выполнить через Millis на примере
     
  9. akl

    akl Гуру

    при включении писка запомнить текущее значение миллис (именно один раз только в момент начала пищания), затем при выполнении условия что писк включен и с момента запоминания миллисов прошло нужное время - выключить писк.
     
    Tomasina нравится это.
  10. Я был бы благодарен у видеть как это практически
    Можете написать как, а Я результат оповещу
     
  11. Пока на светодиодах, с тоном всё сложнее. В этом варианте лэд8 сразу мигает, при нажатии кнопки 1й таймер работает лэд8 тухнет на указанное время и опять мигает.

    Код (C++):

    /////////////////  Таймер  ////////////////////
      // если кнопка нажата впервые
      if((digitalRead(key5Pin) == HIGH) && !flag) {
      flag = 1; // устанавливаем флаг при первом нажатии
      moment = millis(); // запоминаем момент времени
      digitalWrite(outtimerPin, HIGH); // включаем светодиод
      }
       // если прошло время
      if (millis() - moment >= 10000) {
      flag = 0; // сбрасываем флаг
      moment = 2^32 - 1; // устанавливаем максимальное значение
      digitalWrite(outtimerPin, LOW); // выключаем светодиод        
    }
    if((digitalRead(outtimerPin) == LOW) && !flag2) {
      flag2 = 1; // устанавливаем флаг при первом нажатии
      moment2 = millis(); // запоминаем момент времени
      digitalWrite(LED8, HIGH); // включаем светодиод
      }
       // если прошло время
      if (millis() - moment2 >= 2000) {
      flag2 = 0; // сбрасываем флаг
      moment2 = 2^32 - 1; // устанавливаем максимальное значение
      digitalWrite(LED8, LOW); // выключаем светодиод        
    }
    }
     
  12. qwone

    qwone Гик

    могу предложить писать через класс менеджер, если разберетесь как работать.
    Код (C++):
    unsigned long mill; // переменная под millis()
    //-----Cl_Manager---------------------------
    // класс менеджер задач
    struct task_t {
      void (*Do)();
      unsigned long past;
      unsigned int time;
      struct task_t (*next);
      task_t(void (*_Do)(), unsigned long _past, unsigned int _time, struct task_t (*_next))
        : Do(_Do), past(_past), time(_time), next(_next) {}
    };
    class Cl_Manager {
      protected:
        struct task_t (*start) = NULL;
      public:
        /*вствить в loop() программы*/
        void run() {
          struct task_t (*_new);
          for (struct task_t (**i) = &start; (*i) != NULL; ) {
            _new = (*i);
            if (mill - (*_new).past >= (*_new).time) {
              (*i) = (**i).next;
              (*_new).Do();
              delete _new;
            }
            else i = &(**i).next;
          }
        }
        /*загрузить новую задачу*/
        void Task(unsigned int time, void (*Do)()) {
          struct task_t (*_new) = new struct task_t(Do, mill, time, start);
          start = _new;
        }
    };
    Cl_Manager Manager;
    //---Компоновка-----------------------
    // --serial
    void serial_1() {
      Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_2);
      Serial.println("1-one");
    }
    void serial_2() {
      Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_3);
      Serial.println("2-two");
    }
    void serial_3() {
      Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_4);
      Serial.println("3-three");
    }
    void serial_4() {
      Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_5);
      Serial.println("4-four");
    }
    void serial_5() {
      Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_1);
      Serial.println("5-five");
    }
    //---main-----------------------------
    void setup() {
      Serial.begin(9600);
      serial_1();
    }

    void loop() {
      mill = millis();
      Manager.run();
    }
    /*Скетч использует 2400 байт (7%) памяти устройства. Всего доступно 30720 байт.
      Глобальные переменные используют 236 байт (11%) динамической памяти, оставляя 1812 байт для локальных переменных. Максимум: 2048 байт.
    */
     
    ИгорьК нравится это.
  13. qwone

    qwone Гик

    ПС:Вот Blink на менеджере
    Код (C++):
    unsigned long mill; // переменная под millis()
    //-----Cl_Manager---------------------------
    // класс менеджер задач
    struct task_t {
      void (*Do)();
      unsigned long past;
      unsigned int time;
      struct task_t (*next);
      task_t(void (*_Do)(), unsigned long _past, unsigned int _time, struct task_t (*_next))
        : Do(_Do), past(_past), time(_time), next(_next) {}
    };
    class Cl_Manager {
      protected:
        struct task_t (*start) = NULL;
      public:
        /*вствить в loop() программы*/
        void run() {
          struct task_t (*_new);
          for (struct task_t (**i) = &start; (*i) != NULL; ) {
            _new = (*i);
            if (mill - (*_new).past >= (*_new).time) {
              (*i) = (**i).next;
              (*_new).Do();
              delete _new;
            }
            else i = &(**i).next;
          }
        }
        /*загрузить новую задачу*/
        void Task(unsigned int time, void (*Do)()) {
          struct task_t (*_new) = new struct task_t(Do, mill, time, start);
          start = _new;
        }
    };
    Cl_Manager Manager;
    //---Компоновка-----------------------
    // blink через менеджер
    const byte ledPin =/*пин*/13;
    bool led = 0;
    void ledInit() {
      pinMode(ledPin, OUTPUT);
      ledRun();
    }
    void ledRun() {
      Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&ledRun);
      digitalWrite(ledPin, led = !led);
    }
    //---main-----------------------------
    void setup() {
      ledInit();
    }

    void loop() {
      mill = millis();
      Manager.run();
    }
    /*Скетч использует 1580 байт (5%) памяти устройства. Всего доступно 30720 байт.
      Глобальные переменные используют 26 байт (1%) динамической памяти, оставляя 2022 байт для локальных переменных. Максимум: 2048 байт.
    */
     
    ИгорьК нравится это.
  14. Не думаю, что мне это сейчас по силам, у меня ардуино 2 месяца ))) только как
     
  15. qwone

    qwone Гик

    А вы не боитесь подключать библиотеки. Вот считайте, что вы так подключаете библиотеку. вот только вместо #include пишете это. (все что до компоновки и loop b setup). ПС: Надо будет где-то написать тему - написание программ, через менеджер. Там можно и кнопки задействовать и псевдопаралельнось. И главное - "доминошное программирование"-
     
    ИгорьК нравится это.
  16. akl

    akl Гуру

    только желательно с подробными объяснениями, и на ЧистомСИ™
     
  17. b707

    b707 Гуру

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

    И не надо просить "примеров" - для внимательного взгляда их в инете тыщи. а для невнимательного везде пусто и темно.
     
  18. Тыщи чего мигания светодиодом по кругу..... Вместо слов ни о чём, хотя бы от Вас ссылка в студию на тон с милисом, с разовым вызовом. Мне готовый код лично от Вас не надо, и тем более с такими заездами. И в отличие от, qvone, который и не такие коды людя за так пишет, а тут простейший таймер, просто ля ля ни о чём
     
    Последнее редактирование: 31 окт 2017
  19. b707

    b707 Гуру

    ну-ну, попытайтесь переварить код QWONE. Как осилите - и миллис поймете :)
     
  20. B707 :eek: вот мне интересен такой тип людей, нахватались вершков начальных больше чем другие и умных корчите из себя, конструктива ноль. Да Я вообще начинаю сомневаться и ваших познаниях, ибо просто бла бла бла. Только вот Я сюда зашёл с проблемой, а такие как вы зачем?, займитесь полезным чем нибудь. Без обид. Удачи.