Вопросы по NRF24L01

artallo

✩✩✩✩✩✩✩
19 Май 2021
4
1
Здравствуйте!
Микроконтроллер одноядерный, выполняет одну инструкцию за один такт. Опрос и отправка конечно происходят по очереди, но с очень маленькими задержками, что создает ощущение непрерывности и параллельного исполнения. Раз приоритет на LoRa, то происходит его циклический опрос, а если пакет принят, то делаем отправку и возврат в циклический опрос.
Обращайтесь. Стоимость от 5т.р.
 
  • Лойс +1
Реакции: te238s

asdofchik

✩✩✩✩✩✩✩
26 Июл 2021
2
0
Оформи код соответствующим тэгом
Помогите пожалуйста понять в чем проблема

tx:

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(9, 10);
#define PIN_SENSOR 1
int of = 1;

void setup() {
radio.begin();
radio.setChannel(0x60);
radio.setDataRate (RF24_1MBPS);
radio.setPALevel (RF24_PA_MAX);
radio.openWritingPipe (0xAABBCCDD11LL);
radio.powerUp();
radio.stopListening();
}
void loop() {
int val = analogRead(PIN_SENSOR);
if(val==1)
radio.write(&of, sizeof(of));
}

rx:

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(9, 10);
byte pipe;
int of;
void setup() {
pinMode(7, OUTPUT);
delay(1000);
radio.begin();
radio.setChannel(0x60);
radio.setDataRate (RF24_1MBPS);
radio.setPALevel (RF24_PA_MAX);
radio.openReadingPipe (1, 0xAABBCCDD11LL);
radio.openReadingPipe (2, 0xAABBCCDD22LL);
radio.powerUp();
radio.startListening ();
}
void loop() {
if (radio.available(&pipe)) {
radio.read(&of, sizeof(of));
if (pipe == 1);
digitalWrite(7, HIGH);
delay(100);
digitalWrite(7, LOW); ;
if (pipe == 2)digitalWrite(7, HIGH);
delay(500);
digitalWrite(7,LOW);
}
else digitalWrite(7, LOW);
}

При срабатывании первой трубы, пищит 2-4 раза, при срабатывании второй трубы, пищит сначала как будто сработала первая, потом как вторая и тоже 2-4 раза.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,974
633
45
if (pipe == 1);
digitalWrite(7, HIGH);
delay(100);
digitalWrite(7, LOW); ;
if (pipe == 2)digitalWrite(7, HIGH);
delay(500);
digitalWrite(7,LOW);
Чтобы выполнялся блок операторов после условия if их нужно заключать в фигурные скобки:
C++:
if (/* условие */) {
    //
    // операторы которые должны выполняться
    //
}
 

Игор

✩✩✩✩✩✩✩
13 Мар 2021
20
0
Всем добра. Делаю весы, которые передают показания через nRF24l01+(с антеной). С весами проблем нет тензодатчики подключил, скетч залил, в мониторе порта выводит вес.
Для передачи через nRF24l01+ использовал пример AlexGyver "простой приём передача", совместил скетчи и нечего не получилось. Начал разбираться в чем дело и обнаружил что если в примере AlexGyver"простой приём передача" изменить задержку в «лупе» на 15мс и больше, то приемник не принимать. Пробовал изменять число достукиваний и время между ними не помогло. При 10мс работает.
Модули с ардуино спаяны, питание через понижающий модуль.
Меня это интересует потому что на получения значения веса нужно больше 10мс, и тут прием передача не проходит.

В чем может быть дело?

Выручайте начинающего ардуинщика. Заранее благодарен.
Код примера прилагаю.

TX:
/*   
    by AlexGyver 2016
*/

#include <SPI.h>          // библиотека для работы с шиной SPI
#include "nRF24L01.h"     // библиотека радиомодуля
#include "RF24.h"         // ещё библиотека радиомодуля

RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9,53); // для Меги

byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб

byte counter;

void setup() {
  Serial.begin(9600);         // открываем порт для связи с ПК

  radio.begin();              // активировать модуль
  radio.setAutoAck(1);        // режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    // (время между попыткой достучаться, число попыток)
  radio.enableAckPayload();   // разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);   // размер пакета, в байтах

  radio.openWritingPipe(address[0]);  // мы - труба 0, открываем канал для передачи данных
  radio.setChannel(0x60);             // выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX);   // уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); // скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  //при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();        // начать работу
  radio.stopListening();  // не слушаем радиоэфир, мы передатчик
}

