Skip to content

Commit 3f82798

Browse files
authored
Merge pull request #2 from 1-rafael-1/query-status
2 parents c52204d + 449bbde commit 3f82798

File tree

5 files changed

+285
-99
lines changed

5 files changed

+285
-99
lines changed

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "dfplayer-async"
3-
version = "0.2.1"
4-
edition = "2021"
3+
version = "0.3.0"
4+
edition = "2024"
55
description = "A simple embedded-hal-async driver for the DFPlayer mini MP3 module."
66
keywords = ["no-std", "embedded-hal-async", "mp3", "dfplayer", "driver"]
77
categories = ["embedded", "hardware-support", "no-std"]
@@ -18,7 +18,7 @@ authors = [
1818
embedded-io-async = "0.6"
1919
embedded-hal-async = "1.0.0"
2020

21-
defmt = { version = "0.3.10", optional = true }
21+
defmt = { version = "1.0.1", optional = true }
2222

2323
[features]
2424
defmt = ["dep:defmt"]

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Add to your `Cargo.toml`:
3232

3333
```toml
3434
[dependencies]
35-
dfplayer-async = "0.2.0"
35+
dfplayer-async = "0.3.0"
3636
```
3737

3838
## Examples

examples/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ path = "src/basic.rs"
1111
name = "query"
1212
path = "src/query.rs"
1313

14+
[[example]]
15+
name = "sleep"
16+
path = "src/sleep.rs"
17+
1418
[dependencies]
15-
embassy-rp = { version = "0.3.1", features = [
19+
embassy-rp = { version = "0.4.0", features = [
1620
"defmt",
1721
"unstable-pac",
1822
"time-driver",

examples/src/sleep.rs

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
//! Basic Embassy example for the Raspberry Pi Pico 2
2+
//! Showcase sleep and wake up functionality of the DFPlayer Mini
3+
//!
4+
//! Assumes the following connections:
5+
//!
6+
//! - UART0 TX/RX on GPIO 17/16
7+
//! - Busy Pin on GPIO 18
8+
//!
9+
//! Assumes the following for the DFPlayer Mini:
10+
//!
11+
//! - Powered and ground connected
12+
//! - TX/RX connected
13+
//! - Busy Pin connected
14+
//! - Speaker connected
15+
//! - Using SD card for audio files. Place mp3 files on the SD card into a folder structure as documented in the DFPlayer Mini manual. For example:
16+
//! - no folders, use root directory
17+
//! - 0001-whatevernameX.mp3
18+
//! - 0002-whatevernameY.mp3
19+
//! - 0003-whatevernameZ.mp3
20+
21+
#![no_std]
22+
#![no_main]
23+
24+
use defmt::{error, info, Debug2Format};
25+
use dfplayer_async::{DfPlayer, TimeSource};
26+
use embassy_executor::Spawner;
27+
use embassy_rp::{
28+
bind_interrupts,
29+
block::ImageDef,
30+
config::Config,
31+
gpio::{Input, Pull},
32+
peripherals::UART0,
33+
uart::{
34+
BufferedInterruptHandler, BufferedUart, Config as UartConfig, DataBits,
35+
Parity, StopBits,
36+
},
37+
};
38+
use embassy_time::{Delay, Duration, Instant, Timer};
39+
use static_cell::StaticCell;
40+
use {defmt_rtt as _, panic_probe as _};
41+
42+
/// Firmware image type for bootloader
43+
#[unsafe(link_section = ".start_block")]
44+
#[used]
45+
pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe();
46+
47+
bind_interrupts!(pub struct Irqs {
48+
UART0_IRQ => BufferedInterruptHandler<UART0>;
49+
});
50+
51+
/// Firmware entry point
52+
#[embassy_executor::main]
53+
async fn main(_spawner: Spawner) {
54+
let p = embassy_rp::init(Config::default());
55+
56+
// Initialize the DFPlayer Mini
57+
// The modules usually have a busy pin that can be used to determine if the module is currently playing audio. Low if busy, high if not busy.
58+
let mut busy = Input::new(p.PIN_18, Pull::None);
59+
60+
// We need a UART port to communicate with the DFPlayer Mini
61+
let mut uart_config = UartConfig::default();
62+
uart_config.baudrate = 9600;
63+
uart_config.data_bits = DataBits::DataBits8;
64+
uart_config.stop_bits = StopBits::STOP1;
65+
uart_config.parity = Parity::ParityNone;
66+
67+
// Create a buffered UART instance
68+
static TX_BUF: StaticCell<[u8; 64]> = StaticCell::new();
69+
let tx_buf = &mut TX_BUF.init([0; 64])[..];
70+
static RX_BUF: StaticCell<[u8; 64]> = StaticCell::new();
71+
let rx_buf = &mut RX_BUF.init([0; 64])[..];
72+
let mut uart = BufferedUart::new(
73+
p.UART0,
74+
Irqs,
75+
p.PIN_16,
76+
p.PIN_17,
77+
tx_buf,
78+
rx_buf,
79+
uart_config,
80+
);
81+
82+
// Configure DFPlayer parameters
83+
let feedback_enable = true;
84+
let timeout_ms = 1000;
85+
let delay = Delay;
86+
let reset_duration_override = None;
87+
88+
// Implement the TimeSource trait for the DFPlayer Mini
89+
struct MyTimeSource;
90+
impl TimeSource for MyTimeSource {
91+
type Instant = Instant;
92+
93+
fn now(&self) -> Self::Instant {
94+
Instant::now()
95+
}
96+
97+
fn is_elapsed(&self, since: Self::Instant, timeout_ms: u64) -> bool {
98+
Instant::now().duration_since(since)
99+
>= Duration::from_millis(timeout_ms)
100+
}
101+
}
102+
103+
// Create the DFPlayer Mini instance
104+
let mut dfplayer = match DfPlayer::try_new(
105+
&mut uart,
106+
feedback_enable,
107+
timeout_ms,
108+
MyTimeSource,
109+
delay,
110+
reset_duration_override,
111+
)
112+
.await
113+
{
114+
Ok(dfplayer) => dfplayer,
115+
Err(e) => {
116+
error!("Error initializing DFPlayer Mini: {}", Debug2Format(&e));
117+
return;
118+
}
119+
};
120+
121+
// Set the volume to a low level
122+
let volume = 1;
123+
match dfplayer.set_volume(volume).await {
124+
Ok(_) => info!("Volume {} set successfully", volume),
125+
Err(e) => error!("Failed to set volume: {}", Debug2Format(&e)),
126+
}
127+
128+
// Play the first track for a few seconds, then stop
129+
info!("Playing track 1");
130+
match dfplayer.play(1).await {
131+
Ok(_) => info!("Play track 1 command sent successfully"),
132+
Err(e) => error!("Failed to play track: {}", Debug2Format(&e)),
133+
}
134+
Timer::after(Duration::from_secs(5)).await;
135+
match dfplayer.stop().await {
136+
Ok(_) => info!("Stop command sent successfully"),
137+
Err(e) => error!("Failed to stop track: {}", Debug2Format(&e)),
138+
}
139+
140+
// Wait a moment before putting the device to sleep
141+
Timer::after(Duration::from_secs(1)).await;
142+
143+
// Put the device to sleep
144+
info!("Putting DFPlayer Mini to sleep");
145+
match dfplayer.sleep().await {
146+
Ok(_) => info!("Sleep command sent successfully"),
147+
Err(e) => error!("Failed to put device to sleep: {}", Debug2Format(&e)),
148+
}
149+
150+
// Wait while the device is in sleep mode
151+
info!("Device is now in sleep mode. Waiting for 5 seconds...");
152+
Timer::after(Duration::from_secs(5)).await;
153+
154+
// Wake up the device
155+
// info!("Waking up DFPlayer Mini");
156+
// match dfplayer.wake_up(true, None).await {
157+
// Ok(_) => info!("Wake up command sent successfully"),
158+
// Err(e) => error!("Failed to wake up device: {}", Debug2Format(&e)),
159+
// }
160+
// Wake up the device
161+
info!("Waking up DFPlayer Mini");
162+
match dfplayer.reset(None).await {
163+
Ok(_) => info!("Wake up command sent successfully"),
164+
Err(e) => error!("Failed to wake up device: {}", Debug2Format(&e)),
165+
}
166+
167+
168+
// Wait a moment for the device to fully wake up
169+
Timer::after(Duration::from_secs(1)).await;
170+
171+
// Play another track to verify the device is working after waking up
172+
info!("Playing track 2 to verify device is awake");
173+
match dfplayer.play(2).await {
174+
Ok(_) => info!("Play track 2 command sent successfully"),
175+
Err(e) => error!("Failed to play track: {}", Debug2Format(&e)),
176+
}
177+
Timer::after(Duration::from_secs(5)).await;
178+
match dfplayer.stop().await {
179+
Ok(_) => info!("Stop command sent successfully"),
180+
Err(e) => error!("Failed to stop track: {}", Debug2Format(&e)),
181+
}
182+
183+
// Example complete
184+
info!("Sleep/wake up example complete");
185+
186+
// Loop forever
187+
loop {
188+
Timer::after(Duration::from_secs(1)).await;
189+
}
190+
}

0 commit comments

Comments
 (0)