nRF24L01 использует отправителя в качестве получателя и наоборот с помощью библиотеки RF24

У меня есть два модуля nRF24L01 (я попробовал 2 с антенной и 2 без антенны), сопряженные с их базовым модулем питания и подключенные к двум разным платам Arduino Mega 2560. Я могу передавать от одного модуля к другому до 32 байт данных и получать подтверждение без каких-либо проблем. Но когда я переключаю их, когда я пытаюсь отправить данные от получателя и получить их от отправителя, у меня ничего нет. Никаких данных не получено, никакого подтверждения не отправлено в качестве ответа.

Как я уже говорил, первая часть этого кода работает хорошо, но когда дело доходит до второй части, которая находится после задержки(1000), наступает тишина...

мой код таков:

Приемник

#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>
#include "printf.h"

// Set pipes
const uint64_t pipe01_ = 0xE8E8F0F0A1LL;
const uint64_t pipe02_ = 0xE8E8F0F0A2LL; 
const uint64_t pipe03_ = 0xA3LL;
const uint64_t pipe04_ = 0xA4LL;
const uint64_t pipe05_ = 0xA5LL;
const uint64_t pipe06_ = 0xA6LL;

RF24 radio(9, 53);

void setup()
{   
    Serial.begin(115200);
    delay(250);
    radio.begin();
    radio.setChannel(0x57);
    radio.setPALevel(RF24_PA_LOW);
    radio.enableAckPayload();
    radio.openReadingPipe(1, pipe01_);
    radio.openWritingPipe(pipe02_);
    radio.enableDynamicPayloads();
    radio.startListening();
}

void loop()
{
    if (radio.available())
    {
        char newMessage[33];
        memset(newMessage, 0, sizeof(byte) * 33);
        while (radio.available())       
        {radio.read(newMessage, 32);}

        Serial.println("newMessage: " + String((const char*)newMessage));
        delay(1000);
        radio.stopListening();

        char response[32] = "1234567890qwertyuiopasdfghjklzxc";
        radio.write(response, 32);
        unsigned long ack = 0;
        if (radio.isAckPayloadAvailable())
        {
            radio.read(&ack, sizeof(ack));
            Serial.println("ack: " + String(ack));
        }
        radio.startListening();
    }
}

Отправитель

#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>
#include "printf.h"
// Set pipes
const uint64_t pipe01_ = 0xE8E8F0F0A1LL;
const uint64_t pipe02_ = 0xA2LL; 
const uint64_t pipe03_ = 0xA3LL;
const uint64_t pipe04_ = 0xA4LL;
const uint64_t pipe05_ = 0xA5LL;
const uint64_t pipe06_ = 0xA6LL;

RF24 radio(9, 53);

void setup()
{   
    Serial.begin(115200);
    delay(250);
    radio.begin();
    radio.setChannel(0x57);
    radio.setPALevel(RF24_PA_LOW);
    radio.enableAckPayload();
    radio.openReadingPipe(2, pipe02_);
    radio.openWritingPipe(pipe01_);
    radio.enableDynamicPayloads();
    radio.stopListening();

    char message[32] = "qwertyuiopasdfghjklzxc1234567890";
    radio.write(message, 32);

    radio.startListening();
}

void loop()
{
    if (radio.available())
    {
        char respMessage[33];
        memset(respMessage, 0, sizeof(byte) * 33);
        while (radio.available())     
        {radio.read(respMessage, 32);}

        Serial.println("respMessage: " + String((const char*)respMessage));
    }
}

Пожалуйста, помогите мне.

, 👍2

Обсуждение

