LC29H(XX) GPS/RTK HAT

Try to add a 15cm metal plate under the antenna
I tried it outside with a saw blade as plate a while ago. It didn't have any significant measurable effect on my antenna, which came with the standard package. I think I have to measure it over a longer period of time and then calculate an average. That would be the most valid method. What did you do with the long cable? Shorten it or leave it as it is?
 
Today I tested my new GPS Quectel YB0017AA antenna with my LC29H-DA Breakout-Board
First observation: The signal strength of the satellites is much higher than with the cheap antenna.
Second observation: The RTK-FIX achieved much faster (after about 100 seconds).
Third observation: During my walk around the garden, there were no RTK fix dropouts.
Resume: Receiver 33€, antenna 24€ from AliExpress together with my SAPOS Account gives my a
RTK functionality . I think it is the cheapest solution. Thx @Bernard for the hint with the antenna.
I did the walk through the garden with my windows laptop running teh QGNNS SW- Next step is to mount the antenna on top of my RoπLawnMow
and test my python SW on the pi. I'll keep you informed

1761912171253.png
 

Attachments

  • Sat_view.png
    Sat_view.png
    201.1 KB · Views: 4
  • RTK_Map.png
    RTK_Map.png
    35.2 KB · Views: 3
Leave as it , but need to put it as far as possible from motor or DC/DC regulator
Hi Bernard, sorry that I am disturbing you again.
I played around a bit with the LC29H-BS board today. My impression is that the command set is smaller than that of the DA module.
For example, I couldn't even manage to set a different baud rate. But the command $PQTMCFGSVIN,W,2,0,0.0,-2472446.4619,4828304.1363,3343730.2653*34 was acknowledged with $PQTMCFGSVIN,OK*70. So that shows me that the base-station know where it is. The other commands, as described in this blog, don't send an acknowledgment to the terminal window, only the Firmware query is working propperly. Which C++ code are you using in Base Station?
Have you had similar experiences? How long did it take for your rover to recognize an RTK_Fixed signal?
Thanks in Advanced for your Answer.
Best Regards Ulli
 
Leave as it , but need to put it as far as possible from motor or DC/DC regulator
Hi @Bernard, today I had success with the configuration of the RTK-Base-Station in combination with a Raspberry Pi and python as language.
The challenge is to configure / find the absolute Position of the Base Station.
I did it in this way: antenna is installed and has clear view to the sky. First I connect the antenna to the rover modul. The rover speaks with my SAPOS Service, wait until the RTK-Fixed is available and i saved Lat and Lon and alt.
Now I used the same antenna and connected it to the LC29H-BS Modul, loaded the saved Lat lon and alt into the code and run the base-station.
Now I start my Rover-script with the Quectel YB0017AA antenna. After some seconds I got a RTK-Float and after one or two Minutes I got an RTK-Fixed. The position of the detected Lat lon has an offset of around 3 meters. So I think I have to play a little with parameters in the
$PQTMCFGSVIN,W,2,0,0.0,3879099.1095,591052.6521,5011529.9782*2C command.
But great is, that I have the RTK-Rover and the RTK-Base up and running. Now the rest seems that finetuning is needed.
For anyone interested in the Python code of the base station.I have a few more ideas to optimize it.

Python:
#!/usr/bin/env python3
import serial, socket, threading, time, math, sys, os
from datetime import datetime

# === Konfiguration ===
SERIAL_PORT = "/dev/ttyUSB0"
BAUDRATE = 115200
TCP_PORT = 2102           # Port, über den Rover sich verbinden

# Feste Position deiner Basisstation
BASE_LAT = 48.13743
BASE_LON = 11.57549
BASE_ALT = 64.12

# === Globale Variablen ===
clients = []
stop_flag = False

# === Hilfsfunktionen ===
def log(msg):
    now = datetime.now().strftime("%H:%M:%S.%f")[:-3]
    print(f"[{now}] {msg}")

def calc_x_y_z(lat, lon, alt):
    """WGS84 → ECEF (XYZ)"""
    a = 6378137.0
    e2 = 6.69437999014e-3
    lat_r = math.radians(lat)
    lon_r = math.radians(lon)
    N = a / math.sqrt(1 - e2 * math.sin(lat_r)**2)
    x = (N + alt) * math.cos(lat_r) * math.cos(lon_r)
    y = (N + alt) * math.cos(lat_r) * math.sin(lon_r)
    z = (N * (1 - e2) + alt) * math.sin(lat_r)
    return x, y, z

def nmea_checksum(sentence):
    """Berechnet NMEA-Checksumme"""
    csum = 0
    for c in sentence:
        csum ^= ord(c)
    return f"*{csum:02X}"

