Модули NRF24L01+

Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 07 фев 2022, 07:24

Добрый день всем!
Не знаю точно, куда поместить эту тему, вроде как больше всего подходит сюда.

Задумал я детишкам сделать радиоуправление :)
В Китае полно различных готовых модулей и устройств для этого, и я выбрал модули на основе чипа NRF24L01+ и усилителя к нему AT2401C.

Есть два типа плат на таких чипах - без усилителя, со встроенной антенной:
IMG_20220207_105048.jpg
И с усилителем и внешней антенной (антенну я тут не показал, она накручивается на разъём SMA-F):
IMG_20220207_105014.jpg
Мне нужно проконтролировать передачу сигнала, поэтому я выбираю вариант с усилителем и входом на SMA.

Для управления платой потребуется какой-нибудь микроконтроллер с SPI-интерфейсом.
Приспособил для этого китайскую же Ардуино Нано на АТМега328Р.
На плате контроллера уже имеется гнездо USB, что очень удобно при программировании.

Чтобы не припаиваться каждый раз или не изобретать что-то, что отнимает время, взял плату расширения для Ардуино Нано
IMG_20220207_105203.jpg
Контроллер на плате
IMG_20220207_105151.jpg
Также нужно учесть, что плата передатчика питается от напряжения 3,3 В, причём кушает приличный ток (встроенный стабилизатор Ардуино Нано не справляется). Нужен внешний стабилизатор.
Годится специальная платка YL-105
IMG_20220207_105125.jpg

Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 07 фев 2022, 07:31

По многочисленным советам (раз, два) поставил на выход стабилизатора дополнительный электролит на 10 мкФ (на плате нет никакого) и зашунтировал вход питания платы передатчика керамикой на 1 мкФ.
Вышло примерно так
IMG_20220207_105306.jpg
Залил проверочный код.
010.png
Он простоянно передайт одну и ту же цифру (109) на канале 00
/*
Победа над nRF24L01: на три шага ближе, передатчик
https://habr.com/ru/post/476716/
*/

#include <SPI.h>
#include <RF24.h>
RF24 radio(9, 10); // порты D9, D10: CSN CE
const uint32_t pipe = 111156789; // адрес рабочей трубы;

byte data;

void setup() {
Serial.begin(115200);
Serial.println("TransmitterTester ON");

radio.begin(); // инициализация
delay(2000);
radio.setDataRate(RF24_1MBPS); // скорость обмена данными RF24_1MBPS или RF24_2MBPS
radio.setCRCLength(RF24_CRC_8); // размер контрольной суммы 8 bit или 16 bit
radio.setPALevel(RF24_PA_MAX); // уровень питания усилителя RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
radio.setChannel(0x00); // установка канала
radio.setAutoAck(false); // автоответ
radio.powerUp(); // включение или пониженное потребление powerDown - powerUp
radio.stopListening(); //радиоэфир не слушаем, только передача
radio.openWritingPipe(pipe); // открыть трубу на отправку
}

void loop() {
data = 109;
radio.write(&data, 1);
Serial.println("data= " + String(data));
}
Библиотека:
RF24-master.rar
(4.85 МБ) 340 скачиваний


Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 07 фев 2022, 07:54

Далее, мне нужно определить - есть ли передача в эфир?
Воспользоваться программным откликом этого же модуля не совсем достоверно. Китайцы могли накосячить, например, в усилителе.
Тогда NRF24L01+ даст рапорт об успешной передаче, а AT2401C или не переключится на передачу, или ещё что-нибудь...

А что такое AT2401C ? Это китайский аналог RFX2401C - RFeIC (RF Front-end Integrated Circuit), то есть, усилитель мощности передатчика, малошумящий усилитель приёмника и цепи коммутации приём/передача.
Вся эта радость работает на выход 50 Ом на частотах 2,4 ГГц.
Выходной мощности обещано +22 dBm при потребляемом токе 100 мА.

В общем, раз есть 50-омный выход, то решил замерить сигнал прямо оттуда.
Поначалу ничего не получилось, ибо питался я от USB-порта.
Повторюсь, плата передачи кушает весьма неслабый ток. Причём импульсно. 100 мА - это уже среднее значение.
В результате порт просел, какие-то одиночные палочки выпрыгивали, но редко. И похоже, это приводило к перезагрузке контроллера.

Отключился от компа, запитал от лабораторного источника - и дело пошло.
IMG_20220207_110524.jpg
Кстати, по питанию выглядит это так:
Первоначальный пуск - 25 мА,
инициализация - 15 мА,
работа усилителя - 90...100 мА.

