SPI Slave Select

I'm making a bee hive monitor, at the hive I have a nano with a BMP280, soon to be a BME280. the data is being sent to a Mega via NRF24L01+ modules. That part works. I am now trying to add an Adafruit 3.5 TFT display to the mega. That works as well.

What doesn't work is when I try to read the data while having the display and the NRF2401 both connected to the SPI pins. From what I've read I need to select and de-select the slave select pins of the receiving NRF24L01 and the display. I've played around with different pins and methods but obviously it's not working. I don't know enough about getting into the libraries to see what variables I should be using.

My sketch is in 3 tabs, the main tab, display control, and read the hive. Here are all 3.

(I couldn't post all the logic as it exceeded the max length so I remove the logic to draw the screens, you shouldn't need that for my questions, I don't think any ways)

the main

// Bee Hive base Controller with TFT display

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "Adafruit_GFX.h"
#include "Adafruit_HX8357.h"
#include "TouchScreen.h"
#include <Wire.h>
#include "RTClib.h"

// for NRF24L01
#define radio_CS 4
#define radio_CSN 5

RF24 radio(radio_CS, radio_CSN); // 7, 8 CE, CSN
const byte addresses[][6] = {"1Node", "2Node"};

// for TFT display
// These are the four touchscreen analog pins
#define YP A2  // must be an analog pin, use "An" notation!
#define XM A3  // must be an analog pin, use "An" notation!
#define YM 29   // can be a digital pin
#define XP 28   // can be a digital pin

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 110
#define TS_MINY 80
#define TS_MAXX 900
#define TS_MAXY 940
#define MINPRESSURE 10
#define MAXPRESSURE 1000

// Color definitions
#define BLACK    0x0000
#define BLUE     0x001F
#define RED      0xF800
#define GREEN    0x07E0
#define CYAN     0x07FF
#define MAGENTA  0xF81F
#define YELLOW   0xFFE0 
#define WHITE    0xFFFF

// These are 'flexible' lines that can be changed
#define TFT_CS 10
#define TFT_DC 9
int TFTCS_Status;
// #define SD_CS  44
#define TFT_RST 8  // dont use a reset pin, tie to arduino RST if you like
//#define TFT_RST 8 // RST can be set to -1 if you tie it to Arduino's reset

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);

// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// RTC_DS1307 RTC; // define the Real Time Clock object
 RTC_PCF8523 RTC; // define the Real Time Clock object
 

//==== Defining Variables

char text[6] = "";
String inTemp, inHum, outTemp = "", outHum;
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

int x, y;

int currentPage = 0; //, selectedUnit;
int selectedUnit = 0;

char hive1Temp[20] = " "; // Hive 1 Temperature number
char hive1Hum[20] = " "; // Hive 1 Humidity number
long int start_time = millis();
long int read_time = 5000; // time between reading hive data
int hiveRead = 0; // bit that system is reading hive status

//String rtcTime, rtcDate;
//int draw_state = 0;
//unsigned long previousMillis = 0;
//long interval = 3000;

void setup() {
  Serial.begin(9600);
  Serial.println(F("Hive Base"));
  pinMode(TFT_CS, OUTPUT);
  pinMode(TFT_DC, OUTPUT);
  pinMode(radio_CS, OUTPUT);
  pinMode(radio_CSN, OUTPUT);

// NRF24L01 setup
  radio.begin(); // Initiate the radio object
 // radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);  // Set the transmit power to lowest available to prevent power supply related issues
  radio.setDataRate(RF24_2MBPS); // Set the speed of the transmission to the quickest available
  radio.setChannel(124); // Use a channel unlikely to be used by Wifi, Microwave ovens etc
   // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[0]);
  radio.openReadingPipe(1, addresses[1]);
  // Stop the radio listening for data
  radio.stopListening();

// TFT setup
  tft.begin();
  tft.fillScreen(BLACK); //clears screen, sets to Black
  tft.setRotation(1);  // rotates screen 90' for landscape mode

  currentPage = 0; // Indicates that we are at Home Screen
  selectedUnit = 0; // Indicates the selected unit for the first example, cms or inches

  drawHomeScreen();  // Draws the Home Screen

  digitalWrite(TFT_CS, HIGH); // enable display
  digitalWrite(TFT_DC, LOW); // Select display
  digitalWrite(radio_CS, LOW); // Disable NRF24L01
  digitalWrite(radio_CSN, HIGH); // de-select NRF24L01
    
  // connect to RTC
/*  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
  } 
*/

} // end void setup


