1

Setup

  • I have 2 Arduinos... each has two 2.4 GHz nRF24L01+ transceivers (so in total 4).
  • Per Arduino, one is only for transmitting, while the other is for receiving (to prevent the need for switching between transmitting and receiving).
  • The receiver and transmitter are on different channels (per Arduino, so channel 109 for receiver on arduino 1 and transmitter on arduino 2 and 112 for the other pair).

SPI / Chip Select

Because the nRF24L01+ are SPI devices, I need to use Chip Select, since there is only one SPI bus on an Arduino.

Setup settings

Since I can both receive and send (successfully) I did not add the Setup code (I used slowest speed 250 kbps, 16 bytes payload, no auto ack, no retries, highest power).

Problem

I can transmit/receive from both Arduinos, so all 4 transceivers work correctly. However, what I see in the output (see directly after the logging), is when I send, a lot of messages which should be received are missed. See the log at the end

Also, when I remove the write and replace it by a delay(1) than I miss just occasionally a message, so I think the write is the problem.

Assumption

Is it possible that during the write so many message from the other Arduino are colliding? I would expect a very fast on-air time, and even than, using two different channels should not make messages collide.

So it seems, while calling the Transmit for one RF, the other does not receive somehow. I know the CS pin of the receiver is HIGH (inactive) during transmitting (transmitter CS pin is LOW), but I would assume messages would be received by the RF, and when I set the CS pin of the receiver to LOW (active), that I can read the messages.

Code (of one of the Arduinos)

The code for the other Arduino is almost similar (only opposite port names as transmitter/receiver)

/*
*/
#include <SPI.h>
#include "RF24.h"

static const uint8_t RECEIVER_CE    = 5; // Chip Enable
static const uint8_t RECEIVER_CS    = 6; // Chip Select
static const uint8_t TRANSMITTER_CE = 7; // Chip Enable
static const uint8_t TRANSMITTER_CS = 8; // Chip Select

RF24 radioReceiver(RECEIVER_CE, RECEIVER_CS);
RF24 radioTransmitter(TRANSMITTER_CE, TRANSMITTER_CS);

uint32_t counter = 0;

static const int PAYLOAD_SIZE = 16;

static const int NR_OF_LOG_ITEMS = 10;
static const int LOG_LENGTH = 25;
uint32_t logData[LOG_LENGTH][NR_OF_LOG_ITEMS];
uint8_t currentLogLine = 0;

void setup()
{
  for (int m = 0; m < LOG_LENGTH; m++)
  {
    for (int n = 0; n < NR_OF_LOG_ITEMS; n++)
    {
      logData[m][n] = -1;
    }
  }

  pinMode(RECEIVER_CE   , OUTPUT);
  pinMode(RECEIVER_CS   , OUTPUT);
  pinMode(TRANSMITTER_CE, OUTPUT);
  pinMode(TRANSMITTER_CS, OUTPUT);

  digitalWrite(RECEIVER_CE   , HIGH);
  digitalWrite(TRANSMITTER_CE, HIGH);

  Serial.begin(250000);
  Serial.println(F("CONTROLLER"));

  digitalWrite(RECEIVER_CS   , LOW); // Select
  digitalWrite(TRANSMITTER_CS, HIGH); // Deselect

  radioReceiver.begin();
  radioReceiver.setPALevel(RF24_PA_MAX);
  radioReceiver.setChannel(109);
  radioReceiver.setDataRate(RF24_250KBPS);
  radioReceiver.setRetries(0, 0);
  radioReceiver.setAutoAck(false);
  //radioReceiver.enableAckPayload();
  radioReceiver.setPayloadSize(PAYLOAD_SIZE);
  //radioReceiver.enableDynamicPayloads();
  //radioReceiver.disableCRC();
  radioReceiver.setCRCLength(RF24_CRC_8);

  digitalWrite(RECEIVER_CS   , HIGH); // Deselect
  digitalWrite(TRANSMITTER_CS, LOW);  // Select

  radioTransmitter.begin();
  radioTransmitter.setPALevel(RF24_PA_MAX);
  radioTransmitter.setChannel(112);
  radioTransmitter.setDataRate(RF24_250KBPS);
  radioTransmitter.setRetries(0, 0);
  radioTransmitter.setAutoAck(false);
  //radioTransmitter.enableAckPayload();
  radioTransmitter.setPayloadSize(PAYLOAD_SIZE);
  //radioTransmitter.enableDynamicPayloads();
  radioTransmitter.disableCRC();
  radioTransmitter.setCRCLength(RF24_CRC_8);

  byte addresses[][6] = {"Read ", "Write"}; // TODO: Change name to slave/contr?
  radioReceiver.openReadingPipe(0, addresses[1]);
  radioTransmitter.openWritingPipe(addresses[0]);

  radioReceiver.startListening();
  radioTransmitter.stopListening();

  //radio.writeAckPayload(1, &counter, PAYLOAD_SIZE);
  //radio.printDetails();
}


