NRF24L01 прием/передача

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Всем доброго дня! В среде программирования ардуино не долго, поэтому не серчайте, если буду тупить) 

Хотел спросить у Вас вот чего, есть сеть состоящая из NRF24L01 по топологии звезда, как в даташите. Задача стоит показать прием/передачу каждого модуля. Написал прогу, но работает все не так, как бы хотелось. Суть работы в двух словах: каждый TX находится в состоянии приема, с нажатием кнопки начинает слать данные с номером модуля куда их передать, RX в свою очередь принимая определенный номер должен отослать данные на этот самый модуль. Так вот момент передачи данных работает, приема центром и отсылки тоже, а прием на конечном узле  - нет. В чем косяк подскажите, если не трудно.

Код TX:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); 
byte massiv[1];
byte massiv2[1];
uint8_t        pipe;                                           

void setup() {
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(18, OUTPUT);
  pinMode(19, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  pinMode(4, INPUT);
  radio.begin();
  radio.setChannel(5);                                       
  radio.setDataRate     (RF24_1MBPS);                        
  radio.setPALevel      (RF24_PA_HIGH);                      
  radio.openReadingPipe (0, 0xAABBCCDD66LL);                 
  radio.openReadingPipe (1, 0xAABBCCDD11LL);                
  radio.openReadingPipe (2, 0xAABBCCDD22LL);                
  radio.openReadingPipe (3, 0xAABBCCDD33LL);               
  radio.openReadingPipe (4, 0xAABBCCDD44LL);                
  radio.openReadingPipe (5, 0xAABBCCDD55LL);                
  radio.startListening  ();                                 
}

void loop() {
  if (radio.available(&pipe))
  {
    radio.read(massiv, 1);

    if (massiv[0] == 1) 
    {
      radio.stopListening();
      massiv2[0] = 11;
      radio.write(massiv2, 1);
      digitalWrite(2, HIGH);
      delay(1000);
    }
    if (massiv[0] == 2)
    {
      radio.stopListening();
      massiv2[0] = 22;
      radio.write(massiv2, 1);
      digitalWrite(7, HIGH);
      delay(1000);
    }
    if (massiv[0] == 3)
    {
      radio.stopListening();
      massiv2[0] = 33;
      radio.write(massiv2, 1);
      digitalWrite(8, HIGH);
      delay(1000);
    }
    if (massiv[0] == 4)
    {
      radio.stopListening();
      massiv2[0] = 44;
      radio.write(massiv2, 1);
      digitalWrite(3, HIGH);
      delay(1000);
    }
    if (massiv[0] == 5)
    {
      radio.stopListening();
      massiv2[0] = 55;
      radio.write(massiv2, 1);
      digitalWrite(18, HIGH);
      delay(1000);
    }
    if (massiv[0] == 6)
    {
      radio.stopListening();
      massiv2[0] = 66;
      radio.write(massiv2, 1);
      digitalWrite(19, HIGH);
      delay(1000);
    }
  }
}

Код RX:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); 

byte massiv[1];
byte massiv2[1];

int switchPin = 4; 

int val;
int state;
int c;

void setup() {
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(3, OUTPUT);

  pinMode(4, INPUT);
  radio.begin();
  radio.setChannel(5);                                      
  radio.setDataRate     (RF24_1MBPS);                       
  radio.setPALevel      (RF24_PA_HIGH);                     
  radio.openWritingPipe (0xAABBCCDD11LL);                    
}

void loop() {
  state = digitalRead(switchPin);

  if (state == HIGH && c == 0) 
  {
    c = 1;

  }
  if (state == LOW && c == 1) 
  {
    val = ++val;
    if (val == 7)
    {
      val = 0;
    }
    c = 0;
  }

  if (val == 0) 
  {
    digitalWrite(6, HIGH);
    digitalWrite(3, LOW);
    radio.startListening();
    delay(50);
    if (radio.available())
    {
      radio.read(massiv2, 1);
      if (massiv2[0] == 11)
      {
        digitalWrite(5, HIGH);
        digitalWrite(6, HIGH);
      }
    }
  }

  if (val == 1) 
  {
    digitalWrite(6, LOW);
    radio.stopListening();
    massiv[0] = 1;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }
  if (val == 2) 
  {
    digitalWrite(6, LOW);
    radio.stopListening();
    massiv[0] = 2;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }
  if (val == 3) 
  {
    digitalWrite(6, LOW);
    radio.stopListening();
    massiv[0] = 3;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }
  if (val == 4) 
  {
    digitalWrite(6, LOW);
    radio.stopListening();
    massiv[0] = 4;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }
  if (val == 5) 
  {
    digitalWrite(6, LOW);
    radio.stopListening();
    massiv[0] = 5;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }
  if (val == 6) 
  {
    digitalWrite(6, LOW);
    radio.stopListening();
    massiv[0] = 6;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }
  delay(10);
}

 

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

