ESP32: nRF24L01 не получает данных

Использование двух nRF24L01 и двух ESP32 DEVKIT V1. Попытка установки библиотеки RF24. Пример «Начало работы». Однако возможность передачи на обоих узлах не позволяет получить полезную нагрузку при переключении на прием во время передачи на обоих узлах.

Используемые контакты SPI:
MOSI = GPIO23,
МИСО = GPIO19,
SCK = GPIO18,
CE = GPIO21,
ДНС = GPIO5,
IRQ = Нет соединения,
Vcc = 5,0 В при использовании дополнительного адаптера со стабилизатором 3,3 В,
GND = Земля.

Правильно ли используются контакты SPI для ESP32 DEVKIT V1?

<script src="https://gist.github.com/Tech500/b57d4d356baaec48adc41196117c02aa.js"></script>
nRF24L01 Project for use with ESP32 DEVKIT V1
Details.txt
//Пример для начала работы: сведения о Radio_0 и Radio_1.

RF24/examples/GettingStarted
Which radio is this? Enter '0' or '1'. Defaults to '0'
radioNumber = 0
*** PRESS 'T' to begin transmitting to the other node
SPI Frequency       = 10 Mhz
Channel         = 76 (~ 2476 MHz)
Model           = nRF24L01+
RF Data Rate        = 1 MBPS
RF Power Amplifier  = PA_LOW
RF Low Noise Amplifier  = Enabled
CRC Length      = 16 bits
Address Length      = 5 bytes
Static Payload Length   = 4 bytes
Auto Retry Delay    = 1500 microseconds
Auto Retry Attempts = 15 maximum
Packets lost on
    current channel = 0
Retry attempts made for
    last transmission   = 0
Multicast       = Disabled
Custom ACK Payload  = Disabled
Dynamic Payloads    = Disabled
Auto Acknowledgment = Disabled
Primary Mode        = TX
TX address      = 0x65646f4e31
pipe 0 ( open ) bound   = 0x65646f4e31
pipe 1 ( open ) bound   = 0x65646f4e32
pipe 2 (closed) bound   = 0xc3
pipe 3 (closed) bound   = 0xc4
pipe 4 (closed) bound   = 0xc5
pipe 5 (closed) bound   = 0xc6

-------------------------------------

radioNumber = 1
*** PRESS 'T' to begin transmitting to the other node
SPI Frequency       = 10 Mhz
Channel         = 76 (~ 2476 MHz)
Model           = nRF24L01+
RF Data Rate        = 1 MBPS
RF Power Amplifier  = PA_LOW
RF Low Noise Amplifier  = Enabled
CRC Length      = 16 bits
Address Length      = 5 bytes
Static Payload Length   = 4 bytes
Auto Retry Delay    = 1500 microseconds
Auto Retry Attempts = 15 maximum
Packets lost on
    current channel = 0
Retry attempts made for
    last transmission   = 0
Multicast       = Disabled
Custom ACK Payload  = Disabled
Dynamic Payloads    = Disabled
Auto Acknowledgment = Disabled
Primary Mode        = RX
TX address      = 0x65646f4e32
pipe 0 (closed) bound   = 0x65646f4e32
pipe 1 ( open ) bound   = 0x65646f4e31
pipe 2 (closed) bound   = 0xc3
pipe 3 (closed) bound   = 0xc4
pipe 4 (closed) bound   = 0xc5
pipe 5 (closed) bound   = 0xc6
Radio_0.ino

Пример библиотеки RF24 «Начало работы»:

/*
* См. документацию по адресу https://nRF24.github.io/RF24.
* См. информацию о лицензии в корневом каталоге этой библиотеки.
* Автор: Брендан Доэрти (2bndy5)
*/

/**
 * A simple example of sending data from 1 nRF24L01 transceiver to another.
 *
 * This example was written to be used on 2 devices acting as "nodes".
 * Use the Serial Monitor to change each node's behavior.
 * 
 *  TX Code --Radio 0
 */

/*                
  Coded for a ESP32 DEVKIT V1 board type to make use of a pair of 
  nRF24L01+ 2.4 GHz. Transceivers
  SPI Pins used MOSI = 23, CE = 21, MSIO = 19, SCK = 18, CSN = 4
  This code is for Radio 0.
  William Lucid
*/

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

