nRF905 — an another module for wireless communication

You might be already familiar with different transceivers I have described here, namely LoRa module. You can read about it here (STM32 driver for LoRa) and here (Raspberry Pi driver for LoRa). Now, time have come to give nRF905 module a try. As usually, the driver alone and an example are available at my github. If you do not want to read the rest of this blog, just jump straight to nRF905 driver or the example.

What is nRF905?

The nRF905 is a wireless communication module which operates with 433/868/915 MHz frequency. It is using a GFSK (gauss frequency shift keying) modulation to transmit and receive data. At the top of this page you could already see how the nRF905 looks like. Actually, it is the whole module with an external antenna with SMA mounting.

This module has nice features. It consumes 9mA of current during -10dBm transmission and 12.5 mA during reception. This makes it perfect for remote controlled toys, devices etc. and it can be used as transmission module for IoT devices. This chip also has few nice-to-have features. It is capable of listening before transmitting any data. This way the chip provides a way to detect if there is on-going transmission and it will not send data if something else is on the air. Also nRF905 features address matching which allows to filter out messages which are not directed to the group of recipients. Other functionalities involve: automatic retransmission of a package and automatic check sum generation. Thanks to these two features the reliability of wireless media is increased.

The driver

Initially, the code was based on already existing driver for nRF905 but for AVR platform. The code was significantly reworked and now deliver hardware abstraction layer thanks to which it can be easily ported to a different platform, even for Raspberry Pi ;).

STM32 pinout configuration for nRF905

The nRF905 transceiver uses SPI interface as main communication interface. Based on the information provided by the vendor of this chip it can be concluded that the maximum frequency is up to 10 MHz, data package is 8 bit long starting with MSB, while polarity is set to low (ide state of the clock signal) and the data is latched on the first edge (or in this setup, also a rising edge). Moreover, the SPI should be configured in Full-Duplex Master mode meaning that the MCU is initiating transmission plus two data lines are being used allowing for simultaneous read and write operation.

Beside MOSI, MISO, SCK and chip select other pins are available like:

  • TXEN — defines if nRF905 works as transmitter or a receiver,
  • TRX_CE — enables or disables chip for transmission and reception,
  • PWR — enables the chip,
  • CD — carrier detect, responsible for discovering if there is ongoing transmission. Thanks to this it is possible to easily detect if some other nRF905 or similar chip is operating at the same frequency as the device.

Other useful information can be obtained directly from the chip through following pins, however these were not implemented (just in the example, the driver fully supports them):

  • AM — pin indicates if address was matched. Through this it would be easy to check if our device is the target for incoming message,
  • DR — indicates if data is ready, in other words, if data was received.

As mentioned above these two pin were not implemented in the example. However, it does not mean that the information they provide can not be accessed. By reading a status register inside nRF905 information about the address match or the data ready can be easily retrieved. Additionally, the driver supports hardware AM and DR pins. What is required is for you to chose available GPIOs as inputs and initialize the driver with it.

Example

Under this Github repository you can easily find an example which was configured for Stm32 Nucleo64-L452RE development board. The idea of this example is straight forward. To see how nRF905 operates you need two of these dev boards and two wireless modules. After you power up the devices they will constantly change operation mode between transmitter and receiver. However, to get meaningful transition you need to initialize one of the devices as master. Before powering up the device press and hold blue button or just reset the board (with black button) while holding blue button. This operation is needed in order to set different, predefined addresses of the devices since the address match feature is being used.

Below you can see two snippets of output coming from (the firs one) master, and the second one from slave.

The master

Mode: Master, TX, 25D34478
Reg conf: 0A, 0C, 44, 20, 20, 9B, C5, A0, 6D, D8, 
Sending (23): Hello 0, from 25D34478!
ret = 1
Switching to RX (25D34478)
Waiting for max 3700 ms
No response
Sending (23): Hello 1, from 25D34478!
ret = 1
Switching to RX (25D34478)
Waiting for max 3500 ms
Received: Hello 2, from 6DA0C59B!
Switching to TX (25D34478)
Sending (23): Hello 2, from 25D34478!
ret = 1
Switching to RX (25D34478)
Waiting for max 3800 ms
Received: Hello 3, from 6DA0C59B!
Switching to TX (25D34478)
Sending (23): Hello 3, from 25D34478!
ret = 1
Switching to RX (25D34478)
Waiting for max 3400 ms
Received: Hello 4, from 6DA0C59B!
Switching to TX (25D34478)
Sending (23): Hello 4, from 25D34478!
ret = 1
Switching to RX (25D34478)
Waiting for max 3600 ms
Received: Hello 5, from 6DA0C59B!
Switching to TX (25D34478)
Sending (23): Hello 5, from 25D34478!
ret = 1
Switching to RX (25D34478)
Waiting for max 3800 ms

