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

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

  1. ИгорьК

    ИгорьК Гуру

    Глубоко! Класс!
    Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call enableDynamicPayloads() to enable on all pipes.
     
  2. BGreen

    BGreen Нерд

    Охохо, похоже, что dynamic имеет 2 смысла:
    1. переменный размер
    2. событие вызывается или нет по-желанию

    "Переменная полезная нагрузка" (dynamic payloads) включает в себя и прямую отправку данных, и обратную (ACK). Поэтому нужно включить enableDynamicPayloads(), чтобы по-желанию отправлять\не отправлять данные и АСК по любой трубе.
     
    ИгорьК нравится это.
  3. ИгорьК

    ИгорьК Гуру

    Возможно, со стороны это и кажется забавным, но дело вот в чем.
    Исходя из нормальной логики, чтобы два модуля заработали, им нужно сообщить совсем немного вещей - канал, адрес да скорость. Так и делается во многих скетчах, написанных авторами библиотек. Соображение здесь таково, что все остальные настраиваемые параметры у модулей по умолчанию настроены одинаково.
    Но не тут то было - эти настройки у разных модулей разные, или, что еще хуже, не исключено, что при старте модуля не определенные в скетче параметры устанавливаются случайным образом.
    Поэтому, одна пара модулей стартует и работает в скетче, но другая в том же САМОМ скетче на работает.

    В моем частном случае, год назад было связано три модуля некоторым скетчем, и они отлично устойчиво работают. А вот попытка "внедрить" туда четвертый модуль (с тем же программным кодом, что трудится уже год и не кашляет) успехом не увенчалась.
    Более того, все примеры из библиотеки отказывались работать на паре новых модулей! И только один пример заработал и вполне устойчиво. Он отличался от иных лишь одним - прямым вызовом функции setCRCLength. Надеюсь, объяснил.
     
    Последнее редактирование: 1 дек 2015
    BGreen нравится это.
  4. BGreen

    BGreen Нерд

    1 слушатель, 5 передатчиков
    База c IRQ + 5 датчиков.
    Код проверен на 2х NRF, больше нет контроллеров.
    Кто проверит на большем количестве NRF или найдет баги - прошу написать в тему!

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

    #define CE_PIN 9
    #define CSN_PIN 10

    const uint8_t imSensorNum = 1; //1..5

    //'static' - no need
    const uint64_t pipes[6] = {
      0xDEADBEEF00LL,  //pipe0 is SYSTEM_pipe, avoid openReadingPipe(0, );
      0xDEADBEEF01LL,
      0xDEADBEEF02LL,
      0xDEADBEEF03LL,
      0xDEADBEEF04LL,
      0xDEADBEEF05LL
    };

    RF24 radio(CE_PIN, CSN_PIN);

    void setup() {
      delay(2000);
      Serial.begin(9600);
      delay(100);
      Serial.print("Im Sensor# ");
      Serial.print(imSensorNum);
      Serial.print("\r\n");

      radio.begin();
      delay(100);
      radio.powerUp();
      delay(100);
      radio.setChannel(5);
      radio.setRetries(15, 15);
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_MIN);
      radio.setCRCLength(RF24_CRC_8);


      /*
       ===writeAckPayload===enableDynamicPayloads===
       !  Only three of these can be pending at any time as there are only 3 FIFO buffers.
       !  Dynamic payloads must be enabled.
       !  write an ack payload as soon as startListening() is called
       */

      radio.enableDynamicPayloads();//for ALL pipes
      //radio.setPayloadSize(32); //32 bytes? Can corrupt "writeAckPayload"?

      radio.setAutoAck(true);//allow RX send answer(acknoledgement) to TX (for ALL pipes?)
      radio.enableAckPayload(); //only for 0,1 pipes?
      //radio.enableDynamicAck(); //for ALL pipes? Чтобы можно было вкл\выкл получение ACK?

      radio.stopListening();// ?
      radio.openWritingPipe(pipes[imSensorNum]); //pipe0 is SYSTEM_pipe, no reading
    }

    void loop()
    {
      uint16_t messageToBase_batteryVoltage = random(0, 65535); //2^16 - 1
      uint16_t messageToBase_temperature = random(0, 65535); //2^16 - 1
      uint16_t messageToBase_humidity = random(0, 65535); //2^16 - 1

      uint16_t messageToBase[3] = {
        messageToBase_batteryVoltage,
        messageToBase_temperature,
        messageToBase_humidity
      };

      uint8_t answerFromBase; //2^8 - 1   [0,255]

      //Stop listening for incoming messages, and switch to transmit mode.
      //Do this before calling write().
      radio.stopListening();
      radio.write( &messageToBase, sizeof(messageToBase));

      Serial.print("V= ");
      Serial.print(messageToBase[0]);
      Serial.print("\r\n");
      Serial.print("t= ");
      Serial.print(messageToBase[1]);
      Serial.print("\r\n");
      Serial.print("h= ");
      Serial.print(messageToBase[2]);
      Serial.print("\r\n");

      if ( radio.isAckPayloadAvailable() ) {
        radio.read(&answerFromBase, sizeof(answerFromBase)); //приемник принял и ответил

        Serial.print("___Received answer from Base: ");
        Serial.print(answerFromBase, DEC);
        Serial.print("\r\n");
      }
      delay(1000);
    }


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

    #define CE_PIN 9
    #define CSN_PIN 10

    //'static' - no need
    const uint64_t pipes[6] = {
      0xDEADBEEF00LL,  //pipe0 is SYSTEM_pipe, avoid openReadingPipe(0, );
      0xDEADBEEF01LL,
      0xDEADBEEF02LL,
      0xDEADBEEF03LL,
      0xDEADBEEF04LL,
      0xDEADBEEF05LL
    };

    uint8_t currPipeNum;
    uint16_t messageFromSensor[3] = {
      0, //v
      0, //t
      0  //h
    };

    RF24 radio(CE_PIN, CSN_PIN);

    void setup() {
      delay(2000);
      Serial.begin(9600);
      delay(100);
      Serial.println("Im Base with IRQ and AckPayload");

      radio.begin();
      delay(100);
      radio.powerUp();
      delay(100);
      radio.setChannel(5);
      radio.setRetries(15, 15);
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_MIN);
      radio.setCRCLength(RF24_CRC_8);

      /*
        ===writeAckPayload===enableDynamicPayloads===
        !  Only three of these can be pending at any time as there are only 3 FIFO buffers.
        !  Dynamic payloads must be enabled.
        !  write an ack payload as soon as startListening() is called
      */

      radio.enableDynamicPayloads();//for ALL pipes
      //radio.setPayloadSize(32); //32 bytes? Can corrupt "writeAckPayload"?

      radio.setAutoAck(true);//allow RX send answer(acknoledgement) to TX (for ALL pipes?)
      radio.enableAckPayload(); //only for 0,1 pipes?
      //radio.enableDynamicAck(); //for ALL pipes? Чтобы можно было вкл\выкл получение ACK?

      //radio.openReadingPipe(0, pipe0); 0 is SYSTEM, no reading
      radio.openReadingPipe(1, pipes[1]);
      radio.openReadingPipe(2, pipes[2]);
      radio.openReadingPipe(3, pipes[3]);
      radio.openReadingPipe(4, pipes[4]);
      radio.openReadingPipe(5, pipes[5]);
      radio.startListening();

      attachInterrupt(0, radioListen, LOW); //d2  //send acknoledgement FAIL
    }

    void radioListen() {

      if (radio.available(&currPipeNum)) {
        radio.writeAckPayload(currPipeNum, &currPipeNum, sizeof(currPipeNum) );
        if (radio.getDynamicPayloadSize() > 1) { //размер полученного сообщения
          radio.read(&messageFromSensor, sizeof(messageFromSensor));

          Serial.print("Sensor# ");
          Serial.print(currPipeNum);
          Serial.print("\r\n");
          Serial.print("V= ");
          Serial.print(messageFromSensor[0]);
          Serial.print("\r\n");
          Serial.print("t= ");
          Serial.print(messageFromSensor[1]);
          Serial.print("\r\n");
          Serial.print("h= ");
          Serial.print(messageFromSensor[2]);
          Serial.print("\r\n");
          Serial.print("\r\n");
        }
        else {
          // Corrupt payload has been flushed
        }

        //radio.stopListening(); //не надо! СТОП только если хочешь write
        //radio.startListening();//не надо! СТАРТ один раз, когда объявил трубы

      }
      //bool tx, fail, rx;
      //radio.whatHappened(tx, fail, rx); // What happened?
      //if ( rx || radio.available()) {

    }

    void loop() {
      //radioListen();
    }
     
    DIYMan и ИгорьК нравится это.
  5. BGreen

    BGreen Нерд

    Теперь борюсь с проблемой: SD + NFR + TFT on SPI.
    Шина SPI не работает.
    Предварительно:
    sdSS = d4;
    nrfSS = d10 (CSN); //CE - это управление чипом, а не шиной (?)
    Вручную дергаю ножки, но кто-то портит MISO, MOSI.
    Придется найти время и корпеть с осциллом и анализатором, которого еще нет.
     
  6. ИгорьК

    ИгорьК Гуру

    Может на ESP8266 перейдете?
     
  7. BGreen

    BGreen Нерд

    В загашнике ESP8266-12E, но надо плату развести и вытравить под него. Готовая китайская не имеет нужных подтяжек. У китайцев только CH_PD и GPIO15, а надо:

    CH_PD подтянуть к питанию через 4,7k
    GPIO0 подтянуть к питанию через 10k
    GPIO2 подтянуть к питанию через 10k
    GPIO15 подтянуть к земле через 4,7k
    RESET подтянуть к питанию через 10k
    (везде, где 10k можно заменить на 10k..50k)
    -----------------
    LUA и прочие языки для прошивки именно ESP8266 пока нет времени изучать.
    ESP8266 таки wifi, на мой взгляд.
    А NRF более кастомный радио-канал.
     
  8. ИгорьК

    ИгорьК Гуру

    Но можно проще. CH_PD закоротить на питание, GPIO15 закоротить на землю и не париться.
    У меня все работает именно так. Без проблем.
     
  9. BGreen

    BGreen Нерд

    Несколько устройств на шине SPI
    В свежей АрдуиноIDE 1.6.6 появилась поддержка SPI_transaction.
    То есть, устройство начинает транзакцию, выставляет желаемые параметры и работает по SPI.
    Транзакция завершается, SPI свободно и может быть переконфигурировано другим устройством.

    В библиотеке RF24 tmrh20 вроде как есть поддержка SPI_transaction.
    TFT тоже переводят на транзакции.
    Насчет SD и W5200,W5100 не нашел.

    В старых АрдуиноIDE поддержки SPI_transaction нет.
     
    ИгорьК нравится это.
  10. ИгорьК

    ИгорьК Гуру

    Глядя на это разъяснение, суть проблемы в том, что для разных устройств настройки шины SPI - разные.
    Не сталкивался с этим, поскольку, видимо, они скрываются в недрах используемых библиотек.
    Как мне видится (не уверен до конца), появление SPI_transaction мало поможет среднему крестьянину, поскольку, хотя и предоставляет возможность одновременного конфигуирования разных устройств, но для этого, посути, придется слишком сильно ковырять те библиотеки, которые мы раньше воспринимали как даность.
     
  11. BGreen

    BGreen Нерд

    Несколько устройств на SPI - необходимость.
    Например, игрушка "сканер wifi". NRF24 + TFT экранчик, где покажет график занятых частот или "водопад". Можно еще и SD-карту прицепить.. Уже реализовано http://forum.rcdesign.ru/f8/thread397991.html

    microSD card adapter Catalex
    Это беда на колесах.

    В качестве level-shifter стоит SN74LVC125A от TI.

    Ножки OE данного чипа повешены на GND намертво. Поэтому чип всегда активен и транслирует входы-выходы постоянно. То есть, его входы всегда 0 или 1. Это мешает другим SPI-устройствам дергать ножки.
    На осциллографе видно, как SD+LVC125A отключается от шины и фиксирует ноги в 0 или 1 жестко, что ничем не передавить. Я заметил это по D13 светодиоду, он еле светит после работы SD, т.е. SPI_SCK прижимается в 0.

    Для перехода SN74LVC125A в высокоимпедансное состояние нужно на все OE подать VCC. А никак, ножки на GND напаяны.

    Буду ковырять чип и паять сверху тонкие проводки. Потом напишу результат.

    [​IMG]
     
  12. BGreen

    BGreen Нерд

    NFR24L01 и TFT 2.2" ILI9341 на шине SPI друг другу не мешают электрически.
    Т.е. 2 устройства висят на шине. По очереди заливают программы для NRF или TFT - работает.
    Когда совместно пытаюсь запустить, то второе устройство не работает. Надо разбираться, может, сделать SPI-транзакции или как-то хитро дергать SS/CS с командами SPI.write(***). Чтобы ножки отбросили.
     
  13. ИгорьК

    ИгорьК Гуру

    Если второе не работает, можно предположить, что NRF не позволяет заваливать какую-то шину в ноль, когда ее сигнал CS в единице. Эта шина, скорее всего, MISO. Видимо там подтяжка низкоомная. Так, предположения...
     
  14. nifigasebe

    nifigasebe Нуб

    Добрый день. Помогите разобраться, третий день победить не могу.

    У меня есть Arduino Uno и Arduino Leonardo Ethernet. Я подключаю модули как на картинке, заливаю скетч GettingStarted из примеров библиотеки RF24 и ничего не работает. Тишина с одной стороны и Failed с другой. Что я делаю не так ? В чем может быть проблема ?

    [​IMG]
     
  15. ИгорьК

    ИгорьК Гуру

    Проблема в том, что Вы ничего не делаете - иначе Вы бы об этом написали.
     
    shpock, zaynus и BGreen нравится это.
  16. nifigasebe

    nifigasebe Нуб

    Да я уже не знаю чего делать. Я кучу всего перепробовал и перепроверил. Сначала я долго заморачивался со своим кодом, потом убрал все лишнее оставил только пересылку, потом прочитал эту ветку форума и переделал то что написал. От безнадеги менял модули местами, менял провода которыми они подрубаются. Менял скорость и каналы, но ничего не помогает.
     
  17. ИгорьК

    ИгорьК Гуру

    Больше чем написано в этой ветке сложно добавить. Если коротко,
    Убедитесь в том, что соединение верное - загрузите скетч сканера и убедитесь, что связь между модулем и ардуино функционирует правильно в каждом случае. Если этого не происходит - ошибка в соединении или полностью неисправный модуль.
    После этого последовательно загружайте примеры из библиотек и смотрите на их работоспособность.
    Ну и от напайки конденсатора не уйти - проверено многократно.
     
    nifigasebe нравится это.
  18. nifigasebe

    nifigasebe Нуб

    Запустил сканер на двух ардуинках. Вроде работает, хотя я смутно представляю критерии работоспособности :) Но ни мои скетчи, ни примеры из RF24, ничего не работает.

    Arduino Uno:

    Код (Text):
    STATUS         = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    RX_ADDR_P0-1     = 0xe7e7e7e7e7 0xc2c2c2c2c2
    RX_ADDR_P2-5     = 0xc3 0xc4 0xc5 0xc6
    TX_ADDR         = 0xe7e7e7e7e7
    RX_PW_P0-6     = 0x00 0x00 0x00 0x00 0x00 0x00
    EN_AA         = 0x00
    EN_RXADDR     = 0x02
    RF_CH         = 0x4c
    RF_SETUP     = 0x07
    CONFIG         = 0x0f
    DYNPD/FEATURE     = 0x00 0x00
    Data Rate     = 1MBPS
    Model         = nRF24L01+
    CRC Length     = 16 bits
    PA Power     = PA_MAX
    00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777

    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

    00000003336533442220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000003434535675430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000002244447334120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000004542443557220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000006533345543451111000000101010010000100001100201000000000000000000000000000000000000000000000000000000000000000000000000000
    Arduino Leonardo Ethernet:

    Код (Text):
    STATUS         = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    RX_ADDR_P0-1     = 0xe7e7e7e7e7 0xc2c2c2c2c2
    RX_ADDR_P2-5     = 0xc3 0xc4 0xc5 0xc6
    TX_ADDR         = 0xe7e7e7e7e7
    RX_PW_P0-6     = 0x00 0x00 0x00 0x00 0x00 0x00
    EN_AA         = 0x00
    EN_RXADDR     = 0x02
    RF_CH         = 0x4c
    RF_SETUP     = 0x07
    CONFIG         = 0x0f
    DYNPD/FEATURE     = 0x00 0x00
    Data Rate     = 1MBPS
    Model         = nRF24L01+
    CRC Length     = 16 bits
    PA Power     = PA_MAX
    00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777

    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

    00000002223324243200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000003145646654210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000102244613434220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000111222212221200000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000104534224343330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000002112222333421000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000001224332222200000000000000001100000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000002232212213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000114232222322320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    00000001132311123211000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
     
  19. ИгорьК

    ИгорьК Гуру

    Выдерните модуль, запустите скетч и сравните те же картинки. Почувствуйте разницу.

    Изучите глубже вот это сообщение: http://forum.amperka.ru/threads/nrf24l01-побеждаем-модуль.3205/page-26#post-54569

    И самое первое сообщение в ветке.
     
  20. nifigasebe

    nifigasebe Нуб

    Спасибо за помощь.
    А будет работать, если я возьму Конденсаторы электролитические на 10 мкФ которые идут в наборе Матрешка Z ?