void loop() {

// read hive every 5 seconds disble display while reading hive 

if(millis() > (start_time + read_time)){
  start_time = millis();
  hiveRead = 1;
  readHive(); // get hive status
  
} // end if(millis() > (start_time + read_time))

 else if(hiveRead == 0) {
  display_cntrl(); // update display
    
 } // end else

 
} // end void loop

display control

// TFT display control

void display_cntrl()
{
 // Retrieve a point on touch screen
  TSPoint p = ts.getPoint();
/*  
 // for touch screen testing gives, x, y and pressure values
  // we have some minimum pressure we consider 'valid'
  // pressure of 0 means no pressing!
  if (p.z < MINPRESSURE || p.z > MAXPRESSURE) {
     return;
  }

  Serial.print("X = "); Serial.print(p.x);
  Serial.print("\tY = "); Serial.print(p.y);
  Serial.print("\tPressure = "); Serial.println(p.z);  
   
  // Scale from ~0->1000 to tft.width using the calibration #'s
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
*/
 // Home Screen
  if (currentPage == 0) {
         
      // If we press the Report Setup Button 
      if ((p.x>=440) && (p.x<=540) && (p.y>=350) && (p.y<=670)) {
        // drawFrame(35, 90, 285, 130); // Custom Function -Highlighs the buttons when it's pressed
        currentPage = 1; // Indicates that we are the first example
        tft.fillScreen(BLACK); //clears screen, sets to Black
        drawHiveStatus(); // It is called only once, because in the next iteration of the loop, this above if statement will be false so this funtion won't be called. This function will draw the graphics of the first example.
      } // end if for report setup

    // If we press the Test Control Button 
      if ((p.x>=240) && (p.x<=320) && (p.y>=320) && (p.y<=700)) {
        // drawFrame(35, 140, 285, 180);
        currentPage = 2;
        tft.fillScreen(BLACK); //clears screen, sets to Black
      //  drawTestControl();
      } // end if for Test Control  
      
} // end if currentPage ==0

  // Logic for Hive page

   if (currentPage == 1) {

    // If we press the Back to Main Menu Button 
      if ((p.x>=810) && (p.x<=860) && (p.y>=140) && (p.y<=210)) {
        // drawFrame(35, 140, 285, 180);
        currentPage = 0;
        tft.fillScreen(BLACK); //clears screen, sets to Black
        drawHomeScreen();
      } // end if for back to home

  } // end if curentPage ==1 

  
} // end void display_cntrl

Hive read

void readHive()
{

  digitalWrite(TFT_CS, LOW); // disable display
  digitalWrite(TFT_DC, HIGH); // de-select display
  digitalWrite(radio_CS, HIGH); // enable NRF24L01
  digitalWrite(radio_CSN, LOW); // select NRF24L01
      
   // listen for a response
  radio.startListening();

 if (radio.available()) {
  Serial.println("radio.available");
    radio.read(&text, sizeof(text)); // Read incoming data
    outTemp = String(text[0]) + String(text[1]) + " 'F"; // Outdoor Temperature
    outHum = String(text[2]) + String(text[3]) + " inHg"; // Outdoor Humidity
  } // end if (radio.available()

 float  hive1_temp = (outTemp.toFloat()); // convert string to float
 float  hive1_hum = (outHum.toFloat()); // convert string to float

  Serial.print("Hive 1 temp ");
  Serial.print(outTemp);
  Serial.print("\t");
  Serial.print("Hive 1 Pressure ");
  Serial.println(outHum);

  // Stop listening for a response
  radio.stopListening();

if(millis() > (start_time + 1000)){
   
} // if(millis() > (start)time + 1000)
      digitalWrite(TFT_CS, HIGH); // enable display
      digitalWrite(TFT_DC, LOW); // Select display
      digitalWrite(radio_CS, LOW); // Disable NRF24L01
      digitalWrite(radio_CSN, HIGH); // de-select NRF24L01
      hiveRead = 0;
     
} // end void readHive

