РЕШЕНО Nrf24l01+ не понятненько работают

Тема в разделе "Проводная и беспроводная связь", создана пользователем Evgeniy2017, 25 июл 2020.

Статус темы:
Закрыта.
  1. Evgeniy2017

    Evgeniy2017 Нерд

    Всем доброго времени суток! Код рабочий, но работает раз, через раз [​IMG]
    Вообщем у меня тип умный дом.
    Пока что побеждаю радио, пока что имеем рабочую регистрацию, и получение инфы от сенсоров.
    Алгоритм получения инфы: База проходиться по массиву, открывает трубу(персональную для каждого сенсора) на отправку туда шлет некий байт "запрос", а сенсор отвечает на общую трубу для информации.
    Сенсор у меня Arduino nano, База NodeMCU 1.0;
    "Проблема" а точнее не правильную работу заметно начиная с двух устройств в схеме.
    Вот так выглядит лог с одним сенсором(черная консоль это сенсор, а порт ардуино иде это база).
    С одним сенсором.png
    Но вот с подключением в сети второго сенсора, начинаются проблемы(первый сенсор с керамикой и електролитом на nrf24l01+, второй просто керамика на nrf'ке) частичные недолеты пакетов то у одного то у друго-го, то все ок, причем все (увидите на логе) повторяется циклично !
    С двумя сенсором.png
    Поскольку второй сенсор сидит на розетке то его лога по выше указанным причинам нету
    Помогите пожалуйста! Ибо хочется верить в проблемы с питанием, но верится с трудом !

    ----

    База:
    Код (C++):
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    #define v_kef 100
    uint8_t id_sensor = 0;
    uint8_t type_sensor = 1;
    RF24 radio(D4, D8);
    struct message {
      uint8_t id;
      uint8_t type;
      uint8_t data;
    };
    struct info_ {
      uint8_t id_sensor;
      uint8_t type_sensor;
      int16_t v_bat;
      uint8_t status_sensor;
      uint8_t signal_lvl;
      uint8_t person_pipe[1][6];
    };
    message rx_data;
    info_ reg_pack;
    //uint8_t v_kef = 100;
    uint8_t pipe = 0;
    //uint8_t address[][6] = {0xAABBCCDD11LL, 0xAABBCCDD22LL, 0xAABBCCDD33LL, 0xAABBCCDD44LL, 0xAABBCCDD55LL};
    uint8_t address[20][6] = {"0Node", "1Node", "2Node", "3Node"}; //0-Заглушка;1-Alarms;2-Reg; 3-Get_data; Another sesors!
    uint8_t pipes_elems() {
      uint8_t memory = sizeof(address) / sizeof(address[0]);
      uint8_t elems = 0;
      if (memory <= 254) {
        for (uint8_t i = 0; i < memory; i++) {
          if (address[i][0] != 0) {
            elems++;
          }
        }
      }
      else {
        Serial.println("ERROR! Size of array more 255 elements!");
      }
      return elems;
    }
    boolean get_info(uint8_t elem) {
    }
    boolean get_data(uint8_t elem) {
      Serial.print("Elem:");
      Serial.print(elem);
      radio.stopListening();
      radio.openWritingPipe(address[elem]);
      boolean tx = false;
      uint8_t data = 101;
      for (uint8_t i = 0; i < 20; i++) {
        tx = radio.write(&data, sizeof(data));
        if (tx) {
          break;
        }
        delay(200);
      }
      radio.startListening();
      if (!tx) {
        Serial.println(" Sensor not talk with me!");
        return false;
      }
      Serial.print(" Sended! ");
      uint8_t i = 0;
      uint8_t pipe = 0;
      while (i < 20) {
        if (radio.available(&pipe)) {
          Serial.print(pipe);
          if (pipe == 3) {
            break;
          }
        }
        i++;
        delay(150);
      }
      if (i < 15) {
        radio.read(&rx_data, sizeof(rx_data));
        Serial.print(" Id: ");
        Serial.print(rx_data.id);
        Serial.print(" Data:");
        Serial.println(rx_data.data);
        return true;
      }
      else {
        Serial.println("Responce not recived!");
        return false;
      }
    }
    void get_data_all() {
      Serial.println("Start polling sensors!");
      if (pipes_elems() > 4) {
        for (uint8_t i = 4; i <= pipes_elems() - 1; i++) {
          get_data(i);
          delay(20);
        }
      }
      else {
        Serial.println("Not found sensors!");
      }
    }
    boolean register_() {
      radio.stopListening();
      Serial.print("Scaning:");
      radio.openWritingPipe(address[2]);
      boolean tx = false;
      uint8_t status_ = 200; //200 - granted!
      for (uint8_t i = 0; i < 15; i++) {
        tx = radio.write(&status_, sizeof(status_));
        if (tx) {
          break;
        }
      }
      radio.startListening();
      if (!tx) {
        Serial.println("not found!");
        return false;
      }
      Serial.println("found!");
      uint8_t pipe_r = 0;
      for (uint8_t i = 0; i < 20; i++) {
        if (radio.available(&pipe_r)) {
          if (pipe_r == 2) {
            break;
          }
        }
        delay(200);
      }
      if (pipe_r != 2) {
        Serial.println("REG cansel, respocne not recived!");
        return false;
      }
      radio.read(&reg_pack, sizeof(reg_pack));
      if (reg_pack.id_sensor != 0 or reg_pack.signal_lvl < 100) {//Verifying..
        Serial.println("Reg cansel, sensor not verifyed!");
        return false;
      }
      Serial.println("Sensor OK! Continue reg him!");
      reg_pack.id_sensor = random(1, 230);
      Serial.print("Him new id is:");
      Serial.println(reg_pack.id_sensor);
      radio.stopListening();
      boolean tx_second = false;
      for (uint8_t i = 0; i < 20; i++) {
        tx_second = radio.write(&reg_pack, sizeof(reg_pack));
        if (tx_second) {
          break;
        }
        delay(10);
      }
      if (!tx_second) {
        Serial.println("Reg error, packet not recived!");
        radio.startListening();
        return false;
      }
      Serial.println("Reg OK!");
      radio.startListening();
      memcpy(address[pipes_elems()], reg_pack.person_pipe[0], sizeof(address[0]));
      return true;
    }
    void setup() {
      Serial.begin(115200);
      radio.begin();
      radio.setAutoAck(true);
      radio.setChannel(120);
      radio.openReadingPipe(1, address[1]);//Alarm pipe
      radio.setAutoAck(1, true);
      radio.openReadingPipe(2, address[2]);//Reg pipe
      radio.setAutoAck(2, true);
      radio.openReadingPipe(3, address[3]);//Data-info pipe
      radio.setAutoAck(3, true);
      radio.openWritingPipe(address[0]);//Trash pipe
      radio.setPALevel (RF24_PA_MAX);
      radio.setDataRate(RF24_1MBPS);
      radio.startListening();
      radio.powerUp();
      delay(100);
      Serial.println();
      Serial.print("Pipes:");
      Serial.println(pipes_elems());
    }

    void loop() {
      if (Serial.available() > 0) {
        String buffer_ = Serial.readString();
        if (buffer_ == "tx") {
          Serial.println("Start sending...");
          get_data_all();
        }
        else if (buffer_ == "reg") {
          Serial.println("Start registering...");
          register_();
        }
      }
    }
    Сенсор:
    Код (C++):
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    #include <EEPROM.h>
    #define key 131
    uint8_t id_sensor = 0;
    uint8_t type_sensor = 1;
    RF24 radio(9, 10);
    struct message {
      uint8_t id;
      uint8_t type;
      uint8_t data;
    };
    struct info {
      uint8_t id_sensor;
      uint8_t type_sensor;
      int16_t v_bat;
      uint8_t status_sensor;
      uint8_t signal_lvl;
      uint8_t person_pipe[1][6];
    };
    message send_data;
    info info_data;
    const uint8_t v_kef = 100;
    uint8_t pipe = 0;
    //uint8_t address[][6] = {0xAABBCCDD11LL, 0xAABBCCDD22LL, 0xAABBCCDD33LL, 0xAABBCCDD44LL, 0xAABBCCDD55LL};
    uint8_t address[4][6] = {"5Node", "1Node", "2Node", "3Node"}; //0-person pipe; 1-alarms; 2-reg; 3-Info;
    void setup() {
      Serial.begin(115200);
      randomSeed(analogRead(0));
      radio.begin();
      radio.setAutoAck(true);
      radio.setChannel(120);
      radio.setRetries(1, 7);
      radio.openReadingPipe(1, address[0]);
      radio.setAutoAck(1, true);
      radio.openWritingPipe(address[3]);
      radio.setDataRate(RF24_1MBPS );
      radio.setPALevel (RF24_PA_MAX);
      //radio.powerUp();
      delay(100);
      if (id_sensor == 0) {
        Serial.println("Sysetm not reg!");
        Serial.println("Starting register...");
        radio.startListening();
        radio.closeReadingPipe(1);
        radio.openReadingPipe(1, address[2]);
        radio.setAutoAck(1, true);
        while (true) {
          Serial.println("Waiting a reg packet!");
          while (true) {
            if (radio.available(&pipe)) {
              if (pipe == 1) {
                Serial.println("Packet resived!");
                break;
              }
            }
            delay(100);
          }
          uint8_t incoming_data = 0;
          radio.read(&incoming_data, sizeof(incoming_data));
          if (incoming_data != 200) {
            Serial.println("Reg not granted!");
            continue;
          }
          Serial.println("Register granted!");
          Serial.println("Configuring packet...");
          float v_batt = 5.5;
          info_data.id_sensor = 0;
          info_data.type_sensor = type_sensor;
          info_data.v_bat = int(v_batt * v_kef);
          info_data.status_sensor = 1;
          info_data.signal_lvl = 250;
          memcpy(info_data.person_pipe[0], address[0], sizeof(info_data.person_pipe[0]));
          Serial.println("Start sending...");
          radio.stopListening();
          radio.openWritingPipe(address[2]);
          boolean send_status = false;
          for (byte i = 0; i < 10; i++) {
            send_status = radio.write(&info_data, sizeof(info_data));
            delay(10);
            if (send_status == true) {
              break;
            }
          }
          radio.startListening();
          if (send_status == false) {
            Serial.println("Send err!");
            continue;
          }
          Serial.println("Responce wait....");
          boolean is_reciv = false;
          for (uint8_t i = 0; i < 20; i++) {
            if (radio.available(&pipe)) {
              if (pipe == 1) {
                is_reciv = true;
                break;
              }
            }
            delay(200);
          }
          if (!is_reciv) {
            Serial.println("Reg ERR, responce not recived!");
            continue;
          }
          Serial.println("Reg OK!");
          radio.read(&info_data, sizeof(info_data));
          id_sensor = info_data.id_sensor;
          Serial.print("My new id:");
          Serial.println(id_sensor);
          radio.closeReadingPipe(1);
          radio.openReadingPipe(1, address[0]);
          radio.setAutoAck(1, true);
          radio.stopListening();
          radio.openWritingPipe(address[3]);
          radio.startListening();
          break;
        }
      }
      radio.powerUp();
    }

    void loop() {
      if (radio.available()) {
        Serial.println("Data recived!");
        uint8_t incoming_data = 0;
        radio.read(&incoming_data, sizeof(incoming_data));
        if (incoming_data == 101) {
          Serial.println("Request on data get!");
          radio.stopListening();
          boolean status_s = false;
          uint8_t i = 0;
          send_data.id = id_sensor;
          send_data.type = type_sensor;
          send_data.data = random(1, 45);
          while (!status_s && i < 20) {
            delay(10);
            status_s = radio.write(&send_data, sizeof(send_data));
            i++;
          }
          if (status_s) {
            Serial.println("Success! Data sended!");
          }
          else {
            Serial.println("Error! Data not sended!");
          }
          radio.startListening();
        }
        else if (incoming_data == 102) {
          Serial.println("Request on info get!");
          radio.stopListening();
          boolean status_s = false;
          uint8_t i = 0;
          float v_batt = 5.5;
          info_data.id_sensor = id_sensor;
          info_data.type_sensor = type_sensor;
          info_data.v_bat = int(v_batt * v_kef);
          info_data.status_sensor = 1;
          info_data.signal_lvl = 250;
          while (!status_s && i < 20) {
            delay(10);
            status_s = radio.write(&info_data, sizeof(info_data));
            i++;
          }
          if (status_s) {
            Serial.println("Success! Data sended!");
          }
          else {
            Serial.println("Error! Data not sended!");
          }
          radio.startListening();
        }
      }
    }
     
    Последнее редактирование модератором: 25 июл 2020
  2. parovoZZ

    parovoZZ Гуру

    От нас чего хочешь?
     
    NikitOS нравится это.
  3. Evgeniy2017

    Evgeniy2017 Нерд

    Из-за чего могут быть такие циклические сбои, на что мне обратить внимание или что исправить ?
     
  4. parovoZZ

    parovoZZ Гуру

    Взять бубен и вызвать радиодуха. Принести ему что-нить в жертву. Авось и поможет беде.
     
  5. Evgeniy2017

    Evgeniy2017 Нерд

    Сойдет в жертву nrf спалить ?
     
  6. parovoZZ

    parovoZZ Гуру

    Я в принципе отказался от nRF. Ну их в пень.
     
  7. Evgeniy2017

    Evgeniy2017 Нерд

    Все таки не так вопрос поставил) Я хочу узнать почему оно сбоит цыклически ! Оно работает раз через раз, но работает ведь! Так почему же все таки сбоит :(
     
  8. Un_ka

    Un_ka Гуру

    Код (C++):
    for (uint8_t i = 0; i < 20; i++) {
        tx = radio.write(&data, sizeof(data));
        if (tx) {
          break;
        }
        delay(200);
      }
    Зачем 20 раз посылать по икс раз? Это уже есть в библиотеке и настраивается при инициализации
    Код (C++):
    radio.setRetries(0, 15);     // (время между попыткой достучаться, число попыток)

    Код (C++):
    while (i < 20) {
        if (radio.available(&pipe)) {
          Serial.print(pipe);
          if (pipe == 3) {
            break;
          }
        }
        i++;
        delay(150);
      }
    Я жду по-другому:
    Код (C++):
    while ( ! radio.available() && ! timeout ) {
        if ( wait_answ <= millis() ) {
          timeout = true;
        }
      }
      if ( timeout )
      {
        Serial.print("Failed, response timed out.\n");
      }
      else
      {

        //uint8_t len = radio.getDynamicPayloadSize();
        radio.read( &telem, sizeof(telem));              // чиатем входящий сигнал
    Периодическая потеря связи является , скорее всего, следствием нарушения синхронизации между посланием и ответом. Об Autoask думали?
     
  9. parovoZZ

    parovoZZ Гуру

    Во многих протоколах существует процедура перезапроса. Даже тех, что работают по проводам. Снижение скорости работы Wi-Fi есть следствие потери пакетов. Так что вопрос твой риторический.
    Работай на частоте 869МГц. Там пока чисто. Если необходимо гарантированно доставить пакет, то это LoRa и подобное с обязательной коррекцией ошибок.
     
  10. Evgeniy2017

    Evgeniy2017 Нерд

    Думал, но ведь у сенсора постоянно изменяются данные, и как понимаю нельзя изменять те данные которые были записаны в пакет.
    Возможно стоит просто отключить autoack? Ведь я все равно могу ждать ответ не взирая на то отправился ли он или нет. И это освободит радио эфир.
    Специально для этого сижу на 120 канале тобиж я уже возможно ушел от шума роутера на 2.4 я то уже на 2.5 где-то =)
    Хотя я понимаю что не желательно юзать такую частоту, но просто уже затарился такими модулями =(
    Да, но я хотел потом считать качество связи как в Ajax(не реклама). И для этого мне нужно было знать сколько попыток сделала база чтоб достучаться, и потом посчитать силу сигнала(поле в структуре уже выделено).
     
  11. Un_ka

    Un_ka Гуру

    Тогда не забудьте установить
    Код (C++):
    radio.setRetries(0, 1);
     
  12. parovoZZ

    parovoZZ Гуру

    nRF не отдаёт силу сигнала. Не обучено.


    Я их тоже пару купил на LCSC какие-то брендовые. Резюме такое - диапазон в 2.4 ГГц абсолютно не подходит под радиовещание на малых мощностях и дальние расстояния. Либо 16 дБм и получаем дальности, сопоставимые с Wi-Fi, или же 0 дБм и это джойстики, мышки и прочая кухонная утварь.
     
  13. Evgeniy2017

    Evgeniy2017 Нерд

    Да думал, тип какой нибудь алгоритм тип тест на 15 секунд за который там база отсылает 150 пакетов, а потом сенсор отвечает сколько он принял. И тогда например простой пропорцией можно сказать что в данный момент вроде все ок или не ок.
    Да тут полностью согласен, но для моей квартиры при условии что база будет в коридоре, все будет ок и к каждой комнате максимум 2 бетонные стены которые не должны быть ему преградой ( я уже тестил вроде связь норм)
    UPD:
    Про бывал новый код и... не чего =(
    База
    Код (C++):
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    RF24 radio(D4, D8);
    struct message {
      uint8_t id;
      uint8_t type;
      uint8_t data;
    };
    struct info_ {
      uint8_t id_sensor;
      uint8_t type_sensor;
      int16_t v_bat;
      uint8_t status_sensor;
      uint8_t signal_lvl;
      uint8_t person_pipe[1][6];
    };
    message rx_data;
    info_ reg_pack;
    uint8_t address[20][6] = {"0Node", "1Node", "2Node", "3Node", "5Node", "9Node"}; //0-Заглушка;1-Alarms;2-Reg; 3-Get_data; Another sesors!
    void radio_init() {
      radio.begin();
      radio.setAutoAck(true);
      radio.setChannel(120);
      radio.openReadingPipe(1, address[1]);
      radio.setAutoAck(1, true);
      radio.openReadingPipe(2, address[2]);//Reg pipe
      radio.setAutoAck(2, true);
      radio.openReadingPipe(3, address[3]);//Data-info pipe
      radio.setAutoAck(3, true);
      radio.openWritingPipe(address[0]);//Trash pipe
      radio.setRetries(3, 15);
      radio.setPALevel (RF24_PA_LOW);
      radio.setDataRate(RF24_250KBPS);
      radio.startListening();
      radio.powerUp();
    }
    boolean get_data_all() {
      radio_init();
      radio.stopListening();
      radio.powerUp();
      radio.openWritingPipe(address[4]);
      uint8_t data = 101;
      boolean tx = radio.write(&data, sizeof(data));
      Serial.print("TX status:");
      Serial.println(tx);
      radio.startListening();
      uint8_t i = 0;
      while (i < 15) {
        if (radio.available()) {
          break;
        }
        i++;
        delay(150);
      }
      if (i == 15) {
        Serial.println("1 sensor ban =(");
      }
      else {
        message rx_firsth;
        Serial.print("Data recived! ");
        radio.read(&rx_firsth, sizeof(rx_firsth));
        Serial.print("Id:");
        Serial.print(rx_firsth.id);
        Serial.print(" Data:");
        Serial.print(rx_firsth.data);
      }
      delay(150);
      radio.stopListening();
      radio.powerUp();
      radio.openWritingPipe(address[5]);
      uint8_t data2 = 101;
      boolean tx2 = radio.write(&data2, sizeof(data2));
      Serial.print("TX2 status:");
      Serial.println(tx2);
      radio.startListening();
      uint8_t i2 = 0;
      while (i2 < 15) {
        if (radio.available()) {
          break;
        }
        i2++;
        delay(150);
      }
      if (i2 == 15) {
        Serial.println("2 sensor ban =(");
      }
      else {
        message rx_two;
        Serial.print("Data recived! ");
        radio.read(&rx_two, sizeof(rx_two));
        Serial.print("Id:");
        Serial.print(rx_two.id);
        Serial.print(" Data:");
        Serial.print(rx_two.data);
      }
      return true;
    }
    void setup() {
      Serial.begin(115200);
      radio_init();
    }

    void loop() {
      if (Serial.available() > 0) {
        String buffer_ = Serial.readString();
        if (buffer_ == "tx") {
          Serial.println("Start sending...");
          get_data_all();
        }
      }
    }
    Сенсор
    Код (C++):
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    RF24 radio(9, 10);
    uint8_t id_sensor = 10;
    uint8_t type_sensor = 1;
    struct message {
      uint8_t id;
      uint8_t type;
      uint8_t data;
    };
    struct info_ {
      uint8_t id_sensor;
      uint8_t type_sensor;
      int16_t v_bat;
      uint8_t status_sensor;
      uint8_t signal_lvl;
      uint8_t person_pipe[1][6];
    };
    message rx_data;
    info_ reg_pack;
    uint8_t address[20][6] = {"0Node", "1Node", "2Node", "3Node", "5Node", "9Node"}; //0-Заглушка;1-Alarms;2-Reg; 3-Get_data; Another sesors!
    void radio_init() {
      radio.begin();
      radio.setAutoAck(true);
      radio.setChannel(120);
      radio.openReadingPipe(1, address[4]);
      radio.setAutoAck(1, true);
      radio.openWritingPipe(address[3]);
      radio.setRetries(3, 15);
      radio.setPALevel (RF24_PA_LOW);
      radio.setDataRate(RF24_250KBPS);
      radio.startListening();
      radio.powerUp();
    }
    void setup() {
      Serial.begin(115200);
      radio_init();
    }

    void loop() {
      if (radio.available()) {
        uint8_t lol = 0;
        radio_init();
        delay(10);
        radio.read(&lol, sizeof(lol));
        Serial.println("Radio available!");
        radio.stopListening();
        radio.powerUp();
        radio.openWritingPipe(address[3]);
        message mess;
        mess.id = id_sensor;
        mess.type = type_sensor;
        mess.data = (uint8_t)random(1, 20);
        boolean tx = radio.write(&mess, sizeof(mess));
        Serial.print("Send status:");
        Serial.println(tx);
        radio.startListening();
      }
    }
     
    Последнее редактирование: 28 июл 2020
  14. Evgeniy2017

    Evgeniy2017 Нерд

    :rolleyes: УХУ проблема решена вообщем надо было отключить autoAck! !!!!!!!!!!
     
Статус темы:
Закрыта.