Использование функции millis() вместо delay()

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

  1. Den1975

    Den1975 Нерд

    Сделал простую плату выбора режима работы для будущего устройства.
    Плата состоит из 2 кнопок и 6 светодиодов
    Написал скетч.
    При запуске программы должно происходить следующее - поочередно зажигаются шесть светодиодов и плата переходит в режим ожидания, горит 1-й светодиод
    Если нажать на кнопку 2 происходит переключение режима с одновременной индикацией режима соответствующим светодиодом.

    Вопрос. Хотел избавится от функции delay () в нижеуказанной части кода

    /* Устанавливаем выводы, к которым подключены светодиоды платы режимов,
    в OUTPUT. Далее зажигаем и гасим светодиоды с интервалом в 0.5 сек
    для проверки их работы */
    for (vmode = 0; vmode < 6; vmode = vmode + 1)
    {
    pinMode(vledpins[vmode], OUTPUT);
    digitalWrite(vledpins[vmode],HIGH);
    delay (500);
    digitalWrite(vledpins[vmode], LOW);
    }

    * Устанавливаем выводы, к которым подключены светодиоды платы режимов,
    в OUTPUT. Далее зажигаем и гасим светодиоды с интервалом в 0.5 сек
    для проверки их работы */
    for (vmode = 0; vmode < 6; vmode = vmode + 1)
    {
    pinMode(vledpins[vmode], OUTPUT);
    digitalWrite(vledpins[vmode], ledpin);
    }

    и заменить ее на millis(), но не получается. После запуска программы горит только первый светодиод.
    Помогите разобраться.
    Спасибо.



    Код (Text):

    // Плата управления режимами работы
    // Заносим в массив номера выводов контроллера, к которым подключены светодиоды
    // платы выбора режимов работы робота
    const int vledpins[6]={2,3,4,5,6,7};
    int ledpin = LOW;          // предыдущее состояние светодиода
    long previousMillis = 0;  // здесь будет храниться время последнего изменения состояния светодиода
    long interval = 2000;      // интервал мигания в миллисекундах

    // Создаем переменную для сохранения режима работы
    int vmode;
    // Создаем переменную для сохранения предыдущего режима работы
    int vmodeprev = -1;
    // Заносим в массив номера вывода контроллера, к которым подключены кнопки
    // платы выбора режимов работы робота
    const int vbtn[2]={8,9};


    void setup()

    {
     
    /* Инициализируем выводы контроллера, к которым подключены кнопки, в INPUT. */
      pinMode(vbtn[0], INPUT);
      pinMode(vbtn[1], INPUT);
     
      if (millis() - previousMillis > interval)
        {
        previousMillis = millis();  // запоминаем текущее время
        // если светодиод был выключен – включаем и наоборот :)
        if (ledpin == LOW)
          ledpin = HIGH;
        else
          ledpin = LOW;
        }
     
    /* Устанавливаем выводы, к которым подключены светодиоды платы режимов,
      в OUTPUT. Далее зажигаем и гасим светодиоды с интервалом в 0.5 сек
      для проверки их работы */
        for (vmode = 0; vmode < 6; vmode = vmode + 1)
        {
        pinMode(vledpins[vmode], OUTPUT);
        digitalWrite(vledpins[vmode],HIGH);
        //digitalWrite(vledpins[vmode], ledpin);
        delay (500);
        digitalWrite(vledpins[vmode], LOW);
        }
     
    // Устанавливаем значение первого режима работы робота
      vmode = 0;
    }

    //ИСПОЛНЯЕМЫЙ ПРОГРАММНЫЙ МОДУЛЬ

    void loop()
    {
    /* Исполняемый программный модуль переключения режимов работы робота */

    // Кнопка переключения на следующий режим - BTN1
      if (digitalRead(vbtn[0]) == HIGH)
      {
        vmode = vmode + 1;
        vmodeprev = vmode - 1;
        if (vmode > 5)
        {
          vmode = 0;
          vmodeprev = 5;
        }
       
      }
    // Кнопка переключения на предыдущий режим - BTN2
      if (digitalRead(vbtn[1]) == HIGH)
      {
        vmode = vmode - 1;
        vmodeprev = vmode + 1;
       
        if (vmode < 0)
        {
          vmode = 5;
          vmodeprev = 0;
        }
       
      }
    // Засвечиваем светодиод текущего режима работы
      digitalWrite(vledpins[vmode], HIGH);
    // Гасим светодиод предыдущего режима работы
      if (vmodeprev > -1)
      {
        digitalWrite(vledpins[vmodeprev], LOW);
      }
     
    /* Выбор режима работы */
      switch (vmode)
      {
      case 0: // Режим 0
        break;
       
      case 1: // Режим 1
        break;

      case 2: // Режим 2
       
        break;
       
      case 3: // Режим 3
       
       
        break;
       
      case 4: //Режим 4
       
        break;
       
      case 5: // Режим 5
        break;
      }
    }
     
  2. Alex19

    Alex19 Гуру

    setup() - запускается 1 раз, при запуске программы.

    loop() - крутится вечно.

    В setup нет смысла избавляться от delay, там она уместна. В setup мы производим настройку портов модулей и т.д., но не пишем программу, поэтому задержка с использованием delay не критична. Да и уйти от delay таким способом в setup нельзя, так как принцип проверки через millis, требует цикла loop, а setup выполняется только раз.

    Программу мы пишем в loop и там delay, бывает критичен, так как команда delay почти полностью останавливает контролер. Пока программа ожидает завершения delay, нельзя работать с портами и т.д., подробнее тут.

    Подробно о таймерах без delay на русском тут.
     
  3. Den1975

    Den1975 Нерд

    Коллеги, хотел бы понять все таки, как в указанном скетче заменить delay на millis и чтобы он работал.
    При запуске мигает только 1-й светодиод, подключенный к выводу 2, а остальные не зажигаются.
    То есть при включении не наблюдается "дорожка" из светодиодов как собственно указано в программе и она работает с функцией delay
     
  4. Alex19

    Alex19 Гуру

    Не понимаю, что именно не понятно. Но иногда, проще написать код, может он прояснит

    Код (Text):

    // Плата управления режимами работы
    // Заносим в массив номера выводов контроллера, к которым подключены светодиоды
    // платы выбора режимов работы робота
    const int vledpins[6]={2,3,4,5,6,7};//{2,3,4,5,6,7};
    int ledpin = 13;          // предыдущее состояние светодиода
    long previousMillis = 0;  // здесь будет храниться время последнего изменения состояния светодиода
    long interval = 2000;      // интервал мигания в миллисекундах

    // Создаем переменную для сохранения режима работы
    int vmode;
    // Создаем переменную для сохранения предыдущего режима работы
    int vmodeprev = -1;
    // Заносим в массив номера вывода контроллера, к которым подключены кнопки
    // платы выбора режимов работы робота
    const int vbtn[2]={8,9};


    int allLedShow = 0; // Индекс цикла
    boolean ledShow = 0; // Пока 0, зажигаем и гасим светодиоды с интервалом в 0.5 сек
    boolean led13Show = 0;  // Пока 0, зажигаем и гасим светодиод 13
    long previousShowMillis = 0; // Здесь будет храниться время последнего изменения состояния светодиодов
    long intervalShow = 500; // Интервал мигания в миллисекундах светодиодов

    void setup()
    {
      /* Инициализируем выводы контроллера, к которым подключены кнопки, в INPUT. */
      pinMode(vbtn[0], INPUT);
      pinMode(vbtn[1], INPUT);
      pinMode(ledpin, OUTPUT);

      /* Устанавливаем выводы, к которым подключены светодиоды платы режимов,
        в OUTPUT. Далее зажигаем и гасим светодиоды с интервалом в 0.5 сек
        для проверки их работы */
      for (vmode = 0; vmode < 6; vmode++)
      {
        pinMode(vledpins[vmode], OUTPUT);
        /*digitalWrite(vledpins[vmode],HIGH);*/
        /*delay (500);
        digitalWrite(vledpins[vmode], LOW);*/
      }

      // Устанавливаем значение первого режима работы робота
      vmode = 0;
      Serial.begin(9600);
      previousMillis = millis();   // запоминаем текущее время для led13
    }

    //ИСПОЛНЯЕМЫЙ ПРОГРАММНЫЙ МОДУЛЬ

    void loop()
    {
      /* Исполняемый программный модуль переключения режимов работы робота */
      if (!led13Show)
      {
        if (millis() - previousMillis > interval)
        {
          previousMillis = millis();  // запоминаем текущее время
          // если светодиод был выключен – включаем и наоборот :)
          digitalWrite(ledpin, !digitalRead(ledpin));
         
          // После того как светодиод 13 будет выключен, прерываем мигание
          if (!digitalRead(ledpin))
          {
            led13Show = 1;
          }
        }
      }
      // Убеждаемся, что ledShow == 0
      if (!ledShow)
      {
        // Убеждаемся, что previousShowMillis == 0 + millis() > 0
        if (!previousShowMillis && millis())
        {
          digitalWrite(vledpins[allLedShow],HIGH);
          previousShowMillis = millis();
         
          Serial.print("1 step - index array: ");
          Serial.print(allLedShow);
          Serial.print(" pin: ");
          Serial.print(vledpins[allLedShow]);
          Serial.print(" value pin: ");
          Serial.println(digitalRead(vledpins[allLedShow]));
        }

        // Убеждаемся, что previousShowMillis > 0 проверяем что прошло необходимое время
        if ((previousShowMillis > 0) && (millis() - previousShowMillis > intervalShow))
        {
          digitalWrite(vledpins[allLedShow],LOW);
         
          Serial.print("2 step - index array: ");
          Serial.print(allLedShow);
          Serial.print(" pin: ");
          Serial.print(vledpins[allLedShow]);
          Serial.print(" value pin: ");
          Serial.println(digitalRead(vledpins[allLedShow]));
         
          previousShowMillis = 0;
         
          // Увеличиваем на 1, значения индекса
          allLedShow++;
         
          // Прерываем мигание
          if (allLedShow == 6)
          {
            ledShow = 1;
           
            Serial.println("Finish");
          }
        }  
      }
      // Кнопка переключения на следующий режим - BTN1
      if (digitalRead(vbtn[0]) == HIGH)
      {
        vmode = vmode + 1;
        vmodeprev = vmode - 1;
        if (vmode > 5)
        {
          vmode = 0;
          vmodeprev = 5;
        }
       
      }
      // Кнопка переключения на предыдущий режим - BTN2
      if (digitalRead(vbtn[1]) == HIGH)
      {
        vmode = vmode - 1;
        vmodeprev = vmode + 1;
       
        if (vmode < 0)
        {
          vmode = 5;
          vmodeprev = 0;
        }
      }
      // Засвечиваем светодиод текущего режима работы
      digitalWrite(vledpins[vmode], HIGH);
      // Гасим светодиод предыдущего режима работы
      if (vmodeprev > -1)
      {
        digitalWrite(vledpins[vmodeprev], LOW);
      }

      /* Выбор режима работы */
      switch (vmode)
      {
      case 0: // Режим 0
        break;
      case 1: // Режим 1
        break;
      case 2: // Режим 2
        break;
      case 3: // Режим 3
        break;
      case 4: //Режим 4
        break;
      case 5: // Режим 5
        break;
      }
    }
     
    Если хотим именно в setup, хоть это не логично, можно и так, читаем задержки в AVR. Удачи.
     
    artrad нравится это.