Creating Xamarin Android App for connecting to Raspberry Pi Robot – Part 2

featured-xamarin-bluetooth

We are in part 3 of tutorial series of Building Raspberry Pi Robot controlled by Android App via bluetooth! If you want to jump back and forth or missed any of my previous tutorials – here is the consolidated list.

All Tutorials to build Raspberry Pi Robot controlled by Android App via Bluetooth

  1. Build Raspberry PI Robot controlled by Android App via Bluetooth
  2. Programming the Raspberry Pi Robot for Bluetooth with Python
  3. Creating Xamarin Android App for connecting to Raspberry Pi Robot
  4. Final Bluetooth controlled Rasbperry Pi Robot in Action

We have basic infrastructure ready but we don’t have our own mobile app that can connect to Robot and send commands to move forward, reverse, left, right and stop. We are going to build our own app for the same. Here is what we will build:

Step 1: Create Xamarin Android project

If you are totally new to the world of Xamarin, here is how you can setup.

I have Mac so I have used Visual Studio for Mac to create a project. Here are the screenshots of how to create first Xamarin android app.

Step 2: Design layout

We use xml to design layout. Here, we are going to use the simple layout “TableLayout” for this tutorial. It works exactly same as table in html. I am not going to explain below code. It is self explanatory. Replace the code in \Resources\layoutMain.axml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/txtStatus"
            android:textColor="@android:color/holo_red_dark"
            android:gravity="center" />
        <Button
            android:id="@+id/btnConnect"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Connect to Pi Robot" />
        <TableLayout
            android:minWidth="25px"
            android:minHeight="25px"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:stretchColumns="*"
            android:id="@+id/tableLayout1">
            <TableRow
                android:id="@+id/tableRow1">
                <Button
                    android:layout_column="1"
                    android:layout_width="fill_parent"
                    android:id="@+id/btnForward"
                    android:layout_height="70dp"
                    android:text="Forward" />
            </TableRow>
            <TableRow
                android:id="@+id/tableRow2">
                <Button
                    android:layout_column="0"
                    android:id="@+id/btnLeft"
                    android:layout_height="70dp"
                    android:text="Left" />
                <Button
                    android:layout_column="1"
                    android:id="@+id/btnStop"
                    android:layout_height="70dp"
                    android:text="Stop" />
                <Button
                    android:layout_column="2"
                    android:layout_height="70dp"
                    android:id="@+id/btnRight"
                    android:text="Right" />
            </TableRow>
            <TableRow
                android:id="@+id/tableRow3">
                <Button
                    android:layout_column="1"
                    android:layout_height="70dp"
                    android:id="@+id/btnReverse"
                    android:text="Reverse" />
            </TableRow>
        </TableLayout>
    </LinearLayout>
</ScrollView>

If you check the design, it will look like below:

Step 3: Working on core logic

Here is the code that will do the trick:
First of all we are going to use MainActivity.cs which is already created. Use below namespaces:

using Android.App;
using Android.Widget;
using Android.OS;
using Android.Bluetooth;
using System;
using System.Linq;
using Java.Util;
using System.Text;

Main code is below which will create Bluetooth connection:

BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
if (adapter == null)
	throw new Exception("No Bluetooth adapter found.");

if (!adapter.IsEnabled)
	throw new Exception("Bluetooth adapter is not enabled.");

BluetoothDevice device = (from bd in adapter.BondedDevices
		  where bd.Name == "raspberrypi"
		  select bd).FirstOrDefault();

if (device == null)
	throw new Exception("Raspberry Pi device not found.");

BluetoothSocket socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805f9b34fb"));
await socket.ConnectAsync();
  • First of all, we get the Bluetooth adapter of phone by
    adapter = BluetoothAdapter.DefaultAdapter;

    • If Bluetooth adapter is null then Bluetooth is not supported in phone. Hence, we throw exception.
    • If Bluetooth is not enabled we throw exception by checking adapter.IsEnabled.
  • Next, we get the device by name, here name of the device is “raspberrypi” so we get the device by below query and if null no such device is found:device = (from bd in adapter.BondedDevices
    where bd.Name == “raspberrypi”
    select bd).FirstOrDefault();if (device == null)
    throw new Exception(“Raspberry Pi device not found.”);
  • Next, we create a socket RFComm connection by using below lines and display status once connected in UI. Here, 00001101-0000-1000-8000-00805f9b34fb is the default UUID of the port which we want to connect:socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString(“00001101-0000-1000-8000-00805f9b34fb”));
    await socket.ConnectAsync();
    txtStatus.Text = “Pi Robot Connected”;
  • To transfer data we have below code:byte[] buffer = Encoding.ASCII.GetBytes(strDirection);
    await socket.OutputStream.WriteAsync(buffer, 0, buffer.Length);

