NRF24 не всегда подтверждает пакеты

PLYSHKA
Offline
Зарегистрирован: 18.01.2019

Здравствуйте, я студент, разбираюсь в программировании на низко-среднем уровне (небольшой опыт с c#, java) и недавно начал активно заниматься arduino'й.

Проблема:

Программа, которую я написал посылает пакет приёмнику и он должен подтвердить то, что он его принял. Для этого я использую writeAckPayload. Но приёмник после 4 пакета от загрузки ардуины перестаёт передавать подтверждение, при этом принимая пакет. Помогите пожалуйста, не могу понять в чём дело.

Принцип работы таков: смотря в серийный порт ввожу с помощью одной кнопки полное слово до 32 символов (32 байта 1 пакет) и пересылаю, приёмник получает пакет и отправляет его обратно для подтверждения, после этого приёмник выводит сообщение в серийный порт.

Код передатчика:

#include "nRF24L01.h"
#include "RF24.h"

#define button1B 3  // пин кнопки button1

boolean button1S;   // храним состояния кнопок (S - State)
boolean button1F;   // флажки кнопок (F - Flag)
boolean button1R;   // флажки кнопок на отпускание (R - Release)
boolean button1P;   // флажки кнопок на нажатие (P - Press)
boolean button1H;   // флажки кнопок на удержание (многократный вызов) (H - Hold)
boolean button1HO;  // флажки кнопок на удержание (один вызов при нажатии) (HO - Hold Once)
boolean button1D;   // флажки кнопок на двойное нажатие (D - Double)
boolean button1DP;  // флажки кнопок на двойное нажатие и отпускание (D - Double Pressed)

#define double_timer 150   // время (мс), отведённое на второе нажатие
#define hold 500           // время (мс), после которого кнопка считается зажатой
#define debounce 120        // (мс), антидребезг
unsigned long button1_timer; // таймер последнего нажатия кнопки
unsigned long button1_double; // таймер двойного нажатия кнопки


char charsNnums[37] = {' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9'};
int counterCharSelect = 0;
int counterSignedChars = 0;
char typeData[32] = {0};
char checkData[32]= {0};
char lastData[32]= {0};
RF24 radio(9,10); // "создать" модуль на пинах 9 и 10 Для Уно

byte address[][6] = {"1Node","2Node","3Node","4Node","5Node","6Node"};  //возможные номера труб

void setup(){
  pinMode(button1B, INPUT_PULLUP);
  Serial.begin(9600); //открываем порт для связи с ПК
  radio.begin(); //активировать модуль
  radio.setAutoAck(1);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(5,15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах

  radio.openWritingPipe(address[0]);   //мы - труба 0, открываем канал для передачи данных
  radio.setChannel(0x60);  //выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  // при добавлении задержки к приёмнику между чтением пакета и отправки назад возможно использовать пересылку обратно на 250 кбит
  

  radio.powerUp(); //начать работу
  radio.stopListening();  //не слушаем радиоэфир, мы передатчик
}


void loop() { 

//-------опрос кнопок--------
  button1S = !digitalRead(button1B);
  buttons(); //отработка кнопок
//-------опрос кнопок--------

// отработка режимов (опускание флага обязательно!)
  if (button1P) {
    counterCharSelect++;
    if(counterCharSelect > 36){
      counterCharSelect = 0;
    }
    Serial.print ("одиночный ");
    Serial.println (charsNnums[counterCharSelect]);
    button1P = 0;
  }
  if (button1D) {
    if(counterSignedChars > 32){
     memset (typeData,0,sizeof(typeData));
     counterSignedChars = 0;
    }
    typeData[counterSignedChars] = charsNnums[counterCharSelect];
    counterSignedChars++;
    counterCharSelect = 0;
    Serial.print("двойной ");
    Serial.println(typeData);
    button1D = 0;
  }
  if (button1H && button1HO) {
    counterCharSelect = 0;
    counterSignedChars = 0;

    Serial.print("окончательный долгое нажатие ");
    Serial.println(typeData);
    //---------------------------------------ОТПРАВКА СООБЩЕНИЙ-----------------------------------------
    Serial.print("Отправка сообщения | ");
    Serial.print(typeData);
    Serial.println(" |");

    if(radio.write(&typeData, sizeof(typeData))){
      Serial.println("Сообщение доставлено");
    } else {
      Serial.println("Сообщение не доставлено");
    }

    for(int i = 0; i < sizeof(typeData);i++){
      lastData[i] = typeData[i];
    }
    
    for(int i = 0; i < 32; i++){
      typeData[i] = 0;
    }
    radio.flush_tx();
    //---------------------------------------ОТПРАВКА СООБЩЕНИЙ-----------------------------------------
    
    button1HO = 0;
  }
// отработка режимов 
  /*
     if (button1H) {
    Serial.println("hold");
    button1H = 0;
    }
  */
}

//------------------------ОТРАБОТКА КНОПОК-------------------------
void buttons() {
  //-------------------------button1--------------------------
  // нажали (с антидребезгом)
  if (button1S && !button1F && millis() - button1_timer > debounce) {
    button1F = 1;
    button1HO = 1;
    button1_timer = millis();
  }
  // если отпустили до hold, считать отпущенной
  if (!button1S && button1F && !button1R && !button1DP && millis() - button1_timer < hold) {
    button1R = 1;
    button1F = 0;
    button1_double = millis();
  }
  // если отпустили и прошло больше double_timer, считать 1 нажатием
  if (button1R && !button1DP && millis() - button1_double > double_timer) {
    button1R = 0;
    button1P = 1;
  }
  // если отпустили и прошло меньше double_timer и нажата снова, считать что нажата 2 раз
  if (button1F && !button1DP && button1R && millis() - button1_double < double_timer) {
    button1F = 0;
    button1R = 0;
    button1DP = 1;
  }
  // если была нажата 2 раз и отпущена, считать что была нажата 2 раза
  if (button1DP && millis() - button1_timer < hold) {
    button1DP = 0;
    button1D = 1;
    button1_timer = millis();
  }
  // Если удерживается более hold, то считать удержанием
  if (button1F && !button1D && !button1H && millis() - button1_timer > hold) {
    button1H = 1;
  }
  // Если отпущена после hold, то считать, что была удержана
  if (!button1S && button1F && millis() - button1_timer > hold) {
    button1F = 0;
    button1H = 0;
    button1_timer = millis();
  }
  //-------------------------button1--------------------------
}
//------------------------ОТРАБОТКА КНОПОК-------------------------

Код приёмника:

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

RF24 radio(9,10); // "создать" модуль на пинах 9 и 10 Для Уно

unsigned char S[16]= {0};
char has[32]= {0};
char text[32]= {0};
char textAck[32]= {0};

byte address[][6] = {"1Node","2Node","3Node","4Node","5Node","6Node"};  //возможные номера труб
bool butt_flag = 0;
bool butt;

void setup(){
  Serial.begin(9600); //открываем порт для связи с ПК
  radio.begin(); //активировать модуль
  radio.setAutoAck(1);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(5,15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openReadingPipe(1,address[0]);      //хотим слушать трубу 0
  radio.setChannel(0x60);  //выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  
  radio.powerUp(); //начать работу
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
  
}
void loop() {
  if (radio.available()){
    radio.read(&text, sizeof(text));
    delay(50);
    Serial.print("Полученный текст | ");
    Serial.print( text );
    Serial.println(" |");
    Serial.println("Отправка ответа");
    radio.writeAckPayload( 1, &textAck, sizeof(textAck) );
    for(int i = 0; i < 32; i++){
      S[i] = 0;
      has[i] = 0;
      text[i] = 0;
      }
    }
   
  }


 

PLYSHKA
Offline
Зарегистрирован: 18.01.2019

Просьба закрыть тему , решил проблему очисткой буфера с обеих сторон командами

radio.flush_rx();
radio.flush_tx();