void loop() {
  Serial.print("Sent: ");
  Serial.println(counter);
  radio.write(&counter, sizeof(counter));
  counter++;
  delay(10);
}
RX:
/*   
    by AlexGyver 2016
*/

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

RF24 radio(9, 10);  // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9,53); // для Меги

byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб

void setup() {
  Serial.begin(9600);         // открываем порт для связи с ПК
  radio.begin();              // активировать модуль
  radio.setAutoAck(1);        // режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    // (время между попыткой достучаться, число попыток)
  radio.enableAckPayload();   // разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);   // размер пакета, в байтах

  radio.openReadingPipe(1, address[0]);   // хотим слушать трубу 0
  radio.setChannel(0x60);     // выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX);   // уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); // скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  //при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();        // начать работу
  radio.startListening(); // начинаем слушать эфир, мы приёмный модуль
}

void loop() {
  byte pipeNo, gotByte;
  while (radio.available(&pipeNo)) {        // слушаем эфир со всех труб
    radio.read(&gotByte, sizeof(gotByte));  // чиатем входящий сигнал
    Serial.print("Recieved: ");
    Serial.println(gotByte);
  }
}
 

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
на получения значения веса нужно больше 10мс, и тут прием передача не проходит.

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

Для вашей задачи необходима своя логика работы модуля. Ищите другие примеры. Есть хороший перевод документации для работы с nRF24+ с подробным описанием основных функций и многочисленными примерами: https://wiki.iarduino.ru/page/NRF24L01-trema/
 
  • Лойс +1
Реакции: Игор

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
здесь отрывок из документации по работе с фичей ack payload. Обратите внимание, что подтверждающие данные о приеме пакета необходимо поместить в буфер до того как придёт запрос от передатчика! В этом была ваша проблема.
Модуль может работать либо в режиме передатчика, либо в режиме приёмника, но передатчик способен запрашивать, а приёмник отправлять пакет подтверждения приёма данных. Происходит это по протоколу Enhanced Shockburst примерно так: передатчик отправляет данные приёмнику с запросом ответа, приёмник получает данные, проверяет их корректность (сверяет CRC), и если всё верно, то отвечает передатчику «Ок! я все получил, спасибо.». А если приёмник не ответил передатчику, то передатчик отправляет данные приёмнику повторно, пока не исчерпает заданное количество попыток отправки данных.

Так вот в ответе приёмника могут присутствовать и те данные которые Вы хотите отправить передатчику. Правда эти данные уже не будут проходить проверку, и они должны быть сформированы на стороне приёмника до того как он получит данные от передатчика. Но такой тип связи позволит приёмнику возвращать, а передатчику принимать, данные без изменения режимов радиопередач на обоих устройствах, приёмник остаётся приёмником, а передатчик передатчиком...

Обратите внимание на то, что ответ приёмника ackData сначала помещается в буфер FIFO функцией writeAckPayload(), а отправляется он аппаратно, при получении данных от передатчика, но ещё до того как функция available() вернёт true.
 
  • Лойс +1
Реакции: Игор

Игор

✩✩✩✩✩✩✩
13 Мар 2021
20
0
этот пример Гайвера, на сколько я помню, демострирует одну специальную фичу - enableAckPayload() (режим подтверждения получения пакета).
enableAckPayload() -закоментировал, не помогло.
пример брал с названием "простой приём передача» там просто передается переменная, которую инкрементируют. И тут не могу разобраться почему если заделать задержку, например в одну секунду в конце loop, то приемник ничего не принимает, хотя передатчик проходит цикл пишет в порт переменную, которая увеличивается. Значит он получил подтверждение от приемника и цикл крутится? Или я не так что-то понимаю?

описанием основных функций и многочисленными примерами: https://wiki.iarduino.ru/page/NRF24L01-trema/
до того, как задать вопрос здесь, перечитал этот ресурс, и пробовал все примеры из него.


Как поправить этот код чтобы работал с любой задержкой?
 

bort707