The slave

Mode: Slave, RX, 6DA0C59B
Reg conf: 0A, 0C, 44, 20, 20, 78, 44, D3, 25, D8, 
Sending (23): Hello 0, from 6DA0C59B!
ret = 1
Switching to RX (6DA0C59B)
Waiting for max 2500 ms
No response
Sending (23): Hello 1, from 6DA0C59B!
ret = 1
Switching to RX (6DA0C59B)
Waiting for max 2200 ms
Received: Hello 1, from 25D34478!
Switching to TX (6DA0C59B)
Sending (23): Hello 2, from 6DA0C59B!
ret = 1
Switching to RX (6DA0C59B)
Waiting for max 2800 ms
Received: Hello 2, from 25D34478!
Switching to TX (6DA0C59B)
Sending (23): Hello 3, from 6DA0C59B!
ret = 1
Switching to RX (6DA0C59B)
Waiting for max 2100 ms
No response
Sending (23): Hello 4, from 6DA0C59B!
ret = 1
Switching to RX (6DA0C59B)
Waiting for max 3900 ms
Received: Hello 4, from 25D34478!
Switching to TX (6DA0C59B)
Sending (23): Hello 5, from 6DA0C59B!
ret = 1
Switching to RX (6DA0C59B)
Waiting for max 2100 ms
No response

From above it can be seen that one device is master initialized with 25D34478, while the second device is initialized with 6DA0C59B. The reason why sometimes “No response” entry can be seen is because one device has already sent the data while the second one was in RX/TX switching.

Conclusion

The described nRF905 module is a transceiver module which sends data using GFSK modulation. It is quite reliable and can be used with close-to-no-effort in any IoT project. In case you have missed the repositories with driver itself and an example here there are:

2 thoughts on “nRF905 — an another module for wireless communication

  1. Jakub W

    HI
    At first, your name looks polish. Are you from poland, do you speak polish, if yes we can switch to polish. But i writing this message because i have a problem.
    I am using stm32f103c8t6 with nrf905 module. I putted your example into my board, I want to have comunication between two devices, my first question is about connections, looking on top (when antenna is at right)
    VCC TX_EN
    CE PWR
    AD CD
    MISO MOSI
    SCK SS
    GND GND

    the pins which i connected to the pins UP (IDK = i don’t know)
    3V PB15
    PB14 PB13
    IDK PB12
    IDK IDK
    PB4 PB5
    PB3 PA4
    GND GND
    my second question is how should i configurate devices
    how to do it on device 1 which is slave and how to do it on seconds device
    I would be gratefull if you could help me

    Reply
  2. Wojciech Domski Post author

    Hi! Sorry for delayed message. Yes, I am from Poland but I prefer to write in English since it can reach more people.
    I would recommend you to have a look at the example project which I have created. The link could be found here: https://github.com/wdomski/NRF905-STM32-example/blob/main/Core/Src/main.c. This example provides a simple application which could be flashed on two boards. One is a slave and one is a master. The operation mode is selected through one of the GPIO pins. The difference between a master and a slave is only in their addresses, since each is sending data and waiting for some data to come in. However, the address part is what is important. Based on address you can detect if a message with given address matches your address. This way only messages with proper address assigned will be received.
    As for the pins. From what I can see you do not know about CD, AM and DR. These are described in the blog post. CD, this pin allows you if there is an ongoing transmission, in other words, if someone (not necessary you) is transmitting something. In order to check for this, you need to probe CD pin or use NRF905_airway_busy() function for this.
    The other two, AM and DR, might not be connected at all because the address match (AM) and data ready (DR) are mirrored to a status register. So, you do not need extra pins, what you could do instead it pull it from status register with NRF905_address_matched() and NRF905_data_ready(), respectively. To enable it, read from status register, simply set following fields as NULLs:
    NRF905_hw.gpio[NRF905_HW_GPIO_AM].pin = 0;
    NRF905_hw.gpio[NRF905_HW_GPIO_AM].port = NULL;
    NRF905_hw.gpio[NRF905_HW_GPIO_DR].pin = 0;
    NRF905_hw.gpio[NRF905_HW_GPIO_DR].port = NULL;
    Hope that helps, if anything else just write a message 😉

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.