SPI Communication using a NRF24L01 and a Nokia 5110 LCD

Well, since it's my first topic in here, let me introduce myself, My name is David Gudino and I'm a student of mechatronics engineer. I'm new at this arduino thing, but I know something about programming and electronic things, I've worked for IBM and I was an intern in continental automotive. So if I can help you with something just hit me back.

Anyway... I hope that this post fits this section of the forum.

Basicly I'm sending temperature, gas level in the air, and relative humidity from a PCM to a remote controller who also sends information to the PCM ( 2 analog positions from a joystick ( that will help me to control 4 motors with 4 VNH3SP30, using a mixing algorithm for throttle and position) and 4 different digital signals from push buttons that will activate 4 relays.

Here's the thing, I'm doing well with everything but the LCD communication since it's SPI protocol and so is the NRF24L01. I can stablish a duplex communication so I'm sending and receiving data from on way to another and vice versa, but now I need to show the values I'm getting from the PCM on the remote controller ( which has the nokia 5110 lcd), but when I tried it just broke down the communication and I can't even send or recive or show anything.

I don't know much on the practicing of SPI communication, I read that I must share pins for the MISO, MOSI and SCK, using the same for the LCD and the NRF24L01 and having a different CS control pin that will allow me to choose the slave I'm working with, in this case the LCD or the RF module. So I must catch or listening for the temp variable but when I get it, how do I show the temperature without losing any data from the RF module?

Any help will be very apreciated.

Thank you.

The nRF24L01+ always acts as an SPI slave and is controlled by two pins CE and CSN. It sends and receives data in 32 byte packets. As long as the Arduino accesses the nRF24 sufficiently often to collect each packet no data will be lost. The frequency with which packets are sent is obviously an important part of the system.

Have a look at this Simple nRF24L01+ Tutorial and follow up with more specific questions if required.

...R

Robin2:
The nRF24L01+ always acts as an SPI slave and is controlled by two pins CE and CSN. It sends and receives data in 32 byte packets. As long as the Arduino accesses the nRF24 sufficiently often to collect each packet no data will be lost. The frequency with which packets are sent is obviously an important part of the system.

Have a look at this Simple nRF24L01+ Tutorial and follow up with more specific questions if required.

...R

Well, sorry for the delay, I passed yesterday reading all the information, libraries, examples, etc, etc.

I wanted to thank you for the info, because I was using a role swap in the RF and I was having some troubles with the times, anyway I need to translate my code to the ackpayload before moving to the LCD thing.

I worked on that yesterday and had some troubles with it ( I'm using a Arduino Mega 2560 ) But now I have the example running well, Today I will try to make it work with my variables and functions and if everything works, I'll be back with an specific question about the SPI communication with the RF and the LCD and maybe then we can open a thread with two slaves in a arduino mega.

Thanks Robin, definitly you'll be on my thesis acknowledgements. :smiley:

Davidagudino:
I'll be back with an specific question about the SPI communication with the RF and the LCD and maybe then we can open a thread with two slaves in a arduino mega.

I find it much easier if you just use one Thread for one project because then all the info is in one place.

...R

Well, after being reading and trying to make it work and being realizing the schematic and layout for my electronic design at the same time, I get stuck once again in the same thing.

I have all my functions working fine, the one for the motor controller, one for the relays, and I used one of your examples for the NRF24L01 for transmition and reception in both sides with the Ackpayload.

I've read a lot of SPI communication, but I can't make my display work with the NRF24L01 at the same time, at this point if I get one of the slaves isolated It works just fine, even if I get them disable, but if i try to make it work together they just don't.

I just attached my codes below, the one that must show the values on the LCD display it's the transmitter.

Thanks in advance

receptor code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11 

#define CE_PIN   9
#define CSN_PIN 53

DHT dht(DHTPIN, DHTTYPE); 

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);

float dataReceived[6]; // this must match dataToSend in the TX
float ackData[3]; // the two values to be sent to the master
bool newData = false;

const byte controllerFA = 10;
const byte controllerRA = 11;

const byte controllerFB = 12;  //PWM FORWARD PIN for OSMC Controller B (right motor)
const byte controllerRB = 13;  //PWM REVERSE PIN for OSMC Controller B (right motor)

int analogTmp = 0; //temporary variable to store 
int throttle, direction = 0;

int leftMotor,leftMotorScaled = 0; //left Motor helper variables
float leftMotorScale = 0;

int rightMotor,rightMotorScaled = 0; //right Motor helper variables
float rightMotorScale = 0;

float maxMotorScale = 0; //holds the mixed output scaling factor
int deadZone = 10; //jostick dead zone 

//VNH1 RIGHT
const int inaPin = 21;
const int inbPin = 23;
const int diagaPin = 25;
const int diagbPin = 27;