★★★★★★✩
21 Сен 2020
3,064
912
enableAckPayload() -закоментировал, не помогло.
попробуйте строчки
C++:
radio.setAutoAck(1);        // режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    // (время между попыткой достучаться, число попыток)
  radio.enableAckPayload();   // разрешить отсылку данных в ответ на входящий сигнал
выкинуть и из приемника, и из передачика
 
  • Лойс +1
Реакции: Игор

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
до того, как задать вопрос здесь, перечитал этот ресурс, и пробовал все примеры из него.


Как поправить этот код чтобы работал с любой задержкой?
Вам нужен вот этот пример: "Двунаправленная отправка данных"
Двунаправленная отправка данных:
Модуль может работать либо в режиме передатчика, либо в режиме приёмника, но передатчик способен запрашивать, а приёмник отправлять пакет подтверждения приёма данных. Происходит это по протоколу Enhanced Shockburst примерно так: передатчик отправляет данные приёмнику с запросом ответа, приёмник получает данные, проверяет их корректность (сверяет CRC), и если всё верно, то отвечает передатчику «Ок! я все получил, спасибо.». А если приёмник не ответил передатчику, то передатчик отправляет данные приёмнику повторно, пока не исчерпает заданное количество попыток отправки данных.

Так вот в ответе приёмника могут присутствовать и те данные которые Вы хотите отправить передатчику. Правда эти данные уже не будут проходить проверку, и они должны быть сформированы на стороне приёмника до того как он получит данные от передатчика. Но такой тип связи позволит приёмнику возвращать, а передатчику принимать, данные без изменения режимов радиопередач на обоих устройствах, приёмник остаётся приёмником, а передатчик передатчиком.
Скетч приёмника:
#include <SPI.h>                                               // Подключаем библиотеку для работы с шиной SPI.
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24.
#include <RF24.h>                                              // Подключаем библиотеку для работы с nRF24L01+.
RF24     radio(7, 10);                                         // Создаём объект radio для работы с библиотекой RF24, указывая номера выводов модуля (CE, SS).
int      myData[5];                                            // Объявляем массив для приёма и хранения данных (до 32 байт включительно).
int      ackData[5];                                           // Объявляем массив для передачи данных в пакете подтверждения приёма (до 32 байт включительно).
                                                               //
void setup(){                                                  //
    radio.begin();                                             // Инициируем работу nRF24L01+
    radio.setChannel      (27);                                // Указываем канал передачи данных (от 0 до 125), 27 - значит передача данных осуществляется на частоте 2,427 ГГц.
    radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек.
    radio.setPALevel      (RF24_PA_MAX);                       // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm).
    radio.enableAckPayload();                                  // Указываем что в пакетах подтверждения приёма есть блок с пользовательскими данными.
//  radio.enableDynamicPayloads();                             // Разрешить динамически изменяемый размер блока данных на всех трубах.
    radio.openReadingPipe (1, 0xAABBCCDD11LL);                 // Открываем 1 трубу с адресом 0xAABBCCDD11, для приема данных.
    radio.startListening  ();                                  // Включаем приемник, начинаем прослушивать открытые трубы.
    radio.writeAckPayload (1, &ackData, sizeof(ackData) );     // Помещаем данные всего массива ackData в буфер FIFO. Как только будут получены любые данные от передатчика на 1 трубе, то данные из буфера FIFO будут отправлены этому передатчику вместе с пакетом подтверждения приёма его данных.
}                                                              // В модуле имеется 3 буфера FIFO, значит в них одновременно может находиться до трёх разных или одинаковых данных для ответа по одной или разным трубам.
                                                               // После отправки данных из буфера FIFO к передатчику, соответствующий буфер очищается и способен принять новые данные для отправки.
void loop(){                                                   //
    if(radio.available()){                                     // Если в буфере приёма имеются принятые данные от передатчика, то ...
        radio.read            (   &myData,  sizeof(myData)  ); // Читаем данные из буфера приёма в массив myData указывая сколько всего байт может поместиться в массив.
        radio.writeAckPayload (1, &ackData, sizeof(ackData) ); // Помещаем данные всего массива ackData в буфер FIFO для их отправки на следующее получение данных от передатчика на 1 трубе.
    }                                                          // Если все 3 буфера FIFO уже заполнены, то функция writeAckPayload() будет проигнорирована.
}                                                              // Так как в данном скетче данные в буфер помещаются только после получения данных от передатчика, значит один из буферов был только что очищен и заполнение всех 3 буферов в данном скетче невозможно.
Обратите внимание на то, что ответ приёмника ackData сначала помещается в буфер FIFO функцией writeAckPayload(), а отправляется он аппаратно, при получении данных от передатчика, но ещё до того как функция available() вернёт true.

