TL; DR-我无法弄清楚为什么在监听SPI命令后无法使用Arduino和NRF24L01复制Quadcopter的遥控器。

所以我买了这款便宜的四轴飞行器,实际上是3种不同的型号(此,此和该,并且三个型号的原理都相同)
所有型号都使用BK2423无线电,应该是与NRF24l01空气兼容-这就是我所拥有的。

因此,由于我在网上发现(令人惊讶地)有关此问题的信息很少,因此我在遥控器的MPU和BK2423之间放置了一些探针,并使用Saleae Logic Analyzer读取了SPI总线上运行的通信两者之间。我发现它有3个主要阶段:Config,Search / Bind和Command,在这两个阶段之间,MCU会执行一些调整,如下所述。

在Config阶段,正在设置一些寄存器,例如Rx的管道编号以及地址,RF通道等。这是配置捕获的一部分:


因此初始Tx(和Rx)地址为5个字节:0xCCCCCCCCCC。
初始RF通道为0x2D。
这两个芯片的默认地址长度为5个字节,并且由于遥控器不更改它,因此该长度应保持5个字节。在该阶段,远程设备反复发送基本相同的数据,并且仅更改RF通道。这是最后一个搜索数据包:



因此,在使用不同的RF通道进行多次传输之后,发生了一些奇怪的事情。遥控器为四轴飞行器找到了正确的RF通道,但是我无法弄清楚他是如何理解的,因为状态寄存器(在MISO通道上)在最后一个搜索数据包中保持不变。此处,远程控制MCU告诉BK2423更改RF通道,而周围没有其他证据:
然后,MCU通知BK2423将地址和RF通道更改为正确的地址和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;

  }
}

这些方法(这是上述项目中INO文件的修改版本): 。

如果有人在我的问题上提到这条线,我将感谢他/她可以提供的任何帮助。

评论

恐怕我不具备帮助您的知识,但是我希望对RE.SE的更多问题得到充分的研究和撰写。已发表。

#1 楼

在您的代码中有一些我无法理解的项目:


在初始的“绑定”例程中,有命令0x3F,0x3E,0x39,它们对应于寄存器1F,1E,19如果我了解这项权利。这些没有记录在NRF24l01数据表中(顺便说一句,您的链接不起作用)。
使用正确的命令0xA0发送有效载荷。但是,您总共发送了9个字节,包括命令。这是否意味着您要发送的有效负载仅包含八个字节?在其中一个有效载荷发送命令中,将txbuf [8]放置了两次。也许您的意思是第二次txbuf [9]?
作为最后一条命令,您发送了0x20。如果我做对了,这就是“写入配置”。

否则,我对四旋翼机一无所知(只是亚马逊想使用它们...)

评论


感谢您的发言! 1.正确-我只是复制了逻辑分析器捕获的内容。 2.再次正确。第二[8]是个错误。 3.这与原始代码相同,基本上也可以在此阶段出现,对此寄存器可以在流中的何处进行配置没有限制,所以我想应该可以。


15年7月12日在12:58



但是,由于有效载荷大小已设置为9,因此您不应该总共发送10个字节吗?当包含命令时,您还将在逻辑分析器中捕获10个字节。

–乔什
15年7月12日在13:29



对。默认有效负载为8字节,他们没有更改。但是在其他所有方法都失败之后,我决定完全复制捕获的内容。我知道这没有意义,与不存在的寄存器1F和1E一样,但这是我几次嗅探的内容。有这种差异的经验吗?


15年7月12日在13:45

对不起,我没听懂。在“绑定”例程中,将有效载荷长度设置为9个字节(命令0x31),但是随后仅发送8个字节的有效载荷。为什么?但是也许我让您完全错了,而我们正在谈论的是不同的话题。我对微控制器的经验有限。

–乔什
2015年7月12日14:11



我想你又对了。我错过了。在某个阶段,我只是复制了字节,实际上0x31后跟0x9意味着有效负载设置为9个字节。修复双“ txbuf [8]”的错误也应反映出来(意味着包括命令在内总共10个字节)。我应该执行此修复程序并更新问题(谁知道,也许这是问题所在!! ...)


15年7月12日在14:34