nRF24L01 криво работает обратная связь с массивом

valerachuk
Offline
Зарегистрирован: 21.01.2019

Тестирую обратную связь в nRF24L01, но в ответ на отправленые данные приходят предидущие отправленные данные, не могу понять в чем дело (

Заренее благодарен всем, кто подскажет в чем дело!

Приемник:

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#define CH_NUM 0x60
#define SIG_POWER RF24_PA_MAX 
#define SIG_SPEED RF24_1MBPS
RF24 radio(9,10);
                                                                      
byte addresses[][6] = {"1Node","2Node"}; 

int data[2];

void setup(){
  Serial.begin(9600);
  radio.begin();
  radio.setAutoAck(1);                    
 radio.enableAckPayload();              
  radio.setRetries(0,15);              
 radio.setPayloadSize(4);
  radio.setChannel(CH_NUM);            
  radio.setPALevel(SIG_POWER);         
  radio.setDataRate(SIG_SPEED); 
  radio.openWritingPipe(addresses[1]);      
  radio.openReadingPipe(1,addresses[0]);   
  radio.startListening();                
  radio.powerUp();
}

void loop(){
  byte pipeNo, gotByte;
  while (radio.available(&pipeNo)){
    radio.read(&data, sizeof(data));
    Serial.print(data[0]); Serial.print("   ");Serial.println(data[1]);Serial.println("\n");
    radio.writeAckPayload(pipeNo,&data, sizeof(data) );
  }
}

Передатчик: 

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#define CH_NUM 0x60
#define SIG_POWER RF24_PA_MAX  
#define SIG_SPEED RF24_1MBPS
RF24 radio(9,10);
                                                                        
byte addresses[][6] = {"1Node","2Node"}; 
 
int data[2];
int data_in[2];
void setup(){
    Serial.begin(9600);
    radio.begin();
    randomSeed(analogRead(A0));
    radio.setAutoAck(1);                   
   radio.enableAckPayload();            
    radio.setRetries(0,15);               
    radio.setPayloadSize(4);
    radio.setChannel(CH_NUM);             
    radio.setPALevel(SIG_POWER);           
    radio.setDataRate(SIG_SPEED);
    radio.openWritingPipe(addresses[1]);       
    radio.openReadingPipe(1,addresses[0]);   
    radio.stopListening();            
    radio.powerUp();
}

void loop(){
  
    data[0] = random(-100, 100);
    data[1] = data[0]*2;
    Serial.print(data[0]); Serial.print("   ");Serial.println(data[1]); //печатаем то, что хотим отправить
    
   
    if(radio.write(&data,sizeof(data))){
      Serial.println("KK"); // печатаем кк, если отправка успешна
      while(radio.available()){
        radio.read(&data_in, sizeof(data_in));
        Serial.print(data_in[0]); Serial.print("   ");Serial.println(data_in[1]); // получаем обратно то, что отправили, но приходит не то, что отправили, а то что отправили в прошлый раз
      }
    }
    else{
      Serial.println("NN");
    }
   
    Serial.println("\n");
   delay(3000);
 
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, так и написано. Вы не успели отправить, тут же читаете. Прочитаете предыдущие. АВы чего ожидали?

Попробуйте отправить, подождать ответа, принять и только потом отправлять новое.

valerachuk
Offline
Зарегистрирован: 21.01.2019

Вставил задержку, не помогло, сначала так 10 секунд и ждет ответа, а уже потом принимает прошлые отправления...

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#define CH_NUM 0x60
#define SIG_POWER RF24_PA_MAX  
#define SIG_SPEED RF24_1MBPS
RF24 radio(9,10);
                                                                        
byte addresses[][6] = {"1Node","2Node"}; 
 
int data[2];
int data_in[2];
void setup(){
    Serial.begin(9600);
    radio.begin();
    randomSeed(analogRead(A0));
    radio.setAutoAck(1);                   
   radio.enableAckPayload();            
    radio.setRetries(0,15);               
    radio.setPayloadSize(4);
    radio.setChannel(CH_NUM);             
    radio.setPALevel(SIG_POWER);           
    radio.setDataRate(SIG_SPEED);
    radio.openWritingPipe(addresses[1]);       
    radio.openReadingPipe(1,addresses[0]);   
    radio.stopListening();            
    radio.powerUp();
}

void loop(){
  
    data[0] = random(-100, 100);
    data[1] = data[0]*2;
    Serial.print(data[0]); Serial.print("   ");Serial.println(data[1]);
    
   
    if(radio.write(&data,sizeof(data))){
      Serial.println("KK");
      uint16_t d_time = millis();
      while(!radio.available()&&(millis()-d_time<=10000));
      while(radio.available()){
        radio.read(&data_in, sizeof(data_in));
        Serial.print(data_in[0]); Serial.print("   ");Serial.println(data_in[1]);
      }
    }
    else{
      Serial.println("NN");
    }
   
    Serial.println("\n");
   delay(3000);
 
}

 

valerachuk
Offline
Зарегистрирован: 21.01.2019

Я просто хотел, что бы данные проверялись, а если не совпадают, то отправляем заново.

radio.write(&data,sizeof(data)) - выдает true если успешно отправило или оно еще и сверяет данные?

Могу ли я быть уверен, что если radio.write(&data,sizeof(data)) выдала true, то на другой стороне у меня правильныые данные, или это просто информация о том что данные были приняты ?

И все равно интересно, почему оно так странно себя ведет...

Amiak
Offline
Зарегистрирован: 03.01.2021

valerachuk пишет:

Я просто хотел, что бы данные проверялись, а если не совпадают, то отправляем заново.

radio.write(&data,sizeof(data)) - выдает true если успешно отправило или оно еще и сверяет данные?

Могу ли я быть уверен, что если radio.write(&data,sizeof(data)) выдала true, то на другой стороне у меня правильныые данные, или это просто информация о том что данные были приняты ?

И все равно интересно, почему оно так странно себя ведет...

 

Получилось разобраться?

У меня аналогичная проблема. Все это из-за того что writeAckPayload не успевает в заданный интервал времени отправить ответ т.к. перед ним есть функция обработки данных. Поэтому в ответ уходят данные из FIFO буфера.

b707
Онлайн
Зарегистрирован: 26.05.2017

"Не успевает"? А по-моему он и не должен. Почитайте описание протокола , ack_payload всегда плсылает данные, подготовленные в предыдущем цикле. Чтобы получить актуальный ответ - просто пошлите запрос дважды с небольшим промежутком

rkit
Offline
Зарегистрирован: 23.11.2016

Или тупо отключить функцию ack и отправлять ответы вручную.

Amiak
Offline
Зарегистрирован: 03.01.2021

b707 пишет:
"Не успевает"? А по-моему он и не должен. Почитайте описание протокола , ack_payload всегда плсылает данные, подготовленные в предыдущем цикле. Чтобы получить актуальный ответ - просто пошлите запрос дважды с небольшим промежутком

 

Не совсем верно. В описании написано одно, а практика показывает что он отправляет каждый раз то что получил.

Но вот что я вчера заметил, если не обрабатывать ответ а сразу его пересылать обратно, передатчик получает именно то что передал, а если на приемнике производить обработку ответа и потом только его отправлять, приемник передает правильные данные, но передатчик получает то что было передано в прошлый раз. Отсюда можно сделать вывод что это не проблема приемника и его ответов, а проблема передатчика который по истечении таймаута ожидания ответа, читает из FIFO то что было прислано прошлый раз.

Вывод: на передатчике перед получением ответа необходимо очищать буфер принятых данных, но пока я не разобрался как, ибо функция эта сделана локальной. и применить ее не получается. (Возможно это сымитирует ситуацию потери пакета ACK, но это я не уверен. не вникал в принцип его получения. и передатчик сам повторно запросит повторение отправки ACK пакета при включенной setAutoAck(1) .)

 

 

rkit пишет:
Или тупо отключить функцию ack и отправлять ответы вручную.

Не совсем понял как это реализовать? Если отключить enableAckPayload() передатчик не будет обрабатывать АСК пакеты от приемника т.к. их не запрашивал. В данном случае ответить передатчику не представляется возможным. Если только не менять в корне код программы для реализации полудуплекса. Что для меня является не приемлимым.

Или я в корне не правильно понял идею, подскажи пожалуйста, что имел в виду?

rkit
Offline
Зарегистрирован: 23.11.2016

Amiak пишет:

передатчик не будет обрабатывать АСК пакеты от приемника т.к. их не запрашивал

Передатчик делает то, на что ты его запрограммировал, гений. Напишешь код обработки - будет обрабатывать.

Amiak
Offline
Зарегистрирован: 03.01.2021

Верно. но в рамках имеющегося инструментария.

Если функционально отключить запрос ответа, и реализовать его же только по другому чем это отличается от изначального функционала?