Скетч передатчика:
#include <SPI.h>                                               // Подключаем библиотеку для работы с шиной SPI.
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24.
#include <RF24.h>                                              // Подключаем библиотеку для работы с nRF24L01+.
RF24     radio(7, 10);                                         // Создаём объект radio для работы с библиотекой RF24, указывая номера выводов модуля (CE, SS)
int      myData[5];                                            // Объявляем массив для хранения и передачи данных.
int      ackData[5];                                           // Объявляем массив для получения данных из пакета подтверждения приёма (до 32 байт включительно).
                                                               //
void setup(){                                                  //
    radio.begin           ();                                  // Инициируем работу модуля nRF24L01+.
    radio.setChannel      (27);                                // Указываем канал передачи данных (от 0 до 125), 27 - значит передача данных осуществляется на частоте 2,427 ГГц.
    radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек.
    radio.setPALevel      (RF24_PA_MAX);                       // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm).
    radio.enableAckPayload();                                  // Указываем что в пакетах подтверждения приёма есть блок с пользовательскими данными.
//  radio.enableDynamicPayloads();                             // Разрешить динамически изменяемый размер блока данных на всех трубах.
    radio.openWritingPipe (0xAABBCCDD11LL);                    // Открываем трубу с адресом 0xAABBCCDD11 для передачи данных (передатчик может одновременно вещать только по одной трубе).
}                                                              //
                                                               //
void loop(){                                                   //
    radio.write(&myData, sizeof(myData));                      // Отправляем данные из массива myData указывая сколько байт массива мы хотим отправить.
    if( radio.isAckPayloadAvailable() ){                       // Если в буфере имеются принятые данные из пакета подтверждения приёма, то ...
        radio.read(&ackData, sizeof(ackData));                 // Читаем данные из буфера в массив ackData указывая сколько всего байт может поместиться в массив.
    }                                                          //
    delay(50);                                                 // Устанавливаем задержку на 50 мс. В этом скетче нет смысла слать данные чаще.
}                                                              //
В этих скетчах одному модулю назначена роль приемника, а другому передатчика, но не смотря на это связь организована двухсторонняя, без изменения ролей модулей в радиопередаче.

Стоит отметить несколько особенностей данной реализации связи:
  • На стороне передатчика, вместо функции isAckPayloadAvailable() можно использовать функцию available(), она будет работать точно так же.
  • Блоки данных в пакетах подтверждения приёма имеют динамически изменяемый размер, он используется по умолчанию для отправки ответов по трубам 0 и 1, так что если данные приемника нужно отправить передатчику по трубам 2-5 (где по умолчанию используются статичный размер ответных данных), то необходимо раскомментировать функцию enableDynamicPayloads() в обоих скетчах.
  • Если на стороне передатчика не читать данные из буферов, то буферы заполнятся и перестанут принимать пакеты подтверждения приёма, тогда функция write() будет всегда возвращать false, хотя данные будут и отправляться, и приниматься приемниками.
  • Если на стороне приемника формировать ответы для нескольких передатчиков (а каждый из них должен использовать свою трубу), то нужно учитывать тот факт что у модуля для этих целей имеется всего 3 буфера, которые могут хранить до трех ответов для труб с разными или одинаковыми номерами. Если буферы заполнены, то функция writeAckPayload() будет проигнорирована. Например, если в буферах уже есть ответы для труб с номерами 1,2 и 3, новые ответы записать не получится, а пришли данные от передатчика по трубе с номером 0, то он естественно не получит ответ.

1. Пробуйте этот пример, чтобы убедиться что оба модуля исправны: принимают и отправляют тестовые данные. (увеличить время задержки до 1000мс и контролировать прием/передачу данных при помощи светодиода или UART) С UART нужно быть осторожным - возможен конфликт обеих библиотек Serial и nRF24.
2. Разработайте собственную логику работы весов. Сервер - предоставляет функцию весов, Клиент отправляет запросы на взвешивание. Первый Запрос поступает от Клиента, сервер реагирует так-то и так-то, посылает подтверждение Клиенту. Клиент видя подтверждение сервера делает то-то и то-то.. и так далее.
3. Как видно, из примера работы двух модулей (приемник и передатчик) обойтись только одним запросом Клиент-Сервер не получиться. Нужно применить как минимум два запроса: 1. Запрос на взвешивание, а через некоторую задержку уже следующий 2. Запрос на готовность приема результата. Все эти процессы хорошо реализуются стандартным набором библиотечных функций.
 
  • Лойс +1
