Точное время: синхронизация DS3231 RTC с GPS на Arduino Nano
Компоненты и материалы
- Arduino Nano R3 — 1 шт.
- Модуль часов DS3231 — 1 шт.
- GPS-модуль NEO-6M — 1 шт.
- Двунаправленный логический преобразователь уровней — 1 шт.
- LCD-дисплей 16×2 — 1 шт.
- I2C-модуль для LCD (backpack) — 1 шт.
- Розетки 0.1 дюйма: 15-пин (2 шт.), 6-пин (2 шт.), 4-пин (1 шт.), 5-пин (1 шт.)
- Пин-стрип 4-пин — 1 шт.
- Монтажная плата (stripboard) 24×37 — 1 шт.
- Резисторы 4.7 кОм — 2 шт.
- Тактильная кнопка (6 мм) — 1 шт.
О проекте
Мой DS3231 уходил. Обычно я обновлял его через системное время при компиляции, но это неточно из-за прерываний компиляции другими процессами на компьютере.
Узнав, что GPS выдает точное время (UTC) и дату, решил использовать его для настройки DS3231.
Схема подключения
I2C LCD backpack → Arduino:
- GND → GND
- VCC → 5V
- SDA → SDA (A4)
- SCL → SCL (A5)
DS3231 → Arduino:
- GND → GND
- VCC → 5V
- SDA → SDA (A4)
- SCL → SCL (A5)
Преобразователь уровней → Arduino:
- 5V → 5V
- GND → GND
- D3 → BUS
- D4 → BUS
NEO-6M GPS → преобразователь уровней:
- 3V → VCC
- GND → GND
- BUS → TXD (на D3)
- BUS → RXD (на D4)
Кнопка:
- Контакт 1 → D9
- Контакт 2 → GND
Питание
Питание через USB-кабель.
Программное обеспечение
99% кода — это парсинг из примера parsing.ino библиотеки Adafruit GPS. Добавлен код для передачи времени GPS в DS3231 и вывода времени на LCD.
Используемые библиотеки
- Adafruit GPS Library v1.0.3
- RTCLib by Adafruit v1.2.0
- NewLiquidCrystal для I2C backpack
Работа устройства
- Включите блок.
- LCD покажет текущие дату и время из DS3231.
- Подождите, пока GPS зафиксирует спутники.
- Нажмите кнопку для установки времени по GPS.
- LCD покажет новое время.
Ограничения
- GPS требует времени на захват спутников, индикатора захвата нет. Нажатие кнопки без фиксации установит дату 2000:0:0 и время 0:0:0.
- Лучше нажимать кнопку, когда красный светодиод на GPS начинает мигать — это может занять десятки минут (в помещении).
- Изначально батарея DS3231 была садящейся: при настройке дата становилась 2000:0:0, время 0:164:164. Потребовалось время зарядки батареи для корректной работы.
Особенности GPS-модуля
Купленный модуль просто назывался «NEO 6M GPS», на плате был стабилизатор 4A2D (3.3В), но не гарантировано, что линии связи тоже преобразованы. Поэтому использован преобразователь уровней.
Разные GPS-модули по-разному ловят сигнал в помещении, поэтому добавлен LCD для переноса на улицу.
Особенность LCD
Мой I2C-адрес 0x3F (большинство используют 0x27). Если ничего не видно — смените адрес.
Особенность библиотеки RTCLib
Библиотека устанавливает регистры времени и даты, но не регистр дня недели. День недели вычисляется формулой из даты. Это удобно — не нужно корректировать на високосные годы.
UTC и местное время
Для моего часового пояса корректировка UTC не требовалась. При необходимости добавьте код самостоятельно.
Ссылки
[1] Datasheet NEO-6M: https://www.u-blox.com/sites/default/files/products/documents/NEO-6_DataSheet_(GPS.G6-HW-09005).pdf
Исходный код
Код настройки DS3231 по GPS
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include
#include "RTClib.h"
RTC_DS3231 RTC;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const int days_string_length = 12;
// for lcd display
#include
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
#define button 9
#include
#include
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO false
boolean usingInterrupt = false;
void useInterrupt(boolean);
void setup() {
Serial.begin(115200);
Serial.println("Adafruit GPS library basic test!");
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
GPS.sendCommand(PGCMD_ANTENNA);
useInterrupt(true);
delay(1000);
mySerial.println(PMTK_Q_RELEASE);
lcd.begin(16,2);
lcd.backlight();
lcd.clear();
pinMode(button, INPUT_PULLUP);
}
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
#ifdef UDR0
if (GPSECHO) if (c) UDR0 = c;
#endif
}
void useInterrupt(boolean v) {
if (v) {
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
uint32_t timer = millis();
void loop() {
if (!usingInterrupt) {
char c = GPS.read();
if (GPSECHO) if (c) Serial.print(c);
}
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA())) return;
}
if (timer > millis()) timer = millis();
static bool second_time_round = false;
if (!digitalRead(button)) {
RTC.adjust(DateTime(GPS.year, GPS.month, GPS.day, GPS.hour, GPS.minute, GPS.seconds));
lcd.clear();
lcd.setCursor(2,0);
lcd.print("Pressed set");
delay(5000);
lcd.clear();
}
DateTime now = RTC.now();
lcd.setCursor(4,0);
lcd.print(now.year(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.day(), DEC);
lcd.print(' ');
lcd.setCursor(4,1);
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
lcd.print(" ");
}
Схемы


Производственный процесс
- Грунтовые винты (set screws): конструкция, отличия и применение
- Оставляя наследие: аутентичное лидерство для лучшего будущего
- SMRP выпускает стандартизированный набор KPI для профессионалов обслуживания и надежности
- Настройка среды разработки Java 10: сборка, компиляция и запуск
- Угольники: назначение, типы и применение в техническом черчении
- Плоское шлифование: традиционные техники для точности
- Почему токарный станок с коробчатыми направляющими — оптимальный выбор для точности и производительности
- Наборы кernenов (пробивок): полное руководство
- ЧПУ-токарные станки с линейными направляющими: точность, скорость, легкое производство
- Полное руководство по выбору правильного набора инструментов механика