uint8_t receiverBuffer   [PAYLOAD_SIZE];
uint8_t transmitterBuffer[PAYLOAD_SIZE];

uint32_t prevResponse = -1;
uint32_t response;

void loop(void)
{
  // Transmit.
  //Serial.print("Sending: ");
  //Serial.println(counter);

  transmitterBuffer[0] = counter >> 24;
  transmitterBuffer[1] = (counter & 0x00FFFFFF) >> 16;
  transmitterBuffer[2] = (counter & 0x0000FF00) >> 8;
  transmitterBuffer[3] = (counter & 0x000000FF);

  digitalWrite(TRANSMITTER_CS, LOW);  // Select
  digitalWrite(RECEIVER_CS   , HIGH); // Deselect
  //if (!radioTransmitter.write(transmitterBuffer, PAYLOAD_SIZE))
  {
    //Serial.println(F("Sending failed."));
  }
  delay(10); // Fake write

  // Receive.
  byte pipeNo = 0;

  digitalWrite(TRANSMITTER_CS, HIGH);  // Deselect
  digitalWrite(RECEIVER_CS   , LOW); // Select

  while ( radioReceiver.available(&pipeNo))
  {
    radioReceiver.read(receiverBuffer, PAYLOAD_SIZE);

    response = (receiverBuffer[0] << 24) +
               (receiverBuffer[1] << 16) +
               (receiverBuffer[2] << 8) +
               (receiverBuffer[3]);
    Serial.print("Received: ");
    Serial.print(response);

    if (prevResponse == -1)
    {
      prevResponse = response - 1;
    }
    else
    {
      if (prevResponse + 1 != response)
      {
        Serial.print(" MISSED ");
        Serial.print(response - prevResponse - 1);
      }
      prevResponse = response;
    }
    Serial.println("");
  }

  // Logging
  currentLogLine++;
  counter++;
  delay(10);  // Try again later
}

Log

Received: 10261 MISSED 15
Received: 10262
Received: 10263
Sending: 245
Received: 10278 MISSED 14
Received: 10279
Received: 10280
Sending: 246
Received: 10296 MISSED 15
Received: 10298 MISSED 1
Received: 10299
Sending: 247
  • "A complete minimal verifiable example" :) Am I right in assuming response and prevresponse are longs? Am not quite sure if you are doing what I think is this one Arduino talking to itself or two Arduinos talking to each other? If its the latter how do you know that the when you are transmitting from Ard.A the Ard.B is receiving? (Not familiar with these radios, so it might be a stupid question) – Code Gorilla Aug 4 '17 at 11:54
  • @CodeGorilla I added the full code (for the slave, which is similar to the controller), and yes two Arduinos (slave/controller) talk to each other, both arduinos have 2 RFs, one transmitting only and one receiving only. THey have different frequencies and different SPI SlaveSelect pins. – Michel Keijzers Aug 4 '17 at 19:22
  • Brilliant. So how do you synchronise the transmissions on A with the receive on B? I think what might be happening is A is transmitting before B is receiving and that is why you are loosing packets. Does that sound reasonable? – Code Gorilla Aug 4 '17 at 19:58
  • @CodeGorilla Thanks (I guess) ... I don't synchronize to be honest. Since sending is only done by two RFs (on two different Arduino's) and two different frequency ranges, I don't expect any collisions. It's like a two lane highway (or street), bidirectional. I am planning to implement my own acknowledgement system (since I want to send data along with the ack signal with data that might not readily be available). – Michel Keijzers Aug 4 '17 at 20:51
  • (later it will be more complicated when there will be multiple Arduinos transmitting, but I try to solve this problem first for making it more complicated. – Michel Keijzers Aug 4 '17 at 20:52
1

[solved] ... I found out I HAVE to put one of the CS (chip select) pins to pin 10.

I thought it would not needed since the CS pin is different per SPI device, but it seems one needs to be on pin 10. Or at least, now I don't get problems sending/receiving (except some errors now and than, but that's normal with RF devices).

Thanks for everybody giving comments to my question.

  • 1
    You don't have to actually use it as a CS pin, but pin 10 MUST be an output according to the documentation for the SPI library. – Delta_G Aug 6 '17 at 22:24
  • @Delta_G I did not do that when I posted the question... but I can better use pin 10 anyway as CS as output pin in this case to make sure I don't use it for anything else (and forget making it an output pin again)... thanks for the valid comment. – Michel Keijzers Aug 6 '17 at 22:31
  • 1
    Quite right, it just has to be an output. I suggest accepting your answer. – Nick Gammon Sep 6 '17 at 0:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.