Neurolab data transfer – Establishing serial communication between Arduino and Android

In the development process of the Neurolab Android, we needed an Arduino-Android connection for transfer of data from datasets which included String and float data type values. In this blog post, I will show you how to establish a serial communication channel between

Android and Arduino through USB cable through which we can transmit data bidirectionally.

Requirements

Hardware:

  1. Android Phone
  2. Arduino (theoretically from any type, but I’ll be using Arduino Uno)
  3. USB 2.0 Cable Type A/B (for Arduino)
  4. OTG Cable (On The Go)
  5. Normal USB Cable (for transferring the data from Android Studio to your phone)

Software:

  1. Android Studio
  2. Arduino IDE

Wiring and Setup

Wiring must be established in the following way:

                                                                                 Figure: Android-Arduino Setup

Working on the Android Side

We would be using the UsbSerial Library by felHR85 for establishing serial

communication.

1. Adding the dependency:

a) Add the following line of code to your app level build.gradle file.

implementation "com.github.felHR85:UsbSerial:$rootProject.usbSerialLibraryVersion"

Note: The ‘usbSerialLibraryVersion’ may change from time to time. Please keep your project with the latest library version. Updates can be found here.

b) Add jitpack to your project.build.gradle file.

allprojects {
   repositories {
       jcenter()
       maven { url "https://jitpack.io" }
   }
}

2. Working with Arduino:

We need to program the Arduino to send and receive data. We achieve that with the help of Arduino IDE as mentioned above. Verify, compile and upload a sketch to the Arduino for sending and receiving data. If you are a complete beginner in Arduino programming, there are example sketches for this same purpose. Load an example sketch from under the communication segment and choose the serial communication sketch. Here, we will be working with a simple sketch for the Arduino such that it simply echoes whatever it receives on the serial port. Here is sketch code:

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  char incomingByte;
   // If there is a data stored in the serial receive buffer, read it and print it to the serial port as human-readable ASCII text.
  if(Serial.available()){  
    incomingByte = Serial.read();
    Serial.print(incomingByte);  
  }
}

Feel free to compile and upload it to your own Arduino.

2. Working with Android:

  1. Firstly, we need an USBManager instance initialized with the system service – ‘USB_SERVICE’. This needs to be done in an Activity (preferably main) so that this instance can be passed to the Communication Handler class, which we are going to create next.
  2. Now, we will be working with a class for handling the serial communications with our Android device and the Arduino board. We would pass the USBManager instance to this class wherein work will be done with that to find the USBDevice and USBDeviceConnection

Starting with, we need to search for any attached Arduino devices to the Android device. We create a method for this and use the ‘getDevicesList’ callback to achieve this in the following way:

public void searchForArduinoDevice(Context context) {
        HashMap usbDevices = usbManager.getDeviceList();

        if (!usbDevices.isEmpty()) {
            boolean keep = true;
            for (Object object : usbDevices.entrySet()) {
                Map.Entry<String, UsbDevice> entry = (Map.Entry<String, UsbDevice>) object;
                device = entry.getValue();

                int deviceVID = device.getVendorId();
                if (deviceVID == ARDUINO_DEVICE_ID) { //Arduino Vendor ID = 0x2341
                    PendingIntent pi = PendingIntent.getBroadcast(context, 0,
                            new Intent(ACTION_USB_PERMISSION), 0);
                    usbManager.requestPermission(device, pi);
                    keep = false;
                } else {
                    connection = null;
                    device = null;
                }
                if (!keep)
                    break;
            }
        }
    }

c. Now, in the Activity where we will be testing or intend to work with the serial connection, we check for the usb permission in a broadcast receiver which is registered in the onCreate method of the activity along with an Intent Filter. The Intent filter has the usp permission as an action added to it.

usbCommunicationHandler = USBCommunicationHandler.getInstance(this, NeuroLab.getUsbManager());

        deviceConnector = new DeviceConnector(NeuroLab.getUsbManager());

        IntentFilter intentFilter = new IntentFilter();
 
        intentFilter.addAction(ACTION_USB_PERMISSION);
        registerReceiver(broadcastReceiver, intentFilter);

d. In the onReceive callback of the broadcast receiver, if the usb permission is granted, we initialize the serial connection with a baud rate for our Arduino device. In this initialization method, we get the connection and serial port of the connected Arduino to the Android device with which we can work. The method is implemented in the following way:

public boolean initializeSerialConnection(int baudRate) {
        connection = usbManager.openDevice(device);
        serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
        if (serialPort != null) {
            if (serialPort.open()) { 
                serialPort.setBaudRate(baudRate);
                serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
            } else {
                Log.d("SERIAL", "PORT NOT OPEN");
                return false;
            }
        } else {
            Log.d("SERIAL", "PORT IS NULL");
            return false;
        }
        setSerialPort(serialPort);
        return true;
    }

e. Now, with this ‘serialPort’ we can read data from the Arduino in the UsbReadCallback callback from the USBSerialInterface. The data is read in the form of array of bytes. This read data can be used to carry out the various functionalities we want to achieve.

With the above steps we can establish a serial connection between Android and Arduino, transmit data from Arduino to Android device for processing.

The whole working source code of the Neurolab Android project can be found here:

https://github.com/fossasia/neurolab-android/

Thanks for taking the time to read this blog. Hope it was able to make some good contributions to your knowledge base.

References

  1. https://github.com/felHR85/UsbSerial
  2. https://www.arduino.cc/reference/en/language/functions/communication/serial/

Tags: FOSSASIA, Neurolab, GSOC19, Open-source, Arduino, Serial terminal

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.