Help with Tmrh20 nRF24L01 library

Hi,
My setup is as follows:
Two transmitters sending data to one central unit.
The transmitting units do not receive data, they transmit only.
I am using the instruction ok = network.write(header,&payload,sizeof(payload)) to confirm that the data has been sent.
The curious thing is that the function returns a false but the data has been transmitted.
What am I missing?

I will attach the transmitter code, which is "short".
I will not post The receiver code because it has more than 1200 lines and a lot of calculations and functions that are not related to the question.
Thanks.

// Load driver for LED display
#include "Wire.h"
#include "hd44780.h"                       // main hd44780 header
#include "hd44780ioClass/hd44780_I2Cexp.h" // i2c expander i/o class header

// load RF related libraries
#include "RF24Network.h"
#include "RF24.h"
#include "SPI.h"

// Define LCD geometry and properties
hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

//  Define if we want to print values in serial monitor (DEBUG)
 bool serialPrintFlag = HIGH;    //<============ SET THE DEBUG OPTION HERE (ACTIVE HIGH)########################################

// Set a Flag to simulate that data to be transmitted (active HIGH)
bool simulateInputData = LOW;   //  <================================ Use this to input data to the sketch#######################

//---- Define sensor conections to Arduino 
//???????? const int dpPort = 1; // changed in this revision (14/07/2020)
const byte dpPort = 1;
const byte flowSensor1_pin = 7; //  In Arduino Promicro INT6  = Pin7
const byte flowSensor2_pin = 0; //  In Arduino Promicro INT2  = Pin0  ####Do NOT use Serial1 #####

//----Define pin to activate the data sent ok!/ Tx failed messages
const byte activateMessages_pin = 21;

// The hall-effect flow sensor outputs approximately 7.0 pulses per second per litre/minute of flow
float calibrationFactor = 8.275;    // ########Changed according to data on datasheet table pag 2


float altura = 120.00; //altura da caixa dagua em cm
float flow = 0.0;
float totalFlow = 0.0; //used only for sensor calibration
float auxVol = 0.0;      // total volume pumped in this cycle

//------optFlowrate variables------
volatile byte FlowSensorPulseCount_1 = 0;  // 255 counts is about 0.6 liters
volatile byte FlowSensorPulseCount_2 = 0;
float flowRate;
unsigned long oldTime;
float flowRateLPM = 0.0;
float totalLiters_1 = 0.0;
float totalLiters_2 = 0;
float vazaoPoco;

//------Display without delay variables and definitions-------------------
long previousLCDMillis = 0;    // for LCD screen update
long lcdInterval = 4000;
int screen = 0;   
int screenMax = 2;

bool screenChanged = true;   // initially we have a new screen,  by definition
// defines of the screens to show
#define LEVEL       0
#define FLOWRATE       1
#define BATCHVOL         2
#define DATATRANSMISSION   3

//------------ used to caclculate volume pumped in each pumping cycle
float old_Total = 0.0;
int i=0;

int levelDp = 0;
int rawDp = 0;
int rawDpMin = 32;
int rawDpMax = 192; // measured when actual tank was 100% full--revised 2/11/2020

float dummy1 = 0.0;
float dummy2 = 0.0;
bool  dummy3 = 0;
float dummy4 = 0.0;

bool ok = LOW;  // need to be initialised- can go HIGH even without nRF24L01 installed

// nRF24L01(+) radio attached  (CE, CSN)
RF24 radio(9,10);
// Network uses that radio
RF24Network network(radio);
// Channel of our node
const uint16_t channel = 108;
// Address of our node
const uint16_t this_node = 02;   //changed to 02 in rev3b (was 2)
// Address of the other node
const uint16_t other_node = 00; //changed to 00 in rev3b (was 0)
// How many packets have we sent already
unsigned long packets_sent;

//-------added on rev3_newtime----------
// How often to send data 
const unsigned long Tx_interval = 1000; //ms //changed in julY 2023 
// When did we last send?
unsigned long last_sent =0; //changed in rev Marco2021



