For hardware side of this project see Windows Phone Controlled Car Using Arduino

Scope

This article walks you through basic implementation of a UWP App with a virtual joystick that can be used to control the Arduino/RPi based projects over bluetooth. Whenever the joystick is moved, the app sends the new joystick position to the connected device. See it in action.


Creating the Joystick Control

1. Install nuget package using the following command in nuget PM console:
Install-package JoystickUserControl
 
2. Add the Xaml namespace to your Xaml page:
xmlns:JoystickControl="using:JoystickUserControl"

3. Add the joystick control to your page:
<JoystickControl:Joystick x:Name=”MyJoystick”>< /JoystickControl:Joystick>

For more info on joystick control, check this article.

Bluetooth Actions

Our app must have the following basic features,

  1. Search for the paired Bluetooth devices.
  2. Connect to a selected Bluetooth Device.
  3. Send data to the connected device.

Bluetooth device capability must be checked in Package.appxmanifest file under capabilities tab for an app that uses bluetooth.

1. Searching for the Paired Devices

public async Task<DeviceInformationCollection> FindPairedDevicesAsync()
{
    var aqsDevices = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort);
    DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(aqsDevices);
    return devices;
}
  • This code searches for the Serial Bluetooth devices paired with the our Windows 10 device e.g HC-05/HC-06, BlueSmirf.

2. Connecting with a Paired Device

public async Task<bool> ConnectAsync(DeviceInformation device)
{
    RfcommDeviceService rfcommService = await RfcommDeviceService.FromIdAsync(device.Id);
    if (rfcommService == null) return false;
    Stream = new StreamSocket();
    try
    {
        await Stream.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName);
    }
    catch
    {
        return false;
    }
 
    IsConnected = true;
    _btReader = new DataReader(Stream.InputStream);
    _btWriter = new DataWriter(Stream.OutputStream);
    _btWriter.UnicodeEncoding = UnicodeEncoding.Utf8;
    return true;
}
  • IsConnected is a public property defined in the class that can be checked to see if the device is connected before sending the data.
  • device parameter is an element of the DeviceInformationCollection received from the previous step.

3. Sending Data to the Connected Device

public async Task<bool> WriteAsync(string str)
{
    if (!IsConnected) return false;
 
    try
    {
        var n = _btWriter.WriteString(str);
        await _btWriter.StoreAsync();
        return n > 0;
    }
    catch (Exception)
    {
        return false;
    }
 
}

You can used any format to send the joystick position, but a simple format we can use is a string of the form "*X,Y#". Where X and Y are unsigned char whose values varies from 0-255, 127 being the center.