Реакции: Игор

Игор

✩✩✩✩✩✩✩
13 Мар 2021
20
0
1. Пробуйте этот пример, чтобы убедиться что оба модуля исправны:
попробовал, код получился такой(ниже) добавил вывод в порт для наглядности. Так вот этот тоже работает с задержкой 10мс а с 50мс не работает.
лажа кокета, для меня как для начинающего вообще непонятно почему так.
TX:
#include <SPI.h>                                               // Подключаем библиотеку для работы с шиной SPI.
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24.
#include <RF24.h>                                              // Подключаем библиотеку для работы с nRF24L01+.
RF24     radio(9, 10);                                         // Создаём объект radio для работы с библиотекой RF24, указывая номера выводов модуля (CE, SS)
int      myData;                                            // Объявляем массив для хранения и передачи данных.
int      ackData = 5;                                           // Объявляем массив для получения данных из пакета подтверждения приёма (до 32 байт включительно).
//
void setup() {                                                 //
  Serial.begin(9600);
  radio.begin           ();                                  // Инициируем работу модуля nRF24L01+.
  radio.setChannel      (70);                                // Указываем канал передачи данных (от 0 до 125), 27 - значит передача данных осуществляется на частоте 2,427 ГГц.
  radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек.
  radio.setPALevel      (RF24_PA_MAX);                       // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm).
  radio.enableAckPayload();                                  // Указываем что в пакетах подтверждения приёма есть блок с пользовательскими данными.
  //  radio.enableDynamicPayloads();                             // Разрешить динамически изменяемый размер блока данных на всех трубах.
  radio.openWritingPipe (0xAABBCCDD11LL);                    // Открываем трубу с адресом 0xAABBCCDD11 для передачи данных (передатчик может одновременно вещать только по одной трубе).
}                                                              //
//
void loop() {                                                  //
  radio.write(&myData, sizeof(myData));                      // Отправляем данные из массива myData указывая сколько байт массива мы хотим отправить.
 if ( radio.isAckPayloadAvailable() ) {                     // Если в буфере имеются принятые данные из пакета подтверждения приёма, то ...
    radio.read(&ackData, sizeof(ackData));                 // Читаем данные из буфера в массив ackData указывая сколько всего байт может поместиться в массив.
    
                                                    // Устанавливаем задержку на 50 мс. В этом скетче нет смысла слать данные чаще.
  }
    Serial.println(myData);
    Serial.println(ackData);
    myData++;
    delay(50);
}
RX:
#include <SPI.h>                                               // Подключаем библиотеку для работы с шиной SPI.
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24.
#include <RF24.h>                                              // Подключаем библиотеку для работы с nRF24L01+.
RF24     radio(9, 10);                                         // Создаём объект radio для работы с библиотекой RF24, указывая номера выводов модуля (CE, SS).
int      myData;                                            // Объявляем массив для приёма и хранения данных (до 32 байт включительно).
int      ackData = 7;                                         // Объявляем массив для передачи данных в пакете подтверждения приёма (до 32 байт включительно).
//
void setup() {                                                 //
  Serial.begin(9600);
  radio.begin();                                             // Инициируем работу nRF24L01+
  radio.setChannel      (70);                                // Указываем канал передачи данных (от 0 до 125), 27 - значит передача данных осуществляется на частоте 2,427 ГГц.
  radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек.
  radio.setPALevel      (RF24_PA_MAX);                       // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm).
  radio.enableAckPayload();                                  // Указываем что в пакетах подтверждения приёма есть блок с пользовательскими данными.
  //  radio.enableDynamicPayloads();                             // Разрешить динамически изменяемый размер блока данных на всех трубах.
  radio.openReadingPipe (1, 0xAABBCCDD11LL);                 // Открываем 1 трубу с адресом 0xAABBCCDD11, для приема данных.
  radio.startListening  ();                                  // Включаем приемник, начинаем прослушивать открытые трубы.
  radio.writeAckPayload (1, &ackData, sizeof(ackData) );     // Помещаем данные всего массива ackData в буфер FIFO. Как только будут получены любые данные от передатчика на 1 трубе, то данные из буфера FIFO будут отправлены этому передатчику вместе с пакетом подтверждения приёма его данных.
}                                                              // В модуле имеется 3 буфера FIFO, значит в них одновременно может находиться до трёх разных или одинаковых данных для ответа по одной или разным трубам.
// После отправки данных из буфера FIFO к передатчику, соответствующий буфер очищается и способен принять новые данные для отправки.
void loop() {                                                  //
  if (radio.available()) {                                   // Если в буфере приёма имеются принятые данные от передатчика, то ...
    radio.read            (   &myData,  sizeof(myData)  ); // Читаем данные из буфера приёма в массив myData указывая сколько всего байт может поместиться в массив.
    radio.writeAckPayload (1, &ackData, sizeof(ackData) ); // Помещаем данные всего массива ackData в буфер FIFO для их отправки на следующее получение данных от передатчика на 1 трубе.
    Serial.println(myData);
    Serial.println(ackData);

  }                                                          // Если все 3 буфера FIFO уже заполнены, то функция writeAckPayload() будет проигнорирована.
}                                                              // Так как в данном скетче данные в буфер помещаются только после получения данных от передатчика, значит один из буферов был только что очищен и заполнение всех 3 буферов в данном скетче невозможно.