Строка qwertyuiopasdfghjklzxc1234567890 содержит 32 символа плюс неявный нулевой терминатор, для которого в массиве нет пробела. Было бы безопаснее объявить это как `char message [] = "..."'. Здесь вы можете страдать от поврежденной памяти., @Christian Lindig


1 ответ


0

Обновление: Вчера это работало, но сегодня... то же самое, что и с "задержкой()". Что не так с этими радиомодулями??

Я обнаружил, что функция delay() вызывала такое ненормальное поведение.

Поэтому я реализовал периоды вместо задержки (), и теперь я могу переключать режим работы между "приемником" и "передатчиком". Более того, я обнаружил несколько дополнительных условий, которые необходимо выполнить (прочитайте комментарии к коду).

Ниже приведен рабочий пример кода, в котором передатчик отправляет какое-то большое сообщение. Получатель получает его, ждет 2 секунды, затем отвечает другим большим сообщением и получает подтверждение для этого сообщения:

Отправитель

#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>
#include "printf.h"
const uint64_t pipe01_ = 0xE8E8F0F0A1LL; //пишем трубы должен быть полный адрес, если признает, будет использоваться
const uint64_t pipe02_ = 0xE8E8F0F0A2LL; //хотя бы одного из чтения труб должен быть полный адрес
const uint64_t pipe03_ = 0xA3LL;
const uint64_t pipe04_ = 0xA4LL;
const uint64_t pipe05_ = 0xA5LL;
const uint64_t pipe06_ = 0xA6LL;
RF24 radio(9, 53);

void setup()
{   
    Serial.begin(115200);
    delay(250);
    radio.begin();
    radio.setChannel(0x57); //не требуется. Но должны быть равны с обеих сторон
    radio.setPALevel(RF24_PA_LOW); //не требуется. Но должны быть равны с обеих сторон
    radio.enableAckPayload(); //Для возможности изменения полезной нагрузки Ack с помощью writeAckPayload()
    radio.openReadingPipe(2, pipe02_); //По крайней мере один из каналов чтения должен быть полным адресом
    radio.openWritingPipe(pipe01_); //Канал записи должен быть полным адресом, если для подтверждения будет использоваться
    radio.enableDynamicPayloads(); //Если не установлен, размер будет фиксированной длины. Фиксированная длина по умолчанию составляет 32 байта

    /*Необходимо выполнить это, если "startListening()" будет использоваться в любом месте приведенного ниже кода. 
    nRF24L01 запоминает его состояние, даже если Arduino был перезапущен*/
    radio.stopListening();
    Serial.println("Отправка сообщения...");
    char message[32] = "qwertyuiopasdfghjklzxc1234567890"; //какое-то тестовое сообщение
    radio.write(message, 32); //Отправить сообщение по предопределенному "каналу записи".

    Serial.println("Waiting for response...");
    radio.startListening(); //Сбрасывает буфер TX и переключает режим радиомодуля в "приемник".

    uint16_t ack = 123;
    radio.writeAckPayload(2, &ack, sizeof(ack)); //Пользовательская полезная нагрузка ACK должна быть установлена после "startListening()". Потому что "startListening()" сбрасывает буфер TX
}

void loop()
{
    if (radio.available())
    {
        char respMessage[33];
        memset(respMessage, 0, sizeof(byte) * 33);
        while (radio.available())     
        {radio.read(respMessage, 32);}

        Serial.println("respMessage: " + String((const char*)respMessage));
    }
}

Приемник

#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>
#include "printf.h"

#define period_  2000

const uint64_t pipe01_ = 0xE8E8F0F0A1LL; //хотя бы одного из чтения труб должен быть полный адрес
const uint64_t pipe02_ = 0xE8E8F0F0A2LL; //пишем трубы должен быть полный адрес, если признает, будет использоваться
const uint64_t pipe03_ = 0xA3LL;
const uint64_t pipe04_ = 0xA4LL;
const uint64_t pipe05_ = 0xA5LL;
const uint64_t pipe06_ = 0xA6LL;

unsigned long checkPoint = 0;
bool messageReceived = false;
RF24 radio(9, 53);

void setup()
{   
    Serial.begin(115200);
    delay(250);
    radio.begin();
    radio.setChannel(0x57); //не требуется. Но должны быть равны с обеих сторон
    radio.setPALevel(RF24_PA_LOW); //не требуется. Но должны быть равны с обеих сторон
    radio.enableAckPayload(); //Для возможности изменения полезной нагрузки Ack с помощью writeAckPayload()
    radio.openReadingPipe(1, pipe01_); //По крайней мере один из каналов чтения должен быть полным адресом
    radio.openWritingPipe(pipe02_); //Канал записи должен быть полным адресом, если будет использоваться подтверждение
    radio.enableDynamicPayloads(); //Канал записи должен быть полным адресом, если будет использоваться подтверждение
    radio.startListening(); //Если не установлен, размер будет фиксированной длины. Фиксированная длина по умолчанию составляет 32 байта
}

void loop()
{
    if (radio.available())
    {
        char newMessage[33];
        memset(newMessage, 0, sizeof(byte) * 33);
        while (radio.available())       
        {radio.read(newMessage, 32);}

        Serial.println("newMessage: " + String((const char*)newMessage));
        checkPoint = millis(); 
        messageReceived = true;
    }

    unsigned long timePassed = millis() - checkPoint;

    //Когда он получает, контроллер ждет 2 секунды, а затем отправляет ответ только один раз
    if (messageReceived && timePassed > period_)
    {
        messageReceived = false;
        checkPoint = millis();
        Serial.println("отправка ответа...");

        //Это должно быть вызвано перед отправкой чего-либо (кроме подтверждения).
        radio.stopListening(); //Сбрасывает буфер TX и переключает режим радиомодуля на передатчик

        char response[32] = "1234567890qwertyuiopasdfghjklzxc";
        radio.write(response, 32); 

        unsigned long ack = 0;
        if (radio.isAckPayloadAvailable())
        {
            radio.read(&ack, sizeof(ack));
            Serial.println("получено подтверждение: " + String(ack));
        }

        radio.startListening(); //Сбрасывает буфер TX и переключает режим радиомодуля в "приемник".
    }
}
,