Radio.write() всегда возвращает false

Почему radio.write() всегда возвращает false даже если сообщение дошло до приемника?
Как сделать так, чтобы возвращало true,если сообщение дошло?

Настройки модуля:

  radio.setAutoAck(1);        
  radio.setRetries(0, 15);    
  radio.enableAckPayload();  
  radio.setPayloadSize(32);   
  radio.openWritingPipe(address[0]);   
  radio.setChannel(CH_NUM);           
  radio.setPALevel(SIG_POWER);        
  radio.setDataRate(SIG_SPEED);       


  radio.powerUp();
  radio.stopListening();

Поставьте себя на место отвечающего.

Какой нахер radio.write()? Библиотек для радио-модулей овер8к и в каждой из них есть метод write! В каждой!

Без

  1. ссылки на используемую библиотеку;
  2. ссылки на используемый радио-модуль;
  3. полного кода-примера (который можно просто запустить, ничего не дописывая).

Ваш вопрос ничем не отличается от вот этого. И ответы будут такими же.

2 лайка

Почему бы ВАМ САМОМУ не посмотреть в исходнике библиотеки, что именно и при каких условиях возвращает метод write() ?
Мы бы вам помогли и подсказали, но не знаем о какой библиотеке идет речь.

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

Ой, чёт забыл написать.
Модуль: nrf24l01
Библиотека: RF24 by TMRh20

Щас попробую исходник библиотеки посмотреть

#if defined(FAILURE_HANDLING) || defined(RF24_LINUX)

void RF24::errNotify()
{
    #if defined(SERIAL_DEBUG) || defined(RF24_LINUX)
    printf_P(PSTR("RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.\r\n"));
    #endif
    #if defined(FAILURE_HANDLING)
    failureDetected = 1;
    #else
    delay(5000);
    #endif
}

#endif
/******************************************************************/

//Similar to the previous write, clears the interrupt flags
bool RF24::write(const void* buf, uint8_t len, const bool multicast)
{
    //Start Writing
    startFastWrite(buf, len, multicast);

//Wait until complete or failed
#if defined(FAILURE_HANDLING) || defined(RF24_LINUX)
    uint32_t timer = millis();
#endif // defined(FAILURE_HANDLING) || defined(RF24_LINUX)

    while (!(get_status() & (_BV(TX_DS) | _BV(MAX_RT)))) {
#if defined(FAILURE_HANDLING) || defined(RF24_LINUX)
        if (millis() - timer > 95) {
            errNotify();
    #if defined(FAILURE_HANDLING)
            return 0;
    #else
            delay(100);
    #endif
        }
#endif
    }

    ce(LOW);

    write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));

    //Max retries exceeded
    if (status & _BV(MAX_RT)) {
        flush_tx(); // Only going to be 1 packet in the FIFO at a time using this method, so just flush
        return 0;
    }
    //TX OK 1 or 0
    return 1;
}

Если возвращается 0, то значит выполняется это условие if (millis() - timer > 95), значит вызывается и errNotify(), которая говорит что пины неправильно подключены, но у меня сообщения передаются на передатчике и принимаются на приемнике. В чем проблема может быть?

не только. В строке 49 тоже возвращается ноль

Вас не смутила вот эта надпись?

Если бы Вы, читали, что Вам пишут и делали, что говорят

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

Скорее всего Вы пихаете за раз больше одного пакета данных. Размер пакета там в библиотеке устанавливается. А может, и нет - без кода - сами и гадайте.

if (radio.write(&transmit_data, sizeof(transmit_data)))  Serial.println("1");
else Serial.println("0");

transmit_data - int массив с 4 элементами(int transmit_data[4]).
В нем хранятся 1234, 4321, 1, 0

Ну, я же Вам сказал, разбирайтесь сами. Без ссылки на библиотеку и работающего кода-примера я гадать на гуще не буду. Если Вам это настолько не нужно, что лень дать ссылку и сделать пример, то мне-то уж и подавно, сами понимаете.

1 лайк

Попробовал, попробовал, но никак не получается. Заметил только то, что radio.write() возвращает true один раз только при запуске ардуинки.

Скетчи:
Приемник:

/*



//--------------------- НАСТРОЙКИ ----------------------
#define CH_NUM 0x60   // номер канала (должен совпадать с передатчиком)
//--------------------- НАСТРОЙКИ ----------------------

//--------------------- ДЛЯ РАЗРАБОТЧИКОВ -----------------------
// УРОВЕНЬ МОЩНОСТИ ПЕРЕДАТЧИКА
// На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
#define SIG_POWER RF24_PA_MIN

// СКОРОСТЬ ОБМЕНА
// На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
// должна быть одинакова на приёмнике и передатчике!
// при самой низкой скорости имеем самую высокую чувствительность и дальность!!
// ВНИМАНИЕ!!! enableAckPayload НЕ РАБОТАЕТ НА СКОРОСТИ 250 kbps!
#define SIG_SPEED RF24_1MBPS
//--------------------- ДЛЯ РАЗРАБОТЧИКОВ -----------------------

//--------------------- БИБЛИОТЕКИ ----------------------
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(10, 9);   // "создать" модуль на пинах 9 и 10 для НАНО/УНО
//RF24 radio(9, 53); // для МЕГИ
//--------------------- БИБЛИОТЕКИ ----------------------

//--------------------- ПЕРЕМЕННЫЕ ----------------------
byte pipeNo;
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; // возможные номера труб

int recieved_data[2];   // массив принятых данных
int telemetry[2];       // массив данных телеметрии (то что шлём на передатчик)
//--------------------- ПЕРЕМЕННЫЕ ----------------------

void setup() {
  Serial.begin(9600);
  radioSetup();
}

void loop() {
  while (radio.available(&pipeNo)) {                    // слушаем эфир
    radio.read(&recieved_data, sizeof(recieved_data));  // чиатем входящий сигнал

    // формируем пакет данных телеметрии (напряжение АКБ, скорость, температура...)
    telemetry[0] = millis();
    telemetry[1] = 20;
    Serial.println(recieved_data[0]);
    // отправляем пакет телеметрии
    radio.writeAckPayload(pipeNo, &telemetry, sizeof(telemetry));
  }
}

void radioSetup() {             // настройка радио
  radio.begin();                // активировать модуль
  radio.setAutoAck(1);          // режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);      // (время между попыткой достучаться, число попыток)
  radio.enableAckPayload();     // разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     // размер пакета, байт
  radio.openReadingPipe(1, address[0]); // хотим слушать трубу 0
  radio.setChannel(CH_NUM);     // выбираем канал (в котором нет шумов!)
  radio.setPALevel(SIG_POWER);  // уровень мощности передатчика
  radio.setDataRate(SIG_SPEED); // скорость обмена
  // должна быть одинакова на приёмнике и передатчике!
  // при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();         // начать работу
  radio.startListening();  // начинаем слушать эфир, мы приёмный модуль
}

Передатчик:

#define CH_NUM 0x60   // номер канала (должен совпадать с приёмником)
//--------------------- НАСТРОЙКИ ----------------------

//--------------------- ДЛЯ РАЗРАБОТЧИКОВ -----------------------
// УРОВЕНЬ МОЩНОСТИ ПЕРЕДАТЧИКА
// На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
#define SIG_POWER RF24_PA_LOW

// СКОРОСТЬ ОБМЕНА
// На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
// должна быть одинакова на приёмнике и передатчике!
// при самой низкой скорости имеем самую высокую чувствительность и дальность!!
// ВНИМАНИЕ!!! enableAckPayload НЕ РАБОТАЕТ НА СКОРОСТИ 250 kbps!
#define SIG_SPEED RF24_1MBPS
//--------------------- ДЛЯ РАЗРАБОТЧИКОВ -----------------------

//--------------------- БИБЛИОТЕКИ ----------------------
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(10, 9); // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9, 53); // для Меги
//--------------------- БИБЛИОТЕКИ ----------------------

//--------------------- ПЕРЕМЕННЫЕ ----------------------
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; // возможные номера труб

int transmit_data[2];     // массив пересылаемых данных
int telemetry[2];         // массив принятых от приёмника данных телеметрии
byte rssi;
int trnsmtd_pack = 1, failed_pack;
unsigned long RSSI_timer;
//--------------------- ПЕРЕМЕННЫЕ ----------------------

void setup() {
  Serial.begin(9600); // открываем порт для связи с ПК
  radioSetup();
}

void loop() {
  // забиваем transmit_data данными, для примера
  transmit_data[0] = map(analogRead(A7), 0, 1023, 0, 30);
  //transmit_data[0] = 20;
  
  //Serial.println("----------");
  // отправка пакета transmit_data
  if (radio.write(&transmit_data, sizeof(transmit_data))) {
    trnsmtd_pack++;
    Serial.println('1');
    if (!radio.available()) {   // если получаем пустой ответ
    } else {
      Serial.println('2');
      while (radio.available() ) {                    // если в ответе что-то есть
        Serial.println('3');
        radio.read(&telemetry, sizeof(telemetry));    // читаем
        Serial.println(telemetry[0]);
        Serial.println(telemetry[1]);
        Serial.println("----------");
        // получили забитый данными массив telemetry ответа от приёмника
      }
    }
  } else {
    failed_pack++;
    //Serial.println('4');
  }

  if (millis() - RSSI_timer > 1000) {    // таймер RSSI
    // расчёт качества связи (0 - 100%) на основе числа ошибок и числа успешных передач
    rssi = (1 - ((float)failed_pack / trnsmtd_pack)) * 100;

    // сбросить значения
    failed_pack = 0;
    trnsmtd_pack = 0;
    RSSI_timer = millis();
  }
}

void radioSetup() {
  radio.begin();              // активировать модуль
  radio.setAutoAck(1);        // режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    // (время между попыткой достучаться, число попыток)
  radio.enableAckPayload();   // разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);   // размер пакета, в байтах
  radio.openWritingPipe(address[0]);   // мы - труба 0, открываем канал для передачи данных
  radio.setChannel(CH_NUM);            // выбираем канал (в котором нет шумов!)
  radio.setPALevel(SIG_POWER);         // уровень мощности передатчика
  radio.setDataRate(SIG_SPEED);        // скорость обмена
  // должна быть одинакова на приёмнике и передатчике!
  // при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();         // начать работу
  radio.stopListening();   // не слушаем радиоэфир, мы передатчик
}

Ссылку на библиотеку не могу найти, но я ее скачивал в менеджере библиотек. RF24 by TMRh20 1.4.7
Похоже вот эта ссылка:
https://github.com/nRF24/RF24

Что значит “похоже”?
Если байт в байт совпадает, то она, если нет - то нет.
Или эти все проверки тоже кто-то за Вас должен делать?
Ну Вы уж, прежде чем писать на форум, сделайте по максимум то, что можете.

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

Ну, если Вы таки проверите “эта или не эта” путём простого сравнения и подтвердите, что эта (или другую дадите), то я сегодня вечером посмотрю Ваш скетч.

Правильно ли я понимаю, что проблема с возвратом в передатчике? Просто запустить код передатчика, что Вы дали, и посмотреть что там возвращается? Или проще - с каким именно write проблема? В какой строке кода?

Не додумался до этого.
Щас проверил, всё совпадает

Да, ссылка правильная.

Да

В скетче передатчика если одновременно перезапустить приемник и передатчик, то только один раз radio.write возвращает true(47 строчка). Это я узнал с помощью строчки (49) Serial.println('1');. Сами данные приходят на приемник нормально, но все равно radio.write не возвращает true

Какой “один”? Первый? Случайный? Давайте толком.

Не понял Вас.

radio.write из 47 строчки возвращает true один раз при перезагрузке приемника и передатчика одновременно, а потом не возвращает true, хотя данные доходят до приемника

Так, посмотрел я Ваши коды, могу сказать, что всё очень печально. Вы взяли примеры, переделали их без понимания что там и как :frowning: Ошибок очень много. Я начал было править, но … там “систему менять надо”

Ну, вот, например, в том, что Вы называете передатчик, Вы вызываете read (строка №55), а reading pipe Вы точно не забыли открыть? И подобных ошибок очень много.

По поводу Вашего сомнения в нормальной работе read и в возвращаемом значении. Возьмите пример к библиотеке GettingStarted - там проверяют, что вернул write и всё работает правильно. Значит, проблема не в библиотеке, а в Вашем коде. Например, обратите внимание, как они вычитывают payload - полностью! Спрашивают сколько байтов пришло и читают всё. Вы же установили размер payload’а 32 байта (Вам и приходит 32 - нулями дополненное), а читаете только 4 байта. Так делать нельзя. Почитайте комментарий к функции read() в файле RF24.h - там про это много написано.

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

2 лайка

Попробовал установить GettingStarted на приемник и передатчик.

RF24/examples/GettingStarted
Which radio is this? Enter '0' or '1'. Defaults to '0'
radioNumber = 1
*** PRESS 'T' to begin transmitting to the other node
RF24/examples/GettingStarted
Which radio is this? Enter '0' or '1'. Defaults to '0'
radioNumber = 1
*** PRESS 'T' to begin transmitting to the other node
*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK
Transmission failed or timed out
Transmission failed or timed out
Transmission failed or timed out
Transmission failed or timed out

Все равно не работает

У меня работает. Давайте схему подключения, только полную, с соединениями, питанием и номиналами/характеристиками всех компонентов.

Кстати, запомните: схему и полный скетч нужно давать сразу, в первом же посте. Иначе будут долгие переливы из пустого в порожнее, а половина тех, кто мог бы помочь, просто отвалятся от темы, т.к. им уже надоело стоять на коленях перед каждым новичком и выпрашивать у него схему и/или скетч.

1 лайк