TL; DR - 我不明白为什么在窃听遥控器上的 SPI 命令后,我无法用 Arduino 和 NRF24L01 复制四轴飞行器的遥控器。
所以我得到了这个便宜的四轴飞行器,实际上有 3 种不同的型号(这个、这个和这个,三个模型的原理都是一样的)所有模型都使用BK2423 无线电,它应该与NRF24l01空气兼容- 这就是我所拥有的.
因此,由于我在网上(令人惊讶地)发现有关此事的信息很少,因此我在遥控器的 MPU 和它的 BK2423 之间放置了一些探针,并使用 Saleae Logic Analyzer 读取两者之间在 SPI 总线上运行的通信。我发现它有 3 个主要阶段:配置、搜索/绑定和命令,其中 MCU 执行一些调整,如下所述。
在配置阶段,正在设置一些寄存器,例如 Rx 的管道编号和地址、RF 通道等。这是配置捕获的一部分:
所以初始 Tx(和 Rx)地址是 5 个字节:0xCCCCCCCCCC。并且初始 RF 通道是0x2D。两个芯片的默认地址长度为 5 字节,由于遥控器不会改变它,因此长度应保持为 5 字节。
然后是搜索阶段。在那个阶段,遥控器一遍又一遍地发送基本相同的数据,只是改变了射频信道。这是最后一个搜索包:
因此,在使用不同的 RF 通道进行多次传输后,会发生一些奇怪的事情。遥控器击中了四轴飞行器的正确 RF 通道,但我无法弄清楚他是如何理解这一点的,因为状态寄存器(在 MISO 通道上)在最后一个搜索数据包中保持不变。这是远程控制 MCU 告诉 BK2423 更改射频通道的地方,周围没有任何其他证据:
然后 MCU 告诉 BK2423 将地址和 RF 通道更改为正确的。它一定是正确的,因为四轴飞行器反应正确:
从此,遥控器发出指令包,四轴飞行器愉快地飞来飞去。我无法正确通过搜索阶段。
我使用了这个项目中的一些代码(取自这个页面)并更改了 HCD.cpp 以匹配我嗅探到的内容。这里仅是我更改的两种方法(该文件中的其余代码保持不变):
void HCD::bind(unsigned char *ID)
{
for(unsigned char i=0;i<4;i++)
noteID[i]=ID[i];
state=HS_CONNECT;
radio.offline();
radio.txbuf[0] = 0x3F;
radio.txbuf[1] = 0x4C;
radio.txbuf[2] = 0x84;
radio.txbuf[3] = 0x6F;
radio.txbuf[4] = 0x9C;
radio.txbuf[5] = 0x20;
radio.sendBuffer(6);
radio.txbuf[0] = 0x3E;
radio.txbuf[1] = 0xC9;
radio.txbuf[2] = 0x9A;
radio.txbuf[3] = 0xB0;
radio.txbuf[4] = 0x61;
radio.txbuf[5] = 0xBB;
radio.txbuf[6] = 0xAB;
radio.txbuf[7] = 0x9C;
radio.sendBuffer(8);
radio.txbuf[0] = 0x39;
radio.txbuf[1] = 0x0B;
radio.txbuf[2] = 0xDF;
radio.txbuf[3] = 0xC4;
radio.txbuf[4] = 0xA7;
radio.txbuf[5] = 0x03;
radio.sendBuffer(6);
radio.txbuf[0] = 0x30;
radio.txbuf[1] = 0xCC;
radio.txbuf[2] = 0xCC;
radio.txbuf[3] = 0xCC;
radio.txbuf[4] = 0xCC;
radio.txbuf[5] = 0xCC;
radio.sendBuffer(6);
radio.txbuf[0] = 0x2A;
radio.txbuf[1] = 0xCC;
radio.txbuf[2] = 0xCC;
radio.txbuf[3] = 0xCC;
radio.txbuf[4] = 0xCC;
radio.txbuf[5] = 0xCC;
radio.sendBuffer(6);
radio.txbuf[0] = 0xE1;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0] = 0xE2;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0] = 0x27;
radio.txbuf[1] = 0x70;
radio.sendBuffer(2);
radio.txbuf[0] = 0x21;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0] = 0x22;
radio.txbuf[1] = 0x01;
radio.sendBuffer(2);
radio.txbuf[0] = 0x23;
radio.txbuf[1] = 0x03;
radio.sendBuffer(2);
radio.txbuf[0] = 0x25;
radio.txbuf[1] = 0x2D;
radio.sendBuffer(2);
radio.txbuf[0] = 0x24;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0] = 0x31;
radio.txbuf[1] = 0x09;
radio.sendBuffer(2);
radio.txbuf[0] = 0x26;
radio.txbuf[1] = 0x07;
radio.sendBuffer(2);
radio.txbuf[0] = 0x50;
radio.txbuf[1] = 0x73;
radio.sendBuffer(2);
radio.txbuf[0] = 0x3C;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0] = 0x3D;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0] = 0x31;
radio.txbuf[1] = 0x09;
radio.sendBuffer(2);
radio.txbuf[0] = 0x1D;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
}
void HCD::update(unsigned char *payload)
{
Serial.print("Sending, state: ");
Serial.print(state);
Serial.print(" Channel: ");
Serial.println(channel);
unsigned char c=0;
switch(state)
{
case HS_CONNECT:
radio.offline();
radio.txbuf[0] = 0x27;
radio.txbuf[1] = 0x70;
radio.sendBuffer(2);
radio.txbuf[0] = 0xE1;
radio.txbuf[1] = 0x00;
radio.sendBuffer(2);
radio.txbuf[0]=0x25;
radio.txbuf[1]= channel; //0x2A;
radio.sendBuffer(2); //-Chan
//radio.block(baseAddress);
//radio.block(flushTX);
radio.txbuf[0]=0xA0;
radio.txbuf[1]=0x20;
radio.txbuf[2]=0x14;
radio.txbuf[3]=0x03;
radio.txbuf[4]=0x25;
radio.txbuf[5]=0x1F; //noteID[0];
radio.txbuf[6]=0xC3; //noteID[1];
radio.txbuf[7]=0x00; //noteID[2];
radio.txbuf[8]=0xE2; //noteID[3];
radio.txbuf[8]=0xAA; //noteID[3];
radio.sendBuffer(9); //-tx data
//radio.block(PTX);
radio.online();
while(!c)
c=radio.getStatus();
radio.clrStatus();
Serial.print("Status: " );
Serial.println(c);
if(c&0x10) //MRT
{
state=HS_UNINITIALIZED;
Serial.println("Uninitializing :( Connecting");
}
if(c&0x20) //ACK
{
Serial.println("ACK Connecting");
state=HS_CONNECTED;
}
break;
case HS_CONNECTED:
radio.offline();
radio.txbuf[0]=0x25;
radio.txbuf[1]=channel;
radio.sendBuffer(2); //-Chan
radio.txbuf[0]=0x2a;
radio.txbuf[1]=noteID[0];
radio.txbuf[2]=noteID[1];
radio.txbuf[3]=noteID[2];
radio.txbuf[4]=noteID[3];
radio.txbuf[5]=0xCC;
radio.sendBuffer(6); //-tx data
radio.txbuf[0]=0x30;
radio.txbuf[1]=noteID[0];
radio.txbuf[2]=noteID[1];
radio.txbuf[3]=noteID[2];
radio.txbuf[4]=noteID[3];
radio.txbuf[5]=0xAA;
radio.sendBuffer(6); //-tx data
radio.online();
radio.block(flushTX);
radio.txbuf[0]=0xA0;
radio.txbuf[1]=payload[0];
radio.txbuf[2]=payload[1];
radio.txbuf[3]=payload[2];
radio.txbuf[4]=payload[3];
radio.txbuf[5]=payload[4];
radio.txbuf[6]=payload[5];
radio.txbuf[7]=payload[6];
radio.txbuf[8]=payload[7];
radio.sendBuffer(9); //-tx data
radio.txbuf[0]=0x20;
radio.txbuf[1]=0x7A; //-TX
radio.sendBuffer(2);
while(!c)
c=radio.getStatus();
radio.clrStatus();
if(c&0x10) //MRT
{
Serial.println("MRT - connected");
}
if(c&0x20) //ACK
{
Serial.println("ACK - connected");
}
break;
}
}
我正在使用一个相当简单的 Arduino 草图来调用这些方法(这是上述项目中 INO 文件的修改版本):
#include <HCD.h>
HCD drone0;
unsigned char ID0[]={
0x1F, 0xC3, 0x00, 0xCC};
unsigned char payload0[]={ 0x0, 0x20, 0x14, 0x03, 0x25, 0x1F, 0xC3, 0x00 };
unsigned char payload1[]={
0x00,0x70,0x70,0x1E,0x1E,0x00,0x10,0x7E};
void setup()
{
Serial.begin(19200);
Serial.println("ON");
Serial.println("Connecting a");
drone0.bind(ID0);
drone0.setChannel(0x25);
}
unsigned long timer=0;
unsigned char chs[] = { 0x2A, 0x20, 0x34, 0x16, 0x3E, 0x0C, 0x48};
void loop()
{
for (int i=0; i<128; i++)
{
drone0.setChannel(i);
drone0.update(payload0);
delay(10);
}
delay(2000);
drone0.setChannel(0x2);
drone0.update(payload1);
delay(2000);
}
然而,四轴飞行器似乎轻轻地忽略了这个代码和它的许多变体。
如果有人在我的问题中遇到了这条线,我将不胜感激他/她可以提供的任何帮助。