Live Ground Station Preview
A web-based simulation of my Python (Tkinter + Matplotlib) telemetry tool. Actively plots dynamic RSSI/SNR data, parses hex payloads, and validates configuration.
Hardware Debugging
During prototype testing, I found severe thermal issues with the SX1280 transceiver, which began overheating whenever output power exceeded +10 dBm.
// Root Cause Analysis
Performing analysis to trace the reflection loss revealed that the PCB manufacturer errors resulted in 30 Ω RF traces on a design matched for 50 Ω. This massive VSWR mismatch caused the RF energy to reflect back and dissipate as extreme heat within the IC.
To mitigate the trace losses on the compromised boards, I recommended and outlined the specifications for integrating an external transmit-path Power Amplifier (PA). This would ensure the system hits its EIRP target without stressing the primary transceiver's internal amplifier.
Link Budget Analysis
To guarantee telemetry reception at a 20km range (65,000+ feet), I performed a comprehensive 2.4 GHz link budget analysis, evaluating Free Space Path Loss (FSPL) and rocket plume attenuation.
With the SX1280 receiver sensitivity at -116 dBm (SF8/406kHz), the initial calculation yielded a critical -9.6 dB margin deficit.
// Recovery Solution:
I mathematically modeled a reconfiguration to SF12/200kHz to improve base sensitivity, and specified the integration of a receive-path Low Noise Amplifier (LNA) yielding +12 dB gain to push the final link margin into the positive.
Bare-Metal Firmware Driver
Instead of relying on heavy abstractions or third-party libraries, I developed a bare-metal C driver from scratch for the Semtech SX1280.
- Register-level radio configuration and initialization.
- Hardware FIFO data buffering and parsing logic.
- Interrupt-driven packet handling (DIO pins).
Low-level SPI transactions were optimized to avoid RTOS scheduler blocking. I implemented precise hardware timeout handling (`HAL_TIMEOUT`) and busy-wait polling (`SX1280_WaitForReady`) to ensure transaction integrity without halting other crucial avionic tasks.
static SX1280_Status_t SX1280_SPI_TransmitReceive(uint8_t *pTxData, uint8_t *pRxData, uint16_t size)
{
HAL_StatusTypeDef hal_status;
/* Wait for radio to not be busy before starting SPI transaction */
if (SX1280_WaitForReady(100) != SX1280_OK) return SX1280_TIMEOUT;
/* Set NSS low to select the radio */
HAL_GPIO_WritePin(sx1280_hal_config->nssPort, sx1280_hal_config->nssPin, GPIO_PIN_RESET);
if (pRxData == NULL) {
hal_status = HAL_SPI_Transmit(sx1280_hal_config->spiHandle, pTxData, size, SX1280_SPI_TIMEOUT_MS);
} else {
hal_status = HAL_SPI_TransmitReceive(sx1280_hal_config->spiHandle, pTxData, pRxData, size, SX1280_SPI_TIMEOUT_MS);
}
/* Set NSS high to deselect the radio */
HAL_GPIO_WritePin(sx1280_hal_config->nssPort, sx1280_hal_config->nssPin, GPIO_PIN_SET);
if (hal_status != HAL_OK) return SX1280_ERROR;
return SX1280_WaitForReady(100);
}