Дрейф таймера Arduino Nano
https://youtu.be/oVZgFsWsKPM][1]
Я новичок в Arduino. Я сделал 12-часовые 7-сегментные часы с общим катодом. Я сделал 7-сегментный индикатор на светодиодах, используя Arduino Nano.
Если я использую длинный период в 1000 миллисекунд, мои часы отстают на 6 минут каждые 24 часа. Но если я использую 994 миллисекунды, они спешат на 30 секунд каждые 24 часа.
Мой код:
#include "SevSeg.h"
SevSeg Display;
const unsigned long period = 1000; //одна секунда
const unsigned long led_period = 500; //миллисекунда мигания светодиода
unsigned long startMillis;
unsigned long led_startMillis;
unsigned long currentMillis;
unsigned long led_currentMillis;
const int hrs_btn = A0;
const int min_btn = A1;
const int ledPin = A2;
int Hrs = 12;
int Min = 0;
int Sec = 0;
int Time;
int ledState = LOW;
void setup()
{
pinMode(hrs_btn, INPUT_PULLUP);
pinMode(min_btn, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
byte numDigits = 4;
byte digitPins[] = {10, 11, 12, 13};
byte segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
bool resistorsOnSegments = false;
bool updateWithDelays = false;
byte hardwareConfig = COMMON_CATHODE;
bool leadingZeros = true;
bool disableDecPoint = true;
Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
Display.setBrightness(100);
}
void loop()
{
currentMillis = millis();
if (currentMillis - startMillis >= period)
{
Sec = Sec + 1;
startMillis = currentMillis;
}
led_currentMillis = millis();
if (led_currentMillis - led_startMillis >= led_period)
{
led_startMillis = led_currentMillis;
if (ledState == LOW)
{
ledState = HIGH;
if (digitalRead(hrs_btn) == LOW)
{
Hrs = Hrs + 1;
}
if (digitalRead(min_btn) == LOW)
{
Min = Min + 1;
Sec = 0;
}
}
else
{
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
if (Sec == 60)
{
Sec = 0;
Min = Min + 1;
}
if (Min == 60)
{
Min = 0;
Hrs = Hrs + 1;
}
if (Hrs == 13)
{
Hrs = 1;
}
Time = Hrs * 100 + Min;
Display.setNumber(Time);
Display.refreshDisplay();
}
@jagpal singh, 👍-1
Обсуждение3 ответа
Лучший ответ:
Все часы (за исключением разве что атомных) имеют дрейф. Если нужна большая точность, нужно ввести поправочный коэффициент.
Раньше я позволял вводить корректирующую величину. Это ошибка за 24 часа. Затем код делит её на 24 часа и корректирует время для каждого цикла.
Это может повысить точность, если вы сохраните в коде переменную миллисекунд для корректировки.
В коде уже есть переменная миллисекунд, но я ценю вашу идею более сложного решения. Однако, поскольку автор вопроса не умеет программировать, это сложнее, чем использовать micros(), как предлагается в другом месте, и в данном случае слишком сложно., @the busybee
Ваш генератор Arduino слишком медленный из-за:
(24 часа - 6 минут) / 24 часа = (24 * 60 - 6 минут) / (24 * 60 минут) = 0,995833333 (около 0,4%).
После изменения постоянного периода на 994 осциллятор стал слишком быстрым:
(24 часа + 30 секунд) / 24 часа = (24 * 60 * 60 + 30 секунд) / (24 * 60 * 60 секунд) = 1,00034722222 (около 0,03%).
Вы можете настроить константу периода на некоторое следующее целое число, 995 или 996.
Согласно вашему дополнительному вопросу, вы рассматриваете использование микросекунд для повышения точности. Боюсь, это вам не поможет, поскольку неточность связана с аппаратным обеспечением. В зависимости от температуры и напряжения питания частота будет меняться. Для более точной работы вам потребуется другой подход.
В любом случае, вот необходимые изменения для использования микросекунд:
- Замените вызов
millis()наmicros()там, где он используется для времени, в первом оператореloop(). - Умножьте константу
периодана 1000, в миллисекунде 1000 микросекунд:const unsigned long period = 1000000; - Переименуйте переменные времени
startMillisиcurrentMillisвstartMicrosиcurrentMicros. Это не обязательно для работающей программы, но необходимо для чтения кода человеком.
Затем можно начать корректировать постоянный период. Будьте готовы к многократным повторениям корректировки.
И, пожалуйста, не расстраивайтесь, если оборудование не оправдает ваших ожиданий. Недаром цифровые часы используют кварцевый генератор с подстройкой частоты или получают время из внешних, гораздо более точных источников.
Бро, можешь добавить строку в мой оригинальный код, чтобы добавить задержку в 15 секунд через каждые 12 часов? Таким образом, часы будут отставать на 30 секунд в течение 24 часов., @jagpal singh
Когда я использую 995, он теряет более 30 секунд, но с 994 он выигрывает 30 секунд. Мне нужно 994,5, это невозможно., @jagpal singh
@jagpalsingh Именно поэтому я добавил способ использования микросекунд. Пожалуйста, примените предложенные изменения., @the busybee
Братан, я сделал, как ты сказал. Изменил константу на 994500, теперь жду 24 часа, чтобы увидеть результат. 1000000×1000÷994,5, @jagpal singh
Спасибо, братан, ты молодец, у меня это работает., @jagpal singh
Как отметил hcheung в комментарии, не стоит ожидать, что будет удобно
Точность, обеспечиваемая функциями millis() или micros() платы Arduino. Это связано с тем, что
Эти функции используют источник тактовой частоты Arduino, который для Nano
керамический резонатор. Такие резонаторы, как правило, имеют значительный дрейф,
Это не проблема, так как можно откалибровать дрейф. Проблема
что скорость дрейфа не постоянна: в зависимости от температуры и
случайные изменения внутри резонатора, он ускоряется и замедляется в
несколько непредсказуемым образом (частично предсказуемым, если вы следите за
(температура). Arduino с кварцевым тактированием дал бы гораздо лучшие результаты.
Более подробную информацию по этой теме, включая фактическое измерение точности, можно найти здесь.
рекомендую отличный пост в блоге Тактовая частота Arduino
точность, Йорис ван Рантвейк.
В качестве решения hcheung рекомендует использовать что-то вроде DS3231 RTC, и я поддерживаю эту рекомендацию.
Если же точность вас не интересует, и вы хотите откалибровать
В любом случае, часы Arduino будут смещаться, поэтому я предлагаю вам использовать RTClib от Adafruit
библиотека. Помимо поддержки реальных чипов RTC, таких как DS3231, эта
Библиотека предоставляет «мягкие» RTC в классе RTC_Micros.
Этот класс реализует ту же логику, которую вы используете для продвижения вашего
часы, за исключением того, что они делают это правильно (ваша логика немного ошибочна).
Кроме того, класс имеет метод adjustDrift(), который делает
Именно такой тип корректировки дрейфа вы пытаетесь реализовать.
Параметр метода — это поправка на дрейф в ppm (частях на миллион),
где положительная коррекция ускоряет ход часов. Шесть минут в день.
составляет около 4000 ppm.
Вот упрощённая версия вашего скетча, основанная на RTC_Micros. Для
Для простоты я исключил код, управляющий миганием светодиода и временем.
корректировка.
#include <RTClib.h>
#include <SevSeg.h>
const int clockDriftCorrection = +4000; // в ppm
RTC_Micros rtc; // программные RTC
SevSeg Display;
void setup()
{
rtc.begin(DateTime()); // начало в 12:00
rtc.adjustDrift(-clockDriftCorrection);
Display.begin(/* display settings... */);
Display.setBrightness(100);
}
void loop()
{
DateTime now = rtc.now();
Display.setNumber(now.twelveHour() * 100 + now.minute());
Display.refreshDisplay();
}
Хорошо, но теперь мои часы показывают то же самое точно, что и часы на телефоне, нет ни секунды смещения за последние 18 часов., @jagpal singh
- Вопрос по 6-проводному 3-разрядному 7-сегментному дисплею и Arduino
- Библиотека Parola и часы DS3231
- Arduino nano + 4x 7-сегментный дисплей + 74HC595 — включены только точки
- 7 сегмент 4 цифры не показывающие числа 2,3 и 0
- Использование 4-значного 7-сегментного дисплея на Arduino Nano
- Выход TPIC6B595 не может обеспечить подачу питания на 7-сегментный дисплей
- avrdude ser_open() can't set com-state
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
Вы можете использовать
micros()вместоmillis()для более точной калибровки, но не ждите слишком большой точности от керамического резонатора Nano., @Edgar BonetЕсли вам нужна более высокая точность, вы можете приобрести такой модуль, как [DS3231](https://www.amazon.sg/s?k=ds3231&ref=mr_referred_us_sg_sg), который имеет гораздо более точную тактовую частоту., @hcheung
Я использую готовый код, но не знаю программирования. Подскажите, пожалуйста, как автоматически настроить 30 секунд после 24 часов с помощью редактирования кода., @jagpal singh