Any and all help will be greatly appreciated
Thanks
John

First things first, you don't need to manually control the CS or CE pins, that will be handled by the libraries. What you are doing with the pins is causing problems.

Secondly, in the Hive read part, you call radio.startListening(); then immediately call radio.available(); then immediately call radio.stopListening();. You will never receive data because you are not giving the radio any time to receive. The radio should generally be left in listening mode, and only taken out of listening mode to transmit data.

There are a few flaws here, and I am not that familiar withe the TFT display, but that should be a start.

Next, RF24 devices sometimes just don't play well with other SPI devices, so using a secondary SPI BUS is useful in some cases. Both the TFT and RF24 libraries support software-SPI, allowing a secondary SPI BUS.
If you cannot get it working, the Software SPI library will allow you to do this. See the related library documentation for more information.

TMRh20:
Next, RF24 devices sometimes just don't play well with other SPI devices,

I would appreciate it very much if you would expand on that.

I am aware that people have trouble with some SDCard modules and nRF24s but AFAIK the problem is with the SDCard module or library, not the nRF24.

...R

Well you pretty much said it, as I've personally mainly had problems when using an SD card along with RF24. I assumed the problems with the SD libraries would be corrected eventually though.

I've had a number of users report issues or contact me directly regarding using TFT displays along with RF24, like here, but I have not been able to test or troubleshoot this for myself. The library in the issue I linked supports SPI Transactions, so theoretically should work with RF24, but the user in question seems to have had success immediately using softSPI.

Nowadays, when users report issues with RF24 and multiple SPI devices, I typically verify that RF24 and said device are working independently, and default to suggesting a separate SPI BUS for each device. Ideally, I would like to be able to test these issues for myself, but obviously don't have access to all the individual hardware.

Robin2:
I would appreciate it very much if you would expand on that.

I am aware that people have trouble with some SDCard modules and nRF24s but AFAIK the problem is with the SDCard module or library, not the nRF24.

...R

Hi Robin.. How about two devices.. for instance RFID RC522 and Wiznet W5100 Ethernet shield. Can both modules have same pin for RST? Or it must be separated too like SS pin? Thanks, Martin

TMRh20, I will remove the controls I have for the CS and CE pins, my clumsy efforts to figure it out on my own. I will also add some time delays in there to give the radio time to think. I was unaware of software SPI but will definitively look into it.

Robin2 there was a SD module on the mega, but it was a left over from a previous project, I don't need it, for now any ways, and I'm aware that there are some conflicts with using pin 10 as a default on various devices so I removed it. There is a SD card on the TFT display but no card is plugged in and I have no logic for it but the library maybe setting it up any ways.

I have tried reading the hive data by itself without the calls to the display and by disconnecting the display from the SPI buss, that works. One thing I thought odd was if I keep the display connected to the SPI but not powered on the read doesn't work. I assume it must be passively loading down the buss

Thanks for all the responses
John

I looked quick for some info on the software SPI, found some stuff about bit bang that I have to dig into more and not sure I will understand it all. But why should I have to do that? My understanding of SPI is that it is made for multiple devices sharing a common buss, CLK, MOSI, MISO, and by setting one of the slave select pins low at a time you can read/write data to the selected device.

Isn't all I need is to define which pin on the radio and the display is the select and how do I tell the library to set the variable high/low?

thanks again
John

