Ошибка записи 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.
Выход монитора:
Моя установка:
РЕДАКТИРОВАТЬ: Хорошо, мне удалось запустить 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
@Mart, 👍1
Обсуждение2 ответа
Прежде чем решать проблему передачи/приема, посмотрите, как и взаимодействует ли 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
В настоящее время я пишу драйвер (ради развлечения) и заметил, что если линия тактовой частоты не находится на правильном логическом уровне простоя, когда вывод CS переходит в низкий уровень, чип выходит из строя и вызывает проблемы при чтении/записи регистров. Это может помочь вам, а может и не помочь, но я думаю, что стоит упомянуть об этом.
Изменить: чип ожидает CPOL 0, поэтому я использовал понижающий резистор на линии тактовой частоты. Поэтому по умолчанию он будет работать на низком уровне холостого хода.
Перепишите свой ответ как реальное решение, если оно таковое. В настоящее время это выглядит скорее как комментарий., @MichaelT
Спасибо, попробую как можно скорее и отпишусь о результате. Вы поместили резистор между выводом sck и землей? (при условии, что этот макет: https://tmrh20.github.io/RF24/), @Mart
Мне не нужно было физически устанавливать резистор, поскольку он есть внутри моего микроконтроллера, но это должно работать нормально. Может быть, 10 тысяч?, @Brandon Braun
- вопрос по трубке nRF24L01
- Использование функции уровня сигнала модуля nRF24L01
- Как автоматически сбросить nrf24l01+ с кодом?
- Не получаем данные от NRF24L01
- Как отправить данные датчика с Arduino через NRF24L01 на Raspberry Pi
- Модуль nRF24L01 с использованием библиотеки Mirf работал, а затем остановился
- Модуль Bluetooth против беспроводного модуля Arduino
- nRF24L01 + потеря пакетов, вызванная считыванием Arduino и связью с датчиками
У вас такая же настройка ресивера? На каком расстоянии приемник от вашего передатчика? У НРФ возникнут некоторые проблемы, если им придется сблизиться друг с другом., @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