Strcut data NRF24L01

Below is the code that I have working great, Both code of the RX & TX is set up the same. But would like to add a struct so that I could also send out the battery reading to enable me to display this on the RX unit.

But having a bit of trouble in doing so, To start with I just tried to getting it to send the receivedChars value using the struct for the data by using method 1 in my code and thought once I’ve got this part working then add the battery voltage code to the struct to send over to the TX unit.

But the trouble is the angle reading doe not show on the RX unit, All the parts of that code are working so when the TX unit is turned off the lost signal part still works so I know it’s receiving the data.

I’d highlighted out the char inclinometer_send[numChars] of the TX code and left the TX_Value in and set it to the same on the RX code and this is sending the TX_Value out and displaying the correct value on the rX screen.

Method 2 works perfectly and when I highlight out Method 2 and use method 1 I get the error about.

TX_code:

#include <SPI.h>
#include "RF24.h"  // Download and Install (See above)
#include <Wire.h>
const byte numChars = 8; //After testing this is all I need same setting for the RX
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;
#define CE_PIN   6
#define CSN_PIN 10
RF24 Radio(CE_PIN, CSN_PIN); // Create a Radio
float Batt_R1 = 10113.00;
float res2 = 2347.00;
float volts2;
#define VMIN 3.00 // Battery voltage minimum
#define VMAX 4.20  //battery voltage maximum
float TX_batteryPercentage;
#define Error_led 13
const long TX_interval = 500;  //Error flag timer for not recieving from the tx
unsigned long lastRecvTime = 0; // escape from recieve data
unsigned long TX_previousMillis = 0; // stores the last mills
byte addresses[][6] = {"1Node"}; // Create address for 1 pipe.
//Create data to send
struct MyData {
  char   inclinometer_send[numChars];
  // int   TX_Value;
};
MyData data;

void setup() {
  pinMode(Error_led, OUTPUT);
  digitalWrite(Error_led, LOW);
  Serial.begin(9600);
  Radio.begin();  // Start up the physical nRF24L01 Radio
  Radio.setChannel(108);  // Above most Wifi Channels
  Radio.setPALevel(RF24_PA_MAX);  // Uncomment for more power
  Radio.setDataRate(RF24_250KBPS); // Fast enough.. Better range
  Radio.openWritingPipe( addresses[0]); // Use the first entry in array 'addresses' (Only 1 right now)
}

void loop() {
  recvWithEndMarker();
  showNewData();
  int sensorValue = analogRead(A1);
  float voltage = sensorValue * (5.0 / 1023.0);
  volts2 =  voltage / (res2 / (Batt_R1 + res2)); // devide the incoming battery voltage
  TX_batteryPercentage = (( volts2 - VMIN) / (VMAX - VMIN)) * 100; // convert battery voltage to percentage reading
  // data.TX_Value = sensorValue;
  unsigned long TX_Error = millis();
  if (TX_Error - TX_previousMillis >= TX_interval && TX_batteryPercentage < 55 ) {
    // save the last time you blinked the LED
    TX_previousMillis = TX_Error;
    digitalWrite(Error_led, !digitalRead(Error_led));
  }

}
void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;
  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewData() {
  if (newData == true) {
    data.inclinometer_send[numChars] = receivedChars;
    //### Method 1 ,This does not work and the TX remains blank for the angle code reading,whith the same set up on the TX code
    Radio.write( &data, sizeof(MyData) ); //  Transmit the data
    //###Method 2 , This part send ot the correct data and the RX shoes corrrect values whith the same set up on the TX code
    //   Radio.write( &receivedChars, sizeof(receivedChars) ); //  Transmit the data
    newData = false;
  }
}

The psot excced 9000 characters so rahter than people download it I’'ll post teh RX code in second post

Thanks
Steve

Here is the RX Code:

//####################################################
//# Include all the libraries                        #
//####################################################
//#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
#include  <Wire.h> //Wire libary 
#include <SPI.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include "RF24.h"  // Download and Install (See above)
#include <TFT_ST7735.h>
#define CE_PIN   6
#define CSN_PIN 10
//#############################################
// adding read battery
//############################################
float input_voltage = 0.0;
//#########################################
const long TX_interval = 500;  //Error flag timer for not recieving from the tx
unsigned long lastRecvTime = 0; // escape from recieve data
unsigned long TX_previousMillis = 0; // stores the last mills
const long TX_interval1 = 500;  //Error flag timer for not recieving from the tx
unsigned long lastRecvTime1 = 0; // escape from recieve data
unsigned long TX_previousMillis1 = 0; // stores the last mills
int eLevel_angle_; //angle in hundredths of a degree
byte addresses[][6] = {"1Node"}; // Create address for 1 pipe. Test 2
//const uint64_t pipeIn =  0xB3B4B5B6A3LL;//0xE8E8F0F0E1LL64 bit encrypicted code
RF24 Radio(CE_PIN, CSN_PIN);
const byte numChars = 8; //After testing this is all I need same setting for the TX
char receivedChars[numChars];   // an array to store the received data
bool newData = false;
bool lostData = false;
#define Error_led 2
#define sclk 13
#define mosi 11
#define cs   5
#define dc   8
#define rst  4 //  reset
float Batt_R1 = 10113.00;
float res2 = 2347.00;
float RX_volts;
float TX_volts;
int RX_Battery;
#define VMIN 3.00 // Battery voltage minimum
#define VMAX 4.20  //battery voltage maximum
float TX_batteryPercentage;
float RX_batteryPercentage;
TFT_ST7735 myGLCD = TFT_ST7735();
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
struct MyData {
  char eLevel_angle[numChars];
  //int TX_Value;
};
MyData data;
void resetData()
{

  unsigned long TX_Error = millis();
  newData = false;
  TX_batteryPercentage = 0;
  if (TX_Error - TX_previousMillis >= TX_interval) {
    // save the last time you blinked the LED
    TX_previousMillis = TX_Error;
    digitalWrite(Error_led, !digitalRead(Error_led));
    tft.setTextColor(ST7735_RED, ST7735_WHITE);
  }
  if (newData == false) { //new data received from eLevel
    tft.setTextColor(ST7735_BLACK, ST7735_WHITE);
    tft.setTextSize(3);
    tft.setCursor(8, 40);
    // tft.print(receivedChars);
    tft.setTextSize(1);
    tft.setCursor(40, 80);
    tft.print("TX SIGNAL LOST ");
    // tft.setCursor(50, 110);
    // tft.print("LOST ");
  }
}
void setup()   /****** SETUP: RUNS ONCE ******/
{
  pinMode(Error_led, OUTPUT);
  digitalWrite(Error_led, LOW);
  Serial.begin(9600);
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
  tft.setRotation(tft.getRotation() - 1);
  tft.fillScreen(ST7735_WHITE); //  clear screen

  // tft.fillScreen(ST7735_BLACK); //  clear screen
  Radio.begin();  // Start up the physical nRF24L01 Radio
  Radio.setChannel(108);  // Above most Wifi Channels
  Radio.setPALevel(RF24_PA_MAX);  // Uncomment for more power
  Radio.setDataRate(RF24_250KBPS); // Fast enough.. Better range
  Radio.openReadingPipe(1, addresses[0]); // Use the first entry in array 'addresses' (Only 1 right now)
  Radio.startListening();
  // resetData();



}//--(end setup )---
void recvData()
{
  while ( Radio.available() ) {
    //## Method 1, This does not sow anyting on the screen whith the same set up on the TX code
    Radio.read( &data, sizeof(MyData) ); // Get the data payload (You must have defined that already!)
    //## Method 2, This dipslay the correct values whith the same set up on the TX code
    //   Radio.read( &receivedChars, sizeof(receivedChars) ); // Get the data payload (You must have defined that already!)
    lastRecvTime = millis();
    newData = true;
  }
}

