Работа с таймером

Тема в разделе "Arduino & Shields", создана пользователем vasilp, 2 апр 2014.

  1. vasilp

    vasilp Нерд

    Здраствуете! Уважаемые участники форума. В работе с проэктом возникла необходимость разобраться как работать с таймером. Только прошу не пинайте ссылками на короткие примеры которых куча прочитаны, там мне не все понятно а что понятно того нет для понимания этого примера.
    Вопрос вот в чем, к примеру есть три светодиода красный синий и зеленый
    #define Red_DiodPIN 6
    #define Blue_DiodPIN 7
    #define Green_DiodPIN 8
    #define PIN_Button 5

    Для управления их работой задается кучка параметров каждый параметр будет регулироваться в меню

    //пауза между включением светодиодов
    unsigned long next_red = 200;
    unsigned long next_blue = 150;
    unsigned long next_green = 300;

    // время свечения светодиодов
    unsigned long ligth_time_red = 500;
    unsigned long ligth_time_blue = 700;
    unsigned long ligth_time_green = 800;

    свечение должно быть пульсирующим с регулировкой количества импульсов

    // количество импульсов
    unsigned long Pulse_red = 3; // будет регулироваться от 1 до 5
    unsigned long Pulse_blue = 1;
    unsigned long Pulse_green = 4;

    так же присутствует интервал между импульсами

    //интервал пульсаций
    unsigned long Pulse_time_red = 50; // задержка между импульсов
    unsigned long Pulse_time_blue = 60;
    unsigned long Pulse_time_green = 80;

    Нажали на кнопку пауза (next_red) загорелся красный светодиод на заданное время (ligth_time_red), погас совсем если количество (Pulse_red) импульсов равно 0, или погас на время (Pulse_time_red). Повторил работу на установленое (Pulse_red) количество раз. Прошло время паузы (next_blue) в работу вступает синий светодиод. Загорелся на на заданное время (ligth_time_blue), погас совсем если количество (Pulse_blue) импульсов равно 0, или погас на время (Pulse_time_blue) Повторил работу на установленное (Pulse_blue) количество раз. Точно так же и зеленый...
    Если вам не трудно приведите пример работы описанной логики, я поизучаю если какие моменты не понятны то спрошу.
     
  2. acos

    acos Официальный гик Администратор

    Как-то так
    Код (Text):
    #include <TimerOne.h>

    #define Red_DiodPIN 6
    #define Blue_DiodPIN 7
    #define Green_DiodPIN 8
    #define PIN_Button 5

    enum LED_COLOR {
      RED  = 0,
      BLUE = 1,
      GREEN = 2
    };

    enum STATE {
      LIGHT_LED = 0,
      PULSE    = 1
    };

    byte currentState = 0;
    byte currentLed = 0;
    byte currentPulse = 0;

    byte ledPin[] = {
      Red_DiodPIN,
      Blue_DiodPIN,
      Green_DiodPIN
    };

    //пауза между включением светодиодов
    int nextLedTime[] = {
      200,
      150,
      300
    };

    // время свечения светодиодов
    int lightTime[] = {
      500,
      700,
      800
    };

    // количество импульсов будет регулироваться от 1 до 5
    byte pulseCount[] = {
      3,
      1,
      4
    };

    //интервал пульсаций
    int pulseInterval[] = {
      50,
      60,
      80
    };

    //unsigned long time;

    void setup() {
      // put your setup code here, to run once:
      for (byte i = 0; i < 3; ++i)
      {
        pinMode(ledPin[i], OUTPUT);
      }

      Timer1.initialize(100000); // set a timer of length 100000 microseconds (or 0.1 sec - or 10Hz => the led will blink 5 times, 5 cycles of on-and-off, per second)
      Timer1.attachInterrupt( timerIsr ); // attach the service routine here

    //  time = millis();
    }

    void loop() {
      // put your main code here, to run repeatedly:
    /*
      //тупо и «в лоб»
      for (byte i = 0; i < 3; ++i)
      {
        for (byte pulse = 0; pulse < pulseCount[i]; ++pulse)
        {
          digitalWrite(ledPin[i], HIGH);
          delay(lightTime[i]);
          digitalWrite(ledPin[i], LOW);
          delay(pulseInterval[i]);
        }
        delay(nextLedTime[i]);
      }
    */
    }

    void timerIsr()
    {
      unsigned long nextTime;

      switch (currentState)
      {
        case LIGHT_LED:
          digitalWrite(ledPin[currentLed], HIGH);
          nextTime = lightTime[currentLed];
          currentState=PULSE;
          break;
        case PULSE:
          digitalWrite(ledPin[currentLed], LOW);

          if (currentPulse < pulseCount[currentLed])
          {
            nextTime = pulseInterval[currentLed];
            ++currentPulse;
          }
          else
          {      
            currentPulse=0;
            currentState=LIGHT_LED;
            nextTime = nextLedTime[currentLed];
            if (currentLed==GREEN)
            {
              currentLed=RED;
            } else {
            ++currentLed;
            }
          }
          currentState=LIGHT_LED;
          break;

      }
      Timer1.initialize(nextTime*1000);

    }
     
     
    Последнее редактирование: 3 апр 2014
  3. vasilp

    vasilp Нерд

    Почему то начинает работать сразу и не ждет нажатия кнопки.... Что то я совсем ничего не понял
    А попроще для начинающего нет варианта? С библиотеками еще не работал, кроме LiquidCrystal_I2C и debounce У меня настройки используются с помощью case типа такого if (flightTim < 1000) flightTim ++;
    Которая находится в void(loop) с неё вызываются исполняющие коды вроде такого
    if (debounce (Button_START))
    {
    PulseLght();
    }
    else if (debounce(Button_PLUS))
    {
    mode = SELECT;
    }
    else if (debounce(Button_SET))
    {
    mode = STOP;
    }
    }
    Мне теперь не понятен это момент как мне настраивать по отдельности параметры
    int lightTime[] = {
    500,
    700,
    800
    };
    И второй вопрос если я вместо void loop() заменю PulseLght() Будет работать так же?
     
  4. vasilp

    vasilp Нерд

    Можно вариант наподобие этого здесь то я как бы понимаю что происходит Правда он не полностью рабочий
    Код (Text):
    #define Red_DiodPIN 6
    #define Blue_DiodPIN 7
    #define Green_DiodPIN 8
    #define Button_START 5

    // абсолтюное время
    unsigned long time;
    unsigned long timepuls;
    // каждый параметр будет регулироваться
    // интервал между включением

    unsigned long next_red = 200;
    unsigned long next_blue = 150;
    unsigned long next_green = 300;

    // время свечения
    unsigned long ligth_time_red = 500;
    unsigned long ligth_time_blue = 700;
    unsigned long ligth_time_green = 800;

    // количество пульсаций
    unsigned long Pulse_red = 3; // будет регулироваться от 1 до 5
    unsigned long Pulse_blue = 1;
    unsigned long Pulse_green = 4;

    //интервал пульсаций
    unsigned long Pulse_time_red = 100; // задержка между импульсами
    unsigned long Pulse_time_blue = 150;
    unsigned long Pulse_time_green = 200;

    void setup()
    {
      pinMode(Red_DiodPIN, OUTPUT);
      pinMode(Blue_DiodPIN, OUTPUT);
      pinMode(Green_DiodPIN, OUTPUT);
      digitalWrite(Red_DiodPIN, LOW);
      digitalWrite(Blue_DiodPIN, LOW);
      digitalWrite(Green_DiodPIN, LOW);
      pinMode(PIN_BTN_START, INPUT);
    }

    void loop()
    {
      if (digitalRead (Button_START))
      {
        // сохраняем время на момент нажатия кнопки
        time = millis();
        timepuls = millis();
        // флаг, указывающий что цикл закончен
        boolean flag = false;
     
        while (!flag)
        {
        // если текущее время - сохраненое время меньше время свечения
        if (millis() - time <= ligth_time_red)
        digitalWrite(Red_DiodPIN, HIGH);// то выполняется условие Red_DiodPIN, HIGH
        // мне кажеться что сожранять новое время нужно после каждого действия
     
        //if (timepuls() - time <= ((ligth_time_red ++ Pulse_time_red)
        //digitalWrite(Red_DiodPIN, LOW);
        // включился выключился на заданное кличество раз Pulse_red
        else  // инче Red_DiodPIN, LOW
        digitalWrite(Red_DiodPIN, LOW);
        if (millis() - time >= next && millis() - time <= next_blue + ligth_time_blue )
        digitalWrite(Blue_DiodPIN, HIGH);
        else
        digitalWrite(Blue_DiodPIN, LOW);
     
        if (millis() - time >= next_green && millis() - time <= next_green + ligth_time_green )
        digitalWrite(Green_DiodPIN, HIGH);
        else
        digitalWrite(Green_DiodPIN, LOW);
     
        // выходим из цикла
        if (millis() - time <= next_green + ligth_time_green)
          flag = true;
        }
     
      }
    }
     
  5. acos

    acos Официальный гик Администратор

    lightTime[RED]=52; - например так можно менять таймеры
    Подредактировал код чуть - он был немного не того. Теперь того.
    Кнопку можете добавить сами)
    Там есть два варианта - один тупой (закомментированный в loop), второй с таймером. Вам нужен был пример работы - вот он. Если выберете тупой метод - удалите всё, что относится к Timer1.

    По поводу вашего кода с millis() - можно и так)
     
  6. vasilp

    vasilp Нерд

    Спасибо! Ага теперь начал немного догонять, сейчас покумекаю если что то обращусь еще разок.
     
  7. vasilp

    vasilp Нерд

    Что то не могу понять что происходит попытался сделать так lightTime[RED]=52; ошибку выдает
    И еще можете мне объяснить вот это для чего вернее что сдесь происходит я не могу понять если не сложно обьясните пожалуйста построчно.
    enum LED_COLOR {
    RED = 0,
    BLUE = 1,
    GREEN = 2
    };

    enum STATE {
    LIGHT_LED = 0,
    PULSE = 1
    };

    byte currentState = 0;
    byte currentLed = 0;
    byte currentPulse = 0;

    byte ledPin[] = {
    Red_DiodPIN,
    Blue_DiodPIN,
    Green_DiodPIN
    };

    Код (Text):
    #include <TimerOne.h>

    #define Red_DiodPIN 6
    #define Blue_DiodPIN 7
    #define Green_DiodPIN 8
    #define PIN_Button 5

    enum LED_COLOR {
      RED  = 0,
      BLUE = 1,
      GREEN = 2
    };

    enum STATE {
      LIGHT_LED = 0,
      PULSE    = 1
    };

    byte currentState = 0;
    byte currentLed = 0;
    byte currentPulse = 0;

    byte ledPin[] = {
      Red_DiodPIN,
      Blue_DiodPIN,
      Green_DiodPIN
    };

    //пауза между включением светодиодов
    int nextLedTime[] = {
      200,
      150,
      300
    };

    // время свечения светодиодов
    int lightTime[RED]=500;
    int lightTime[BLUE]=750;
    int lightTime[GREEN]=800;
    // количество импульсов будет регулироваться от 1 до 5
    byte pulseCount[] = {
      3,
      1,
      4
    };

    //интервал пульсаций
    int pulseInterval[] = {
      50,
      60,
      80
    };

    //unsigned long time;

    void setup() {
      // put your setup code here, to run once:
      for (byte i = 0; i < 3; ++i)
      {
        pinMode(ledPin[i], OUTPUT);
      }

    //  time = millis();
    }

    void loop() {

      for (byte i = 0; i < 3; ++i)
      {
        for (byte pulse = 0; pulse < pulseCount[i]; ++pulse)
        {
          digitalWrite(ledPin[i], HIGH);
          delay(lightTime[i]);
          digitalWrite(ledPin[i], LOW);
          delay(pulseInterval[i]);
        }
        delay(nextLedTime[i]);
      }

    }
     
     
  8. vasilp

    vasilp Нерд

    Пожалуйста если не трудно покажите как это сделать с millis() так хоть мне больше всего понятней будет. Я сам плохо разбираюсь еще только учусь мне не как было не заставить работать свой код так как я еще неопытен в программировании.
     
  9. acos

    acos Официальный гик Администратор

    что в нём не работает?
    почему так? ligth_time_red ++ Pulse_time_red
     
  10. acos

    acos Официальный гик Администратор

  11. vasilp

    vasilp Нерд

    Спасибо статья полезная кое чем помогла скретив ваш код и свой я разобрался как заставить мигать красный светодиод, Вот ту то и пошла загвоздка подскажите пожалуйста как delay() заменить на milis() чтобы в этот момент управлять остальными диодами статья типа Blink без Delay мне не помогла как записать выражение что пора выключить светодиод? Вот такой код у меня получился он работает но только на красный светодиод мне нужно чтобы синий и зеленый запускались в момент нажатия кнопки у каждого своя пауза перед запуском свой интервал и своя длительность свечения С delay это не подходит так как следущий диод будет ждать пока не закончит красный... С библиотекой TimerOne мне никак не разобраться...
    Код (Text):
    #define RED_PIN 6
    #define BLUE_PIN 7
    #define GREEN_PIN 10
    #define PIN_BTN_START 5

    // абсолтюное время
    unsigned long time;
    unsigned long timepuls;
    // каждый параметр будет регулироваться
    // пауза перед работой после старта
    unsigned long next_red = 200;
    unsigned long next_blue = 150;
    unsigned long next_green = 300;

    // длительность свечения
    unsigned long ligth_time_red = 500;
    unsigned long ligth_time_blue = 700;
    unsigned long ligth_time_green = 800;

    // количество сколько раз мигнуть
    byte Pulse_red = 2; // будет регулироваться от 1 до 5
    byte Pulse_blue = 1;
    byte Pulse_green = 4;

    //интервал между миганием
    unsigned long pulseIntervalRed = 100; // задержка между импульсами
    unsigned long pulseIntervalBlue = 150;
    unsigned long pulseIntervalGreen = 200;
    // флаг статуса кнопки
    boolean btn_flag = false;

    void setup()
    {
      pinMode(RED_PIN, OUTPUT);
      pinMode(BLUE_PIN, OUTPUT);
      pinMode(GREEN_PIN, OUTPUT);
      digitalWrite(RED_PIN, LOW);
      digitalWrite(BLUE_PIN, LOW);
      digitalWrite(GREEN_PIN, LOW);
      pinMode(PIN_BTN_START, INPUT);
    }

    void loop()
    {
      if ((digitalRead (PIN_BTN_START)) && !btn_flag)
      {
        btn_flag = true;
     
        // флаг отработки свечения диодов
        boolean flag = false;
     
        // текущее системное время
        long time = millis();
        while(!flag)
        {
        // если текущее время - сохраненое время меньше время свечения
        if (millis() - time <= next_red)
       
      {
        for (byte pulse = 0; pulse < Pulse_red; ++pulse)
        {
          digitalWrite(RED_PIN, HIGH);
          delay(ligth_time_red);
          digitalWrite(RED_PIN, LOW);
          delay(pulseIntervalRed);
        }
        delay(next_red);
          flag = true;
        }

      }

      if (!(digitalRead (PIN_BTN_START)) && btn_flag)
      {
        btn_flag = false;
        delay(100);
      }
      }
    }
     
    Последнее редактирование: 5 апр 2014
  12. vasilp

    vasilp Нерд

    Не ужели мне никто не может помочь?
     
  13. Unixon

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

    Возьмите код для красного и повторите для других светодиодов.
     
  14. vasilp

    vasilp Нерд

    Я так делал но проблема в том что следующие светодиоды ждут когда закончит работать красный, delay портит всю картину мне нужно что бы работа трех диодов была независима...Вот примерно попытался изобразить

    Безымянный.jpg
     
  15. vasilp

    vasilp Нерд

    Это я эксперементировал да так и осталось :)
     
  16. Unixon

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

    Ну так уберите этот delay(). В чем проблема то?
     
  17. vasilp

    vasilp Нерд

    Если б я знал как это сделать! Я бы наверное не обращался за помощью.
     
  18. Unixon

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

    Кнопкой Backspace или кнопкой Delete, как вам больше нравится. :)
     
  19. vasilp

    vasilp Нерд

    Я думал мне помогут а тут реально только издеваются над новичками Спасибо конечно я то и не догадался....
     
  20. Unixon

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

    Вам код типа такого нужно сделать:

    Код (Text):

    bool active = false;
    long int time = 0;

    void loop()
    {
     if (digitalRead(PIN_BTN_START))
     {
      active = true;
      time = millis();
     }
     if (active)
     {
      long int rt = millis() - time;
      // timer event 1
      if ((rt>=TIME_START_RED) && (rt<TIME_STOP_RED))
      {
      digitalWrite(PIN_LED_RED, HIGH);
      }
      if (rt>=TIME_STOP_RED)
      {
      digitalWrite(PIN_LED_RED, LOW);
      }
      // timer event 2
      if ((rt>=TIME_START_GREEN) && (rt<TIME_STOP_GREEN))
      {
      digitalWrite(PIN_LED_GREEN, HIGH);
      }
      if (rt>=TIME_STOP_GREEN)
      {
      digitalWrite(PIN_LED_GREEN, LOW);
      }
      // timer event 3
      if ((rt>=TIME_START_BLUE) && (rt<TIME_STOP_BLUE))
      {
      digitalWrite(PIN_LED_BLUE, HIGH);
      }
      if (rt>=TIME_STOP_BLUE)
      {
      digitalWrite(PIN_LED_BLUE, LOW);
      }
      if (rt>=TIME_STOP_ALL)
      {
      active = false;
      }
     }
    }