Поскольку передаётся цифра, то сигнал выглядит как набор палок.
IMG_20220207_105448.jpg
Включаем удержание пиков.
Это канал 00:
IMG_20220207_110503.jpg
Насколько я помню, верхний канал тут имеет номер 7F.
Проверим, на какой частоте находится этот канал:
IMG_20220207_110300.jpg
Ага, что-то работает.
Во-первых, контроллер устанавливает частоту чипа и происходит какая-то передача данных.
Во-вторых, усилитель тоже работает.
Но на нижних каналах мощность почему-то оказалась больше:
канал 00, частота 2400 МГц, сигнал +19 dBm,
канал 7F, частота 2520 МГц, сигнал +12 dBm.

Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 07 фев 2022, 17:44

Так, передача есть.
Теперь надо наладить приём.

Поскольку мы работаем на диапазоне, также занятым сетями Wi-Fi, то сначала глянем, что там в эфире твориться.
Ставлю антенну на гнездо анализатора и разворачиваю диапазон 2,4 ГГц
IMG_20220207_203626.jpg
Ага, кто-то есть!
IMG_20220207_203711.jpg
Собственно, это и не удивительно.
Мой стационарный комп также подключен по Wi-Fi.

Собираем второй комплект.
На приёмнике нет особой надобности ставить конденсаторы по питанию. Может потом добавлю.
К тому же, приёмник соединён с компом - он получает данные через порт.
IMG_20220207_213751.jpg
Прошиваем программу сканера диапазона
Spoiler
/*
Победа над nRF24L01: на три шага ближе, сканер эфира
https://habr.com/ru/post/476716/
*/

/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/

/**
Channel scanner

Example to detect interference on the various channels available.
This is a good diagnostic tool to check whether you're picking a
good channel for your application.

Inspired by cpixip.
See http://arduino.cc/forum/index.php/topic,54795.0.html
*/

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

//
// Hardware configuration
//

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10

RF24 radio(9, 10); //Arduino UNO

//
// Channel info
//

const uint8_t num_channels = 128;
uint8_t values[num_channels];

//
// Setup
//

void setup(void)
{
//
// Print preamble
//

Serial.begin(9600);
Serial.println("Scanner Air On");
printf_begin();

//
// Setup and configure rf radio
//

radio.begin();
radio.setAutoAck(false);

// Get into standby mode
radio.startListening();
radio.printDetails();
delay(5000);

// Print out header, high then low digit
int i = 0;
while ( i < num_channels )
{
printf("%x", i >> 4);
++i;
}
printf("\n\r");
i = 0;
while ( i < num_channels )
{
printf("%x", i & 0xf);
++i;
}
printf("\n\r");
}

//
// Loop
//

const int num_reps = 100;

void loop(void)
{
// Clear measurement values
memset(values, 0, sizeof(values));

// Scan all channels num_reps times
int rep_counter = num_reps;
while (rep_counter--)
{
int i = num_channels;
while (i--)
{
// Select this channel
radio.setChannel(i);

// Listen for a little
radio.startListening();
delayMicroseconds(512);
radio.stopListening();

// Did we get a carrier?
if ( radio.testCarrier() )
++values;
}
}

// Print out channel measurements, clamped to a single hex digit
int i = 0;
while ( i < num_channels )
{
printf("%x", min(0xf, values & 0xf));
++i;
}
printf("\n\r");
}

Начинаем сканировать.
Каждый столбик цифр - это свой канал.
011.png
Циферки от работы сетей Wi-Fi примерно совпадают с тем местом на диапазоне, что показал анализатор.
В середине работы включаю передатчик (выделено красным).

Значит что-то передаётся и что-то принимается.
Уже хорошо.

P.S.
Кстати, на передатчике пришлось поднять напряжение до +8 вольт.
При питании от +7В возникали ошибки передачи по SPI, если потрогать пальцем около сигнальных линий. Видимо надо снизить скорость обмена.

Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 08 фев 2022, 05:16

ru0aog писал(а):
07 фев 2022, 07:54
канал 00, частота 2400 МГц, сигнал +19 dBm,
канал 7F, частота 2520 МГц, сигнал +12 dBm.
Посмотрел описание частот каналов.
Канал 00 = 2400 МГц.
Каждый следующий канал отстоит на 1 МГц.
Канал 7F = 127. Частота 2400+127 = 2527 МГц.

Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 08 фев 2022, 06:08

Хм, забавно.
Вчера модули на передачу работали, а сегодня - нет.
Ответ дают, но тока не потребляют и сигнала на выходе нет.

dukovit
Сообщения: 14
Зарегистрирован: 09 янв 2025, 21:43
Благодарил (а): 1 раз
Поблагодарили: 4 раза

