Struct Nrf24l01

Source
pub struct Nrf24l01<SPI, CE> { /* 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, &mut delay, NrfConfig::default()).unwrap();

Implementations§

Source§

impl<SPI, CE> Nrf24l01<SPI, CE>
where SPI: SpiDevice, CE: OutputPin,

Source

pub fn new<D: DelayNs>( spi: SPI, ce: CE, delay: &mut D, config: NrfConfig, ) -> Result<Self, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Creates a new nRF24L01 driver with the given configuration.

This function initializes the device, configures it according to the provided settings, and performs validation to ensure proper communication with the chip. After initialization, the device is powered up and ready to use.

§Arguments
  • spi - SPI interface for communicating with the nRF24L01 chip, this type should implement the SpiDevice trait from embedded_hal
  • ce - Chip Enable pin for controlling the chip’s operating states
  • delay - Delay provider for timing requirements during initialization
  • config - Configuration settings for the chip (see NrfConfig for options)
§Errors

This function may return errors in the following situations:

  • SPI communication errors
  • Chip enable pin errors
  • Communication errors with the module (e.g., incorrect configuration register values)
§Examples
use nrf24::{Nrf24l01, SPI_MODE};
use nrf24::config::{NrfConfig, PALevel, DataRate};

// Initialize hardware interfaces (platform-specific)
let spi = setup_spi(SPI_MODE);
let ce = setup_pin();
let mut delay = setup_delay();

// Create custom configuration
let config = NrfConfig::default()
    .channel(76)
    .data_rate(DataRate::R2Mbps)
    .pa_level(PALevel::Low);

// Initialize the nRF24L01 driver
match Nrf24l01::new(spi, ce, &mut delay, config) {
    Ok(nrf) => {
        // Successfully initialized
        // Continue with nrf.open_reading_pipe(), nrf.start_listening(), etc.
    },
    Err(e) => {
        // Handle initialization error
        panic!("Failed to initialize nRF24L01: {:?}", e);
    }
}
§Note

The chip requires some settling time after power-up. This function includes appropriate delays to ensure reliable initialization.

Source

pub fn is_connected( &mut self, ) -> Result<bool, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Checks if the chip is connected to the SPI bus.

§Examples
if !chip.is_connected()? {
    // Handle disconnection
}
Source

pub fn open_reading_pipe<T: Into<DataPipe>>( &mut self, pipe: T, addr: &[u8], ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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().

Source

pub fn open_writing_pipe( &mut self, addr: &[u8], ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Opens a writing pipe for writing data to an address.

§Examples
// Open writing pipe for address "Node1"
chip.open_writing_pipe(b"Node1")?;
§Warnings

Must be called before writing data.

Source

pub fn start_listening( &mut self, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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.

Source

pub fn stop_listening( &mut self, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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()?;
Source

pub fn data_available( &mut self, ) -> Result<bool, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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.

Source

pub fn data_available_on_pipe( &mut self, ) -> Result<Option<DataPipe>, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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
    }
}
Source

pub fn read( &mut self, buf: &mut [u8], ) -> Result<usize, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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, &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(50);
}
Source

pub fn write<D: DelayNs>( &mut self, delay: &mut D, buf: &[u8], ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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, &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(50);
}

Will clear all interrupt flags after write. Returns an error when max retries have been reached.

Source

pub fn set_retries<T: Into<AutoRetransmission>>( &mut self, auto_retry: T, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Setup of automatic retransmission.

§Arguments
  • delay is 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

  • count is 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))?;
Source

pub fn retries( &mut self, ) -> Result<AutoRetransmission, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Returns the auto retransmission config.

§Examples
// Initialize the chip
let mut chip = Nrf24l01::new(spi_struct, ce_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);
Source

pub fn set_channel( &mut self, channel: u8, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Set the frequency channel nRF24L01 operates on.

§Arguments
  • channel number between 0 and 127.
§Examples
nrf24l01.set_channel(74)?;
Source

pub fn channel( &mut self, ) -> Result<u8, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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, delay, NrfConfig::default())?;
// Default is channel 76
assert_eq!(chip.channel()?, 76);
Source

pub fn set_address_width<T>( &mut self, width: T, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>
where T: Into<AddressWidth>,

Set the address width, saturating values above or below allowed range.

§Arguments
  • width number between 3 and 5.
§Examples
nrf24l01.set_address_width(5)?;
Source

pub fn data_rate( &mut self, ) -> Result<DataRate, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Returns the current data rate as a DataRate enum.

§Examples
// Initialize the chip
let mut chip = Nrf24l01::new(spi_struct, ce_pin, delay, NrfConfig::default())?;
// Default is 2 Mb/s
assert_eq!(chip.data_rate()?, DataRate::R2Mbps);
Source

pub fn power_amp_level( &mut self, ) -> Result<PALevel, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Returns the current power amplifier level as a PALevel enum.

§Examples
// Initialize the chip
let mut chip = Nrf24l01::new(spi_struct, ce_pin, delay, NrfConfig::default())?;
// Default is Min PALevel
assert_eq!(chip.power_amp_level()?, PALevel::Min);
Source

pub fn flush_tx( &mut self, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Flush transmission FIFO, used in TX mode.

§Examples
chip.flush_tx()?;
Source

pub fn flush_rx( &mut self, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Flush reciever FIFO, used in RX mode.

§Examples
nrf24l01.flush_rx()?;
Source

pub fn enable_crc( &mut self, scheme: EncodingScheme, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Enable CRC encoding scheme.

§Examples
chip.enable_crc(EncodingScheme::R2Bytes)?;
Source

pub fn crc_encoding_scheme( &mut self, ) -> Result<EncodingScheme, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Get the CRC encoding scheme

§Examples
match chip.crc_encoding_scheme()? {
    EncodingScheme::NoRedundancyCheck => println("No crc check"),
    EncodingScheme::R1Byte => println("8 bit check"),
    EncodingScheme::R2Bytes => println("16 bit check"),
};
Source

pub fn set_payload_size<T: Into<PayloadSize>>( &mut self, payload_size: T, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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_SIZE will 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`
Source

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, delay, NrfConfig::default())?;
// Default payload size is MAX_PAYLOAD_SIZE
assert_eq!(chip.payload_size()?, PayloadSize::Static(MAX_PAYLOAD_SIZE));
Source

pub fn power_up<D: DelayNs>( &mut self, delay: &mut D, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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 up
Source

pub fn power_down( &mut self, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

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 up
Source

pub fn status( &mut self, ) -> Result<Status, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Reads the status register from device. See Status.

Source

pub fn reset_status( &mut self, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Resets the following flags in the status register:

  • data ready RX fifo interrupt
  • data sent TX fifo interrupt
  • maximum number of retries interrupt
Source

pub fn mask_interrupts( &mut self, irq: Interrupts, ) -> Result<(), TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Masks the selected interrupt flags.

By default, the IRQ pin will pull low when one of the following events occur:

  • Maximum number of retries is reached
  • Transmission data is sent
  • Receiver data is avaiable to be read

This function allows you to disable these interrupts.

§Note

Masking an interrupt doesn’t prevent the event from occurring or prevent the status flag from being set. It only prevents the external IRQ pin from triggering. You can still read the status register to see if the event occurred, even if the interrupt is masked.

§Examples
let interrupts = Interrupts::new().max_retries().rx_data_ready();
chip.mask_interrupts(interrupts)?;

Disable all interrupts.

let interrupts = Interrupts::all();
chip.mask_interrupt(interrupts);
Source

pub fn interrupt_src( &mut self, ) -> Result<Interrupts, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Query which interrupts were triggered.

Clears the interrupt request flags, so new ones can come in.

Source

pub fn read_config( &mut self, ) -> Result<NrfConfig, TransceiverError<<SPI as SpiErrorType>::Error, <CE as PinErrorType>::Error>>

Reads the config from the device and returns it in a NrfConfig struct. Can be used to log the configuration when using defmt feature.

Auto Trait Implementations§

§

impl<SPI, CE> Freeze for Nrf24l01<SPI, CE>
where SPI: Freeze, CE: Freeze,

§

impl<SPI, CE> RefUnwindSafe for Nrf24l01<SPI, CE>
where SPI: RefUnwindSafe, CE: RefUnwindSafe,

§

impl<SPI, CE> Send for Nrf24l01<SPI, CE>
where SPI: Send, CE: Send,

§

impl<SPI, CE> Sync for Nrf24l01<SPI, CE>
where SPI: Sync, CE: Sync,

§

impl<SPI, CE> Unpin for Nrf24l01<SPI, CE>
where SPI: Unpin, CE: Unpin,

§

impl<SPI, CE> UnwindSafe for Nrf24l01<SPI, CE>
where SPI: UnwindSafe, CE: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.