#define CE_PIN 21
#define CSN_PIN 5

// создаем экземпляр объекта для трансивера nRF24L01
RF24 radio(CE_PIN, CSN_PIN);

// Пусть эти адреса будут использоваться для пары
uint8_t address[][6] = { "1Node", "2Node" };
// Очень полезно думать об адресе как о пути, а не как о
// место назначения идентифицирующего устройства

// чтобы использовать разные адреса на паре радиостанций, нам нужна переменная для
// однозначно определить, какой адрес это радио будет использовать для передачи
bool radioNumber = 0;  // 0 использует адрес[0] для передачи, 1 использует адрес[1] для передачи

// Используется для управления отправкой или получением этого узла
bool role = true;  // true = роль TX, false = роль RX

// В этом примере мы будем использовать полезную нагрузку, содержащую
// одно число с плавающей запятой, которое будет увеличиваться
// при каждой успешной передаче
float payload = 0.0;

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    // некоторым платам нужно подождать, чтобы обеспечить доступ к последовательному порту через USB
  }

  pinMode(CE_PIN, OUTPUT);
  pinMode(CSN_PIN, OUTPUT);

  // инициализируем трансивер на шине SPI
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {}  // удержание в бесконечном цикле
  }

  //radio.setAutoAck(false);

  // распечатываем вводную подсказку примера
  Serial.println(F("RF24/examples/GettingStarted"));

  // Чтобы установить радиономер через последовательный монитор при запуске
  Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
  while (!Serial.available()) {
    // ждем ввода пользователя
  }
  char input = Serial.parseInt();
  radioNumber = input == 1;
  Serial.print(F("radioNumber = "));
  Serial.println((int)radioNumber);

  // переменная роли жестко запрограммирована в поведении RX, сообщите об этом пользователю
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

  // Установите низкий уровень PA, чтобы попытаться предотвратить проблемы, связанные с питанием
  // потому что эти примеры, скорее всего, выполняются с узлами, расположенными в непосредственной близости от
  // друг друга.
  radio.setPALevel(RF24_PA_LOW);  // RF24_PA_MAX используется по умолчанию.

  // экономим время передачи, настроив радио на передачу только
  // количество байтов, которое нам нужно для передачи числа с плавающей запятой
  radio.setPayloadSize(sizeof(payload));  // тип данных с плавающей запятой занимает 4 байта

  // устанавливаем адрес TX узла RX в канал TX
  radio.openWritingPipe(address[radioNumber]);  // всегда использует канал 0

  // устанавливаем адрес RX узла TX в канал RX
  radio.openReadingPipe(1, address[!radioNumber]);  // используем канал 1

  // дополнительная настройка, специфичная для роли узла
  if (role) {
    radio.stopListening();  // переводим радио в режим TX
  } else {
    radio.startListening();  // переводим радио в режим приема
  }

  // Для отладочной информации
  printf_begin();  // требуется только один раз для печати деталей
  // radio.printDetails(); // (меньшая) функция, которая печатает необработанные значения регистров
  radio.printPrettyDetails();  // (большая) функция, которая печатает удобочитаемые данные

}  // настраивать