Модули NRF24L01+

Сообщение dukovit » 09 янв 2025, 21:53

Ну мне удалось обсепечивать управление через этот модуль метров до 500 примерно

Аватара пользователя
ru0aog
Сообщения: 1053
Зарегистрирован: 30 сен 2021, 05:50
Позывной: ru0aog
Город: Красноярск
Имя: Станислав
Благодарил (а): 138 раз
Поблагодарили: 151 раз

Модули NRF24L01+

Сообщение ru0aog » 14 янв 2025, 05:29

Очень хорошо. Поделитесь технологией и кодом.

dukovit
Сообщения: 14
Зарегистрирован: 09 янв 2025, 21:43
Благодарил (а): 1 раз
Поблагодарили: 4 раза

Модули NRF24L01+

Сообщение dukovit » 19 янв 2025, 10:08

ну кодом не поделюсь - не обессудьте. Там большая разработка и передатчик очень маленькая часть сиситемы. А технология - да вообще - воткнул модуль на 3.3В и все работает. Из нюансов было по конфигурации - работало только на 1й мощности из конфигурации. Собственно код - в нем на самом деле нет ничего интерсного. Интересное - это подружить контроллер и плату. чтобы по уровням сигналов все работало

dukovit
Сообщения: 14
Зарегистрирован: 09 янв 2025, 21:43
Благодарил (а): 1 раз
Поблагодарили: 4 раза

Модули NRF24L01+

Сообщение dukovit » 22 янв 2025, 00:56

Вот если вырезать все что касается собственно применения связки NRF24L01+Arduino NANOv3 то вот пример рабочего кода приемника:

Код: Выделить всё

/*
--------------------------------------------------------------------------------
  -Используемая плата радиосвязи NRF24L01
ОСОБЕННОСТИ ЭЛЕКТРОПИТАНИЯ: поскольку радиомодуль питается 3,3В от стабилизитора 
ардуины, То и ардуине на Vin подано 12В от внешнего источника питания. 
При питании 5В ардуины и 3,3В радиомодуля, возникает сбой: при питании
от USB, связь есть. А при подаче подного питания - пропадает.
--------------------------------------------------------------------------------
  ШИНА I2C
                      A3 <---> A3
                      A4 <---> A4

----------------------------------------------------------------
  ПОДКЛЮЧЕНИЕ РАДИОМОДУЛЯ:
  1 GND
  2 +3.3v
  3 D9
  4 D10
  5 D13
  6 D11
  7 D12


*/

#include <SPI.h>
#include <RF24.h>
#include <nRF24L01.h>
#include <Wire.h>
#include <EEPROM.h>

#define debug       true    //режим отладки 
#define Accum       A3      //здесь мерим напряжение питания
#define Power_relay A0      //подача напряжения на схему  
#define Light_relay A1      //управление освещением

//--------------радио--------------
const byte  address[6] = "00001";
RF24        radio(9,10); // для платы MEGA2560 radio(9,53);
int8_t      data[25];
bool        Light=false;
int         battarey;


//============================== Стартовая программа ===============================
void setup() 
  {
    //------------------- конфигурация ножек процессора
    pinMode (Accum,       INPUT);
    pinMode (Power_relay, OUTPUT);
    pinMode (Light_relay, OUTPUT);

    //------------------- включим силовое и выключим свет
    digitalWrite (Light_relay, LOW);
    digitalWrite (Power_relay, HIGH);
    
    Wire.begin (8);                   //Запуск шины I2C с адресом 0х08 
    Wire.onRequest(send_Data);        //обработчик запросов от потребителя информации
    
    //------------------- Инициализация радиомодуля
    if (debug) Serial.begin(115200);  //запускаем порт отладки
    if (debug) Serial.print("Starting radio... ");
    delay(1000);		      //пауза чтобы все включилось и загрузилось
    radio.begin();
    radio.setPALevel(RF24_PA_HIGH);   //мощность передатчика 
    radio.openReadingPipe(0, address);//канал связи 0
    radio.startListening();           //включен на прием
    delay(1000);
    
    if (radio.available()) Serial.println("OK");
        else Serial.println("error");
  }

//======================= передача данных на потребитель данных===================
void send_Data() 
  {
    uint8_t i=1;
    while (i<20)
      {
        //Wire.write( data[i] );    		//трансляция на потребитель данных 
        if (debug) Serial.print(data[i]); //при отладке выводим значение 
        if (debug) Serial.print(" ");     //в монитор порта
        i++;
      };
    delay(5);
  };   
}

//============================== Основная программа ===============================
void loop() {
  if (radio.available())
    {
      radio.read(&data, sizeof(data));    
    };
  
  delay(2);
}  
Собственно передатчик для этого комплекта был такой:

