Функция Millis () не работает в течение длительного периода времени
Я использую функцию millis() для управления таймером моего светодиода. Это очень простой код, который я использовал из примеров библиотек. Код работал хорошо в течение 6 часов (включен в течение 6 часов, выключен в течение следующих 6 часов и так далее), однако, когда я установил его на 12 часов, свет не выключился, когда я проверил его. Расчетное время должно было уместиться в 2 ^ 32 бита для unsigned long, которые я определил заранее. Может ли кто-нибудь помочь в этом вопросе? Спасибо!
/*
Мигать без задержки
Включает и выключает светоизлучающий диод (LED), подключенный к цифровому контакту,
без использования функции delay(). Это означает, что другой код может выполняться одновременно с
в то же время, не прерываясь кодом светодиода.
Схема:
- Используйте встроенный светодиод.
- Примечание. Большинство плат Arduino имеют встроенный светодиод, которым вы можете управлять. На УНО, МЕГА
и ZERO подключается к цифровому пину 13, на MKR1000 к пину 6. LED_BUILTIN
устанавливается на правильный вывод светодиода, независимо от того, какая плата используется.
Если вы хотите узнать, к какому контакту подключен встроенный светодиод на вашем
Модель Arduino, проверьте технические характеристики вашей платы по адресу:
https://www.arduino.cc/en/Main/Продукты
создан в 2005 г.
Дэвид А. Меллис
изменено 8 февраля 2010 г.
Пол Штоффреген
изменено 11 ноября 2013 г.
Скотт Фицджеральд
изменено 9 января 2017 г.
Артуро Гуадалупи
Этот пример кода находится в общественном достоянии.
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
// константы не изменятся. Используется здесь для установки вывода:
const int ledPin = 7;// номер вывода светодиода
// Переменные изменятся:
int ledState = LOW; // ledState используется для установки светодиода
// Как правило, вы должны использовать "unsigned long" для переменных, которые содержат время
// Значение быстро станет слишком большим для хранения в int
unsigned long previousMillis = 0; // запомним время последнего обновления светодиода
// константы не изменятся:
unsigned long interval = 12*60*60*1000UL; // интервал мигания (миллисекунды)
void setup() {
// устанавливаем цифровой вывод в качестве выхода:
pinMode(ledPin, OUTPUT);
}
void loop() {
// здесь вы бы разместили код, который должен выполняться все время.
// проверяем, не пора ли мигнуть светодиодом; то есть если разница
// между текущим временем и последним временем, когда вы моргнули, светодиод больше, чем
// интервал, с которым вы хотите мигать светодиодом.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// сохранить время последнего мигания светодиодом
previousMillis = currentMillis;
// если светодиод выключен, включить его и наоборот:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// устанавливаем светодиод с помощью переменной ledState:
digitalWrite(ledPin, ledState);
}
}
@syuen, 👍1
Обсуждение2 ответа
Вы пытались изменить свои переменные, чтобы расчеты производились в секундах, а не в миллисекундах? IOW добавьте "/1000" после millis() и соответственно уменьшите ваши константы.
millis() периодически переполняется, но это происходит примерно раз в 49 дней, и это даже не должно влиять на то, как вы его используете (разница также будет переполняться в другом направлении).
Не добавляйте /1000
после millis()
, иначе у вас возникнут проблемы, когда millis()
перевернется., @Edgar Bonet
В C++ оператор умножения является «левоассоциативным». Это означает что выражение
12*60*60*1000UL
интерпретируется как
((12*60)*60)*1000UL
Левый множитель, а именно (12*60)*60
, вычисляется с использованием данных int
тип, но результат выходит за рамки этого формата, что приводит к проблеме, которую вы
см.
Простое решение – сделать один из факторов первого продукта
быть unsigned long
. Например
1000UL*60*60*12
Затем вычисляется 1000UL*60
с типом данных unsigned long
. С
результат сам по себе является unsigned long
, следующее умножение также
делается как unsigned long
и аналогично для последнего.
Если вы находите этот метод несколько непонятным, вы также можете добавить UL
суффикс к каждому фактору. Это позволит избежать неявных преобразований
компилятор, делая все типы явными.
Проблема раскрыта! Спасибо, сэр! Программирование вообще не моя область и поэтому у меня явно нет базы. Ваш комментарий очень полезен и высоко ценится., @syuen
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
пожалуйста, посмотрите на свой пост ... листинг программы выглядит так, как вы предполагали? ... пожалуйста, отформатируйте код... используйте кнопку
{}
, @jsotolaиспользуйте
длинный интервал без знака = 1000UL*12*60*60*;
, @Juraj