//VNH2 RIGHT
const int inaPin1 = 30;
const int inbPin1 = 32;
const int diagaPin1 = 34;
const int diagbPin1 = 36;

//VNH3 RIGHT
const int inaPin2 = 38;
const int inbPin2 = 40;
const int diagaPin2 = 42;
const int diagbPin2 = 44;

//VNH4 RIGHT
const int inaPin3 = 45;
const int inbPin3 = 46;
const int diagaPin3 = 47;
const int diagbPin3 = 48;

//=============

int sensor=A0;
const int rly1 = 22,rly2 = 24,rly3 = 26,rly4 = 28;

//==============

void setup() {  
  
  Serial.begin(9600);
  
    pinMode(sensor,INPUT);
    
    pinMode(rly1, OUTPUT);
    pinMode(rly2, OUTPUT);
    pinMode(rly3, OUTPUT);
    pinMode(rly4, OUTPUT);
   

  //VNH1  
  pinMode(inaPin, OUTPUT);
  pinMode(inbPin, OUTPUT);
  pinMode(diagaPin, INPUT);
  pinMode(diagbPin, INPUT);
  
  //VNH2  
  pinMode(inaPin1, OUTPUT);
  pinMode(inbPin1, OUTPUT);
  pinMode(diagaPin1, INPUT);
  pinMode(diagbPin1, INPUT);

  //VNH3
  pinMode(inaPin2, OUTPUT);
  pinMode(inbPin2, OUTPUT);
  pinMode(diagaPin2, INPUT);
  pinMode(diagbPin2, INPUT);
  
  //VNH4
  pinMode(inaPin3, OUTPUT);
  pinMode(inbPin3, OUTPUT);
  pinMode(diagaPin3, INPUT);
  pinMode(diagbPin3, INPUT);

  //PWM OTUPUTS
  pinMode(controllerFB, OUTPUT);
  pinMode(controllerRB, OUTPUT);
  pinMode(controllerFA, OUTPUT);
  pinMode(controllerRA, OUTPUT);

    Serial.println("SimpleRxAckPayload Starting");
    //pinMode(53, OUTPUT);
    radio.begin();
    dht.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openReadingPipe(1, thisSlaveAddress);

    radio.enableAckPayload();
    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data

    radio.startListening();
}
//==========

void updateReplyData() {
//    ackData[0] -= 1;
//    ackData[1] -= 1;
//    if (ackData[0] < 100) {
//        ackData[0] = 109;
//    }
//    if (ackData[1] < -4009) {
//        ackData[1] = -4000;
//    }
    
    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}

//===============

void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        updateReplyData();
        newData = true;
    }
}

//================

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.print(" X: ");Serial.print(dataReceived[0]);
        Serial.print(" Y: ");Serial.print(dataReceived[1]);
        Serial.print(" B1: ");Serial.print(dataReceived[2]);
        Serial.print(" B2: ");Serial.print(dataReceived[3]);
        Serial.print(" B3: ");Serial.print(dataReceived[4]);
        Serial.print(" B4: ");Serial.print(dataReceived[5]);
        Serial.println();
        
        Serial.print(" ackPayload sent ");
        Serial.print(" Humedad: ");Serial.print(ackData[0]);
        Serial.print(" Temperatura: ");Serial.print(ackData[1]);
        Serial.print(" Gas: ");Serial.print(ackData[2]);
        Serial.println();
        newData = false;
    }
}

//================


void relay(){
  ////
    if (dataReceived[2] == HIGH) {
    digitalWrite(rly1, HIGH);
  } else {
    digitalWrite(rly1, LOW);
  }
  ////
    if (dataReceived[3] == HIGH) {
    digitalWrite(rly2, HIGH);
  } else {
    digitalWrite(rly2, LOW);
  }
  ////
    if (dataReceived[4] == HIGH) {
    digitalWrite(rly3, HIGH);
  } else {
    digitalWrite(rly3, LOW);
  }
  ////
  if (dataReceived[5] == HIGH) {
    digitalWrite(rly4, HIGH);
  } else {
    digitalWrite(rly4, LOW);
  }
}

//=========

