Skip to main content

r_d_inclita_sofware/telemetry/
lora.rs

1use crate::telemetry::data;
2use defmt::{error, info};
3use embassy_stm32::gpio::Output;
4use embassy_stm32::mode::Blocking;
5use embassy_stm32::spi::Spi;
6use embassy_time::{Delay, Duration, Ticker};
7use sx127x_lora::LoRa;
8#[embassy_executor::task]
9
10pub async fn lora_task(
11    spi: Spi<'static, Blocking, embassy_stm32::spi::mode::Master>,
12    cs: Output<'static>,
13    reset: Output<'static>,
14) {
15    info!("Initializing RFM95 LoRa Module...");
16    const FREQUENCY: i64 = 868;
17
18    let mut lora = match LoRa::new(spi, cs, reset, FREQUENCY, Delay) {
19        Ok(radio) => radio,
20        Err(_) => {
21            // We throw away the specific error payload and just panic cleanly via defmt
22            defmt::panic!("Failed to initialize RFM95 LoRa module!");
23        }
24    };
25
26    // 1. Set Maximum Bandwidth (500 kHz)
27    // Valid options for RFM95: 125_000, 250_000, or 500_000 Hz.
28    let _ = lora.set_signal_bandwidth(500_000);
29
30    // 2. Set Lowest Spreading Factor (SF7)
31    // Default is often SF9 or SF10. SF7 is the fastest standard LoRa setting.
32    // Every step down roughly halves your Time on Air!
33    let _ = lora.set_spreading_factor(7);
34
35    // 3. Set the lowest Coding Rate (4/5)
36    // This is the error-correction overhead. 4/5 means for every 4 bits of data,
37    // 1 parity bit is sent. It's the lowest overhead setting.
38    let _ = lora.set_coding_rate_4(5);
39
40    // 17 dBm - max power lol
41    let _ = lora.set_tx_power(17, 1);
42
43    let mut tx_buffer = [0u8; 255];
44
45    // Create a Ticker that fires exactly 5 times per second (every 200ms)
46    let mut ticker = Ticker::every(Duration::from_hz(5));
47
48    loop {
49        let packet = {
50            let guard = data::LATEST_TELEMETRY.lock().await;
51            guard.clone()
52        }; // Guard goes out of scope here, freeing the lock for the sensors!
53
54        // 2. Serialize to bytes
55        if let Ok(payload_len) = postcard::to_slice(&packet, &mut tx_buffer).map(|b| b.len()) {
56            // 3. Transmit the packet!
57            match lora.transmit_payload(tx_buffer, payload_len) {
58                Ok(size) => info!("Transmitted {} bytes at 5Hz", size),
59                Err(_) => error!("LoRa Transmission Failed!"),
60            }
61        }
62
63        // 5. Wait for the exact remainder of the 200ms window
64        ticker.next().await;
65    }
66}