Introduction
This final tutorial has some explanatory comments about the two programs running on the Arduino and the Android device. Those programs should be largely self-explanatory as they represent a simple, but complete, exposure of the APIs on both Arduino and Basic4android but the explanation given here might also be helpful
Arduino
Arduino programs are written in a simplified form C/C++ syntax, are translated to C++ source code and compiled by a C++ compiler targeting the Atmel MEG2560 chip in the Arduino board.
The API to make the Arduino look like an Accessory to Android is remarkably simple as you can see from the demo. The entire API consists of only a single constructor and four class methods.
The constructor takes a set of string arguments that are available from the similarly named properties in the Basic4android UsbAccessory object. In addition, if Android does not find an application that has registered to deal with that Accessory it will display a dialog on connection offering to open the URI provided in the constructor.
In the setup() function it is necessary to call the not very well named powerOn() method of the AndroidAccessory object which sets up the MAX3421E host USB interface chip after it has been powered on or reset. If this method is called too soon the phase locked loop of the chip may not have settled and a "starterror: OSCOKIRQ failed to assert" message will be displayed in the console window. The 500mS delay in the demo allows the PLL to settle and avoids this error.
The isConnected() method returns true if the Arduino is connected to an Android device and if the Android device has recognised it as an Accessory. Once that has occurred communication with programs running on the Android device is trivially easy.
Call the read() method to see if there is any data available from the Android device passing in the address of an array to receive any data and the maximum numbers of bytes to be returned and the return value will indicate the number of bytes copied into the buffer, if any. The nakLimit is an optional parameter that the Android Accessory demo sets to 1. The default is 32000 and is the number of NAKs that will be accepted during a USB transfer. Setting this parameter to 0 means that NAKs are not counted and are ignored. A NAK in the USB protocol reports that the Android device temporarily cannot send or received data. If communications problems occasionally arise it would be worth setting this to a value greater than one. The default limit looks far too high to me and appears to be an entirely arbitrary value.
Sending data is merely a matter of calling the write() method passing the address of an array containing the data to be send and the number of bytes to be sent.
Both read() and write() are asynchronous operations and so will not block your loop() function.
I included in the demo a useful freeRam() method which can be called at any time to determine the amount of Ram still available. Ram is a limited resource on the Arduino chip. The website ATmega memory use JeeLabs from which the freeRam() method was taken has a diagram of how memory is used. The site mentions 2Kb of Ram which applies to lesser Arduinos but our Arduino ADK has four times a much – a massive 8Kb! As that web page explains, strings can rapidly eat up RAM so a method has been provided in the Arduino 1.0 software that enables literal strings to be referenced directly from ROM without copying them to RAM. This is the F() function and as there is a relatively generous 256Kb of ROM available for programs it seems sensible to use this as much as possible.
Basic4android
The main item to take note of on the Basic4android side of things is the reconnect bug mentioned in detail in the previous tutorial.
The UsbAccessory in Basic4android is just as easy to use as the API on the Arduino. In order for your program to be able to use a UsbAccessory it needs permission and if it does not have permission you have to request permission from the user. The permission code below is structured as it is because the RequestAccessoryPermission dialog is non-modal so your code runs on while it is shown. Therefore you must exit the Sub and recheck for permission later otherwise your code will fail
Once you have permission you just open the UsbAccessory and pass its Streams to an instance of AsyncStreams and carry on as you want. You can send data whenever you need with the Write() method and your NewData() event will be called when data arrives from the Arduino.
The various other ways of btaining permission using the manifest and Intents are described here.
USB Accessory | Android Developers
On exit from your program you should close both the AsyncStream and UsbAccessory instances, but the bug mentioned earlier will prevent you reconnecting until your program process is killed and the Arduino reset or disconnected and reconnected.
Tutorials
In addition to this tutorial there are other tutorials. They are:
1. Introduction to the Arduino Mega ADK and Android Accessories. Introduction
2. Installing the Arduino IDE and compiling your first program. Installation
3. Connecting the Arduino Mega ADK to your computer and running programs on it. Programming
4. Connecting the Arduino Mega ADK to your Android device and writing both an Arduino and a Basic4android program to communicate with each other. Consummation
5. This one!
This final tutorial has some explanatory comments about the two programs running on the Arduino and the Android device. Those programs should be largely self-explanatory as they represent a simple, but complete, exposure of the APIs on both Arduino and Basic4android but the explanation given here might also be helpful
Arduino
Arduino programs are written in a simplified form C/C++ syntax, are translated to C++ source code and compiled by a C++ compiler targeting the Atmel MEG2560 chip in the Arduino board.
The API to make the Arduino look like an Accessory to Android is remarkably simple as you can see from the demo. The entire API consists of only a single constructor and four class methods.
B4X:
AndroidAccessory(const char *manufacturer,
const char *model,
const char *description,
const char *version,
const char *uri,
const char *serial);
B4X:
void powerOn(void);
B4X:
bool isConnected(void);
B4X:
int read(void *buff, int len, unsigned int nakLimit = USB_NAK_LIMIT);
B4X:
int write(void *buff, int len);
Both read() and write() are asynchronous operations and so will not block your loop() function.
I included in the demo a useful freeRam() method which can be called at any time to determine the amount of Ram still available. Ram is a limited resource on the Arduino chip. The website ATmega memory use JeeLabs from which the freeRam() method was taken has a diagram of how memory is used. The site mentions 2Kb of Ram which applies to lesser Arduinos but our Arduino ADK has four times a much – a massive 8Kb! As that web page explains, strings can rapidly eat up RAM so a method has been provided in the Arduino 1.0 software that enables literal strings to be referenced directly from ROM without copying them to RAM. This is the F() function and as there is a relatively generous 256Kb of ROM available for programs it seems sensible to use this as much as possible.
Basic4android
The main item to take note of on the Basic4android side of things is the reconnect bug mentioned in detail in the previous tutorial.
The UsbAccessory in Basic4android is just as easy to use as the API on the Arduino. In order for your program to be able to use a UsbAccessory it needs permission and if it does not have permission you have to request permission from the user. The permission code below is structured as it is because the RequestAccessoryPermission dialog is non-modal so your code runs on while it is shown. Therefore you must exit the Sub and recheck for permission later otherwise your code will fail
B4X:
If Not(USBman.HasAccessoryPermission(ADK)) Then
USBman.RequestAccessoryPermission(ADK) ' this is not a modal dialog so the the code will run on
Else
USBman.OpenAccessory(ADK)
AStream.Initialize(ADK.InputStream, ADK.OutputStream, "AStream")
End If
The various other ways of btaining permission using the manifest and Intents are described here.
USB Accessory | Android Developers
On exit from your program you should close both the AsyncStream and UsbAccessory instances, but the bug mentioned earlier will prevent you reconnecting until your program process is killed and the Arduino reset or disconnected and reconnected.
Tutorials
In addition to this tutorial there are other tutorials. They are:
1. Introduction to the Arduino Mega ADK and Android Accessories. Introduction
2. Installing the Arduino IDE and compiling your first program. Installation
3. Connecting the Arduino Mega ADK to your computer and running programs on it. Programming
4. Connecting the Arduino Mega ADK to your Android device and writing both an Arduino and a Basic4android program to communicate with each other. Consummation
5. This one!
Last edited: