NRF24 не всегда подтверждает пакеты
- Войдите на сайт для отправки комментариев
Здравствуйте, я студент, разбираюсь в программировании на низко-среднем уровне (небольшой опыт с 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;
}
}
}
Просьба закрыть тему , решил проблему очисткой буфера с обеих сторон командами