Сообщение передается несколько раз от одного arduino к другому с помощью nRF24L01

Я пытаюсь построить двунаправленный канал связи, используя nRF24L01 и два arduino. Сообщение вводится с помощью кнопки (but) в азбуке Морзе, декодируется и затем отправляется при нажатии другой кнопки (but_send). Хотя все вроде бы работает нормально, сообщение отправляется несколько раз, хотя я и добавил задержки. Я новичок в Arduino и понятия не имею, что еще я мог бы сделать. Я даже попытался удалить строку сразу после radio.write, но, похоже, это тоже не сработало. Если у кого-то есть идея, пожалуйста, помогите!

Вот эти два кода. Они довольно похожи, но я добавил их на всякий случай:

#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);



}

Я полагаю, что соответствующая часть будет следующей:

    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);

где а-это сообщение, которое должно быть отправлено.

, 👍1

Обсуждение

Попробуйте создать новый, простой проект, который отправляет число от 1 arduino к другому. Если вы отправляете его из функции setup (), то он должен быть отправлен только один раз. Если это работает, попробуйте создать простую программу, которая отправляет "1", когда кнопка нажата, и "0", если кнопка отпущена. Когда это сработает, постройте свой проект морзе из этого. Проще отлаживать короткие, простые программы и заставлять работать по одному биту за раз., @jkp

@jkp Привет. Спасибо, что ответили на этот вопрос! Я уже пробовал это делать, так как начинал с простого проекта, который сработал. Но с тех пор как я добавил больше функций, мне кажется, что где-то что-то идет не так. Есть ли у вас какое-то общее представление о том, что может быть не так в коде, возможно, о задержках?, @MarryPoppins


1 ответ


1

(Слишком мало символов в комментариях, поэтому пишем вместо ответа)

Это немного сложно понять, не имея настройки здесь, и я не думаю, что у меня есть какие-либо радиомодули в моей коробке.

Я думаю, что происходит вот что.

Похоже, что первый код ничего не отправит, пока не получит сообщение от второго кода, потому что radio.write находится внутри radio.available if-block. Но когда он получает сообщение, сообщение для отправки обратно должно присутствовать, поэтому вы начинаете с ввода сообщения на Arduino1.

Затем вы вводите сообщение на Arduino2. Вы нажимаете кнопку, она пропускает цикл while ниже метки. Когда вы отпустите кнопку, она войдет в цикл while и отправит сообщение. Для обеих версий сообщение будет отправлено, как только "но" будет выпущено. but_send копируется в отправленную запись, но отправка не зависит от состояния этой кнопки. Для этого вам нужен оператор if, который проверяет but_send. В результате вы можете отправить только". "или" -", потому что сообщение отправляется сразу же, прежде чем вы успеете ввести больше точек или тире.

В любом случае, сообщение от Arduino2 принимается Arduino1. Если поле состояния сообщения равно 1, то сообщение записывается в последовательный порт. Затем сообщение от Arduino1 отправляется на Arduino2. Поскольку мы не нажимаем никаких кнопок, сообщение от Arduino 2 отправляется снова, снова и снова. Поле state будет 0, потому что but_send не нажата, но сообщение все равно отправляется. Это запускает новую отправку на Arduino 1, потому что он получает что-то от Arduino 2 и попадает в радио.

Кажется, что сообщения будут отскакивать назад и вперед. Единственная причина, по которой вы не видите, что ваша последовательная консоль заполнена буквами, заключается в том, что состояние равно 0 для большинства сообщений, потому что вы выпускаете btn_send. Но пока вы удерживаете btn_send, он установит state=1 и напечатает сообщение на приемном конце.

Чтобы предотвратить это, вы не должны вызывать radio.write, пока не будет выпущен btn_send. Это движение от НИЗКОГО УРОВНЯ к ВЫСОКОМУ. Чтобы проверить это, есть переменная old_btn_send и сделать что-то вроде этого: Инициализировать old_btn_send в HIGH in setup()

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

То есть вы нажимаете btn_send. Мы не войдем в блок if, но old_btn_send будет НИЗКИМ. Когда вы отпустите его, условие будет истинным, но только один раз, потому что old_btn_send будет ВЫСОКИМ после блока if.

Пожалуйста, обратите внимание, что то, что я пишу, происходит от чтения кода и не делает никакого тестирования, так что я могу быть совершенно неправ :)

,