nRF905 Radio Library for AVR and Arduino

The nRF905 is a radio transceiver IC similar to the well known nRF24L01, but operates at 433/898/915MHz instead of 2.4GHz, has a much longer range and a few extra IO pins. However, the nRF905 data rate is only 50Kbps compared to nRF24L01’s 2Mbps.

This library offers quite a bit of flexibility: Optional use of interrupts, 2 of the connections to the module are optional since their states can also be accessed by the ICs status register, and supports basic collision avoidance.

NOTE: v3.0.0 of the library was released on 12th September 2017, the default CD pin has changed and the AM pin is now used by the library.

Download:
ArduinoDocumentation (or use the Arduino library manager, search for “nrf905”)
AVR (non-Arduino)
Documentation

nRF905 ATmega48/88/168/328 Arduino Uno Description
VCC 3.3V 3.3V Power (3.3V)
CE D7 (13) 7 Standby – High = TX/RX mode, Low = standby
TXE B1 (15) 9 TX or RX mode – High = TX, Low = RX
PWR B0 (14) 8 Power-up – High = on, Low = off
CD D4 (6) 4 Carrier detect – High when a signal is detected, for collision avoidance
AM D2 (4) 2 Address Match – High when receiving a packet that has the same address as the one set for this device, optional since state is stored in register, if interrupts are used (default) then this pin must be connected
DR D3 (5) 3 Data Ready – High when finished transmitting/High when new data received, optional since state is stored in register, if interrupts are used (default) then this pin must be connected
SO B4 (18) 12 SPI MISO (Mega pin 50)
SI B3 (17) 11 SPI MOSI (Mega pin 51)
SCK B5 (19) 13 SPI SCK (Mega pin 52)
CSN B2 (16) 10 SPI SS
GND GND GND Ground

Some of the module pin names differ from the IC pin names in the datasheet:

Module IC
CE TRX_EN
TXE TX_EN

The nRF905 is not 5V compatible, so some level conversions will need to be done with the Arduino outputs. A simple voltage divider or resistor and zener diode will do the trick. Only TXE, CE, PWR, SI, SCK and CSN pins need level conversion (not CD, AM, DR and SO).

Divider Zener

The nRF905 has 511 channels ranging 422.4MHz – 473.5MHz in 100KHz steps on the 433MHz band and 844.8MHz – 947MHz in 200KHz steps on the 868/915MHz band (remember to check which frequencies are legal in your country!), but each channel overlaps adjacent channels so there are only a total of 170 usable channels at once.

Searching for nRF905, PTR8000 and PTR8000+ should yield some results for modules on AliExpress, Ebay and DealExtreme. You should be able to get 2 for around £10.

Callbacks
Since v3.0.0 this library uses callbacks which are ran when events occur. If the option to use interrupts is enabled then the callbacks will run from the interrupt routine so be sure that any global variables you use in them are declared ‘volatile’, just as you would when dealing with normal ISRs. These events will wake the microcontroller if it is sleeping.

Event Callback Notes
New packet incoming NRF905_CB_ADDRMATCH  
Valid packet received NRF905_CB_RXCOMPLETE  
Invalid packet received NRF905_CB_RXINVALID  
Packet transmission complete NRF905_CB_TXCOMPLETE This only works if the nextMode is NRF905_NEXTMODE_STANDBY when calling nRF905_TX()

Nitty-gritty radio stuff
The actual air data-rate of nRF905 is 100Kbps, but the data is Manchester encoded which halves the throughput to 50Kbps. The modulation is GFSK with ±50KHz deviation. The radio also adds a few extra bits of data to the address and payload; a preamble and CRC.

Transmitted packet
Preamble
10 bits
Address
1 or 4 bytes
Payload
1 – 32 bytes
CRC
0 – 2 bytes

The address is also used as the syncword and should have as many level shifts as possible. 10100110 01100101 00011010 11011010 (2791643866) would be a good address to use, but 00000000 00000000 00000000 0010000 (32) would not be.

The CRC is used to detect errors in the received data. Having a CRC doesn’t eliminate all bad packets, there is always a small chance of a bad packet passing the CRC. Using larger CRCs helps to reduce that chance.
When the CRC is set to 16 bit the radio uses the CRC16-CCITT-FALSE (0xFFFF) algorithm. I’m not sure what it uses for 8 bit CRCs.

Transmission time
The sizes of the address, payload and CRC can be adjusted for a balance between throughput and latency.

Example configurations
Address size Payload size CRC size = Throughput (bps) Latency (ms)
4 32 2 = 36940 6.93
1 4 1 = 17680 1.81
1 1 0 = 6838 1.17

Throughput is how much useful data can be sent (the payload part), assuming no delays for writing and reading the payload.
Latency is how long it takes for the transmission to complete.
Switching from standby mode to receive or transmit mode takes a maximum of 650us and switching between receive and transmit modes takes a maximum of 550us.

Transmission time can be worked out with:

