Ошибка записи NRF24L01

Мой Arduino Uno с комбинацией NRF24L01 выдает сообщения об ошибках при записи.

Используя базовый пример кода «Начало работы», буквально скопированный из: http://tmrh20.github.io/RF24/GettingStarted_8ino-example.html, мой последовательный монитор постоянно пишет "не удалось" (см. прикреплённый скриншот)

Настройка для моего Arduino uno описана в таблице на http://arduino-info.wikispaces.com/Nrf24L01-2.4GH-HowTo#PP (контакт Arduino для Библиотека ТМРх20 РФ24)

Код:

/*
* Пример эскиза для начала работы с радиостанциями nRF24L01+.
* Это очень простой пример того, как отправлять данные с одного узла на другой.
* Обновлено: декабрь 2014 г., автор TMRh20.
*/
#include <SPI.h>
#include "RF24.h"
#include <printf.h>

/****************** Конфигурация пользователя ****************************/
/*** Установить это радио как радио номер 0 или 1 ***/
bool radioNumber = 1;
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(7,8);
/**********************************************************/
byte addresses[][6] = {"1Node","2Node"};
// Используется для управления отправкой или получением этого узла
bool role = 0;
void setup() {
  Serial.begin(115200);
  printf_begin();
  Serial.println(F("RF24/examples/GettingStarted"));
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

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

  // Открываем канал записи и чтения на каждом радио с противоположными адресами
  if(radioNumber){
    radio.openWritingPipe(addresses[1]);
    radio.openReadingPipe(1,addresses[0]);
  }else{
    radio.openWritingPipe(addresses[0]);
    radio.openReadingPipe(1,addresses[1]);
  }
  radio.printDetails();
  // Запускаем радиоприемник, прослушивающий данные
  radio.startListening();
}
void loop() {


/****************** Ping Out Role ***************************/  
if (role == 1)  {

    radio.stopListening();                                    // Во-первых, перестань слушать, чтобы мы могли поговорить.


    Serial.println(F("Now sending"));
    unsigned long start_time = micros();                             // Найдите время и отправьте его. Это будет заблокировано до завершения
     if (!radio.write( &start_time, sizeof(unsigned long) )){
       Serial.println(F("failed"));
     }

    radio.startListening();                                    // Теперь продолжаем слушать

    unsigned long started_waiting_at = micros();               // Устанавливаем период таймаута, получаем текущие микросекунды
    boolean timeout = false;                                   // Настраиваем переменную, чтобы указать, был ли получен ответ или нет

    while ( ! radio.available() ){                             // Пока ничего не получено
      if (micros() - started_waiting_at > 200000 ){            // Если ожидание превышает 200 мс, укажите таймаут и выйдите из цикла while
          timeout = true;
          break;
      }      
    }

    if ( timeout ){                                             // Описываем результаты
        Serial.println(F("Failed, response timed out."));
    }else{
        unsigned long got_time;                                 // Получаем ответ, сравниваем и отправляем на отладку
        radio.read( &got_time, sizeof(unsigned long) );
        unsigned long end_time = micros();

        // Выплеснуть это
        Serial.print(F("Sent "));
        Serial.print(start_time);
        Serial.print(F(", Got response "));
        Serial.print(got_time);
        Serial.print(F(", Round-trip delay "));
        Serial.print(end_time-start_time);
        Serial.println(F(" microseconds"));
    }
    // Повторите попытку через 1 секунду
    delay(1000);
  }
/****************** Pong Back Role ***************************/
  if ( role == 0 )
  {
    unsigned long got_time;

    if( radio.available()){
                                                                    // Переменная для полученной временной метки
      while (radio.available()) {                                   // Пока данные готовы
        radio.read( &got_time, sizeof(unsigned long) );             // Получаем полезную нагрузку
      }

      radio.stopListening();                                        // Во-первых, перестань слушать, чтобы мы могли поговорить
      radio.write( &got_time, sizeof(unsigned long) );              // Отправляем последний обратно.
      radio.startListening();                                       // Теперь возобновляем прослушивание, чтобы перехватить следующие пакеты.
      Serial.print(F("Sent response "));
      Serial.println(got_time);  
   }
 }
/****************** Change Roles via Serial Commands ***************************/
  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'T' && role == 0 ){      
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      role = 1;                  // Стать основным передатчиком (пинговать)

   }else
    if ( c == 'R' && role == 1 ){
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));      
       role = 0;                // Становимся основным получателем (ответ на понг)
       radio.startListening();

    }
  }
} // Петля