2. Разработайте собственную логику работы весов.
Свою не разработал знаний маловато, но изменив параметры считывания с весов, а именно количество замеров для усреднённого результата, было 10 поставил 1, цикл проходит быстрее и дание отправляются и принимаются, пока так получилось решить это. Теперь на стороне приемника буду усреднять показания, еще не знаю как, есть пару идей, но как реализовать буду думать доучивать, а дальше буду разбираться как график строить.
 

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
@Игор,
Итак, начнем по-порядку.

Если вы внимательно читали мой последний пост, то дожны были знать, что под Сервером (весы) подразумевался ПРИЕМНИК, а под Клиентом (получающим данные измерений) - ПЕРЕДАТЧИК.

Далее, если nRF модуль был инициирован в сейтапе как приемник, то работать как передатчик он не может и наоборот, если инициирован как передатчик, то прослушивать эфир не может. Но к счастью, есть такой мешанизм как подтверждение принятых данных. То есть приемник на короткий момент становиться передатчиком, а передатчик - приемником. И они могут обмениваться данными. Здесь еще одно большое НО. Те данные, которые в качестве подтвеждения посылает назад приемник НИКАК НЕ ОБРАБАТЫВАЮТСЯ, другими словами, они должны ЕЩЁ ДО ПРИЁМА СИГНАЛА, загодя!, быть помещеными в буфер модуля nRF. То есть никакие задержки на стороне Сервера-приемника тут нафиг не помогут. Поэтому, я предложил вам вариант с двумя запросами. Первый запрос приводит в действие механизм измерения (конечный автомат), который после взвешивания помешает измерения в буфер. А вот, второй запрос уже забирает данные измерения из буфера в качестве потверждения приема сигнала. Надеюсь, приведенная логика понятна. Спрашивайте, если что..
 

Игор

✩✩✩✩✩✩✩
13 Мар 2021
20
0
что под Сервером (весы) подразумевался ПРИЕМНИК, а под Клиентом (получающим данные измерений) - ПЕРЕДАТЧИК.
у меня весы-передатчик(будут стоять на улице), а приемник - приемник(дома у компа, рисовать график и тд.).
Мне не нужно получать дание из подтверждения доставки, нужно просто слать write-ом дание с весов.
В таком виде работает, но если хочу отправлять раз в секунду то неработает.
Vesa+TX:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "HX711.h"

#define CE_PIN 9    //!!!!!!!!!!! Для Уно. Здесь установить для ваших плат!            
#define CSN_PIN 10  //!!!!!!!!!!! Для Уно. Здесь установить для ваших плат!
uint8_t DOUT_PIN = 3;                                         // указываем вывод DOUT, к которому подключен HX711
uint8_t SCK_PIN  = 2;                                         // указываем вывод SCK , к которому подключен HX711
int myData;
RF24 radio(CE_PIN, CSN_PIN);

