diff options
| author | ceekdee <[email protected]> | 2022-10-10 12:35:42 -0500 |
|---|---|---|
| committer | ceekdee <[email protected]> | 2022-10-10 12:35:42 -0500 |
| commit | 327d3cf0df7a1b116ea7ec44d36a569e6ba6ca16 (patch) | |
| tree | 67c69a2d511ba9dee2def2f7858e859d8150559b /examples | |
| parent | 79ba20d315f456ac525daf4c3d5dd0d2ce92ad2b (diff) | |
Change rak4631 feature to sx126x, removing use in board-specific processing; simplify the P2P examples; correct RSSI computation.
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/nrf/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/lora_p2p_report.rs | 56 | ||||
| -rw-r--r-- | examples/nrf/src/bin/lora_p2p_sense.rs | 84 |
3 files changed, 44 insertions, 98 deletions
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 91c418213..6949042e2 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml | |||
| @@ -18,7 +18,7 @@ embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defm | |||
| 18 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } | 18 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } |
| 19 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } | 19 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } |
| 20 | embedded-io = "0.3.0" | 20 | embedded-io = "0.3.0" |
| 21 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["rak4631", "time", "defmt"], optional = true } | 21 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } |
| 22 | 22 | ||
| 23 | lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } | 23 | lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } |
| 24 | lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } | 24 | lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } |
diff --git a/examples/nrf/src/bin/lora_p2p_report.rs b/examples/nrf/src/bin/lora_p2p_report.rs index 4ba3d30ce..d512b83f6 100644 --- a/examples/nrf/src/bin/lora_p2p_report.rs +++ b/examples/nrf/src/bin/lora_p2p_report.rs | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | //! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio. | 1 | //! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio. |
| 2 | //! Other nrf/sx126x combinations may work with appropriate pin modifications. | ||
| 3 | //! It demonstates LORA P2P functionality in conjunction with example lora_p2p_sense.rs. | ||
| 2 | #![no_std] | 4 | #![no_std] |
| 3 | #![no_main] | 5 | #![no_main] |
| 4 | #![macro_use] | 6 | #![macro_use] |
| @@ -18,7 +20,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 18 | async fn main(_spawner: Spawner) { | 20 | async fn main(_spawner: Spawner) { |
| 19 | let p = embassy_nrf::init(Default::default()); | 21 | let p = embassy_nrf::init(Default::default()); |
| 20 | let mut spi_config = spim::Config::default(); | 22 | let mut spi_config = spim::Config::default(); |
| 21 | spi_config.frequency = spim::Frequency::M1; // M16 ??? | 23 | spi_config.frequency = spim::Frequency::M16; |
| 22 | 24 | ||
| 23 | let mut radio = { | 25 | let mut radio = { |
| 24 | let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); | 26 | let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); |
| @@ -47,38 +49,30 @@ async fn main(_spawner: Spawner) { | |||
| 47 | Timer::after(Duration::from_secs(5)).await; | 49 | Timer::after(Duration::from_secs(5)).await; |
| 48 | start_indicator.set_low(); | 50 | start_indicator.set_low(); |
| 49 | 51 | ||
| 50 | match radio.lora.sleep().await { | 52 | loop { |
| 51 | Ok(()) => info!("Sleep successful"), | 53 | let rf_config = RfConfig { |
| 52 | Err(err) => info!("Sleep unsuccessful = {}", err), | 54 | frequency: 903900000, // channel in Hz |
| 53 | } | 55 | bandwidth: Bandwidth::_250KHz, |
| 54 | 56 | spreading_factor: SpreadingFactor::_10, | |
| 55 | let rf_config = RfConfig { | 57 | coding_rate: CodingRate::_4_8, |
| 56 | frequency: 903900000, // channel in Hz | 58 | }; |
| 57 | bandwidth: Bandwidth::_250KHz, | ||
| 58 | spreading_factor: SpreadingFactor::_10, | ||
| 59 | coding_rate: CodingRate::_4_8, | ||
| 60 | }; | ||
| 61 | 59 | ||
| 62 | let mut buffer = [00u8; 100]; | 60 | let mut buffer = [00u8; 100]; |
| 63 | 61 | ||
| 64 | // P2P receive | 62 | // P2P receive |
| 65 | match radio.rx(rf_config, &mut buffer).await { | 63 | match radio.rx(rf_config, &mut buffer).await { |
| 66 | Ok((buffer_len, rx_quality)) => info!( | 64 | Ok((buffer_len, rx_quality)) => info!( |
| 67 | "RX received = {:?} with length = {} rssi = {} snr = {}", | 65 | "RX received = {:?} with length = {} rssi = {} snr = {}", |
| 68 | &buffer[0..buffer_len], | 66 | &buffer[0..buffer_len], |
| 69 | buffer_len, | 67 | buffer_len, |
| 70 | rx_quality.rssi(), | 68 | rx_quality.rssi(), |
| 71 | rx_quality.snr() | 69 | rx_quality.snr() |
| 72 | ), | 70 | ), |
| 73 | Err(err) => info!("RX error = {}", err), | 71 | Err(err) => info!("RX error = {}", err), |
| 74 | } | 72 | } |
| 75 | 73 | ||
| 76 | match radio.lora.sleep().await { | 74 | debug_indicator.set_high(); |
| 77 | Ok(()) => info!("Sleep successful"), | 75 | Timer::after(Duration::from_secs(2)).await; |
| 78 | Err(err) => info!("Sleep unsuccessful = {}", err), | 76 | debug_indicator.set_low(); |
| 79 | } | 77 | } |
| 80 | |||
| 81 | debug_indicator.set_high(); | ||
| 82 | Timer::after(Duration::from_secs(5)).await; | ||
| 83 | debug_indicator.set_low(); | ||
| 84 | } | 78 | } |
diff --git a/examples/nrf/src/bin/lora_p2p_sense.rs b/examples/nrf/src/bin/lora_p2p_sense.rs index 405a8403f..b9768874b 100644 --- a/examples/nrf/src/bin/lora_p2p_sense.rs +++ b/examples/nrf/src/bin/lora_p2p_sense.rs | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | //! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio. | 1 | //! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio. |
| 2 | //! Other nrf/sx126x combinations may work with appropriate pin modifications. | ||
| 3 | //! It demonstates LORA P2P functionality in conjunction with example lora_p2p_report.rs. | ||
| 2 | #![no_std] | 4 | #![no_std] |
| 3 | #![no_main] | 5 | #![no_main] |
| 4 | #![macro_use] | 6 | #![macro_use] |
| @@ -9,8 +11,7 @@ | |||
| 9 | use defmt::*; | 11 | use defmt::*; |
| 10 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 11 | use embassy_lora::sx126x::*; | 13 | use embassy_lora::sx126x::*; |
| 12 | use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin as _, Pull}; | 14 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; |
| 13 | use embassy_nrf::temp::Temp; | ||
| 14 | use embassy_nrf::{interrupt, spim}; | 15 | use embassy_nrf::{interrupt, spim}; |
| 15 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 16 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 16 | use embassy_sync::pubsub::{PubSubChannel, Publisher}; | 17 | use embassy_sync::pubsub::{PubSubChannel, Publisher}; |
| @@ -18,10 +19,6 @@ use embassy_time::{Duration, Timer}; | |||
| 18 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; | 19 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; |
| 19 | use {defmt_rtt as _, panic_probe as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _, panic_probe as _}; |
| 20 | 21 | ||
| 21 | // Sensor packet constants | ||
| 22 | const TEMPERATURE_UID: u8 = 0x01; | ||
| 23 | const MOTION_UID: u8 = 0x02; | ||
| 24 | |||
| 25 | // Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection) | 22 | // Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection) |
| 26 | static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new(); | 23 | static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new(); |
| 27 | 24 | ||
| @@ -32,53 +29,20 @@ enum Message { | |||
| 32 | } | 29 | } |
| 33 | 30 | ||
| 34 | #[embassy_executor::task] | 31 | #[embassy_executor::task] |
| 35 | async fn temperature_task( | 32 | async fn temperature_task(publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>) { |
| 36 | mut temperature: Temp<'static>, | 33 | // Publish a fake temperature every 43 seconds, minimizing LORA traffic. |
| 37 | publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>, | ||
| 38 | ) { | ||
| 39 | Timer::after(Duration::from_secs(45)).await; // stabilize for 45 seconds | ||
| 40 | |||
| 41 | let mut temperature_reporting_threshhold = 10; | ||
| 42 | |||
| 43 | loop { | 34 | loop { |
| 44 | let value = temperature.read().await; | 35 | Timer::after(Duration::from_secs(43)).await; |
| 45 | let mut temperature_val = value.to_num::<i32>(); | 36 | publisher.publish(Message::Temperature(9)).await; |
| 46 | |||
| 47 | info!("Temperature: {}", temperature_val); | ||
| 48 | |||
| 49 | // only report every 2 degree Celsius drops, from 9 through 5, but starting at 3 always report | ||
| 50 | |||
| 51 | if temperature_val == 8 || temperature_val == 6 || temperature_val == 4 { | ||
| 52 | temperature_val += 1; | ||
| 53 | } | ||
| 54 | |||
| 55 | if temperature_reporting_threshhold > temperature_val | ||
| 56 | && (temperature_val == 9 || temperature_val == 7 || temperature_val == 5) | ||
| 57 | { | ||
| 58 | temperature_reporting_threshhold = temperature_val; | ||
| 59 | publisher.publish(Message::Temperature(temperature_val)).await; | ||
| 60 | } else if temperature_val <= 3 { | ||
| 61 | publisher.publish(Message::Temperature(temperature_val)).await; | ||
| 62 | } | ||
| 63 | |||
| 64 | Timer::after(Duration::from_secs(20 * 60)).await; | ||
| 65 | } | 37 | } |
| 66 | } | 38 | } |
| 67 | 39 | ||
| 68 | #[embassy_executor::task] | 40 | #[embassy_executor::task] |
| 69 | async fn motion_detection_task( | 41 | async fn motion_detection_task(publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>) { |
| 70 | mut pir_pin: Input<'static, AnyPin>, | 42 | // Publish a fake motion detection every 79 seconds, minimizing LORA traffic. |
| 71 | publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>, | ||
| 72 | ) { | ||
| 73 | Timer::after(Duration::from_secs(30)).await; // stabilize for 30 seconds | ||
| 74 | |||
| 75 | loop { | 43 | loop { |
| 76 | // wait for motion detection | 44 | Timer::after(Duration::from_secs(79)).await; |
| 77 | pir_pin.wait_for_low().await; | ||
| 78 | publisher.publish(Message::MotionDetected).await; | 45 | publisher.publish(Message::MotionDetected).await; |
| 79 | |||
| 80 | // wait a minute before setting up for more motion detection | ||
| 81 | Timer::after(Duration::from_secs(60)).await; | ||
| 82 | } | 46 | } |
| 83 | } | 47 | } |
| 84 | 48 | ||
| @@ -91,7 +55,7 @@ async fn main(spawner: Spawner) { | |||
| 91 | let motion_detection_publisher = unwrap!(MESSAGE_BUS.publisher()); | 55 | let motion_detection_publisher = unwrap!(MESSAGE_BUS.publisher()); |
| 92 | 56 | ||
| 93 | let mut spi_config = spim::Config::default(); | 57 | let mut spi_config = spim::Config::default(); |
| 94 | spi_config.frequency = spim::Frequency::M1; // M16 ??? | 58 | spi_config.frequency = spim::Frequency::M16; |
| 95 | 59 | ||
| 96 | let mut radio = { | 60 | let mut radio = { |
| 97 | let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); | 61 | let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); |
| @@ -113,15 +77,7 @@ async fn main(spawner: Spawner) { | |||
| 113 | } | 77 | } |
| 114 | }; | 78 | }; |
| 115 | 79 | ||
| 116 | // set up for the temperature task | ||
| 117 | let temperature_irq = interrupt::take!(TEMP); | ||
| 118 | let temperature = Temp::new(p.TEMP, temperature_irq); | ||
| 119 | |||
| 120 | // set the motion detection pin | ||
| 121 | let pir_pin = Input::new(p.P0_10.degrade(), Pull::Up); | ||
| 122 | |||
| 123 | let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard); | 80 | let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard); |
| 124 | let mut debug_indicator = Output::new(p.P1_03, Level::Low, OutputDrive::Standard); | ||
| 125 | 81 | ||
| 126 | start_indicator.set_high(); | 82 | start_indicator.set_high(); |
| 127 | Timer::after(Duration::from_secs(5)).await; | 83 | Timer::after(Duration::from_secs(5)).await; |
| @@ -132,15 +88,15 @@ async fn main(spawner: Spawner) { | |||
| 132 | Err(err) => info!("Sleep unsuccessful = {}", err), | 88 | Err(err) => info!("Sleep unsuccessful = {}", err), |
| 133 | } | 89 | } |
| 134 | 90 | ||
| 135 | unwrap!(spawner.spawn(temperature_task(temperature, temperature_publisher))); | 91 | unwrap!(spawner.spawn(temperature_task(temperature_publisher))); |
| 136 | unwrap!(spawner.spawn(motion_detection_task(pir_pin, motion_detection_publisher))); | 92 | unwrap!(spawner.spawn(motion_detection_task(motion_detection_publisher))); |
| 137 | 93 | ||
| 138 | loop { | 94 | loop { |
| 139 | let message = lora_tx_subscriber.next_message_pure().await; | 95 | let message = lora_tx_subscriber.next_message_pure().await; |
| 140 | 96 | ||
| 141 | let tx_config = TxConfig { | 97 | let tx_config = TxConfig { |
| 142 | // 11 byte maximum payload for Bandwidth 125 and SF 10 | 98 | // 11 byte maximum payload for Bandwidth 125 and SF 10 |
| 143 | pw: 20, // up to 20 // 5 ??? | 99 | pw: 10, // up to 20 |
| 144 | rf: RfConfig { | 100 | rf: RfConfig { |
| 145 | frequency: 903900000, // channel in Hz, not MHz | 101 | frequency: 903900000, // channel in Hz, not MHz |
| 146 | bandwidth: Bandwidth::_250KHz, | 102 | bandwidth: Bandwidth::_250KHz, |
| @@ -149,13 +105,13 @@ async fn main(spawner: Spawner) { | |||
| 149 | }, | 105 | }, |
| 150 | }; | 106 | }; |
| 151 | 107 | ||
| 152 | let mut buffer = [TEMPERATURE_UID, 0xffu8, MOTION_UID, 0x00u8]; | 108 | let mut buffer = [0x00u8]; |
| 153 | match message { | 109 | match message { |
| 154 | Message::Temperature(temperature) => buffer[1] = temperature as u8, | 110 | Message::Temperature(temperature) => buffer[0] = temperature as u8, |
| 155 | Message::MotionDetected => buffer[3] = 0x01u8, | 111 | Message::MotionDetected => buffer[0] = 0x01u8, |
| 156 | }; | 112 | }; |
| 157 | 113 | ||
| 158 | // crypto for text ??? | 114 | // unencrypted |
| 159 | match radio.tx(tx_config, &buffer).await { | 115 | match radio.tx(tx_config, &buffer).await { |
| 160 | Ok(ret_val) => info!("TX ret_val = {}", ret_val), | 116 | Ok(ret_val) => info!("TX ret_val = {}", ret_val), |
| 161 | Err(err) => info!("TX error = {}", err), | 117 | Err(err) => info!("TX error = {}", err), |
| @@ -165,9 +121,5 @@ async fn main(spawner: Spawner) { | |||
| 165 | Ok(()) => info!("Sleep successful"), | 121 | Ok(()) => info!("Sleep successful"), |
| 166 | Err(err) => info!("Sleep unsuccessful = {}", err), | 122 | Err(err) => info!("Sleep unsuccessful = {}", err), |
| 167 | } | 123 | } |
| 168 | |||
| 169 | debug_indicator.set_high(); | ||
| 170 | Timer::after(Duration::from_secs(5)).await; | ||
| 171 | debug_indicator.set_low(); | ||
| 172 | } | 124 | } |
| 173 | } | 125 | } |
