Arduino Mega ADK奇怪的acc.write()行为(巨大的延迟)NAK问题似乎得到了证实。由于acc.write,Android会生成NAK

时间:2015-01-14 15:42:22

标签: android arduino adk

我正在尝试在Arduino Mega Adk(ADK 2011)和Android设备之间进行通信。 有些事情没问题,但有些事情是完全错误的。 通过来自Arduino端的acc.read将数据从Android传输到Arduino工作正常。 但是当我尝试将一些字节从Arduino发送到Android时 - 发生了一些奇怪的事情。 首先,这里是Arduino sketch:

    #include <Max3421e_constants.h>
    #include <Max3421e.h>
    #include <Usb.h>
    #include <AndroidAccessory.h>

    #define COMMAND_LED 0x2
    #define TARGET_PIN_18 0x12
    #define TARGET_PIN_19 0x13
    #define V_ON 0x1
    #define V_OFF 0x0

    #define PIN_18 18
    #define PIN_19 19
    #define INPUT_PIN 30


    AndroidAccessory acc("Google, Inc.",
                 "DemoKit",
                 "Ololo device board",
                 "1.0",
                 "http://www.android.com",
                 "0000000012345678");

    byte rcvmsg[3];
    byte sndmsg[3];
    int buttonState = 0;

    void setup();
    void loop();

    void led_setup(){
      pinMode(PIN_18, OUTPUT);     
      pinMode(PIN_19, OUTPUT);
      pinMode(INPUT_PIN, INPUT);
    }
    void setup()
    {
      Serial.begin(115200);
      Serial.print("\r\nStart");
      led_setup();
      acc.powerOn();
    }
    void loop()
    {
      if (acc.isConnected()) {
     buttonState = digitalRead(INPUT_PIN);
      if (buttonState == 1){
       sndmsg[0] = 0x2;
       sndmsg[1] = 0x1;
       sndmsg[2] = 0x1;
       int len = acc.write(sndmsg, 3);
       digitalWrite(PIN_19, HIGH);
      }
      else {
       //Nothing here for test
      }  
    }
  //usefull test for button  
     buttonState = digitalRead(INPUT_PIN);
     if (buttonState == 1){
       digitalWrite(PIN_19, HIGH);
      }
      else {
        digitalWrite(PIN_19, LOW);
      }
    }

确定。执行acc.write()时,需要大约1秒才能将数据传输到android。而这次不依赖于sndmsg中的字节数。只有当我执行acc.write(sndmsg,0)(发送0字节)时 - 一切都很快。 这有点令人不安。我试图将电路板改为另一个但是得到了相同的结果。 有什么建议吗?可能这是一个常见的错误,但在网络上没有这么多的信息。

UPD: 写了一些非常简单的代码,只通过acc.write发送3个字节。 这是:

#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>

AndroidAccessory acc("Google, Inc.",
             "DemoKit",
             "Demokit board",
             "1.0",
             "http://www.android.com",
             "0000000012345678");


byte msg[3];
unsigned long time;
void setup();
void loop();
void led_setup(){
}
void setup()
{
  Serial.begin(115200);
  Serial.print("\r\nStart");
  acc.powerOn();
}
void loop()
{
  if (acc.isConnected()) {
   Serial.print("\r\nis Connected");
   msg[0] = 0x1;
   msg[1] = 0x1;
   msg[2] = 0x1;
   //Serial.print("\r\nSending");
   time = millis();
   Serial.print ("\r\nBefore write\r\n");
   Serial.print (time);
   acc.write(msg, 3);
   time = millis();
   Serial.print("\r\nAfter write: \r\n");
   Serial.print (time);
   //delay(500);
  }
}

它的调试输出是:

is Connected
Before write
6983
After write: 
10958
is Connected
Before write
10958
After write: 
14491
is Connected

等等。因此,由于某些原因,acc.write需要花费大量时间,并且Android应用程序中没有数据。

新UPD(2015年1月19日)

今天我做了一些实验。这是结果。 首先,我查看了AndroidAccessory.cpp并找到了写函数:

 int AndroidAccessory::write(void *buff, int len)
    {
        usb.outTransfer(1, out, len, (char *)buff);
        return len;
    }

好的,然后我查看usb主机屏蔽库,发现usb.cpp有outTransfer功能,如果ouckured则返回错误代码,如果一切正常则返回0x00。 所以我修改了write函数来返回错误代码而不是lenght,如下所示:

int AndroidAccessory::write(void *buff, int len)
{
    byte rcode;
    rcode =  usb.outTransfer(1, out, len, (char *)buff);
    return int(rcode);
}
结果

并收到“4”。 根据MAX3421Econstants.h,它是hrNAK(0x04)错误代码。 有任何想法吗?看起来配件没有从Android中恢复NAK,因此写入失败。

情况更新: 做了一些研究。当配件连接时,NAK有一个地狱。这是从usb连接器转储: enter image description here

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。它非常简单 - 我没有正确设置与配件的通信。 这不是Arduino问题。 Arduino工作得很好。 它就是android如何与android配件交互。 所以,结果:

  • 当AndroidAccessory插入Android并且Android尚未设置时 与配件通信,Android OS将发送很多 USB NAK到配件,这是正常的。
  • 你一定要小心 在设置与附件的通信期间。如果你做一些 错误,你可以收到同样的情况:可能写的 到配件,但附件是不可写的 机器人。
  • 如果UsbManager正确打开附件,则会停止发送 NAK并开始从arduino接收数据。

对我来说有点奇怪,因为很难找到问题:我有一个应用程序,根据本手册编写:http://developer.android.com/guide/topics/connectivity/usb/accessory.html但是,因为我对android不是很熟悉,似乎我犯了一些错误并且收到了奇怪的行为:

  • 我能写信给arduino
  • 我能够将有关arduino的信息作为android配件进行检索
  • 可以请求权限
  • 但是当arduino试图写入android时,它会收回很多NAK

所以我决定以更简单的方式重写程序,只需使用一个函数并尝试以正确的方式执行。经过一些调试后,它终于开始按我的意愿工作了。 非常感谢大家,他们花时间阅读本文。 奖励:转储正常数据包,以EOP而不是NAK结束 enter image description here

UPD 26.01.2015: 我发现问题,它在我的Android代码中。 这是解释:

Android开发人员手册说,设置与附件通信的功能必须启动它自己的线程,其中保存与输入和输出流的所有通信。像这样的Smth:

private void openAccessory() {
    Log.d(TAG, "openAccessory: " + accessory);
    mFileDescriptor = mUsbManager.openAccessory(mAccessory);
    if (mFileDescriptor != null) {
        FileDescriptor fd = mFileDescriptor.getFileDescriptor();
        mInputStream = new FileInputStream(fd);
        mOutputStream = new FileOutputStream(fd);
        Thread thread = new Thread(null, this, "AccessoryThread");
        thread.start();
    }
}

我真的搞砸了这件事。忘了在openAccessory函数中创建新线程并试图在不同的地方进行。并收到了NAK的地狱。然后我改变了我的代码并添加了一些类似于调试的run()函数:

public void run() {
        final byte[] buffer = new byte[16384];
        int ret = 0;
        int i = 0;
        while (i<50) {
            try {
                ret = mInputStream.read(buffer);
                i++;
                Thread.sleep(500);
            } catch (IOException e) {
                break;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

直到此运行方法存在(而我<50),android正确读取arduino。当线程结束时(i> 50) - Arduino开始从Android读出错误代码4(NAK)。

这就是所有人。