модули работают или на прием или на передачу, поэтому надо после передачи переключать на прием

radio.startListening();

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Valera19701 пишет:

модули работают или на прием или на передачу, поэтому надо после передачи переключать на прием

radio.startListening();

Так, они же по умолчанию стоят на прием. В не нажатом состоянии, они слушают эфир, при нажатии уходят в передачу.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

вы же останавливаете прием, и не возобновляете :)

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Valera19701 пишет:

вы же останавливаете прием, и не возобновляете :)

Вы имеете ввиду в коде TX? Или я что-то не догоняю)

Просто получается, что к примеру с 4 модуля ушла единичка на центр, центр ее обработал и полслал 11, в свою очередь 1 модуль услышал и отреагировал. Так вот с последним проблема. 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

у вас везде

 radio.stopListening();

а старта нигде нет, кроме сетапа, который срабатывает один раз

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Valera19701 пишет:

у вас везде

 radio.stopListening();

а старта нигде нет, кроме сетапа, который срабатывает один раз

Теперь понял, попробую, спасибо)

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Поправил, проблема не ушла, видимо где-то в приеме RX косяк.

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017
 if (val == 0) 
  {
    digitalWrite(6, HIGH);
    digitalWrite(3, LOW);
    radio.startListening();
    delay(50);
    if (radio.available())
    {
      radio.read(massiv2, 1);
      if (massiv2[0] == 11)
      {
        digitalWrite(5, HIGH);
        digitalWrite(6, HIGH);
      }
    }
  }

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

не забывайте, на переключение с приема на передачу и обратно время уходит, надо ставить задержки около 20 мс

на передатчике тоже , т. е. попасть передачей тогда, когда приемник начал уже слушать

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Valera19701 пишет:

не забывайте, на переключение с приема на передачу и обратно время уходит, надо ставить задержки около 20 мс

на передатчике тоже , т. е. попасть передачей тогда, когда приемник начал уже слушать

То есть здесь на RX: 

if (val == 1) 
  {
    digitalWrite(6, LOW);
    radio.stopListening(); 
    delay(20);
    massiv[0] = 1;
    radio.write(massiv, 1);
    digitalWrite(3, HIGH);

  }

И здесь на TX:

if (massiv[0] == 1)  
    {
      radio.stopListening();
      delay(20);
      massiv2[0] = 11;
      radio.write(massiv2, 1);
      digitalWrite(2, HIGH);
      delay(1000);
      digitalWrite(2, LOW);
    }

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

у вас опять нет строки переключающей на прием

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Valera19701 пишет:

у вас опять нет строки переключающей на прием

Я ее в loop сразу поставил, неверно?

void loop() {
  radio.startListening();
  if (radio.available(&pipe))
  {
    radio.read(massiv, 1);
   }
  }

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

так нельзя

надо так

    radio.stopListening();
    radio.write(&data_out, sizeof(data_out) );
    radio.startListening();

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Вот так:

if (massiv[0] == 1)  
    {
      radio.stopListening();
      delay(20);
      massiv2[0] = 11;
      radio.write(&massiv2, sizeof(massiv2));
      digitalWrite(2, HIGH);
      delay(1000);
      digitalWrite(2, LOW);
      radio.startListening();
    }

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

дааааа, delay 1000?

 у вас на 1 секунду все умирает, используйте millis();

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Походу че-то не верно я сделал, так как прием на центральном модуле тоже ушел:


unsigned long time;

void loop() {


if (massiv[0] == 1) //если пришла 1, то нужно отправить данные на TX1
    {
      radio.stopListening();
      delay(20);
      massiv2[0] = 11;
      radio.write(&massiv2, sizeof(massiv2));
      digitalWrite(2, HIGH);
      time = millis();
      digitalWrite(2, LOW);
      radio.startListening();
    }



}

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Все-таки на RX косяк может??

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