Хотя у другого моего Arduino такие же настройки, только у него radioNumber = 0.

Выход монитора: вывод монитора

Моя установка: Настройка Arduino

РЕДАКТИРОВАТЬ: Хорошо, мне удалось запустить printDetails() (спасибо за помощь) Получилось:

STATUS       = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1     = 0x65646f4e31 0x65646f4e32
RX_ADDR_P2-5     = 0xc3 0xc4 0xc5 0xc6
TX_ADDR      = 0x65646f4e31
RX_PW_P0-6   = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA        = 0x3f
EN_RXADDR    = 0x02
RF_CH        = 0x4c
RF_SETUP     = 0x03
CONFIG       = 0x0e
DYNPD/FEATURE    = 0x00 0x00
Data Rate    = 1MBPS
Model        = nRF24L01+
CRC Length   = 16 bits
PA Power     = PA_LOW

на arduino one и на следующем на arduino 2 с радиономером = 1

STATUS       = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1     = 0x65646f4e32 0x65646f4e31
RX_ADDR_P2-5     = 0xc3 0xc4 0xc5 0xc6
TX_ADDR      = 0x65646f4e32
RX_PW_P0-6   = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA        = 0x3f
EN_RXADDR    = 0x02
RF_CH        = 0x4c
RF_SETUP     = 0x03
CONFIG       = 0x0e
DYNPD/FEATURE    = 0x00 0x00
Data Rate    = 1MBPS
Model        = nRF24L01+
CRC Length   = 16 bits
PA Power     = PA_LOW

, 👍1

Обсуждение

У вас такая же настройка ресивера? На каком расстоянии приемник от вашего передатчика? У НРФ возникнут некоторые проблемы, если им придется сблизиться друг с другом., @Gerben

Та же установка, примерно на расстоянии 2/3 метра. Однако это скорее похоже на проблему передачи, а не приема, потому что это говорит о том, что передача даже не работает, верно?, @Mart

