3
votes

I have an Arduino project that is using an nRF24l01+ radio module over SPI (using this library: http://tmrh20.github.io/RF24/) and an RFID reader over softwareserial. I am sleeping my Arduino and having them wake it up via interrupt when a message has been received or an RFID tag is ready to be read. The RFID is on pins 4 and 5, while the nRF covers pins 9 - 13 as well as number 2 for its interrupt.

Both of these modules work fine with the sleep and interrupt code separately, but when combined in to a single sketch, the Arduino will wake up due to an RFID tag, read it, then try to send something over the radio and then just hang, waiting for the library call to write() to return.

I have delved a bit into the two libraries, but I mostly can't make heads or tails of the softwareserial library. It seems to maybe be using the same ISR behind the scenes as my nRF module, but I don't immediately see why that should be a big problem, and I don't understand why it should cause the radio to hang.

I know it may be a long shot, but does anyone have any idea what might be going on? Maybe somebody knows these libraries? Any thoughts on a work around? Thanks.

1
do you mean software SPI with the RFID reader?Eric Kelly
RFID reader uses softwareserial, hence uses UART type protocol. The nRF uses SPI.MaxStrange
so i take it the hardware serial ports are all taken? Anyway, they should work together fine. How is the radio powered? a separate supply? is this an uno? if it's a uno and you're using the 3.3v i would use a separate 3.3v supply as the current capacity of it is pretty tiny and adding another device for example could make it stop working. However, if that's not the case, then after reading from RFID disable the software serial so it doesn't turn off interrupts (in case it gets another while you try to transmit). see if it works. its a software issue or power issue with the radioEric Kelly
Also add some filter caps to the radio, no doubt it's the Chinese clones which seem rather sensitive and aren't the same as the real authentic ones.Eric Kelly
The hardware serial ports were taken, but I have fiddled with the circuit to free them up now that I am having trouble with the softwareserial. I will change to those pins and try using the normal serial. It is a pro mini 3.3v 8 MHz, and it is powered by 2 AAs through a boost converter to 3.3. Same voltage supply for the nRF, which is most certainly a cheap Chinese knockoff - can't resist the price :PMaxStrange

1 Answers

0
votes

I was experiencing the same symptoms, and the problem turned out to be a buffer overrun in my code. The overrun itself was due to SoftwareSerial dropping bytes because the RF24 library was interring with its interrupt handling.

The code in question reads from a GPS receiver using SoftwareSerial, parses the NMEA sentences and extracts the latitude and longitude information for sending over radio using RF24. It goes something like this:

if (gpsSerial.available()) {
  int c = gpsSerial.read();
  if (c == '\r') {
    buf[bdx] = '\0';
    // process buf here, which contains a null terminated NMEA sentence
    // and then send via RF24
    bdx = 0;
  else if (c != '\n' && bdx < BUFLEN) buf[bdx++] = c;
}

Where BUFLEN was sized to be larger than any single NMEA sentence.

The experienced reader will pick up on the problematic line:

buf[bdx] = '\0';

Which writes to buf without a range check. In normal operation, with an uninterrupted stream of characters from the GPS module, this code works fine, because we will always encounter a \r before running out of space in buf. However sending information over RF24 causes enough delays that characters are dropped or corrupted by SoftwareSerial, and this assumption no longer holds.

So now what happens is this:

  1. a \r is missed, and the previous NMEA sentence is not discarded
  2. the next NMEA sentence is read into buf
  3. bdx advances until stopped by the range check in the else
  4. \r of the next NMEA sentence is countered
  5. buf[bdx] = '\0'; writes past the end of buf

At this point the Arduino stops responding, and it looks like write is blocking.

The fix is this line added before the if:

if (bdx >= BUFLEN) bdx = 0;

With no other modification than this line, the code has now been running for over 5 hours without issue, whereas previously it would not last more than 30 seconds before write "blocks".