Things used in this project

Hardware components:
Microsoft Xbox Controller and Wireless Adapter for Windows
This controller can be added to a Windows PC using the adapter
×1
12577 01
SparkFun SparkFun Bluetooth Modem - BlueSMiRF Silver
Or an identical (HC-05, HC-06) Bluetooth module
×1
A000066 iso both
Arduino Arduino UNO & Genuino UNO
×1
Software apps and online services:
10
Microsoft Windows 10 IoT Core
This app is the intermediate between the standard Firmata sketch and the Xbox One controller

Code

Xaml controls to start the communicationsnippets
Paste this into the main form of your new UWP app
<StackPanel Orientation="Vertical">
  <Button Name="btnStart"
          Click="btnStart_Click"
          FontSize="50"
          Width="400"
          Content="Start" />
  <Button Name="btnController"
          Content="Controller"
          FontSize ="50"
          Width="400"
          IsEnabled="False"
          Click="btnController_Click" />
  <TextBlock Name="tbRead"
             FontSize="20"
             Foreground="Gray" />
</StackPanel>
Code-Behind of the the UWP app mainformC#
This code connects to the rover using Firmata and passes Xbox One Controller commands
public sealed partial class MainPage : Page
{
  private BluetoothSerial _bluetooth;
  private RemoteDevice _arduino;

  private UwpFirmata _firmata = null;
  private Gamepad _Gamepad = null;
  // We never supply a PWM of more then 255 * 0,75
  private double _SpeedLimit = 0.75;
  // values below this absolte value stop the rover
  private double _ActionPoint = 0.15;

  private byte _LeftForward = 6;
  private byte _LeftBackward = 7;
  private byte _LeftValue = 5;
  private byte _RightForward = 9;
  private byte _RightBackward = 8;
  private byte _RightValue = 10;

  private Dictionary<byte, PinState> _CurrentPinStates 
                           = new Dictionary<byte, PinState>();

  private Dictionary<byte, ushort> _CurrentSpeedValues 
                             = new Dictionary<byte, ushort>();

  public MainPage()
  {
    this.InitializeComponent();
  }

  private void btnStart_Click(object sender, 
                               RoutedEventArgs e)
  {
    btnStart.IsEnabled = false;

    Gamepad.GamepadAdded += Gamepad_GamepadAdded;
    Gamepad.GamepadRemoved += Gamepad_GamepadRemoved;

    _bluetooth = new BluetoothSerial("HC-06");
    _bluetooth.ConnectionLost += BluetoothConnectionLost;
    _bluetooth.ConnectionFailed += BluetoothConnectionFailed;
    _bluetooth.ConnectionEstablished += 
                                   OnConnectionEstablished;

    _firmata = new UwpFirmata();
    _arduino = new RemoteDevice(_firmata);
    _firmata.begin(_bluetooth);

    _bluetooth.begin(9600, SerialConfig.SERIAL_8N1);

    _arduino.DeviceReady += ArduinoDeviceReady;
  }

  private async void BluetoothConnectionLost(string message)
  {
    await Dispatcher.RunAsync(
      CoreDispatcherPriority.Normal, () =>
      {
        tbRead.Text = "ConnectionLost" + message;
        btnStart.IsEnabled = true;
      });
  }

  private async void BluetoothConnectionFailed(string message)
  {
    await Dispatcher.RunAsync(
      CoreDispatcherPriority.Normal, () =>
      {
        tbRead.Text = "ConnectionFailed" + message;
        btnStart.IsEnabled = true;
      });
  }

  private async void ArduinoDeviceReady()
  {
    await Dispatcher.RunAsync(
      CoreDispatcherPriority.Normal, () =>
      {
        tbRead.Text = "Device Ready";
      });
  }

  private void OnConnectionEstablished()
  {
    var action = Dispatcher.RunAsync(
      CoreDispatcherPriority.Normal, 
      new DispatchedHandler(() =>
      {
        DisableEnableButtons(true);

        ArduinoDigitalWrite(_LeftForward, PinState.LOW);
        ArduinoDigitalWrite(_LeftBackward, PinState.LOW);
        ArduinoDigitalWrite(_RightBackward, PinState.LOW);
        ArduinoDigitalWrite(_RightForward, PinState.LOW);
      }));
  }

  private void DisableEnableButtons(bool enabled)
  {
    // Disable all buttons. Otherwise 
    //  the 'A' will press the one focussed.
    btnController.IsEnabled = enabled;
    btnStart.IsEnabled = enabled;
  }

  private async void Gamepad_GamepadRemoved(
                                   object sender, Gamepad e)
  {
    _Gamepad = null;

