Use Bluetooth between Win 10 UWP and Arduino

This is part 3 of a series of blogs about device communication between Arduino, RaspberryPi etc:

  • Part 1: Using I2C to connect two Arduino Nano’s
  • Part 2: Using I2C between Rpi Master and Arduino Slave
  • Part 3: Use Bluetooth between Win 10 UWP and Arduino
  • Part 4: Add virtual Arduino ports to your UWP app
  • Part 5: Custom Firmata function called by Windows 10 IoT Core
  • Part 6: Better long running custom Firmata functions
  • Part 7: Custom servo usage in Firmata
  • Part 8: Using NRF24L01+ modules between Arduino’s
  • Part 9: Cheap Arduino mesh using RF24 radio modules

In previous blogs, I have written about combining one or more Arduino Nano’s with a RaspberryPi using the I2C protocol. Although this is very useful, the communication is limited to the length of the cables. This is not very practical for a local gateway.

fatfight3 Get it on Windows 10

So I looked at communication using Bluetooth. So I bought some Bluetooth modules. These little components are relatively cheap and reliable. They come with four and six pins (for now, it has just two extra pins not needed, the inner four are the same with the four pins version) but the four pin variant is used in this example.

 HC-05

Note: Ignore the ‘module base plates’ for only 30 cents. These do not contain the actual Bluetooth logic. In fact: it’s just the base plate, hence the price difference 🙂

Wiring the Bluetooth module is very simple. In this diagram is shown how I wired power, ground, RX and TX.

Nano plus HC-05_bb

Do you see how RX and TX are crossed?

In some examples, the Bluetooth RX and TW are attached to port 0 and 1. I use port 4 and 3 because 0 and 1 are traditionally used for uploading the code to the Arduino using the USB cable. Now the upload is not interfered.

So upload the code:

#include <SoftwareSerial.h>
int ledPin = 13;

/* This sample code demonstrates the normal use of reading Bluetooth serial port.
It requires the use of SoftwareSerial, and assumes that you have the 9600-baud Bluetooth serial device hooked up on pins 4(rx) and 3(tx).
This way, port 0 and 1 stay clear for uploading and serial monitor.
*/

SoftwareSerial ss(4, 3);

void setup() {
  // Force the Bluetooth module to communicate 9600 baud on Serial
  ss.begin(9600);
  ss.print("$");
  ss.print("$");
  ss.print("$");
  delay(100);
  ss.println("SU,96");
  delay(100);
  ss.println("---");
  ss.begin(9600);

  // 9600 is the default baud rate for the screen module
  Serial.begin( 9600 );
  Serial.print("Start... ");
}

void loop() {
  // listen for serial data
  if ( ss.available() > 0 ) {
    // read a numbers from serial port
    int count = ss.parseInt();// print out the received number
    if (count > 0) {
      Serial.print("You have input: ");
      Serial.println(String(count));

      // blink the LED
      blinkLED(count);
    }
    else {
      Serial.print("nope");
    }
  }
}

void blinkLED(int count) {
  for (int i=0; i < count; i++) {
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
  }
}

So I use the SoftwareSerial library to communicate over port 4 and 3. And during the setup phase, I send some information to the Bluetooth module so it will communicate at 9600 baud.

And every time a character is received by the Bluetooth module, it is turned into an integer. This is shown on the serial monitor of the Arduino IDE but, more important, Led13 will blink so many times.

Here I attach the Bluetooth to a power bank (once the code is uploaded), just to proof that it works: without wires!?!

WP_20160106_21_59_28_Rich_LI

The Arduino Nano is now ready for use.

Let’s go to the RaspberryPi. Attach a Bluetooth dongle to it. Although it seems still a limited amount of types are supported, just try the ones you have already. I had some luck, a cheap dongle I already had is supported.

And use the newest version of the Windows 10 IoT Core because it makes your life very easy when you want to pair to a Bluetooth module. How do you get the new image? Use the new Windows 10 IoT Core Dashboard.  You can find it here.

IoT Dashboard

After you have flashed the newest image and rebooted your pi, find it in the My Devices list. Select it and open the web interface (a tiny web server is running on your Rpi). Log into your Rpi (do you know the default username-password?) and go to the Bluetooth page.

Observation: Woo hoo, now we have a Windows Update feature!

pairing on rpi

When your Bluetooth dongle is recognised and your Bluetooth module is powered up, try to find it in the list of available devices. Do you see something like HC-5 or HC-6?

Try to pair with them. I have two modules and paired to both of them. I found out that ‘1234’ is the pass key for both of them.

So now your Pi can talk over Bluetooth! But wait, we have to connect first.

Note: because we are going to work with a UWP app, try to avoid as long as possible to debug on the Rpi. Why? Simply, speed up your development. It’s just too slow to debug your code in progress!  If you pair the module also to a Windows Phone 10 or just to your own development desktop or laptop or Surface (lucky ****** 😉 ) use those devices. It works just the same!

Start a new empty UWP template. First of all, add Bluetooth to the list of capabilities your app needs to run on.

capabilities

Go to the XAML page and add these controls to the grid (in a vertical stack panel):

<StackPanel>
  <Button Name="btnConnect" 
          Content="Connect" 
          Click="btnConnect_Click" 
          FontSize="40" />
  <Button Name="btnDisconnect" 
          Content="Disconnect" 
          Click="btnDisconnect_Click" 
          FontSize="40" />
  <TextBox Name="tbInput" 
           Text="2" 
           FontSize="40" />
  <Button Name="btnSend" 
          Content="Send" 
          Click="btnSend_Click" 
          FontSize="40" />
  <TextBlock Name="tbError" 
             FontSize="40" />