t = tstartup + tpreamble + ((Naddress + Npayload + NCRC) / BR)

tstartup is the time to switch mode as stated above (650us / 550us).
tpreamble is 200us for the 10 bit preamble.
Naddress, Npayload and NCRC are the address, payload and CRC sizes in bits.
BR is the bit rate which is 50,000.

For config 1, switching from standby to transmit:

t = 0.00065 + 0.0002 + ((32 + 256 + 16) / 50000)
t = 0.00693 seconds (6.93ms)

A note to developers: Before v3.0.0 this library would load the address bytes in reverse order, keep that in mind if you’re using an old version of the library to interface with other radio systems!

618 comments

3 pings

Skip to comment form

    • Chris on July 28, 2019 at 7:31 pm
    • Reply

    Hello Zak,
    First of all thank you for this library. Great work!
    The communication of my modules works flawlessly. I have also connected 2 Sevomotors to the Mega (PIN 40 and 42 with separate power supply) which permanently ticks when the communication starts. Do you have any idea why this could be?
    Many thanks and best regards,
    Chris

    1. Hey Chris, thanks! You’ll have to post your code before I can see what’s up! -> https://pastebin.com/

    • Tim on September 27, 2019 at 8:23 pm
    • Reply

    Hi Zak, I’ve built a few of these links running at 4800 baud to handle 30 bytes of data every 250mS running at 433MHz carrier.

    However on one of the links it runs ok for about 20 seconds then hangs no tx or rx activity. This problem can happen at either end and I suspect it may actually be nRf905 module related.

    I’ve tried disabling IRQ and other variants but always the same result.

    Pressing the reset button on the tx Arduino fixes the problem. Maybe there’s an overflow problem somewhere ?

    Any pointers on how to debug ?

    I’ll try slowing down the refresh rate from 250mS to 1S and see what happens

    • Tim on September 27, 2019 at 8:52 pm
    • Reply

    Hi Zak, me again. Just reduced the update rate to 1 second and still the same problem. However looking at the MOSI pin on the nRF905 when the sending end stops transmitting there is not the normal activity on this pin – looks as though some is corruption.
    Then it’ll start up again.

    Time for a beer – will look at this again tomorrow as I’m well down a ‘rabbit hole’ here 🙂

    • Tim on September 28, 2019 at 8:52 pm
    • Reply

    Hi Zak,

    further to my last e mail about a problem I was having – I’ve managed to fix it.
    I’m running the wireless UART example and found that it would hang in the rx loop and not detect incoming traffic unless the device was reset.
    This problem appears with both the Arduino and AVR code on 2 out of 5 links.
    I fixed it by putting a watch timer set to 1 second which gets reset on transmission or reception of data.
    Thus when the rx stops getting traffic the watch dog kicks in and restarts the link.
    Bit of a bodge as I’m not sure how to get to the root cause.
    Before this fix when the rx hung the carrier detect line didn’t work – so suspect it could be the nRf905 losing it settings and needing to be re-initialized ?

    Regards Tim

    1. Hey Tim, the wireless link example isn’t really very reliable, but it shouldn’t cause things to hang. Things will get even more wack if you’ve got 5 modules with the wireless link example all talking to each other, since it’s only meant for 2 modules! I don’t think the modules are loosing their settings, what state are the TXE, DR and CE pins in when it hangs?

        • Tim on September 28, 2019 at 9:53 pm
        • Reply

        Hi Zak,

        thanks for the reply – just to clarify I’m only using them in pairs but have seen this problem on a couple of pairs and the problem moves with a particular unit.
        Each pair is far enough away not to cause mutual interference and operate on a clear frequency in the 70cm 433MHz band for which I’m licensed.
        By wrapping some extra code around yours combined with the watch dog timer it’s now fairly robust.
        I’ll check the TXE, DR and CE lines when it hangs and report back.

        Best regards Tim

    • Tim on September 29, 2019 at 12:58 pm
    • Reply

    Hi Zak,

    when the rx hangs all the lines are as they should be – a bit more testing seems to indicate the rx crash is possibly being caused by something on the tx side.

    Maybe irq collisions between UART and SPI ?

    I’m sending a total of 30 characters including a string terminator and I suspect this might be the root cause as this is the maximum allowed #define MAX_PACKET_SIZE (NRF905_MAX_PAYLOAD – 2).

    Wonder why maxpayload is -2 ?

    As I’m always sending a fixed length message I’m wondering if there’s a better way to assemble the message in the nano ready for the nRF905 to process it ?

    Currently I’m sending the message character by character at 4800 – just for fun I’ll try 9600.

    Regards Tim

    • Tim on September 29, 2019 at 7:42 pm
    • Reply

    Hi Zak,

    still plugging away at this and learning / discovering as I go along. As I suspected sometimes the tx gets corrupted and either sends jibberish or only part of the packet – maybe roughly once out of a 100 packets.
    I see you mention in your code about needing a 700uS delay going from tx to rx to avoid this so I set it to 1mS then 2mS and seems to have helped but not perfect.
    I also tried to remove your ‘ack code’ – seemed pretty obvious how it worked but strangely it shortened the tx data packet.
    Time for another break and reflection !
    I’m thinking it maybe the nRF905 chip – perhaps a counterfeit device ?
    I have another batch of nRF905’s coming so will see if that helps.

    Regards Tim

    • Tim on September 30, 2019 at 7:29 pm
    • Reply

    Ok, I’m 99% certain it’s a dodgy chip problem as my code works fine on 4 out of 5 links and never misses a beat.

    On the plus side it’s caused me to refine the protocol and generally harden the code to cope with drop outs and missed data.

    I’m going to install the next batch of nRF905 modules in sockets for easy test and replace meant !

    Thanks for a great piece of code and listening to my trials and tribulations !

    • saniul on October 2, 2019 at 1:05 am
    • Reply

    Hi Zak,
    I need your help. I need to transmit a constant data through the nrf905 transceiver module at 915mhz band. I have a arduino uno and a nano. can you please tell me how to set up the whole thing and code for transmitting a constant data. I need these for my final year project. Another thing, Can it jam a mobile signal which operates under 915mhz frequency band? I know it’s illegal to make a jammer but I am working on this project which needs to jam a signal, Which I would use with my bomb disposing robot.

    1. lol I’m not going to do your school work for you.

    • Geoffrey Brown on December 4, 2019 at 11:23 pm
    • Reply

    There are a number of NRF905 + STC15F204 combinations available from various places:

    https://www.aliexpress.com/item/32931569323.html?spm=a2g0o.productlist.0.0.16195be05Nt8Xe&algo_pvid=ba66008d-0bfd-4ec7-ab0b-c23d5750a36b&algo_expid=ba66008d-0bfd-4ec7-ab0b-c23d5750a36b-25&btsid=7bee88fa-c4ed-4600-84b8-b34c31622546&ws_ab_test=searchweb0_0,searchweb201602_2,searchweb201603_55

    The STC module appears to have defined pins for certain functions (presumably for TxE, DR, CD etc).

    https://1drv.ms/u/s!Am_AnSJTVHLYmo8ib-sQB_OszURpew?e=yHpupr

    It appears that the device uses a serial interface perhaps for a lot of functions and the pin assignments indicate to me that there is no SPI interface as on a mega these use D50-D52. The fact that it references P34 and P55 indicates this is intended for connection to a Arduino Mega only as other processors, to my knowledge, don’t have these pins. I think the DR and AM pins need to go to external interrupt lines so the fact that none of the labelled ports, to my knowledge.

    I suspect it was perhaps produced for a company for a specific need hence the reason that there is little available on it on the internet.

    Anyway, if you can shed any light on this it would be much appreciated.

    Geoffrey Brown, Papamoa, NZ.

    1. Hi Geoffrey, those STC15F204/NRF905 modules are plain serial-RF bridges, and are not compatible with this library (it runs its own code on the STC15F204). Those extra pin holes appear to be extra GPIOs from the STC15F204 microcontroller rather than connections to the nRF905 module. I don’t think they have any special protocol, just send it serial data at the correct baud rate and out pops the data wherever other modules are that are in range.

    • Andrei on December 9, 2019 at 1:09 pm
    • Reply

    Is it possible to change pins 2,3,4 and 7 to analog pins? As far as I know, analog pins can be used as digital, but not the ones with pwm.

    Thanks!

    1. Hey Andrei! Pins 4 and 7 can be moved around anywhere (change things in nRF905_config.h), but 2 and 3 must be interrupt pins unless you disable interrupts (NRF905_INTERRUPTS 0).

    • Geoffrey Brown on January 25, 2020 at 9:26 am
    • Reply

    I believe I have uncovered a little issue with this library, in particular, in regards the nRF905_TX routine.

    I, like some others have mentioned, have had a situation whereby the communications have come to an end and the Arduino Mega, in my case, needed to be restarted.

    The issue I believe is as follows:

    uint8_t nRF905_TX(uint32_t sendTo, void* data, uint8_t len, nRF905_nextmode_t nextMode)
    {
    // TODO check DR is low?

    NRF905_NO_INTERRUPT()
    {
    if(nRF905_airwayBusy())
    return 0;

    setAddress(sendTo, NRF905_CMD_W_TX_ADDRESS);

    // Load new payload
    if(data != NULL)
    {
    NRF905_ATOMIC()
    {
    CHIPSELECT()
    {
    spi_transfer_nr(NRF905_CMD_W_TX_PAYLOAD);
    for(uint8_t i=0;i<len;i++)
    spi_transfer_nr(((uint8_t*)data)[i]);
    }
    }
    }

    if(!POWERED_UP())
    {
    STANDBY_ENTER();
    POWER_UP();
    delay_ms(3);
    }

    if(nRF905_airwayBusy()) //PROBLEM LOCATION ACCORDING TO GEOFFREY
    return 0;

    // Put into transmit mode
    MODE_TX();

    // Pulse standby pin to start transmission
    STANDBY_LEAVE();

    if(nextMode == NRF905_NEXTMODE_RX)
    {
    // The datasheets says that the radio can switch straight to RX mode after
    // a transmission is complete by clearing TX_EN while transmitting, but
    // if this is done within ~700us the transmission seems to get corrupt.
    delay_us(700);
    MODE_RX();
    }
    else if(nextMode == NRF905_NEXTMODE_STANDBY)
    {
    delay_us(14);
    STANDBY_ENTER();
    }
    // else NRF905_NEXTMODE_TX
    }

    return 1;
    }

    What happens is that the CHIPSELECT() part that is inside the NRF905_ATOMIC section does two things as seen in its associated define (if I have things right):

    #define CHIPSELECT(standby) standby; for(uint8_t _cs = cselect(); _cs; _cs = cdeselect())

    #define STANDBY_LEAVE() (digitalWrite(NRF905_TRX_EN, HIGH))
    #define STANDBY_ENTER() (digitalWrite(NRF905_TRX_EN, LOW))
    #define STANDBY (STANDBY_ENTER())

    It enters standby mode (CE line goes low) as the first step. Note that in Zac’s code NRF905_TRX_EN is synonymous with CE (chip enable). The second part (in the for loop) toggles the CSN pin.
    So if we look at the first part of the code we have:

    if(data != NULL)
    {
    NRF905_ATOMIC()
    {
    CHIPSELECT()
    {
    spi_transfer_nr(NRF905_CMD_W_TX_PAYLOAD);
    for(uint8_t i=0;i<len;i++)
    spi_transfer_nr(((uint8_t*)data)[i]);
    }
    }
    }

    And NRF905_ATOMIC has the following define:

    #define NRF905_ATOMIC() for(uint8_t _cs2=interrupt_off(); _cs2; _cs2=interrupt_on())

    So this NRF905_ATOMIC part of the loop turns interrupts off then on again at the end of the loop. The CHIPSELECT inside this turns the NRF905 into standby mode (CE low) and pulses the CSN line low while SPI communications are occurring:

    Now if COLLISION_AVOID is enabled (default) the second nrf905_airwayBusy check is made. This is marked as //PROBLEM LOCATION in code above and reproduced below:

    if(nRF905_airwayBusy())
    return 0;

    // Put into transmit mode
    MODE_TX();

    // Pulse standby pin to start transmission
    STANDBY_LEAVE();

    The end result is that if the NRF905 is busy receiving a packet at this point in the code (nrf905_airwayBusy is true) the nRF905_TX routine causes the device to return with the NRF905 in a standby state (from the CHIPSELECT loop) and the STANDBY_LEAVE never occurs as this code is after the return 0 of the second nRF905_airwayBusy and so is never reached. The upshot is that the nRF905_TX routine returns having left the NRF905 in a standby mode and the packet transmit has not started. The device will not receive another packet even if the device was in receive mode before the nRF905_TX routine was called (refer nRF905_RX()). If the code abandons the transmit of the packet then we have the signals left in the following state according to my multimeter:

    TXE 0V (read mode)
    CE 0V (also TRX_EN in code; device in standby) – this is the problem
    PWR 3.2V (device powered on)
    AM 0V (no address matched because device in standby mode)
    DR 0V (no data ready because nothing happening)

    The interrupts are left enabled (from the NRF905_ATOMIC loop completing fine). The CSN line is also left in the correct state because the CHIPSELECT loop completes as well.

    If the packet being sent was in response to a packet received (the last one) and if this issue occurs in nRF905_TX and the nRF905_TX is abandoned in the code for whatever reason then the nRF905_TX leaves the system in an mode where nothing will be received again until nRF905_RX() is called.

    What is needed is one of three solutions:

    1) Don’t perform the second check of nRF905_airwayBusy because you already did it at start of nRF905_TX routine – my preferred answer. The second nRF905_airwayBusy and the return is what is causing this issue.

    2) In the second nRF905_airwayBusy check do the following:

    if(nRF905_airwayBusy()) {
    STANDBY_LEAVE();
    return 0;
    }

    3) After any failed nRF905_TX immediately call nRF905_RX() to restore an operational receive mode.

    This will undo the effect of the CHIPSELECT having entered standby mode.

    Thoughts…

    1. Hi Geoffrey, I get where you’re coming from about the CHIPSELECT() standby stuff, however this is not the case. The first parameter of the CHIPSELECT() statement is blank, which means that “standby” in the #define is also blank, and does not enter standby mode. To enter standby mode it would have to be written as CHIPSELECT(STANDBY), but this was only used in older verions of the library in a few places.
      The only way nRF905_TX() might assert the standby pin is by setting nextMode to NRF905_NEXTMODE_STANDBY.

        • Geoffrey Brown on March 2, 2020 at 9:15 am
        • Reply

        Many thanks for that feedback. Very useful. Have some more learning on #defines to do…

    • Michael on October 29, 2020 at 5:57 am
    • Reply

    hi,
    Brand new to all of this.
    I wired as per the diagram and opened the supplied code in the IDE. Tried to upload but got errors with the include statement . copied all of the nRF905 folder to the libraries but no luck. Copied the individual files into the same folder as the sketch and it seems better. i now get:

    In file included from nRF905.c:15:0:
    /usr/share/arduino/libraries/SPI/SPI.h:36:1: error: unknown type name ‘class’
    class SPIClass {
    ^
    /usr/share/arduino/libraries/SPI/SPI.h:36:16: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{‘ token
    class SPIClass {
    ^

    1. You’re using the files for non-Arduino stuff, only use the stuff in the arduino folder. Also, try using the new library here – https://github.com/zkemble/nRF905-arduino

        • Michael on October 29, 2020 at 11:29 pm
        • Reply

        I really appreciate the reply Zak. Have downloaded the files from Github however they seem to be only examples. I copied the nRF905-master/arduino/nRF905 library files to ~/Arduino/library/nRF905 and also to /usr/share/arduino/library/nRF905 however it did not much difference.

        I then tried to run the lowpwr_note_baseStation and got the following error:

        lowpwr_node_baseStation.ino:20:22: fatal error: LowPower.h: No such file or directory
        compilation terminated.

        Sorry for my lack of understanding.

        1. I’m not sure what you mean by they’re only examples, but to fix your error you also need this library https://github.com/rocketscream/Low-Power

          • Michael on October 30, 2020 at 1:08 am
          • Reply

          Hi again Zak,
          Well, I have found one very silly thing I should have though about earlier – my preferences were pointing to the wrong directory!! No wonder it could not find the library.
          It seems to be compiling and uploading OK now. Now I just need to waiting on my second nRF905 arriving before I can test it.

    • Andrei on January 3, 2021 at 9:18 am
    • Reply

    I’m trying to compile wireless serial example, but i get this errors…
    wirelessSerialLink:40:18: error: 'NRF905_ADDR_SIZE' was not declared in this scope
    byte dstAddress[NRF905_ADDR_SIZE];
    ^~~~~~~~~~~~~~~~
    C:\Users\Andrei\Google Drive\Arduino\libraries\nRF905_Radio_Library\examples\wirelessSerialLink\wirelessSerialLink.ino:40:18: note: suggested alternative: 'NRF905_ADDR_SIZE_RX'
    byte dstAddress[NRF905_ADDR_SIZE];
    ^~~~~~~~~~~~~~~~
    NRF905_ADDR_SIZE_RX
    C:\Users\Andrei\Google Drive\Arduino\libraries\nRF905_Radio_Library\examples\wirelessSerialLink\wirelessSerialLink.ino: In function 'void NRF905_CB_RXCOMPLETE()':
    wirelessSerialLink:52:2: error: 'nRF905_read' was not declared in this scope
    nRF905_read((byte*)newData, sizeof(newData));
    ^~~~~~~~~~~

    (*ADMIN EDIT* Shortened error messages)

    I’ve used your library in the past, but it was working fine. Any suggestion?

    1. Hey Andrei, that’s expected. The wireless serial example has a comment at the top that says “DONT USE THIS EXAMPLE, IT STILL NEEDS TO BE UPDATED FOR THE NEW VERSION OF THE NRF905 LIBRARY (v4)”.

        • Andrei on January 3, 2021 at 11:41 am
        • Reply

        :)) I’m sure you are tired of ignorants.
        Sorry for bothering you. I needed the code, I knew it as a working code and took it…surprise.

        1. It’s fine 🙂 If you really need the old stuff working again then you can get v3.1.0 from here https://github.com/zkemble/nRF905/releases/tag/v3.1.0

    • Pablo on April 13, 2021 at 11:57 am
    • Reply

    Hi, are you usign Manchester Encoded data before GFSK Modulation in “lowpwr_node_sensor” example?

    Thanks and amazing repository! 🙂

    1. Hi Pablo, data is automatically manchester encoded and decoded by the radio IC.

    • Jarosław on April 21, 2021 at 10:01 am
    • Reply

    Hello.
    I want to pair 2 devices. I have a problem with addressing. I generate random addresses for devices, and this is not a problem. The problem is to assign a generated UINT32_T number in HEX format to the variable in which I want to keep the address. I tried through string, but without the effect. There is still a problem with the data type.
    Can you help me?
    Greetings.

    p.s. code:
    uint32_t RXADDR = 0xE7E7E7E7; //this work
    uint32_t buforWysylany.adresMiernika = random(268435456,368435456);
    RXADDR = “0x”+ (buforWysylany.adresMiernika ,HEX); //this is my problem

    1. Hi Jaroslaw, the 0x part tells the compiler that its a hex value, which tells it to convert 0xE7E7E7E7 to 3890735079 decimal during compilation. All you need is RXADDR = buforWysylany.adresMiernika; without any string conversion.

        • Jarosław on April 21, 2021 at 11:38 am
        • Reply

        Hmmm.
        I think I tried so. I will try again.
        Thank you for the quick reply.

    • henry on April 23, 2021 at 11:35 am
    • Reply

    Hi all,

    i would like to be able to send a single message to all my NRF905 and get a message back.

    Is this possible or i need to send individual message to each radio devices ?

    BR/

    1. Hi Henry, if all of the receiving radios have the same address then they will all receive the same message. However, if you also want all of them to reply to that message then you will have to make sure that only 1 radio transmits at a time, otherwise the transmissions will corrupt each other. The library does include some collision avoidance where it checks for other transmissions before transmitting, but it may not be 100% effective. It’s probably easier to send a message to each radio one at a time (each radio will need a unique address).

        • henry on April 23, 2021 at 2:16 pm
        • Reply

        Hi Zak,

        thanks for a such prompt answer !

        No unfortunately not, each device will have its own address. i was thinking, at “switch on” of the server, to interrogate all the “client” devices in order to know which ones are up and running and optionally to ask them for the revision of their software.
        I guess i will stick to a certain range of addressees and ping them all sequentially. Unless you come up with good idea 🙂

        BR/

    • Ollie Roberts on September 9, 2021 at 7:04 am
    • Reply

    Hi Zak
    I don’t know if you still check these comments but i’m having trouble with this library, If you do still check these comments could you give me a hand?
    Im using a arduino uno and the nRF905 transceiver to transmit 32bites on the 433mhz frequency band, Im using the “low_pwr_node_sensor” example to base my code off but my the code keeps on getting stuck at the “while (!txDone)”, i made it print “waiting” in the serial monitor when its doing this loop to see what happens and the serial just keeps on printing “waiting” indicating that code is getting stuck on the loop so i dont know if the loop and “ontxcomplete” event isnt working properly or if the radio is just not transmitting. If you could have a look at my code (as per below) and let me know whats wrong. Thanks (let me know if you need more info)

    /*
     * Project: nRF905 Radio Library for Arduino (Low power sensor node example)
     * Author: Zak Kemble, contact@zakkemble.net
     * Copyright: (C) 2020 by Zak Kemble
     * License: GNU GPL v3 (see License.txt)
     * Web: https://blog.zakkemble.net/nrf905-avrarduino-librarydriver/
     */
    
    // This examples requires the low power library from https://github.com/rocketscream/Low-Power
    
    // This examples configures the nRF905 library to only use 5 connections:
    // MOSI
    // MISO
    // SCK
    // SS -> 6
    // PWR -> 8
    
    // The following pins on the nRF905 must be connected to VCC (3.3V) or GND:
    // CE (TRX_EN) -> VCC
    // TXE (TX_EN) -> VCC
    
    #include 
    #include 
    #include 
    
    byte mess_Address = {0xB54CAB34};
    byte Message[] = {0b00000000, 0b10000001, 0b10000010, 0b10000011, 0b10000100, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10011000, 0b10101000, 0b10111000, 0b11001000, 0b11011000, 0b11101000, 0b11111001, 0b00101001, 0b00111001, 0b01011001, 0b01101001, 0b01111001, 0b10011010, 0b10011011, 0b10011101, 0b10011110, 0b10011111, 0b10101010, 0b11101011, 0b01101011, 0b11101101, 0b11101110, 0b11111111};
    
    
    nRF905 transceiver = nRF905();
    
    static bool txDone; // NOTE: In polling mode this does not need to be volatile
    
    // Event function for TX completion
    void nRF905_onTxComplete(nRF905* device)
    {
    	txDone = true;
    }
    
    void setup()
    {
    	Serial.begin(115200);
    	Serial.println(F("Sensor node starting..."));
    
    
    	// standby off TODO
    	//pinMode(7, OUTPUT);
    	//digitalWrite(7, HIGH);
    	// pwr
    	//pinMode(8, OUTPUT);
    	//digitalWrite(8, HIGH);
    	// trx
    	//pinMode(9, OUTPUT);
    	//digitalWrite(9, HIGH);
    	
    	
    	// This must be called first
    	SPI.begin();
    
    	// Minimal wires (polling mode)
    	// Up to 5 wires can be disconnected, however this will reduce functionalliy and will put the library into polling mode instead of interrupt mode.
    	// In polling mode the .poll() method must be called as often as possible. If .poll() is not called often enough then events may be missed.
    	transceiver.begin(
    		SPI,
    		10000000,
    		6,
    		NRF905_PIN_UNUSED, // CE (standby) pin must be connected to VCC (3.3V)
    		NRF905_PIN_UNUSED, // TRX (RX/TX mode) pin must be connected to VCC (3.3V) (force TX mode)
    		8, // PWR
    		NRF905_PIN_UNUSED, // Without the CD pin collision avoidance will be disabled
    		NRF905_PIN_UNUSED, // Without the DR pin the library will run in polling mode and poll the status register over SPI. This also means the nRF905 can not wake the MCU up from sleep mode
    		NRF905_PIN_UNUSED, // Without the AM pin the library must poll the status register over SPI.
    		NULL, // Running in polling mode so no interrupt function
    		NULL // Running in polling mode so no interrupt function
    	);
    
    	// Register event functions
    	transceiver.events(
    		NULL,
    		NULL,
    		nRF905_onTxComplete,
    		NULL
    	);
    
    	// Low-mid transmit level -2dBm (631uW)
    	transceiver.setTransmitPower(NRF905_PWR_10);
      transceiver.setChannel(106);
      transceiver.setBand(NRF905_BAND_433);
      transceiver.setPayloadSize(32, 0); // Will transmit 5 byte payloads, receive 32 byte payloads
      transceiver.setAddressSize(4, 4);
    
      Serial.println(F("Transciever Started"));
    }
    
    void loop()
    {
    
    	Serial.println("---");
    
    	// Write data to radio
    	transceiver.write(mess_Address, Message, sizeof(Message));
    
    	txDone = false;
    
    	// This will power-up the radio and send the data
    	transceiver.TX(NRF905_NEXTMODE_TX, false);
    
    	// Transmission will take approx 6-7ms to complete (smaller paylaod sizes will be faster)
    	while(!txDone)
    		transceiver.poll();
        Serial.println(F("waiting"));
    	// Transmission done, power-down the radio
    	transceiver.powerDown();
    	Serial.println(F("Transciever complete"));
    
    	// NOTE:
    	// After the payload has been sent the radio will continue to transmit an empty carrier wave until .powerDown() is called. Since this is a sensor node that doesn't need to receive data, only transmit and go into low power mode, this example hard wires the radio into TX mode (TXE connected to VCC) to reduce number of connections to the Arduino.
    	// TODO
    	// Sleep for 64 seconds
    	//uint8_t sleepCounter = 8;
    	//while(sleepCounter--)
    	// Sleep for 1 second
    		LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
    }
    1. Hi Ollie, your “waiting” message is outside of the while loop (you need to put the while code inside { and } if it’s more than 1 line), so if you’re currently seeing the message then it’s working.

        • Ollie Roberts on September 9, 2021 at 11:00 am
        • Reply

        Hi Zak
        I just gave this a go and it now just spams the terminal with “waiting” implying the loop is not ending and the transmission isnt being completed, can you make sure theres nothing else wrong with my code and if theres not i might try a new nRF905 Transceiver. Also im using a Logic level converter (https://learn.sparkfun.com/tutorials/bi-directional-logic-level-converter-hookup-guide/all) to convert the 5v to 3.3v, could that be the problem?

        New code BTW

        /*
           Project: nRF905 Radio Library for Arduino (Low power sensor node example)
           Author: Zak Kemble, contact@zakkemble.net
           Copyright: (C) 2020 by Zak Kemble
           License: GNU GPL v3 (see License.txt)
           Web: https://blog.zakkemble.net/nrf905-avrarduino-librarydriver/
        */
        
        // This examples requires the low power library from https://github.com/rocketscream/Low-Power
        
        // This examples configures the nRF905 library to only use 5 connections:
        // MOSI
        // MISO
        // SCK
        // SS -> 6
        // PWR -> 8
        
        // The following pins on the nRF905 must be connected to VCC (3.3V) or GND:
        // CE (TRX_EN) -> VCC
        // TXE (TX_EN) -> VCC
        
        #include 
        #include 
        #include 
        
        byte mess_Address = {0xB54CAB34};
        byte Message[] = {0b00000000, 0b10000001, 0b10000010, 0b10000011, 0b10000100, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10011000, 0b10101000, 0b10111000, 0b11001000, 0b11011000, 0b11101000, 0b11111001, 0b00101001, 0b00111001, 0b01011001, 0b01101001, 0b01111001, 0b10011010, 0b10011011, 0b10011101, 0b10011110, 0b10011111, 0b10101010, 0b11101011, 0b01101011, 0b11101101, 0b11101110, 0b11111111};
        
        
        nRF905 transceiver = nRF905();
        
        static bool txDone; // NOTE: In polling mode this does not need to be volatile
        
        // Event function for TX completion
        void nRF905_onTxComplete(nRF905* device)
        {
          txDone = true;
        }
        
        void setup()
        {
          Serial.begin(115200);
          Serial.println(F("Sensor node starting..."));
        
        
          // standby off TODO
          //pinMode(7, OUTPUT);
          //digitalWrite(7, HIGH);
          // pwr
          //pinMode(8, OUTPUT);
          //digitalWrite(8, HIGH);
          // trx
          //pinMode(9, OUTPUT);
          //digitalWrite(9, HIGH);
        
        
          // This must be called first
          SPI.begin();
        
          // Minimal wires (polling mode)
          // Up to 5 wires can be disconnected, however this will reduce functionalliy and will put the library into polling mode instead of interrupt mode.
          // In polling mode the .poll() method must be called as often as possible. If .poll() is not called often enough then events may be missed.
          transceiver.begin(
            SPI,
            10000000,
            6,
            NRF905_PIN_UNUSED, // CE (standby) pin must be connected to VCC (3.3V)
            NRF905_PIN_UNUSED, // TRX (RX/TX mode) pin must be connected to VCC (3.3V) (force TX mode)
            8, // PWR
            NRF905_PIN_UNUSED, // Without the CD pin collision avoidance will be disabled
            NRF905_PIN_UNUSED, // Without the DR pin the library will run in polling mode and poll the status register over SPI. This also means the nRF905 can not wake the MCU up from sleep mode
            NRF905_PIN_UNUSED, // Without the AM pin the library must poll the status register over SPI.
            NULL, // Running in polling mode so no interrupt function
            NULL // Running in polling mode so no interrupt function
          );
        
          // Register event functions
          transceiver.events(
            NULL,
            NULL,
            nRF905_onTxComplete,
            NULL
          );
        
          // Low-mid transmit level -2dBm (631uW)
          transceiver.setTransmitPower(NRF905_PWR_10);
          transceiver.setChannel(106);
          transceiver.setBand(NRF905_BAND_433);
          transceiver.setPayloadSize(32, 0); // Will transmit 5 byte payloads, receive 32 byte payloads
          transceiver.setAddressSize(4, 4);
        
          Serial.println(F("Transciever Started"));
        }
        
        void loop()
        {
        
          Serial.println("---");
        
          // Write data to radio
          transceiver.write(mess_Address, Message, sizeof(Message));
        
          txDone = false;
        
          // This will power-up the radio and send the data
          transceiver.TX(NRF905_NEXTMODE_TX, false);
        
          // Transmission will take approx 6-7ms to complete (smaller paylaod sizes will be faster)
          while (!txDone) {
            transceiver.poll();
            Serial.println(F("waiting"));
          }
          // Transmission done, power-down the radio
          transceiver.powerDown();
          Serial.println(F("Transciever complete"));
        
          // NOTE:
          // After the payload has been sent the radio will continue to transmit an empty carrier wave until .powerDown() is called. Since this is a sensor node that doesn't need to receive data, only transmit and go into low power mode, this example hard wires the radio into TX mode (TXE connected to VCC) to reduce number of connections to the Arduino.
          // TODO
          // Sleep for 64 seconds
          //uint8_t sleepCounter = 8;
          //while(sleepCounter--)
          // Sleep for 1 second
          LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
        }
        1. It will spam while it is waiting for the transmission to complete, around 6-7ms, then stop for 1 second. Does it print “Transciever complete” at all? The logic level converter might be too slow for the SPI clock, change 10000000 to 125000 in transceiver.begin(....

          Also try replacing LowPower.powerDown(... with delay(1000);

            • Ollie Roberts on September 9, 2021 at 11:50 am

            Unfortunately it didn’t and actually crashed the serial monitor, i assume you mean 6-7 milliseconds right. i only have the mosi, miso, sck, ss, pwr, txeN and ce connected like the library says is that correct? Also just to be sure is MOSI labeled as si, is MISO labeled as so and is SS labeled as CSN on the nRF905? I’ve also attached some images here with my hardware setup, its messy because i only have long wires but maybe you can see something wrong with it https://imgur.com/a/uyHQ64T (Red wire – 5v or 3.3v, Blue – TXeN, Green – CE, Grey – PWR, Orange – MOSI, Yellow – MISO, White – SCK, Purply brown – CSN, Black – ground) If theres nothing wrong with anything ill try a new nRF905 Transceiver. Thanks

          1. Yes, 6-7 milliseconds. Your wiring looks ok and you’ve got the naming correct. Try adding delay(1); into the while loop, it should then only print “waiting” around 6 times rather than spamming it and also try the other things mentioned in my last comment. I would also use a different serial terminal rather than the Arduino one, like Realterm.

            • Ollie Roberts on September 12, 2021 at 4:23 am

            Hi again Zak,
            Sorry for bothering you but i just tried to use another nRF905 Transceiver with another arduino to try and receive the transmission from the nRF905 that i was asking about earlier to make sure it was working and the receiver isn’t receiving anything from the other nRF905 other than some random junk. As you can probably tell i’m not much of a code person so could you see if theres anything wrong with the code? Also what is the range of the transmitter??

            Reciever Code
            https://pastebin.com/2bKFaZHV

            Transmitter code
            https://pastebin.com/BaCHX4h6

          2. Ok, sounds like it’s receiving valid data, but something gets messed up between the module and Arduino. What data did you expect to see what did you actually get? Also try running the debug example.
            In your transmitter code you’ve commented out .powerDown(), it would be best to put it back in and take note of the note just below that line.

Leave a Reply to Roland Cancel reply

Your email address will not be published.

Are you human? *