HX711 scale;                                                  // создаём объект scale

float calibration_factor = 0.84;                             // вводим калибровочный коэффициент
float ounces;                                                   // задаём переменную для измерений в граммах
     

void setup() {
  Serial.begin(9600);
  radio.begin();                          // Включение модуля;

  scale.begin(DOUT_PIN, SCK_PIN);                             // инициируем работу с датчиком
  scale.set_scale();                                          // выполняем измерение значения без калибровочного коэффициента
  scale.tare();                                               // сбрасываем значения веса на датчике в 0
  scale.set_scale(calibration_factor);  

  radio.setChannel(70);                    // Установка канала вещания;
  radio.setRetries(0, 15);               // Установка интервала и количества попыток "дозвона" до приемника;
  radio.setDataRate(RF24_250KBPS);        // Установка минимальной скорости;
  radio.setPALevel(RF24_PA_MAX);          // Установка максимальной мощности;
  radio.setAutoAck(0);                    // Установка режима подтверждения приема;
  //radio.enableDynamicPayloads();
// radio.setCRCLength(RF24_CRC_16);
  radio.openWritingPipe(0xE8E8F0F0ABLL);     // Активация данных для отправки
  radio.powerUp();
  radio.stopListening();  // не слушаем радиоэфир, мы передатчик
}

void loop() {
  ounces = scale.get_units(1);                               // получаем значение с датчика, усреднённое по 10 измерениям
  myData = ounces * 0.035274;

  //Serial.print("Sent: ");
  //Serial.println(myData);

    radio.write(&myData, sizeof(myData));

    //myData++;
    //delay(20);
}
RX:
/*
    by AlexGyver 2016
*/

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

RF24 radio(9, 10);  // "создать" модуль на пинах 9 и 10 Для Уно

//int x[10]; /* резервирует место для 10 целочисленных элементов */
//int t, y, d;

void setup() {
  Serial.begin(9600);         // открываем порт для связи с ПК
  radio.begin();              // активировать модуль
  radio.setChannel(70);     // выбираем канал (в котором нет шумов!)
  radio.setRetries(0, 15);    // (время между попыткой достучаться, число попыток)
  radio.setDataRate (RF24_250KBPS); // скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  radio.setPALevel (RF24_PA_MAX);   // уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setAutoAck(0);        // режим подтверждения приёма, 1 вкл 0 выкл
  //radio.enableDynamicPayloads();
  // radio.setCRCLength(RF24_CRC_16);
  radio.openReadingPipe(1, 0xE8E8F0F0ABLL);   // хотим слушать трубу 0

  //radio.setPayloadSize(32);   // размер пакета, в байтах



  //должна быть одинакова на приёмнике и передатчике!
  //при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();        // начать работу
  radio.startListening(); // начинаем слушать эфир, мы приёмный модуль
}

void loop() {
  byte pipeNo;
  int gotByte;
  while (radio.available(&pipeNo)) {        // слушаем эфир со всех труб
    radio.read(&gotByte, sizeof(gotByte));  // чиатем входящий сигнал
      Serial.println(gotByte);
  }
/*
if (t <10){
x[t] = gotByte;
t++;
}
else if(t >=10){
d = (x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7] + x[8] + x[9])/10;
  Serial.println("masiv");
Serial.print(d);

t = 0;
}*/
}
 

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
@Игор,
у вас одна труба:
RX:
  radio.openReadingPipe(1, 0xE8E8F0F0ABLL);   // хотим слушать трубу 0
в коде же идет опрос по массиву труб
RX:
  while (radio.available(&pipeNo)) {        // слушаем эфир со всех труб
    radio.read(&gotByte, sizeof(gotByte));  // чиатем входящий сигнал
      Serial.println(gotByte);
  }
заменить на
RX new:
  if (radio.available()) {                                   // Если в буфере приёма имеются принятые данные от передатчика, то ...
    radio.read            (   &gotByte,  sizeof(gotByte)  ); // Читаем данные из буфера в массив.
   Serial.println(gotByte);
  }
 
  • Лойс +1
Реакции: Игор

Игор

✩✩✩✩✩✩✩
13 Мар 2021
20
0
@SergejEU,
в RX заменил, да так правильней, но прикол с задержкой не пофиксило.

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

