Помните, как мы удаленно мигали светодиодом при помощи NRF24L01 , а затем использовали этот же беспроводной модуль для управления гусеничным роботом ? В этих заметках модуль мы использовали по принципу «подключаем к таким-то пинам, берем готовую библиотеку, пишем пару строк кода и все работает, магия». Так вот, мне не нравится магия. Я программист, а не колдун, и потому хочу знать точно, что там и в каком виде передается в эфире. К счастью, Software Defined Radio позволяет с легкостью это увидеть.
Итак, первым делом я залил в Arduino следующий скетч:
#include «nRF24L01.h»
#include «RF24.h»
RF24 radio ( 9 , 10 ) ;
void setup ( void )
{
radio. begin ( ) ;
radio. setChannel ( 108 ) ;
radio. setPALevel ( RF24_PA_LOW ) ;
radio. setDataRate ( RF24_250KBPS ) ;
radio. openWritingPipe ( 0xA1B2C3D4E5 ) ;
}
void loop ( void )
{
uint8_t state [ ] = { 0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 } ;
delay ( 100 ) ;
radio. write ( & state, sizeof ( state ) ) ;
}
Как видите, он просто передает раз в 100 мс довольно бессмысленный пакет размером 8 байт на 108-м канале. С помощью LimeSDR и Gqrx несложно увидеть, что сигнал, в соответствии с нашими ожиданиями, передается на частоте 2508 МГц (2400 + номер канала). Также Gqrx позволяет записать сигнал в файл, чтобы сигнал этот можно было, например, лучше рассмотреть в Inspectrum:
Каждый вызов radio.write
сопровождается посылкой 16-и пакетов (см верхнюю часть картинки). Забегая немного вперед отмечу, что пакеты абсолютно идентичны и посылаются повторно исключительно для избыточности. Если приблизить один из этих пакетов (см нижнюю часть картинки), можно фактически увидеть единички и нолики, передаваемые при помощи изменения частоты сигнала. Как нам уже известно, NRF24L01 использует модуляцию GFSK , поэтому такой результат был вполне ожидаем. В сигнале можно заметить длинную последовательность нулей. Это тоже вполне объяснимо, если вспомнить, что максимальный размер пакета у NRF24L01 составляет 32 байта, из которых мы использовали только 8.
Декодировать GFSK можно при помощи такого проекта в GNU Radio:
Изучать получившийся в итоге сигнал можно, конечно, и в Scope Sink, но на практике это не очень-то удобно. Scope Sink подходит разве что для визуального определения, что что-то действительно декодировалось. Для просмотра получившегося сигнала лучше подходит утилита под названием baudline . Открываем файл, указав sample rate, использованный при записи (в моем случае это 5000000), а также формат 32 bit float, little endian. Открываем окно waveform и ищем что-то вроде:
Фактически, это уже единички и нолики в чистом виде. Как не видите единичек и ноликов? Да вот же они:
Здесь красная полоска означает границу бита, а синяя полоска — границу байта. Аккуратно выписав единички и нолики, получаем:
10100001 A1 <- 5 байт адреса
10110010 B2
11000011 C3
11010100 D4
11100101 E5
11001101 CD <- видимо, флаги
00000000 00 <- данные
00010001 11
00100010 22
00110011 33
01000100 44
…
То есть, при сильном желании теперь мы можем написать софтверный декодер пакетов. Только польза от такого проекта, на мой взгляд, будет несколько сомнительной. Во-первых, потому что такой проект уже есть , и, возможно, не один. А во-вторых, потому что пакеты намного проще декодировать при помощи самого NRF24L01 и Arduino. Может понадобиться разве что знать адрес передающего устройства, но мы только что выяснили, как его определить. Впрочем, если рассматривать задачу исключительно как code kata на выходные, то почему бы и нет.
Все исходники к посту, как обычно, вы найдете на GitHub .