Cable OTG Arduino + Xamarin.Android

Haciendo referencia a mi antigua entrada sobre comunicacion arduino por bluetooth http://alejandroruizvarela.blogspot.mx/2014/01/bluetooth-arduino-xamarinandroid.html hoy continuaremos con una nueva entrada dedicada a este tema solo que ahora trabajaremos con el cable OTG el cual nos permite conectar dispositivos USB a dispositivos android.



Requisitos necesarios libreria usb-serial-for-android-v010.jar by mik3y (https://github.com/mik3y/usb-serial-for-android/releases/download/v0.1.0/usb-serial-for-android-v010.jar)
o pueden bajar el binding de la libreria dll realizado por mi desde esta direccion (Recomendado)(https://app.box.com/s/fk48ldawrpls397ww2hx)

Device filter xml (https://app.box.com/s/w231nt5lt9ack4s8vl1m)

Iniciamos con nuestro Sketch:

int led=13, msg=0;
void setup()
{
  pinMode(led,OUTPUT);
  Serial1.begin(9600); 
}
void loop()
{
  while(Serial1.available()>0)
  {
    msg=Serial1.read();
    if(msg=='e')
    {
      digitalWrite(led,HIGH);
      Serial1.write('H');
      delay(1000);
      digitalWrite(led,LOW);
      Serial1.write('E');
      delay(1000);
      digitalWrite(led,HIGH);
      Serial1.write('L');
      delay(1000);
      digitalWrite(led,LOW);
      Serial1.write('L');
      delay(1000);
      digitalWrite(led,HIGH);
      Serial1.write('O');
      delay(1000);
      digitalWrite(led,LOW);
      delay(500);
      digitalWrite(led,HIGH);
      delay(500);
      digitalWrite(led,LOW);
      delay(500);
      digitalWrite(led,HIGH);
      delay(500);
      digitalWrite(led,LOW);
      delay(500);
      digitalWrite(led,HIGH);
      delay(500);
      digitalWrite(led,LOW);
      delay(500);
      digitalWrite(led,HIGH);
      delay(500);
      digitalWrite(led,LOW);
      delay(500);
      digitalWrite(led,HIGH);
      delay(500);
      digitalWrite(led,LOW);
      delay(500);
      Serial1.write(' ');
      Serial1.write("OK");
    }
  }
}

En nuestra carpeta de Resources crearemos una carpeta llamada "xml" en la cual agregaremos nuestro archivo device_filter.xml el cual contiene el siguiente codigo:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 0x0403 / 0x6001: FTDI FT232R UART -->
    <usb-device vendor-id="1027" product-id="24577" />
    <!-- 0x0403 / 0x6015: FTDI FT231X -->
    <usb-device vendor-id="1027" product-id="24597" />
    <!-- 0x2341 / Arduino -->
    <usb-device vendor-id="9025" />
    <!-- 0x16C0 / 0x0483: Teensyduino -->
    <usb-device vendor-id="5824" product-id="1155" />
    <!-- 0x10C4 / 0xEA60: CP210x UART Bridge -->
    <usb-device vendor-id="4292" product-id="60000" />
    <!-- 0x067B / 0x2303: Prolific PL2303 -->
    <usb-device vendor-id="1659" product-id="8963" />
</resources>

A continuacion registraremos el permiso para poder usar nuestro puerto usb como host dentro de nuestro AndroidManifest.xml:

<uses-feature android:name="android.hardware.usb.host" />

El codigo de nuestra interfaz principal (Main.axml) es el siguiente:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:p1="http://schemas.android.com/apk/res/android"
    p1:orientation="vertical"
    p1:minWidth="25px"
    p1:minHeight="25px"
    p1:layout_width="match_parent"
    p1:layout_height="match_parent"
    p1:id="@+id/linearLayout1">
    <ToggleButton
        p1:id="@+id/toggleButton1"
        p1:layout_height="wrap_content"
        p1:layout_width="match_parent" />
    <TextView
        p1:textAppearance="?android:attr/textAppearanceLarge"
        p1:gravity="center_horizontal"
        p1:id="@+id/textView1"
        p1:layout_height="match_parent"
        p1:layout_width="match_parent"
        p1:text="..." />
</LinearLayout>

Antes de continuar con el codigo no olviden referenciar la libreria dll(https://app.box.com/s/fk48ldawrpls397ww2hx) a nuestro proyecto:

Ahora si podemos continuar con el codigo principal de nuestra aplicacion:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Hardware.Usb;
using Com.Hoho.Android.Usbserial.Driver;
using System.IO;
using System.Threading.Tasks;
using Com.Hoho.Android.Usbserial.Util;

namespace OTGExample
{
      [Activity (Label = "OTGExample", MainLauncher = true)]
      [IntentFilter (new[]{"android.hardware.usb.action.USB_DEVICE_ATTACHED"})]
      [MetaData ("android.hardware.usb.action.USB_DEVICE_ATTACHED", Resource = "@xml/device_filter")]
      public class MainActivity : Activity
      {
           ToggleButton tgConnect=null;
           TextView Result=null;
           UsbManager manager=null;
           UsbSerialDriver driver=null;
           private Java.Lang.String dataToSend;

           protected override void OnCreate (Bundle bundle)
           {
                base.OnCreate (bundle);
                SetContentView (Resource.Layout.Main);
                manager = (UsbManager)this.GetSystemService (Context.UsbService);
                tgConnect = FindViewById<togglebutton>(Resource.Id.toggleButton1);
                Result = FindViewById<textview>(Resource.Id.textView1);
                tgConnect.CheckedChange += tgConnect_HandleCheckedChange;
           }

           void tgConnect_HandleCheckedChange (object sender, CompoundButton.CheckedChangeEventArgs e)
           {
                  if (e.IsChecked) {
                      driver = UsbSerialProber.Acquire(manager);
                      if (driver != null) {
                         driver.Open ();
                         driver.SetBaudRate (9600);
                         beginListenForData ();
                         dataToSend = new Java.Lang.String("e");
                         writeData(dataToSend);
                      }
                      else
                      {
                         Toast.MakeText (this, "Error Arduino no detectado", ToastLength.Short).Show();
                      }
                   } else {
                     try {
                         driver.Close();
                     } catch (System.Exception ex) {
                         Console.WriteLine (ex.Message);
                     }
                  }
            }

            public void beginListenForData() {
                   Task.Factory.StartNew (() => {
                   byte[] buffer = new byte[1024];
                   int bytes;
                   while (true) {
                       try {
                          bytes = driver.Read(buffer, buffer.Length);
                          if(bytes>0)
                          {
                                 RunOnUiThread(()=>{
                                 string valor = System.Text.Encoding.ASCII.GetString (buffer);
                                 Result.Text = Result.Text+"\n"+valor;
                                 });
                          }
                    } catch (Exception e) {
                       driver.Close();
                       RunOnUiThread(()=>{
                             Toast.MakeText (this, e.Message, ToastLength.Short).Show ();
                             Result.Text = string.Empty;
                       });
                       break;
                      }
                   }
               });
            }

            private void writeData(Java.Lang.String data) {
                       Java.Lang.String message = data;
                       byte[] msgBuffer = message.GetBytes();
                       try {
                           driver.Write(msgBuffer, 0);
                       } catch (System.Exception e) {
                           Toast.MakeText (this, e.Message, ToastLength.Short).Show ();
                           System.Console.WriteLine("Error al enviar"+e.Message);
                       }
            }
      }
}

Pueden acceder al ejemplo completo desde mi github:

https://github.com/AlejandroRuiz/Mono/tree/master/Arduino/OTGExample

Espero que el ejemplo les sea de mucha utilidad cualquier pregunta que les surga pueden hacermelas llegar


Comentarios

  1. Hola Alejandro! que gran post! Es un gran aporte para los que estamos luchando por comunicar el celular con Arduino.
    Por una de esas casualidades pudiste conectar Xamarin con Google Adk? estoy luchando para lograr eso sin resultados aun.

    Muchas gracias!

    ResponderEliminar
  2. Gran trabajo! Recien empiezo a usar visual studio y en el codigo me tira un error con"Resource" - no existe en el contexto actual, esto a que se debe?

    ResponderEliminar
  3. Hola Alejandro, cuando comencé a crear este comentario note que yo mismo ya comente hace mucho tiempo! y aun lucho por hacer funcionar esta comunicacion...

    No logro que tu codigo funcione, ya que esta linea:
    driver = UsbSerialProber.Acquire(manager);
    siembre vuelve en null...

    Ya agregue al archivo device_filter.xml la configuracion de mi Arduino Mega:



    Y se que es la correcta, ya que con estas lienas, si puedo obtener el dispositivo:

    var usbManager = (UsbManager)GetSystemService(Context.UsbService);

    // Get the device you want to access from the DeviceList
    // I know the vendorId and ProductId but you can iterate to find the one you want
    var usbDeviceConf = usbManager.DeviceList.FirstOrDefault(device => device.Value.VendorId == 6790 && device.Value.ProductId == 29987);

    El problema es que no tengo idea de como obtener el UsbSerialDriver a continuacion...

    Espero puedas darme una mano.

    De todas formas muchas gracias por tu post

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Bluetooth Arduino + Xamarin.Android

Xamarin.Forms: Get native image from ImageSource

Simple ListView with Xamarin.Forms