GPS приемники можно использовать не только для определения местоположения, но и для получения сигналов точного времени. В статье я покажу как настроить сервер точного времени, использующий в качестве источника GPS и работающий с точностью до нескольких микросекунд. В качестве примера я использую приемник Garmin и ОС FreeBSD, но статья также будет полезна обладателям Linux и Windows.
UPD: сервер доступен по адресу stratum1.net Веб-морда:
www.stratum1.net.
Подобный топик на хабре уже
пробегал, но я считаю, что тему надо раскрыть гораздо подробнее: многие важные детали автор опустил.
1. Немного теории
По оценке журнала GPS World, сейчас в мире находится в использовании более миллиарда приёмников GPS, и более 90% из них используются только для получения сигналов точного времени. [19]
Для определения собственных трехмерных координат GPS-приемник рассчитывает расстояние до 4-х спутников. Это расстояние вычисляется путем измерения времени прохождения радиосигнала от спутника. Т.к. скорость света составляет 3×10
8 м/с, то время прохождения сигнала очень мало, и для расчета требуется очень точная синхронизация хода часов на спутнике и приемнике. Поэтому каждый спутник GPS оборудован атомными часами с точностью хода 1 нс/сут, а приемник обеспечивает точность времени около 50 нс [17]. Для определения времени приемнику достаточно получить сигнал с одного спутника (
tanenn).
Таким образом, можно получать точное время с GPS-приемника. Ведь часы компьютера не являются особо точными, не говоря уже о свитчах, IP-камерах и т.д. Но зачем нужен GPS, если можно синхронизироваться по протоколу NTP, например, с pool.ntp.org?
- если у системы нет доступа в Интернет;
- если вам нужна высокая точность времени — единицы микросекунд (мкс);
- если вам нужно синхронизировать распределенную систему от надежного источника времени;
- просто ради интереса :)
2. GPS-приемник
GPS-приемник можно использовать практически любой — главное, чтобы он поддерживал стандартный протокол NMEA 0183. Протокол
NMEA служит для передачи GPS-информации простыми ASCII-строками по последовательному интерфейсу, такому как RS-232. Вместе с географическими координатами NMEA передает еще и точное время, как правило, раз в секунду.
Точность времени, полученного от обычного GPS-приемника, может составлять до нескольких миллисекунд (мс), однако она сильно зависит от модели приемника: обычно передача NMEA сообщений не является приоритетной задачей для приемника, поэтому точность может быть не очень хорошей.
Если вы хотите обеспечить еще большую точность — до нескольких микросекунд, необходимо использовать GPS-приемник, который умеет выдавать сигнал
PPS (
Pulse per second). PPS-импульс повторяется раз в секунду с очень большой точностью и может быть считан ntpd.
Ниже я рассмотрю оба варианта: сначала обычный NMEA и более подробно PPS.
3. Получение времени от GPS (без PPS)
3.1 Настройка GPS и ntpd
Windows администраторы могут установить порт ntpd для Windows и следовать указаниям в
этой статье.
Для Linux и FreeBSD инструкции одинаковы:
- Подключите GPS-приемник к COM-порту сервера (USB переходник тоже должен сработать).
- Создайте символическую ссылку /dev/gpsX на устройство (например, у меня /dev/cuau0 -> /dev/gps0).
- В ntp.conf добавьте строку
server 127.127.20.0 mode 0 prefer iburst minpoll 4 maxpoll 6
Строка 127.127.20.0 означает, что мы используем локальный источник времени, драйвер 20 (NMEA Generic), устройство /dev/gps0.
Если ваше устройство работает на скорости отличной от 4800 бит/c, необходимо задать скорость с помощью команды mode: 0 — 4800 бит/c (по умолчанию, можно не указывать), 16 — 9600, 32 — 19200 и т.д.
iburst — ускоряет инициализацию;
minpoll n — минимальный интервал опроса в 2n секунд, минимум 4, т.е. 16 с;
maxpoll n — максимальный интервал опроса в 2n секунд, максимум 17, около полутора суток;
prefer — предпочитаемый сервер.
Более подробные сведения можно найти в замечательной документации ntpd..
- Перезапустите сервер. Запустите ntpq -p. В списке должна быть строка GPS_NMEA(0)… Если этого не произошло, обратитесь к п. 5 «Возможные проблемы».
3.2 Проверка и коррекция
Проблема заключается в том, что приемник может посылать данные о времени с запозданием. Также не стоит забывать о задержке при передаче NMEA-сообщений. Для того, чтобы скорректировать эту задержку, добавьте в ntp.conf надежный NTP-сервер stratum-1 с параметром prefer и перезапустите ntpd.
Для проверки нам потребуется использовать команду ntpq -p. Формат выдачи:
На каждой строке идет информация об источнике времени, будь то NTP-сервер или локальный источник времени.
Первый символ в строке — статус выбора:
* — выбранный источник,
+ — насколько я понял, кандидат для выбора — на него переключится система в случае отказа основного источника,
o — PPS-источник, пробел — не работающий источник,
— x и др. — «забракованные» (ненадежные) источники.
Далее идут:
remote — имя узла или IP-адрес;
refid — ID источника (имя драйвера или адрес сервера, с которым синхронизируется источник);
stratum: 0 для первичного источника времени (GPS), 1 для сервера к нему подключенного, 2 для сервера, который синхронизируется с сервером stratum 1 и т.д.;
t — тип: l — локальные часы, u — сетевой узел и т.д.;
when — время с последней передачи;
poll — интервал опроса log
2 секунд, т.е. если poll=4, сервер опрашивает источник раз в 2
4 = 16 секунд;
reach — восьмеричное число, показывающее успешность последних 8 попыток передачи. Например, 0 — ни одной успешной попытки, 377
8=11111111
2 — все попытки успешны. После запуска ntpd, если все в порядке источник проходит значения reach 0, 1, 3, 7, 17, 37, 77, 177, 377;
delay — время следования пакета;
offset — разница между временем источника и локальным;
jitter — джиттер или иными словами дисперсия (разброс) времени прохождения пакета.
Больше всего нас будет интересовать символ статуса выбора, reach, offset и jitter. Reach должен быть равен 377, а offset и jitter быть как можно меньше.
Запустите команду ntpq -p. Дождитесь пока offset NTP-сервера не станет достаточно низким.
remote refid st t when poll reach delay offset jitter
==============================================================================
*mail.mobatime.r .DTS. 1 u 5 377 1 14.894 -3.198 0.490
xGPS_NMEA(0) .GPS. 0 l 2 377 7 0.000 -955.90 31.554
Выбранный ntpd сервер отмечен
*, в то время как наш GPS-приемник помечен как плохой (x). Offset GPS-приемника составляет около -956 мс. По всей видимости, информация передается о предыдущей секунде. Чтобы скорректировать это отставание необходимо под строкой server 127.127.20.0… добавить строку:
fudge 127.127.20.0 time2 0.956
Теперь можно снова сделать GPS предпочитаемым сервером. После перезапуска сервера перед GPS_NMEA(0) должна появиться
*.
4. Получение времени от GPS с сигналами PPS
4.1 Подключение приемника Garmin 18x LVC
Для себя я выбрал приемник
Garmin 18x LVC с точностью PPS-импульса ±1 мкс. Это OEM-приемник, у него нет красивого экранчика, но его удобно использовать в собственных приложениях.
Этот приемник передает данные на COM-порт и требует питания 5В, 90 мА, поэтому его будет удобно запитать от USB. Нам понадобится разъем «мама» DB9 или COM-кабель, разрезанный пополам, а также разрезанный кабель USB для питания. Родной разъем приемника тоже нужно отрезать — это не повлияет на гарантию. Схема соединения:
желтый провод — с pin 1 (PPS)
белый провод — с pin 2 (передача)
зеленый провод — с pin 3 (прием)
оба черных провода — с черным проводом USB и pin 5 (земля)
красный провод — с красным проводом USB (+5В).
Желательно
припаять контакты. Простая скрутка может и не заработать (впрочем, я не проверял).
Вдохновившись статьями [2] и [3] я пошел еще дальше и добавил в схему подключения предохранитель, светодиод «питание», светодиод «PPS» и резисторы для светодиодов. Умельцы-электронщики вполне могут уместить все в вилке COM-кабеля, у меня же получилась целая коробочка.
Я купил готовую макетную плату, розетки DB-9 и USB тип B, винтовые клеммники (родной разъем BM06B-SRSS-TBT или SM06B-SRSS-TB я в продаже не нашел), предохранитель 1А и держатель. Как смог припаял все это, а разъемы приклеил Epoxy :)
В принципе, так заморачиваться необязательно. Можно просто соединить жилы от GPS, COM и USB, как сделано
здесь.
4.2 Настройка Garmin 18x LVC
Для повышения производительности и надежности желательно настроить приемник. Это можно сделать, посылая команды через терминал (см.
мануал) или с помощью Windows-утилиты
SNSRCFG. Я выбрал второй путь.
Подключаемся к приемнику:
Comm → Setup: устанавливаем COM-порт, Baud rate: manual, 4800.
Comm → Connect
Программа должна загрузить текущую конфигурацию.
Настраиваем:
Config → Sensor Configuration
Необходимо убедиться, что PPS включен и увеличить длину импульса до 200 мс.
Также можно попробовать отключить DGPS — мы им пользоваться не будем, и установить Fix Mode = 2D — в теории это позволит приемнику работать при трех видимых спутниках вместо четырех. Однако не ручаюсь, что эти две опции на что-то влияют.
Выбираем NMEA-сообщения:
Config → NMEA Sentence Selection
NTPd понимает GPRMC и GPGGA сообщения. Чтобы снизить время передачи данных, я оставил только GPGGA.
4.3 Настройка FreeBSD и ntpd
Поддержка PPS во FreeBSD присутствует довольно давно, поэтому PPS здесь настраивается проще и работает точнее. Пользователи Linux могут обратиться к статье
Using a Garmin GPS 18 LVC as NTP stratum-0 on Linux 2.6. Настройки написанные ниже относится к FreeBSD.
Для включения поддержки PPS необходимо
пересобрать ядро системы с опцией:
options PPS_SYNC
NTP-сервер уже присутствует в системе, но не лишним будет обновить. Для FreeBSD делаем это из портов:
cd /usr/ports/net/ntp
make install clean
Теперь необходимо добавить в rc.conf строки:
ntpd_enable="YES"
ntpd_program="/usr/local/bin/ntpd"
ntpd_program указывает на путь установки ntpd из портов.
Создайте символическую ссылки /dev/gpsX и на /dev/ppsX устройство (например, у меня /dev/cuau0 -> /dev/gps0). Можно воспользоваться командой ln или добавить соответствующие строки в /etc/devfs.conf:
link cuau0 gps0
link cuau0 pps0
В документации NTP рекомендуется с GPS получать только PPS-импульсы для точного хода часов, а само время — с другого сервера stratum 1. Для этого необходимо добавить в /etc/ntp.conf несколько (4-5)
серверов stratum 1 и наш PPS, например:
server ntp.mobatime.ru prefer iburst maxpoll 9
server ntp1.vniiftri.ru iburst maxpoll 9
server ntp2.vniiftri.ru iburst maxpoll 9
server 127.127.22.0 minpoll 4
fudge 127.127.22.0 flag3 1
Драйвер 22 отвечает за PPS. flag3 включает режим коррекции времени ядра (
kernel discipline). В документации ntpd
написано, что включать kernel discipline совсем не обязательно: ntpd будет работать точнее, если просто выставить minpoll 4. Однако у меня получается как раз наоборот: с flag3 часы идут точнее — так что я предлагаю вам поэкспериментировать с этим параметром самостоятельно.
Можно пойти другим путем: получать и время с GPS и сигналы PPS:
server 127.127.20.0 prefer minpoll 4
fudge 127.127.20.0 flag1 1 flag3 1
flag1 включает PPS, flag3 — kernel discipline.
Это позволит получать время без использование Интернета, но в этом случае скорее всего понадобится коррекция (аналогично п. 3.2).
После внесения изменений необходимо перезапустить ntpd:
/etc/rc.d/ntpd restart
Запустите команду ntpq -p (подробнее о ней рассказано в п. 3.2). Если вы получаете только PPS сигнал, то вывод должен приблизительно быть таким:
remote refid st t when poll reach delay offset jitter
==============================================================================
xnut.rsuitb.ru 5.89.176.137 3 u 21 64 377 2.074 41.522 5.869
+mx.kr-pro.ru 62.117.76.138 2 u 34 64 377 4.167 0.336 0.423
+wooster.rojer.p 195.54.192.55 3 u 25 64 377 70.609 9.523 0.262
x193.124.4.177 7.123.225.33 3 u 21 64 377 2.133 56.525 9.041
ntp1.vniiftri.r .INIT. 16 u - 512 0 0.000 0.000 0.000
xntp2.vniiftri.r .PPS. 1 u 39 64 377 73.585 -14.117 0.189
*mail.mobatime.r .DTS. 1 u 17 64 377 15.223 0.147 0.843
oPPS(0) .PPS. 0 l 5 16 377 0.000 -0.001 0.002
Перед PPS(0) должно стоять «o», reach в течении пары минут дойти до 377. Остальные сервера используются для получения времени.
Если вы получаете с GPS еще и NMEA-информацию, то
remote refid st t when poll reach delay offset jitter
==============================================================================
*GPS_NMEA(0) .GPS. 0 l 11 16 17 0.000 -9.795 14.537
Перед GPS_NMEA(0) должна стоять
*.
Не лишним будет проверить статус PPS. Это можно сделать с помощью команд ntpdc -c kerninfo или ntptime. ntptime дает немного более подробную информацию:
ntptime
ntp_gettime() returns code 0 (OK)
time d24065e8.9067dfac Wed, Oct 12 2011 23:15:52.564, (.564085545),
maximum error 4739 us, estimated error 1 us, TAI offset 0
ntp_adjtime() returns code 0 (OK)
modes 0x0 (),
offset 2.004 us, frequency -28.979 ppm, interval 256 s,
maximum error 4739 us, estimated error 1 us,
status 0x2107 (PLL,PPSFREQ,PPSTIME,PPSSIGNAL,NANO),
time constant 4, precision 0.001 us, tolerance 496 ppm,
pps frequency -28.979 ppm, stability 0.019 ppm, jitter 1.434 us,
intervals 313, jitter exceeded 195, stability exceeded 0, errors 1.
На что нужно смотреть:
ntp_gettime() и ntp_adjtime() должны возвращать «OK».
в status должны быть флаги PPSFREQ, PPSTIME, PPSSIGNAL, и не должно быть PPSWANDER, PPSJITTER, PPSERROR.
jitter exceeded показывает количество импульсов, пришедших не совсем вовремя. Беспокоиться стоит, если значение jitter exceeded станет слишком большим, и в статусе появится флаг PPSJITTER.
intervals — количество интервалов калибровки, должно увеличиваться на единицу раз в
interval секунд (в примере 256 с)
stability exceeded — число слишком больших коррекций времени, 0 — всё в порядке.
errors — количество PPS импульсов, не пришедших вообще или пришедших совершенно не вовремя, не должно увеличиваться во время работы.
stability — чем меньше, тем стабильнее работает PPS-источник и часы сервера. Должно быть меньше 0.1.
jitter —
джиттер PPS-импульсов. Должен быть несколько микросекунд (us), не больше.
5. Возможные проблемы и отладка
5.1 Don't panic!
Всегда учитывайте, что GPS-приемнику требуется некоторое время, чтобы установить свое местоположение после включения: до получаса для старых моделей, 45 секунд для Garmin 18x. Это время зависит от того, насколько долго приемник был выключен (
tanenn). ntpd также требуется определенное время для коррекции хода часов. По моим наблюдениям: 10-20 секунд чтобы «увидеть» приемник, 20-30 минут чтобы offset снизился до оптимального значения. Если ваш reach после нескольких минут работы установился в 377, а offset сокращается (по модулю) — то все в порядке.
5.2 ntpd не видит приемник
Если ntpd не видит приемник: reach в ntpq -p застыл на нуле, — необходимо тщательно проверить подключение приемника к серверу. Остановите ntpd и откройте COM-порт в терминале. В FreeBSD:
cu -l /dev/gps0 -s 4800
Connected
$GPGGA,160042,5545.7890,N,03722.6113,E,1,08,0.9,188.3,M,13.3,M,,*47
$GPGGA,160043,5545.7890,N,03722.6114,E,1,08,0.9,188.3,M,13.3,M,,*41
|ччммсс|---широта--|--долгота---| ^^
|число спутников
...
где /dev/gps0 файл устройства, 4800 — скорость передачи данных.
Если приемник подключен правильно, должны «посыпаться» NMEA-сообщения. Убедитесь, что приемник «видит» спутники. В сообщении GPGGA число спутников должно быть 4 или больше, а перед этим числом должна стоять единица. Если у вас включены сообщения GPRMC, то после времени, должен идти символ «A».
Чтобы выйти из cu нажмите «Enter», затем "~", затем ".".
Если NMEA-сообщения говорят о том, что приемник не видит спутники, необходимо переместить его в зону уверенного приема. Лучше всего, чтобы приемник мог обозревать всё небо. Мой Garmin можно устанавливать и на крыше, но путем экспериментов я приклеил его в такое место на окне, где он видит спутники круглосуточно.
Изучите логи ntpd. Возможно стоит установить самую свежую версия сервера.
Если NMEA-сообщения не приходят вообще, убедитесь, что скорость передачи данных от приемника, соответствует ожидаемой ntpd. Проверьте работоспособность COM-порта и подключения приемника к нему.
Убедитесь, что общая длина кабеля от порта до приемника не превышает 5 м. В противном случае, вам придется заморачиваться и делать дифференциальную линию для передачи сигнала для защиты от помех. Рекомендуется экранирование кабеля GPS соединить с экранированием USB-кабеля.
5.3 ntpd не видит сигнал PPS
Опять же проверьте подключение, например с помощью вольтметра или осцилографа. Я использую карманный дешёвый осциллограф DSO Nano. Так выглядит PPS сигнал:
Также удобно использовать
RealTerm: он показывает и NMEA-сообщения и сигнал PPS раз в секунду на линии DCD.
Не используйте переходники USB-COM: PPS сигнал через них может не идти или идти с задержкой. Как правило, COM-порт всегда присутствует на материнской плате, просто он может быть не выведен на стенку корпуса.
5.4 Большой offset/jitter
Убедитесь в том, что вы скорректировали принимаемое время, как описано в 3.2. Если настройки приемника позволяют отключите все NMEA-сообщения, кроме одного из: $GPRMC, $GPGLL, $GPGGA, $GPZDA или $GPZDG. Если вы используете только PPS, можно отключить все сообщения.
Попробуйте выключить буфферизацию COM-порта. Установите в /boot/device.hints:
hint.sio.0.flags="0x2"
Посмотрите, нет ли новых версий прошивки для вашего GPS-приемника. (
Garmin 18x LVC Firmware download)
Очевидной идеей является повышение скорости передачи данных. Но согласно
документации ntpd это нам ничем не поможет. Скорость лучше оставить 4800.
Возможно стоит попробовать изменить системный таймер ОС. В FreeBSD можно прописать в /etc/sysctl.conf:
kern.timecounter.hardware=i8254
У меня offset стал «прыгать», когда кондиционер в серверной стал постоянно то включаться, то выключаться.
График зависимости offset PPS и температуры, когда температура стабильна:
Когда кондиционер безобразничает:
Из графика видно, что offset зависит от температуры воздуха в помещении. Связано это, видимо, с несовершенством таймера на сервере. Способы устранения этой проблемы описаны
здесь и
здесь.
«Хардварным» способом является замена генератора на материнской плате на термокомпенсированный (TXCO). Но это вариант для гуру микроэлектроники и паяльника.
6. Подготовка NTP-сервера к использованию
Перед публикацией сервера в сеть, прочитайте разделы документации, касающиеся
установки прав доступа и
ограничения количества запросов.
Если вы хотите создать NTP-сервер для локальной сети, то можно добавить адрес сервера в параметры DHCP. Однако у меня есть подозрения, что на Windows-клиентах эта опция не работает, а на *nix dchpclient нужно настраивать на каждой машине.
Часто просто подменяют в DNS time.windows.com локальным NTP-сервером :) Теперь все Windows-компьютеры будут долбиться на наш сервер.
Список клиентов можно посмотреть командой ntpdc -c monlist.
Также написал небольшой
скрипт для
Zabbix, отслеживающий параметры reach/offset/jitter PPS и выбранного сервера времени. Запуск скрипта нужно добавить в zabbix_agentd.conf:
UserParameter=ntp.pps_jitter,/usr/local/bin/php /usr/local/share/zabbix/ntp_zabbix.php pps jitter
UserParameter=ntp.pps_offset,/usr/local/bin/php /usr/local/share/zabbix/ntp_zabbix.php pps offset
UserParameter=ntp.pps_reach,/usr/local/bin/php /usr/local/share/zabbix/ntp_zabbix.php pps reach
UserParameter=ntp.source_jitter,/usr/local/bin/php /usr/local/share/zabbix/ntp_zabbix.php source jitter
UserParameter=ntp.source_offset,/usr/local/bin/php /usr/local/share/zabbix/ntp_zabbix.php source offset
UserParameter=ntp.source_reach,/usr/local/bin/php /usr/local/share/zabbix/ntp_zabbix.php source reach
Перезапустите агент. На сервере соответственно нужно добавить эти item'ы для NTP-сервера. Теперь можно настраивать триггеры и графики.
7. Другие способы синхронизации времени
Помимо NMEA ntpd поддерживает еще массу более экзотических устройств (см.
полный список).
Стоит отметить, в первую очередь, возможность синхронизации часов по радиосигналу. Например, в России работает служба
RWM, из Франкфурта в Германии вещает станция DCF77. DCF77 неплохо ловится в европейской части России (у меня в Москве уверенный прием). Подружить DCF77 и ntpd несложно, см.
статью. Точность такого решения будет ниже, однако оно дешевле варианта с GPS в несколько раз: нужно только купить антенну, никаких знаний радиотехники здесь не требуется.
Умельцы могут настроить синхронизацию по импульсам радио «Маяк» в конце каждого часа. Длина последнего шестого импульса зависит от текущего часа. Но такой способ будет явно хуже по точности, чем обычная синхронизация времени по Интернету.
Точное время можно получать от оператора сотовой связи (
hellt). Такая «фича» называется NITZ. Однако не все операторы и не все GSM-устройства её поддерживают. Я проверил свои GSM-модемы Siemens MC55 и Arduino GPRS-shield на чипе SIM900 — таких AT-команд в этих устройствах нет.
Существуют также готовые NTP-сервера с датчиками GPS или ГЛОНАСС, но они, понятно, стоят гораздо дороже.
Список работающих российских публичных серверов statum 1
ntp1.vniiftri.ru
ntp2.vniiftri.ru
ntp4.vniiftri.ru
ntp.mobatime.ru
ntp0.ntp-servers.net
ntp1.ntp-servers.net
ntp2.ntp-servers.net
ntp0.zenon.net
gps-time.prao.psn.ru
ntp.ix.ru
Свой сервер я постараюсь сделать открытым, как только разберусь с правами доступа. stratum1.net.
Литература
Отсортировано по «полезности»:
- Документация ntpd
- Adding a FreeBSD NTP server based on an GPS 18 LVC device
- Using a Garmin GPS 18 LVC as NTP stratum-0 on Linux 2.6
- NTP Reference Clocks Using FreeBSD 7.0
- Stratum 1 NTP, Garmin GPS 18 LVC on FreeBSD 8.0 (зеркало)
- Time synchronization with a Garmin GPS
- PPS Synchronization (NTP FAQ)
- Stratum One Time Servers
- Prof. David R. Andersen: NTP Temperature Compensation
- NTP temperature compensation
- Network Time Protocol server using PC gnu/linux and freebsd
- LinuxPPS NTPD support
- The Kernel Discipline
- Why does the clock on my computer keep incorrect time? (FreeBSD FAQ)
- Система точного времени NTP
- Network Time Protocol (NTP) в конце приведены ссылки на RFC и списки рассылок.
- Пять идей, лежащих в основе GPS
- DFC77 receiver
- Чем опасны дешёвые GPS-глушилки