//The data to be transmitted by lower and upper water tanks modules is:
//         type       cisterna     caixa superior
//        -------    ----------    --------------
//  1      float      Irms         auxVol   (last pumping cycle volume)
//  2      float     flow          flow
//  3      float     Pdisch        totalLiters_1
//  4      float     DpFilter      vazaoPoco // changed in July 2023
//  5      float     Pinlet        dummy2
//  6      float     lampCurrent   dummy4  //added in March 2021
//  7      int       rawDp         rawDp
//  8      bool      flapstate     dummy3

// Structure of our payload, limited to 32 bytes
struct payload_t      // 32 bytes max,  used=7*4+2+1 = 31 bytes OK! updated March 2023
{
  uint32_t counter;     // number of packets transmitted  4-bytes
  float auxVol;         //-4 bytes
  float flowRateLPM;    //-4 bytes
  float totalLiters_1;  //-4 bytes
  float vazaoPoco;      //-4 bytes
  float dummy2;         //-4 bytes
  float dummy4;         //-4 bytes
  int16_t rawDp;        //-2 bytes
  bool  dummy3;         //-1 byte 
};

//???  payload_t payload = { packets_sent++, auxVol, flowRateLPM, totalLiters_1, vazaoPoco, dummy2, dummy4, rawDp, dummy3 }; // DOES NOT WORK HERE!!!!
// * Invoked by interrupt once per pulse of the flow sensor.
// * Interrupt handlers should be kept as small as possible so they return quickly.
void pulseCounter_1()
{
  FlowSensorPulseCount_1++;  // Increment the pulse counter
}

void pulseCounter_2()  // Added July 2023
{
  FlowSensorPulseCount_2++;  // Increment the pulse counter
}
void setup()
{
  Serial.begin(115200); // start serial communication

  // Print a message to the LCD
  lcd.begin(16, 2);
  lcd.backlight();
  
//-----Welcome Display Function  
  showWelcome();

 // Check if data input is simulated and print warning message
  if (simulateInputData == HIGH)
   { lcd.clear(); 
     lcd.print(F("DATA READ SIMULATED"));
   }

// If message ok pin is HIGH, increase screenMax to 3 (data sent ok/ Tx failed case)
 if (digitalRead(activateMessages_pin) == HIGH) screenMax = 3;
 
  //*******Start Radio and define some parameters
  SPI.begin();
  radio.begin();
  network.begin(channel, this_node);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setAutoAck(false);             //        added Marco2021
  radio.setDataRate( RF24_250KBPS );  //         added on rev 3C
//???  radio.setRetries(15,15); // (delay, count)     added on rev 3C-----  No need if setAutoAck = false
  radio.stopListening();   //                    added on rev 3C

// New Flowmeter initializations
 pinMode(flowSensor1_pin, INPUT);
 attachInterrupt(digitalPinToInterrupt(flowSensor1_pin), pulseCounter_1, RISING);
pinMode(flowSensor2_pin, INPUT);
attachInterrupt(digitalPinToInterrupt(flowSensor2_pin), pulseCounter_2, RISING);

}    //------ end of setup

