RTClib now() в цикле while не обновляется
Я столкнулся с этим, пытаясь сделать монитор заряда батареи, и удивился, где же я ошибся. Используя RTClib
, доступный в Arduino IDE или из adafruit github, я столкнулся с проблемами при попытке вызвать now
в цикле while внутри
цикла
. Вот простой пример:
#include "RTClib.h"
#define ledPIN 13
RTC_PCF8523 rtc;
void setup() {
// put your setup code here, to run once:
pinMode(ledPIN, OUTPUT);
digitalWrite(ledPIN, LOW);
Serial.begin(9600);
while(!Serial) {/* wait for Serial */}
rtc.begin();
rtc.start();
digitalWrite(ledPIN, HIGH);
}
void loop() {
// put your main code here, to run repeatedly:
char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
while (millis() < 60000){
Serial.println((rtc.now()).toString(fmt));
delay(5000);
}
Serial.println("Finished");
digitalWrite(ledPIN, LOW);
while(1) { /* do nothing forever */ }
}
Результатом этого небольшого теста будет одно и то же время, повторяемое каждые 5 секунд. Если это имеет значение, я использую перо M0 с фезерлоггером, на котором установлен RTC. Изменение этой функции цикла на следующую:
void loop() {
// put your main code here, to run repeatedly:
char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
if (millis() < 60000){
Serial.println((rtc.now()).toString(fmt));
delay(5000);
} else {
Serial.println("Finished");
digitalWrite(ledPIN, LOW);
while(1) { /* do nothing forever */ }
}
}
показывает, что теперь
действительно обновляет время каждые 5 секунд. Я посмотрел на код сейчас
, и он, кажется, делает очень простые команды i2c, чтобы получить время и сообщить об этом. Единственное, что я могу придумать, это то, что компилятор создал (не так) временный объект DateTime для меня в цикле
while, и библиотека RTC не предоставляет удобный конструктор или оператор для перезаписи существующего объекта.
Я проверил свою теорию с помощью этого
void loop() {
// put your main code here, to run repeatedly:
char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
while (millis() < 60000){
DateTime t1 = rtc.now();
Serial.println(t1.toString(fmt));
delay(5000);
}
Serial.println("Finished");
digitalWrite(ledPIN, LOW);
while(1) { /* do nothing forever */ }
}
Но опять же, время не изменилось так явно, что я не понимаю, что здесь происходит. Почему функция rtc now не
работает так, как задумано в цикле while внутри функции
loop
?
@Matt, 👍0
Обсуждение1 ответ
Лучший ответ:
См. Документацию DateTime::toString()
:
Параметр buffer должен быть инициализирован вызывающим абонентом строкой, указывающей запрашиваемый формат. Эта строка формата может содержать любой из следующих спецификаторов: [...] Спецификаторы внутри буфера будут перезаписаны соответствующие значения из
DateTime
. Любые символы, не принадлежащие ни одному из вышеперечисленных спецификаторов, остаются как есть.
Важно понимать что используется параметр buffer
как в качестве входных данных (для описания формата), так и в качестве выходных данных (для
форматированной даты и времени). Вы инициализируете его описанием формата
(
"YYYY/MM/DD-hh:mm:ss\n"
). Затем, после первого вызова функции toString()
,
тот же буфер содержит отформатированные дату и время. Он больше не
содержит описания формата. При втором вызове
toString()
, согласно правилу “Любые символы, не принадлежащие одному из
указанных выше спецификаторов, остаются как есть”, буфер не изменяется.
Решение: Поместите инициализацию буфера в тот же цикл while
, что и вызов
toString()
.
Как обычно, чтение документации сэкономило бы ОП много времени... ;-) +1, @the busybee
- Преобразование в Unix Timestamp и обратно
- Разница между «time_t» и «DateTime»
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
- DS1307RTC Выводит загадочную дату 165/165/2165. Какие возможны исправления?
- RtcDateTime' не называет тип
- Библиотека времени Arduino и библиотеки RTC
- Не удалось выделить SSD1306 при добавлении константы
- Как получить текущую дату
если (! rtc.begin()) { Serial.println("Не удалось найти RTC"); Serial.flush(); отбой(); }
вы можете добавить эту часть в свой код, чтобы проверить, дает ли он какую-либо ошибку или нет, @Maaz SkВы также не добавили дату и время в свой код. Перед тем, как продолжить, вы можете проверить, работает ли пример кода или нет, @Maaz Sk
Попробуйте изменить цикл на
while (millis() < 60000){ volatile DateTime time = rtc.now(); Serial.println(time.toString(fmt)); delay(5000); }
Если это работает, ваша теория о неправильной оптимизации компилятора верна., @PMF