    await Dispatcher.RunAsync(
      CoreDispatcherPriority.Normal, () =>
      {
        tbRead.Text = "Controller removed";
      });
  }
  
  private async void Gamepad_GamepadAdded(
                                   object sender, Gamepad e)
  {
    _Gamepad = e;

    await Dispatcher.RunAsync(
      CoreDispatcherPriority.Normal, () =>
      {
        tbRead.Text = "Controller added";
      });
  }

  private async void btnController_Click(object sender, 
                                          RoutedEventArgs e)
  {
    DisableEnableButtons(false);

    while (true)
    {
      await Task.Delay(TimeSpan.FromMilliseconds(3));

      if (_Gamepad == null)
      {
        continue;
      }

      // Get the current state
      var reading = _Gamepad.GetCurrentReading();

      if (Math.Abs(reading.LeftThumbstickY) < _ActionPoint)
      {
        ArduinoDigitalWrite(_LeftForward, PinState.LOW);
        ArduinoDigitalWrite(_LeftBackward, PinState.LOW);
        sldrLeftSpeed.Value = 0;
      }
      else if (reading.LeftThumbstickY >= _ActionPoint)
      {
        ArduinoDigitalWrite(_LeftForward, PinState.HIGH);
        ArduinoDigitalWrite(_LeftBackward, PinState.LOW);
        sldrLeftSpeed.Value = 255 * 
               Math.Abs(reading.LeftThumbstickY) * _SpeedLimit;
      }
      else if (reading.LeftThumbstickY <= -_ActionPoint)
      {
        ArduinoDigitalWrite(_LeftForward, PinState.LOW);
        ArduinoDigitalWrite(_LeftBackward, PinState.HIGH);
        sldrLeftSpeed.Value = 255 * 
               Math.Abs(reading.LeftThumbstickY) * _SpeedLimit;
      }

      if (Math.Abs(reading.RightThumbstickY) < _ActionPoint)
      {
        ArduinoDigitalWrite(_RightForward, PinState.LOW);
        ArduinoDigitalWrite(_RightBackward, PinState.LOW);
        sldrRightSpeed.Value = 0;
      }
      else if (reading.RightThumbstickY >= _ActionPoint)
      {
        ArduinoDigitalWrite(_RightForward, PinState.HIGH);
        ArduinoDigitalWrite(_RightBackward, PinState.LOW);
        sldrRightSpeed.Value = 255 * 
          Math.Abs(reading.RightThumbstickY) * _SpeedLimit;
      }
      else if (reading.RightThumbstickY <= -_ActionPoint)
      {
        ArduinoDigitalWrite(_RightForward, PinState.LOW);
        ArduinoDigitalWrite(_RightBackward, PinState.HIGH);
        sldrRightSpeed.Value = 255 * 
          Math.Abs(reading.RightThumbstickY) * _SpeedLimit;
      }
    }
  }

  private void ArduinoDigitalWrite(byte port, PinState state)
  {
    // ignore duplicate commands
    var exists = _CurrentPinStates.ContainsKey(port);

    if (!exists
           || _CurrentPinStates[port] != state)
    {
      _CurrentPinStates[port] = state;
      _arduino.digitalWrite(port, state);
    }
  }
  
  private void ArduinoAnalogWrite(byte port, ushort value)
  {
    // ignore duplicate commands
    var exists = _CurrentSpeedValues.ContainsKey(port);

    if (!exists
          || _CurrentSpeedValues[port] != value)
    {
      _CurrentSpeedValues[port] = value;
      _arduino.analogWrite(port, value);
    }
  }
}

Credits

Pasfotosander300x450
Sander van de Velde

I started as a IT consultant in 1993. I like getting my hands dirty with software innovations and I try to implement these in my daily work

Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

PHPoc Blue to Control Door Knob by MQTT Protocol and Cortana
Intermediate
  • 86
  • 7

Programming a PHPoc Blue board to control a servo motor to rotate the knob of a door using MQTT Protocol through voice command.

Starry Night Prom
Intermediate
  • 2,299
  • 18

How did I stand out at prom? In a light up dress of course!

The Trump Button
Intermediate
  • 1,175
  • 8

Full instructions

The famous connected button to order your favorite drink using Sigfox network.

ARDUINO PONG
Intermediate
  • 7
  • 1

Full instructions

The game in a dot matrix display P10 16x32 pixels

Direction Indicators for Bikes
Intermediate
  • 299
  • 6

Full instructions

Riding bike is a little dangerous. With the Direction Indicators for a bike, car's know if you want to turn right or left. Make biking safe!

Third Eye for The Blind
Intermediate
  • 997
  • 13

Full instructions

An innovative wearable technology for visually impaired peoples.

ProjectsCommunitiesTopicsContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login