Skip to content

Repository files navigation

STM32 & Python-Based Real-Time Telemetry & Ground Station System (V1.0)

STM32F446RE Language-C Language-Python Protocol-I2C Protocol-UART

A high-performance, real-time embedded telemetry system and ground station desktop software engineered for aerospace and defense benchmark requirements. The project features a deterministic firmware architecture implemented on an ARM Cortex-M4 microcontroller and a high-throughput Ground Station GUI written in Python.


Key System Architecture Features

  • Deterministic Non-Blocking Architecture: Hardware Timer (TIM2) drives a strict 50 Hz ($20\text{ ms}$) base sampling and transmission tick. Zero blocking delays (HAL_Delay or blocking I2C/UART transactions) inside Interrupt Service Routines to guarantee interrupt safety.
  • Timer-Driven IMU & Baro Sampling: Replaced EXTI line polling with a deterministic $50\text{ Hz}$ Hardware Timer flag mechanism (mpu_data_ready_flag and bmp_read_flag) to avoid pin noise and enforce synchronized frame generation.
  • Hybrid Firmware Driver Model: Utilizes STM32 HAL for system clock tree initialization alongside optimized bitwise shift (high << 8 | low) register extraction for raw sensor payloads.
  • Robust 40-Byte Fixed Binary Frame Protocol: Custom telemetry packet structure featuring a 2-byte frame synchronization header (0xAA 0x55), rolling sequence counter, payload identifier, and 16-bit CRC-CCITT verification.
  • Attitude & Environmental Estimation: Real-time Roll and Pitch calculation using a Complementary Filter fusing 6-DOF IMU data (MPU6050), alongside barometric pressure and temperature acquisition (BMP280).
  • High-FPS Desktop Ground Station: Built with PyQt6 and PyQtGraph to ensure sub-1% CPU usage at 50 FPS telemetry rates, integrated with an OpenGL 3D aircraft visualization view and automatic CSV data logging.

System Architecture & Data Flow Diagram

graph TD
    subgraph SENSORS ["Hardware Layer (I2C Bus @ 100 kHz)"]
        MPU["MPU6050 (6-DOF IMU)"]
        BMP["BMP280 (Baro & Temp)"]
    end

    subgraph MCU ["STM32F446RE Firmware Architecture"]
        ISR["TIM2 Hardware Timer ISR (50 Hz / 20 ms)<br/>• Sets volatile flags: mpu_read, bmp_read, send_telemetry"]
        
        subgraph MAIN_LOOP ["Deterministic Main Loop Priorities"]
            P1["1. Read MPU6050 Raw Payload"]
            P2["2. Read BMP280 Raw Payload (10 Hz)"]
            P3["3. Build Telemetry Packet & Calculate CRC-16"]
        end
        
        UART_TX["UART2 Peripheral (115200 Baud / 8N1)"]
    end

    subgraph GUI ["Python Ground Station (Desktop App)"]
        PARSER["Non-Blocking State Machine Parser<br/>• Header Check (0xAA 0x55)<br/>• Sequence Counter Verification<br/>• CRC-16 Validation"]
        
        subgraph DISP ["Real-Time Display & Storage"]
            G3D["3D Orientation View (OpenGL)"]
            G2D["2D Live Graphs (PyQtGraph)"]
            LOG["Automated CSV Logging"]
        end
    end

    MPU -->|Raw I2C Payload| P1
    BMP -->|Raw I2C Payload| P2
    ISR -->|Trigger Flags| MAIN_LOOP
    P1 --> P3
    P2 --> P3
    P3 -->|40-Byte Binary Frame| UART_TX
    UART_TX -->|Serial Data Stream| PARSER
    PARSER -->|Validated Data| G3D
    PARSER -->|Validated Data| G2D
    PARSER -->|Timestamped Data| LOG

    style SENSORS fill:#1f2937,stroke:#3b82f6,stroke-width:2px,color:#fff
    style MCU fill:#111827,stroke:#10b981,stroke-width:2px,color:#fff
    style GUI fill:#1e1b4b,stroke:#8b5cf6,stroke-width:2px,color:#fff

Loading

Hardware Pin Connections

Microcontroller Pin Peripheral / Module Signal Line Functional Description
PB6 I2C1 I2C1_SCL Serial Clock Line ($100\text{ kHz}$)
PB7 I2C1 I2C1_SDA Serial Data Line
PA2 USART2 USART2_TX Telemetry Transmit Line ($115200\text{ Baud}$)
PA3 USART2 USART2_RX Telemetry Receive Line (Reserved for V2.0)
+3.3V / GND Power Bus VCC / GND Common Power and Ground Rail

Telemetry Binary Frame Specification