c millis сначала разберитесь

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Valera19701 пишет:

c millis сначала разберитесь

Так?

 if (massiv[0] == 1) //если пришла 1, то нужно отправить данные на TX1
    {
      radio.stopListening();
      delay(20);
      massiv2[0] = 11;
      radio.write(&massiv2, sizeof(massiv2));

      if (currentMillis - previousMillis > interval) {
        previousMillis = currentMillis;
        digitalWrite(2, HIGH);
      }
      radio.startListening();
    }
Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Думаю проблема может еще быть в том, что модули настроены на передачу, и поэтому не могут принимать данные: 

  radio.openWritingPipe (0xAABBCCDD11LL);                   

Или я не прав, и модули могут и принимать при таких настройках? Если так, то тогда как их перенастроить для приема от центра, командой:

radio.openReadingPipe ();

но как это сделать правильно?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

да, надо

const uint64_t pipe[2] = {0xE8E8F0F0E1LL, 0xE8E8F0F0E2LL};

и в сетапе

  radio.openReadingPipe(1, pipe[1]);
  radio.openWritingPipe(pipe[0]);

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

это получается 1 центр и еще 5 дочерних? и как задать адрес центра?

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

То есть 0xAABBCCDD11LL - центр, 0xAABBCCDD22LL,.. дочерние:

const uint64_t pipe[2] = {0xAABBCCDD11LL, 0xAABBCCDD22LL};

И так для других?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

да, одна для передачи, другая для приема

если ипользовать то что я дал первым, то это пусть будет центр, а для дочерних тогда так

  radio.openReadingPipe(1, pipe[0]);
  radio.openWritingPipe(pipe[1]);

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

А количесвто дочерних только 5 да?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

хоть 100, если опрашивать по очереди по одному

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Спасибо Valera19701, прием - передача теперь работает, но вот каксделать, чтобы они друг другу не мешали? 

void loop() {

  radio.openReadingPipe (1, pipe[1]);
  if (radio.available())
  {
    radio.read(&data2, sizeof(data2));
    digitalWrite(2, HIGH);
    lcd.setCursor(0, 0);
    lcd.print(data2[0]);
    radio.startListening();
  }
  radio.openReadingPipe (1, pipe[4]);
  if (radio.available())
  {
    radio.stopListening  ();
    radio.write(&data2, sizeof(data2));
    digitalWrite(3, HIGH);
    radio.startListening();
  }

  radio.openReadingPipe (1, pipe[2]);
  if (radio.available())
  {
    radio.read(&data, sizeof(data));
    digitalWrite(7, HIGH);
    lcd.setCursor(7, 0);
    lcd.print(data[0]);
    radio.startListening();
  }
  radio.openReadingPipe (1, pipe[5]);
  if (radio.available())
  {
    radio.stopListening  ();
    radio.write(&data, sizeof(data));
    digitalWrite(18, HIGH);
    radio.startListening();
  }

}

 

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

я же написал, опрашивать по одному, оставить 2 pipe, и например первым байтом передавать число,

, а на приемниках принимать это число, если оно совпадает с передаваемым то отвечать на запрос, както так

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Просто свзяь работает хорошо, но по одному, да и важно чтобы были отдельные каналы. Может просто на время глушить как-то? И странно что информация передается в разных массивах, и все равно перемешивается, то есть массив data, для одного приемника вмешивается в массив data2 для другого.

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Реализовать к примеру опрос 3 модулей записать данные в массив, а затем эти данные разослать другим 3.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

я не знаю вашу задачу, но у себя с двумя каналами (pipe) за 1 сек я опрашиваю 30 датчиков

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Сеть, центральная точка, 6 дочерних, с 3 данные принимаем, другим 3 передаем, прием работает, а отсылка данных сбивает все.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

ну так присвойте каждой точке чтото типа номера (device id), например 1, 2, 3 в первый байт массива и таким образом распознавайте что и кому

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Так в том то и дело,  что информация доходит и распознается, вопрос только как сделать чтобы, не мешали друг другу и не перебивали информацию соседа.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