void loop() {
  if (role) {
    // Это устройство является узлом TX

    unsigned long start_timer = micros();               // запускаем таймер
    bool report = radio.write(&payload, sizeof(float)); // передаем & сохранить отчет
    unsigned long end_timer = micros();                 // завершаем таймер

    if (report) {
      Serial.print(F("Transmission successful! "));  // полезная нагрузка была доставлена
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);  // распечатываем результат таймера
      Serial.print(F(" us. Sent: "));
      Serial.println(payload);  // распечатываем отправленные полезные данные
      payload += 0.01;          // увеличиваем полезную нагрузку с плавающей запятой
    } else {
      Serial.println(F("Transmission failed or timed out"));  // полезная нагрузка не была доставлена
    }

    // чтобы сделать этот пример доступным для чтения на последовательном мониторе
    delay(1000);  // замедляем передачу на 1 секунду

  } else {
    // Это устройство является узлом RX

    uint8_t pipe;
    if (radio.available(&pipe)) {              // есть ли полезная нагрузка? получить номер трубы, которая его получила
      uint8_t bytes = radio.getPayloadSize();  // получаем размер полезной нагрузки
      radio.read(&payload, bytes);             // извлекаем полезную нагрузку из FIFO
      Serial.print(F("Received "));
      Serial.print(bytes);  // распечатываем размер полезной нагрузки
      Serial.print(F(" bytes on pipe "));
      Serial.print(pipe);  // печатаем номер трубы
      Serial.print(F(": "));
      Serial.println(payload);  // распечатываем значение полезной нагрузки
    }
  }  // роль

  if (Serial.available()) {
    // меняем роль через последовательный монитор

    char c = toupper(Serial.read());
    if (c == 'T' && !role) {
      // Становимся узлом TX

      role = true;
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      radio.stopListening();

    } else if (c == 'R' && role) {
      // Становимся узлом RX

      role = false;
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
      radio.startListening();
    }
  }

}  // петля

Radio_1.ino:

/*
* См. документацию по адресу https://nRF24.github.io/RF24.
* См. информацию о лицензии в корневом каталоге этой библиотеки.
* Автор: Брендан Доэрти (2bndy5)
*/

/**
* Простой пример отправки данных с 1 трансивера nRF24L01 на другой.
*
* Этот пример был написан для использования на двух устройствах, выступающих в качестве «узлов».
* Используйте последовательный монитор, чтобы изменить поведение каждого узла.
*/

/*
Кодирован для типа платы ESP32 DEVKIT V1 для использования пары
nRF24L01+ 2,4 ГГц. Трансиверы
Используемые контакты SPI MOSI = 23, CE = 21, MSIO = 19, SCK = 18, CSN = 4
Этот код предназначен для Радио 1.
  
*/

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

#define CE_PIN  21
#define CSN_PIN  5

// создаем экземпляр объекта для трансивера nRF24L01
RF24 radio(CE_PIN, CSN_PIN);

// Пусть эти адреса будут использоваться для пары
uint8_t address[][6] = { "1Node", "2Node" };
// Очень полезно думать об адресе как о пути, а не как о
// место назначения идентифицирующего устройства

// чтобы использовать разные адреса на паре радиостанций, нам нужна переменная для
// однозначно определить, какой адрес это радио будет использовать для передачи
bool radioNumber = 1;  // 0 использует адрес[0] для передачи, 1 использует адрес[1] для передачи

// Используется для управления отправкой или получением этого узла
bool role = false;  // true = роль TX, false = роль RX

// В этом примере мы будем использовать полезную нагрузку, содержащую
// одно число с плавающей запятой, которое будет увеличиваться
// при каждой успешной передаче
float payload = 0.0;

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    // некоторым платам нужно подождать, чтобы обеспечить доступ к последовательному порту через USB
  }

  pinMode(CE_PIN, OUTPUT);
  pinMode(CSN_PIN, OUTPUT);

  // инициализируем трансивер на шине SPI
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {}  // удержание в бесконечном цикле
  }

  radio.setAutoAck(false);

  // распечатываем вводную подсказку примера
  Serial.println(F("RF24/examples/GettingStarted"));

  // Чтобы установить радиономер через последовательный монитор при запуске
  Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
  while (!Serial.available()) {
    // ждем ввода пользователя
  }
  char input = Serial.parseInt();
  radioNumber = input == 1;
  Serial.print(F("radioNumber = "));
  Serial.println((int)radioNumber);

  // переменная роли жестко запрограммирована в поведении RX, сообщите об этом пользователю
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

  // Установите низкий уровень PA, чтобы попытаться предотвратить проблемы, связанные с питанием
  // потому что эти примеры, скорее всего, выполняются с узлами, расположенными в непосредственной близости от
  // друг друга.
  radio.setPALevel(RF24_PA_LOW);  // RF24_PA_MAX используется по умолчанию.

  // экономим время передачи, настроив радио на передачу только
  // количество байтов, которое нам нужно для передачи числа с плавающей запятой
  radio.setPayloadSize(sizeof(payload));  // тип данных с плавающей запятой занимает 4 байта

  // устанавливаем адрес TX узла RX в канал TX
  radio.openWritingPipe(address[radioNumber]);  // всегда использует канал 0

  // устанавливаем адрес RX узла TX в канал RX
  radio.openReadingPipe(1, address[!radioNumber]);  // используем канал 1

  // дополнительная настройка, специфичная для роли узла
  if (role) {
    radio.stopListening();  // переводим радио в режим TX
  } else {
    radio.startListening();  // переводим радио в режим приема
  }

  // Для отладочной информации
  printf_begin();             // требуется только один раз для печати деталей
  // radio.printDetails(); // (меньшая) функция, которая печатает необработанные значения регистров
  radio.printPrettyDetails(); // (большая) функция, которая печатает удобочитаемые данные

}  // настраивать

