aboutsummaryrefslogtreecommitdiff
path: root/examples/rp235x/src/bin
diff options
context:
space:
mode:
authorMatt Johnston <[email protected]>2025-09-14 16:38:20 +0800
committerMatt Johnston <[email protected]>2025-09-14 16:54:14 +0800
commit7c551b4fdfd7fcf410423355a3a1b3f92d5f65a6 (patch)
tree4253d92723bdd8574952957d2b1a4549e6ca95e6 /examples/rp235x/src/bin
parent8f10e3638d77cadf058b9083de09fc7189048b0b (diff)
rp/pio: Copy onewire examples from rp to rp235x
The rp pio_onewire example was updated on cd27a8a06b0160d654ebed7b89ca473041710235 but not rp235x. Copy them to be the same.
Diffstat (limited to 'examples/rp235x/src/bin')
-rw-r--r--examples/rp235x/src/bin/pio_onewire.rs103
-rw-r--r--examples/rp235x/src/bin/pio_onewire_parasite.rs89
2 files changed, 143 insertions, 49 deletions
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs
index 991510851..102f13c45 100644
--- a/examples/rp235x/src/bin/pio_onewire.rs
+++ b/examples/rp235x/src/bin/pio_onewire.rs
@@ -1,4 +1,5 @@
1//! This example shows how you can use PIO to read a `DS18B20` one-wire temperature sensor. 1//! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors.
2//! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example.
2 3
3#![no_std] 4#![no_std]
4#![no_main] 5#![no_main]
@@ -6,9 +7,10 @@ use defmt::*;
6use embassy_executor::Spawner; 7use embassy_executor::Spawner;
7use embassy_rp::bind_interrupts; 8use embassy_rp::bind_interrupts;
8use embassy_rp::peripherals::PIO0; 9use embassy_rp::peripherals::PIO0;
9use embassy_rp::pio::{self, InterruptHandler, Pio}; 10use embassy_rp::pio::{InterruptHandler, Pio};
10use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram}; 11use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch};
11use embassy_time::Timer; 12use embassy_time::Timer;
13use heapless::Vec;
12use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
13 15
14bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
@@ -21,63 +23,66 @@ async fn main(_spawner: Spawner) {
21 let mut pio = Pio::new(p.PIO0, Irqs); 23 let mut pio = Pio::new(p.PIO0, Irqs);
22 24
23 let prg = PioOneWireProgram::new(&mut pio.common); 25 let prg = PioOneWireProgram::new(&mut pio.common);
24 let onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); 26 let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg);
25 27
26 let mut sensor = Ds18b20::new(onewire); 28 info!("Starting onewire search");
27 29
28 loop { 30 let mut devices = Vec::<u64, 10>::new();
29 sensor.start().await; // Start a new measurement 31 let mut search = PioOneWireSearch::new();
30 Timer::after_secs(1).await; // Allow 1s for the measurement to finish 32 for _ in 0..10 {
31 match sensor.temperature().await { 33 if !search.is_finished() {
32 Ok(temp) => info!("temp = {:?} deg C", temp), 34 if let Some(address) = search.next(&mut onewire).await {
33 _ => error!("sensor error"), 35 if crc8(&address.to_le_bytes()) == 0 {
36 info!("Found addres: {:x}", address);
37 let _ = devices.push(address);
38 } else {
39 warn!("Found invalid address: {:x}", address);
40 }
41 }
34 } 42 }
35 Timer::after_secs(1).await;
36 } 43 }
37}
38 44
39/// DS18B20 temperature sensor driver 45 info!("Search done, found {} devices", devices.len());
40pub struct Ds18b20<'d, PIO: pio::Instance, const SM: usize> {
41 wire: PioOneWire<'d, PIO, SM>,
42}
43 46
44impl<'d, PIO: pio::Instance, const SM: usize> Ds18b20<'d, PIO, SM> { 47 loop {
45 pub fn new(wire: PioOneWire<'d, PIO, SM>) -> Self { 48 onewire.reset().await;
46 Self { wire } 49 // Skip rom and trigger conversion, we can trigger all devices on the bus immediately
47 } 50 onewire.write_bytes(&[0xCC, 0x44]).await;
48 51
49 /// Calculate CRC8 of the data 52 Timer::after_secs(1).await; // Allow 1s for the measurement to finish
50 fn crc8(data: &[u8]) -> u8 { 53
51 let mut temp; 54 // Read all devices one by one
52 let mut data_byte; 55 for device in &devices {
53 let mut crc = 0; 56 onewire.reset().await;
54 for b in data { 57 onewire.write_bytes(&[0x55]).await; // Match rom
55 data_byte = *b; 58 onewire.write_bytes(&device.to_le_bytes()).await;
56 for _ in 0..8 { 59 onewire.write_bytes(&[0xBE]).await; // Read scratchpad
57 temp = (crc ^ data_byte) & 0x01; 60
58 crc >>= 1; 61 let mut data = [0; 9];
59 if temp != 0 { 62 onewire.read_bytes(&mut data).await;
60 crc ^= 0x8C; 63 if crc8(&data) == 0 {
61 } 64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.;
62 data_byte >>= 1; 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else {
67 warn!("Reading device {:x} failed", device);
63 } 68 }
64 } 69 }
65 crc 70 Timer::after_secs(1).await;
66 }
67
68 /// Start a new measurement. Allow at least 1000ms before getting `temperature`.
69 pub async fn start(&mut self) {
70 self.wire.write_bytes(&[0xCC, 0x44]).await;
71 } 71 }
72}
72 73
73 /// Read the temperature. Ensure >1000ms has passed since `start` before calling this. 74fn crc8(data: &[u8]) -> u8 {
74 pub async fn temperature(&mut self) -> Result<f32, ()> { 75 let mut crc = 0;
75 self.wire.write_bytes(&[0xCC, 0xBE]).await; 76 for b in data {
76 let mut data = [0; 9]; 77 let mut data_byte = *b;
77 self.wire.read_bytes(&mut data).await; 78 for _ in 0..8 {
78 match Self::crc8(&data) == 0 { 79 let temp = (crc ^ data_byte) & 0x01;
79 true => Ok(((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.), 80 crc >>= 1;
80 false => Err(()), 81 if temp != 0 {
82 crc ^= 0x8C;
83 }
84 data_byte >>= 1;
81 } 85 }
82 } 86 }
87 crc
83} 88}
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs
new file mode 100644
index 000000000..fd076dee0
--- /dev/null
+++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs
@@ -0,0 +1,89 @@
1//! This example shows how you can use PIO to read one or more `DS18B20`
2//! one-wire temperature sensors using parasite power.
3//! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet.
4//! For externally powered sensors, use the pio_onewire.rs example.
5
6#![no_std]
7#![no_main]
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_rp::bind_interrupts;
11use embassy_rp::peripherals::PIO0;
12use embassy_rp::pio::{InterruptHandler, Pio};
13use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch};
14use embassy_time::Duration;
15use heapless::Vec;
16use {defmt_rtt as _, panic_probe as _};
17
18bind_interrupts!(struct Irqs {
19 PIO0_IRQ_0 => InterruptHandler<PIO0>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_rp::init(Default::default());
25 let mut pio = Pio::new(p.PIO0, Irqs);
26
27 let prg = PioOneWireProgram::new(&mut pio.common);
28 let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg);
29
30 info!("Starting onewire search");
31
32 let mut devices = Vec::<u64, 10>::new();
33 let mut search = PioOneWireSearch::new();
34 for _ in 0..10 {
35 if !search.is_finished() {
36 if let Some(address) = search.next(&mut onewire).await {
37 if crc8(&address.to_le_bytes()) == 0 {
38 info!("Found address: {:x}", address);
39 let _ = devices.push(address);
40 } else {
41 warn!("Found invalid address: {:x}", address);
42 }
43 }
44 }
45 }
46
47 info!("Search done, found {} devices", devices.len());
48
49 loop {
50 // Read all devices one by one
51 for device in &devices {
52 onewire.reset().await;
53 onewire.write_bytes(&[0x55]).await; // Match rom
54 onewire.write_bytes(&device.to_le_bytes()).await;
55 // 750 ms delay required for default 12-bit resolution.
56 onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await;
57
58 onewire.reset().await;
59 onewire.write_bytes(&[0x55]).await; // Match rom
60 onewire.write_bytes(&device.to_le_bytes()).await;
61 onewire.write_bytes(&[0xBE]).await; // Read scratchpad
62
63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp);
68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data);
70 }
71 }
72 }
73}
74
75fn crc8(data: &[u8]) -> u8 {
76 let mut crc = 0;
77 for b in data {
78 let mut data_byte = *b;
79 for _ in 0..8 {
80 let temp = (crc ^ data_byte) & 0x01;
81 crc >>= 1;
82 if temp != 0 {
83 crc ^= 0x8C;
84 }
85 data_byte >>= 1;
86 }
87 }
88 crc
89}