1

I am trying to build a bidirectional communication channel, using nRF24L01 and two arduinos. The message is introduced using a button (but) in Morse code, decoded and then sent when another button (but_send) is pressed. Although everything seems to work fine, the message is sent multiple times even though I added delays. I am a beginner in Arduino and I have no idea what else i could do. I even tried deleting the string right after radio.write, but it doesn't seem to work either. If anyone has an idea, please help!

enter image description here

These are the two codes. They are quite similar, but i added them both just in case:

#include <LiquidCrystal.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
struct record
{
  char mesaj[10];
  boolean state = 1;
};

typedef struct record Record;
Record  button_state, button_state1 ;
RF24 radio(9, 10); // CE, CSN(pini nrf01)
const byte addresses [][6] = {"00001", "00002"};  //Setting the two addresses. One for transmitting and one for receiving
String code = "";
int len = 0;
char ch;
int ok;
char new_char;
int i1 = 0;
int i2 = 1;
const int but_send = 8;
const int but = 5;
const int led = 4;
const int del = 3;
String a = "";
unsigned long pres_len = 0, rel_time, pres_time = 0, old_time_len = 0, old_pres = 0, space = 0;
int state = 0;
int unit_delay = 250;
int min_delay = 10;
int buttonState = 0;

char MakeString()
{
  if (pres_len < (unit_delay * 3) && pres_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (pres_len > (unit_delay * 3))
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}

void Morse_decod()
{
  static String morse[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                           "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                           ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "!"
                          };
  int i = 0;
  while (morse[i] != "!")
  {
    if (morse[i] == code)
    {
      Serial.print(char('A' + i));
      a = a + char('A' + i);
      Serial.print(" ");
  }
  if (morse[i] == "!")
  {
    Serial.println("");
    Serial.println("This code is not exist!");
  }

  code = "";
}
void sendText()
{
  // Aici trebuie sa fe codul pentru trimiterea efectiva a msj
  if (ok == 1) {
    Serial.println("Lavinia:" + a);
  }
  ok = 0;

  delay(100);
}
void setup() {
  Serial.begin(9600);
  pinMode(but, INPUT_PULLUP);
  pinMode(but_send, INPUT_PULLUP);
  pinMode(del, INPUT_PULLUP);

  pinMode(led, OUTPUT);
  radio.begin();                           //Starting the radio communication
  radio.openWritingPipe(addresses[0]);     //Setting the address at which we will send the data
  radio.openReadingPipe(1, addresses[1]);  //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MIN); //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.

}
void loop() {

label:
  while (digitalRead(but) == HIGH) {
    delay(5);
    radio.startListening();

    if (radio.available())                     //Looking for incoming data
    {
      radio.read(&button_state, sizeof(button_state));
      if (button_state.state == 0)
      {

        ok = 1;
        sendText();
        String final = "";

        for (int i = 0; i < strlen(button_state.mesaj); i++)
        {
          final += String(button_state.mesaj[i]);
        }
        ok = 1;
        Serial.println("Iulia: " + final);
        button_state.state = 1;
        radio.stopListening(); 
      }
      else
      {
        //nu se intampla nimic daca eu nu am trimis mesaj

      }
      delay(5);

      radio.stopListening();                           //This sets the module as transmitter
      button_state1.state = digitalRead(but_send);
      int n = a.length();
      char char_array[n + 1];
      strcpy(char_array, a.c_str());
      strcpy(button_state1.mesaj, char_array);
      radio.write(&button_state1, sizeof(button_state1));   //Sending the data
    }

    if (digitalRead(del) == LOW && a[0] != '\0' ) {
      Serial.println("Deleted string");
      a = "\0";
      Serial.println(a);
    }


  }
  old_pres = rel_time;
  pres_time = millis();
  digitalWrite(led, HIGH);
  while (digitalRead(but) == LOW) {}
  rel_time = millis();
  digitalWrite(led, LOW);
  pres_len = rel_time - pres_time;
  space = pres_time - old_pres;
  if (pres_len > min_delay)
  {
    code += MakeString();
  }
  while ((millis() - rel_time) < (unit_delay * 3))
  {
    if (digitalRead(but) == LOW)
    {
      goto label;
    }

  }

  Morse_decod();
  delay(1000);

}
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN(pini nrf01)
#include <LiquidCrystal.h>
struct record
{
  char mesaj[10];
  boolean state = 1;
};

typedef struct record Record;
const byte addresses [][6] = {"00001", "00002"};  //Setting the two addresses. One for transmitting and one for receiving
String code = "";
int len = 0;
char ch;
int ok;
int ok2;
char new_char;
int i1 = 0;
int i2 = 1;
const int but_send = 8;
const int but = 5;
const int led = 4;
const int del = 3;
String a = "";
unsigned long pres_len = 0, rel_time, pres_time = 0, old_time_len = 0, old_pres = 0, space = 0;
int state = 0;
int unit_delay = 250;
int min_delay = 10;
Record  button_state, button_state1 ;



char MakeString()
{
  if (pres_len < (unit_delay * 3) && pres_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (pres_len > (unit_delay * 3))
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}

void Morse_decod()
{
  static String morse[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                           "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                           ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "!"
                          };
  int i = 0;
  while (morse[i] != "!")
  {
    if (morse[i] == code)
    {
      Serial.print(char('A' + i));
      a = a + char('A' + i);
      Serial.print(" ");
  }
  if (morse[i] == "!")
  {
    Serial.println("");
    Serial.println("This code is not exist!");
  }

  code = "";
}
void sendText()
{
  // Aici trebuie sa fe codul pentru trimiterea efectiva a msj
  if (ok == 1) {
    Serial.println("Iulia:" + a);
  }
  ok = 0;

  delay(100);
}
void setup() {
  Serial.begin(9600);
  pinMode(but, INPUT_PULLUP);
  pinMode(but_send, INPUT_PULLUP);
  pinMode(del, INPUT_PULLUP);

  pinMode(led, OUTPUT);
  radio.begin();                           //Starting the radio communication
  radio.openWritingPipe(addresses[1]);     //Setting the address at which we will send the data
  radio.openReadingPipe(1, addresses[0]);  //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MIN); //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.

}
void loop() {
label:
  while (digitalRead(but) == HIGH) {
        
    delay(5);
    radio.stopListening();                             //This sets the module as transmitter
    button_state.state = digitalRead(but_send);

    int n = a.length();
    char char_array[n + 1];
    strcpy(char_array, a.c_str());
    strcpy(button_state.mesaj, char_array);
    radio.write(&button_state, sizeof(button_state));  //Sending the data
    delay(5);

    radio.startListening();                            //This sets the module as receiver
    if (radio.available())
    { 
      radio.read(&button_state1, sizeof(button_state1)); //Reading the data    
      String final = "";
      if (button_state1.state == 0)      {
        ok = 1;
        
        sendText();
        for (int i = 0; i < strlen(button_state1.mesaj); i++)
        {
          final += String(button_state1.mesaj[i]);
        }
        Serial.println("Lavinia: " + final);
        button_state1.state = 1;
      }

    }
    
    if (digitalRead(del) == LOW && a[0] != '\0' ) {
      Serial.println("Deleted string");
      a = "\0";
      Serial.println(a);
    }



  }
  old_pres = rel_time;
  pres_time = millis();
  digitalWrite(led, HIGH);
  while (digitalRead(but) == LOW) {}
  rel_time = millis();
  digitalWrite(led, LOW);
  pres_len = rel_time - pres_time;
  space = pres_time - old_pres;
  if (pres_len > min_delay)
  {
    code += MakeString();
  }
  while ((millis() - rel_time) < (unit_delay * 3))
  {

    if (digitalRead(but) == LOW)
    {
      goto label;

    }

  }

  Morse_decod();
  delay(1000);



}

I believe the relevant part would be:

    int n = a.length();
    char char_array[n + 1];
    strcpy(char_array, a.c_str());
    strcpy(button_state.mesaj, char_array);
    radio.write(&button_state, sizeof(button_state));  //Sending the data
    delay(5);

where a is the message to be sent.

2
  • Try creating a new, simple project that sends a number from 1 arduino to the other. If you send it from the setup() function, it should only be sent once. If you get that working, try creating a simple program that sends a "1" when a button is pressed and a "0" if the button is released. When that works, build your morse project from that. It's easier to debug short, simple programs and make one bit work at a time.
    – jkp
    May 18, 2021 at 13:32
  • @jkp Hi there. Thanks for answering this! I have tried doing this, as i started from a simple project which worked. But since i added more functionalities, it seems like something goes wrong somewhere. Do you have any general idea what could be wrong in the code, perhaps the delays? May 18, 2021 at 15:14

1 Answer 1

1

(Too few characters in comments, so writing as answer instead)

It's a bit hard to figure out without having the setup here and I don't think I have any of the radio modules in my box.

What I think is happening is this.

It seems like the first code will not send anything unless it receives a message from the second code, because the radio.write is inside the radio.available if-block. But when it receives a message, the message to send back must be present, so you start by entering a message on Arduino1.

Then you enter a message on Arduino2. You press the button, it skips the while loop below the label. When you release the button, it will enter the while loop and send the message. For both versions, the message will be sent as soon as 'but' is released. but_send is copied to the record that is sent, but the sending does not depend on the state of this button. You need an if statement that checks but_send to do this. The effect is, that you can only send '.' or '-' because the message is sent right away, before you get to enter more dots or dashes.

Anyways, the message from Arduino2 is received by Arduino1. If the state field of the message is 1, the message is written to Serial. Then the message from Arduino1 is send to Arduino2. Since we are not pressing any buttons, the message from Arduino 2 is send again and again and again. The state field will be 0, because but_send is not pressed, but the message is sent anyway. This triggers a new send on Arduino 1, because it receives something from Arduino 2 and gets into the radio.available part.

It seems like the messages will bounce back and forth. The only reason you don't see your Serial console filled with letters is that state is 0 for most of the messages, because you release btn_send. But as long as you hold down btn_send, it will set state=1 and print the message at the receiving end.

To prevent this, you should not call radio.write unless btn_send is released. That is going from LOW to HIGH. To test this, have a variable called old_btn_send and do something like this: Initialize old_btn_send to HIGH in setup()

if (old_btn_send == LOW && digitalRead(btn_send) == HIGH {
    [do the sending thing]
}
old_btn_send = digitalRead(btn_send);

That is, you press btn_send. We will not enter the if block, but old_btn_send will be LOW. When you release, the condition will be true, but only once, because old_btn_send will be HIGH after the if block.

Please note, that what I write is from reading the code and not doing any testing, so I might be completely wrong :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.