void vnh(){
const byte joysticYA = dataReceived[0]; //Analog Jostick Y axis
const byte joysticXA = dataReceived[1]; //Analog Jostick X axis


  
//aquire the analog input for Y  and rescale the 0..1023 range to -255..255 range
  analogTmp = analogRead(joysticYA);
  throttle = (512-analogTmp)/2;

  delay(1000);
  //...and  the same for X axis
  
  analogTmp = analogRead(joysticXA);
  direction = -(512-analogTmp)/2;

  //mix throttle and direction
  leftMotor = throttle+direction; // 
  rightMotor = throttle-direction;

  //print the initial mix results
  Serial.print("LIN:"); Serial.print( leftMotor, DEC);
  Serial.print(", RIN:"); Serial.print( rightMotor, DEC);

  //calculate the scale of the results in comparision base 8 bit PWM resolution
  leftMotorScale =  leftMotor/255.0;
  leftMotorScale = abs(leftMotorScale);
  rightMotorScale =  rightMotor/255.0;
  rightMotorScale = abs(rightMotorScale);

  Serial.print("| LSCALE:"); Serial.print( leftMotorScale,2);
  Serial.print(", RSCALE:"); Serial.print( rightMotorScale,2);

  //choose the max scale value if it is above 1
  maxMotorScale = max(leftMotorScale,rightMotorScale);
  maxMotorScale = max(1,maxMotorScale);

  //and apply it to the mixed values
  leftMotorScaled = constrain(leftMotor/maxMotorScale,-255,255);
  rightMotorScaled = constrain(rightMotor/maxMotorScale,-255,255);

  Serial.print("| LOUT:"); Serial.print( leftMotorScaled);
  Serial.print(", ROUT:"); Serial.print( rightMotorScaled);

  Serial.print(" |");

  //apply the results to appropriate uC PWM outputs for the LEFT motor:
  if(abs(leftMotorScaled)>deadZone)
  {

    if (leftMotorScaled > 0)
    {
      Serial.print("F");
      Serial.print(abs(leftMotorScaled),DEC);

      digitalWrite(inaPin2, HIGH);
      digitalWrite(inbPin2, LOW);

      digitalWrite(inaPin3, HIGH);
      digitalWrite(inbPin3, LOW);
      
      analogWrite(controllerRA,0);
      analogWrite(controllerFA,abs(leftMotorScaled));            
    }
    else 
    {
      Serial.print("R");
      Serial.print(abs(leftMotorScaled),DEC);


       digitalWrite(inaPin2, LOW);
      digitalWrite(inbPin2, HIGH);

      digitalWrite(inaPin3, LOW);
      digitalWrite(inbPin3, HIGH);
       
      analogWrite(controllerFA,0);
      analogWrite(controllerRA,abs(leftMotorScaled));  
    }
  }  
  else 
  {
  Serial.print("IDLE");
  analogWrite(controllerFA,0);
  analogWrite(controllerRA,0);
  } 

  //apply the results to appropriate uC PWM outputs for the RIGHT motor:  
  if(abs(rightMotorScaled)>deadZone)
  {

    if (rightMotorScaled > 0)
    {
      Serial.print("F");
      Serial.print(abs(rightMotorScaled),DEC);


       digitalWrite(inaPin, HIGH);
      digitalWrite(inbPin, LOW);

      digitalWrite(inaPin1, HIGH);
      digitalWrite(inbPin1, LOW);
      
      analogWrite(controllerRB,0);
      analogWrite(controllerFB,abs(rightMotorScaled));            
    }
    else 
    {
      Serial.print("R");
      Serial.print(abs(rightMotorScaled),DEC);


      digitalWrite(inaPin, LOW);
      digitalWrite(inbPin, HIGH);

      digitalWrite(inaPin1, LOW);
      digitalWrite(inbPin1, HIGH);
      
      analogWrite(controllerFB,0);
      analogWrite(controllerRB,abs(rightMotorScaled));  
    }
  }  
  else 
  {
  Serial.print("IDLE");
  analogWrite(controllerFB,0);
  analogWrite(controllerRB,0);
  } 

  Serial.println("");

  delay(10);
}
//==========

void loop() {
    ackData[0] = dht.readHumidity();
    ackData[1] = dht.readTemperature();
    ackData[2] = analogRead(sensor);
    getData();
    vnh();
    showData();
    relay();
}

Davidagudino:
at this point if I get one of the slaves isolated It works just fine, even if I get them disable, but if i try to make it work together they just don't.

That is not meaningful for me. Perhaps you can post a diagram - or a more detailed description.

How many slaves are there?
Does it work with N-1 slaves?
Does it matter which slave is isolated?
What is the difference beween disable and isolate?

...R

Transmitter Code ( Here's where I'm having the problem with the LCD )

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <LCD5110_Basic.h>

#define CE_PIN   9
#define CSN_PIN 53

const byte slaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN); 


 LCD5110 myGLCD(52,51,10,11,12); 
 extern uint8_t SmallFont[]; 
 extern uint8_t MediumNumbers[]; 
 extern uint8_t BigNumbers[]; 
 extern uint8_t cetiimagen [];

float dataToSend[6];
float ackData[3]; // to hold the two values coming from the slave
bool newData = false;
int xPin = A1;
int yPin = A0;
int buttonPin = 2;
int buttonPin1 = 3;
int buttonPin2 = 4;
int buttonPin3 = 5;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

