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

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

  1. parovoZZ

    parovoZZ Гуру

    Есть у меня блок питания Traco Power. На холостую выдаёт 5 вольт. Подключаю нагрузку в пару ампер - те же 5 вольт. Не знаю, что на максимуме (20 ампер) - пока нечем нагрузить.
     
  2. Mavric84

    Mavric84 Нуб

    не реклама.... мы брали небольшую партию (100шт.) ML01DP5 (на базе nrf24) вот у этих ребят, ценник более менее адекватный roboshop.spb.ru
    работают на много стабильнее чем стандартные с +, кстать на алихе они по 350р.

     
  3. Neu

    Neu Нерд

    Друзья, поясните, как читать этот вывод? Перечитал 100500 раз комментарий Игоря, все равно не пойму, где первая цифра в первой строке, а где вторая во второй. И откуда начинается уровень зашумленности?
     
  4. parovoZZ

    parovoZZ Гуру

    Первые две строчки - это номер канала в шестнадцатиричной системе исчисления. Всего каналов - 127. Там, где водопад из цифр - это и есть шум. Гарантированно можно работать на последних каналах - туда не забирается вехдесущий вай фай.
     
    Neu нравится это.
  5. ИгорьК

    ИгорьК Гуру

    В сериал выводятся строки цифр.
    Эти строки равной длины, Так?
    Берете одну цифру из первой строки, цифра под ней во второй строке - вторая цифра номера канала.
     
  6. Neu

    Neu Нерд

    Так "зашумленность канала" надо по столбцам что-ли смотреть?
    Вот я выделил первый канал 0 и канал 39:
    [​IMG]

    Получается, что канал 0 - свободен, а 39 - шумит. Вроде верно?
     
  7. ИгорьК

    ИгорьК Гуру

    39 и несколько следующих каналов.
    И помните, что не 39 а 0х39 канал. Различие понимаете?
     
    Neu нравится это.
  8. Neu

    Neu Нерд

    Да. ИгорьК, parovoZZ, большое спасибо за пояснения!
     
  9. Neu

    Neu Нерд

    Благодаря этой теме удалось поднять канал на китайских модулях nRF24L01+ (с усилителем). В качестве стабилизатора питания - модуль на AMS1117 3.3V. Спасибо автору и участникам!
    В начальных попытках, пока подбирал комбинацию параметров, понял, что гонять цифры времени из примера "pingpair" не очень наглядно, т.к. в канал валился всякий мусор и определить стабильность приема-передачи на глаз было сложно. В итоге, чуток подправил исходный пример на передачу меняющейся строчки. Может пригодиться кому:
    Код (C++):

    /*
    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.
    */


    /**
    * Example RF Radio Ping Pair
    *
    * This is an example of how to use the RF24 class.  Write this sketch to two different nodes,
    * connect the role_pin to ground on one.  The ping node sends the current time to the pong node,
    * which responds by sending the value back.  The ping node can then see how long the whole cycle
    * took.
    */


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

    //
    // Hardware configuration
    //

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

    RF24 radio(9,10);

    // sets the role of this unit in hardware.  Connect to GND to be the 'pong' receiver
    // Leave open to be the 'ping' transmitter
    const int role_pin = A4;

    //
    // Topology
    //

    // Radio pipe addresses for the 2 nodes to communicate.
    const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

    // имена получателей приветов
    const char * names[] = {"Elena", "Ivan", "Jonny", "Vasya", "Hoolio", "Azazello"};

    // характеристики
    const char * charac[] = {"crazy", "happy", "funny", "sexy", "sunny", "brave"};

    //
    // Role management
    //
    // Set up role.  This sketch uses the same software for all the nodes
    // in this system.  Doing so greatly simplifies testing.  The hardware itself specifies
    // which node it is.
    //
    // This is done through the role_pin
    //

    // The various roles supported by this sketch
    typedef enum { role_ping_out = 1, role_pong_back } role_e;

    // The debug-friendly names of those roles
    const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

    // The role of the current running sketch
    role_e role;

    unsigned long time = 0;

    void setup(void)
    {
      //
      // Role
      //

      // set up the role pin
      pinMode(role_pin, INPUT);
      digitalWrite(role_pin,HIGH);
      delay(20); // Just to get a solid reading on the role pin

      // read the address pin, establish our role
      if (!digitalRead(role_pin))
        role = role_ping_out;
      else
        role = role_pong_back;

      //
      // Print preamble
      //

      Serial.begin(57600);
      printf_begin();
      printf("\n\rRF24/examples/pingpair/\n\r");
      printf("ROLE: %s\n\r",role_friendly_name[role]);

      //
      // Setup and configure rf radio
      //
      delay(1000);
      radio.begin();
      delay(20);
      radio.setChannel(0x67);                // Установка канала вещания;
      radio.setRetries(15, 15);              // Установка интервала и количества попыток "дозвона" до приемника;
      //radio.setDataRate(RF24_250KBPS);       // Установка минимальной скорости;
      radio.setPALevel(RF24_PA_LOW);         // Установка мин мощности;
      radio.setAutoAck(0);                   // Установка режима подтверждения приема;
      radio.setCRCLength(RF24_CRC_8);

      // optionally, reduce the payload size.  seems to
      // improve reliability
      //radio.setPayloadSize(8);

      //
      // Open pipes to other nodes for communication
      //

      // This simple sketch opens two pipes for these two nodes to communicate
      // back and forth.
      // Open 'our' pipe for writing
      // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

      if ( role == role_ping_out )
      {
        radio.openWritingPipe(pipes[0]);
        radio.openReadingPipe(1,pipes[1]);
      }
      else
      {
        radio.openWritingPipe(pipes[1]);
        radio.openReadingPipe(1,pipes[0]);
      }

      //
      // Start listening
      //

      radio.startListening();

      //
      // Dump the configuration of the rf unit for debugging
      //

      radio.printDetails();
    }

    void loop(void)
    {
      //
      // Ping out role.  Repeatedly send the current time
      //

      if (role == role_ping_out)
      {
        // First, stop listening so we can talk.
        radio.stopListening();

        // Take the time, and send it.  This will block until complete
        //unsigned long time = millis();
        char v_hello[] = "Hello";
        char * v_msg;
        int v_names_idx = rand() % 6;
        int v_charac_idx = rand() % 6;
     
        v_msg = (char *)malloc(strlen(names[v_names_idx]) + strlen(charac[v_charac_idx]) + strlen(v_hello) + 4);
        sprintf(v_msg, "%s, %s %s\0", &v_hello, charac[v_charac_idx], names[v_names_idx]);
     

        //printf("Now sending %lu...", time);
        printf("Now sending \"%s\"...", v_msg);
        //bool ok = radio.write( &time, sizeof(unsigned long) );
        bool ok = radio.write(v_msg, strlen(v_msg));
        free(v_msg);
     
        if (ok)
          printf("ok...");
        else
          printf("failed.\n\r");

        // Now, continue listening
        radio.startListening();
        delay(20);

        // Wait here until we get a response, or timeout (250ms)
        unsigned long started_waiting_at = millis();
        bool timeout = false;
        while (!radio.available() && !timeout)
        {
          if (millis() - started_waiting_at > 3000)
            timeout = true;
        }

        // Describe the results
        if ( timeout )
        {
          printf("Failed, response timed out.\n\r");
        }
        else
        {
          // Grab the response, compare, and send to debugging spew
          int len=0;
          len = radio.getDynamicPayloadSize();
          char gotmsg[len] = {0};
          //unsigned long got_time;
          radio.read( &gotmsg, len);

          // Spew it
          printf("Got response: %s\n\r", &gotmsg);
        }

        // Try again 1s later
        delay(1000);
      }

      //
      // Pong back role.  Receive each packet, dump it out, and send it back
      //

      if ( role == role_pong_back )
      {
        // if there is data ready
        if ( radio.available() )
        {
          // Dump the payloads until we've gotten everything
          unsigned long got_time = 0;
          bool done = false;
          int len=0;
       
          while (!done)
          {
            // Fetch the payload, and see if this was the last one.
            //done = radio.read( &got_time, sizeof(unsigned long) );
            len = radio.getDynamicPayloadSize();
            char gotmsg[len] = {0};
            done = radio.read(&gotmsg, len);

            // Spew it
            //printf("Got payload %lu...\n",got_time);
            printf("Receive: %s...\n", &gotmsg);

            // Delay just a little bit to let the other unit
            // make the transition to receiver
            delay(20);
          }

          // First, stop listening so we can talk
          radio.stopListening();
          delay(1000);

          // Send the final one back.
          char v_ok[] = "OK";
          radio.write(&v_ok, strlen(v_ok));
          printf("Sent response: %s\n\r", &v_ok);

          // Now, resume listening so we catch the next packets.
          radio.startListening();
          delay(1000);
        }
      }
      time = time + 1;
    }

    int serial_putc( char c, FILE * )
    {
      Serial.write( c );
      return c;
    }

    void printf_begin(void)
    {
      fdevopen( &serial_putc, 0 );
    }
    Правда, осталась нерешенной одна проблема:
    при "отбивки" после приема основной строки (radio.write(&v_ok, strlen(v_ok));) почему то этот ОК не долетает до исходного передатчика (с ошибкой - Failed, response timed out). Обложил задержками кругом - не помогает. Буду экспериментировать.
     
    Последнее редактирование: 3 авг 2017
  10. Stas0232

    Stas0232 Нерд

    У меня была такая ситуация: write отправляет данные нормально (причем на приемник они приходят целиком), а возвращает все равно false; и ответное сообщение от приемника тоже не приходит.

    Решение: мне помогли уже много раз оговоренные конденсаторы 2-10 мкФ припаянные прямо на +/- платки. И с 2 мкФ и с 10 мкФ заработало сразу же.

    Эксперимент: для эксперимента попробуйте подставить палец к +/- платки (где-то в этой теме говорилось про такое). У меня частично даже таким способом начало все отсылать и все получать.
     
    Последнее редактирование: 8 авг 2017
    Neu нравится это.
  11. Stas0232

    Stas0232 Нерд

    У меня другой вопрос.
    Работал с библиотекой RF24, в которой была встроена проверка подключения NRF к SPI:
    Код (C++):
    bool isChipConnected();
    а вот read() там почему-то void (мне нужен bool).
    Где брал либу уже не помню. Но работало шикарно. Какой контакт от NRF не отдерни - на все реагирует и возвращает false.
    А в RF24 на github этой функции нету.

    Чем заменить эту функцию или где есть более новая либа с ней?

    P.S. скопировать из одной либы в другую может и не составит проблемы (вроде функционал похожий), но реализация функций разная. Не уверен что ровно будет работать.
     
  12. Neu

    Neu Нерд

    Есть. См. версию от maniacbug: http://maniacbug.github.io/RF24/classRF24.html
    Поторопился. Показалось, что речь о radio.read идет...
    По поводу isChipConnected(): если нужна только она, то наверное лучшим выходом будет попробовать перенести. Эта ф-ция добавлена 3 месяца назад в основной ветке по RF24: https://github.com/nRF24/RF24. См. RF24.cpp


    ЗЫ: За подсказку по кондерам и палец - отдельное спасибо, обязательно попробую :)
     
    Последнее редактирование: 8 авг 2017
  13. Stas0232

    Stas0232 Нерд

    Нашел я ту либу. Подскажите кто имел дело с ней, как она по всем параметрам? Может кто проверял быстродействие, оптимизацию и т.д.
    Меня вроде бы устраивала, пока не захотел использовать
    Код (C++):
    bool read( void* buf, uint8_t len );
    который в этой либе void.
     
  14. zeonmaster

    zeonmaster Нуб

    Приветствую, коллеги! Есть вопрос - удавалось ли кому-то на nrf24 собрать устройство, которое бы выполняло команды за очень короткое время, к примеру, чтобы между отправкой и приемом проходило не более 10 миллисекунд? У нас девайс, где передатчик отправляет оцифрованные данные с двух потенциометров на приемник и тот на основании этих данных даёт команду драйверу ШД на вращение - но нужны минимальные задержки, потому как текущие, примерно 80 миллисекунд, порождают рысканья шаговика и неустойчивую его работу
     
  15. Stas0232

    Stas0232 Нерд

    Когда тестил с помощью millis() выдавало всего 3 результата: 0 ms (до сих пор смущает, что отправка и прием прошли меньше чем за милисекунду, может косяк), 16-17 ms. т.е. иногда есть задержка, а иногда нет.
    Может мои результаты не верны и есть другие способы, но опять же повторюсь, что это с помощью функции millis().
     
  16. rkit

    rkit Гуру

    Если у вас это занимает больше 2 мс, то вы делаете что-то очень сильно неправильно.
     
  17. zeonmaster

    zeonmaster Нуб

    Скину скетч чуть позже, может поможете советом. Немного улучшили дела тем, что перевели модули с 1мбит на 2мбит - работать стал немного увереннее, но все равно далеко от варианта без радиомодулей, напрямую с резисторов в ардуино и на драйвер ШД
     
  18. b707

    b707 Гуру

    Это называется "просчеты эргономики" - таблица оформлена нелогично, ни одному инженеру, как мне кажется, не пришло бы в голову расположить данные вертикальными столбцами :)
    Игорь, прошу не обижаться за этот небольшой стеб...
     
  19. ИгорьК

    ИгорьК Гуру

    Да о чем там... :)

    Предложите вариант вывода в serial, с учетом того, что модуль последовательно сканирует 127 каналов туеву хучу раз. Предлагаете собирать данные в 127 корзин и там считать что-то среднее?

    Не, народ и так не часто утруждается мыслительным процессом (не заметили по этой теме?), поэтому пусть привыкает :)
     
  20. sslobodyan

    sslobodyan Гик

    Если честно, то когда я впервые увидел вывод сканера, то тоже сразу не въехал что это :) А надо было всего лишь написать "Channels", затем вывести нумерацию каналов, пропустить строку и вывести "Noise Levels", после чего уже выводить уровни зашумленности. Короче, пример считаю не доработанным :)