回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

Beetle树莓派RP2350 - GPS桌面时钟 简单

头像 无垠的广袤 2025.05.29 32 0

GPS桌面时钟

 

本文介绍了 RP2350 通过 MicroPython 编程实现桌面 GPS 卫星授时时钟的项目设计。

 

项目介绍

 

包括串口连接测试、原始 NMEA 数据捕获、库函数调用与格式转换、获取 GPS 卫星授时数据、OLED 显示等流程。

 

硬件连接

 

示意图

 

connect_gp02.jpg

 

GP-02

GP-02RP2350
RXGPIO0
TXGPIO1
VCC3V3
GNDGND

OLED

 

GP4 ---- SDA (OLED_SSD1306)

GP5 ---- SCL (OLED_SSD1306)

 

工程调试

 

包括串口读取 GP-02 模组原始数据、NVEA 数据解析,为之后的代码合并和调用作铺垫。

 

原始数据

 

串口连接 GP-02 模组,终端打印原始串口数据

 

代码

'''
Name: GPS module
Version: v1.0
Date: 2025.05
Author: ljl
Other: Acquiring origin GPS data and print them in Shell
'''

from machine import Pin, UART
import time

# initialize UART
gps_uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))

def read_gps_data():
    """ Read GPS data and print """
    if gps_uart.any():
        line = gps_uart.readline().decode('utf-8').strip()
        print(f"{line}")

while True:
    read_gps_data()
    time.sleep(0.05)

 

连接芯片,配置解释器,运行代码。

 

效果

 

终端打印原始 NMEA 数据

 

gps_print.gif

 

分别给出几种不同卫星定位系统的数据

 

gps_print.jpg

 

解析数据

 

使用 micropyGPS 库实现 GPS 原始 NMEA 数据解析,实现 GP-02 模组的快速开发和应用。

 

代码

'''
Name: GPS data translation
Version: v1.0
Date: 2025.05
Author: ljl
Other: Translate origin GPS data by micropyGPS library and print them in Shell
'''

from machine import UART,Pin
from micropyGPS import MicropyGPS
import time

# initialize UART configuration
gps_uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))

# initialize GPS translator
my_gps = MicropyGPS(8)  # east eight time zone

def update_gps():
    """ Read GPS module """
    while gps_uart.any():
        char = gps_uart.read(1)
        if char:
            my_gps.update(chr(char[0]))

def print_gps_data():
    """ print GPS data """
    if my_gps.date and my_gps.timestamp:
        date_str = f"{my_gps.date[2]}-{my_gps.date[1]:02d}-{my_gps.date[0]:02d}"
        time_str = f"{my_gps.timestamp[0]:02d}:{my_gps.timestamp[1]:02d}:{int(my_gps.timestamp[2]):02d}"
        latitude_str = f"{my_gps.latitude[0]:.6f} {my_gps.latitude[1]}"
        longitude_str = f"{my_gps.longitude[0]:.6f} {my_gps.longitude[1]}"
        speed_str = f"{my_gps.speed[2]:.2f} km/h"
        
        print(f"Date: {date_str}")
        print(f"Time: {time_str}")
        print(f"Latitude: {latitude_str}")
        print(f"Longitude: {longitude_str}")
        print(f"Speed: {speed_str}")
    else:
        print("Waiting for GPS data...")

while True:
    update_gps()
    print_gps_data()
    time.sleep(1)

 

效果

 

终端打印日期、时间、经纬度、速度信息

 

gps_translate_print.gif

 

 

流程图

 

flowchart_gps.jpg

 

工程代码

 

在前面获取 GP-02 模组数据并实现转换的基础上,进一步结合 OLED 和电池模块,实现桌面 GPS 授时时钟的设计。

 

'''
Name: GPS clock
Version: v1.0
Date: 2025.05
Author: ljl
Other: Acquiring GPS data and showing on OLED screen
include data, time, latitude, longtitude and speed.
The micropyGPS.py is necessary, see details to https://github.com/inmcm/micropyGPS/
'''

from machine import Pin, I2C, UART, ADC
import ssd1306
from micropyGPS import MicropyGPS
import time

# initialize I2C and OLED
sda = Pin(4)
scl = Pin(5)
i2c = I2C(0, sda=sda, scl=scl, freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)

# initialize UART
gps_uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))

# initialize GPS
my_gps = MicropyGPS(8)  # east eight time zone

# initialize ADC pin
adc = ADC(Pin(29))

def update_gps():
    """ Read data from GPS module """
    while gps_uart.any():
        char = gps_uart.read(1)
        if char:
            my_gps.update(chr(char[0]))

