Struct Nrf24l01

Source
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>
where SPI: Transfer<u8, Error = SPIErr> + Write<u8, Error = SPIErr>, NCS: OutputPin<Error = PinErr>, CE: OutputPin<Error = PinErr>,

Source

pub fn new<D>( spi: SPI, ce: CE, ncs: NCS, delay: &mut D, config: NrfConfig, ) -> Result<Self, TransferError<SPIErr, PinErr>>
where D: DelayMs<u8>,

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

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

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

Source

pub fn open_writing_pipe( &mut self, addr: &[u8], ) -> Result<(), TransferError<SPIErr, PinErr>>

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

Source

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

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.

Source

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

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

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.

Source

pub fn set_retries<T: Into<AutoRetransmission>>( &mut self, auto_retry: T, ) -> Result<(), TransferError<SPIErr, PinErr>>

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, 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);
Source

pub fn set_channel( &mut self, channel: u8, ) -> Result<(), TransferError<SPIErr, PinErr>>

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, 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);
Source

pub fn set_address_width<T>( &mut self, width: T, ) -> Result<(), TransferError<SPIErr, PinErr>>
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, TransferError<SPIErr, PinErr>>

Returns the current data rate as a DataRate enum.

§Examples
// Initialize the chip
let mut chip = Nrf24l01::new(spi_struct, ce_pin, ncs_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, TransferError<SPIErr, PinErr>>

Returns the current power amplifier level as a PALevel enum.

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

pub fn flush_tx(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>

Flush transmission FIFO, used in TX mode.

§Examples
chip.flush_tx()?;
Source

pub fn flush_rx(&mut self) -> Result<(), TransferError<SPIErr, PinErr>>

Flush reciever FIFO, used in RX mode.

§Examples
nrf24l01.flush_rx()?;
Source

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

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_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, ncs_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>( &mut self, delay: &mut D, ) -> Result<(), TransferError<SPIErr, PinErr>>
where D: DelayMs<u8>,

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<(), 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 up
Source

pub fn status(&mut self) -> Result<Status, TransferError<SPIErr, PinErr>>

Reads the status register from device. See Status.

Source

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

Trait Implementations§

Source§

impl<SPI, CE, NCS> Debug for Nrf24l01<SPI, CE, NCS>
where SPI: Debug, CE: Debug, NCS: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

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

§

impl<SPI, CE, NCS> RefUnwindSafe for Nrf24l01<SPI, CE, NCS>

§

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

§

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

§

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

§

impl<SPI, CE, NCS> UnwindSafe for Nrf24l01<SPI, CE, NCS>
where SPI: UnwindSafe, NCS: 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.