Yes Stumpy, you are technically correct, but if I remember correctly the SD issue is related to the SD card not responding correctly when it is de-selected. I'm sure somebody else here can correct me on that if needed.

In any case, the common trend here seems to be the SD card issue, so that is why you would need to use the SoftwareSPI library, is because of a bug in SPI behaviour, likely related to SD cards.

Check out this library: GitHub - greiman/DigitalIO: Fast Digital I/O, Software I2C, and Software SPI for AVR Arduino

This is the library RF24 uses for softSPI, so you don't have to do the bit-banging yourself, its all automatic like the standard SPI library once configured correctly. It should be available in the Arduino Library Manager.

TMRh20 I'm good with other people figuring it out so I don't have to :slight_smile: plus I think that would have been a bit beyond me. I'll check that out.

The SD card issue you mention, is that the SD card in the TFT display?

Thanks for your help

Yup, well technically its the SD hardware, I don't think the actual card matters. I recall it requiring an extra step that either cannot be done or is not done in software.

FYI the RF24 documentation has some info softSPI.

TMRh20:
Nowadays, when users report issues with RF24 and multiple SPI devices, I typically verify that RF24 and said device are working independently, and default to suggesting a separate SPI BUS for each device.

That may be a practical solution but I felt that your comment in Reply #1 unfairly puts the blame at the feet of the nRF24. I have seen nothing in your RF24 library that should give rise to a problem and the nRF24 hardware is very straightforward.

...R

Yeah, it should have been "Next, other SPI devices sometimes just don't play well with the RF24".

Without your comment however, and the response regarding SD cards, it would not have been as easy to identify as the SD issue, so thanks for that. :stuck_out_tongue:

Close but no cigar yet. I made the changes to have the soft SPI work, installed the DigitalIO.h library, in the RF24_Conf.h file I un-commented the line #define SOFTSPI. Took me a little bit to figure out that the lines to define the soft SPI pins went in the RF24_conf.h file and not my sketch

#define SOFT_SPI_MISO_PIN 16
#define SOFT_SPI_M0SI_PIN 15
#define SOFT_SPI_SCK_PIN 14

So now it reads the radio except the characters are not showing correctly. If I comment the #define SOFTSPI and reconnect the radio to the standard SPI pins on a mega, 50, 51, 52. it reads the temperature and pressure correctly. With the soft SPI working instead of the temp and pressure values, 68, 29 I get 2 small squares for each.

I have a sketch that just reads the radio, no display, I have the logic to read the data, convert it from a string then print it on the serial monitor in a if (radio.available()) statement. Before I put the pin definitions in the RF24_conf file nothing would print so that told me the radio wasn't available. Once I did define the pins I get the printout but not the right values.

Does that tell me it now sees the radio, it's available, but not really reading the data?

Here's the sketch I am using.

// Bee Hive base Controller

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

#define radio_CS 4
#define radio_CSN 5

RF24 radio(radio_CS, radio_CSN); // 7, 8 CE, CSN
const byte addresses[][6] = {"1Node", "2Node"};

char text[6] = "";
//int readDHT22, t, h;
String inTemp, inHum, outTemp = "", outHum;

//String rtcTime, rtcDate;
//int draw_state = 0;
//unsigned long previousMillis = 0;
//long interval = 3000;

void setup() {
  Serial.begin(9600);
  Serial.println(F("Hive Base"));
   
  radio.begin(); // Initiate the radio object
 // radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);  // Set the transmit power to lowest available to prevent power supply related issues
  radio.setDataRate(RF24_2MBPS); // Set the speed of the transmission to the quickest available
  radio.setChannel(124); // Use a channel unlikely to be used by Wifi, Microwave ovens etc
   // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[0]);
  radio.openReadingPipe(1, addresses[1]);
  // Start the radio listening for data
  radio.startListening();

  
  
}
// end void setup