Step 4: Integrating with Raspberry Pi Robot code and full code

Putting it altogether:

  • We will disable all the functions once Bluetooth is connected in order to avoid exceptions.
  • We will display status in Mobile UI on top.
  • When we press Forward, we want to move the robot forward and hence we pass “1”. Hence, I have create generic function which takes care of the same. Below are the commands that we pass from mobile app:
    • Forward: 1
    • Reverse: 2
    • Left: 3
    • Right: 4
    • Stop: 0

Here is entire class code which you can replace – MainActivity.cs

using Android.App;
using Android.Widget;
using Android.OS;
using Android.Bluetooth;
using System;
using System.Linq;
using Java.Util;
using System.Text;

namespace PiBot
{
    [Activity(Label = "PiBot", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : Activity
    {
        BluetoothDevice device;
        BluetoothAdapter adapter;
        Button btnConnect;
        Button btnLeft;
        Button btnRight;
        Button btnForward;
        Button btnReverse;
        Button btnStop;
        TextView txtStatus;
        BluetoothSocket socket;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Main);
            btnConnect = this.FindViewById&amp;amp;lt;Button&amp;amp;gt;(Resource.Id.btnConnect);
            btnLeft = this.FindViewById&amp;amp;lt;Button&amp;amp;gt;(Resource.Id.btnLeft);
            btnRight = this.FindViewById&amp;amp;lt;Button&amp;amp;gt;(Resource.Id.btnRight);
            btnForward = this.FindViewById&amp;amp;lt;Button&amp;amp;gt;(Resource.Id.btnForward);
            btnReverse = this.FindViewById&amp;amp;lt;Button&amp;amp;gt;(Resource.Id.btnReverse);
            btnStop = this.FindViewById&amp;amp;lt;Button&amp;amp;gt;(Resource.Id.btnStop);
            txtStatus = this.FindViewById&amp;amp;lt;TextView&amp;amp;gt;(Resource.Id.txtStatus);
            btnConnect.Click += BtnConnect_Click;
            btnLeft.Click += BtnLeft_Click;
            btnRight.Click += BtnRight_Click;
            btnStop.Click += BtnStop_Click;
            btnForward.Click += BtnForward_Click;
            btnReverse.Click += BtnReverse_Click;
            EnableOrDisableAllMainFunctions(false);
        }

        private void EnableOrDisableAllMainFunctions(bool isEnabled){
            btnLeft.Enabled = btnRight.Enabled = btnForward.Enabled = btnReverse.Enabled = btnStop.Enabled = isEnabled;
        }

        async void BtnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                adapter = BluetoothAdapter.DefaultAdapter;
                if (adapter == null)
                    throw new Exception("No Bluetooth adapter found.");

                if (!adapter.IsEnabled)
                    throw new Exception("Bluetooth adapter is not enabled.");

                device = (from bd in adapter.BondedDevices
                          where bd.Name == "raspberrypi"
                          select bd).FirstOrDefault();

                if (device == null)
                    throw new Exception("Raspberry Pi device not found.");

                socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805f9b34fb"));
                await socket.ConnectAsync();
                txtStatus.Text = "Pi Robot Connected";
                EnableOrDisableAllMainFunctions(true);
                btnConnect.Enabled = false;
            }
            catch (Exception ex)
            {
                txtStatus.Text = ex.Message;
                Toast.MakeText(this, ex.Message, ToastLength.Short);
            }
        }
        void BtnReverse_Click(object sender, EventArgs e)
        {
            RobotMainFunction("2");
        }

        void BtnForward_Click(object sender, EventArgs e)
        {
            RobotMainFunction("1");
        }

        void BtnStop_Click(object sender, EventArgs e)
        {
            RobotMainFunction("0");
        }

        void BtnRight_Click(object sender, EventArgs e)
        {
            RobotMainFunction("4");
        }

        void BtnLeft_Click(object sender, EventArgs e)
        {
            RobotMainFunction("3");
        }
        private async void RobotMainFunction(string strDirection)
        {
            try
            {
                byte[] buffer = Encoding.ASCII.GetBytes(strDirection);
                await socket.OutputStream.WriteAsync(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                Toast.MakeText(this, ex.Message, ToastLength.Short);
            }
        }
    }
}

**Note: if you replace entire code make sure you have correct namespace.

Please follow and like us:

2 comments

  1. Andi Reply

    Hello,

    when i press the BtnConnect it will connect only for 5 sec and dont show “Pi Robot Connected”
    how can i solve this problem? I’m using the raspberry pi zero W

    Thank you

    • Vishal Avalani Post authorReply

      It should work as specified. Check the bluetooth connection or try custom code in python so that you can figure out root cause.

Leave a Reply

Your email address will not be published. Required fields are marked *