• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Работа с аппаратным таймером.

Goga075

New member
Приветствую всех.
Использую в своем проекте программный таймер, который срабатывает при смене часа и производит логирование.
Написал код для аппаратного таймера.
C++:
#include "esp_timer.h"
#include <Wire.h>
#include <DS3231.h>

DS3231 myRTC;

esp_timer_handle_t timer1;

void setup() {
    Serial.begin(115200);
    Wire.begin();
      delay(1000);
      Serial.println("Timer 1 triggered");
      Serial.print(myRTC.getMinute(), DEC);
      Serial.print(":");
      Serial.println(myRTC.getSecond(), DEC);

    const esp_timer_create_args_t timer1_args = {
        .callback = &timer1_callback,
        .name = "timer1"
    };

    esp_timer_create(&timer1_args, &timer1);
    esp_timer_start_once(timer1, (3600-(myRTC.getMinute()*60+myRTC.getSecond()))*1000000ul);

}

void timer1_callback(void* arg) {
      Serial.println("Timer 1 triggered");
      Serial.print(myRTC.getMinute(), DEC);
      Serial.print(":");
      Serial.println(myRTC.getSecond(), DEC);

    const esp_timer_create_args_t timer1_args = {
        .callback = &timer1_callback,
        .name = "timer1"
    };

    esp_timer_create(&timer1_args, &timer1);
    esp_timer_start_once(timer1, (3600-(myRTC.getMinute()*60+myRTC.getSecond()))*1000000ul);
    
}


void loop() {
 

}
Но расчет времени сбивается и почему это происходит не могу понять.
Мой код не учитывает время выполнение самого кода и значения меньше секунды, по этому получается некий временной сдвиг и каждый последующий цикл выполняется со сдвигом. Примерно через 15 циклов сдвиг равен 1 секунде и формула это компенсирует. Точнее должна, но по какой-то причине иногда это происходит некорректно.
photo_2024-07-28_19-34-04.jpg
 

CodeNameHawk

Moderator
Команда форума
Вы про 59:59?
Ну тут вы не учитываете "знак" смещения времени работы таймера.
Подставьте эти цифры в формулу и вручную расчитайте новое время таймера.
 

CodeNameHawk

Moderator
Команда форума
Опишите, как вы получаете смещение времени и как расчитываете новое время таймера.
 

Goga075

New member
Смещение времени я ни как не получаю. Весь код я в первом посте написал.
 

Goga075

New member
Просто, будет тогда так:
esp_timer_start_once(timer1, 36000000000ul);

Но нет, ты не верно понял суть вопроса и кода.
Мне нужно сделать логирование в 0 минут и 0 секунд каждого часа. По этому и RTC
Да, конечно можно в сеттапе оставить RTC а в цикле timer1_callback пихнуть esp_timer_start_once(timer1, 36000000000ul);
Но в таком случае мы будим иметь задержку при каждом выполнении цикла timer1_callback равной времени выполнения кода. Ну и через пару месяцев беспрерывной работы мы получим хороший сдвиг.
Еще можно воспользоваться костылем if (myRTC.getSecond() && myRTC.getMinute() == 0). Но не считаю это оптимальным решением.
По этому хочу докопаться до истины и может у форумчан есть свежие идеи т.к. я уже 2 недели ломаю голову.
 

pvvx

Активный участник сообщества
myRTC.setA1Time( следующий час, 00:00)
и по прерыванию с пина RTC снова
myRTC.setA1Time( следующий час, 00:00)
А между прерываниями от вывода Alarm RTS к GPIO IRQ - ESP спать.
 

Goga075

New member
Что-то немного не то.
1. На моем RTC нету пина SQW. Но даже если и заказывать другой, в свободных пинах на ESP я сильно ограничен.
2. ticker.h это тоже самое что и esp_timer.h который я сейчас использую. Время придется задавать через формулу. И мы опять получим ложные срабатывания из-за кривизны этой формулы.
 

pvvx

Активный участник сообщества
1. На моем RTC нету пина SQW. Но даже если и заказывать другой, в свободных пинах на ESP я сильно ограничен.
Значит никакой точности в синхронизации события с RTC не получите.
Придется заранее перед переходом на новый час устраивать циклический опрос регистра секунд RTC до переключения...
 

Goga075

New member
Ну да, код подразумевает при каждом пересчете формулы запрос точного времени у RTC.
 

pvvx

Активный участник сообщества
Ну да, код подразумевает при каждом пересчете формулы запрос точного времени у RTC.
Это время не точное - имеет разброс в +- 1 сек.
Кароче это всё не верное определение задачи: хочу что-то, но не знаю чего.
Так что если нужна синхронизация с RTC, то это и надо решать. А в вашем коде этого нет.
 

pvvx

Активный участник сообщества
При выполнении процедуры прерывания таймера в RTC имеем варианты чтения минут и секунд: 59:59, 00:00, 00:01. А вы их перемножаете на что-то…
Плюс неверные раздельные чтения минут и секунд дадут ещё варианты 00:59, 59:00, 00:59
 

pvvx

Активный участник сообщества
Механизм чтения регистров RTC предусматривает защелку при правильной последовательности чтения счетных регистров. В Arduino на это наверняка плевали…

Для синхронизации, используя аппаратные свойства RTC, считываются сразу все значения – секунды, …, год. Переводятся в uint32 UTC. Это значение имеет "джиттер" в размер счетчика лет и +- 1 сек.
 

pvvx

Активный участник сообщества
Так что если вы не рассчитываете работу вашего устройства на момент перехода времени столетий, то счетчик UTC (в секундах к примеру от 01.01.1970) вам подойдет :)
И то полученный правильно, при чтении регистров из RTC по документации к ним.
Аналогично и установка RTC должна производиться по документации... Обычно с остановкой счета на время записи регистров...
 

Goga075

New member
Это время не точное - имеет разброс в +- 1 сек.
Если быть точнее разброс будет 0.999999 секунды. Которые моя формула не учитывает и их невозможно высчитать.

59:59, 00:00, 00:01. А вы их перемножаете на что-то…
Все прекрасно перемножается. Формула высчитывает как надо. Но разброс в 0.999999 секунды примерно через 15 циклов переходит в целое значение 1 секунды и формула сбоит.

(в секундах к примеру от 01.01.1970) вам подойдет :)
На unixtime() тоже писал и точно такая-же фигня, не подошло.
 

pvvx

Активный участник сообщества
В некоторых RTC для чтения есть бит состояния или прерывания, фронт которого указывает, что можно читать регистры в течении следующей части секунды до их пересчета.

В других вариантах алгоритмов чтение, к примеру, регистра секунд, останавливает изменение других регистров, пока не будет считан последний из регистров счетчиков.

Ещё бывают варианты с битом защелки – пока он записан, счетные регистры не меняются...

И варианты с остановкой счета – останавливаете счет и читаете регистры...

Так что изучайте документацию к купленным RTC часикам и беспокойтесь о том, что это китайская подделка… :p
 

pvvx

Активный участник сообщества
Все прекрасно перемножается. Формула высчитывает как надо. Но разброс в 0.999999 секунды примерно через 15 циклов переходит в целое значение 1 секунды и формула сбоит.
Это пока не нарвалось на пересчет в минутах :p
У кварца ESP точность хода от температуры не более 5 знаков. Дешевка же...
У часов свои нестабильности хода...
Плюс Arduinо и всякие sleep. Тут нарушения хода любые...
И работа WiFi - это ещё джиттер всяких запретов прерываний кроме NMI на более нескольких секунд, как не выкручивайтесь.
 
Сверху Снизу