//===============

void setup() {
    Serial.begin(9600);
    myGLCD.InitLCD(); 
    
    pinMode(xPin, INPUT);
    pinMode(yPin, INPUT);
    pinMode(buttonPin, INPUT);
    pinMode(buttonPin1, INPUT);
    pinMode(buttonPin2, INPUT);
    pinMode(buttonPin3, INPUT ); 
    
    radio.begin();
    radio.setDataRate(RF24_250KBPS);

    radio.enableAckPayload();

    radio.setRetries(3,5); // delay, count
    radio.openWritingPipe(slaveAddress);
}

//=============

void loop() {
    dataToSend[0] = analogRead(xPin);
    dataToSend[1] = analogRead(yPin);
    dataToSend[2] = digitalRead(buttonPin);
    dataToSend[3] = digitalRead(buttonPin1);
    dataToSend[4] = digitalRead(buttonPin2);
    dataToSend[5] = digitalRead(buttonPin3);
    currentMillis = millis();
    
    if (currentMillis - prevMillis >= txIntervalMillis) {
        //digitalWrite(53, HIGH);
        pinMode(53, HIGH);
        send();
        //digitalWrite(53, LOW);
        pinMode(53, LOW);
    }
    showData();
    //digitalWrite(53, HIGH);
    pinMode(12, HIGH);
     myGLCD.clrScr();
     myGLCD.setFont(SmallFont);
     myGLCD.print("CETI",CENTER,24);
     delay(8000);
     //digitalWrite(53, HIGH);
     pinMode(12, LOW);
}

//================

void send() {
    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        // Always use sizeof() as it gives the size as the number of bytes.
        // For example if dataToSend was an int sizeof() would correctly return 2

    Serial.print("Enviado ");
    Serial.print(" X: ");Serial.print(dataToSend[0]);
    Serial.print(" Y: ");Serial.print(dataToSend[1]);
    Serial.print(" B1: ");Serial.print(dataToSend[2]);
    Serial.print(" B2: ");Serial.print(dataToSend[3]);
    Serial.print(" B3: ");Serial.print(dataToSend[4]);
    Serial.print(" B4: ");Serial.print(dataToSend[5]);
    Serial.println();
    if (rslt) {
        if ( radio.isAckPayloadAvailable() ) {
            radio.read(&ackData, sizeof(ackData));
            newData = true;
        }
        else {
            Serial.println("  Acknowledge but no data ");
        }
    }
    else {
        Serial.println("  Tx failed");
    }
    prevMillis = millis();
 }


//=================

void showData() {
    if (newData == true) {
        Serial.print("  Acknowledge data ");
        Serial.print(" Humedad: ");Serial.print(ackData[0]);
        Serial.print(" Temperatura: ");Serial.print(ackData[1]);
        Serial.print(" Gas: ");Serial.print(ackData[2]);
        Serial.println();
        newData = false;
    }
}

Please answer the questions in Reply #6 if I am to help you.

...R

Robin2:
That is not meaningful for me. Perhaps you can post a diagram - or a more detailed description.

How many slaves are there?
Does it work with N-1 slaves?
Does it matter which slave is isolated?
What is the difference beween disable and isolate?

...R

Sorry for not make it clear enough, Robin.

  1. I have 2 slaves, one is the NRF24L01 Module and the other one is the Nokia 5110 LCD.

  2. Yes, it works with only 1 slave, either the NRF24 or the LCD.

3 & 4. For isolated I meant, to make a separate program for each and test it apart, using a push button to "disable" the "CS" output and it worked for both. I can have the NRF24L01 working and if I push the button, I can send it to "sleep". same for the LCD.

Here's a little diagram sorry, but I could find the module and the LCD on fritzing so I made it in my preview tool.

NRF PINOUT

NRF24L01- ARDUINO MEGA 2560

Pin 3 RF - pin 9 (CE)
Pin 4 RF - pin 53 (CS)
Pin 5 RF - pin 52 (SCK)
Pin 6 RF - pin 51 (MOSI)
Pin 7 RF - pin 50 (MISO)

NOKIA 5110 LCD - ARDUINO

DC PIN - PIN 10
RST PIN - PIN 11
CS PIN - PIN 12
SCK PIN - PIN 52
MOSI PIN - PIN 51