void loop() 
{
//------ Initialize OptFlowrate & Display without Delay variables ------
  unsigned long currentMillis = millis();
  static unsigned long previousMillis = 0;
  static unsigned long totalFlowSensorPulseCount_1 = 0;
  static unsigned long totalFlowSensorPulseCount_2 = 0;
  
 //--------- Calculate flow once per interval --------
  const unsigned long interval = 1000;  // count the number of pulses in one second ==> 1 pps = 1 Hz
  if (currentMillis - previousMillis >= interval)
  {
    previousMillis += interval;

    noInterrupts();  // Prevent an interrupt while we sample and reset the pulse count
    byte currentFlowSensorPulseCount_1 = FlowSensorPulseCount_1;
    byte currentFlowSensorPulseCount_2 = FlowSensorPulseCount_2;
    FlowSensorPulseCount_1 = 0;  // Re-start the counter for the next second
    FlowSensorPulseCount_2 = 0;
    interrupts();
    totalFlowSensorPulseCount_1 += currentFlowSensorPulseCount_1;
    totalFlowSensorPulseCount_2 += currentFlowSensorPulseCount_2;


     flowRateLPM = (currentFlowSensorPulseCount_1 / calibrationFactor) * (1000.0 / interval); // 1 calibrationFactor  pulses per second == 1 LPM
     totalLiters_1 = totalFlowSensorPulseCount_1 / (calibrationFactor * 60.0);  // 1 calibrationFactor pulses per second == 1 LPM so 7*60 P == 1 L
     vazaoPoco = (currentFlowSensorPulseCount_2 / calibrationFactor) * (1000.0 / interval);
     totalLiters_2 = totalFlowSensorPulseCount_2 / (calibrationFactor * 60.0); 
if ( serialPrintFlag == HIGH)
    {
    Serial.print(F("currentMillis = "));
    Serial.println(currentMillis);
    Serial.print(F("currentFlowSensorPulseCount_1 = "));
    Serial.println(currentFlowSensorPulseCount_1);
    Serial.print(F("flowRateLPM = "));
    Serial.println(flowRateLPM);
    Serial.print(F("totalFlowSensorPulseCount_1 = "));
    Serial.println(totalFlowSensorPulseCount_1);
    Serial.print(F("totalLiters_1 = "));
    Serial.println(totalLiters_1);
    Serial.print(F("currentFlowSensorPulseCount_1 = "));
    Serial.println(currentFlowSensorPulseCount_2);
    Serial.print(F("Vazao Poco = "));
    Serial.println(vazaoPoco);
    Serial.print(F("totalFlowSensorPulseCount_2 = "));
    Serial.println(totalFlowSensorPulseCount_2);
     Serial.print(F("totalLiters_2 = "));
    Serial.println(totalLiters_2);
   }
  }

// Calculate the volume pumped each time the pumping turns on-off


// check if the pump has started 
if (flowRateLPM > 0.0 && i== 0 ) 
    { auxVol = totalLiters_1 - old_Total;
     if (serialPrintFlag == HIGH)
      {
      Serial.println(F("esta bombeando")); 
      Serial.print(F("Total= "));
      Serial.println(totalLiters_1);
      Serial.print(F("old_Total= "));
      Serial.println(old_Total);
      Serial.print(F("Vol Bomb= "));
      Serial.println(auxVol);
     }
    }
// If the pump stopped, store the current total flow
// making i=1 would prevent variables to be updated until the pump starts again   
if (flowRateLPM == 0.0 && i==0 )
{
   old_Total = totalLiters_1; 
   i=1;
}

// If the pump has started again, set i=0 and start over
if (flowRateLPM > 0.0 && i==1 ) i=0; 

//********Read level from DP sensor************
  rawDp = analogRead(dpPort);
  delay (1000);
  
// ********Calculate level (in %) from measurements*********
  levelDp  = map(rawDp, rawDpMin, rawDpMax, 0, 100);

// print level on serial monitor
 if ( serialPrintFlag == HIGH)
  {
  Serial.print (F("rawDp= "));
  Serial.println (rawDp);
  Serial.print (F("level= "));
  Serial.println (levelDp);
  Serial.print (F(" %"));
  }
//******* Pump the network regularly*******
  network.update();

// check if we want to define a set of value to the variables to be transmitted
 if(simulateInputData == HIGH) input_Data();
  
//-----added in rev3_newtime-----------
  // If it's time to send a message, send it!
  unsigned long now = millis();   // move up after testing...
  if ( now - last_sent >= Tx_interval  )
  {
    last_sent = now;
    sendPayload();
  }
  
  display_Data();


}        // this is the end of the loop

  
//////////////////////////////////////////////////////////////////////////////////
//          sendPayload                                                         //
//////////////////////////////////////////////////////////////////////////////////
// ********* Transmit data ********************
void sendPayload()
{

  RF24NetworkHeader header(/*to node*/ other_node);
  payload_t payload = { packets_sent++, auxVol, flowRateLPM, totalLiters_1, vazaoPoco, dummy2, dummy4, rawDp, dummy3 };
  ok = network.write(header,&payload,sizeof(payload));

//------Debug--------
 if ( serialPrintFlag == HIGH)
   {
    Serial.println(F("---------------------------"));
    Serial.print(F("millis() = "));
    Serial.println(millis());
   }
   
}

