GPS 授时时钟:低成本高精度的 Arduino 卫星校时方案
项目简介
摆脱 RTC 模块漂移与 NTP 依赖网络的局限,利用超低成本 GPS 接收模块 (GY-GPS6MV2, u-blox NEO-6M) 解析 NMEA 语句,直接获取 UTC 时间、日期、速度、海拔、卫星数等信息,驱动 I2C LCD 显示,构建一款“永不漂移”的台式/车载时钟。硬件成本极低,代码简洁,适合入门学习 GPS 解析与串口通信。
硬件清单
| 组件 | 数量 | 备注 |
|---|---|---|
| Arduino UNO | 1 | |
| GY-GPS6MV2 (u-blox NEO-6M) | 1 | 3.3V/5V 兼容,自带天线 |
| I2C LCD (2004 或 1602) | 1 | 带 PCF8574 模块,地址 0x27/0x3F |
| 面包板 + 杜邦线 | 1套 |
接线表
| GPS 模块 | Arduino | LCD (I2C) | Arduino |
|---|---|---|---|
| VCC | 5V | VCC | 5V |
| GND | GND | GND | GND |
| TX | D8 (SoftwareSerial RX) | SDA | A4 |
| RX | D7 (SoftwareSerial TX) | SCL | A5 |
软件库
Adafruit_GPS:专用 NMEA 解析库 (库管理器搜索安装)SoftwareSerial:IDE 自带,模拟串口读取 GPSWire+LiquidCrystal_I2C:I2C LCD 驱动
核心代码逻辑
#include
#include
#include
#include
LiquidCrystal_I2C lcd(0x3F, 20, 4); // 地址 0x3F 或 0x27
SoftwareSerial mySerial(8, 7); // RX=8, TX=7
Adafruit_GPS GPS(&mySerial);
int timezone = +1; // 东一区 (北京/柏林),UTC+1,中国为 +8
void setup() {
lcd.init(); lcd.backlight();
Serial.begin(115200);
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // 开启 RMC+GGA 语句
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1Hz 更新率
GPS.sendCommand(PGCMD_ANTENNA); // 天线状态
delay(1000);
}
uint32_t timer = millis();
void loop() {
char c = GPS.read();
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA())) return;
}
if (millis() - timer > 2000) { // 2秒刷新一次显示
timer = millis();
// 串口调试输出
Serial.print("Time: "); /* 打印 UTC 时间 */
// LCD 显示本地时间
lcd.setCursor(5,0);
int hour = GPS.hour + timezone;
if (hour >= 24) hour -= 24;
if (hour < 10) lcd.print('0');
lcd.print(hour); lcd.print(':');
if (GPS.minute < 10) lcd.print('0');
lcd.print(GPS.minute); lcd.print(':');
if (GPS.seconds < 10) lcd.print('0');
lcd.print(GPS.seconds);
// 日期
lcd.setCursor(5,1);
if (GPS.day < 10) lcd.print('0');
lcd.print(GPS.day); lcd.print('.');
if (GPS.month < 10) lcd.print('0');
lcd.print(GPS.month); lcd.print('.');
lcd.print(GPS.year);
if (GPS.fix) { // 定位成功才显示扩展信息
// 速度转换:节 → km/h (1 knot = 1.852 km/h)
float speed_kmh = GPS.speed * 1.852;
lcd.setCursor(0,2);
lcd.print(speed_kmh, 1); lcd.print(" km/h ");
// 风力等级 (复用速度字段演示)
if (speed_kmh <= 1) lcd.print("Wind calm");
else if (speed_kmh <= 9) lcd.print("Light air");
else if (speed_kmh <= 46) lcd.print("Breeze");
else if (speed_kmh <= 56) lcd.print("Strong wind");
else if (speed_kmh <= 74) lcd.print("Gale");
else if (speed_kmh <= 83) lcd.print("Storm");
else if (speed_kmh <= 102) lcd.print("Heavy storm");
else lcd.print("Hurricane");
// 海拔
lcd.setCursor(0,3);
lcd.print("Alt: "); lcd.print(GPS.altitude); lcd.print("m");
// 卫星数
lcd.print(" Sat:"); lcd.print((int)GPS.satellites);
}
}
}
关键技术点解析
NMEA 语句与解析
$GPRMC:推荐最小定位信息 (时间、日期、经纬度、速度、航向)$GPGGA:定位质量、海拔、卫星数、HDOP- Adafruit_GPS 库自动校验校验和、解析字段、填充结构体
时区处理
GPS 输出均为 UTC。代码中 timezone 变量按整数小时偏移,中国标准时间 (CST) 为 +8。注意跨日边界处理 (hour ≥ 24 减 24,hour < 0 加 24)。夏令时需自行扩展逻辑。
定位状态判断
GPS.fix(bool):是否有有效定位 (3D/2D Fix)GPS.fixquality:1=GPS, 2=DGPS, 0=无效GPS.satellites:参与定位卫星数,≥4 才能得出海拔
速度与海拔单位
GPS.speed:节 (knots, 海里/小时),×1.852 = km/hGPS.altitude:米 (相对 WGS84 椭球面)
实测效果与优化
- 冷启动首次定位约 30-60 秒 (需开阔天空),后续热启动 <5 秒
- 室内靠窗可定位,但卫星数少、精度差、海拔漂移大
- 显示刷新 2 秒一次平衡功耗与实时感;可改 1 秒并隐藏秒显示以适配 1602
- 配合 18650 电池 + 升压模块可做便携 GPS 表
对比:GPS vs DCF77 vs RTC vs NTP
| 方案 | 精度 | 成本 | 联网需求 | 室内可用 | 备注 |
|---|---|---|---|---|---|
| GPS (本项目) | ~微秒级 (UTC) | 极低 (~$5) | 无 | 靠窗可用 | 全球通用、自带日期/海拔/速度 |
| DCF77 (欧波) | ~毫秒级 | 中等 | 无 | 欧洲限定、易受干扰 | |
| DS3231 RTC | ±2ppm/年 (~1分钟/年) | 低 | 无 | 是 | 需定期校准、无自动授时 |
| NTP (WiFi/以太网) | ~毫秒级 | 中 (需模块) | 是 | 是 | 依赖网络、服务器可达性 |
扩展项目创意
- 车载行车记录仪时间戳同步
- 户外探险/航海专用多功能手表 (加电子罗盘、气压计)
- 移动测速雷达 (GPS 速度 + 超声波测距)
- 时间同步服务器 (GPS + PPS 脉冲输出校准本地网络设备)
- 日出日落计算器 (结合经纬度算法)
资源链接
- u-center 配置工具:u-blox 官网 (Windows 串口调试、固件升级、轨迹回放)
- NMEA 在线解码器:rl.se/gprmc
- Adafruit_GPS 库文档:GitHub
制造工艺
- DIY低成本手套控制器与螺旋桨小车:自制Arduino手部控制器
- DHT11 温湿度传感器项目:LED 指示与压电蜂鸣器报警
- 构建 GPS 数据记录器:结合 Azure IoT Hub 实现空间分析
- Arduino + DHT11 + 以太网盾板温湿度数据记录仪
- Arduino Due 驱动 3.2″ TFT 实现温度监测与实时时钟
- 模拟指针风格 POV 时钟:Arduino Nano + 17 LED + 霍尔传感器
- 光影交响:Arduino DIY 生日祝福灯光音乐装置
- u-blox LEA-6H GPS 模块:Arduino 与 Python 集成指南
- Arduino Nano 驱动 128x64 OLED 实时运行康威生命游戏 (元胞自动机)
- Arduino 高速转速计 - 单次检测算法实测 6.5MHz 级响应,红外 + 红激光方案
- eDOT:基于 Arduino 的精密时钟与气象站,内置红外遥控
- DIY 吉他高速拨片与踏板 - 3D 打印电机驱动拨片制作指南