How is your reception lately? (WSPR, ADS-B, SatNOGS, etc.)

Status Update: Stepping back for today! :sweat_smile:

  • What went right: Successfully built the wired direct connection to the NEC Debian host and got the serial data pipeline nicely structured.

  • Where it went wrong: But wait—the Heltec V3 is refusing to cooperate properly, and after diving head-first into a pointless troubleshooting rabbit hole with AI, I am officially stuck in the mud and unable to move an inch!

Bailing out for today and calling it quits. Time to step away before things get worse!

Does the discussion on the RadioLib GitHub page help with any useful information?

1 Like

Any details of this?

1 Like

Here are the details of my struggle with the Heltec V3 yesterday! :joy:

  • What went right: Building the wired direct connection to the NEC Debian host and structuring the serial data pipeline went completely smoothly.

  • Where it went wrong (The Rabbit Hole):

    1. Tried flashing the Heltec V3 via esptool, but hit a version mismatch/missing stub JSON in the system Python environment.

    2. Reinstalled esptool via pip, but then it started throwing device reports readiness to read but returned no data right after Connecting......

    3. Tried manual BOOT button timing tricks, but after wrestling with the AI in circles, I officially hit a brick wall and waved the white flag to step away!

  • Current status: Taking a breather and checking out the RadioLib GitHub. Anyone else run into weird serial quirks with ESP32-S3 boards?

1 Like

I initially ran into issues, but was able to fix these with help of AL. I have now updated the code with bug-fixes in my following post: However the most important part to Dynamically set frequency is missing. Also the frequency in this code i 433.1, which need to be modified to frequency of LoRa satellite passing over your city.

https://discussions.flightaware.com/t/how-is-your-reception-lately-wspr-ads-b-satnogs-etc/100643/103

 

 

Hello everyone!

I would like to share my setup for tracking and receiving LoRa satellite downlinks using a low-cost, compact node.

1. Hardware Stack

  • MCU/Radio: Heltec WiFi LoRa 32 (V3) featuring ESP32-S3 and onboard SX1262.

  • Host Machine: Linux (NEC machine running Python, MQTT broker, and Skyfield).

  • Connection: USB Serial (/dev/ttyUSB0 via CP210x, 115200 bps).

2. Key Hardware Gotchas & Fixes (for Heltec V3)

Getting the SX1262 on the Heltec V3 to initialize properly required a few specific configurations in RadioLib:

  • Power: Vext (GPIO 36) must be pulled LOW to supply power to the RF section.

  • TCXO: Voltage must be explicitly set to 1.8V.

  • RF Switch: DIO2 must be enabled as an RF switch (radio.setDio2AsRfSwitch(true)).

  • Explicit SPI Initialization: SPI.begin(9, 11, 10, 8); with module pins mapped to (8, 14, 12, 13).

3. Software Architecture

  • Orbit Calculation (sat_commander.py): Uses Skyfield with local TLE data (CelesTrak amateur group) to calculate pass events (Rise, Culmination, Set) for target satellites (e.g., NETSAT-1) based on observer location (Hirosaki, Japan).

  • MQTT & Serial Bridge (mqtt_serial_bridge.py): Listens to the heltec/control MQTT topic and translates target parameters into serial commands (SET,FREQ:<val>,BW:<val>,SF:<val>).

  • Firmware (sketch.ino): Parses incoming serial commands dynamically and applies real-time frequency adjustments (crucial for tracking Doppler shifts) using RadioLib while continuously monitoring for downlink packets with RSSI/SNR feedback.

4. Arduino Firmware Snippet

C++

#include <RadioLib.h>

SX1262 radio = new Module(8, 14, 12, 13);