def display_data():
    """ Display Date on OLED """
    oled.fill(0)
    if my_gps.date and my_gps.timestamp:
        date_str = f"{my_gps.date[2]}-{my_gps.date[1]:02d}-{my_gps.date[0]:02d}"
        time_str = f"{my_gps.timestamp[0]:02d}:{my_gps.timestamp[1]:02d}:{int(my_gps.timestamp[2]):02d}"
        latitude_str = f"{my_gps.latitude[0]:.3f} {my_gps.latitude[1]}"
        longitude_str = f"{my_gps.longitude[0]:.3f} {my_gps.longitude[1]}"
        speed_str = f"{my_gps.speed[2]:.1f} km/h"
        
        oled.text('Date: '+date_str, 0, 0)
        oled.text('Time: '+time_str, 0, 10)
        oled.text('LAT: '+latitude_str, 0, 20)
        oled.text('LON: '+longitude_str, 0, 30)
        oled.text('Speed: '+speed_str, 0, 40)
    else:
        oled.text("Waiting for GPS...", 0, 0)
    oled.rotate(0)
    oled.show()

def print_gps_data():
    """print GPS data"""
    if my_gps.date and my_gps.timestamp:
        date_str = f"{my_gps.date[2]}-{my_gps.date[1]:02d}-{my_gps.date[0]:02d}"
        time_str = f"{my_gps.timestamp[0]:02d}:{my_gps.timestamp[1]:02d}:{int(my_gps.timestamp[2]):02d}"
        print(f"Date: {date_str}, Time: {time_str}")
        print(f"Latitude: {my_gps.latitude[0]:.6f} {my_gps.latitude[1]}")
        print(f"Longitude: {my_gps.longitude[0]:.6f} {my_gps.longitude[1]}")
        print(f"Altitude: {my_gps.altitude} m")
        print(f"Speed: {my_gps.speed[2]} km/h")
        print(f"Course: {my_gps.course} degrees")
        print(f"Satellites in view: {my_gps.satellites_in_view}")
        print(f"Satellites in use: {my_gps.satellites_in_use}")
        print(f"HDOP: {my_gps.hdop}")
        print(f"VDOP: {my_gps.vdop}")
        print(f"PDOP: {my_gps.pdop}")
    else:
        print("Waiting for GPS data...")

# parameters of voltage divide resistor
R1, R2 = 1000000, 1000000 # 1M 
Vref_BAT = 3.9 # battery voltage in full charged state

def get_battery_level():
    ''' measure battery voltage by ADC '''
    adc_value = adc.read_u16()
    voltage = (adc_value / 65535) * 3.3
    DIV_RATIO = (R1 + R2) / R1
    actual_voltage = voltage * DIV_RATIO  # voltage division compensation
    percent = min(max((actual_voltage - 3.3) / (Vref_BAT - 3.3) * 100, 0), 100)
    return percent, actual_voltage

def BAT_display(percent,x,y,width,height):
    ''' battery percent, icon position and size (x,y,width,height) '''
    oled.fill_rect(x,y,width+2,height+16,0) # part clear
    oled.text('{:.0f}%'.format(percent), width+6+x, y)
    # draw battery icon
    oled.rect(0+x, 0+y, width, height, 1) # frame (x,y,width,height)
    oled.rect(width-1+x, int(height/3)+y, 3, int(height/3), 1)  # anode
    oled.fill_rect(2+x, 2+y, int((width-4) * percent / 100), height-4, 1) # electric percent column
    oled.rotate(0)
    oled.show()

while True:
    update_gps()
    display_data()
    print_gps_data()
    percent, voltage = get_battery_level()
    BAT_display(percent,0,52,30,9)
    print('Battery Voltage: {:.2f} V, Battery Level: {:.1f}%'.format(voltage,percent))
    time.sleep(1)

 

运行代码,确认执行无误后,将代码文件上传至芯片根目录。

 

效果演示

 

连接锂电池供电,显示 GPS 数据,包括日期、时间、经纬度、速度、电池电量信息。

gps_clock_battery.jpg
gps_clock_GP02.jpg

 

动态效果(每秒刷新一次)

 

gps_clock.gif

 

同时终端打印 GPS 数据与电池电量信息

 

gps_clock_print.gif

 

室外测试

 

室外环境或窗边,等待 30 秒左右,可获取到位置信息

gps_module_night.jpg

读取经纬坐标信息,输入网络地图,可得到相应的地理位置

gps_clock_test_night.jpg

将上述采集得到的经纬坐标 (121,31) 输入网址 经纬度定位 ,点击 查询 按钮,可获得对应的地理位置

gps_local.jpg

定位结果与实际位置 (121.45,31.03) 较为接近

gps_module_night.gif

 

总结

 

本文介绍了 Beetle RP2350 通过 MicroPython 编程实现桌面 GPS 卫星授时时钟的项目设计,为 RP2350 的快速开发和应用提供了参考。

评论

user-avatar