As we can see MOSI and SCK are common pins between the slaves ( The Nokia LCD doesn't need a MISO pin, since it does not sends anything back to the master ) In the NRF24L01 we have CE and CS and in the LCD we have only CS Pin, as far as I know, those are the pins that we must set up or down to enable o disable the slave in use, Am i right?

That would be my only problem I can't make them work together, but i don't know if I'm misunderstanding something.

Thanks Robin.

Davidagudino:
3 & 4. For isolated I meant, to make a separate program for each and test it apart, using a push button to "disable" the "CS" output and it worked for both. I can have the NRF24L01 working and if I push the button, I can send it to "sleep". same for the LCD.

I'm not sure that I understand what's going on there.

I would expect your program to turn CS on and off as necessary to select whichever slave the Arduino wants to talk to.

What is different when you disable CS with a push button?

...R

I can't help feeling there is something else going on. If the LCD backjlight is in use, your problem might be inadequate power.
When you say

I must share pins for the MISO, MOSI and SCK, using the same for the LCD and the NRF24L01 and having a different CS control pin that will allow me to choose the slave I'm working with,

you're dead right, but you shouldn't have to do the choosing with a button. That's crazy. It should all be in code, and that's where your problem should lie. For what it's worth, you are not obliged to run the 5110 on SPI. It doesn't care what pins it's, just so long as you call them in the proper order. I don't think there is anything wrong with the wiring but, if you are desperate, separating the modules might help.

Robin2:
I'm not sure that I understand what's going on there.

I would expect your program to turn CS on and off as necessary to select whichever slave the Arduino wants to talk to.

What is different when you disable CS with a push button?

...R

I've made a code where I turn off the CS of the LCD Display ( Isolated, just the LCD ) and It worked, I can enable it and disable it.

I've made a code where I turn off the CS and CSN for the NRF24L01 ( Isolated, Just the NRF24L01 ) and it worked, It transmits and it disables just fine.

I used the push button to disable and enable the modules with a condition in the program ( an if )

So... I can enable and disable the slave that I choose but when I tried to make them work together they just don't and. I mean, come on! I just need to do something like this:

With this it's supposed that I'm talking to the LCD slave which must show at least signs of life, let's say a simple "Hello World", Well... It doesn't.

digitalWrite(CS1, LOW); // NRF24L01  CS
digitalWrite(CSN, LOW); // NRF24L01 CSN
digitalWrite(CS2, HIGH); // LCD CS

And with this it's supposed that I'm talking to the NRF24L01 which must transmit and receive. Well It doesn't

digitalWrite(CS2, LOW); // LCD CS
digitalWrite(CS1, HIGH); // NRF24L01  CS
digitalWrite(CSN, HIGH); // NRF24L01 CSN

Yes, I'm desperate and I'm freaking out. I've been working for hours ( hours by many, many days ) and it just doesn't work, I haven't found a tutorial for anything like this and I'm considering to change to a 16x2 LCD display with an I2C module but I don't want to just give up on this.

Thanks

Nick_Pyner:
I can't help feeling there is something else going on. If the LCD backjlight is in use, your problem might be inadequate power.

you're dead right, but you shouldn't have to do the choosing with a button. That's crazy. It should all be in code, and that's where your problem should lie. For what it's worth, you are not obliged to run the 5110 on SPI. It doesn't care what pins it's, just so long as you call them in the proper order. I don't think there is anything wrong with the wiring but, if you are desperate, separating the modules might help.

Hi Nick, as you say I'm desperate, dead, buried and all those kind of things. I use the button just as a selector to enable or disable the slaves separated (LCD and NRF24L01) and it works, but when I put them together, it doesn't work. I don't know if it has something to do with the time that it needs to disable the other slave. As far as I know that shouldn't be a problem, but at this time I don't even know my name.

If I'm reading your code correctly, it looks like you're setting CSN to HIGH when you want to control the device? Is that what you're trying to do?

If so, that's backwards. CSN is an active-low signal. It should be LOW for the one device you are talking to, and HIGH for all other devices.

Davidagudino:
And with this it's supposed that I'm talking to the NRF24L01 which must transmit and receive. Well It doesn't

digitalWrite(CS2, LOW); // LCD CS

digitalWrite(CS1, HIGH); // NRF24L01  CS
digitalWrite(CSN, HIGH); // NRF24L01 CSN

That's pointing in the correct direction but it is not correct. CE and CSN are used for specific purposes with the nRF24 - they are not "ON" all the time. When you are using the nRF24 CS for the LCD must be OFF - but I can't recall whether it should be HIGH or LOW for off. Using the proper names for the pins makes code much easier to follow.

Post the latest version of your program so we can see all the details.

...R

MicrocontrollerGuy:
If I'm reading your code correctly, it looks like you're setting CSN to HIGH when you want to control the device? Is that what you're trying to do?

If so, that's backwards. CSN is an active-low signal. It should be LOW for the one device you are talking to, and HIGH for all other devices.

Hi, I spend last night reading and I realize that you're right in AVR I must set CSN to high to disable the slave. That was one of my mistakes, but even with it it must have worked, as you say backwards... but it didn't work.

Thanks!

Robin2:
That's pointing in the correct direction but it is not correct. CE and CSN are used for specific purposes with the nRF24 - they are not "ON" all the time. When you are using the nRF24 CS for the LCD must be OFF - but I can't recall whether it should be HIGH or LOW for off. Using the proper names for the pins makes code much easier to follow.

Post the latest version of your program so we can see all the details.

...R

Hi Robin, as GuyMicro says when the CS is High the slave is disable, so I was doing it backwards, but still it must have worked. I'll post my code below, but before that I wanted to share with you guys an example that I found last night so, I think that may solve the problem but, I don't know how exactly am going to implement it in the code.

Transactional SPI configuration

A common problem used to be that different SPI devices needed different, incompatible settings. Your sketch had to take care of saving and restoring the SPI settings before communicating with each SPI device. If any SPI device was accessed from an interrupt, this could result in data corruption if another SPI device was communicating at the time.

With the new SPI library, configure each SPI device once as an SPISettings object. Also, if that device will be called from an interrupt, say so with SPI.usingInterrupt(interruptNumber). To communicate with a specific SPI device, use SPI.beginTransaction which automatically uses the settings you declared for that device. In addition, it will disable any interrupts that use SPI for the duration of the transaction. Once you are finished, use SPI.endTransaction() which re-enables any SPI-using interrupts.

Example using transactions

#include <SPI.h>  // include the new SPI library:

// using two incompatible SPI devices, A and B
const int slaveAPin = 20;
const int slaveBPin = 21;

// set up the speed, mode and endianness of each device
SPISettings settingsA(2000000, MSBFIRST, SPI_MODE1); 
SPISettings settingsB(16000000, LSBFIRST, SPI_MODE3); 

void setup() {
  // set the Slave Select Pins as outputs:
  pinMode (slaveAPin, OUTPUT);
  pinMode (slaveBPin, OUTPUT);
  // initialize SPI:
  SPI.begin(); 
}

uint8_t stat, val1, val2, result;

void loop() {
  // read three bytes from device A
  SPI.beginTransaction(settingsA);
  digitalWrite (slaveAPin, LOW);
  // reading only, so data sent does not matter
  stat = SPI.transfer(0);
  val1 = SPI.transfer(0);
  val2 = SPI.transfer(0);
  digitalWrite (slaveAPin, HIGH);
  SPI.endTransaction();
  // if stat is 1 or 2, send val1 or val2 else zero
  if (stat == 1) { 
   result = val1;
  } else if (stat == 2) { 
   result = val2;
  } else {
   result = 0;
  }
  // send result to device B
  SPI.beginTransaction(settingsB);
  digitalWrite (slaveBPin, LOW);
  SPI.transfer(result);
  digitalWrite (slaveBPin, HIGH);
  SPI.endTransaction();
}

Source: SPI Arduino Library, connecting SPI devices to Teensy

Receiver Code

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "DHT.h"

#define DHTPIN 2
#define DHTTYPE DHT11 
#define CE_PIN   9
#define CSN_PIN 53

DHT dht(DHTPIN, DHTTYPE); 

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);
float dataReceived[6]; // this must match dataToSend in the TX
float ackData[3]; // the two values to be sent to the master
bool newData = false;