To guarantee zero frame desynchronization and immediate packet loss detection, the network protocol enforces 1-byte struct alignment (#pragma pack(push, 1)):

$$\text{Frame Format}: \underbrace{[\text{HEADER}]}_{2\text{ Bytes}} + \underbrace{[\text{SEQ}]}_{2\text{ Bytes}} + \underbrace{[\text{LENGTH}]}_{1\text{ Byte}} + \underbrace{[\text{TYPE}]}_{1\text{ Byte}} + \underbrace{[\text{PAYLOAD}]}_{32\text{ Bytes}} + \underbrace{[\text{CRC16}]}_{2\text{ Bytes}} = 40\text{ Bytes}$$

Frame Memory Layout

 0x00      0x01      0x02      0x04      0x05      0x06                       0x26      0x28
+---------+---------+---------+---------+---------+--------------------------+---------+
|  0xAA   |  0x55   | SEQ_NUM | LENGTH  | TYPE    | PAYLOAD (32-Byte Floats) |  CRC16  |
| Header1 | Header2 | (uint16)|  (0x20) | (0x01)  | Accel, Gyro, Temp, Press | (uint16)|
+---------+---------+---------+---------+---------+--------------------------+---------+


Hardware-in-the-Loop (HIL) Verification & Testing

🎬 System Demonstration Video

Click the thumbnail below to watch the full system demonstration, featuring real-time 50 Hz telemetry streaming, 3D aircraft attitude synchronization, and zero-packet-loss verification:

STM32 & Python Telemetry Station Demo

📌 Note: If the video thumbnail does not load, you can watch the demonstration directly on YouTube via this link.

1. Physical Layer Analysis (Saleae Logic Analyzer)

Hardware signal integrity was verified on the physical I2C bus using a Saleae Logic Analyzer at a $24\text{ MHz}$ digital sampling rate:

Saleae Logic Analyzer I2C Verification

  • I2C Clock Verification: Stable $100\text{ kHz}$ SCL frequency validated.
  • Bus Protocol Integrity: Validated Start/Stop bit conditions, 7-bit slave addressing (0x68 for MPU6050, 0x76 for BMP280), and slave ACK responses without clock stretching or timeout bus lockups.

2. 30-Minute Continuous Stress Test ($T_0$ vs $T_{30}$)

To verify long-term stability and zero packet loss under continuous streaming, a 30-minute stress test was executed. The results were logged directly to telemetry_data_log.csv.

Test Benchmark ($T = 0\text{ min}$) Test Benchmark ($T = 30\text{ min}$)
Ground Station T0 Ground Station T30
Timestamp: 09:35:43 | Lost Packets: 0 Timestamp: 10:05:43 | Lost Packets: 0

Verification Matrix Summary

Test Parameter Targeted Value Measured / Verified Value Status Verification Method
I2C SCL Frequency $100\text{ kHz}$ $100.0\text{ kHz}$ PASSED Saleae Logic Analyzer Waveform
I2C Bus ACK/NACK Hardware ACK $100%\text{ ACK Response}$ PASSED Saleae Protocol Decoder
Telemetry Rate $50\text{ Hz}\ (20\text{ ms})$ $50.0\text{ Hz}\ (\pm 0.1\text{ Hz})$ PASSED Hardware TIM2 ISR & GUI FPS Counter
Stress Test Duration $30\text{ Minutes}$ $30\text{ Minutes}\ (1800\text{ s})$ PASSED System Clock & CSV Timestamp Delta
Total Transmitted Packets $90,000\text{ Frames}$ $90,000\text{ Frames}$ PASSED Continuous SEQ_NUM Counter
Packet Loss Rate $0.00%$ 0 Lost Packets PASSED Parser State Machine Tracking
CRC-16 Checksum Errors $0\text{ Errors}$ 0 Errors PASSED Software CRC-CCITT Verification

Repository File Structure

├── firmware/
│   ├── Core/
│   │   ├── Inc/
│   │   │   ├── config.h          # Global defines, Telemetry struct, CRC-16 inline utility
│   │   │   ├── mpu6050.h         # MPU6050 driver header & raw data structures
│   │   │   ├── bmp280.h          # BMP280 driver header & trimming parameters
│   │   │   └── main.h            # HAL imports and system function prototypes
│   │   └── Src/
│   │       ├── main.c            # Entry point, TIM2 ISR flag handling, while(1) scheduling
│   │       ├── mpu6050.c         # MPU6050 I2C burst read & register bit-shift extraction
│   │       └── bmp280.c          # BMP280 trimming math & compensation implementation
│   └── Firmware.ioc              # STM32CubeMX Project Configuration File
├── ground_station/
│   ├── ground_station.py         # PyQt6 Desktop GUI & Serial State Machine Parser
│   └── baykar_bayraktar_tb2.glb  # 3D CAD Aircraft Model
├── docs/
│   ├── i2c_saleae_verification.png
│   ├── ground_station_gui_t0.png
│   └── ground_station_gui_t30.png
├── telemetry_data_log.csv        # 30-minute validation CSV log
└── README.md                     # System Engineering Documentation


Build & Execution Guide

Firmware Setup (STM32)

  1. Open STM32CubeIDE and import the firmware/ directory.
  2. Ensure compiler flags include -O2 optimization and Hardware FPU enabled (-mfpu=fpv4-sp-d16 -mfloat-abi=hard).
  3. Compile and flash the binary to the STM32F446RE Nucleo via ST-LINK.

Ground Station Setup (Python)

  1. Install Python dependencies:
pip install PyQt6 pyqtgraph PyOpenGL pyserial trimesh numpy
  1. Run the Ground Station application:
python ground_station/ground_station.py
  1. Select the active ST-LINK COM port, set Baud Rate to 115200, and click Start Telemetry.

Future Roadmap (V2.0 Upgrades)

  • UART RX Ring Buffer: Circular buffer implementation for non-blocking ground-to-air command parsing.
  • UART TX DMA Integration: Offload UART frame serialization to DMA channels to reduce CPU usage.
  • Independent Watchdog (IWDG): Hardware fault recovery and dynamic I2C bus-reset sequences on bus lockup.
  • Sensor Fusion Upgrade: Extended Kalman Filter (EKF) integration for noise-immune attitude estimation.
  • RF Wireless Link: Replace wired UART link with SPI-based NRF24L01 or LoRa modules.

Releases

Packages

Contributors

Languages