m_sav47

✩✩✩✩✩✩✩
1 Дек 2020
1
0
Добрый день!
У меня ситуация похуже! Три модуля и 2 ардуины, не при каких схемах подключения не распознает модули, бьюсь сутки уже((
2022-03-20 11-50-01.JPG

У продавца отзывы что модули рабочие. (Беспроводной модуль NRF24L01 + PA + LNA с антенной 1000 метров на большие расстояния GT-24)
2022-03-20_11-59-42.png

Понимаю что надо все паять намертво итд но хоть с ошибками же должен был подключится?
 
Изменено:

Геннадий П

★★★★★★✩
14 Апр 2021
1,974
633
45

Нока

✩✩✩✩✩✩✩
7 Фев 2020
4
0
Привет всем, а кто знает такую реализацию:
Из этой статьи я вычитал, что модуль может работать в одном из 4 режимом, и как раз из примера Гавера и RX, и TX работает в режиме полудуплекса.
Но вот не задача, не получается заставить ПРИЕМНИК отправлять данные без получения данных от ПЕРЕДАТЧИКА.

Звучит конечно бредово, но если есть возможность работы полудуплекса, почему нельзя заставить работать два ПЕРЕДАТЧИКА вместе...

В общем, у меня есть реализация работы, но при условии я бы хотел, чтобы потенциальный приемник отправлял "критический сигнал о каком-то событии", не дожидаясь запроса от передатчика. Как мне это сделать?
 

Kartellinni

✩✩✩✩✩✩✩
28 Июл 2022
3
0
Здравствуйте!

Имеется передатчик и приемник на NRF24L01 + Arduino, управляет лодкой на двух моторах.

Подскажите, как определить, что передатчик отключен?

Сейчас при отключении передатчика, моторы продолжают работать, если раскомментировать motorR.setMode(STOP); и motorL.setMode(STOP);, то моторы не включаются.

C++:
void loop() {
  byte pipeNo;
  if ( radio.available(&pipeNo)) {
      radio.read( &recieved_data, sizeof(recieved_data));
      motorR.setSpeed(recieved_data[0]);
      motorL.setSpeed(recieved_data[1]);
  } else {
    //delay(30);
     //motorR.setMode(STOP);
     //motorL.setMode(STOP);
  }
}
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Данные от передатчика как правило идут с определенной частотой. Если прошедшее с последней передачи раза в 2-3 больше чем интервал передачи, то передатчик отключился. Глуши мотор, табань.
 

Kartellinni

✩✩✩✩✩✩✩
28 Июл 2022
3
0
Пока такое решение сделал, но не уверен, что оно правильно.


C++:
void loop() {
  byte pipeNo;
  if ( radio.available(&pipeNo)) {
      radio.read( &recieved_data, sizeof(recieved_data));
      motorR.setSpeed(recieved_data[0]);
      motorL.setSpeed(recieved_data[1]);
      count = 0; 
  } else {
    if (count > 10000 ){
      motorR.setSpeed(0);
      motorL.setSpeed(0);
    }
    count++;
  }
}
Не будет ли переполнение count, при выключенном передатчике.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Будет. Ведь увеличение счетчика будет происходить вне зависимости от его величины. А вот если перед count++; поставить else, то не будет.
Получится условие такое: если счетчик больше 10 000, то выключить мотора, а иначе увеличить счетчик
Могу предположить, что 10 000 для ардуины это будет не более 0.1 секунды, если это весь цикл loop
 

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
98
В лупе:
1. Читаем приемник, count=millis
2. Если приёма нет,то смотрим превышено ли время таймаута.
Хотя я повторился наверное.
 

Kartellinni

✩✩✩✩✩✩✩
28 Июл 2022
3
0
Правильно ли я понимаю, что должно быть примерно так?
C++:
void loop() {
  byte pipeNo;
  if ( radio.available(&pipeNo)) {
      radio.read( &recieved_data, sizeof(recieved_data));
      motorR.setSpeed(recieved_data[0]);
      motorL.setSpeed(recieved_data[1]);
      timeroffline = millis();
      
  } else {
    if (millis() - timeroffline > 500){
      Serial.println(F("Данных нет"));
      motorR.setSpeed(0);
      motorL.setSpeed(0);
    }
  }
}