nRF24L01+ : побеждаем модуль.

Тема в разделе "Проводная и беспроводная связь", создана пользователем ИгорьК, 19 июн 2014.

  1. Oleg_

    Oleg_ Нуб

    Как часто Нод1 должен отправлять данные Ноду2? Раз в минуту, т.е. в начале ее?
     
  2. volgoled

    volgoled Нерд

    В седующем проекте тоже планирую перейти на 8266, эти нрф чет меня уже достали
    Так что придется к вам обратиться за советом, если вы не против
     
  3. volgoled

    volgoled Нерд

    Совершенно верно
     
  4. ИгорьК

    ИгорьК Гуру

    Я не против, но ту задачу, что Вы решатете сейчас, похоже надо делать именно на NRF. С точки зрения скорости - они самые самые. Если задача важная - покупать модули надо в брэндовых магазинах, в надежде что там "более-менее".
    Ну а что касается этой - я бы работал с "бирками".
     
  5. Oleg_

    Oleg_ Нуб

    Еще одни вариант реализации:
    Нод2 постоянно слушает Нод1 на трубе №1.
    Нод2 и Нод3 слушают и общаются на трубе №2.
     
  6. volgoled

    volgoled Нерд

    та и было задумано изначально
    но когда Нод2 отправляет данные в Нод 3, вот эти данные и появляются в приемном буфере Нод 1
    соответственно когда общаяются Нод 1 и Нод2 такойме мусор появляется в приемном буфере Нод 3
    знаете, что я подумал есть ли команда, команда которая очищает буферы в НРФ
    это бы решило проблему
    тоесть перед тем как пообщаться НРФка очищает буфер и вперед
    блин теперь получается подтверждения переплитаться будут
    придется всетаки переходить на разные каналы, тогда наверника
     
  7. ИгорьК

    ИгорьК Гуру

    Вообще то ничего не должно оставаться в буферах.
    Модуль прочитал сообщение и отдал его в МК. МК решает что делать дальше.
    Тем не менее в библиотеках есть команды flush на принудительную очистку буферов. Пользуйтесь ими. Читайте второй пост этой темы.
     
  8. Oleg_

    Oleg_ Нуб

    Вы драматизируете ситуацию.
    Как ранее говорил, если использовать разные трубы, тогда Нод1 не будет слышать информацию от Нода3 и когда Нод2 отправляет Ноду3 информацию.
    В Ноде2 сделайте разные переменные для работы с Нодами 1 и 3.
    Также, как написали выше есть две команды очищающие буфер Tx и Rx
    flush_tx(void); и flush_rx(void); Последняя функция вынесена в приват. Можете подправить библиотеку в файле RF24.h и вынести ее в публичную часть как flush_tx(void). Но это, на мой взгляд, костыли.
     
  9. volgoled

    volgoled Нерд

    Мужики спасибо Вам за пищу для мозгов, и за то, что не остались равнодушными, после экспериментов отпишусь обязательно
     
  10. Dimitriy32ru

    Dimitriy32ru Нуб

    Всем доброго времени суток.
    Сталкивался ли кто-нибудь с подобной ситуацией, ну или же куда копать?
    Передаю массив типа byte по радиоканалу, затем вывожу его в монитор порта, в результате только первые два байта совпадают с тем, что якобы передал, остальные в нулях.
    ***
    Код передатчика:
    Код (C++):
    #include <SPI.h>
    #include "RF24.h"
    #include "nRF24L01.h"
    #include "printf.h"

    RF24 Radio(2,SS);

    byte USB_IN[7];
    byte USB_OUT;

    void setup() {
      Serial.begin(9600);
      //
      Radio.begin();
      printf_begin();
      delay(100);
      Radio.setChannel        (60);
      Radio.setDataRate       (RF24_1MBPS);
      Radio.setPALevel        (RF24_PA_HIGH);
      Radio.setRetries        (15,15);
      Radio.openWritingPipe   (  0xF0F1F2F3F6LL);
      Radio.openReadingPipe   (1,0xF0F1F2F3F5LL);
      Radio.setCRCLength      (RF24_CRC_DISABLED);
    }
    void loop() {
      USB_IN:
        if(Serial.available()>=7){
          for(int i=0;i<7;i++){
            USB_IN[i]=Serial.read();
          }
          Serial.println("********************************");
          Serial.println("   Receive data interface USB");
          Serial.print("Digit: ");
          for(int i=0;i<4;i++){
            Serial.print(USB_IN[i]-48);
          }
          Serial.println();
          Serial.print("Button allowed: ");
          Serial.println(USB_IN[4]-48);
          Serial.print("Write allowed: ");
          Serial.println(USB_IN[5]-48);
          Serial.print("Number display: ");
          Serial.println(USB_IN[6]-48);
          Serial.println("USB_IN->->->->->NRF");
          while(Serial.available()){
            delay(2);
            Serial.read();
          }
          goto NRF;
        }
        else{
          goto USB_IN;
        }
      NRF:
        Radio.write(&USB_IN,7);
        Serial.println("Tranceive data interface NRF");
        Serial.println("___________SETUP_NRF___________");
        Radio.printDetails();
        Serial.println("_______________________________");
        Serial.println("NRF->->->->->USB_OUT");
        goto USB_OUT;
      USB_OUT:
        Radio.startListening();
        if(Radio.available()==1){
          Radio.read(&USB_OUT,sizeof(1));
          Radio.stopListening();
          Serial.println("Receive data interface NRF");
          Serial.write(USB_OUT);
          Serial.print("Data: ");
          Serial.println(USB_OUT);
          USB_OUT=0;
          Serial.println("USB_OUT->->->->->USB_IN");
          Serial.println("********************************");
          goto USB_IN;
        }
        else if(Serial.available()==1){
          if(Serial.read()=='R'){
            Radio.stopListening();
            Serial.println("USB_OUT->->->->->USB_IN");
            Serial.println("********************************");
            goto USB_IN;
          }
        }
        goto USB_OUT;
    }
    Монитор передатчика:
    Код (Text):
    ********************************
       Receive data interface USB
    Digit: 1234
    Button allowed: 5
    Write allowed: 6
    Number display: 7
    USB_IN->->->->->NRF
    Tranceive data interface NRF
    ___________SETUP_NRF___________
    STATUS         = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    RX_ADDR_P0-1     = 0xf0f1f2f3f6 0xf0f1f2f3f5
    RX_ADDR_P2-5     = 0xf4 0xf3 0xf2 0xf1
    TX_ADDR         = 0xf0f1f2f3f6
    RX_PW_P0-6     = 0x20 0x20 0x20 0x20 0x20 0x20
    EN_AA         = 0x3f
    EN_RXADDR     = 0x3f
    RF_CH         = 0x3c
    RF_SETUP     = 0x05
    CONFIG         = 0x02
    DYNPD/FEATURE     = 0x00 0x00
    Data Rate     = 1MBPS
    Model         = nRF24L01+
    CRC Length     = 8 bits
    PA Power     = PA_HIGH
    _______________________________
    NRF->->->->->USB_OUT
    Receive data interface NRF
    Data: 1
    USB_OUT->->->->->USB_IN
    ********************************
     
    Код приемника:
    Код (C++):
    #include <SPI.h>
    #include "RF24.h"
    #include "nRF24L01.h"
    #include "printf.h"

    RF24 Radio(2,SS);

    byte NRF_IN[7];
    byte NRF_OUT=1;


    void setup() {
      Serial.begin(9600);
      //
      Radio.begin();
      delay(100);
      Radio.setChannel        (60);
      Radio.setDataRate       (RF24_1MBPS);
      Radio.setPALevel        (RF24_PA_HIGH);
      Radio.setRetries        (15,15);
      Radio.openWritingPipe   (  0xF0F1F2F3F5LL);
      Radio.openReadingPipe   (1,0xF0F1F2F3F6LL);
      Radio.startListening    ();
      Radio.setCRCLength      (RF24_CRC_DISABLED);
    }

    void loop() {
      delay(100);
      if(Radio.available()){
        Radio.read(&NRF_IN,sizeof(7));
        Serial.println("********************************");
        Serial.println("   Receive data interface NRF");
        Serial.print("Digit: ");
        for(int i=0;i<4;i++){
          Serial.print(NRF_IN[i]-48);
        }
        Serial.println();
        Serial.print("Button allowed: ");
        Serial.println(NRF_IN[4]-48);
        Serial.print("Write allowed: ");
        Serial.println(NRF_IN[5]-48);
        Serial.print("Number display: ");
        Serial.println(NRF_IN[6]-48);
        Radio.stopListening    ();
        Radio.write(&NRF_OUT,sizeof(1));
        Radio.startListening   ();
        Serial.println("Tranceive data interface NRF");
      }
      else{
        //Serial.println("NO_DATA");
      }
    }
    Монитор приемника:
    Код (Text):
    ********************************
       Receive data interface NRF
    Digit: 12-48-48
    Button allowed: -48
    Write allowed: -48
    Number display: -48
    Tranceive data interface NRF
     
    Пытался поиграть с длиной пакета, результатов не принесло, как-будто передатчик вместо 7 байт только 2 отправляет, все остальное по умолчанию забивается нулями.......
     
  11. Dimitriy32ru

    Dimitriy32ru Нуб

    Прошу прощения :-D Не прошло и 5-ти минут как методом "тыка" разобрался, хоть и смысла не понял=(
    Все дело было в коде приемника, строка:
    Radio.read(&NRF_IN,sizeof(7));
    исправил на
    Radio.read(&NRF_IN,7);
    и все заработало, быть может кому-пригодится
     
  12. ИгорьК

    ИгорьК Гуру

    sizeof(7)); равно 2. А 7 = 7.
     
  13. Lictor

    Lictor Нуб

    Доброго времени суток. Так же купил россыпью (10шт) этих модулей. Все исправны, Сканером проверял. Конденсаторы напаял. Питаю от 2 разных источников 3.3В по 1А каждый. Написал код для ардуино Децимия (передатчик) и Мега (приемник). Коды, думаю, приводить смысла нет, т.к. по ним вопросов нет и они идеально работают. НО! эти передатчики часть бОльшего проекта с кучей периферии. (Экран, EEPROM, GPS, часы реального времени, SD карта и т.п.). Когда же я в ключаю код приемника в общий код в серийный порт постоянно выдаются нули, т.е. модуль якобы всегда принимает какие-то сообщения. Никак не могу разобраться что не так. Имею мнение, что это влияет SD карта (больше к ICSP порту ничего не подключено). Это возможно?
    Код приемника, на всякий случай.
    Код (C++):
    #include<SPI.h>
    #include<nRF24L01.h>
    #include<RF24.h>

    const uint64_t pipe = {0xF0F0F0F0E1LL}; //адрес трубы

    RF24 radionrf(7, 6); //Мега

    byte red[4] = {1, 2, 3, 4};          //куда получем сообщение

    void setup() {

      Serial.begin(9600); //запуск серийного опрта
      radionrf.begin();      //запуск радиомодуля
      delay(100);         //небольшая задержка для запуска
      radionrf.enableDynamicPayloads();      //отключаем изменение размера передаваемого буфера????
      radionrf.openReadingPipe(1, pipe);     //открываем трубу для прослушки
      radionrf.openWritingPipe(pipe);       //Открывем трубу для отправки
      radionrf.startListening();            //начинаем слушать эфир

    }

    void loop() {
      int y = 4;
      if (y != 8) {
    while(9){
      if ( radionrf.available() ) {          //если в эфире что-то есть, то
        radionrf.read( red, sizeof(red) );  //принимаем сообщение

        Serial.print(red[0]);      //и выводим в серийный порт
        Serial.print(" ");
        Serial.print(red[1]);
        Serial.print(" ");
        Serial.print(red[2]);
        Serial.print(" ");
        Serial.print(red[3]);
        Serial.println(" ");
      }
    }
      }
    }//конец loop
    Цикл while я вставил для проверки, т.к. в основном коде для которого я приготовил этот кусок, код приемника в loop тоже будет в таком цикле.
    Понимаю, что информации мало, но в основном проекте более 3500 строк, вряд ли кто будет разбираться, мне бы понять хоть в какую сторону копать(
    Буду признателен за любую помощь.

    Как выяснилось дело в SD карте, если после загрузки с нее картинки отключить управляющий пин или просто ее достать, то приемник начинает работать. Есть какие-либо пути решения? Способ отсюда не помог. Может можно как-то на время отключать карту?
     
    Последнее редактирование: 1 ноя 2016
  14. sslobodyan

    sslobodyan Гик

    Во-первых, спасибо за тему. Очень много полезной информации.
    Во-вторых, видел несколько раз вопросы по поводу того, что модули с усилителем ведут себя не понятно. То есть, подносишь к ним руку - связь появляется, убираешь - связь пропадает. Типа черная магия :)
    Так вот, наступил я на такие грабли и долго ковырялся в коде. Проверял посылки осциллографом, замерял токи модулей. Уж чуть не начал шаманский бубен искать. А причина оказалась банальной.
    Разобрав антенну, которая шла вместе с модулем, обнаружил обычную китайскую халтуру. Противовес (такая металлическая гильзочка на антенном кабеле) китаезы просто обжимают на кабеле. Естественно, сильно его обжать нельзя - передавит экран и коротнет на центральную жилу. И вот именно из-за этого плохого контакта (а у меня так вообще противовес слетел с кабеля) и вся барабашка случается. Я одел противовес на место, припаял его к экрану и все чудненьким образом устаканилось. Намерял дальность связи в поле около 500 метров - а дальше мне и не нужно.
    Всем удачи, особенно ТС за его старания :)
     
    Oleg_ и ИгорьК нравится это.
  15. Lictor

    Lictor Нуб

    Проблема решилась подключением SD к SPI через буфер HEF4050, а nRF24L01+ напрямую к выходам SPI на ардуино.
     

    Вложения:

  16. Oleg_7

    Oleg_7 Гик

    Добрый день! а можно по подробнее, что за буфер HEF4050 ? как выглядит и принцип действия?
     
  17. Коллеги, добрый день! Требуется ваш совет или идеи.
    Имеется домашний проект из разряда "Hello Word!" для Arduino :) - метеопанель, с внешним датчиком температуры (и не одним).
    В ходе экспериментов были потери среди модулей nRF (так получилось). Остались модули из разных партий но одной схемотехники.
    Итак, есть:
    nRF24L01+ с внешней антеной на домашнем блоке
    nRF24L01+ со встроенной антеной на внешнем блоке (aTtiny85)
    nRF24L01+ со встроенной антеной на внешнем блоке (Pro mini)
    Настройки везде одинаковые:
    Код (C++):

      radio.begin();                          // nRF24L01+
      radio.powerUp();                        //
      delay(20);
      radio.setPayloadSize(32);               // определяет размер буфера обмена. По умолчанию размер буфера 32
      radio.setChannel(RF24_Channel);         // Канал связи
      radio.setDataRate(RF24_250KBPS);        // RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
      radio.setPALevel(RF24_PA_HIGH);         // RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM
      radio.setAutoAck(true);                 // Подтверждение передачи
      radio.setRetries(15, 15);               // Повторы и интервал между повторами
      radio.setCRCLength(RF24_CRC_8);         // RF24_CRC_8 for 8-bit or RF24_CRC_16
      radio.openReadingPipe(1, pipeOut1);     // Слушаем канал 1
      radio.startListening();                 // nRF24L01+ включаем прием
     
    Проблема:
    Нет подтверждения приема сообщения, т.е.
    Код (C++):
    state = radio.write( &iPacket, sizeof(struct sPacket) );
    Всегда возвращает "FALSE". Из за этого всегда идет большое количество попыток отправить данные
    Код (C++):

      radio.stopListening();
      radio.openWritingPipe(pipeOut1);
      radio.flush_tx();
      delay(20);
      for (int i = 0; ((i < RETRY_SEND) & (!state)); i++) {
        state = radio.write( &iPacket, sizeof(struct sPacket) );
        delay(250);
      };
      radio.startListening();
      delay(20);
     
    Со стороны принимающей ВСЕ отправленные пакеты принимаются в количестве "RETRY_SEND". (напомню - настройки иденичные)
    Код приема проще некуда:
    Код (C++):
      if ( radio.available() ) {                            // Если что-то пришло
        radio.read( &iPacket, sizeof(struct sPacket) );     // по адресу переменной iPacket функция записывает принятые данные;
      }
     
    Проблема началась при замене "сгоревшего" модуля на передатчике. Т.е. теперь у меня модули из разных партий (разные продавцы на Ali).
    Если включить 2 модуля из одной партии - работает код корректно. Из разных - нет.
    Что я забыл подкрутить или что перекрутил?

    Извините за небольшой возможный сумбур, 2 недели уже бьюсь без видимых результатов.
    P.S. Всю тему прочитал, но либо пропустил ответ либо не осознал что является ответом.
     
  18. Lictor

    Lictor Нуб

    Это односторонний согласователь уровня сигнала: на входе в него 5В на выходе 3.3В. У него есть множество аналогов, например, cd4050, А так даже не знаю что еще про него сказать. Кстати, бывают двухсторонние согласователи. Они нужны если шина двухсторонняя. Выглядит как обычная микросхема DIP-16.
     
  19. Oleg_7

    Oleg_7 Гик

    Т.Е., можно на spi вешать смело и nrf + sd + ethernet одновременно?!
     
  20. Lictor

    Lictor Нуб

    Ну интернет не знаю, а nrf и SD у меня работают отлично. Хотя без буфера радиомодуль при включенной SD карте не работал.
     
    MickNich нравится это.