void setup() {
  Serial.begin(115200);
  while(!Serial);
  delay(1000);
  
  // Power up Vext and initialize SPI
  pinMode(36, OUTPUT);
  digitalWrite(36, LOW);
  delay(100);
  SPI.begin(9, 11, 10, 8);

  // Initialize RadioLib with 1.8V TCXO
  int state = radio.begin(435.6, 125.0, 9, 5, 0x34, 10, 8, 1.8);
  if (state == RADIOLIB_ERR_NONE) {
    radio.setDio2AsRfSwitch(true);
    radio.startReceive();
  }
}

void loop() {
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil(10);
    command.trim();
    if (command.startsWith("SET")) {
      // Parse and apply frequency/BW/SF dynamically for Doppler tracking
      parseAndApplyCommand(command);
    }
  }

  // Packet reception check
  if (radio.getPacketLength() > 0) {
    String recvStr = "";
    if (radio.readData(recvStr) == RADIOLIB_ERR_NONE) {
      // Log packet, RSSI, and SNR
    }
    radio.startReceive();
  }
  delay(10);
}

This setup bridges orbital calculation directly down to a low-cost embedded LoRa receiver, enabling smooth real-time parameter tuning for satellite passes. Feedback or suggestions are always welcome!
I hope to share a follow-up report once I successfully capture a pass!
73!

:warning: Current Status Note: Please note that this is an interim report. While I have successfully verified the hardware initialization, MQTT-to-serial bridging, and dynamic parameter tuning, I have not yet confirmed actual reception or decoding of live LoRa satellite downlinks in the field.

2 Likes

Mini Update:

Managed to get the virtual environment and skyfield sorted out on the Linux host (Debian), and finally booted up both the MQTT-to-serial bridge and the orbit commander script!

As you can see in the terminal screenshot below, the bridge is successfully hooked up to /dev/ttyUSB0 listening on heltec/control, and the tracker has successfully pulled the TLE data, showing upcoming passes (like AO-7 starting around 16:55 JST).

Fingers crossed—I’m hoping to test out actual live tracking. To be honest, I’m a bit skeptical if that tiny stock antenna bundled with the kit can actually pull in a signal, but I’m excited to find out!

Any thoughts or advice as I step into the live test phase are always welcome. 73!

1 Like

@SHIRAKAMI :+1: :+1: :+1:

I have partial success, i.e. suceeded in flashing heltec so that

(1) It is tuned to receive 433.5 Mhz
(2) Conects to LAN on WiFi
(3) Can connects to MQTT server on Debian Server, either via USB C and tty/USB0 or through LAN
(4) Can connects MQTT server on RPi through WiFi

What it Lacks is automatic tuning and adjustment for Dopler effect through Skyfield. I am in total darkness as to how accomplish this.

 

1 Like

Hi @abcd567!

Thanks for sharing your setup! To be honest, I’m still feeling my way through the dark myself, but that’s precisely what I’m working on right now!

My approach is using a Python script on the host PC with skyfield to calculate the orbit and Doppler shift, and then publishing frequency updates via MQTT (paho-mqtt) to the Heltec over /dev/ttyUSB0 (or Wi-Fi).

I’ve just updated my script into a persistent monitoring loop and am waiting for the next satellite pass to test it out live. Once I get it running smoothly, I’d be happy to share the python script and logic! 73!

1 Like

Basically, I would think the way it’s done is: from the message preamble you get an estimate of the Doppler frequency error. Then when you get the message data you apply a frequency correction in the demodulation process. I think the tuning parameters are published for the particular satellite you are tracking.

SIMULATION to prove Hardware & Software are working OK

 

 

1 Like

Congratulations @abcd567! That simulation setup looks fantastic!

Thanks for sharing your progress. Here in my shack, I’m diving back in today to fine-tune my configuration and scripts with my AI collaborator (Gemini). Let’s keep making progress! 73!

My unit is just blinking its orange LED, and the tiny display is staying completely dark… Still troubleshooting on my end! :sweat_smile:

At what level does the simulation work? Is a simulated satellite signal generated and input to your receiver? Or is it something else?

A python script, running on RPi, generates it and pushes it to heltec v3 LoRa board through MQTT server running on RPi