я же писал, по очереди, например отправил запрос на 1 устройство- переключился на прием, дождался ответа, переключился на передачу отправил на 2 и т. д. на дочерних также, все время слушают, получил свой id, переключился на передачу, отправил, и опять на прием

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

То есть как то так:

дочерняя:

void loop() {
  radio.startListening  ();
  if (radio.available())
  {
    radio.read(&zapros, sizeof(zapros));
    if (zapros[1] == 1)
    {
      radio.stopListening  ();
      digitalWrite(Trig, HIGH);
      delayMicroseconds(10); // равный 10 микросекундам
      digitalWrite(Trig, LOW); // Отключаем
      impulseTime = pulseIn(Echo, HIGH); // Замеряем длину импульса
      distance_sm = impulseTime / 58; // Пересчитываем в сантиметры
      Serial.println(distance_sm); // Выводим на порт
      data2[0] = distance_sm;
      radio.write(&data2, sizeof(data2));
      digitalWrite(3, HIGH);
      delay(100);
      radio.startListening  ();
    }
  }
}

центр:

void loop() {
  radio.openReadingPipe (1, pipe[1]);
  radio.stopListening  ();
  zapros[1] = 1;
  radio.write(&zapros, sizeof(zapros));
  delay(100);
  digitalWrite(2, HIGH);

  radio.startListening  ();
  if (radio.available())
  {
    radio.read(&data2, sizeof(data2));
    digitalWrite(2, HIGH);
    lcd.setCursor(0, 0);
    lcd.print(data2[0]);
    lcd.print(" cm ");
    delay(500);
  }
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Блин. Вам руки надо за delay() поотбивать

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

qwone пишет:

Блин. Вам руки надо за delay() поотбивать

 

Если будет работать, то ок)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

 А ваша проблема заставить работать вашу голову, а я так просто указываю на ваши ошибки(имхо разумеется)

void loop() {
  radio.startListening  ();
  if (radio.available()>=sizeof(zapros) { // <- когда пакет полностью в буфере, а не только 1 первый байт
    radio.read(&zapros, sizeof(zapros));
  }
}

 

Skyline7546
Skyline7546 аватар
Offline
Зарегистрирован: 03.12.2017

Не слышит дочерняя. Еще ошибки?

SVD
Offline
Зарегистрирован: 05.04.2018

Лиди подскажите пожалуйста кусочек кода, где реализовано переключение каналов.

IVAN222
Offline
Зарегистрирован: 19.04.2017

Вы уже сюда перешли! Я понял так,  Вам нужно переключать каналы на НРФ24, с помощью кнопки - включил ардуино это 1 канал, нажал на кнопку 2 канал , еще раэ нажал 3, еще раз 1 канал, можно сделать на сколько хотите. Вот есть урок про кнопку ,

http://ampexpert.ru/arduino-urok-3-knopka/

в конце посмотрите код, как раз для Вас. Только в коде в режимах 1, 2, 3, 4 впишите строку  radio.setChannel(0x70);  В кавычках вставте канал какой Вам нужен. 

IVAN222
Offline
Зарегистрирован: 19.04.2017

этот код соедените со своим.

int regim=1;
int flag=0;

void setup(){
pinMode(2,INPUT); // кнопка
}

void loop(){
if(digitalRead(2)==HIGH&&flag==0)//если кнопка нажата
// и перемення flag равна 0 , то ...
{
regim++;
flag=1;

//это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие
// плюс защита от "дребезга"  100%

if(regim>4)//ограничим количество режимов
{
regim=1;//так как мы используем только одну кнопку,
// то переключать режимы будем циклично
}
}

if(digitalRead(2)==LOW&&flag==1)//если кнопка НЕ нажата
//и переменная flag равна - 1 ,то ...
{
flag=0;//обнуляем переменную "knopka"
}

if(regim==1)//первый режим
{
radio.setChannel(0x70);
}

if(regim==2)//второй режим
{
radio.setChannel(0x71);
}

if(regim==3)//третий режим
{
radio.setChannel(0x72);
}

if(regim==4)//четвертый режим
{
radio.setChannel(0x73);
}

}

 

Amiak
Offline
Зарегистрирован: 03.01.2021

Valera19701 пишет:
я не знаю вашу задачу, но у себя с двумя каналами (pipe) за 1 сек я опрашиваю 30 датчиков

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