سؤال

I am trying to write an Android application that can send and receive serial data to and from an Arduino board that is connected by an On-The-Go (OTG) adapter. I am using the usb-serial-for-android library. I am setting the Arduino up so that if it receives the string "T" then it will send the string "T" back. The Android is set up so that it will do the same, although if the string variable dataToSend isn't empty then it will send the value of that along with the "T". I basically want these two to send data back and forth. The Arduino side of this project is working perfectly, whenever it receives data it records everything to an SD card, and if it detects the "T" it will send a "T" back to tell the Android it can send again.

Here is my code, sorry for the length but I feel that there could be multiple places that could be the problem:

public class MainActivity extends Activity {

private boolean canSend;
private boolean notInit; 
private String dataToSend; 
private UsbManager manager;
private SerialInputOutputManager serialIoManager; 
private static UsbSerialDriver sendDriver; 
private static UsbSerialDriver recDriver; 
private TextView outputText; 
private ExecutorService mExecutor = Executors.newSingleThreadExecutor(); 
private SerialInputOutputManager.Listener mListener = new    SerialInputOutputManager.Listener() {

    @Override
    public void onRunError(Exception e) {   }

    @Override
    public void onNewData(final byte[] data) {

        MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {

                MainActivity.this.updateReceivedData(data);

            } catch (IOException e) { e.printStackTrace(); }
                    }
                 });

    }
}; 

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    dataToSend = ""; 
    notInit = true; 
    canSend = true; 
    outputText = (TextView) findViewById(R.id.textView1); 
}

@Override
    protected void onPause() {
    super.onPause();
    stopIoManager();
    if (recDriver != null) {
        try {
            recDriver.close();
        } catch (IOException e) {
            // Ignore.
        }
        recDriver = null;
    }
    finish();
}

@Override
protected void onResume() {
    super.onResume();

        manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        recDriver = UsbSerialProber.acquire(manager);


    if (recDriver == null) {

        } else {
              try {
                  recDriver.open();
                  recDriver.setBaudRate(9600); 
            } catch (IOException e) {
                  try {
                  recDriver.close();
              } catch (IOException e2) {
                    // Ignore.
                }
              recDriver = null;
              return;
            }
            recDriver.getClass().getSimpleName());
        }
        onDeviceStateChange();
    }

 private void stopIoManager() {

    // Get UsbManager from Android.
    manager = (UsbManager) getSystemService(Context.USB_SERVICE);

    // Find the first available driver.
    recDriver = UsbSerialProber.acquire(manager);

        if (serialIoManager != null) {
            Log.i("Device", "Stopping io manager ..");
            serialIoManager.stop();
            serialIoManager = null;
        } else {

            Log.d("Device", "recDriver NULL"); 
        }
    }

 private void startIoManager() {
        // Get UsbManager from Android.
        manager = (UsbManager) getSystemService(Context.USB_SERVICE);

        // Find the first available driver.
        recDriver = UsbSerialProber.acquire(manager);

        if (recDriver != null) {
            Log.i("Device", "Starting io manager ..");
            serialIoManager = new SerialInputOutputManager(recDriver, mListener);
            mExecutor.submit(serialIoManager);
        } else {

            Log.d("Device", "recDriver NULL"); 
        }
    }

 private void onDeviceStateChange() {
        stopIoManager();
        startIoManager();
    }

protected void updateReceivedData(byte[] data) throws IOException {
    //use the data

     Log.d("Device", "is updating"); 

     final String dataIn = HexDump.dumpHexString(data);

     outputText.setText(dataIn); 

     canSend = checkForSend(dataIn);

     if (canSend) {

         sendData(); 
     }
}

private boolean checkForSend (String in) {

    String cur; 
    int len = in.length(); 

    for (int i = 0; i < len; i++) {

        cur = in.substring(i, i + 1); 

        if (cur.equals("T")) {

            return true; 
        } 

    }
    return false; 
}

static void show(Context context, UsbSerialDriver driver) {
    recDriver = driver;
    final Intent intent = new Intent(context, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public void requestSend(View v) {

    dataToSend = "9375644603\n"; 

    if (notInit) {

        try {
            sendData();

        } catch (IOException e) {

            e.printStackTrace();
        } 
    }

    notInit = false; 

}

private void sendData() throws IOException {

    // Get UsbManager from Android.
    manager = (UsbManager) getSystemService(Context.USB_SERVICE);

    // Find the first available driver.
    sendDriver = UsbSerialProber.acquire(manager);

    if (sendDriver != null) {
        sendDriver.open();
        try {
            sendDriver.setBaudRate(9600);

                            dataToSend = "2345\n";   
            if (!dataToSend.equals("")) {

                byte [] byteToSend = dataToSend.getBytes(); 
                sendDriver.write(byteToSend, 1000); 
            }

            dataToSend = ""; 

            byte[] terminator = "T\n".getBytes();
            sendDriver.write(terminator, 1000);

        } catch (IOException e) {
            // Deal with error.
        } finally {
            sendDriver.close();
        } 
    }

    // Get UsbManager from Android.
    manager = (UsbManager) getSystemService(Context.USB_SERVICE);

    // Find the first available driver.
    sendDriver = UsbSerialProber.acquire(manager);

}


}

Notice that I am trying to use two separate drivers with the same I/O manager. I am not sure if that should negatively affect it. I am able to send the data to the Arduino, and the Arduino's TX led comes on, so I know something is being sent. The onNewData method that is triggered when the SerialInputOutputManager listener detects incoming data is never being ran. So I take it that the driver for the manager's listener is not getting initialized correctly or something.

If anyone has a better method of talking between the Android and the Arduino via two-way usb serial, please let me know what it is. I have had a lot of trouble trying to get this to work.

هل كانت مفيدة؟

المحلول

I found that downloading the app Arduino Uno Communicator for Android, and using the Arduino Uno Communicator-Client code from the developer was the best option. I could easily broadcast intents and receive data using an intent filter, and the communication was obviously done on a separate thread, so I didn't have to worry about crashes. If you want to implement this method locally in your code, you can look at the source code of the app here.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top