pub struct Nrf24l01<SPI, CE, NCS> { /* private fields */ }Expand description
The nRF24L01 driver type. This struct encapsulates all functionality.
For the different configuration options see: NrfConfig.
§Examples
use nrf24::Nrf24l01;
use nrf24::config::NrfConfig;
// Initialize the chip with deafault configuration.
let nrf24 = Nrf24l01::new(spi, ce, ncs, &mut delay, NrfConfig::default()).unwrap();
Implementations§
Source§impl<SPI, CE, NCS, SPIErr, PinErr> Nrf24l01<SPI, CE, NCS>
impl<SPI, CE, NCS, SPIErr, PinErr> Nrf24l01<SPI, CE, NCS>
Sourcepub fn new<D>(
spi: SPI,
ce: CE,
ncs: NCS,
delay: &mut D,
config: NrfConfig,
) -> Result<Self, TransferError<SPIErr, PinErr>>
pub fn new<D>( spi: SPI, ce: CE, ncs: NCS, delay: &mut D, config: NrfConfig, ) -> Result<Self, TransferError<SPIErr, PinErr>>
Creates a new nrf24l01 driver with given config.
Starts up the device after initialization, so calling power_up() is not necessary.
§Examples
// Initialize all pins required
let dp = Peripherals::take()::unwrap();
let mut portd = dp.PORTD.split();
let ce = portd.pd3.into_output(&mut portd.ddr); // Chip Enable
let mut portb = dp.PORTB.split();
let ncs = portb.pb2.into_output(&mut portb.ddr); // Chip Select (active low)
let mosi = portb.pb3.into_output(&mut portb.ddr); // Master Out Slave In Pin
let miso = portb.pb4.into_pull_up_input(&mut portb.ddr); // Master In Slave Out Pin
let sclk = portb.pb5.into_output(&mut portb.ddr); // Clock
// Now we initialize SPI settings to create an SPI instance
let settings = spi::Settings {
data_order: DataOrder::MostSignificantFirst,
clock: SerialClockRate::OscfOver4,
// The required SPI mode for communication with the nrf chip is specified in
// this crate
mode: nrf24_rs::SPI_MODE,
};
let (spi, ncs) = spi::Spi::new(dp.SPI, sclk, mosi, miso, ncs, settings);
let mut delay = hal::delay::Delay::<clock::MHz16>::new();
// Construct a new instance of the chip with a default configuration
// This will initialize the module and start it up
let nrf24 = nrf24_rs::Nrf24l01::new(spi, ce, ncs, &mut delay, NrfConfig::default())?;
Sourcepub fn is_connected(&mut self) -> Result<bool, TransferError<SPIErr, PinErr>>
pub fn is_connected(&mut self) -> Result<bool, TransferError<SPIErr, PinErr>>
Checks if the chip is connected to the SPI bus.
§Examples
if !chip.is_connected()? {
// Handle disconnection
}Sourcepub fn open_reading_pipe<T: Into<DataPipe>>(
&mut self,
pipe: T,
addr: &[u8],
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn open_reading_pipe<T: Into<DataPipe>>( &mut self, pipe: T, addr: &[u8], ) -> Result<(), TransferError<SPIErr, PinErr>>
Opens a reading pipe for reading data on an address.
§Examples
chip.open_reading_pipe(DataPipe::DP0, b"Node1")?;pipe can either be an instance of the type DataPipe or an integer.
Note that if an integer is provided, numbers higher than 5 will default to reading pipe 0.
§Warnings
You have to call this before calling start_listening().
Sourcepub fn open_writing_pipe(
&mut self,
addr: &[u8],
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn open_writing_pipe( &mut self, addr: &[u8], ) -> Result<(), TransferError<SPIErr, PinErr>>
Sourcepub fn start_listening(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn start_listening(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
Starts listening on the pipes that are opened for reading. Used in Receiver Mode.
§Examples
// First open data pipe 0 with address "Node1"
chip.open_reading_pipe(DataPipe::DP0, b"Node1")?;
// Configure the chip to listening modes (non blocking)
chip.start_listening()
// Now we can check for available messages and read them§Warnings
Make sure at least one pipe is opened for reading using the open_reading_pipe() method.
Sourcepub fn stop_listening(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn stop_listening(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
Stops listening.
§Examples
// Configure chip and start listening
chip.open_reading_pipe(DataPipe::DP0, b"Node1")?;
chip.start_listening()?;
// ... read data
// Reading is done, now we can stop listening
chip.stop_listening()?;Sourcepub fn data_available(&mut self) -> Result<bool, TransferError<SPIErr, PinErr>>
pub fn data_available(&mut self) -> Result<bool, TransferError<SPIErr, PinErr>>
Checks if there are any bytes available to be read.
§Examples
// Chip has to be set in listening mode first
chip.open_reading_pipe(DataPipe::DP0, b"Node1")?;
chip.start_listening()?;
// Check if there is any data to read
while chip.data_available()? {
// ... read the payload
delay.delay_ms(50); // small delay between calls of data_available
}§Notes
If data_available is called in too rapid succession, the chip can glitch out.
If this is the case, just add a small delay between calling successive data_available.
Sourcepub fn data_available_on_pipe(
&mut self,
) -> Result<Option<DataPipe>, TransferError<SPIErr, PinErr>>
pub fn data_available_on_pipe( &mut self, ) -> Result<Option<DataPipe>, TransferError<SPIErr, PinErr>>
Returns the data pipe where the data is available and None if no data available.
§Examples
// Chip has to be set in listening mode first
chip.open_reading_pipe(DataPipe::DP0, b"Node1")?;
chip.start_listening()?;
// Check if there is any data to read on pipe 1
while let Some(pipe) = chip.data_available_on_pipe()? {
if pipe == DataPipe::DP1 {
// ... read the payload
delay.delay_ms(50); // small delay between calls of data_available
}
}Sourcepub fn read(
&mut self,
buf: &mut [u8],
) -> Result<usize, TransferError<SPIErr, PinErr>>
pub fn read( &mut self, buf: &mut [u8], ) -> Result<usize, TransferError<SPIErr, PinErr>>
Reads the available payload. To check if there are any payloads available, call
data_available().
Make sure the chip is configured in listening mode and at least one data pipe is opened for reading, see:
Returns the number of bytes read into the buffer.
§Examples
// We will be receiving float values
// Set the payload size to 4 bytes, the size of an f32
let config = NrfConfig::default().payload_size(PayloadSize::Static(4));
let chip = Nrf24l01::new(spi, ce, ncs, &mut delay, config).unwrap();
// Put the chip in listening mode
chip.open_reading_pipe(DataPipe::DP0, b"Node1");
chip.start_listening();
// The buffer where we will read the data into
let mut buffer = [0u8; 4];
loop {
// Keep reading data if any is available
while let Ok(true) = chip.data_available() {
match chip.read(&mut buffer) {
Err(e) => eprintln!("Error while reading data from buffer: {:?}", e),
Ok(n) => {
println!("Successfully read {} bytes of data!", n);
assert_eq!(n, 4);
// reinterpret memory as a float
let f = f32::from_le_bytes(buffer);
println!("Received value: {}", f);
},
}
}
// Wait some time before trying again
delay.delay_us(50u16);
}Sourcepub fn write<D: DelayUs<u8>>(
&mut self,
delay: &mut D,
buf: &[u8],
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn write<D: DelayUs<u8>>( &mut self, delay: &mut D, buf: &[u8], ) -> Result<(), TransferError<SPIErr, PinErr>>
Writes data to the opened channel.
§Examples
// We will be sending float values
// Set the payload size to 4 bytes, the size of an f32
let config = NrfConfig::default().payload_size(PayloadSize::Static(4));
let chip = Nrf24l01::new(spi, ce, ncs, &mut delay, config).unwrap();
// Put the chip in transmission mode
chip.open_writing_pipe(b"Node1");
chip.stop_listening();
// The buffer where we will write data into before sending
let mut buffer = [0u8; 4];
loop {
let f = get_reading(); // data from some sensor
// reinterpret float to bytes and put into buffer
buffer.copy_from_slice(&f.to_le_bytes());
match chip.write(&mut delay, &buffer) {
Err(e) => eprintln!("Error while sending data {:?}", e),
Ok(_) => {
println!("Successfully wrote the data!");
},
}
// Wait some time before trying again
delay.delay_us(50u16);
}Will clear all interrupt flags after write. Returns an error when max retries have been reached.
Sourcepub fn set_retries<T: Into<AutoRetransmission>>(
&mut self,
auto_retry: T,
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn set_retries<T: Into<AutoRetransmission>>( &mut self, auto_retry: T, ) -> Result<(), TransferError<SPIErr, PinErr>>
Setup of automatic retransmission.
§Arguments
delayis the auto retransmit delay. Values can be between 0 and 15. The delay before a retransmit is initiated, is calculated according to the following formula:
((delay + 1) * 250) + 86 µs
countis number of times there will be an auto retransmission. Must be a value between 0 and 15.
§Examples
// Set the auto transmit delay to (5 + 1) * 250) + 86 = 1586µs
// and the retransmit count to 15.
nrf24l01.set_retries((5, 15))?;Sourcepub fn retries(
&mut self,
) -> Result<AutoRetransmission, TransferError<SPIErr, PinErr>>
pub fn retries( &mut self, ) -> Result<AutoRetransmission, TransferError<SPIErr, PinErr>>
Returns the auto retransmission config.
§Examples
// Initialize the chip
let mut chip = Nrf24l01::new(spi_struct, ce_pin, ncs_pin, delay, NrfConfig::default())?;
let retries_config = chip.retries()?;
// Default values for the chip
assert_eq!(retries_config.delay(), 1586);
assert_eq!(retries_config.count(), 15);Sourcepub fn set_channel(
&mut self,
channel: u8,
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn set_channel( &mut self, channel: u8, ) -> Result<(), TransferError<SPIErr, PinErr>>
Sourcepub fn channel(&mut self) -> Result<u8, TransferError<SPIErr, PinErr>>
pub fn channel(&mut self) -> Result<u8, TransferError<SPIErr, PinErr>>
Return the frequency channel nRF24L01 operates on. Note that the actual frequency will we the channel +2400 MHz.
§Examples
// Initialize the chip
let mut chip = Nrf24l01::new(spi_struct, ce_pin, ncs_pin, delay, NrfConfig::default())?;
// Default is channel 76
assert_eq!(chip.channel()?, 76);Sourcepub fn set_address_width<T>(
&mut self,
width: T,
) -> Result<(), TransferError<SPIErr, PinErr>>where
T: Into<AddressWidth>,
pub fn set_address_width<T>(
&mut self,
width: T,
) -> Result<(), TransferError<SPIErr, PinErr>>where
T: Into<AddressWidth>,
Sourcepub fn data_rate(&mut self) -> Result<DataRate, TransferError<SPIErr, PinErr>>
pub fn data_rate(&mut self) -> Result<DataRate, TransferError<SPIErr, PinErr>>
Sourcepub fn power_amp_level(
&mut self,
) -> Result<PALevel, TransferError<SPIErr, PinErr>>
pub fn power_amp_level( &mut self, ) -> Result<PALevel, TransferError<SPIErr, PinErr>>
Sourcepub fn flush_tx(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn flush_tx(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
Sourcepub fn flush_rx(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn flush_rx(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
Sourcepub fn enable_crc(
&mut self,
scheme: EncodingScheme,
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn enable_crc( &mut self, scheme: EncodingScheme, ) -> Result<(), TransferError<SPIErr, PinErr>>
Enable CRC encoding scheme.
Note that this configures the nrf24l01 in transmit mode.
§Examples
chip.enable_crc(EncodingScheme::R2Bytes)?;Sourcepub fn set_payload_size<T: Into<PayloadSize>>(
&mut self,
payload_size: T,
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn set_payload_size<T: Into<PayloadSize>>( &mut self, payload_size: T, ) -> Result<(), TransferError<SPIErr, PinErr>>
Sets the payload size in bytes. This can either be static with a set size, or dynamic.
payload_size can either be an instance of the PayloadSize enum, or an integer.
§Notes
- A value of 0 means the dynamic payloads will be enabled.
- Values bigger than
MAX_PAYLOAD_SIZEwill be set to the maximum.
§Examples
// Two equal methods to set the chip to dynamic payload mode.
chip.set_payload_size(PayloadSize::Dynamic)?;
chip.set_payload_size(0)?;
// Following methods set a static payload size.
chip.set_payload_size(12)?; // Messages will be 12 bytes
chip.set_payload_size(PayloadSize::Static(12))?; // Same as previous
chip.set_payload_size(49)?; // Messages will be `MAX_PAYLOAD_SIZE`Sourcepub fn payload_size(&self) -> PayloadSize
pub fn payload_size(&self) -> PayloadSize
Returns the payload size as a PayloadSize enum.
§Examples
// Initialize chip
let mut chip = Nrf24l01::new(spi_struct, ce_pin, ncs_pin, delay, NrfConfig::default())?;
// Default payload size is MAX_PAYLOAD_SIZE
assert_eq!(chip.payload_size()?, PayloadSize::Static(MAX_PAYLOAD_SIZE));Sourcepub fn power_up<D>(
&mut self,
delay: &mut D,
) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn power_up<D>( &mut self, delay: &mut D, ) -> Result<(), TransferError<SPIErr, PinErr>>
Powers the chip up. Note that a new initialized device will already be in power up mode, so
calling power_up() is not necessary.
Should be called after power_down() to put the chip back into power up mode.
§Examples
// Go to sleep
chip.power_down(&mut delay)?;
// Zzz
// ...
chip.power_up(&mut delay)?; // power back upSourcepub fn power_down(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn power_down(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
Powers the chip down. This is the low power mode. The chip will consume approximatly 900nA.
To power the chip back up, call power_up().
§Examples
// Go to sleep
chip.power_down(&mut delay)?;
// Zzz
// ...
chip.power_up(&mut delay)?; // power back upSourcepub fn status(&mut self) -> Result<Status, TransferError<SPIErr, PinErr>>
pub fn status(&mut self) -> Result<Status, TransferError<SPIErr, PinErr>>
Reads the status register from device. See Status.
Sourcepub fn reset_status(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
pub fn reset_status(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>
Resets the following flags in the status register:
- data ready RX fifo interrupt
- data sent TX fifo interrupt
- maximum number of number of retries interrupt