void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  recvData();
  // Read the RX battery
  RX_Battery = analogRead(A1);
  float RX_voltage = RX_Battery * (5.0 / 1023.0);
  RX_volts =  RX_voltage / (res2 / (Batt_R1 + res2)); // devide the incoming battery voltage
  RX_batteryPercentage = (( RX_volts - VMIN) / (VMAX - VMIN)) * 100; // convert battery voltage to percentage reading
  //Read the TX battery
  /*
    float TX_voltage = data.TX_Value * (5.0 / 1023.0);
    TX_volts =  TX_voltage / (res2 / (Batt_R1 + res2)); // devide the incoming battery voltage
    TX_batteryPercentage = (( TX_volts - VMIN) / (VMAX - VMIN)) * 100; // convert battery voltage to percentage reading
  */

  if (newData == true) { //new data received from eLevel
    tft.setTextColor(ST7735_GREEN, ST7735_WHITE);
    tft.setTextSize(1);
    tft.setCursor(40, 80);
    tft.print("TX SIGNAL GOOD ");
    // tft.setCursor(50, 110);
    // tft.print("GOOD ");
  }
  // recvData();
  unsigned long now = millis();
  if ( now - lastRecvTime > 1000 ) { //if data stops coming turn everything off with a second
    // signal lost?
    resetData();
  }
  showData();
  digitalWrite(Error_led, LOW);

}




void showData() {
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(1);
  tft.setCursor(20, 5);
  tft.println("STEVE'S INCLINOMETER");
  tft.setCursor(40, 20);
  tft.println("PRO3600 LEVEL");
  tft.setTextColor(ST7735_BLACK, ST7735_WHITE);
  tft.setTextSize(3);
  tft.setCursor(8, 40);
  tft.print(data.eLevel_angle);
  //  }
  tft.setTextSize(2);
  tft.setCursor(135, 20);
  tft.print("o");
  tft.setTextSize(1);
  tft.setCursor(15, 85);
  //  tft.print(data.TX_Value);
  tft.setCursor(15, 100);
  tft.print("RX BATTERY:");
  tft.print(RX_batteryPercentage, 0);
  tft.print(" %");
  tft.setCursor(15, 115);
  tft.print("TX BATTERY:");
  tft.print(TX_batteryPercentage, 0);
  tft.print(" %");
  //tft.print("   ");
}

Where am I going wrong ?

Thanks
Steve

The code seems quite confusing, but I spotted this line:

data.inclinometer_send[numChars] = receivedChars;

If you think that this will copy "numChars" from "receivedChars" to "data.inclinometer_send" then you are wrong, the right approach is:

memcpy(data.inclinometer_send, receivedChars, numChars);

But I think this line of code should not be necessary at all. Read the chars directly from serial into "data.inclinometer_send" and remove "receivedChars" from the code since it is not required and a waste of memory.

Danois90:
But I think this line of code should not be necessary at all. Read the chars directly from serial into "data.inclinometer_send" and remove "receivedChars" from the code since it is not required and a waste of memory.

That may be more efficient but it is probably not as clear for a newbie. The array receivedChars is part of the code in Serial Input Basics and it is probably easier for a newbie to avoid fiddling with that.

Optimising to avoid wasting memory is only useful when you are actually running out of it :slight_smile:

...R

Danois90:
The code seems quite confusing, but I spotted this line:

data.inclinometer_send[numChars] = receivedChars;

If you think that this will copy "numChars" from "receivedChars" to "data.inclinometer_send" then you are wrong, the right approach is:

memcpy(data.inclinometer_send, receivedChars, numChars);

But I think this line of code should not be necessary at all. Read the chars directly from serial into "data.inclinometer_send" and remove "receivedChars" from the code since it is not required and a waste of memory.

That works, I now have it working in a fashion that I'm happy with.

I now display both the Angle Level and the battery percentage coming from the TX unit on the TFT RX screen.
I will have to see about reading up on memcpy. Learning something new every day

Thanks Guys

Steve