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

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

  1. Oleg_Dr

    Oleg_Dr Нуб

    Здравствуйте. Читать то читать...но английским нужно владеть в совершенстве. Иначе слова то знаю, а смысл написанного не понять....
    Да, я нашел этот документ, Антон подсказал. Будем изучать....
    Вот интересно, автоматический подтверждающий ответ, Ack, без пейлоуд, можно какими то методами вывести на дерганье ног? Или это только через прочтение регистров?
    Да, картинки эти я видел в даташите. ну.....
     
  2. Oleg_Dr

    Oleg_Dr Нуб

    Почитал нормально переведенную статью про модули.
    Это получается, что если у меня передатчик отправляет телеметрию, темп/влажн, приемнику. Нужен всего один канал, т.е. нулевой!
    А в качестве бонуса, приемник в подтверждении приема с полезной нагрузкой, отправляет обратно, по этому же каналу один байт. Который я методом if (radio.isAckPayloadAvailable() зажигаю светодиод на ножке контроллера передатчика, сигнализируя о нормально принятых приемником данных. (Это для наглядности).
    Ну мне пока и этого достаточно....Всего один канал!
    Это сколько в скетче можно закомментировать!
     
  3. Oleg_Dr

    Oleg_Dr Нуб

    Интересная ситуация....Изменил канал приемника с первого на нулевой
    radio.openReadingPipe(1, address[0]); // открыть канал на приём
    radio.openReadingPipe(0, address[0]); // открыть канал на приём
    ...перепрошил приемник. Работает, передатчик принимает подтверждение. Значит приемник отправляет Подтверждение с Полезной нагрузкой по этому же каналу передатчику!
    Снял питание с приемника (в нем менял канал), вновь подал.....И...подтверждение уже не приходит на передатчик.??
    Пришлось заново устанавливать первый канал на прием в приемнике!!!
    radio.openReadingPipe(1, address[0]); // открыть канал на приём
    А как же приемник работает с шестью передатчиками с Подтверждениями???
    Может только Подтверждение с Полезной Нагрузкой нужен отдельный канал...
    Странно.
     
  4. parovoZZ

    parovoZZ Гуру

    ни разу не пользовался дуриновскими библиотеками - они все кривые. А из даташита мы узнаём, что в пакет подтверждения записывается адрес TX_ADDR приёмника. Поэтому, чтобы ACK ответ улетел передатчику, адрес RX_ADDR приёмника обязан совпадать с его же TX_ADDR. Это показано на картинке выше. И у передатчика один из pipe должен быть с этим же адресом.
     
  5. Oleg_Dr

    Oleg_Dr Нуб

    Все таки разбирался с функцией MultiCeiver.
    Это когда до шести передатчиков шлют нагрузку на один приемник. Приемник в ответ передает Подтверждение приема каждому передатчику, или вместе с подтверждением добавляет Полезную Нагрузку. Важно, что приемник в ответ подтверждает в туже самую трубу/канал из которого пришла нагрузка! Работа только с Подтверждениями. Без задачи передавать что то приемником для передатчиков специальным требованием.
    Вроде разобрался. Да, дуриновские бибиотеки, но вроде заработало. Хотя без танцев с бубном не обошлось. Очень помогла та картинка из даташита, которую выложил parovoZZ.

    Это первый передатчик.
    Multi Ceiver_один_перед+АСК.jpg

    Это один приемник.
    Multi Ceiver_прием+АСК.jpg
     
  6. MR_koz

    MR_koz Нерд

    Всем доброго дня! Для меня данная тема тоже стала камнем преткновения. Возможно кто-то сможет посоветовать, в какую сторону копать дальше. Имеем: две ардуины нано, конденсатор к модулям добавлен. Приемник молчит. При проверке приемника отображаются следующие данные:
    STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    RX_ADDR_P0-1 = 0xe7e7e7e7e7 0xaabbccdd11
    RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
    TX_ADDR = 0xe7e7e7e7e7
    RX_PW_P0-6 = 0x00 0x0c 0x00 0x00 0x00 0x00
    EN_AA = 0x00
    EN_RXADDR = 0x03
    RF_CH = 0x4a
    RF_SETUP = 0x07
    CONFIG = 0x0f
    DYNPD/FEATURE = 0x3f 0x06
    Data Rate = 1MBPS
    Model = nRF24L01
    CRC Length = 16 bits
    PA Power = PA_HIGH

    Код передатчика:
    Код (C++):
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    RF24 radio(9, 10);                              
    const uint64_t writingPipe = 0xAABBCCDD11LL;

    void setup(){
       Serial.begin(57600);
       pinMode(4, OUTPUT);
      radio.begin();
      radio.setChannel(5);
      radio.setRetries(15,15);
      radio.setPayloadSize(12);
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_LOW);
      radio.setAutoAck(1);
      radio.setCRCLength(RF24_CRC_8);
      radio.setAutoAck(1);
       radio.powerUp();
       radio.openWritingPipe(writingPipe);
    }
    void loop(){
        const char text[] = "Hello World";                              
        radio.write(&text, sizeof(text));                        
        delay(50);                                              
      digitalWrite(4,1);
      delay(1000);
      digitalWrite(4,0);
      delay(1000);
    }
    Код приемника:
    Код (C++):
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    RF24  radio(9, 10);                                
    const uint64_t readingPipe = 0xAABBCCDD11LL;
    uint8_t  pipe;                                        

    void setup(){
        delay(1000);
        Serial.begin(57600);
         radio.begin();
      radio.setChannel(5);
      radio.setRetries(15,15);
      radio.setPayloadSize(12);
      radio.enableAckPayload();
      radio.powerUp();
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_LOW);
      radio.setAutoAck(1);
      radio.setCRCLength(RF24_CRC_8);
      radio.openReadingPipe(1,readingPipe);
      radio.startListening();
    pinMode(4, OUTPUT);
    }

    void loop(){
        if(radio.available()){                            
            char text[32] = "";
            radio.read(&text, sizeof(text));
            Serial.println(text);
             digitalWrite(4,1);
      delay(1000);
      digitalWrite(4,0);
      delay(1000);
        }
    }
     
    Последнее редактирование: 13 май 2026
  7. parovoZZ

    parovoZZ Гуру

    для начала я бы запустил код сканера эфира - просто для проверки приёмника.

    По коду - я бы не начинал с передачи переменных с неизвестной длиной. Начинать надо с каких-то простых числовых типов.
     
  8. MR_koz

    MR_koz Нерд

    Спасибо за совет. Судя по сканеру, приемник что-то видит, а одно простое число с передатчика не ловит.
    Код (C++):
    00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777
    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
    00000001200030021632000150650050901228100192210990002003038400050041034000400011010100000000010000000000000000000000000000000000
    00100005400013000460010140340040621405100082061370000010022001000000000012000101012020000000000000000000001000000000000000000000
    001000043000130015410044513601407533271000c7020380000000044000000000000000001113022010000000000000000000001000000000000000000000
    00200004300002010a51002120270060982629000084000890003003014201030020012001101110103001000000000000000000000000000000000000000000
    00100003300010000640000050040040711504100093120790000000022000000010000000000010122100000000000000000000000000000000000000000000
    002000023001222109400002400500309205070001c3010480000000034000000010000000011141212000000000000000000000001000000000000000000000
    10000004300001110a50000130140050761305000051330350000000024000000010100000001010103010000000000000000000000000000000000000000010
    00000002400014200860000340130050740606100082231460000000042100000000000102011021210000000000000000000000001000000000000000000000
    00300003300021200940000051010250830506300092331490000000024000000000000000000000125020000000000000000000001000000000000000000000
    001000044100100007300004101312508107064000a6030890000000022000000000000000000000100000000000000000000000003000000000000000000000
    00100000220100000940000310130030a302085000831207a0001001033000000001000000000000100000000000000000000000001000000000000000000000
    101000013100101107310004001400105114073000961104a0000000035001000001000000003000000000000000000000000000000000000000000000000000
    00000003400000000b700002301400707100055000a4021230000000021000000001000000101000100000000000000000000000000000000000000000000000
    00000001310000100b800000402400309100066000b8031460010000034000000001000000001000100000000000000000000000001000000000000000000000
    00101002400010500c80000040050160710107700086143390001010022000000001001000001000200000000000000000000000000000000000000000000000
    00200001500010300b700001501403407201086000d5033290000000044000000000000000000000100000000000000000000000000000000000000000000000
    00000005522100120c700002300513508304063000a7301660000000034001010001000000000000100000000000000000000000000000000000000000000000
    00000003143000030530000640050560820207100094350560000000023000000000001000000000000000000000000000000000001000000000000000000000
    00000105152010030b50001540090340811207200098130680000000043000000000000000000000101000000000000000000000000000000000000000000000
    00300004320000040a40000540050580831506500084132590000000045000000001000000000000100000000000000000000000000000000000000000000020
    00200004540100120c70000910181450812506500096094230000000041000000011001000110000000000000000000000000000001000000000000000000000
    00000006443010010a600004002406607114165000a7023450000000055000000000000000000000100000000000000000000000000000000000000000000010
    00100000330001321c50001315130450500205610031051470000000012000000001000000000000200000000000000000000000000000000000000000000010
    00100000210000210960000003300150800108700050040470000100053000000001000000002000000000000000000000000000000000000000000000000000
    00100000530002420b60000204210681800005500070041580000000034000010000100010001000200000000000000000000000001000000000000000000000
    00200001620000400ba0001084151240600106501043150650000000023000000002000000001000200000000000000000000000000000000000000000000000
     
    Последнее редактирование: 14 май 2026
  9. parovoZZ

    parovoZZ Гуру

    теперь можно включать передатчик на чистом канале и лупить с него в эфир. На сканере смотреть активность.

    а дальше не изобретать что-то своё, а закодить какой-то рабочий пример. Если изобретать что-то своё, то неизбежно придётся читать даташит, т.к. абсолютно все библиотеки КРИВЫЕ.
     
  10. MR_koz

    MR_koz Нерд

    С помощью минимальных изменений кода монитора слушаем 62-й канал:

    Код (C++):
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"

    RF24 radio(9,10); // Для Уно
    //RF24 radio(9,53);// Для Меги
    const uint8_t num_channels = 128;
    uint8_t values[num_channels];
    void setup(void)
    {
      Serial.begin(57600);
      printf_begin();
      radio.begin();
      delay(2000);
      radio.enableDynamicPayloads();
      radio.enableAckPayload();
      radio.setDataRate(RF24_250KBPS);
      //radio.setChannel(0);
      radio.setRetries(15,15);
      radio.setAutoAck(false);
      radio.startListening();
      radio.setChannel(62);
      radio.setCRCLength(RF24_CRC_16);
      radio.setPALevel(RF24_PA_MAX);
      radio.powerUp();
       //radio.write_register( NRF_CONFIG, 0b00001100 ) ;
      radio.printDetails();  // Вот эта строка напечатает нам что-то, если все правильно соединили.
      delay(5000);              // И посмотрим на это пять секунд.

      radio.stopListening();
      int i = 0;    // А это напечатает нам заголовки всех 127 каналов
      while ( i < num_channels )  {
        printf("%x",i>>4);
        ++i;
      }
      printf("\n\r");
      i = 0;
      while ( i < num_channels ) {
        printf("%x",i&0xf);
        ++i;
      }
      printf("\n\r");
    }
    const int num_reps = 100;

    void loop(void)
    {
      memset(values,0,sizeof(values));
      int rep_counter = num_reps;
      while (rep_counter--) {
        int i = num_channels;
        while (i--) {
          radio.setChannel(62);
          radio.startListening();
          delayMicroseconds(128);
          radio.stopListening();
          if ( radio.testCarrier() )
            ++values[i];
        }
      }
      int i = 0;
      while ( i < num_channels ) {
        printf("%x",min(0xf,values[i]&0xf));
        ++i;
      }
      printf("\n\r");
    }
    int serial_putc( char c, FILE * ) {
      Serial.write( c );
      return c;
    }

    void printf_begin(void) {
      #if !defined(__arm__)
      fdevopen( &serial_putc, 0 );
      #endif
    }
     
    Передатчик пробую также запустить на 62-й:

    Код (C++):
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>

    const uint64_t writingPipe = 0xE8E8F0F0AALL;

    int out = 99;

    RF24 radio(9, 10);

    void setup() {
        Serial.begin(57600);
        delay(2000);                  
        radio.begin();                  
        radio.setChannel(62);              
        radio.setRetries(15,15);          
        radio.setDataRate(RF24_250KBPS);
        radio.setPALevel(RF24_PA_MAX);  
        radio.setAutoAck(1);            
        radio.openWritingPipe(writingPipe);
        pinMode(4, OUTPUT);
    }

    void loop()
    {
    radio.write(&out,sizeof(out));
    Serial.println(out);
    digitalWrite(4,1);
    delay(100);
    digitalWrite(4,0);
    delay(100);

    }
    Но в результате видим совершенно нулевую картину:
    Код (C++):
    00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777
    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000
    00000010000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000001000000000011000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110000000000100000000000000000000000
    00000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000
    Видимо, в моём случае кривые не только библиотеки :-D
     
  11. ИгорьК

    ИгорьК Гуру

    @MR_koz , если задача решить вопрос связи - возьми HC-11, HC-12 и есть ещё какие-то модули, название которых @DetSimen знает.

    Все работают по uart и горя не знают. А эти оставь для музея.
     
    MR_koz нравится это.
  12. DetSimen

    DetSimen Гуру

    JDY-40 еще есть, но он на 2.4ГГц работает, дальность не очень (до 100м в прямой видимости). HC-12 работает на 433 Мгц, у него дальность гораздо гораздее. Оба - радиоудлинители для Serial. Почитай.
     
  13. MR_koz

    MR_koz Нерд

    @ИгорьК , спасибо за совет, HC-12 отлично работают! Но не будет ли такого, что один передает, а несколько других ловят? Пока не нашлась информация, как можно настроить каналы связи по парам устройств, чтобы не было пересечений.
     
    ИгорьК нравится это.
  14. parovoZZ

    parovoZZ Гуру

    протоколом обмена. Если нужна защита от прослушивания -> шифрование. Впрочем, это же касается и nrf.
     
  15. ИгорьК

    ИгорьК Гуру

    Когда-то занимался этим.
    Все зависит от задачи. Управление погребом до сих пор работает на HC-12.

    зы. 10 лет прошло...
     
    Последнее редактирование: 29 май 2026
    MR_koz нравится это.