Код: Выделить всё

/*
стандартный джойстик с кнопкой (350р в ближайшем магазине):
ось джойстика         |     от/на себя  | лево/право | нажатие    | удержание 3 сек   
назначенное действие  | вперед/назад    | лево/право | действие 1 | действие 2

*/

#include <EEPROM.h>
#include "RF24.h"

#define  axess_1   A0  //
#define  axess_2   A1  //
#define  key_1     4   //

int8_t    AX1;
int8_t    AX2;

uint16_t  middle_AX1;
uint16_t  middle_AX2;

long pressed_key_1;
long now;


bool  but1;
bool  last_but_1;
bool  manual_mode       =true;
bool  calibrate         =false;
bool  light_ON          =false;

//-----------------  настройки радио  ----------------------
RF24 	   radio(9,10);                //создаем обьект радио
bool       radioNumber = 0;
const byte address[6] = "00001";
uint8_t    data[25];

//----------------- Стартовая программа ---------------------
void setup() 
{
  delay(500);
  
  middle_AX1=(analogRead(axess_1)/4);
  middle_AX2=(analogRead(axess_2)/4);
    
  pinMode (key_1, INPUT_PULLUP);
  Serial.begin (115200);

 // ========= инициализация радиомодуля ===================
  radio.begin();
  radio.setDataRate( RF24_1MBPS );
  Serial.println("Radio started..."); 	// Оповещаем о начале работы
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MAX);
  radio.stopListening();
  if (radio.available()) Serial.println ("Radio aviable!"); 
	else Serial.println ("not worked");
 
}

//=========== основная программа ==========================
void loop() 
{
  now=millis();				//текущее время контроллера
  int R;
  float alfa;
  AX1= (analogRead(axess_1)-512)/4;	//Считываем с помощью АЦП значение с
  AX2= (analogRead(axess_2)-512)/4;	//осей джойстика
					//Поскольку передача значений джойстика 
					//задумана в виде 1 байта для оси
					//то значения с АЦП делим на 4 и применяем
					//ограничение от -128 до +128
  AX1= ( constrain(AX1, -128, 128));
  AX2= ( constrain(AX2, -128, 128));
  
  Serial.print ("AX1=");		//для отладки выводим в монитор значения осей
  Serial.print (AX1);
  Serial.print (" AX2=");
  Serial.print (AX2);
   
  Serial.println();

  but1=digitalRead(key_1);		//опрос кнопок джойстика и дополнительных
  but2=digitalRead(key_2);
  but3=digitalRead(key_3);
  
  if ((but1 == false) and (last_but_1 == true)) pressed_key_1 = now;
  if ((but2 == false) and (last_but_2 == true)) pressed_key_2 = now;
  if ((but3 == false) and (last_but_3 == true)) pressed_key_3 = now;

  //------------------- действие 1/действие 2 ----------------------
  if ((but1 == true) and (last_but_1 == false)) 
    {
      if (now-pressed_key_1 < 500 )             //короткое нажатие
        {                                       //обработка нажатия
          Serial.println ("Pressing Button 1");
          manual_mode   = !manual_mode;         
        }
      if (now-pressed_key_1 > 2500)             //удержание более 3 сек
        {                                       //боработка удержания
          Serial.println ("Holding Button 1");
          calibrate = true;
        }
    }
    
    last_but_1 = but1;				//сохраняем текущее значение кнопок
    last_but_2 = but2;
    last_but_3 = but3;
    
    
  delay (100);

  if (not(but1) and not(but2))
    { 
      Serial.println("saved to eerptom..");

    }

  //data[1]  =  B00000001;  
  bitWrite ( data[1], 0, manual_mode);
  bitWrite ( data[1], 6, calibrate);
  
  data[2]  =  2;
  data[3]  =  AX1;
  data[4]  =  AX2;
  data[5]  =  0;
  data[6]  =  0;
  data[7]  =  0;
  data[8]  =  0;
  data[9]  =  0;
  data[9]  =  0;
  data[10]  =  B00000000;
  data[11]  =  B00000000;
  data[12]  =  B00000000;
  data[13]  =  B00000000;
  data[14]  =  B00000000;
  data[15]  =  B00000000;
  data[16]  =  B00000000;
  data[17]  =  B00000000;
  data[18]  =  B00000000;
  data[19]  =  B00000000;
   
 radio.write(&data,19);
 calibrate = false;			//считаем что сигнал передан и сбрасываем флаг
					//действия калибровки (действие 2)
 
}

Ответить

Вернуться в «SDR трансиверы»