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

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

  1. ИгорьК

    ИгорьК Победитель модулей

    Дык... доработайте! Критики, ....ь. :) Я эту тему писал - впервые учебник Сей читал и узнавал что такое плюс и что минус в батарейках.
    Теперь вам и вода не жидкая и мирра не так пахнет...
     
  2. ELRT

    ELRT Нуб

    Доброго всем времени суток. Обращаюсь за помощью. Пытался все прочитать , но так и не осилил.
    На первых страницах вроде обсуждался мой вопрос , но я так и не смог полностью уловить мысли писавших,потому что еще плохо разбираюсь в этом деле.
    Суть в чем : есть 2 радиомодуля nrf24l01. Хочу сделать квадрокоптер на котором установлен датчик давления для расчета высоты. Проблем с передачей данных от джойстика к " мозгам " квадрокоптера с помощью двух этих радиомодулей нет.
    Вопрос в другом : Может ли приемник посылать данные,полученные от датчика давления, передатчику, и что для этого нужно дописать в коде и передатчика и приемника ???
     
  3. rkit

    rkit Гуру

    Выкладывайте весь код и полные схемы со всеми номиналами в новую тему в разделе "закажу проект", и готовьте деньги.
     
  4. ELRT

    ELRT Нуб

    Извините конечно,но когда вас на улице спрашивают дорогу, чтобы пройти к определенному месту , вы тоже с них деньги требуете ?
    Я же не прошу сделать весь проект за меня (причем , что многое у меня уже сделано) , я просто попросил о помощи с модулями: возможно ли так сделать с радиомодулями, и что для этого нужно дописать в коде, так как не полностью разбираюсь в этом деле.
    Ведь это же форум, где люди свободно общаются и помогают друг другу
     
  5. ИгорьК

    ИгорьК Победитель модулей

    Ответ здесь: http://forum.amperka.ru/threads/nrf24l01-побеждаем-модуль.3205/page-2#post-25478

    Ответ на ВТОРОЙ странице. Вы это читали? (Конечно нет! Ведь местные лохи верят на слово!)

    В коде приемника нужно вместо uint32_t message = 111; написать uint32_t message = "полученные от датчика давления" ;
    В коде передатчика следует правильно обработать переменную uint32_t message.

    Уверен, эта информация вам хорошо помогла.

    Нет? Тогда rkit дал вам правильный совет.
     
    Последнее редактирование: 21 авг 2017
  6. rkit

    rkit Гуру

    Лично я с вас денег не требую. Мне такая мелочь не интересна. Все что я сделал, это как раз помог, и как раз указал дорогу, пойдя по которой вы будете иметь максимальный шанс реально решить задачу. И то без гарантии, что кто-то возьмется. А тот путь, который избрали вы, сколько ни возмущайся, и ни приводи примеров про взаимовыручку, и "спросить дорогу", и христианскую мораль, и что угодно, — вас к результату не приведет. Это я вам гарантирую. И вы могли бы догадаться и сами, что это неправильный подход, раз в первый раз он не помог никак.
     
  7. Братья, спасайте, есть к вам много вопросов.... задам первый: как можно усыпить в глубокий сон NRF24L01, вместе с МК (у меня Atmega168), и по действию от брелка (тот же Atmega168 и тот же передатчик) выйти из этого глубокого сна? По прерыванию, но не сторожевым псом! Если знаете, ответьте пожалуйста, очень надо ! Заранее Благодарен!
     
  8. rkit

    rkit Гуру

    nrf24 в глубоком сне сигналов не принимает. Читайте даташит, для начала.
     
  9. А вот как вывести из глубокого сна приёмник, но не используя сторожевого пса? Может есть возможность радиомодуль выключать частями, оставив лишь канал что следит за эфиром, а лучше просто за IRQ?
     
  10. rkit

    rkit Гуру

    Лучше сесть и прочитать даташит, где функционал применика раписан четко, и даже блок-схемы нарисованы. А сидеть и фантазировать ни о чем - очень и очень плохо.
     
  11. b707

    b707 Гик

    Короткий ответ - нельзя. Приемник спать не может, иначе это не приемник.
     
  12. TolTolic

    TolTolic Нуб

    подскажите у меня оба nRF дохлые или только первый?
    nRF1
    [​IMG]
    nRF2
    [​IMG]
    nRF2
    [​IMG]
     
  13. Stas0232

    Stas0232 Нерд

    Как я понимаю есть два способа и оба они заключаются в следующем: После отправки команды на квадрик (выше/ниже) тут же обратно отправлять ответ от квадрика о текущем значении давления. Результат будет немного заторможенным.
    Вариант №1: Взять пример GettingStarted и оттуда вытащить 2 куска кода, где после успешной отправки данных передатчик переходит на короткое время в режим приема и ждет ответа. А приемник после получения данных пытается послать ответ.
    Вариант №2: Есть функция заготовленного ответа при получении данных и в теории достаточно в специально подготовленную переменную просто постоянно пихать текущее значение давления. А еще проще не делать никаких специальных переменных для ответа, а просто кидать адрес той самой переменной, которая и была заведена для хранения давления на квадрике.
     
  14. Worldmaster

    Worldmaster Нуб

    Здравствуйте. Может кто нибудь сможет подсказать в чем проблема.
    Два модуля NRF, основная проблема в том что не приходит подтверждение на трудах 4 и 5.
    на 1,2,3 все нормально.

    Базовый пример использовал со страницы 17 этой ветки. Он немного изменен потому что у меня платформа другая. Также пришлось портировать библиотеку RF24. Но по логике функции соответствуют оригинальной.

    вот инициализация передатчика и отправка сообщения:
    Код (C++):

    // LSB должен идти первым потому что записываем с нуля
    // можно изменить функции в RF24 для разворота
    BYTE pipe0[5] = {0x00, 0xED, 0xDA, 0xEB, 0xFE};
    BYTE pipe1[5] = {0x01, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe2[5] = {0x02, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe3[5] = {0x03, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe4[5] = {0x04, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe5[5] = {0x05, 0xDE, 0xAD, 0xBE, 0xEF};

    BYTE* pipes[6] = {pipe0, pipe1, pipe2, pipe3, pipe4, pipe5};

    int main(void)
    {
    RF24_begin(); // Инициируем работу nRF24L01+
    RF24_setChannel(5);
    RF24_setRetries(5, 15);
    RF24_setDataRate(RF24_250KBPS); // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек
    RF24_setPALevel(RF24_PA_MIN); // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
    RF24_setCRCLength(RF24_CRC_8);
    RF24_enableDynamicPayloads();
    RF24_setAutoAck(TRUE);
    RF24_enableAckPayload();

    while (1) {
        for (channels = 1; channels < 6; channels++) {
            // сбросили счетчик ошибок
            errorcount = 0;

            // переключился но другую трубу
            RF24_stopListening();
            RF24_openWritingPipe(pipes[channels]);

            for (MaxCount = 0; MaxCount < 100; MaxCount++) {
                //delay_us(1000);
                s_counter = 2; // чтобы зайти в цицл
                if (s_counter > 1) {
                    s_counter = 0;
                    ClearArray(TXbuffer, 32);
                    TXbuffer[0] = 0xA2;
                    itoa((char*) (TXbuffer + strlen((const char*) TXbuffer)), MaxCount, 10);
                    memcpypgm2ram(TXbuffer + strlen((const char*) TXbuffer), "|", 1);

                    // отправляем данные
                    int res = SendData(TXbuffer, 32, 5);
                    BYTE received = res == 0 ? 1 : 0;
                    errorcount += !received;
                }
            }
            // отправим гарантированной отправкой рапорт
            ClearArray(TXbuffer, 32);
            TXbuffer[0] = 0xA2;
            memcpypgm2ram((char*) (TXbuffer + strlen((char*) TXbuffer)), " err: ", 5);
            itoa((char*) (TXbuffer + strlen((char*) TXbuffer)), errorcount, 10);
            memcpypgm2ram((char*) (TXbuffer + strlen((char*) TXbuffer)), "\r\n\r\n", 4);
            SendData(TXbuffer, 32, 5);
        }
    }
    }

    // отправляет данные с автоподтверждением
    int SendData(BYTE* data, BYTE len, BYTE reTransCount) {
        while (reTransCount--) {
            // отправляем данные
            RF24_stopListening();
            RF24_write(data, len, 0);

            // ждем автоответ
            UINT16 waittime = 200; // макс 2 мс.
            while (waittime--) {
                delay_us(10);
                if (RF24_isAckPayloadAvailable()) {
                    BYTE cnt = RF24_getDynamicPayloadSize();
                    if (cnt > 0) {
                        BYTE ack[cnt]; // считали ответ
                        RF24_read(ack, cnt);
                        return 0;
                    }
                }
            }
        }
        return -1;
    }
    Инициализация и работа приемника:

    Код (C++):
    // LSB должен идти первым потому что записываем с нуля
    // можно изменить функции в RF24 для разворота
    BYTE pipe0[5] = {0x00, 0xED, 0xDA, 0xEB, 0xFE};
    BYTE pipe1[5] = {0x01, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe2[5] = {0x02, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe3[5] = {0x03, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe4[5] = {0x04, 0xDE, 0xAD, 0xBE, 0xEF};
    BYTE pipe5[5] = {0x05, 0xDE, 0xAD, 0xBE, 0xEF};

    BYTE* pipes[6] = {pipe0, pipe1, pipe2, pipe3, pipe4, pipe5};

    // прием данных из модуля по прерыванию
    void LowISR() {
         if (INTCON3bits.INT2IF) {
            BYTE pipeNum = 0;
            // надо считать данные из модуля
            if (RF24_available(&pipeNum)) {
                BYTE sender = pipeNum; // номер трубы с данными
                DEBUG_LED_OUT = 1;
                pipeNum |= 0xE0; // дополняем своей меткой
                RF24_writeAckPayload(sender, (BYTE*) & pipeNum, 1); // пишем в буфер
                if (countInBuf < 8) {
                    // общий буфер 256 индекс сам переполниться через 8 блоков по 32 байта
                    ringBuffer[writeIndex] = sender; // сохраним номер трубы чтобы вывести потом в терминал
                    RF24_read(&ringBuffer[writeIndex+1], RF24_BUFLEN - 1); // Читаем данные в массив data и указываем сколько байт читать
                    writeIndex += 32;
                    countInBuf++;
                } else {
                    RF24_flush_tx(); // если места в буфере нету то отбросим пакет
                    RF24_flush_rx(); //Clear the two possible interrupt flags with one command
                    RF24_write_one_register(NRF_STATUS, _BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS));
                }
            }
            INTCON3bits.INT2IF = 0;
        }
    }

    void main(void) {
        RF24_begin(); // Инициируем работу nRF24L01+
        RF24_maskIRQ(1, 1, 0); // прерывание если пришли данные    
        RF24_setChannel(5);
        RF24_setRetries(5, 15);
        RF24_setDataRate(RF24_250KBPS); // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек
        RF24_setPALevel(RF24_PA_MIN); // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
        RF24_setCRCLength(RF24_CRC_8);
        RF24_enableDynamicPayloads();
        RF24_setAutoAck(TRUE);
        RF24_enableAckPayload();
       
        RF24_openReadingPipe(1, pipes[1]);
        RF24_openReadingPipe(2, pipes[2]);
        RF24_openReadingPipe(3, pipes[3]);
        RF24_openReadingPipe(4, pipes[4]);
        RF24_openReadingPipe(5, pipes[5]);
       
        RF24_startListening();

        while (1) {
            if (USB_CDC_RC_COUNT() != 0) {
                ProcessUSBCMD();
            }

            if (countInBuf > 0) {
            // считываем пакет из кольцевого буфера
                ReadNextRingBuffer(TXbuffer);
                if (TXbuffer[1] == 0xA2) {
                // разбираем пакет и отправляем в USB терминал
                    BYTE tmp[5];
                    itoa(TXbuffer[0], (char*) tmp);
                    TXbuffer[0] = tmp[0];
                    TXbuffer[1] = ' ';
                    WRITE_TO_USB_CDC(TXbuffer, strlen(TXbuffer));
                }
            }
        }
    }

    /*Считывает очередной блок данных из кольцевого буфера*/
    void ReadNextRingBuffer(BYTE * dest) {
        if (countInBuf > 0) {
            memcpy(dest, (const void*) &ringBuffer[readIndex], RF24_BUFLEN);
            readIndex += RF24_BUFLEN;
            countInBuf--;
        }
    }
    В терминале видно что по всем 5 трубам данные приемником получены. Но вот по какой то причине передатчик не получает ACK_PAYLOAD.
    Что может быть??
    Спасибо.