RTClib now() в цикле while не обновляется

rtc

Я столкнулся с этим, пытаясь сделать монитор заряда батареи, и удивился, где же я ошибся. Используя 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?

, 👍0

Обсуждение

если (! 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


1 ответ


Лучший ответ:

3

См. Документацию DateTime::toString():

Параметр buffer должен быть инициализирован вызывающим абонентом строкой, указывающей запрашиваемый формат. Эта строка формата может содержать любой из следующих спецификаторов: [...] Спецификаторы внутри буфера будут перезаписаны соответствующие значения из DateTime. Любые символы, не принадлежащие ни одному из вышеперечисленных спецификаторов, остаются как есть.

Важно понимать что используется параметр buffer как в качестве входных данных (для описания формата), так и в качестве выходных данных (для форматированной даты и времени). Вы инициализируете его описанием формата ("YYYY/MM/DD-hh:mm:ss\n"). Затем, после первого вызова функции toString(), тот же буфер содержит отформатированные дату и время. Он больше не содержит описания формата. При втором вызове toString(), согласно правилу “Любые символы, не принадлежащие одному из указанных выше спецификаторов, остаются как есть”, буфер не изменяется.

Решение: Поместите инициализацию буфера в тот же цикл while , что и вызов toString().

,

Как обычно, чтение документации сэкономило бы ОП много времени... ;-) +1, @the busybee