int sensor=A0;

const int rly1=4,rly2=5,rly3=6,rly4=7;

const byte controllerFA = 13; //PWM FORWARD PIN for OSMC Controller A (left motor)
const byte controllerRA = 12;  //PWM REVERSE PIN for OSMC Controller A (left motor)

const byte controllerFB = 11;  //PWM FORWARD PIN for OSMC Controller B (right motor)
const byte controllerRB = 10;  //PWM REVERSE PIN for OSMC Controller B (right motor)

int analogTmp = 0; //temporary variable to store 
int throttle, direction = 0; //throttle (Y axis) and direction (X axis) 

int leftMotor,leftMotorScaled = 0; //left Motor helper variables
float leftMotorScale = 0;

int rightMotor,rightMotorScaled = 0; //right Motor helper variables
float rightMotorScale = 0;

float maxMotorScale = 0; //holds the mixed output scaling factor

int deadZone = 10; //jostick dead zone

//VNH1 
const int inaPin = 22;
const int inbPin = 24;
const int diagaPin = 26;
const int diagbPin = 28;

//VNH2 
const int inaPin1 = 30;
const int inbPin1 = 32;
const int diagaPin1 = 34;
const int diagbPin1 = 36;

//VNH3 
const int inaPin2 = 38;
const int inbPin2 = 40;
const int diagaPin2 = 42;
const int diagbPin2 = 44;

//VNH4
const int inaPin3 = 45;
const int inbPin3 = 46;
const int diagaPin3 = 47;
const int diagbPin3 = 48;