///////////////////////////////////////////////////////////////////////////////
// Auxiliary display functions                                                         //
///////////////////////////////////////////////////////////////////////////////
void showWelcome()
{
  lcd.clear(); 
  lcd.setCursor(0,0);
  lcd.print(F("caixa Opt Flow"));
  lcd.setCursor(0, 1);
  lcd.print(F("rev A-Set 2023"));
   delay(2000); 
  lcd.clear(); 
  lcd.setCursor(0,0);
  lcd.print(F("23/08/2023"));
   delay(2000); 
}

void showLevel()
{
  lcd.clear();
  lcd.print(F("rawDp= "));
  lcd.print(rawDp);
  lcd.setCursor(0, 1);
  lcd.print(F("nivelDp= "));
  lcd.print(levelDp);
  lcd.print(F(" %"));
}

void showFlowrate()
{
    lcd.clear();
   lcd.print(F("Flow=  "));
   lcd.print(flowRateLPM);
   lcd.setCursor(0, 1);
   lcd.print(F("Vazao Poco= "));
   lcd.print(vazaoPoco);
}

void showBatchVolume()
{
   lcd.clear();
   lcd.print(F("Vol in this Cycle"));
   lcd.setCursor(0, 1);
   lcd.print(auxVol);
}

void showDataTransmission()
{
  if (ok)
    { lcd.clear();
     lcd.print(F( "data sent OK"));
     if( serialPrintFlag == HIGH) Serial.println(F("data sent OK"));
     
    }
    else{
     lcd.clear();
     lcd.print( "TX FAILED");
     if ( serialPrintFlag == HIGH) Serial.println(F("TX FAILED"));
    } 
}

////////////////////////////////////////////////////////////////////////////
//        Display Function
////////////////////////////////////////////////////////////////////////////
 // MUST WE SWITCH SCREEN?
 void display_Data()
 {
  unsigned long currentLCDMillis = millis();
  if(currentLCDMillis - previousLCDMillis > lcdInterval)              // save the last time you changed the display
  {
    previousLCDMillis = currentLCDMillis;
    screen++;
    if (screen > screenMax) screen = 0;  // all screens done? => start over
    screenChanged = true;
  }

  // DISPLAY CURRENT SCREEN
  if (screenChanged)  // -- only update the screen if the screen is changed.
  {
    screenChanged = false; // reset for next iteration
    switch(screen)
    {
    case LEVEL:
      showLevel();
      break;
    case FLOWRATE:
      showFlowrate();
      break;
    case BATCHVOL:
     showBatchVolume();
      break;
    case DATATRANSMISSION:
     showDataTransmission();
      break;
    default:
      // cannot happen -> showError() ?
      break;
    }
  }
 }

 //////////////////////////////////////////////////////////////////////
 // input_Data - define values to variables to be transmitted
 //////////////////////////////////////////////////////////////////
 void input_Data()
 {
  auxVol = 123.4;
  flowRateLPM =7.6;
  vazaoPoco = 5.4;
  rawDp = 120;
 }

Part of the problems are the same as here

Why is the payload still too big, why do you still try to run the network layer without AutoAck?

To me, it seems you ignore hints and just ask the same in a new thread.

Hi Whandall,
I am not igoring the hints, but there are ocasions where I do not understand what I am supposed to do.
Concerning the network layer, the unit that was having the problem described o the thread you mentioned has been competely rebuilt and had worked fine since then.

I am rebuilding the 2nd transmitter ( the earlier versions has been mofied on the field many times and ia a little messy) and these are bech tests.

In these becnh tests, the use of autoack instruction cause the system to stop working EVERYTIME I tried, that's why I am not using it.

Would you please help me to implement this in the code?
Thank you.

Good luck.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.