sudo python3 simulate_pass.py

Contents of file simulate_pass.py

import time
import json
import paho.mqtt.client as mqtt
import serial

# ==================== CONFIGURATION ====================
# Toggle between 'MQTT' or 'SERIAL' depending on what you are testing
TEST_MODE = 'MQTT'


# Serial Settings (Used if TEST_MODE = 'SERIAL')
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 115200

# MQTT Settings (Used if TEST_MODE = 'MQTT')
MQTT_BROKER = "192.168.12.24"  # Your Raspberry Pi IP
MQTT_PORT = 1883
MQTT_TOPIC_FREQ = "sat_tracker/frequency"
# =======================================================

BASE_FREQ_HZ = 433500000  # 433.500 MHz

print(f"--- Launching Satellite Doppler Pass Simulation ({TEST_MODE} Mode) ---")

ser = None
mqtt_client = None

if TEST_MODE == 'SERIAL':
    try:
        ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=0.1)
        print(f"[SUCCESS] Connected to Heltec on {SERIAL_PORT}")
    except Exception as e:
        print(f"[ERROR] Serial connection failed: {e}")
        exit(1)
elif TEST_MODE == 'MQTT':
    try:
        mqtt_client = mqtt.Client()
        mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60)
        mqtt_client.loop_start()
        print(f"[SUCCESS] Connected to MQTT Broker at {MQTT_BROKER}")
    except Exception as e:
        print(f"[ERROR] MQTT connection failed: {e}")
        exit(1)

# Pass sweep array (+10 kHz to -10 kHz)
simulated_shifts = [10000, 8000, 6000, 4000, 2000, 0, -2000, -4000, -6000, -8000, -10000]
simulated_elevations = [5, 15, 30, 45, 65, 80, 65, 45, 30, 15, 5]

try:
    for shift, elevation in zip(simulated_shifts, simulated_elevations):
        target_frequency = BASE_FREQ_HZ + shift
        print(f"Simulating -> Elevation: {elevation}° | Doppler Shift: {shift:+} Hz | Tuning Radio to: {target_frequency} Hz")

        if TEST_MODE == 'SERIAL':
            payload_str = f"FREQ:{target_frequency}\n"
            ser.write(payload_str.encode('utf-8'))

        elif TEST_MODE == 'MQTT':
            payload_data = {
                "satellite": "SIMULATED_CUBE_SAT",
                "status": "VISIBLE",
                "elevation": elevation,
                "target_freq_hz": target_frequency
            }
            mqtt_client.publish(MQTT_TOPIC_FREQ, json.dumps(payload_data))

        time.sleep(2) # Step every 2 seconds

    print("\n--- Simulation Sweep Completed! Satellite dropped below horizon. ---")

except KeyboardInterrupt:
    print("\nSimulation aborted.")
finally:
    if ser:
        ser.close()
    if mqtt_client:
        mqtt_client.loop_stop()




1 Like

Update: Success! :tada:

After some troubleshooting with the firmware and flashing, the display is finally alive and showing “LoRa Gateway” correctly!

I’ve now integrated it with an automated Linux server pipeline (using Skyfield for satellite pass calculation, an MQTT-serial bridge, and SQLite logging) running persistently via systemd. Everything is fully automated now—ready to track AO-7 passes without manual terminal intervention!

Thanks for all the inspiration, and good luck with your setups! 73!

This is NOT simulation. It is actual trial run

 

 

1 Like

Right now, I’m just using that tiny stock antenna attached to the unit… but I suppose this little guy won’t be enough to actually pull in satellite signals, right? :grinning_face_with_smiling_eyes: What kind of antenna setup are you using?

Same for me. Currently I am also using the tiny stock antenna .

1 Like

Are you kidding me?
Even if you’re actually using that tiny stock antenna, you wouldn’t be trying to use it indoors… right? :grinning_face_with_smiling_eyes: