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

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

  1. Un_ka

    Un_ka Гуру

    Atmega 328, или ch340( с него берётся 3,3 вольта в НАНО, причём максимальный ток где-то 100 с чем-то миллиампер), или что-то ещё греется?
     
  2. b707

    b707 Гуру

    Kot26ru я так понял. что сейчас аппаратные проблемы...
    Но вообще, код приемника. приведенные выше - опять совершенно не рабочий.
    такое впечатление. что вы вообще не понимаете логики радио обмена
    Работает так, как написано. посмотрите в свой код. вы как только пришло первое сообщение - сразу же его в цикле читаете 4 раза и заполняете одними и теми же данными весь массив
     
  3. Kot26ru

    Kot26ru Гик

    Atmega 328
     
  4. Kot26ru

    Kot26ru Гик

     
  5. Kot26ru

    Kot26ru Гик

    согласен, но:
    подразумевается, что после принятия пакета уйдет назад ответ передатчику. Передатчик получив ответ закинет пакет с новыми данными. Такой был план. Согласен, что код сырой, но говорю же - учусь только. Вы совершенно правы, что так как написано сейчас - массив "забъется" одними и теми же координатами. Надо бы условие проверки добавить. Я просто еще не придумал какое. Для понимания моей задумки ниже код передатчика
    Код (C++):
    #include <avr/wdt.h>
    #include <avr/sleep.h>

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

    #define CNT 1                       // количество циклов по 8 секунд между "посылками" (время между посылками = 8*CNT секунд)
    #define NumArt 4                    // количество артов

    #define PIN_CE 9                   // Номер пина Arduino, к которому подключен вывод CE радиомодуля
    #define PIN_CSN 10                   // Номер пина Arduino, к которому подключен вывод CSN радиомодуля

       
    uint8_t count;                      //переменная для счётчика циклов
    volatile boolean wdt_tripped=1;

    struct ArtMessage{                  // структура данных посылки
    uint8_t id;
    int32_t Lat;
    int32_t Long;
    };                    

    ArtMessage art[NumArt];             // создаем массив артов

    // вывод на экран
    #define printArt() \              
    Serial.print(F("Передача Арта[")); \
    Serial.print(art[i].id); \
    Serial.println(F("]:")); \
    Serial.print(art[i].Lat); \
    Serial.print(F(", ")); \
    Serial.print(art[i].Long);

    RF24 radio(PIN_CE, PIN_CSN);            // Создаём объект radio с указанием выводов CE и CSN

    const uint64_t pipe_Write = 0x7878787878LL;   // адрес трубы для передачи
    //const uint64_t pipe_Read = 0xE8E8F0F0ABLL;     // адрес трубы для приема

    bool rx_respond;                        // переменная для сбора обратного сообщения от приемника

    //режим сна для МК
    void system_sleep() {
      delay(2);
      _SFR_BYTE(ADCSRA) &= ~_BV(ADEN);      // Switch ADC off
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sleep_enable();
      sleep_mode();                         // System sleeps here
      sleep_disable();
      _SFR_BYTE(ADCSRA) |= _BV(ADEN);       // Switch ADC on
    }

    void wdt_interrupt_mode() {
      wdt_reset();
      WDTCSR |= _BV(WDIE);                  // Restore WDT interrupt mode
    }

    ISR(WDT_vect) {
      wdt_tripped=1;                        // set global volatile variable
    }

    void sendArtMessage(uint8_t temp) {                 // отправить сообщение по RF24
      do {
        rx_respond=false;
        radio.write(&art[temp],sizeof(art[temp]));        // Передаём по радиоканалу
        delay (20);
        if (radio.isAckPayloadAvailable()) {        
        radio.read(&rx_respond,sizeof(rx_respond));   // получаем ответ от приемника
        delay (20);
        }
      } while (rx_respond=false);                          // Ждем подтверждения от приемника
    }
    void setup(){

    wdt_disable();
    wdt_reset();
    wdt_enable(WDTO_8S);   //пробуждение каждые 8 сек
    count = 0;

    // заполняем массив артов
    art[0] = {1, 5575, 59938732};
    art[1] = {2, 487081906, 56328571};
    art[2] = {3, 472213858, 446245814};
    art[3] = {4, 450433245, 450352566};

    Serial.begin(9600);                           // Инициализация серийного порта для отладки

    radio.begin();                                // Старт RF24
    if (!radio.begin()) {                         // если радиомодуль не запустился
    Serial.println(F("Радиомодуль не отвечает"));
    while (1) {}                                 // ждем когда запустится радиомодуль
    }

    radio.setPayloadSize(10);                     // задаем объем посылки в байтах
    radio.setChannel(5);                          // Обмен данными будет вестись на пятом канале (2,405 ГГц)
    radio.setRetries(0,5);                        // Кол-во попыток отправить данные
    radio.setDataRate (RF24_1MBPS);               // Скорость обмена данными 1 Мбит/сек
    radio.setPALevel(RF24_PA_HIGH);               // Выбираем высокую мощность передатчика (-6dBm)
    radio.setCRCLength(RF24_CRC_8);              
    radio.enableAckPayload();
    radio.openWritingPipe(pipe_Write);            // открываем трубу передачи
    //radio.openReadingPipe(1,pipe_Read);           // открываем трубу приема
    radio.stopListening();                        // отключаем режим приёма
    }

    void loop(){
    //тут можно увеличить интервал времени между отправками данных по RF24 за счёт счётчика циклов
    wdt_interrupt_mode();

    if (wdt_tripped) {
        count++;
        wdt_tripped = 0;

    // отправим данные, если уже "пора"
        if (count == (CNT)) {
          radio.powerUp();                        //подаём питание на NRF24
          delay(20);

        for (uint8_t i=0; i<4; i++) {
          sendArtMessage(i);                      // отправляем посылку
          printArt();
        }
       
        radio.powerDown();                        // отключаем питание RF24
        delay(20);
        count = 0;
        }
    }

    // спать!
    system_sleep();   //МК засыпает
    }
     
  6. b707

    b707 Гуру

    очевидно какое - пришли новые данные или нет
    Сейчас вы проверяете это только перед чтением первого пакета. а потом просто читаете старые данные. не думая вообще. обновились они или нет
     
  7. Kot26ru

    Kot26ru Гик

    условие "if ( radio.available())" это же наличие пакета для приема? а как узнать новый там пакет или старый еще?
     
  8. b707

    b707 Гуру

    библиотека это делает за вас - когда вы читаете пакет функцией read() . условие available() сбрасывается до прихода новых данных
     
  9. parovoZZ

    parovoZZ Гуру

    Так ответ уходит или нет?

    Раз обмен идёт, значит передатчик всё ж получает ACK ответ. Иначе передатчик встанет на прерывании "переполнение TX буфера". Дуринщикам кажется, что nRF24 зависла. А всего-то надо очистить буфер.
     
  10. parovoZZ

    parovoZZ Гуру

    это не библиотека делает, а сама nRF24. При чтении RX буфера он очищается аппаратно.
     
  11. Kot26ru

    Kot26ru Гик

    Теперь понятно, Спасибо. Такая запись будет корректна?
    Код (C++):
    void loop(){
    if ( radio.available()) {
    Serial.println(F("Пришла посылка"));  
    if (i<4) {
       art[i] = receivArtMessage();      // заполняем арт из принятой посылки
       lsd_Art();                        // выводим на ЖКИ
       i++;
       delay (500);
    }
    else {
      Serial.println(F("Массив артов заполнен"));
      delay (500);
    }
    }
    }
     
  12. b707

    b707 Гуру

    не путай человека. приемный массив в клиентской программе не очищается. в нем остаются старые данные
     
  13. b707

    b707 Гуру

    не люблю оценивать код по маленькому кусочку.
    тут вроде все нормально. если не считать того. что принять набор сообщений вы сможете только один раз...
     
  14. Kot26ru

    Kot26ru Гик

    ну потом же приемник отправит ответ передатчику, что посылка принята и тот сменит пакет на новый. И соответственно условие "if( radio.available())" снова запустит процесс чтения. Так же?
     
  15. Kot26ru

    Kot26ru Гик

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

    #include <Wire.h>                 // Библиотека для работы с шиной 1-Wire
    #include <LiquidCrystal_I2C.h>    // Библиотека для работы с ЖКИ

    #define NumArt 4                    // количество артов

    #define PIN_CE 9                   // Номер пина Arduino, к которому подключен вывод CE радиомодуля
    #define PIN_CSN 10                   // Номер пина Arduino, к которому подключен вывод CSN радиомодуля

    uint8_t i=0;

    struct ArtMessage{                  // структура данных посылки
    uint8_t id;
    int32_t Lat;
    int32_t Long;
    };  

    ArtMessage art[NumArt], tx_send;             // создаем массив артов

    // вывод на ЖКИ
    #define lsd_Art() \
    lcd.setCursor(0,0); \
    lcd.print("ART["); \
    lcd.print(art[i].id); \
    lcd.print("]="); \
    lcd.setCursor(0,1); \
    lcd.print(art[i].Lat); \
    lcd.print(", ");\
    lcd.print(art[i].Long); \

    LiquidCrystal_I2C lcd(0x27,16,2);       // создаем ЖКИ

    RF24 radio(PIN_CE, PIN_CSN);            // Создаём объект radio с указанием выводов CE и CSN

    //const uint64_t pipe_Write = 0xE8E8F0F0ABLL;   // адрес трубы для передачи
    const uint64_t pipe_Read = 0x7878787878LL;    // адрес трубы для приема

    ArtMessage receivArtMessage() {         // получить сообщение по RF24
    radio.read(&tx_send,sizeof(tx_send));        // получаем пакет
    delay (20);
    bool rx_respond = true;                      // сообщение ответа передатчику
    radio.writeAckPayload( 1, &rx_respond, sizeof(rx_respond) );  // Грузим сообщение для автоотправки
    delay (20);
    return tx_send;
    }

    void setup(){
    Serial.begin(9600);                           // Инициализация серийного порта для отладки

    lcd.init();
    lcd.clear();
    lcd.backlight();                    // Включаем подсветку


    bool result = radio.begin();                      // Старт RF24
    delay (300);
    Serial.println(result);
    //radio.printDetails();
    if (!radio.begin()) {               // если радиомодуль не запустился
      Serial.println(F("Радиомодуль не отвечает"));
     
      while (1) {
        lcd.print("RADIO OFF");
        delay (100);
        lcd.clear();
        delay (100);
        }                       // ждем когда запустится радиомодуль
    }
       
    radio.setPayloadSize(10);           // задаем объем посылки в байтах
    radio.setChannel(5);                // Обмен данными будет вестись на пятом канале (2,405 ГГц)
    radio.setRetries(0,5);              // Кол-во попыток отправить данные
    radio.setDataRate (RF24_1MBPS);     // Скорость обмена данными 1 Мбит/сек
    radio.setPALevel(RF24_PA_HIGH);     // Выбираем высокую мощность передатчика (-6dBm)
    radio.setCRCLength(RF24_CRC_8);              
    radio.enableAckPayload();
    //radio.openWritingPipe(pipe_Write);            // открываем трубу передачи
    radio.openReadingPipe(1,pipe_Read);           // открываем трубу приема
    radio.startListening();                       // включаем режим приёма
    }

    void loop(){
    if ( radio.available()) {
    Serial.println(F("Пришла посылка"));  
    if (i<4) {
       art[i] = receivArtMessage();      // заполняем арт из принятой посылки
       lsd_Art();                        // выводим на ЖКИ
       i++;
       delay (500);
    }
    else {
      Serial.println(F("Массив артов заполнен"));
      delay (500);
    }
    }
    }
     
  16. b707

    b707 Гуру

    я не об этом.
    Вот у вас есть цикл с условием
    Код (C++):
    if (i<4) {
       art[i] = receivArtMessage();      // заполняем арт из принятой посылки
       lsd_Art();                        // выводим на ЖКИ
       i++;
       delay (500);
    }
    4 пакета вы приняли, значение < i >теперь 5. И все, приплыли...
     
  17. parovoZZ

    parovoZZ Гуру

    сова, не вывезешь спор. Читаем даташит:
    upload_2021-3-12_17-11-52.png
    Дословно: после чтения данные из буфера удаляются. Другой команды для чтения буфера в nRF24l01 нет.
     
  18. Kot26ru

    Kot26ru Гик

    ну это же будут 4 разных пакета. Их и должно быть 4. Передатчик каждые 8 секунд в цикле передает 4 пакета. Приемник и должен все 4 принять и записать их в массив. Что я не так делаю?
     
  19. b707

    b707 Гуру

    ты лучше меня читай. полезнее будет :)
    Прочитай внимательнее. что я тебе написал
     
  20. b707

    b707 Гуру

    Вот именно. что передатчик у вас передает пакеты в цикле, а приемник примет 4 пакета и заткнется