</StackPanel>

Now we have buttons to connect and disconnect and we can send an integer.

The code behind is:

public sealed partial class MainPage : Page
{
  private StreamSocket _socket;

  private RfcommDeviceService _service;
  public MainPage()
  {
    this.InitializeComponent();
  }

  private async void btnSend_Click(object sender,
                                   RoutedEventArgs e)
  {
    int dummy;

    if (!int.TryParse(tbInput.Text, out dummy))
    {
      tbError.Text = "Invalid input";
    }

    var noOfCharsSent = await Send(tbInput.Text);

    if (noOfCharsSent != 0)
    {
      tbError.Text = noOfCharsSent.ToString();
    }
  }
  private async Task<uint> Send(string msg)
  {
    tbError.Text = string.Empty;

    try
    {
      var writer = new DataWriter(_socket.OutputStream);

      writer.WriteString(msg);

      // Launch an async task to 
      //complete the write operation
      var store = writer.StoreAsync().AsTask();

      return await store;
    }
    catch (Exception ex)
    {
      tbError.Text = ex.Message;

      return 0;
    }
  }

  private async void btnConnect_Click(object sender, 
                                      RoutedEventArgs e)
  {
    tbError.Text = string.Empty;

    try
    {
      var devices = 
            await DeviceInformation.FindAllAsync(
              RfcommDeviceService.GetDeviceSelector(
                RfcommServiceId.SerialPort));

      var device = devices.Single(x => x.Name == "HC-05");

      _service = await RfcommDeviceService.FromIdAsync(
                                              device.Id);

      _socket = new StreamSocket();

      await _socket.ConnectAsync(
            _service.ConnectionHostName, 
            _service.ConnectionServiceName, 
            SocketProtectionLevel.
            BluetoothEncryptionAllowNullAuthentication);
    }
    catch (Exception ex)
    {
      tbError.Text = ex.Message;
    }
  }

  private async void btnDisconnect_Click(object sender, 
                                       RoutedEventArgs e)
  {
    tbError.Text = string.Empty;

    try
    {
      await _socket.CancelIOAsync();
      _socket.Dispose();
      _socket = null;
      _service.Dispose();
      _service = null;
    }
    catch (Exception ex)
    {
      tbError.Text = ex.Message;
    }
  }
}

Look at the code. Maybe you will have to make a simple adjustment: I have hard coded “HC-5” because that is the name of the module that I just used. Check the name of your module. An exception will be thrown when the name does not exist.

Run the code. Try to connect.

Note: if you use the UWP app on your PC and connect for the first time, you will get this consent screen. You have to say Yes:

Consent

If the connection is established, you will observe that the rhythm of the blinking led on the Bluetooth module (not led 13!) will change in modulation (it will slow down).

Now try to send the character 2 (and later on 3, 4 and 5):

Laptop

Tadaah, is Led 13 blinking twice? And is the serial monitor showing:

SerialOutput

Then you have succeeded!

Now it’s time to deploy your app to your Rpi. I worked on my machine. I also deployed the same app to my Windows Phone. It just works:

wp_ss_20160107_0002

Every time I deploy to both laptop, RaspberryPi and a Windows Phone I am surprised again that the same code is working on these different devices. It’s great to develop UWP apps!

This code is the most simple example to show you how to communicate using Bluetooth. After this, try to receive a value from the module or make the pairing/connection process more robust.

 

Advertenties

15 thoughts on “Use Bluetooth between Win 10 UWP and Arduino

  1. Hello Sander, your page turned in a instant bookmark for my future windows 10 projects. But I have doubts.

    I have incidently been wandering the internet the last week. I’ve learned about windows 10, learned about windows visio, via a tutorial that explained it was very easy to communicate with Arduino, with the right plugin. And not that easy as I expected.
    I was specifically looking for a windows universal app that could communicate over a wired (usb to serial) connection. Like the FTDI chips on a Arduino.

    Is Bluetooth that much easier to use? Is it also easy to adjust your code for a wired connection or is it completely different?

    Somehow I think that 15 years ago this was a lot easier to do 🙂 with Visual Basic.

    I’m not really sure how stable a bluetooth connection will be compared to a usb to serial connection.

    1. Hello Joeri, the Firmata protocal makes it very easy to connect using wireless communication. But when a wired connection is possible, you do not have to worry about pairing etc.

  2. Hi,

    when I run this UWP app on my Surface and try to connect to my Arduino the application gives a Exception message saying “NoMatch”. Do you maybe have an idea what this means and how to fix it?

    1. Hmm, difficult to say, there are many variables. This example shows how to connect using Bluetooth with some custom code. Please be aware that in more recent blogs, I use the Firmata protocol. This takes away a lot of connection issues. And Microsoft has issues an example app. I recommend to look at this first. When it is working you can always come back for this light weight solution.

  3. Thanks for this article. It worked for me, but I had to change one thing. In C# code, the name is set to “HC-05”. For some reason during debugging it turned out that my mdoeule’s name is “Dev B” (even though in Bluetooth monitor it’s sown as “HC-05”). So now I’m able to send data to arduino.

    Could you show us how to transfer data the other way? I’d like to send data from arduino to PC – I’m a newbie here and I can’t do it myself. I don’t really understand all this async/await/task stuff yet. If someone knows any good source where it’s explained nicely, please also post it here.

Reacties zijn gesloten.