void loop() {


  // Now listen for a response
  radio.startListening();
 
    
 if (radio.available()) {
  Serial.println("radio.available");
    radio.read(&text, sizeof(text)); // Read incoming data
    outTemp = String(text[0]) + String(text[1]) + " 'F"; // Outdoor Temperature
    outHum = String(text[2]) + String(text[3]) + " inHg"; // Outdoor Humidity
  
 float  hive1_temp = (outTemp.toFloat()); // convert string to float
 float  hive1_hum = (outHum.toFloat()); // convert string to float

  Serial.print("Hive 1 temp ");
  Serial.print(outTemp);
  Serial.print("\t");
  Serial.print("Hive 1 Pressure ");
  Serial.println(outHum);
  } // end if (radio.available()
  
  delay(2000);

} // end void loop

Thanks again for taking the time to help, and educate, me. Greatly appreciated
John

You should be able to define the softSPI pins in your sketch as long as you put the defines at the very top, prior to including the .h files.

From your description, it sounds like a softSPI communication error, providing incorrect data, but it is most likely that the radio would not be responding at all if that was the case.

Without being able to see all of your code, it is very difficult to diagnose problems. Please post TX + RX code.

I would suggest learning about data structures:
https://playground.arduino.cc/Code/Struct/
http://tmrh20.github.io/RF24/GettingStarted_HandlingData_8ino-example.html

If you are starting with purely numerical data, like humidity and temperature readings, it is easiest to use data structures to keep it as such, until or unless it needs to be combined with character data. I suspect your issue is related to the handling of data, but cannot say without code.

I did have the pin defines after the includes, I moved them to before and commented them out in the conf file. It doesn't work. I then commented them out in my sketch, un-commented them in the config file and it works. At least it does make the radio available, still not reading the characters correctly. If I put it back to the standard SPI it does read them right.

Here's the sketch for the transmitter side.

// Hive 1 transmitter

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>
#include <nRF24L01.h>
#include <RF24.h>
//#include <LowPower.h>

Adafruit_BMP280 bmp; // I2C
RF24 radio(7, 8); // 10, 9 CE, CSN
//const byte address[6] = "00001";
byte addresses[][6] = {"1Node","2Node"};

float c_Temp = 0; // temp in C' from BMP280
float f_Temp = 0; // calculated F'
float H1_Prss = 0; // hive pressure
char thChar[32] = "";
String thString = "";


void setup() {
  Serial.begin(9600);
  Serial.println(F("Bee Hive 1"));

// Initialise NRF24L01
  radio.begin();
//  radio.openWritingPipe(address); 
  radio.setDataRate(RF24_2MBPS);
  radio.setChannel(124);
  radio.setPALevel(RF24_PA_MIN);
   // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1, addresses[0]);
  
  radio.stopListening();


  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1);
  } // end if (!bmp.begin())

   /* Default settings from datasheet for BMP280. */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  

} // end void setup

void loop() {
  Serial.print(F("Temperature = "));
    c_Temp = bmp.readTemperature(); // read temp from BMP280
    f_Temp = (c_Temp * 9/5) + 32; // calculate F'
    H1_Prss = (bmp.readPressure() / 3389.39);
    
    Serial.print(f_Temp);
    Serial.print("\t");
    
    Serial.print(F("Pressure = "));
    Serial.print(bmp.readPressure() / 3389.39);
    Serial.println(" inHg");

    Serial.println();

    // Transmitter Temp and Pressure
 // int readData = DHT.read22(dataPin); // Reads the data from the sensor
  int t = f_Temp; //bmp.readTemperature(); // Gets the values of the temperature
  int h = H1_Prss; // Gets the values of the humidity
  thString = String(t) + String(h);
  thString.toCharArray(thChar, 12);
  
  
  // Sent the data wirelessly to the indoor unit
  for (int i = 0; i <= 3; i++) {           // Send the data 3 times
    radio.write(&thChar, sizeof(thChar));
    delay(50);
  }// end for loop
  
    
    delay(2000);

} // end void loop

thanks
John

Ok, I guess the pins can't be defined in the sketch. :confused:

I should have realized what the problem was right away...