void loop() {

  if (role) {
    // Это устройство является узлом TX

    unsigned long start_timer = micros();                // запускаем таймер
    bool report = radio.write(&payload, sizeof(float));  // передаем & сохранить отчет
    unsigned long end_timer = micros();                  // завершаем таймер

    if (report) {
      Serial.print(F("Transmission successful! "));  // полезная нагрузка была доставлена
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);  // распечатываем результат таймера
      Serial.print(F(" us. Sent: "));
      Serial.println(payload);  // распечатываем отправленные полезные данные
      payload += 0.01;          // увеличиваем полезную нагрузку с плавающей запятой
    } else {
      Serial.println(F("Transmission failed or timed out"));  // полезная нагрузка не была доставлена
    }

    // чтобы сделать этот пример доступным для чтения на последовательном мониторе
    delay(1000);  // замедляем передачу на 1 секунду

  } else {
    // Это устройство является узлом RX

    uint8_t pipe;
    if (radio.available(&pipe)) {              // есть ли полезная нагрузка? получить номер трубы, которая его получила
      uint8_t bytes = radio.getPayloadSize();  // получаем размер полезной нагрузки
      radio.read(&payload, bytes);             // извлекаем полезную нагрузку из FIFO
      Serial.print(F("Received "));
      Serial.print(bytes);  // распечатываем размер полезной нагрузки
      Serial.print(F(" bytes on pipe "));
      Serial.print(pipe);  // печатаем номер трубы
      Serial.print(F(": "));
      Serial.println(payload);  // распечатываем значение полезной нагрузки
    }
  }  // роль

  if (Serial.available()) {
    // меняем роль через последовательный монитор

    char c = toupper(Serial.read());
    if (c == 'T' && !role) {
      // Становимся узлом TX

      role = true;
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      radio.stopListening();

    } else if (c == 'R' && role) {
      // Становимся узлом RX

      role = false;
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
      radio.startListening();
    }
  }

}  // петля

Видео, подтверждающее передачу; оба радио

, 👍2


1 ответ


1

Выводы SPI подходят для ESP32 DEVKIT V1; У меня сейчас он и передает, и принимает.

Я заменил всю проводку Dupont длиной более 10 см, изменил канал с помощью функции radio.setChannel на 125 как на передатчике, так и на приемнике, а также добавил электролитический конденсатор 100 мкФ, 16 В между Шина 5 В и земля.

Transmission successful! Time to transmit = 403 us. Sent: 5.96
Transmission successful! Time to transmit = 403 us. Sent: 5.97
Transmission successful! Time to transmit = 403 us. Sent: 5.98
Transmission successful! Time to transmit = 403 us. Sent: 5.99
Transmission successful! Time to transmit = 403 us. Sent: 6.00
Transmission successful! Time to transmit = 403 us. Sent: 6.01
Transmission successful! Time to transmit = 403 us. Sent: 6.02
Transmission successful! Time to transmit = 403 us. Sent: 6.03
Transmission successful! Time to transmit = 403 us. Sent: 6.04

Received 4 bytes on pipe 1: 6.25
Received 4 bytes on pipe 1: 6.26
Received 4 bytes on pipe 1: 6.27
Received 4 bytes on pipe 1: 6.28
Received 4 bytes on pipe 1: 6.29
Received 4 bytes on pipe 1: 6.30

Списки кодов для nRF24L01, радиопередачи и приема

,