Функции времени

Задержки
Простейшей с точки зрения использования функцией времени является задержка: программа “зависает” внутри функции задержки и ожидает указанное время. Задержка позволяет очень удобно и наглядно организовать работу простой “однозадачной” программы, у нас есть два варианта задержек:
delay(time)- Задержка на указанное количество миллисекунд (мс). 1 секунда = 1’000 мс.
timeпринимает тип данныхunsigned longи может приостановить выполнение на срок от 1 до 4 294 967 295 мс (~50 суток) с разрешением 1 мс.- Работает на системном таймере, поэтому не работает внутри прерывания и при отключенных прерываниях.
delayMicroseconds(time)- Задержка на указанное количество микросекунд (мкс). 1 секунда = 1’000’000 мкс.
timeпринимает тип данныхunsigned intи может приостановить выполнение на срок от 4 до 16383 мкс (да, меньше чем максимум для этого типа данных) с разрешением 4 мкс.- Работает не на таймере, а на пропуске тактов процессора, поэтому может работать в прерывании и при отключенных прерываниях.
- Иногда не совсем корректно работает с переменными, поэтому нужно стараться использовать константы (
constили просто число). - Часто используется в библиотеках для эмуляции цифровых интерфейсов связи.
Задержки использовать очень просто:
void setup() {}
void loop() {
// что-то выполнить
delay(500); // подождать полсекунды
} Мышление “задержками” – главная проблема новичков. Организовать работу сложной программы при помощи задержки – невозможно, поэтому дальше рассмотрим более полезные инструменты.
Функция yield()
Разработчики Arduino позаботились о том, чтобы функция delay() не просто блокировала выполнение кода, но и позволяла выполнять другой код во время этой задержки. Данный “костыль” получил название yield() и работает следующим образом: если объявить функцию
void yield() {
// ваш код
} то расположенный внутри неё код будет выполняться во время работы любой задержки delay() в программе! Это решение хоть и кажется нелепым, но в то же время позволяет быстро и без написания лишних костылей и таймеров реализовать пару параллельно выполняющихся задач. Это вполне соответствует идеологии Arduino – максимально простая и быстрая разработка прототипа. Рассмотрим простой пример: стандартный мигающий светодиод, но с опросом кнопки:
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, 1);
delay(1000);
digitalWrite(13, 0);
delay(1000);
}
void yield() {
// а тут можно опрашивать кнопку
// и не пропустить нажатия из за delay!
} Данный трюк работает на AVR Arduino, на esp8266 его нет
Функции счёта времени
Данные функции возвращают время, прошедшее с момента запуска программы, так называемый аптайм (англ. uptime). Таких функций у нас две:
millis()– миллисекунды, типunsigned long, от 1 до 4 294 967 295 мс (~50 суток), разрешение 1 мс. После “переполнения” отсчёт начинается с нуля.micros()– микросекунды, типunsigned long, от 4 до 4 294 967 295 мкс (~70 минут), разрешение 4 мкс. После “переполнения” отсчёт начинается с нуля.
Эти функции позволяют организовать программу практически любой сложности с любым количеством параллельно выполняющихся по таймеру задач. Подробнее об этом поговорим в уроке про многозадачность.
Раньше здесь было рассказано про таймер на millis(). Информация переехала в урок про многозадачность.
millis() в часы и секунды
Миллисекунды – не самый удобный способ оценить время работы программы. Можно перевести его в более человеческие часы, минуты и секунды при помощи нехитрых математических операций:
uint32_t sec = millis() / 1000ul; // полное количество секунд int timeHours = (sec / 3600ul); // часы int timeMins = (sec % 3600ul) / 60ul; // минуты int timeSecs = (sec % 3600ul) % 60ul; // секунды
Видео
Полезные страницы
- Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
- Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
- Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
- Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
- Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
- Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
- Поддержать автора за работу над уроками
- Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])
Функция millis()
Описание
Возвращает время в миллисекундах, прошедшее с начала выполнения программы на плате Arduino. Это число будет переполнено и сброситься до 0 примерно через 50 дней выполнения.
Синтаксис
millis()
Параметры
нет
Возвращаемое значение
Количество миллисекунд, прошедших с момента запуска программы
Пример
Выводим значение, возвращаемое функцией millis() и ждем 1 секунду:
unsigned long mTime;
void setup()
{
Serial.begin(9600);
}
void loop()
{
mTime = millis();
Serial.println(mTime);
delay(1000);
}
Функция micros()
Описание
Возвращает время в микросекундах, прошедшее с начала выполнения программы на плате Arduino. Это число будет переполнено и сброситься до 0 примерно через 70 минут выполнения.
Синтаксис
micros()
Параметры
нет
Возвращаемое значение
Количество микросекунд, прошедших с момента запуска программы
Пример
Выводим значение, возвращаемое функцией micros() и ждем 1 секунду:
unsigned long mTime;
void setup()
{
Serial.begin(9600);
}
void loop()
{
mTime = micros();
Serial.println(mTime);
delay(1000);
}
Примечания
На платах Arduino 16 МГц (например Uno и Nano) эта функция имеет разрешение в четыре микросекунды, поэтому значение всегда кратно четырем. На платах Arduino 8 МГц (например, LilyPad) эта функция имеет разрешение восемь микросекунд.
Функция delay()
Описание
Приостанавливает выполнение программы на заданноое время в миллисекундах.
Синтаксис
delay(ms)
Параметры
ms — время в миллисекундах, на которое нужно приостановить программу
Возвращаемое значение
нет
Пример
Мигаем встроенным светодиодом:
int ledPin = 13;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
}
Примечания
Несмотря на то, что с помощью функции delay() легко создать мигающий светодиод и многие другие простые скетчи, использование функции имеет существенные недостатки. Во время приостановки программы невозможны любые манипуляции с пинами, например опрос датчиков. Также не будут работать многие математические функции. Поэтому рекомендуется в качестве альтернативы использовать функцию millis().
Однако некоторые функции во вовремя выполнение delay() все же продолжают работать. Например, прерывания.
Функция delayMicroseconds()
Описание
Приостанавливает выполнение программы на заданное время в микросекундах.
Синтаксис
delayMicroseconds(us)
Параметры
us — время в микросекундах, на которое нужно приостановить программу
Возвращаемое значение
нет
Пример
Посылаем последовательность импульсов с периодом раз в 100 микросекунд:
int outPin = 8;
void setup()
{
pinMode(outPin, OUTPUT);
}
void loop()
{
digitalWrite(outPin, HIGH);
delayMicroseconds(50);
digitalWrite(outPin, LOW);
delayMicroseconds(50);
}
Often, you need to measure the time your microcontroller takes to perform a particular task. You can use the millis() function of Arduino to measure the time. This function returns the number of milliseconds passed since your board started running the current program. Therefore, to calculate the time taken by an operation, you can call millis() before and after your operation, and take the difference of the two values.
An example implementation is given below −
Example
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
long int t1 = millis();
task_whose_time_is_to_be_measured();
long int t2 = millis();
Serial.print("Time taken by the task: "); Serial.print(t2-t1); Serial.println(" milliseconds");
}
void loop() {
// put your main code here, to run repeatedly:
} As you can see, this will give the execution time of the task in milliseconds. But what if you want the execution time to be in microseconds? You guessed it! You can use micros() instead of millis().
Often, you need to measure the time your microcontroller takes to perform a particular task. You can use the millis() function of Arduino to measure the time. This function returns the number of milliseconds passed since your board started running the current program. Therefore, to calculate the time taken by an operation, you can call millis() before and after your operation, and take the difference of the two values.
An example implementation is given below −
Example
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
long int t1 = millis();
task_whose_time_is_to_be_measured();
long int t2 = millis();
Serial.print("Time taken by the task: "); Serial.print(t2-t1); Serial.println(" milliseconds");
}
void loop() {
// put your main code here, to run repeatedly:
} As you can see, this will give the execution time of the task in milliseconds. But what if you want the execution time to be in microseconds? You guessed it! You can use micros() instead of millis().
Возвращает количество миллисекунд с момента начала выполнения текущей программы на плате Arduino. Это количество сбрасывается на ноль, в следствие переполнения значения, приблизительно через 50 дней.
Параметры
нет
Возвращаемое значение
Количество миллисекунд с момента начала выполнения программы. (unsigned long)
Пример
unsigned long time;
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.print("Time: ");
time = millis();
//выводит количество миллисекунд с момента начала выполнения программы
Serial.println(time);
// ждет секунду, перед следующей итерацией цикла.
delay(1000);
} Смотрите также
- delay()
- delayMicroseconds()
- micros()
Справочник языка Arduino
Обратимся к первому уроку, где мы управляли LED. Между включением и выключением которого была секундная задержка.
В используемой там программе (см. код ниже) был один очень большой недостаток. Для выдержки паузы между вкл/выкл LED в 1 сек. нами была использована функция delay(). В это время контроллер не может выполнять другие команды в главной функции loop()
/* Мигание LED
* ------------
*
* Включает и выключает светодиод (LED) подсоединенный
* к выходу 13, с интервалом в 2 секунды
*
*/
int ledPin = 13; // LED подсоединен к выводу 13
void setup()
{
pinMode(ledPin, OUTPUT); // устанавливаем вывод 13 как выход
}
void loop()
{
digitalWrite(ledPin, HIGH); // включаем LED
delay(1000); // пауза 1 секунда
digitalWrite(ledPin, LOW); // выключаем LED
delay(1000); // пауза 1 секунда
}
Первое, что мы сделаем, это внесем небольшие корректировки в функцию loop(). Чтобы сделать код более компактным и изящным, заменим 2 пары строчек на одну пару. Вместо установки значения в HIGH, а затем обратно в LOW, мы получим текущее значение ledPin и проинвертируем его. Т.е. если оно было HIGH, то станет LOW и наоборот.
void loop()
{
digitalWrite(ledPin, !digitalRead(ledPin)); // включаем/выключаем LED
delay(1000); // задержка 1 сек.
}
Отлично! Теперь мы усовершенствуем функцию delay(). Взамен, мы будем использовать функцию millis(). Данная функция возвращает количество миллисекунд, прошедшее с момента запуска текущей программы. Функция переполнится (вернется в нуль) приблизительно через 50 суток работы программы.
Альтернативной функцией является micros(), которая возвращает количество микросекунд, прошедшее с момента запуска текущей программы. Функция переполнится (вернется в нуль) приблизительно через 70 минут работы программы.
В нашем уроке мы будем использовать функцию millis():
/* Мигание LED Версия 2
* ------------------------
* Включает и выключает светодиод (LED) подсоединенный
* к выходу 13, с интервалом в 2 секунды используя функцию millis()
*
*/
int ledPin = 13; // LED подсоединен к выводу 13
unsigned long currentTime;
unsigned long loopTime;
void setup()
{
pinMode(ledPin, OUTPUT); // устанавливаем вывод 13 как выход
currentTime = millis(); // считываем время, прошедшее с момента запуска программы
loopTime = currentTime;
}
void loop()
{
currentTime = millis(); // считываем время, прошедшее с момента запуска программы
if(currentTime >= (loopTime + 1000)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда
digitalWrite(ledPin, !digitalRead(ledPin)); // включаем/выключаем LED
loopTime = currentTime; // в loopTime записываем новое значение
}
// Здесь могут быть другие команды
}
В данном примере мы ввели две дополнительные переменные currentTime и loopTime. В функции setup() обе переменные имеют одно и тоже значение. В функции loop(), переменная currentTime каждый раз обновляется в цикле. Когда currentTime больше чем loopTime на 1 секунду (loopTime + 1000), то LED меняет свое состояние, а переменной loopTime присваивается текущее значение currentTime.
Обратите внимание, что в данном примере мы не использовали функцию delay() и процессор может выполнять другие операции.
Оригинал статьи на английском языке (перевод Колтыков А.В. для сайта cxem.net)
Оригинал статьи
Теги:
Колтыков А.В.
Опубликована: 2011 г.

1
![]()
Вознаградить
Я собрал
0
0
x
Оценить статью
- Техническая грамотность
- Актуальность материала
- Изложение материала
- Полезность устройства
- Повторяемость устройства
- Орфография
0
Средний балл статьи: 0
Проголосовало: 0 чел.
