Arduino Due Side:
In current Arduino IDE 1.6.5, both Arduino Due and ADK library are not include by default, so you have to:
- Install Arduino Due to Arduino IDE
- Install USBHost library to Arduino IDE
DurAdkLed.ino (same as before)
#include "variant.h"
#include <stdio.h>
#include <adk.h>
// Accessory descriptor. It's how Arduino identifies itself to Android.
char applicationName[] = "HelloADKLED"; // the app on your phone
char accessoryName[] = "Arduino Due"; // your Arduino board
char companyName[] = "Arduino-er";
// Make up anything you want for these
char versionNumber[] = "0.1";
char serialNumber[] = "1";
char url[] = "https://sites.google.com/site/arduinosite/exercise/androidadkled/AndroidADKLED_0.1.apk";
USBHost Usb;
ADK adk(&Usb, companyName, applicationName, accessoryName,versionNumber,url,serialNumber);
// Pin 13 has an LED connected on most Arduino boards.
int led = 13;
void setup() {
Serial.begin(9600);
cpu_irq_enable();
pinMode(led, OUTPUT);
//Indicate start of program
digitalWrite(led, LOW);
delay(2000);
digitalWrite(led, HIGH);
for(int i = 0; i <= 2; i++){
digitalWrite(led, HIGH);
delay(250);
digitalWrite(led, LOW);
delay(250);
}
}
#define RCVSIZE 128
void loop() {
char helloworld[] = "Hello World!\r\n";
uint8_t buf[RCVSIZE];
uint32_t nbread = 0;
Usb.Task();
if (adk.isReady()){
adk.read(&nbread, RCVSIZE, buf);
if (nbread > 0){
adk.write(nbread, buf);
//Convert nbread to String
String s = "";
for (uint32_t i = 0; i < nbread; ++i) {
s += (char)buf[i];
}
if(s == "LEDON"){
digitalWrite(led, HIGH);
}else if(s == "LEDOFF"){
digitalWrite(led, LOW);
}
}
}
}
Android Side:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blogspot.android_er.androidadkled" >
<uses-feature android:name="android.hardware.usb.accessory"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/myfilter"/>
</activity>
</application>
</manifest>
xml/myfilter.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory
manufacturer="Arduino-er"
model="HelloADKLED"
version="0.1"/>
</resources>
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arduino-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:id="@+id/textin"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/LedOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED On" />
<RadioButton
android:id="@+id/LedOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED Off" />
</RadioGroup>
</LinearLayout>
AbstractAdkActivity.java
package com.blogspot.android_er.androidadkled;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.AppCompatActivity;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public abstract class AbstractAdkActivity extends AppCompatActivity {
private static int RQS_USB_PERMISSION = 0;
private static final String ACTION_USB_PERMISSION = "arduino-er.usb_permission";
private PendingIntent PendingIntent_UsbPermission;
private UsbManager myUsbManager;
private UsbAccessory myUsbAccessory;
private ParcelFileDescriptor myAdkParcelFileDescriptor;
private FileInputStream myAdkInputStream;
private FileOutputStream myAdkOutputStream;
boolean firstRqsPermission;
//do something in onCreate()
protected abstract void doOnCreate(Bundle savedInstanceState);
//do something after adk read
protected abstract void doAdkRead(String stringIn);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
myUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(myUsbReceiver, intentFilter);
//Ask USB Permission from user
Intent intent_UsbPermission = new Intent(ACTION_USB_PERMISSION);
PendingIntent_UsbPermission = PendingIntent.getBroadcast(
this, //context
RQS_USB_PERMISSION, //request code
intent_UsbPermission, //intent
0); //flags
IntentFilter intentFilter_UsbPermission = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(myUsbPermissionReceiver, intentFilter_UsbPermission);
firstRqsPermission = true;
doOnCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
if(myAdkInputStream == null || myAdkOutputStream == null){
UsbAccessory[] usbAccessoryList = myUsbManager.getAccessoryList();
UsbAccessory usbAccessory = null;
if(usbAccessoryList != null){
usbAccessory = usbAccessoryList[0];
if(usbAccessory != null){
if(myUsbManager.hasPermission(usbAccessory)){
//already have permission
OpenUsbAccessory(usbAccessory);
}else{
if(firstRqsPermission){
firstRqsPermission = false;
synchronized(myUsbReceiver){
myUsbManager.requestPermission(usbAccessory,
PendingIntent_UsbPermission);
}
}
}
}
}
}
}
//Write String to Adk
void WriteAdk(String text){
byte[] buffer = text.getBytes();
if(myAdkOutputStream != null){
try {
myAdkOutputStream.write(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
protected void onPause() {
super.onPause();
closeUsbAccessory();
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myUsbReceiver);
unregisterReceiver(myUsbPermissionReceiver);
}
Runnable runnableReadAdk = new Runnable(){
@Override
public void run() {
int numberOfByteRead = 0;
byte[] buffer = new byte[255];
while(numberOfByteRead >= 0){
try {
numberOfByteRead = myAdkInputStream.read(buffer, 0, buffer.length);
final StringBuilder stringBuilder = new StringBuilder();
for(int i=0; i<numberOfByteRead; i++){
stringBuilder.append((char)buffer[i]);
}
runOnUiThread(new Runnable(){
@Override
public void run() {
doAdkRead(stringBuilder.toString());
}});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
}
}
}
};
private BroadcastReceiver myUsbReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)){
UsbAccessory usbAccessory =
(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if(usbAccessory!=null && usbAccessory.equals(myUsbAccessory)){
closeUsbAccessory();
}
}
}
};
private BroadcastReceiver myUsbPermissionReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(ACTION_USB_PERMISSION)){
synchronized(this){
UsbAccessory usbAccessory =
(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)){
OpenUsbAccessory(usbAccessory);
}else{
finish();
}
}
}
}
};
private void OpenUsbAccessory(UsbAccessory acc){
myAdkParcelFileDescriptor = myUsbManager.openAccessory(acc);
if(myAdkParcelFileDescriptor != null){
myUsbAccessory = acc;
FileDescriptor fileDescriptor = myAdkParcelFileDescriptor.getFileDescriptor();
myAdkInputStream = new FileInputStream(fileDescriptor);
myAdkOutputStream = new FileOutputStream(fileDescriptor);
Thread thread = new Thread(runnableReadAdk);
thread.start();
}
}
private void closeUsbAccessory(){
if(myAdkParcelFileDescriptor != null){
try {
myAdkParcelFileDescriptor.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
myAdkParcelFileDescriptor = null;
myUsbAccessory = null;
}
}
MainActivity.java
package com.blogspot.android_er.androidadkled;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AbstractAdkActivity {
TextView textIn;
RadioButton ledOn, ledOff;
@Override
protected void doOnCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
textIn = (TextView)findViewById(R.id.textin);
ledOn = (RadioButton)findViewById(R.id.LedOn);
ledOff = (RadioButton)findViewById(R.id.LedOff);
ledOn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
WriteAdk("LEDON");
Toast.makeText(getApplicationContext(),
"LEDON", Toast.LENGTH_LONG).show();
}
}});
ledOff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
WriteAdk("LEDOFF");
Toast.makeText(getApplicationContext(),
"LEDOFF", Toast.LENGTH_SHORT).show();
}
}});
}
@Override
protected void doAdkRead(String stringIn) {
textIn.setText(stringIn);
}
}
Following exactly your instruction but on Arduino Due compiling get this error:
ReplyDeletearm-none-eabi-gcc: error: C:\Users\WKHO~1\AppData\Local\Temp\build5105731938559175413.tmp/core/syscalls_sam3.c.o: No such file or directory
Error compiling.
Can I know which version of Arduino IDE you use?
DeleteI had the same problem with the SAM Boards version 1.6.5 and 1.6.6. When I went back to 1.6.4 everything worked fine.
DeleteThis is fantastic! It's so rare to find such a complete example that works perfectly on the first time. I really appreciate this. It surely has saved me a bunch of work. Thanks, dude!
ReplyDeleteI can get my Nexus 5 to write to the Arduino and toggle the LED, but my read function fails -- java.io.Exception: read failed: EIO (I/O error). It seems strange that one works and the other doesn't. Any ideas? I'm running the same code you've posted.
ReplyDelete