I said prev.

From your description, it sounds like a softSPI communication error, providing incorrect data, but it is most likely that the radio would not be responding at all if that was the case.

Well, that is exactly what the problem was. Not sure what I was thinking, but the radio should always respond, just with garbage data if your wiring is incorrect for softSPI.

I was confused because the code is odd, but doesn't explain the behaviour, so I tested it myself and it works as I expected it to. I can't recreate your issue without mis-wiring the radio module.

A bit confused as to what you're saying. Do you think I don't have the radio wired correctly for the softSPI. I have MISO on pin 16, MOSI on pin 15, and SCK on pin 14, I haven't changed the CS pin 4, or CSN pin 5 for either SPI.

What do feel is odd about the code? I got this off of a website where the guy builds different Arduino projects, this one happens to be a weather station, he used DHT22 sensors, I find those aren't very accurate so I swapped out for the BMP280. It may not be the best way to send data but it works when I use the standard SPI. Do I have to transfer or decoded the data a different way because of the softSPI?

Thanks

A bit confused as to what you're saying. Do you think I don't have the radio wired correctly for the softSPI.

Yes. That or something else you are doing different that I cannot identify. I use the same hardware, same code, but get a working result. There are few possibilities.

What do feel is odd about the code?

Hmm, well the transmitter takes a reading as a Float, then the Float value is loaded into an Integer, then converted to a String, then converted to a char array.

The receiver gets the char array, converts it back to a String, then back to a Float, and prints the String.

Its like some kind of Rube Golberg Machine.

I'll double check my connections and disconnect anything not associated with the basic setup.

It does seem like a long way around to get there doesn't it. I have another sketch that I had used to send data from one Arduino to another via Xbees, not that it should matter how it's sent. I'll rewrite the code to that format.

thanks so much for your patience

TMRh20 I stripped everything down and went back to square 1, the radio's are now communicating, I think I had criss crossed a couple of the radio wires when going back and forth with the SPI's. I still can't get the soft SPI to work but the display can also be used in a 8-bit mode so I'll move on and do it that way.

This is slightly off the subject and I hope you don't mind me asking otherwise I'll start a new thread. First I changed my sensor to a BME280 so I get temp, humidity and pressure now. Then I changed the method of sending the data, as you mentioned it was a bit convoluted. I have used this before but with Xbee's, not sure if that makes a difference. I actually got this from another helpful person on this forum a couple of years ago. I build a string with start and end markers with the data separated by commas. So when I send the string for temp, press, humidity I get <68.45,29.67,30.12>. I believe that part is working.

On the receiving end, the mega, I parse the string, at least that's what it's supposed to do all I get is 00.00,00.00,00.00. I've confirmed that the radio is available. So I'm not sure if I am reading the data into the array correctly, or not parsing it right, or something else.

If you have the time could you look this over for me?
Thanks so much
John

Here are the sketches

Hive transmitter

// Hive 1 transmitter, reads BME280 for temp and pressure

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <nRF24L01.h>
#include <RF24.h>
#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
RF24 radio(7, 8); // 10, 9 CE, CSN
//const byte address[6] = "00001";
byte addresses[][6] = {"1Node","2Node"};

float c_Temp = 0; // temp in C' from BMP280
float f_Temp = 0; // calculated F'
float H1_Prss = 0; // hive pressure
float H1_Humd = 0; // Hive humidity

char thChar[32] = "";
String thString = "";
char a;
char startMarker = '<';
char endMarker = '>';
char comma = ',';


void setup() {
  Serial.begin(9600);
  Serial.println(F("Bee Hive 1"));

// Initialise NRF24L01
  radio.begin();
  radio.setDataRate(RF24_2MBPS);
  radio.setChannel(124);
  radio.setPALevel(RF24_PA_MIN);
   // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1, addresses[0]);
  
  radio.stopListening();


   if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  } // end if (!bmp.begin())


   /* Default settings from datasheet for BMP280. */
 // bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
