Jan 01 2013

nRF905 AVR/Arduino Library/Driver

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 from GitHub
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
UPDATE: Use 470R instead of
4k7 and 1k instead of 10k
Zener
UPDATE: Use 470R instead of 4k7
res_div 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 is only a total of 170 usable channels at once.

Searching for nRF905, PTR8000 and PTR8000+ should yield some results for modules on 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 it 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 Payload CRC = 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 setting 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!

512 comments

2 pings

Skip to comment form

    • Jasmin on October 8, 2016 at 11:36 am
    • Reply

    while(!nRF905_send());
    is this how i will put it in a while loop? i’ve tried it but the arduino does not read sensor data anymore

    1. Yup. You could see if the ping example works as that has the send in a while() loop, if the example doesn’t work then you might have a wiring issue (probably to do with the CD pin).

        • Jasmin on October 8, 2016 at 11:51 am
        • Reply

        it does not work πŸ™ however, i checked the CD pin and it is connected to pin2. all the other pins are also connected correctly.

        1. Did you load ping_client on to one Arduino, and ping_server onto another? There’s definitely a wiring issue if pings don’t work, could you post some picture of your setup?

            • Jasmin on October 8, 2016 at 12:00 pm

            Yes we did. where can i post the pictures? do you need the picture of the connections?

          1. You can upload to https://imgur.com Yeah, pictures of all the wires connecting the Arduino to the radio module.

    • Jasmin on October 8, 2016 at 12:13 pm
    • Reply

    http://imgur.com/a/nq7vU
    here are the pictures.

    • Jasmin on October 8, 2016 at 12:19 pm
    • Reply

    we tried again, it’s not ping time out anymore. but on the other side, it only outputs waiting for ping.

    1. Ah, you’re using a MEGA. Have you changed INTERRUPT_NUM to 5 in nRF905_config.h?

        • Jasmin on October 8, 2016 at 2:38 pm
        • Reply

        oh, i’ve changed it before but now that i have checked it, it went back to 1. ugh. now it is working thank you ^_^ but there are many garbage data, how can we eliminate or lessen those?

        1. Hah alright πŸ˜› Can you post a screen shot showing the bad data?

            • Jasmin on October 11, 2016 at 4:37 pm

            http://imgur.com/a/fF1sU
            here’s the screen shot πŸ™‚

          1. What does your latest code look like now? (pastebin)

    • Jasmin on October 8, 2016 at 12:22 pm
    • Reply

    http://imgur.com/a/a3m1N
    here is the print screen of the output from the ping example

    • Brian on October 11, 2016 at 5:17 pm
    • Reply

    Hey I’m having trouble getting these two NRF905 modules talking with two Arduino Uno R3 controllers. I have followed your Arduino Uno connections to the letter and I am using the ping_client, ping_server code provided. I have the digital pins directly connected to the NRF905 pins. When I change the interrupt to 0 (as I’ve read in through the comments) in the config file the client prints out:

    Client started
    Ping time: 0ms
    Data from server:
    …etc

    and the server:

    Server started
    Waiting for ping…

    Nothing happens in the server side after that. I’m guessing the receiver isn’t working? Would you have any suggestions? I’ve been racking my brain all day. I’ve used recommended below connections: Thank you for your help and time!

    * 7 -> CE
    * 8 -> PWR
    * 9 -> TXE
    * 2 -> CD
    * 3 -> DR
    * 10 -> CSN
    * 12 -> SO
    * 11 -> SI
    * 13 -> SCK

    1. Hi Brian, if the ping time is 0 or 1 then there is a problem with the client side, as it already takes around 6ms just for the radio to transmit the packet. What does the debug example print out?

        • Brian on October 14, 2016 at 5:31 am
        • Reply

        Hey Zak,

        Thanks for the reply! Sorry in the client side it does display 6ms afterwards, but the issue is the receiver I believe. It’s just stays at the “waiting for ping….” print. Are there different pin connections for the receiver side? I have both wired exactly the same according to your tutorial.

        Thanks!

        1. 6ms still means there’s an issue on the client side, it should timeout if it doesn’t get a response from the server. The “Data from server” part should print out “test #” where # is a number that increments if everything is ok. Both sides have the same connections, could you post a picture of the client side connections? Upload to http://imgur.com

    • Jasmin on October 14, 2016 at 8:39 pm
    • Reply

    Hello Zak! I would like to ask if it is possible to increase the maximum payload in your program from 32 bytes to 64 bytes? If yes, how can we implement it? Thanks!

    1. No, 32 bytes is the limit as that the maximum payload the nRF905 radio can send.

    • Jasmin on October 16, 2016 at 12:28 pm
    • Reply

    Hey πŸ™‚ I have another question. The serial monitor freezes when I send a frame. What can i do to solve this?

    1. What sketch are you running on the Arduino?

        • Jasmin on October 16, 2016 at 9:08 pm
        • Reply

        http://pastebin.com/NXamBDG6 here is for the TX
        http://pastebin.com/5hzu6YM1 here is for the RX

        1. You’ve got a lot going on there, I don’t really have time to go though it all. Though, I’d try to avoid using strings as they tend to eat up a lot of RAM, which the Arduino doesn’t have much of. Instead of strings use byte arrays or char arrays and use numeric values or characters to indicate what type of packet it is. [0] could be the packet type (1 = ENQ, 2 = ACK, 3 = EOT …), [1] could be the message length and the rest are the bytes is the message data. You don’t really need CRC as the radio already does all that stuff, and if the received packet is corrupted then it is automatically discarded.

            • Jasmin on October 17, 2016 at 6:42 am

            I’ve tried using bytes but i can’t put it in an if else condition even if i tried to convert the received bytes into string. What can be the solution to this?

          1. You can do conditionals on individual bytes like this:

            if(myArray[0] == 1)
            {
            }
            
    • Jasmin on October 25, 2016 at 11:45 am
    • Reply

    hey i tried it but it lags what should i do πŸ™

    1. I’m not sure what you mean by it lags?

        • Jasmin on October 25, 2016 at 12:25 pm
        • Reply

        the serial monitor freezes.

        1. The Arduino is probably crashing or getting stuck in a loop, what’s your latest code like?

            • Jasmin on October 25, 2016 at 12:36 pm

            http://pastebin.com/bBXWEaXx – for the rx
            http://pastebin.com/Mmx8PmpM – for the tx

          1. Looks ok to me, although the transmitter will be spamming out packets since it doesn’t have any delays between transmissions. Put more Serial.print debugging messages around the code, so you can see exactly where it gets to.

    • Jasmin on October 27, 2016 at 4:27 am
    • Reply

    ohhh okay i’ll try. hey, i have another question. can i put pins 2 3 7 and 51 52 53 into another input? im also using an lcd tft and the pins collided.

    1. 2 and 7 can be moved to any pin.
      3 must be connected to an interrupt pin, unless you’ve disabled interrupts with NRF905_INTERRUPTS 0 then it can be any pin.
      Make sure you update the nRF905_config.h file.
      50, 51 and 52 can’t change as they connect to the SPI bus, unless you modify the library to use software SPI then you can move to any pin.
      53 can be moved to any pin.

      SPI pins (50, 51 and 52) can be shared with multiple SPI devices.

    • Michael on January 13, 2017 at 2:24 am
    • Reply

    Hi Zak,

    Thanks for the blog, it’s been a great help to get communication between two Arduino Unos. I don’t have enough pins on the receiver for other sensors, so am trying to set this up with an Arduino Mega 2560. Like a few other respondents to the blog am having difficulty with the Mega, but I think I am very close. I have follow your instructions and set INTERRUPT_NUM to 5 in nRF905_config.h and changed the pins:
    11 -> 51
    12 -> 50
    13 -> 52

    With the INTERRUPT_NUM set to 1 the debug sketch seemed to work OK – see below.

    Started
    Raw: 108 12 68 32 32 229 166 76 254 2 Channel: 108
    Freq: 433200KHz
    Auto retransmit: 0 Low power
    RX: 0
    TX Power: 10dBm
    Band: 433MHz
    TX Address width: 4
    RX Address width: 4
    RX Payload size: 32
    TX Payload size: 32
    RX Address [0]: 229
    RX Address [1]: 166
    RX Address [2]: 76
    RX Address [3]: 254
    RX Address: 4266436325
    CRC Mode: 16bit
    Xtal freq: 16MHz
    Clock out freq: Disabled

    But when I set it to 5 it runs with errors – see below.

    All registers read as 0xFF or 0x00! Is the nRF905 connected correctly?
    Raw: 0 0 0 0 0 0 0 0 0 0

    With INTERRUPT_NUM set to 5 and the Mega set up as the ping server I get communication, but the data appear to sometimes scramble – see below.

    On the server ……..
    Data: Β£+›‘‰�
    Waiting for ping… Got ping
    Sending reply… Reply sent
    On the client ……..
    Ping time 122ms
    Data from the server: Β£+›‘‰�

    No communication when I set the Mega up as the client

    I have the wirelessSerialLink and my own sketch working with the two Unos, but neither work with the Mega.

    Any suggestions would be much appreciated?

    Thanks
    Michael

    1. Hey Michael, odd that the debug sketch doesn’t work with INTERRUPT_NUM 5, since it doesn’t use any interrupt stuff to read the config registers. Everything else seems fine. Since the nRF905 is a 3.3V device and the Arduino uses 5V signalling, how are you doing the level conversion? Is the nRF905 the only thing connected to the Mega?

    • ksshin on January 18, 2017 at 5:50 am
    • Reply

    Thank you, this saved me a lot of trouble.
    I had to rename *.c files into *.cpp to get this working (Xubuntu 16.04 + default Arduino package), but maybe it does not happen on other Arduino IDE installations?

    1. Hey, for Arduino you should use the files from the Arduino folder, which are already .cpp and include example code written for Arduino.

    • stevestrong on February 4, 2017 at 5:44 pm
    • Reply

    Hi Zak,

    thank you for this great work.
    I am using your software, actually I rewrote it a bit for my needs, but still works fine.
    I am currently using my module only in receive mode, in 868 MHz range.
    So far so good.

    The only problem I have is the limited Rx range: if the transmitter is closer than 1 meter, all data is received OK.
    But I cannot receive anymore data if i place the transmitter more than 1 m away form the module.

    Could you maybe recommend what can I do in order to improve the Rx performance?

    Thank you in advance.
    Steve

    1. Hey Steve, nRF905 modules are usually only tuned for 433MHz operation. Using a different frequency band will result in very short range as you’ve found out. I don’t think I’ve came across any modules for 868MHz so you’ll probably have to design the module yourself, the nRF905 datasheet shows what components are needed for each frequency band.

    • Jean on March 2, 2017 at 11:14 am
    • Reply

    Hi there !
    First of all thanks for your work !
    I was able to make this working the client and server examples using an arduino UNO.
    I didn’t use power level conversion and it was still working, is it normal ?

    Then I tried with an arduino mega, changing SO SI and SCK pins as expected.
    I also updated the config.h changing the INTERRUPT_NUM to 5 as requested.
    Everything is compiling great.
    But this time when debugging I have “ing timeout” for the client and “Waiting for ping…” for the server

    Did I miss something ? πŸ™

    Jean (France)

      • Jean on March 5, 2017 at 11:11 am
      • Reply

      Hi zak,

      I finally achieved make it working.
      Indeed after having read every comments from the beginning, I found one saying that he solved the same problem as me by uncommenting and modifying these lines :
      #define REG_EXTERNAL_INT EIMSK
      #define BIT_EXTERNAL_INT INT5
      #define INT_VECTOR INT5_vect
      #define REG_EXTERNAL_INT_CTL EICRB
      #define BIT_EXTERNAL_INT_CTL (_BV(ISC51)|_BV(ISC50))
      Now it’s working even if it’s surprising that I need that knowing that I’ve already changed the INT_NUM to 5.

      Anyway, I would like to ask you a new question :
      I have a TX which send a string every 100ms.
      I have a RX which receive this string and analyse it : I added a TIMEOUT if the RX doesn’t receive anything during 1 second (in order to stop motors running in my specific case).
      To test that I disconnect the TX and it’s working fine (the RX stop).
      But when I connect the TX again, this takes around 5 seconds for the RX to receive again (in the meantime I display “timeout”).
      Does this time to reconnect is normal ? Do you have some advices to imporove that ?

      Thanks for you help
      Jean

      1. Hey Jean, I’ve just put a fix up on Github for the INTERRUPT_NUM issue, shouldn’t have to use the REG_EXTERNAL_INT stuff anymore. About the slow reconnect, add some Serial.println()s in your code to see where it’s taking its time. It should work straight away since there aren’t any connections being made with the radio modules, they just transmit to everything as fast as they can.

        Without any level conversion you are applying 5V to the IO pins, which are only meant to have 3.3V. This is slowly damaging the chip, and it’ll probably start going weird after a while.

    • Jasmin on June 25, 2017 at 11:17 am
    • Reply

    Hello, Zak πŸ™‚ Our group wants to thank you for all your help in our thesis. We finished it successfully. Thank you very much πŸ™‚

    1. Awesome, glad to hear that!

    • ICG on August 9, 2017 at 7:40 am
    • Reply

    how can i make communication distance longer?
    i succeed to test communication and after it, i tried to get “test” word by getting more distance from server.
    however, after 100m, the connection is lost. i expected it should be at least 200m (there was no obstacle).
    can you tell me somthing about it?

    1. Heya, how close to the ground the modules are (put them high up in the air), the antenna (quarter, half, full length), antenna gain, orientation of the antennas and impedance matching circuits on the module can all cause the range vary. Try different antennas or use a module that has a RF power amplifier built-in.

    • fly.ing.fox on August 10, 2017 at 9:53 am
    • Reply

    Hi Zak,

    great library – thank you for your work!

    I am using both an UNO and an ATMega Nano.

    I know I have to change the config file, however since I am using the library for both boards, compilation becomes a pain if I am testing different things out on both boards at the same time.

    Is it okay if I “re-publish” the library in my local system as a permanent change for the ATMega board? I do not intend to change any of your credits etc.

    Thanks In Advance,
    fly.ing.fox

    1. I’m not really sure what you mean by ‘as a permanent change for the ATMega board’, but I don’t see why not πŸ˜›

      It’s possible to edit the config and add a few preprocessor checks to see if it’s building for the Nano or Uno:

      #ifdef ARDUINO_AVR_UNO
      // uno config here
      #elif defined(ARDUINO_AVR_NANO)
      // nano config here
      #else
      #error "Unknown board!"
      #endif
      

      If you’re using separate sketches for each board then you can also copy the .cpp and .h files from the src folder into the sketch folders, then they’ll each have their own copies of the library.

    • Pilatte on August 29, 2017 at 9:38 pm
    • Reply

    Hello zac. Sorry for my bad language, I’m French.
    Thank you verry much for your library. I make a chronometer wireless with Nrf905 433Mhz, 10 dBm. It works good but how can i make communication distance longer?
    After 25m, the connection is lost. (there was no obstacle). I would like near 100m.
    can you tell me somthing about it?

    My board (modules) works on mega and uno
    http://www.dx.com/fr/p/nrf905-wireless-module-socket-adapter-plate-board-for-arduino-blue-428272#.WaXP5yhJbIU
    http://www.dx.com/fr/p/nrf905-433-868-915mhz-wireless-module-w-antenna-green-2-7-3-3v-222915#.WaXP-ihJbIU

    Thank you for your help.

    1. Hey Pilatte, you could try different antennas like THIS or use an nRF905 module with a built-in RF amplifier like THIS.

    1. The sketch/library can only adjust the transmit power, which is already set to the max (10dBm). That linked amp might work, however I’m not sure how it will react when the module transmits something.

        • Pilatte on August 30, 2017 at 8:05 pm
        • Reply

        Ok. I will try more options.
        Perhaps it’s not high enough (0.5m)
        Thanks for the advice

    • Roy on August 31, 2017 at 10:43 am
    • Reply

    Thanks for all the work you have put into this blog Zak – it is greatly appreciated.

    I have managed to get an arduino uno to send data to an arduino mega. the data represents the position of a joystick.

    The mega reads the data Ok . My problem is that the mega controls a DC motor and uses a feed back loop. The feedback loop reads an encoder so I need to implement an interrupt. Unfortunately as soon as I add an attachInterrupt statement I get an error when compiling as below.

    WInterrupts.c.o (symbol from plugin): In function `attachInterrupt’:

    (.text+0x0): multiple definition of `__vector_6′

    libraries\nRF905\nRF905.cpp.o (symbol from plugin):(.text+0x0): first defined here

    c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.9.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

    collect2.exe: error: ld returned 1 exit status

    exit status 1
    Error compiling for board Arduino/Genuino Mega or Mega 2560.

    It would appear that I am not able to assign interrupts to pins on the mega while I use your library. Is there a solution for this ?

    I would appreciate your help

    Thanks

    1. Hey Roy, this is because the library uses native AVR interrupts instead of Arduinos implementation (I’ll be updating the lib to use Arduino interrupts sometime). The fix is pretty easy, you can see what needs changing here – https://github.com/zkemble/nRF905/commit/00c223fdd243ded1ed7f77dee9dd014f4276f618

      In nRF905.cpp remove the line with ‘REG_EXTERNAL_INT_CTL |= BIT_EXTERNAL_INT_CTL;’ and change ‘ISR(INT_VECTOR)’ to ‘void nRF905_processInterrupt()’, then modify your nRF905.h to match the nRF905.h from the link above (only need to change 3 lines).

    • Roy on September 1, 2017 at 11:42 pm
    • Reply

    Thanks for your quick reply Zak. I made those modifications and reran my sketch and there were no error messages on compiling but the receiver no longer worked. So to make things simple I reran your ping server example. With no modifications to the cpp file the ping client and ping server communicate as expected but once I introduce the mods you suggested the ping server sits on

    server started
    waiting for ping…….

    your advice would be appreciated.

    1. Oops, the detachInterrupt(…) and attachInterrupt(…) lines are the wrong way around, swap them and see what happens.

        • Roy on September 5, 2017 at 12:14 am
        • Reply

        Thanks Zak working now

        • Roy on November 4, 2017 at 10:56 pm
        • Reply

        I have decided to improve my software on this project. After making the mods you suggested a couple of months ago the sketch compiled and down loaded and the device worked.
        However now when I recompile the original software the sketch no longer compiles. I have checked through carefully to make sure that none of the modifications you suggested have been corrupted and have not found any problems.

        The error message I receive is as follows

        :\Users\PETETH~1\AppData\Local\Temp\cc8cZZ5e.ltrans1.ltrans.o: In function `__vector_1′:

        cc8cZZ5e.ltrans1.o:(.text+0x8fc): undefined reference to `nRF905_processInterrupt()’

        cc8cZZ5e.ltrans1.o:(.text+0x8fe): undefined reference to `nRF905_processInterrupt()’

        collect2.exe: error: ld returned 1 exit status

        exit status 1
        Error compiling for board Arduino/Genuino Mega or Mega 2560.

        I would appreciate your help

        1. Hey Roy, I’m guessing you’re trying to use the mods with v3 of the library? A lot has changed so any mods probably won’t work now and probably won’t need anymore. Some function names have changed and it now uses callbacks, so you’ll have to look at the examples and update your program to work with the new library.

    • derp on September 2, 2017 at 2:17 pm
    • Reply

    Thanks for the library.

    The power off seems to be kind of bugged, if I do not periodically disable the clock output its power consumption dies increase to about 300uA. But if I disable the clock output every second (it was never enabled to begin with). it (and the ATmega) are using about 5uA.

    Do you know why this ist?

    1. Is the 300uA including the ATmega? The power down function only changes the state of a pin from HIGH to LOW, it doesn’t touch any register settings.

    • Hans on November 1, 2017 at 10:43 pm
    • Reply

    Hi. Thanks for investing time in this, first of all.
    I’ve built a receiver on an Arduino Ethernet and a WiFi, using this library. I’m sniffing data between commercial home automation devices. Thing is, I seem to be missing [at least] a byte of information. I connected the HA device via USB, and via the Arduino console I can see it’s output, an so see what values it is receiving. I only changed the CSN pin for the Arduino Ethernet, from 10 to 5. I receive info from the HA device, 16 byte buffer, and tried to reverse engineer the values, so I can send them out via mqtt.

    Now, here’s the buffer I receive on the Arduino Ethernet (each byte separated by a dot):
    AB.24.7.0.FA.E3.2.0.0.0.0.0.0.1.0.0
    From the console, I can see that there should be a value of decimal 636 in here. This is hex 27C. The first four bytes are the same for all readings, and seem to indicate some sore of device address. The fifth I don’t know what it is, but also never changes. The sixth seems to be indicating the port that the value is received from, E3 is the one I’m looking for it seems. Now, the 2 is the 2 from the 27C. If the value changes to hex 3??, I see that change into a 3. But, the 7C is nowhere to be found. These readings occur quite often, and the serial monitor displays a different value received each time, but the buffer display from the Arduino Ethernet is often the same value as before. Djeez, I hope this still makes sense.
    Anyway, I believe that the 7C part is sent between HA devices, but doesn’t show up in my buffer. Is this in any way something that sounds familiar?

    1. Hey Hans, there’s no known issue with missing bytes, when nRF905_read() is called it just reads exactly what the nRF905 has received and places it into the provided buffer. How do you know that there should be a 0x7C byte?

        • Hans on November 5, 2017 at 9:59 pm
        • Reply

        Hi Zak, thanks for the reply.

        Yeah, the question was sort of a long shot. The HA receives data like current power consumption. The console output displays what it receives, but not in buffer but interpreted form (so current power usage is 600W). I have other readings (daily kWh for example), that consist of multiple bytes, which are received in reversed order. From those it also seems that the missing data should be in the byte after E3. I thought I might have similar issues as the bit shift issue mentioned in one of the comments. But I have stuff working on a NodeMCU also now, which is 3v, without level shifter, so that’s probably not it.

        Thing is, although I don’t know what I’m doing, I seem to have had some luck. The first three bytes consistently show addresses of slave devices that the HA device is receiving from. When the HA displays it received something, so does the nRF905. I can consistently get 868MhZ thermometer sensor values this way. There’s no garbage received by the nRF905. Since that address data is consistent, the rest probably is also. That makes me assume that I’ve tuned in to the right band and channel. Yet comparing data I receive with the interpreted data the HA is displaying (which means that it IS transmitted from slave to HA), it looks like I’m missing a byte of data for some slave devices.

        Since the HA code is not public domain, I cannot check any radio settings, so it’s hard to figure out what I’m doing wrong. Anyway, I will keep playing with it. Thanks again!

        1. The reversed bytes thing is probably due to the endianness. You could try sniffing the SPI bus inside the devices using a logic analyser which can be brought for around Β£5 on ebay or aliexpress, and use the software from here – https://www.saleae.com

            • Hans on November 7, 2017 at 12:54 am

            Oh, that would have been cool. But it’s not necessary anymore. I found the configuration (Band, channel, crc and stuff), so I was sure I had my receiver configured correctly. Still missing some data. In the end, I connected the receiver to a laptop, and walked downstairs, away from the HA and close to the slave device that is actually sending the data. Guess what. No more missing data. So it was interference, I might have been reading ACKS instead of the source data, or it was just a distance thing, or maybe a combination of both. Super glad it works though, and was certainly not an issue with the library.
            Again, thanks for helping me out here, sorry to have waisted your time.

            Cheers, Hans.

          1. Hah that’s alright πŸ˜› Though, if CRC is enabled it will detect the missing or corrupt data and report an invalid packet or nothing at all. But with raw radio stuff data doesn’t go missing, it just gets corrupted and the amount of data will stay the same.

    • Srikanth on November 25, 2017 at 12:35 pm
    • Reply

    I have two standalone arduino running at 8 MHz and the ping client- server example works well. My real world sketch however needs to use the timer1 interrupt which gets triggered every 10ms to do some housekeeping. I’m not sure if this is interrupting the NRF transmission but when the same ping code goes into my code , it does not function and says Packet Invalid.
    Will the rapid timer1 firing interrupt the NRF905 transmit code

    1. Hey Srikanth, by default the nRF905 uses 2 interrupt pins (AM and DR) where the timing of when these interrupts fire is important to correctly detect valid and invalid packets. If your interrupt takes a long to time to run then it could cause the library to mess up. You could try disabling the AM interrupt (NRF905_INTERRUPTS_AM 0 in nRF905_config.h), but then the invalid packet and address match callbacks won’t work (invalid packets will just be ignored), though that might be fine for your application if you’re not bothered about those two.

        • Srikanth on November 26, 2017 at 1:38 am
        • Reply

        Thank you Zak for your quick reply. I tried disabling all interrupts (NRF905_INTERRRUPTS 0 and NRF905_INTERRUPTS_AM 0) as I realized (too late) that my circuit uses the AM pin to run a LED matrix. I disconnected the connections to bot AM and DR pins as these are needed to be connected only if interrupts are used. But now the ping client just times out and the ping server waits for ever for reply.
        Are the ping client-server example not made to work without interrupts ?

          • Srikanth on November 26, 2017 at 3:47 am
          • Reply

          Dear Zak,
          I have tried various combinations of removing requirement of AM and DR pins
          As mentioned in config.h, I have set NRF905_INTERRUPTS as 0 and NRF905_DR_SW as 1 and NRF905_INTERRUPT_AM as 0 and NRF905_AM_SW as 1 so apparently both AM and DR can be left connected as checking is done in software though maybe slowly. However the ping client times out every time and the ping server hangs on waiting for ping. Incidentally the pins have been left connected though disabled in config.
          When I change it back to use interrupts everything works as before. Unfortunately my PCB is actually made and I had counted on leaving out AM and DR by using a jumper (without actually checking if it works without interrupts). So I need to get the code to work without interrupts as I have no spare pins to assign to my LED matrix
          Regards

            • Zak Kemble on November 26, 2017 at 6:25 am
              Author

            Ah, to use the library without interrupts the nRF905_SERVICE() function should to be called as often as possible (which none of the examples use at the moment). See if you can get it working by sticking nRF905_SERVICE() in the various while loops of the ping examples.

            • Srikanth on November 26, 2017 at 1:25 pm

            Calling nRF905_SERVICE seemed to work on the client side but server was still unresponsive (dont know how that could happen). I finally found an unused pin (A0) on an unused device on PCB and tried to change the config to use that as AM (as the pins were very close on the PCB) but it still did not work (why ? A0 is an interrupt pin too) . Finally I routed that free pin to the LED matrix and used the original C3 as AM and everything works ! (For your info : The devices I’m making is a network of connected synchronized clocks. One of the devices runs on a DS3231 set by a GPS; the rest run a timer based software clock and are updated every minute by the master device with the GPS clock via teh nRF network. All slaves share the same receive address)
            So I have worked around the problem for now. would have been convenient if the AM had worked on A0 though. Thanks a million Zak for your great library and promptness in your replies. I can see you have been keeping that up for over 4 years ! Regards !

            • Zak Kemble on November 26, 2017 at 3:02 pm
              Author

            Hah thanks πŸ˜›
            A0 is only a pin change interrupt like all pins (PCINTx), but the library only supports using external interrupts (INTx). This is because PCINTx interrupts are shared between multiple pins and Arduino doesn’t have any built-in way of dealing with them, which makes it hard to have two or more libraries using PCINTx stuff. Though it should be pretty easy to modifiy the nRF905 lib to use PCINTx if you wanted to.

            • Srikanth on November 26, 2017 at 1:52 pm

            One more question. Now that I have them synced the receivers usually lag 1 sec behind the master. As the typical ping time is only 16 ms, is there anyway I could get them to sync better than that ? Like say calculate a transmission delay and add that ? I’m very tempted to add 1 sec via software at the receiver and am sure we could not make out the difference but is there a better way of getting say a 100 ms sync ? How do ZigBee’s synchronize time ?

            • Zak Kemble on November 26, 2017 at 3:02 pm
              Author

            This really depends on how your code works. Does the master send the time at 0 milliseconds, or does it use a seperate timer? Is a millisecond counter on the slaves reset or not when the new time is received? Might be best to post your code to https://pastebin.com
            I’ve no idea how ZigBees do it.

    • Srikanth on December 9, 2017 at 8:50 am
    • Reply

    Dear Zak,
    I got my NRF905 synchronised clocks to work based on your replies and they are working satisfactorily now.
    The next thing I need to do is that there are 5 -6 such devices one on each floor. I need messages to be passed by anyone to the other. I do not want to assign a separate address to each device as I want the single message to be broadcast to all the other 4. I have checked separately that my messages can reach from one floor to 4 floors away as they are almost in line of sight in the stairway. But as a failsafe, , the plan is that each device has a software device number (say one to 5) . A message is sent by device 1. Devices 2-4 receive it as they have the same receive address (as does device 1). After a latency equal to 2x (message transmission time) x deviceNum the receiving device also broadcasts the message again . The message also contains one byte info about who has initiated it and who is re-transmitting it and a message ID no. So that if the same message ID has been just received within the last 1 sec, it is ignored. That way I can ensure that even the last most distant nRF receives it. That way the same message gets sent 5 times, one by each node so that it is sort of like a rudimentary mesh network.

    My question is if all Rx addresses are the same, will the first device have a problem by its own message echoing back to it or will that not happen as the device will be in transmit mode and hence its own message will not be seen by it ?

    Will this system work for a few nodes ? It is basically a signalling system in a small 4 floor clinic where the device at each floor will be able to transmit different alarm conditions to each floor – like fire, earthquake, cardiac arrest, theft etc, so the entire personnel are immediately alerted.

    I initally thought of doing this as Device one transmits only to 2 and device 2 to 3 but that would be less elegant as for eg if one device fails and is replaced the other devices will also need to be re-programmed

    Thanks

    1. Good stuff πŸ™‚ Transmitting radios cannot receive anything, even their own transmissions, so no need to worry about echoing messages there. It sounds like your mesh idea should work, but even though the radios already have a basic collision avoidance system you might still need to see about the problem of multiple nodes transmitting at the exact same time. I’ve not done mesh networking stuff before, so you’ll have to do some experimenting.

  1. […] are used include the standard SPI library provided in the Arduino IDE.  We will also use the nRF905.h library developed by Zak Kemble.  Zak’s nRF905 library will initialized power, provide the communication addresses, and […]

Leave a Reply

Your email address will not be published.

Are you human? *