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

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

  1. Lagvin

    Lagvin Нерд

    Это продолжение темы "Умная жерлица"
    Передатчики работать одновременно будут (хотя одновременные поклевки случаются крайне редко, но надеюсь будут:))
    Также попробовал с библиотекой radiohead - ничего не понял и ковыряю тут.
    И на сегоднешний день похвастаться нечем, а скоро зима.
    Посмотрел уроки Дмитрия Осипова - программы написал вручную с образца и ничего.
    Молчат мои модули.

    Может выкините ненужное, а мне полезное?
     
  2. Lagvin

    Lagvin Нерд

    И вот что у меня выходит
    негуд.JPG
     
  3. Инженер

    Инженер Нерд

    Странные на мой взгляд настройки автоповтор сообщений и автоподтверждение отключено длинна посылок 32 байта. Ну ладно просто сделай такие настройки на обоих применик и передатчик (только CONFIG должен отличаться) и отправляй 32 байта. Монитором который у тебя запущен ловить посылку бесполезно и даже глупо посылка длится микросекунды и а это время твой монитор может слушать другой канал. У меня на первых этапах несмотря на то что приемник слушал нужный канал очень резко возникал флаг наличия несущей. Делай стразу полноценный прием и передачу данных
     
  4. Lagvin

    Lagvin Нерд

    А как эго сделать этот полноценный прем-передачу?
    Пробовал заливать скетчи приемника(mega) и передатчика(uno) c с примера Дмитрия Осипова там где две кнопки и два светодиода - не работает.

    Может у кого есть альтернативный скетч (на передатчике кнопка- на приемнике светодиод)?
     
  5. Инженер

    Инженер Нерд

    выложи код с кнопкой и светодиодиками гляну
     
  6. Lagvin

    Lagvin Нерд

    Дело в том, что коды находятся на месте работы, так как дома трое детей не дают возможности заняться любимым делом.
    Скину ссылку, там все один к одному(кроме Mega).
     
  7. Инженер

    Инженер Нерд

    У передатчика поставьте radio.powerUp(); и задержку 1.5мс (не знаю как она у вас делается) перед каждым radio.write(msg, 1); и перед radio.openWritingPipe(pipe) пропишите radio.setPayloadSize(1) на всякий случай
    А у приемника radio.setPayloadSize(1); перед radio.openReadingPipe(1,pipe);
    После всего этого в обеих прошивках в конце setup командой radio.printDetails() выведете настроенные параметры в терминал и сюда выложите там уже видно будет что не так настроилось.
    В коде я вижу 2 явные ошибки не задан размер пакета у приемника (а это архиважно) и у передатчика после пробуждения слишком маленькая пауза перед попыткой начала передачи. (150мкс вместо 1.5мс) наверно поэтому у многих тут и "глючат" передатчики. Эта задержка прописана в startWrite, если хотите можите прямо в библиотеке исправить.
     
    Последнее редактирование: 30 мар 2015
  8. Lagvin

    Lagvin Нерд

    Все как-то пока круто написано.
    Если у Вас есть рабочий код для передатчика и приемника может скините, дабы проверить все ли работает?!
    Попутный вопрос: Как удалить библиотеку из Arduino IDE?

    Про ошибки не знаю, он вроде наяву загружал скетч и все работало. ИМХО.

    Совсем забыл спросить
    вопрос:
    Если я работаю на Mega 2560, там пины (9,53) я их прописываю, а остальные как с 50 по 52 они что автоматом ставятся или надо в самой библиотеке менять что-то?
     
  9. zaynus

    zaynus Нерд

    Здравствуйте!
    Largvin,Вы прописываете ce and csn остальные пины - хардварный SPI, (не знаю где они на меге), попробуйте скопировать параметры инициализации (Setup) из моих скетчей на стр. 14(построены на прерывании но для setup это не особо важно).
    "Там много подводных камней" допустим если не прописать AskPayload то не работают.
    Поиграйтесь со скоростью(что бы понять что железо подключено правильно(например если перепутать ce and csn) то prindetails выводит "по умолчанию" 1 Мбит, даже если поставлено 2 или 256
    У меня один модуль из той же партии на скорости 256 не работает только 1 или 2 Мбит.
    Сейчас работают 2 передатчика и 2 приемника на одной трубе с разными интервалами и id.
    Ниже скетч вебсервера на thingspeak (с моими предыдущими работать не будет, немножко переделано)
    Предыдущие скетчи 3 штуки 2 передатчика и 1 приемник - работали почти без проблем)
    Все ловилось, только переменные свои иначе сделал, и поставил startListening в начале loop, дабы затирать предыдущие полученные значения принудительно, если передачи не стало вдруг.
    Когда начал собирать световой костюм с радиоуправлением по миди со startWrite повисало через несколько минут потокового миди, когда исправил на radio.write повисания прекратились.

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

    // Local Network Settings
    byte mac[] = { 0xD4, 0x28, 0xB2, 0xFF, 0xA0, 0xA1 }; // Must be unique on local network
    uint64_t pipe0 =  0xF0F0F0F0E1LL;
    uint64_t pipe1 =  0xF0F0F0F0D2LL;
      uint64_t pipe2 = 0xF0F0F0F0D5LL;
      RF24 radio(7, 8);
    // ThingSpeak Settings
    char thingSpeakAddress[] = "api.thingspeak.com";
    String writeAPIKey = "XXXXXE9I5D2CXIU";
    const int updateThingSpeakInterval = 16 * 1000;      // Time interval in milliseconds to update ThingSpeak (number of seconds * 1000 = interval)

    // Variable Setup
    long lastConnectionTime = 0;
    boolean lastConnected = false;
    int failedCounter = 0;

    // Initialize Arduino Ethernet Client
    EthernetClient client;
    /////////////////////////////////////////
    typedef struct {
        int ID;//main id
      short int B;//tmp
      short int C;//tmp
      short int D;//tmp
      short int S;
      short int T;
      short int U;
      short int V;
      short int W;
      short int X;
      short int Y;
      short int Z;
    }
    B_t;
    B_t message;

    typedef struct {
      short int V;
      short int W;
      short int X;
      short int Y;
      short int Z;
    }
    R_t;
    R_t rget;
    ////////////////////////////////
    short int P = 0;
    short int Temp1 = 0 ;
    short int Temp2 = 0;
    short int Temp3 = 0 ;
    short int Temp4 = 0;
    short int Temp5 = 0 ;
    short int TempHome=0;
    short int Alt=0;
    short int Pressure=0;
    ////////////////////////////////
    void setup()
    {
      // pinMode(7, OUTPUT);                    // установить SS вывод как выходящий
    // digitalWrite(7, HIGH);//down rf24 for wait
      // Start Serial for debugging on the Serial Monitor
      Serial.begin(115200);
      printf_begin();
      radio.begin();
      radio.setRetries(15, 15);
      radio.setChannel(120);
      radio.setPayloadSize(32);
      radio.setPALevel(RF24_PA_MAX);
      radio.setDataRate(RF24_1MBPS);
      radio.openReadingPipe(1, pipe1);
      //radio.openWritingPipe(pipes[0]);
      radio.startListening();
      radio.printDetails();
      radio.enableAckPayload();
    // radio.setAutoAck(false);
      radio.powerUp();
      //attachInterrupt(0, check_radio, FALLING);
      // Start Ethernet on Arduino
      startEthernet();
    }

    void loop()
    {
      radio.startListening();
      delay (30);
            //attachInterrupt(0, check_radio, FALLING);
            if (  radio.available()  )
            {
            // Serial.println("get payload");
    radio.read( &message, sizeof(message) );
    //Serial.println("reading RF");
    if(message.ID==31240)
    {
    P = message.S ;
    //nagr1 =  message.T ;
    //nagr2 =  message.U  ;
    Temp1 =  message.V  ;
    Temp2 = message.W  ;
      Temp3 = message.X  ;
    // Temp4 = message.Y;
      Temp5 = message.Z ;//ulitsa
    }
    else if (message.ID==31241)
    {
    TempHome  = message.S ;
    //ALT =  message.T ;
    Pressure  =  message.U  ;
    // =  message.V  ;
    //  = message.W  ;
    //  = message.X  ;
    // = message.Y;
    // = message.Z ;
    }
            }
                    //Serial.println("P=");
            //Serial.println(P);
          // Serial.println("Pressure=");
          // Serial.println(Pressure);
          // Serial.println("TempHome=");
                  // Serial.println(TempHome);

       
      /////////////////////////////////////////////////////////////////////////////
      String nagruzka = String(P);
      String Pres = String(Pressure);
      String Tmp1 = String(Temp2);
      String Tmp2 = String(Temp2);
      String Tmp3 = String(Temp3);
      String TmpH = String(TempHome);
      String TmpUL = String(Temp5);


      // Serial.println(P);


      // Print Update Response to Serial Monitor
      if (client.available())
      {
        char c = client.read();
        Serial.print(c);
      }

      // Disconnect from ThingSpeak
      if (!client.connected() && lastConnected)
      {
        Serial.println("...disconnected");
        Serial.println();

        client.stop();

      }

      // Update ThingSpeak
      if(!client.connected() && (millis() - lastConnectionTime > updateThingSpeakInterval))
      {//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        updateThingSpeak("1="+nagruzka+"&2="+Pres+"&3="+Tmp1+"&4="+TmpH+"&5="+Tmp3+"&6="+TmpUL);
        //updateThingSpeak("field1="+String(P, DEC));
      }

      // Check if Arduino Ethernet needs to be restarted
      if (failedCounter > 3 ) {startEthernet();}

      lastConnected = client.connected();
    }

    void updateThingSpeak(String tsData)
    {
      if (client.connect(thingSpeakAddress, 80))
      {  
        client.print("POST /update HTTP/1.1\n");
        client.print("Host: api.thingspeak.com\n");
        client.print("Connection: close\n");
        client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
        client.print("Content-Type: application/x-www-form-urlencoded\n");
        client.print("Content-Length: ");
        client.print(tsData.length());
        client.print("\n\n");

        client.print(tsData);

        lastConnectionTime = millis();

        if (client.connected())
        {
          Serial.println("Connecting to ThingSpeak...");
          Serial.println();
     
          failedCounter = 0;
        }
        else
        {
          failedCounter++;

          Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");
          Serial.println();
        }

      }
      else
      {
        failedCounter++;

        Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
        Serial.println();

        lastConnectionTime = millis();
      }
    }

    void startEthernet()
    {

      client.stop();

      Serial.println("Connecting Arduino to network...");
      Serial.println();

      delay(1000);

      // Connect to network amd obtain an IP address using DHCP
      if (Ethernet.begin(mac) == 0)
      {
        Serial.println("DHCP Failed, reset Arduino to try again");
        Serial.println();
      }
      else
      {
        Serial.println("Arduino connected to network using DHCP");
        Serial.println();
      }

      delay(1000);
    }

     
     
    Последнее редактирование: 30 мар 2015
  10. zaynus

    zaynus Нерд

    Не знаю как километр у меня со встроенной антенной и 1 Мбит не добивает 30 метров и 2 стены до бани.
     
  11. Lagvin

    Lagvin Нерд

    попробую отпишусь 1.4.2015
     
  12. Инженер

    Инженер Нерд

    Я не пишу в ардуино я пишу на cvavr. Соответственно ардуиновского кода у меня нет. Просто я очень внимательно читал datasheet и экспериментировал. По моему все написано проще некуда найти строчку в коде длинной 1 страница и написать 1-2 строчки выше или ниже.
    У меня работает без этой функции. Вы вероятно прописали setAutoAck(false) если прописать эту команду только на приемнике он ничего не примет, это действительно нюанс меняется формат посылки и приемник ее игнорирует.
    На мой взгляд модули достаточно стабильные для начала работы нужно лишь разбудить оба модуля установить размер пакета на приемнике, и отправить с передатчика столько байт сколько установлено на приемнике. (адреса, каналы, настройки по умолчанию есть и они одинаковы) В "продвинутом режиме" нужно следить чтобы все параметры сети совпадали (номер канала, скорость, размер CRC, и т.д.)
     
    Последнее редактирование: 30 мар 2015
    zaynus нравится это.
  13. zaynus

    zaynus Нерд

    Вы правы, setAutoAck(false) я прописывал на одном приемопередатчике, однако я говорил про radio.enableAckPayload();, без нее у меня не запускалось(возможно тоже на одном писал)
    про формат посылок особо не заморачивался(собственно и преимущества человека пишущего на СИ, в корень зрит товарищ :) )Кстати enableAckPayload() кидает в ответ 3 AckPayload посылки(вроде у maniacbag про это написано и он не знает почему так)
     
  14. Инженер

    Инженер Нерд

    Почему-то никто не использует одну из главных фишек nrf24l01+ версии. Динамическую длину посылки. Всего то нужно radio.enableDynamicPayloads() в setup (у приемника и передатчика) После получения посылки на приемнике, перед чтением буфера getDynamicPayloadSize() вернет размер полученной посылки. Кстати приемник может быть настроенным по старинке на работу со статическим буфером и посылки будут доходить.
     
  15. zaynus

    zaynus Нерд

    Пока что руки не дошли(спасибо за напоминание)
    Надеюсь, когда нибудь соберемся и напишем вики по этим модулям, со всеми граблями и на русском :rolleyes:
     
    Последнее редактирование: 31 мар 2015
  16. geher

    geher Гуру

    Почему никто? Я использую.
     
  17. zaynus

    zaynus Нерд

    если 2 передатчика на одной трубе кидают разных размеров пакеты(radio.enableDynamicPayloads()) в 1 приемник, а приемник посылает конфиг одному из передатчиков то идут траблы(у меня по крайней мере) кто нибудь еще проверял такую конфигурацию?
     
  18. Инженер

    Инженер Нерд

    В чем траблы то? Надеюсь все участники сети имеют (radio.enableDynamicPayloads()) ? проверь
     
  19. zaynus

    zaynus Нерд

    Код (Text):
    typedef struct {
    volatile  int ID ;//main id
    volatile  short int B;//tmp
    volatile short int C;//tmp
    volatile  short int D;//tmp
    volatile  short int S;//nagruzka
    volatile  short int T;//ustanovka otsechki 1
    volatile  short int U;//ustanovka otsechki 2
    volatile  char V;//temperatury dathikov
    volatile  char W;//temperatury dathikov
    volatile  char X;//temperatury dathikov
    volatile  char Y;//temperatury dathikov
    volatile char Z;//temperatury dathikov
    }
    B_t;
    B_t message;//структура принимаемая приемником


    typedef struct {
    volatile  short int V;//ustanovka otsechki 1
    volatile  short int W;//ustanovka otsechki 2
    volatile  short int X;main id
    volatile  short int Y;
    volatile short int Z;
    }
    R_t;
    R_t rget;//структура отправляемая в ответ
     

    Код (Text):

     EEPROM_read(32, rget);//часть кода из передатчика
      P1 = rget.V;
      P2 = rget.W;
    message.T = P1;
      message.U = P2 ;
    ////,,,,,,,,,//////
    if ( rx )
      {
           Serial.println("Read askPayload");
        radio.read( &rget, sizeof(rget));
      if( rget.X == 31312)
      {
        if  ((P1 != rget.V) || (P2 != rget.W))
    int temp = rget.V;
        Serial.println("rget:");
        Serial.println(temp);
        {
          EEPROM_write(32, rget);
          Serial.println("Memory writed");
    каким то образом message.T в передатчике
    становится равным rget.X(31312) потом нулю, потом 2260(установленное значение)
    и так по кругу хаотично, скетчи сдесь же на 14 стр(1-барометр,2-приемник,3-злополучный передатчик). переделаны малость в т.ч. включено enableDynamicPayloads(), и немного урезал размер с int до char
    а radio.setPayloadSize(32); убрано вообще
    Как будто словив посылку n байт он тут же не может словить посылку другого размера
    Сейчас откатился на прошлую версию
     
  20. Инженер

    Инженер Нерд

    Давай думать логически у тебя все пакеты были 32 байт, что что не используется забито нулями/мусором
    Ты включаешь динамический размер пакета и начинаются проблемы очевидно ты не до конца читаешь/передаешь какой то пакет. Либо отправляешь пакет не до конца либо из буфера приемника читаешь не до конца. а вообще код смотреть нужно, для того чтобы программа глючила достаточно 1 лишнего знака