//                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
//                 Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
//                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
//                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */


} // end void setup

void loop() {

    // Read BMP280
    c_Temp = bme.readTemperature(); // read temp from BME280
    f_Temp = (c_Temp * 9/5) + 32; // calculate F'
    H1_Prss = (bme.readPressure() / 3389.39);
    H1_Humd = bme.readHumidity();
    
 Serial.print("Temperature = ");
 // Serial.print(bme.readTemperature());
  Serial.print(f_Temp);
  Serial.println("*F");

  Serial.print("Pressure = ");
  //Serial.print(bme.readPressure() / 100.0F);
  //Serial.println("hPa");
  Serial.print(bme.readPressure() / 3389.39);
   Serial.println(" inHg");

/*  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println("m");
*/
  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println("%");

  Serial.println();
  
// build string to transmitt
  thString = String(startMarker) + String(f_Temp) + String(comma) + String(H1_Prss) + String(comma) + String(H1_Humd) + String(endMarker);
  thString.toCharArray(thChar, 20);
  Serial.println(thString);
  
  radio.write(&thString, sizeof(thString)); // send strin to base
   
    
    delay(2000);

} // end void loop

and here is the receiving base

// Read Bee Hive data

#include <SPI.h>
m #include <RF24.h>
#include "Adafruit_GFX.h"
#include "Adafruit_HX8357.h"

// for NRF24L01
#define radio_CS 4
#define radio_CSN 5

RF24 radio(radio_CS, radio_CSN); // 4, 5 CE, CSN
const byte addresses[][6] = {"1Node", "2Node"};


// Variables

char hive1Temp[20] = " "; // Hive 1 Temperature number
char hive1Hum[20] = " "; // Hive 1 Humidity number
long int start_time = millis();
long int read_time = 5000; // time between reading hive data
int hiveRead = 0; // bit that system is reading hive status
float  hive1_Temp = 0; // Hive 1 temp
float  hive1_Hum = 0; // Hive 1 humdity
float  hive1_Press = 0; // Hive 1 pressure
boolean newData = false;

    // temporary array for use when parsing
const byte numChars = 64;
char receivedChars[numChars];
char tempChars[numChars];  
unsigned char text;     

void setup() {
   Serial.begin(9600);
  Serial.println(F("Hive Base"));
  

// NRF24L01 setup
  radio.begin(); // Initiate the radio object
 // radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);  // Set the transmit power to lowest available to prevent power supply related issues
  radio.setDataRate(RF24_2MBPS); // Set the speed of the transmission to the quickest available
  radio.setChannel(124); // Use a channel unlikely to be used by Wifi, Microwave ovens etc
   // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[0]);
  radio.openReadingPipe(1, addresses[1]);
  // Start the radio listening for data
  radio.startListening();


} // end void setup

void loop() {
   recvWithStartEndMarkers(); // Read data from controller
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
            
        parseData(); // Split data into separate variables
        newData = false;
    }

showParsedData(); // Send data to serial monitor

} // end void loop

void recvWithStartEndMarkers() { // reads variables from controller 
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

     while (radio.available() > 0 && newData == false) {
      Serial.println("available");
        radio.read(&text, sizeof(text));  

        if (recvInProgress == true) {
            if (text != endMarker) {
                receivedChars[ndx] = text;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (text == startMarker) {
            recvInProgress = true;
        }
    }

  } // end recvWithStartEndMarkers()

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

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    hive1_Temp = atoi(strtokIndx);     // Hive temperature
    
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    hive1_Hum = atoi(strtokIndx);     // Hive humidity

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    hive1_Press = atoi(strtokIndx);     // Hive pressure

    } // end parsedata

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

void showParsedData() { // print to serial monitor
   
  // Write the results to the serial port, to Pi
Serial.print(hive1_Temp); Serial.print(",");
Serial.print(hive1_Hum); Serial.print(",");
Serial.println(hive1_Press);

  // delay 500 milliseconds
delay(100);

} // end showparsedData