Need help with bidirectional communication on Arduino

Hello, I started making a project which involved 2 Arduino Unos, 2 nRF24L01+ modules, 2 LCDs, and buttons. The plan was to make bidirectional communication between the Arduinos with sending each other a text message which is displayed on the LCDs using a button on the other side. I made the code and uploaded it on both the Arduinos but it only work one way. The first arduino is sending the message to the second but not vice versa. I think my problem is how I made the code so I am uploading it here with the schematics and I look forward to the answers. (I apologize for the schematic it's kind of messy.


//Code 1: First Arduino

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

RF24 radio(7, 8);                                           // CE, CSN
const byte addresses[][10] = { "ADDRESS01", "ADDRESS02" };  //addresses define

const int rs = 10, en = 9, d4 = 5, d5 = 4, d6 = 3, d7 = 2;  //LCD define
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);                  //LCD
const int B1_Pin = 6;                                       // Pushbutton B1
char txt1[] = "B1", txt3[] = "00";

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);

  pinMode(B1_Pin, INPUT);

  radio.begin();
  radio.openWritingPipe(addresses[0]);     //ADRESS01
  radio.openReadingPipe(1, addresses[1]);  //ADRESS02
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
};

void loop() {
  delay(10);
  radio.startListening();
  delay(10);
  radio.stopListening();

  int B1_State = digitalRead(B1_Pin);

  if (B1_State == HIGH) {
    radio.write(&txt1, sizeof(txt1));
    Serial.println(txt1);
  } else {
    radio.write(&txt3, sizeof(txt3));
    Serial.println(txt3);
  };
  delay(10);

  if (radio.available()) {
    char txt[5] = "";
    radio.read(&txt, sizeof(txt));
    switch (txt[1]) {
      case '2':
        lcd.print("hello, world!");
        delay(3000);
        lcd.clear();
        break;
      default: lcd.clear(); break;
    };
    Serial.println(txt);
  };
};


//Code 2: Second Arduino

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

RF24 radio(7, 8);  // CE, CSN
const byte addresses[][10] = {"ADDRESS01","ADDRESS02"}; //adresses define

const int rs = 10, en = 9, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //LCD define
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //LCD
const int B2_Pin = 6;  // Pushbutton B1
char txt7[] = "B2", txt8[] = "00";

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);

  pinMode(B2_Pin, INPUT);

  radio.begin();
  radio.openWritingPipe(addresses[1]); //ADDRESS02
  radio.openReadingPipe(1, addresses[0]); //ADRESS01
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
};

void loop() {
  delay(10);
  radio.stopListening();
  delay(10);
  radio.startListening();

  int B2_State = digitalRead(B2_Pin);
  
 if (B2_State == HIGH) {
    radio.write(&txt7, sizeof(txt7));
    Serial.println(txt7);
  } else {
    radio.write(&txt8, sizeof(txt8));
    Serial.println(txt8);
  };
  delay(10);
  
  if (radio.available()) {
    char txt[6] = "";
    radio.read(&txt, sizeof(txt));
    switch (txt[1]) {
      case '1':
        lcd.print("hello, world!");
        delay(3000);
        lcd.clear();
        break;
      default: lcd.clear(); break;
    };
    Serial.println(txt);
  };
};

1 Like

When faced with such a challenge, I would suggest taking an alternate approach to simplify the system but keep basic logic.

That is, rather than complicating the design with the RF modules and libaries, simply remove the RF stuff and concentrate on full-duplex serial comms.
Rx ---> TX and Tx ---> Rx

You can even include software-serial to simulate the RF portion and abstract the physical USART pins.

Once you can exchange messages bidirectionally, comment the software serial code and insert the RF module code.

A problem I foresee ( and I could wrong )is that one has to be in receive mode when the other is transmitting, if they both transmit at the same time the message is lost .

So … you could do after sending a message

… <ACK rec’d>. Change modes to listen < rec msg> < send ACK >change mode

And so on .. have a time out , so after a period a default Tx/Rx arrangement is used.

You can put a message in the ACK to be sent back from the receiver , that you can change .
You could therefore have a master /slave setup such that one defaults to always receive , you could then ask that receiver for information , which could be out in the ACK or could be used to reverse roles .
I’ve only ever sent a message to one NRFL , then got that one to send to another.

You could use 4 NRFL’s , they are cheap …..

Worth studying the examples and the data sheets .
The IRQ which changes when message is received and clears when read might be useful too

You can also look at transmitting and receiving on different frequencies which would stop clashes

1 Like

In a full-duplex system, both parties can communicate with each other simultaneously. An example of a full-duplex device is plain old telephone service; the parties at both ends of a call can speak and be heard by the other party simultaneously. The earphone reproduces the speech of the remote party as the microphone transmits the speech of the local party. There is a two-way communication channel between them, or more strictly speaking, there are two communication channels between them.

In a half-duplex or semiduplex system, both parties can communicate with each other, but not simultaneously; the communication is one direction at a time. An example of a half-duplex device is a walkie-talkie, a two-way radio that has a push-to-talk button. When the local user wants to speak to the remote person, they push this button, which turns on the transmitter and turns off the receiver, preventing them from hearing the remote person while talking. To listen to the remote person, they release the button, which turns on the receiver and turns off the transmitter. (Wikipedia)

As you only have a single communication channel you can only implement half duplex system; and that means you need to provide a protocol for handling the data.

https://www.ibm.com/docs/en/zos/2.3.0?topic=communications-half-duplex-protocols

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