def send_cmd(ser, cmd):
    """Sendet ASCII-Befehl mit automatischer Prüfsumme"""
    if "*" not in cmd:
        base = cmd.split("$")[1]
        cmd = f"${base}{nmea_checksum(base)}"
    ser.write((cmd + "\r\n").encode())
    log(f"[TX] {cmd}")
    time.sleep(0.2)

# === Initialisierung LC29H ===
def init_lc29_base(ser):
    """Setzt LC29H-DA in Basis-Mode"""
    log("=== LC29HDA Basis Init Start ===")

    # Berechne ECEF-Koordinaten
    x, y, z = calc_x_y_z(BASE_LAT, BASE_LON, BASE_ALT)
    log(f"[BASE POS] LAT={BASE_LAT:.7f}, LON={BASE_LON:.7f}, ALT={BASE_ALT:.2f}")
    log(f"[BASE POS] X={x:.4f}, Y={y:.4f}, Z={z:.4f}")

    # Standort (ECEF) schreiben
    send_cmd(ser, f"$PQTMCFGSVIN,W,2,0,0.0,{x:.4f},{y:.4f},{z:.4f}")

    # Antenne aktivieren, Ausgabe einschalten
    send_cmd(ser, "$PQTMCFGRTCM,W,1,1,1,1,1,1,1,1,1,1")  # alle RTCM aktivieren
    #send_cmd(ser, "$PQTMCFGMSG,0,1,0,0,0,0,0")           # nur RTCM-Ausgabe
    send_cmd(ser, "$PQTMVERNO")
    log("[DONE] LC29HDA ready and transmitting RTCM ✓")

# === RTCM Listener ===
def rx_thread(ser):
    """Liest RTCM von LC29H und verteilt sie an Clients"""
    global stop_flag
    buffer = b""
    while not stop_flag:
        try:
            chunk = ser.read(1024)
            if not chunk:
                continue
            buffer += chunk

            # RTCM frames starten immer mit 0xD3
            while len(buffer) > 2:
                if buffer[0] != 0xD3:
                    buffer = buffer[1:]
                    continue
                if len(buffer) < 3:
                    break
                length = ((buffer[1] & 0x03) << 8) | buffer[2]
                if len(buffer) < 3 + length + 3:
                    break
                frame = buffer[:3 + length + 3]
                buffer = buffer[3 + length + 3:]

                if len(frame) < 6:
                    continue
                msg_type = ((frame[3] & 0xFC) << 4) | (frame[4] >> 4)
                log(f"[RTCM3] Type {msg_type:<4} | Size {len(frame)} bytes")

                # An alle verbundenen Rover senden
                for c in clients.copy():
                    try:
                        c.sendall(frame)
                    except Exception:
                        clients.remove(c)
        except Exception as e:
            log(f"[RX ERROR] {e}")
            time.sleep(1)

# === TCP-Server für Rover ===
def tcp_server():
    """TCP Server, der RTCM an Rover streamt"""
    global clients
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(("0.0.0.0", TCP_PORT))
    s.listen(1)
    log(f"[SERVER] RTCM TCP Server läuft auf Port {TCP_PORT}")
    while True:
        conn, addr = s.accept()
        log(f"[SERVER] Neuer Rover verbunden: {addr}")
        clients.append(conn)

# === Main ===
def main():
    ser = serial.Serial(SERIAL_PORT, BAUDRATE, timeout=1)
    init_lc29_base(ser)
    threading.Thread(target=tcp_server, daemon=True).start()
    rx_thread(ser)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        log("Beendet durch Benutzer.")
        stop_flag = True
        sys.exit(0)
 
The challenge is to configure / find the absolute Position of the Base Station.
I don't understand.

To find the absolute position of your base station, simply connect your base station to Qgnss and read the value.
Leave the LC29HBS powered ON for at least 24Hours to have a perfect location.
 
I don't understand.

To find the absolute position of your base station, simply connect your base station to Qgnss and read the value.
Leave the LC29HBS powered ON for at least 24Hours to have a perfect location.
so the values in the lat lon and alt field after 24Hours operation?
okay that would be easy. is this documented in a Quectel Guide?
 
I don't understand.

To find the absolute position of your base station, simply connect your base station to Qgnss and read the value.
Leave the LC29HBS powered ON for at least 24Hours to have a perfect location.
Now I found the quectel_lc29hbs_gnss_protocol_specification_v1.pdf and started the survey-in-process. Hope I have a result after the process is finished. 💪
 
Now I found the quectel_lc29hbs_gnss_protocol_specification_v1.pdf and started the survey-in-process. Hope I have a result after the process is finished. 💪
Here the 2 protocol for base and rover module:
 

Attachments

Back
Top