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

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

  1. Un_ka

    Un_ka Гик

    Может лучше в рекламе?
     
  2. Cadas

    Cadas Нерд

    Просто и без проблем соединить радио модули nRF24L01+ по эфиру мне удалось после выполнения трех простых шагов. Подробно – тут.

    1. Вначале модули проверяются на работоспособность и правильность подключения. Для этого загрузить в контроллер платы Ардуино скетч сканера эфира.
    Код (C++):
    /*
    сканер эфира
    https://habr.com/ru/post/476716/
    */


    /*
      Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>

      This program is free software; you can redistribute it and/or
      modify it under the terms of the GNU General Public License
      version 2 as published by the Free Software Foundation.
    */


    /**
       Channel scanner

       Example to detect interference on the various channels available.
       This is a good diagnostic tool to check whether you're picking a
       good channel for your application.

       Inspired by cpixip.
       See http://arduino.cc/forum/index.php/topic,54795.0.html
    */


    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    #include "printf.h"

    //
    // Hardware configuration
    //

    // Set up nRF24L01 radio on SPI bus plus pins 9 & 10

    RF24 radio(9, 10); //Arduino UNO

    //
    // Channel info
    //

    const uint8_t num_channels = 128;
    uint8_t values[num_channels];

    //
    // Setup
    //

    void setup(void)
    {
      //
      // Print preamble
      //

      Serial.begin(9600);
      Serial.println("Scanner Air On");
      printf_begin();

      //
      // Setup and configure rf radio
      //

      radio.begin();
      radio.setAutoAck(false);

      // Get into standby mode
      radio.startListening();
      radio.printDetails();
      delay(5000);        

      // Print out header, high then low digit
      int i = 0;
      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");
    }

    //
    // Loop
    //

    const int num_reps = 100;

    void loop(void)
    {
      // Clear measurement values
      memset(values, 0, sizeof(values));

      // Scan all channels num_reps times
      int rep_counter = num_reps;
      while (rep_counter--)
      {
        int i = num_channels;
        while (i--)
        {
          // Select this channel
          radio.setChannel(i);

          // Listen for a little
          radio.startListening();
          delayMicroseconds(512);
          radio.stopListening();

          // Did we get a carrier?
          if ( radio.testCarrier() )
            ++values[i];
        }
      }

      // Print out channel measurements, clamped to a single hex digit
      int i = 0;
      while ( i < num_channels )
      {
        printf("%x", min(0xf, values[i] & 0xf));
        ++i;
      }
      printf("\n\r");
    }
    Далее подключить модуль nRF24L01 к плате Ардуино или любому прототипу. На мониторе последовательного порта Arduino IDE увидите нечто похожее:
    scanner.png
    Если видна похожая картинка — тест на работоспособность (исправность) модуля и правильность его подключения пройден успешно. Проверить второй модуль из пары.

    2. Затем один из пары модулей тестируется на работу в режиме передатчика без ожидания отклика с приемника. Для этого по схеме, аналогичной первой, собираем второй радиоузел. Это будет передатчик. В его контроллер загружаем скетч передатчика.
    Код (C++):
    /*
    передатчик
    https://habr.com/ru/post/476716/
    */


    #include <SPI.h>
    #include <RF24.h>
    RF24 radio(9, 10); // порты D9, D10: CSN CE
    const uint32_t pipe = 111156789; // адрес рабочей трубы;

    byte data;

    void setup() {
      Serial.begin(115200);
      Serial.println("TransmitterTester ON");

      radio.begin();                // инициализация
      delay(2000);
      radio.setDataRate(RF24_1MBPS); // скорость обмена данными RF24_1MBPS или RF24_2MBPS
      radio.setCRCLength(RF24_CRC_8); // размер контрольной суммы 8 bit или 16 bit
      radio.setPALevel(RF24_PA_MAX); // уровень питания усилителя RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
      radio.setChannel(0x6f);         // установка канала
      radio.setAutoAck(false);       // автоответ
      radio.powerUp();               // включение или пониженное потребление powerDown - powerUp
      radio.stopListening();  //радиоэфир не слушаем, только передача
      radio.openWritingPipe(pipe);   // открыть трубу на отправку
    }

    void loop() {
      data = 109;
      radio.write(&data, 1);
      Serial.println("data= " + String(data));
    }
    Подать питание на сканер эфира и передатчик. Если все верно , то на канале 6f и соседних появится сигнал.
    transmitter.png

    3. Последний этап — улучшение качества связи в этой связке передатчик-приемник. Загрузить вместо скетча сканера скетч приемника.
    Код (C++):
    /*
    приемник
    https://habr.com/ru/post/476716/
    */

    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"

    RF24 radio(9, 10); // порты D9, D10: CSN CE

    const uint32_t pipe = 111156789; // адрес рабочей трубы;
    byte data[1];
    int scn;  //счетчик циклов прослушивания эфира
    int sg;  //счетчик числа принятых пакетов с передатчика

    void setup() {
      Serial.begin(9600);
      Serial.println("ReceiverTester ON");

      radio.begin();  // инициализация
      delay(2000);
      radio.setDataRate(RF24_1MBPS); // скорость обмена данными RF24_1MBPS или RF24_2MBPS
      radio.setCRCLength(RF24_CRC_8); // размер контрольной суммы 8 bit или 16 bit
      radio.setChannel(0x6f);         // установка канала
      radio.setAutoAck(false);       // автоответ
      radio.openReadingPipe(1, pipe); // открыть трубу на приём
      radio.startListening();        // приём
    }

    void loop() {
      if (scn < 1000)
      { // прослушивание эфира
        if (radio.available())
        {
          radio.read(data, 1);

          if (data[0] == 109) {
            sg++;
          }
        }
      } else {//всего принято
        {
          Serial.println("Принято: " + String(sg) + " пакетов");
          sg = 0;
        }
        scn = 0;
      }
      scn++;
      delay(20);

      if (scn >= 1000) scn = 1000; //защита от переполнения счетчика
    }
    Включить пару передатчик-приемник. Если нет приема максимального возможного числа пакетов 999 из 1000, то установить ВЧ и НЧ фильтры по питанию радио модулей, добавить дополнительную антенну, установить пассивную нагрузку по цепи внешней антенны, грамотно экранировать модули, исключая антенну. Предполагаю, что достаточно будет одного из перечисленного. Позитив не заставит себя долго ждать:
    receiver.png
     
    Последнее редактирование: 7 апр 2021
    Un_ka нравится это.
  3. Kot26ru

    Kot26ru Нерд

    Подскажите, можно ли заменить вход SCK на другой? Есть подозрение, что я его спалил. Например использовать D8 вместо D13
     
  4. Un_ka

    Un_ka Гик

    Проверьте его на выход (светодиод и резистор), вход(тоже) и подтяжку к питанию через 10кОм.
     
  5. parovoZZ

    parovoZZ Гуру

    в древних AVR - нет. В новых - да.
     
  6. Kot26ru

    Kot26ru Нерд

    спасибо, попробую
     
  7. Kot26ru

    Kot26ru Нерд

    а можете объяснить как это сделать? Желательно пошагово, если нетрудно
     
  8. Un_ka

    Un_ka Гик

    А Atmega 328/p, Atmega 168p - это древние или уже новые?
     
  9. parovoZZ

    parovoZZ Гуру

    Новые - это DA серия. 0-ая и 1-ая серия тоже новые, но более не поддерживается. В них выводы SPI можно ремапить. Например, arduino nano every.

    В AtMega328PB два блока SPI. Поэтому есть место для маневра.

    В остальных можно UART перевести в режим USART, но надо в даташите смотерть, куда подключается клок..
     
  10. Kot26ru

    Kot26ru Нерд

    на светодиод проверил - мигает. Значит живой выход. Но проверку
    Код (C++):
    radio.begin();                                // Старт RF24
    if (!radio.begin()) {                         // если радиомодуль не запустился
    Serial.println(F("Радиомодуль не отвечает"));
    while (1) {}                                 // ждем когда запустится радиомодуль
    }
    не проходит. Сам радиомодуль 100% живой, потому как подключаю к другой такой же ардуинке и все работает. Пробовал CE CSN менять местами, пробовал назначать их на D7 D8 - ничего не помогает.
     
  11. Un_ka

    Un_ka Гик

    Зачем вызывать два раза метод begin?
    Согласно документации он ничего не возвращает.
    К какой плате подключаете и с каким питанием?
    Настоятельно рекомендую прозвонить контакты.
     
  12. Kot26ru

    Kot26ru Нерд

    if(!radio.begin()) - стандартная проверка на запустился/не запустился. Взял её с примера в этой ветке. Плата - arduino nano ch340. Модули nrf24l01 с антенами. Для модулей взял адаптеры под 5В. Контакты я смотрел, там все норм. Говорю же - ставлю такую же ардуину, заливаю тот же код - все работает. Изначально ардуинка нормально работала и я связал две пары без особых проблем и обмен у меня шел. Но потом, что то произошло и одна из ардуин перестала запускать нрф-ку. Нрф-ки у меня три, я их пробовал все по очереди. На одной ардуине все работают. На второй ни одна не хочет запускаться.
     
  13. Ustinoff

    Ustinoff Нуб

     
  14. Ustinoff

    Ustinoff Нуб

    Добрый день. Мне кажется, что у вас перепутаны ножки 9 и 10.
     
  15. Ustinoff

    Ustinoff Нуб

    Ошибки подключения. Поменяй местами 9, 10 ноги при инициализации.
     
  16. Kot26ru

    Kot26ru Нерд

    не, они так на приемнике и подключены. Дело не в них