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; } } }
Просьба закрыть тему , решил проблему очисткой буфера с обеих сторон командами