Android Tutorial Arduino ADK Coda

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.

B4X:
AndroidAccessory(const char *manufacturer,
const char *model,
const char *description,
const char *version,
const char *uri,
const char *serial);
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.

B4X:
 void powerOn(void);
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.

B4X:
 bool isConnected(void);
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.

B4X:
 int read(void *buff, int len, unsigned int nakLimit = USB_NAK_LIMIT);
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.

B4X:
int write(void *buff, int len);
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
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
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!
 
Last edited:

OccamsArrow

New Member
Licensed User
Longtime User
I do hope this particular thread is not dead. I am pulling what's left of my hair out. My problem is the reliability of the transfer of numbers from the Arduino Uno to the android tablet. The Arduino Serial Monitor almost never misses a beat; giving me the correct values in the proper sequence. However, the transfer of numbers to the tablet is sporadically, and seemingly randomly unreliable about 25% of the time. The numbers are often cut at one end or the other - leaving me with numbers of the wrong magnitude. The facts that the serial monitor provides exactly what I need and my code does most of the time leads me to the suspicion this is a firmware issue. Is the tablet going off and doing housekeeping when I'm sending it information? I'm trying to send a fairly steady stream of data. How do I make the tablet stay focused (assuming that's the problem)? What did I overlook?

This is an application to run pump motors and replace 40 year old equipment. Fortunately, what I'm pumping (and you don't want to know what that is) flows very slowly. So, routine-wise, I have all the time in the world to deal with this substance.

I can provide my code if necessary but at the moment it looks a lot like the substance I'm trying to pump and smells just about as bad.
 

agraham

Expert
Licensed User
Longtime User
This is a standard network comms "feature". From http://www.b4x.com/android/forum/threads/asyncstreams-tutorial.7669/#content. My emphasis.

  1. Which mode / framework to choose?

    There are four modes or frameworks available: AsyncStreams, AsyncStreams in prefix mode, AsyncStreamsText class and AsyncStreamsObject class (based on prefix mode).

    Prefix mode can only be used if both sides of the connection follow the "prefix" protocol. In most cases you can only use this mode when you implement both sides of the connection. For example you are building a chat application.
    In this case you should use AsyncStreamsObject. AsyncStreamsObject doesn't expose the progress though it does support sending files of any size. If all you want to do is send very large files then you should consider following the FileTransfer example.

    If you are communicating with a non B4A app (and cannot implement the prefix protocol) then you have two options:
    - If the data sent and received is text based and each message ends with an end of line character(s) then you should use AsyncStreamsText. For example if you are connecting to an external GPS. Note that it is also possible to modify the class and support different delimiters.
    The advantage of using AsyncStreamsText is that it will build the messages correctly. You will not receive partial messages (or multiple messages together).
    - In other cases you should use AsyncStreams in regular mode. This means that there is no guarantee that each sent message will be received as a single message. In fact it is more or less guaranteed not to happen. So your code is responsible for correctly collecting and receiving the message.
 

adrianstanescu85

Active Member
Licensed User
Longtime User
Hi

I noticed an important bug when I integrated Arduino into my app. It took me a while to realize what was happening.

The problem appeared after I connected the Arduino and clicked the Connect button. Using the test app above everything worked well, I was expecting the usual dialog for permission to access the USB accessory, but in my app I got a full screen with my app icon, which was really odd! I later realized that the USB permission dialog uses the app icon to the whole of its size (I actually think it even enlarges it a few times), so since I was using a 512x512 px icon my whole screen got covered with the icon!

I have two questions:
1) How can I get rid of the app icon being shown at the top of that USB accessory permission dialog, or force it to show a fixed size icon?
2) How can I grant automatic access to the USB accessory (the Arduino) so that the dialog wouldn't be necessary all together?

In the mean time I reduced the size of the icon as a bypass solution, but that's not the best way to solve this.

Any help?

Thank you!
 
Top