void vnhDeclare(){
    pinMode(sensor,INPUT);
    pinMode(rly1, OUTPUT);
    pinMode(rly2, OUTPUT);
    pinMode(rly3, OUTPUT);
    pinMode(rly4, OUTPUT);
   
  
    pinMode(controllerFA, OUTPUT);
    pinMode(controllerRA, OUTPUT);
    pinMode(controllerFB, OUTPUT);
    pinMode(controllerRB, OUTPUT);  
  
       
    pinMode(inaPin, OUTPUT);
    pinMode(inbPin, OUTPUT);
    pinMode(diagaPin, INPUT);
    pinMode(diagbPin, INPUT);
    
      
    pinMode(inaPin1, OUTPUT);
    pinMode(inbPin1, OUTPUT);
    pinMode(diagaPin1, INPUT);
    pinMode(diagbPin1, INPUT);
    
      
    pinMode(inaPin2, OUTPUT);
    pinMode(inbPin2, OUTPUT);
    pinMode(diagaPin2, INPUT);
    pinMode(diagbPin2, INPUT);
    
      
    pinMode(inaPin3, OUTPUT);
    pinMode(inbPin3, OUTPUT);
    pinMode(diagaPin3, INPUT);
    pinMode(diagbPin3, INPUT);
  
  }
  
void setup() {
  
    Serial.begin(9600);
  
    vnhDeclare();
    
    Serial.println("SimpleRxAckPayload Starting");
    radio.begin();
    dht.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openReadingPipe(1, thisSlaveAddress);

    radio.enableAckPayload();
    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data

    radio.startListening();
}


void updateReplyData() {
    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}


void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        updateReplyData();
        newData = true;
    }
}


void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.print(" X: ");Serial.print(dataReceived[0]);
        Serial.print(" Y: ");Serial.print(dataReceived[1]);
        Serial.print(" B1: ");Serial.print(dataReceived[2]);
        Serial.print(" B2: ");Serial.print(dataReceived[3]);
        Serial.print(" B3: ");Serial.print(dataReceived[4]);
        Serial.print(" B4: ");Serial.print(dataReceived[5]);
        Serial.println();
        
        Serial.print(" ackPayload sent ");
        Serial.print(" Hum: ");Serial.print(ackData[0]);
        Serial.print(" Temp: ");Serial.print(ackData[1]);
        Serial.print(" Gas: ");Serial.print(ackData[2]);
        Serial.println();
        newData = false;
    }
}


void relays(){

    if (dataReceived[2] == HIGH) {
    digitalWrite(rly1, HIGH);
  } 
  else {
    digitalWrite(rly1, LOW);
  }

    if (dataReceived[3] == HIGH) {
    digitalWrite(rly2, HIGH);
  } 
  else {
    digitalWrite(rly2, LOW);
  }
    if (dataReceived[4] == HIGH) {
    digitalWrite(rly3, HIGH);
  } 
  else {
    digitalWrite(rly3, LOW);
  }

  if (dataReceived[5] == HIGH) {
    digitalWrite(rly4, HIGH);
  } 
  else {
    digitalWrite(rly4, LOW);
  }
}


void motorController(){

  const byte joysticYA = dataReceived[1]; //Analog Jostick Y axis
  const byte joysticXA = dataReceived[0]; //Analog Jostick X axis

    //aquire the analog input for Y  and rescale the 0..1023 range to -255..255 range
  analogTmp = analogRead(joysticYA);
  throttle = (512-analogTmp)/2;

  delay(1000);
  //...and  the same for X axis
  
  analogTmp = analogRead(joysticXA);
  direction = -(512-analogTmp)/2;

  //mix throttle and direction
  leftMotor = throttle+direction; // 
  rightMotor = throttle-direction;

  //calculate the scale of the results in comparision base 8 bit PWM resolution
  leftMotorScale =  leftMotor/255.0;
  leftMotorScale = abs(leftMotorScale);
  rightMotorScale =  rightMotor/255.0;
  rightMotorScale = abs(rightMotorScale);

  //choose the max scale value if it is above 1
  maxMotorScale = max(leftMotorScale,rightMotorScale);
  maxMotorScale = max(1,maxMotorScale);

  //and apply it to the mixed values
  leftMotorScaled = constrain(leftMotor/maxMotorScale,-255,255);
  rightMotorScaled = constrain(rightMotor/maxMotorScale,-255,255);

  //apply the results to appropriate uC PWM outputs for the LEFT motor:
  if(abs(leftMotorScaled)>deadZone)
  {

    if (leftMotorScaled > 0)
    {

      digitalWrite(inaPin2, HIGH);
      digitalWrite(inbPin2, LOW);

      digitalWrite(inaPin3, HIGH);
      digitalWrite(inbPin3, LOW);
      
      analogWrite(controllerRA,0);
      analogWrite(controllerFA,abs(leftMotorScaled));            
    }
    else 
    {

      digitalWrite(inaPin2, LOW);
      digitalWrite(inbPin2, HIGH);

      digitalWrite(inaPin3, LOW);
      digitalWrite(inbPin3, HIGH);
       
      analogWrite(controllerFA,0);
      analogWrite(controllerRA,abs(leftMotorScaled));  
    }
  }  
  else 
  {
  analogWrite(controllerFA,0);
  analogWrite(controllerRA,0);
  } 

  //apply the results to appropriate uC PWM outputs for the RIGHT motor:  
  if(abs(rightMotorScaled)>deadZone)
  {

    if (rightMotorScaled > 0)
    {
     
      digitalWrite(inaPin, HIGH);
      digitalWrite(inbPin, LOW);

      digitalWrite(inaPin1, HIGH);
      digitalWrite(inbPin1, LOW);
      
      analogWrite(controllerRB,0);
      analogWrite(controllerFB,abs(rightMotorScaled));            
    }
    else 
    {

      digitalWrite(inaPin, LOW);
      digitalWrite(inbPin, HIGH);

      digitalWrite(inaPin1, LOW);
      digitalWrite(inbPin1, HIGH);
      
      analogWrite(controllerFB,0);
      analogWrite(controllerRB,abs(rightMotorScaled));  
    }
  }  
  else 
  {
  analogWrite(controllerFB,0);
  analogWrite(controllerRB,0);
  } 

  delay(10);

}


void loop() {
    ackData[0] = dht.readHumidity();
    ackData[1] = dht.readTemperature();
    ackData[2] = analogRead(sensor);
    getData();
    motorController();
    showData();
    relays();
}

TX Code.

Data to show in the Nokia 5110 it's humidity, temp and gas. At this point everything works with the example that Robin post about "bidirectional communication" with the NRF24L01.

All my modules and sensores are working but now show them it's the problem.

This code does not add the LCD because the problem is with it. I think the function that I need to work with it's the show data, instead of showing the data in the serial monitor it must show it in the LCD, by disable ( by micro or nano S ) the NRF24L01 and enable the LCD.

Here is where I'm stuck.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define CE_PIN   9
#define CSN_PIN 53

const byte slaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

float dataToSend[6];
float ackData[3]; // to hold the two values coming from the slave
bool newData = false;
int xPin = A1;
int yPin = A0;
int buttonPin = 2;
int buttonPin1 = 3;
int buttonPin2 = 4;
int buttonPin3 = 5;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second


void setup() {    
  
    Serial.begin(9600);
    
    pinMode(xPin, INPUT);
    pinMode(yPin, INPUT);
    pinMode(buttonPin, INPUT);
    pinMode(buttonPin1, INPUT);
    pinMode(buttonPin2, INPUT);
    pinMode(buttonPin3, INPUT ); 
    
    radio.begin();
    radio.setDataRate(RF24_250KBPS);

    radio.enableAckPayload();

    radio.setRetries(3,5); // delay, count
    radio.openWritingPipe(slaveAddress);
}


void loop() {
  
    dataToSend[0] = analogRead(xPin);
    dataToSend[1] = analogRead(yPin);
    dataToSend[2] = digitalRead(buttonPin);
    dataToSend[3] = digitalRead(buttonPin1);
    dataToSend[4] = digitalRead(buttonPin2);
    dataToSend[5] = digitalRead(buttonPin3);
    currentMillis = millis();
    
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
    }
    showData();
}


void send() {
  
    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );


    Serial.print("Send ");
    Serial.print(" X: ");Serial.print(dataToSend[0]);
    Serial.print(" Y: ");Serial.print(dataToSend[1]);
    Serial.print(" B1: ");Serial.print(dataToSend[2]);
    Serial.print(" B2: ");Serial.print(dataToSend[3]);
    Serial.print(" B3: ");Serial.print(dataToSend[4]);
    Serial.print(" B4: ");Serial.print(dataToSend[5]);
    Serial.println();
    
    if (rslt) {
        if ( radio.isAckPayloadAvailable() ) {
            radio.read(&ackData, sizeof(ackData));
            newData = true;
        }
        else {
            Serial.println("  Acknowledge but no data ");
        }
    }
    else {
        Serial.println("  Tx failed");
    }
    prevMillis = millis();
 }



void showData() {
    if (newData == true) {
        Serial.print("  Acknowledge data ");
        Serial.print(" Hum: ");Serial.print(ackData[0]);
        Serial.print(" Temp: ");Serial.print(ackData[1]);
        Serial.print(" Gas: ");Serial.print(ackData[2]);
        Serial.println();
        newData = false;
    }
}