Извините, вы правы. Сообщение о тайм-ауте сбило меня с толку. Похоже, что Arduino не может связаться с NRF. Попробуйте пошевелить все соединения, чтобы убедиться, что они имеют хороший контакт. Попробуйте вызвать функцию [printDetails](https://tmrh20.github.io/RF24/cl assRF24.html#adc95213ed4c8569a90eb33122e16cea6)., @Gerben

хм, с соединением вроде все в порядке... особенно потому, что оба устройства выдают одну и ту же ошибку. (та же установка). У меня небольшая проблема с реализацией printDetails. когда я добавляю строку radio.printDetails(); где-нибудь, я не вижу никакого ответа на своем мониторе?, @Mart

@Mart Сначала вам нужно инициализировать printf, чтобы printDetails работал., @Avamander

Спасибо @Avamander. Я обновил свой первоначальный вопрос выводом printDetails. Я понятия не имею, что может быть не так, @Mart

Глядя на фотографии, я уверен, что эта проблема вызвана слишком слабым источником питания. Попробуйте припаять большой развязывающий конденсатор напрямую к контактам VCC и GND модуля. Если это не улучшит ситуацию, используйте внешний стабилизатор на 3,3 В., @Avamander

Кросс опубликован по адресу: https://github.com/nRF24/RF24/issues/445., @Avamander


2 ответа


0

Прежде чем решать проблему передачи/приема, посмотрите, как и взаимодействует ли Arduino с главным nRF.

Используйте код, указанный ниже, для распечатки радиорегистров tx и rx (не требуются библиотеки, кроме SPI). Вам нужно будет использовать правильные значения для контактов CE и CSN. Опубликуйте данные в своем вопросе, на stack exchange есть много людей, которые смогут помочь вам найти решение.

#include <SPI.h>
#define CE_pin 4
#define CSN_pin 5
#define MOSI_pin 11
#define MISO_pin 12
#define SCK_pin 13
byte data_in;

byte radio1_tx_addr[5] = {0xC5, 0xC5, 0xC5, 0xC5, 0xC5};
byte radio2_tx_addr[5] = {0x31, 0x31, 0x31, 0x31, 0x31};

void setup() {
  Serial.begin(115200);
  pinMode(CE_pin, OUTPUT);//включение чипа установлено как выход
  pinMode(CSN_pin, OUTPUT);//выбор вывода чипа в качестве выхода
  pinMode(MOSI_pin, OUTPUT);//вывод данных SPI
  pinMode(MISO_pin, INPUT); //данные SPI в
  pinMode(SCK_pin, OUTPUT);//SPI тактовый выход
  SPI.setBitOrder(MSBFIRST);//Самый значимый бит SPI первый
  SPI.setDataMode(SPI_MODE0);// Режим 0 Нарастающий фронт данных, поддерживать тактовую частоту на низком уровне
  SPI.setClockDivider(SPI_CLOCK_DIV2);//Запускаем данные на частоте 16 МГц/2 - 8 МГц
  digitalWrite(CE_pin, HIGH);//режим RX
  digitalWrite(CSN_pin, HIGH);//SPI в режиме ожидания
  SPI.begin();//запускаем библиотеку SPI
  delay(100);

  nrf_set_TX_ADDR(radio1_tx_addr); // установить адреса TX/RX
  nrf_set_RX_ADDR_P1(radio2_tx_addr); 

  Serial.print("CONFIG");
  nrf_read_register(0x00);
  Serial.print("EN_AA");
  nrf_read_register(0x01);
  Serial.print("EN_RXADDR");
  nrf_read_register(0x02);
  Serial.print("SETUP_AW");
  nrf_read_register(0x03);
  Serial.print("SETUP_RETR");
  nrf_read_register(0x04);
  Serial.print("RF_CH");
  nrf_read_register(0x05);
  Serial.print("RF_SETUP");
  nrf_read_register(0x06);
  Serial.print("STATUS");
  nrf_read_register(0x07);
  Serial.print("OBSERVE_TX");
  nrf_read_register(0x08);
  Serial.print("RPD");
  nrf_read_register(0x09);
  Serial.print("RX_ADDR_P0");
  nrf_read_register(0x0A);
  Serial.print("RX_ADDR_P1");
  nrf_read_register(0x0B);
  Serial.print("RX_ADDR_P2");
  nrf_read_register(0x0C);
  Serial.print("RX_ADDR_P3");
  nrf_read_register(0x0D);
  Serial.print("RX_ADDR_P4");
  nrf_read_register(0x0E);
  Serial.print("RX_ADDR_P5");
  nrf_read_register(0x0F);
  Serial.print("TX_ADDR");
  nrf_read_register(0x10);
  Serial.print("RX_PW_P0");
  nrf_read_register(0x11);
  Serial.print("RX_PW_P1");
  nrf_read_register(0x12);
  Serial.print("RX_PW_P2");
  nrf_read_register(0x13);
  Serial.print("RX_PW_P3");
  nrf_read_register(0x14);
  Serial.print("RX_PW_P4");
  nrf_read_register(0x15);
  Serial.print("RX_PW_P5");
  nrf_read_register(0x16);
  Serial.print("FIFO_STATUS");
  nrf_read_register(0x17);
  Serial.print("DYNPD");
  nrf_read_register(0x1C);
  Serial.print("FEATURE");
  nrf_read_register(0x1D);  
}

void loop() {
}

void nrf_read_register(byte reg) {
  digitalWrite(CSN_pin, LOW);
  SPI.transfer(reg);
  data_in = SPI.transfer(0x00);
  digitalWrite(CSN_pin, HIGH);
  Serial.print(": 0x");
  Serial.print(reg,HEX);
  Serial.print(" => 0x");
  Serial.println(data_in,HEX);
  delay(10);
}

void nrf_set_TX_ADDR(byte x) {
  digitalWrite(CSN_pin, LOW);
  SPI.transfer(0x30);
  SPI.transfer(x[0]);
  SPI.transfer(x[1]);
  SPI.transfer(x[2]);
  SPI.transfer(x[3]);
  SPI.transfer(x[4]);
  digitalWrite(CSN_pin, HIGH);
  delay(10);
}

void nrf_set_RX_ADDR_P1(byte x) {
  digitalWrite(CSN_pin, LOW);
  SPI.transfer(0x2B);
  SPI.transfer(x[0]);
  SPI.transfer(x[1]);
  SPI.transfer(x[2]);
  SPI.transfer(x[3]);
  SPI.transfer(x[4]);
  digitalWrite(CSN_pin, HIGH);
  delay(10);
}
,

КОНФИГУРАЦИЯ: 0x0 => 0xF EN_AA: 0x1 => 0x3F EN_RXADDR: 0x2 => 0x2 НАСТРОЙКА_AW: 0x3 => 0x3 НАСТРОЙКА_ВОЗВРАТА: 0x4 => 0x5F RF_CH: 0x5 => 0x4C RF_SETUP: 0x6 => 0x3 СТАТУС: 0x7 => 0xE НАБЛЮДАТЬ_TX: 0x8 => 0x0 РПД: 0x9 => 0x0 RX_ADDR_P0: 0xA => 0x31 RX_ADDR_P1: 0xB => 0x32 RX_ADDR_P2: 0xC => 0xC3 RX_ADDR_P3: 0xD => 0xC4 RX_ADDR_P4: 0xE => 0xC5 RX_ADDR_P5: 0xF => 0xC6 TX_ADDR: 0x10 => 0x31 RX_PW_P0: 0x11 => 0x20 RX_PW_P1: 0x12 => 0x20 RX_PW_P2: 0x13 => 0x0 RX_PW_P3: 0x14 => 0x0 RX_PW_P4: 0x15 => 0x0 RX_PW_P5: 0x16 => 0x0 FIFO_STATUS: 0x17 => 0x11 ДИНПД: 0x1C => 0x0 ФУНКЦИЯ: 0x1D => 0x0, @Mart

Вы, по крайней мере, разговариваете с радио. Все настройки по умолчанию, за исключением CONFIG: 0x0 => 0xF (режим PRX, включено, crc=2 включен) SETUP_RETR: 0x4 => 0x5F (до 15 попыток повторной передачи) RF_CH: 0x5 => 0x4C (канал 2476 МГц) RX_PW_P0: 0x11 => 0x20 (полезная нагрузка 32 байта) RX_PW_P1: 0x12 => 0x20 (полезная нагрузка 32 байта). См. раздел 9 спецификации nRF для индекса значений регистров., @MichaelT

Одно из радио должно быть PTX (основной передатчик), данные, которые вы разместили выше, показывают, что радио настроено на PRX (основной приемник). Убедитесь, что приемник и передатчики имеют общие адреса труб и используют одну и ту же радиочастоту. Пожалуйста, поддержите ответ, если он вам полезен., @MichaelT

Хорошо, спасибо! так если я могу говорить с радио, почему запись приведет к сбою? Это неправильные настройки? Я просто достал их из коробки вот так и начал работать с ними, как описано выше, не редактируя настройки., @Mart

Для каждого Arduino, управляющего радио TX/RX, вставьте мой код в свою программу в конце раздела настройки и скопируйте сюда то, что выводится. Есть много вещей, которые могут быть неправильными. Также проверьте, что одно из радио имеет bool radioNumber = 0;, а другое bool radioNumber = 1;, @MichaelT

КОНФИГУРАЦИЯ: 0x0 => 0xF RU_AA: 0x1 => 0x0 EN_RXADDR: 0x2 => 0x2 НАСТРОЙКА_AW: 0x3 => 0x3 НАСТРОЙКА_ВОЗВРАТА: 0x4 => 0x5F RF_CH: 0x5 => 0x4C RF_SETUP: 0x6 => 0x3 СТАТУС: 0x7 => 0xE НАБЛЮДАТЬ_TX: 0x8 => 0x0 РПД: 0x9 => 0x0 RX_ADDR_P0: 0xA => 0x24 RX_ADDR_P1: 0xB => 0x15 RX_ADDR_P2: 0xC => 0xC3 RX_ADDR_P3: 0xD => 0xC4 RX_ADDR_P4: 0xE => 0xC5 RX_ADDR_P5: 0xF => 0xC6 TX_ADDR: 0x10 => 0x24 RX_PW_P0: 0x11 => 0x20 RX_PW_P1: 0x12 => 0x20 RX_PW_P2: 0x13 => 0x0 RX_PW_P3: 0x14 => 0x0 RX_PW_P4: 0x15 => 0x0 RX_PW_P5: 0x16 => 0x0 FIFO_STATUS: 0x17 => 0x11 ДИНПД: 0x1C => 0x0 ФУНКЦИЯ: 0x1D => 0x0, @Mart

радиономер 1 на первом ардуино, 2 на втором, @Mart

Адреса TX и RX не противоположны, они одинаковы на каждой плате Arduino. Посмотрите это, сравнив RX_ADDR_P0 с TX_ADDR: 0x24 на одной плате Arduino, 0x31 на другой. Попробуйте поменять radio.openReadingPipe(1,addresses[0]); на radio.openReadingPipe(1,addresses[1]); и наоборот, @MichaelT

Все хорошо и все такое, но разве библиотека nrf24 от tmrh20 не должна исправить это? Ваше последнее предложение не сработало.. (и голосовать за это я пока не могу), @Mart

Я не знаю об этой библиотеке, но из предоставленной вами информации следует, что проблема была в неправильной установке адресов. Адрес TX радио 1 должен быть равен адресу RX (соответствующего канала данных) для радио 2, и наоборот. Я добавлю в свой ответ код, который позволит вам устанавливать адреса вручную., @MichaelT

Давайте [продолжим это обсуждение в чате](https://chat.stackexchange.com/rooms/79986/discussion-between-mart-and-michaelt)., @Mart


1

В настоящее время я пишу драйвер (ради развлечения) и заметил, что если линия тактовой частоты не находится на правильном логическом уровне простоя, когда вывод CS переходит в низкий уровень, чип выходит из строя и вызывает проблемы при чтении/записи регистров. Это может помочь вам, а может и не помочь, но я думаю, что стоит упомянуть об этом.

Изменить: чип ожидает CPOL 0, поэтому я использовал понижающий резистор на линии тактовой частоты. Поэтому по умолчанию он будет работать на низком уровне холостого хода.

,

Перепишите свой ответ как реальное решение, если оно таковое. В настоящее время это выглядит скорее как комментарий., @MichaelT

Спасибо, попробую как можно скорее и отпишусь о результате. Вы поместили резистор между выводом sck и землей? (при условии, что этот макет: https://tmrh20.github.io/RF24/), @Mart

Мне не нужно было физически устанавливать резистор, поскольку он есть внутри моего микроконтроллера, но это должно работать нормально. Может быть, 10 тысяч?, @Brandon Braun