Controlling a Gadgeteer device using Bluetooth Module and 32feet.NET library

Posted by Marco Minerva

In this post, I’ll show how to send messages to a GHI Bluetooth module from a PC application using the 32feet .NET library.

First of all, let’s create the Gadgeteer application. Connect an USB ClientDP and an OLED Display to a FEZ Spider Mainboard, as in the following screenshot.

.NET Gadgeteer Modules in the Designer

.NET Gadgeteer Modules in the Designer

We don’t add the Bluetooth module to the Designer because we use the beta driver implemented by Eduardo Velloso. Download the driver from CodePlex and add the Bluetooth.cs file to your project. Connect the module to socket 9. We initialize the driver in the ProgramStarted method:

bluetooth = new Bluetooth(9);
client = bluetooth.ClientMode;

bluetooth.SetDeviceName("Gadgeteer");
bluetooth.SetPinCode("1234");
bluetooth.DataReceived += new Bluetooth.DataReceivedHandler(bluetooth_DataReceived);
client.EnterPairingMode();

In this code, we set Gadgeteer as device name and we configure a PIN code. Then, in the bluetooth_DataReceived event handler, we print the received text on display:

private void bluetooth_DataReceived(Bluetooth sender, string data)
{
    oledDisplay.SimpleGraphics.ClearNoRedraw();
    oledDisplay.SimpleGraphics.DisplayText(data, Resources.GetFont(Resources.FontResources.NinaB), 
                                           GT.Color.Yellow, 0, 60);
}

The complete Program.cs file follows:

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;
using Gadgeteer.Modules.Seeed;
using Gadgeteer.Modules.Velloso;

namespace GadgeteerBluetooth
{
    public partial class Program
    {
        private Bluetooth bluetooth;
        private Bluetooth.Client client;

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            oledDisplay.SimpleGraphics.Clear();

            bluetooth = new Bluetooth(9);
            client = bluetooth.ClientMode;

            bluetooth.SetDeviceName("Gadgeteer");
            bluetooth.SetPinCode("1234");
            bluetooth.DataReceived += new Bluetooth.DataReceivedHandler(bluetooth_DataReceived);
            client.EnterPairingMode();

            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
        }

        private void bluetooth_DataReceived(Bluetooth sender, string data)
        {
            oledDisplay.SimpleGraphics.ClearNoRedraw();
            oledDisplay.SimpleGraphics.DisplayText(data, 
                                                   Resources.GetFont(Resources.FontResources.NinaB),
                                                   GT.Color.Yellow, 0, 60);
        }
    }
}

When you run the program, Windows informs you that a device are trying to make a connection:

Connect to Bluetooth device

Connect to Bluetooth device

Click the popup and enter the PIN code to make the connection. You need to perform this task only the first time.

Now that the Gadgeteer application is up and running, and the Bluetooth module is correctly configured, we can write a PC program to control it.

Create a new WPF Application with name BluetoothControl. Write the following XAML in the MainWindow.xaml file:

<Window x:Class="BluetoothControl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Bluetooth Control" Height="200" Width="400" ResizeMode="NoResize"
        Loaded="Window_Loaded" Closing="Window_Closing" Icon="bluetooth.png">
    <Grid Background="WhiteSmoke">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Margin="10" Text="Bluetooth Control" FontWeight="Bold" FontSize="20">
        </TextBlock>
        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock Margin="10" Text="Status:" VerticalAlignment="Center" 
                       Grid.Row="0" Grid.Column="0"></TextBlock>
            <TextBlock x:Name="lblStatus" Text="No Device" Width="200" VerticalAlignment="Center" 
                       HorizontalAlignment="Left" Grid.Row="0" Grid.Column="1"></TextBlock>
            <Button Content="Search device" x:Name="btnSearchDevice" Grid.Row="0" Grid.Column="2" 
                    HorizontalAlignment="Left" VerticalAlignment="Center" Padding="5" Margin="5" 
                    Click="btnSearchDevice_Click"></Button>
            <TextBlock Margin="10" Text="Message:" VerticalAlignment="Center" Grid.Row="1"
                    Grid.Column="0"></TextBlock>
            <TextBox x:Name="txtMessage" Margin="0 0 0 0" Width="200" 
                     VerticalAlignment="Center" Grid.Row="1" Grid.Column="1"
                     HorizontalAlignment="Left"></TextBox>
            <Button Content="Send message" x:Name="btnSendMessage" VerticalAlignment="Center" 
                    Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left" Margin="5" Padding="5" 
                    IsEnabled="False" Click="btnSendMessage_Click"></Button>
        </Grid>
        <TextBlock Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="5">
            Realized by
            <Hyperlink NavigateUri="http://blogs.ugidotnet.org/marcom" 
                       RequestNavigate="Hyperlink_RequestNavigate"> 
            Marco Minerva</Hyperlink>
        </TextBlock>
    </Grid>
</Window>

The application UI will appear as in the following screenshot:

WPF Application

WPF Application

Then, download and add a reference to the 32feet.NET library (if you use NuGet, you can find it simply searching Bluetooth).

In the btnSearchDevice_Click event handler, we create a BackgroundWorker that executes the following code inside the DoWork event (you can refer to the downloadable project available at the end of this article for a complete reference):

try
{
    bluetooth = new BluetoothClient();
    var gadgeteerDevice = bluetooth.DiscoverDevices()
                                   .Where(d => d.DeviceName == "Gadgeteer").FirstOrDefault();
    if (gadgeteerDevice != null)
    {
        bluetooth.SetPin("1234");
        bluetooth.Connect(gadgeteerDevice.DeviceAddress, BluetoothService.SerialPort);
        bluetoothStream = bluetooth.GetStream();
        e.Result = true;
    }
    else
    {
        e.Result = false;
    }
}
catch (Exception)
{
    e.Result = false;
}

To manage bluetooth devices, we start creating a BluetoothClient object, contained in the InTheHand.Net.Sockets namespace. Then, we call the DiscoverDevices method, that returns an array of all the devices it finds. As we have called our device Gadgeteer, we use LINQ to search for a device with this name. If we find it, we set the PIN code and use the Connect method to establish a connection. It requires the device address and the Bluetooth service class to use. We must use BluetoothService.SerialPort, that identifies a service that provides a basic serial emulation connect over Bluetooth. Finally, we get the stream that allows us to communicate with the device.

In the btnSendMessage_Click event handler, if the connection has been correcly established, we can send messages over the stream:

private void btnSendMessage_Click(object sender, RoutedEventArgs e)
{
    if (bluetooth.Connected && bluetoothStream != null)
    {
        var buffer = System.Text.Encoding.UTF8.GetBytes(txtMessage.Text);
        bluetoothStream.Write(buffer, 0, buffer.Length);
        txtMessage.Text = string.Empty;
    }
}

We simply get the bytes that compose the message and then we call the Write method on the stream object: the Bluetooth module on Gadgeteer device will receive the data and show it on the diplay.

Both the Gadgeteer and the WPF application are avaiable for download.

GadgeteerBluetooth.zip

, ,

  1. #1 by wintonlin on April 21, 2012 - 8:13 PM

    Very Useful, could you show an example, how to receive the sensor data from Gadgeteer to PC via the Bluetooth module? Thanks.

    • #2 by Marco Minerva on April 22, 2012 - 3:27 AM

      It’s really simple: from Gadgeteer, you need to use the client.Send method. Then, the PC application can invoke the bluetoothStream.Read method to read the data.

  2. #3 by Moreno on April 22, 2012 - 11:13 AM

    Nell’applicazione wpf come fai a rilevare se sul pc il bluetooth è acceso o spento ?

    • #4 by Marco Minerva on April 22, 2012 - 4:29 PM

      Puoi realizzare tutti i controlli che ti servono con la classe InTheHand.Net.Bluetooth.BluetoothRadio. La sua proprietà IsSupported ti dice ss il PC dispone del Bluetooth. In caso positivo, leggendo il valore della proprietà PrimaryRadio.Mode, puoi sapere qual è la modalità corrente: in particolare, per sapere se è accesso o spento, devi controllare se Mode è uguale a PowerOff.

  3. #5 by apmankins on April 24, 2012 - 9:55 PM

    Apologies in advance if this is a stupid question (I am new to .NET), but how exactly do I add Eduardo’s Bluetooth class to the Gadgeteer libraries?

    • #6 by apmankins on April 24, 2012 - 10:40 PM

      Never mind. Problem solved.

  4. #7 by Michael Dodaro on April 24, 2012 - 10:38 PM

    If you download Marco’s project from this page, everything you need to build the library is there in the namespace Gadgeteer.Modules.Velloso.
    Eduardo Velloso is the developer who designed the driver.

    • #8 by apmankins on April 25, 2012 - 5:56 AM

      Got it. Thank you for your help!

      • #9 by wintonlin on May 8, 2012 - 3:01 AM

        Dear Michael

        I test your project but not work.
        I don’t have Bluetooth on my PC now, so I use my ipad2 to find the bluetooth device.

        But I can’t find the “Gadgeteer”.

        The output is below,

        WORK:SLAVER
        Client Mode
        Enter Pairing Mode
        Program Started
        +STNA=Gadgeteer
        +STPIN=1234
        +INQ=1
        OK
        OK
        OK
        OK
        +BTSTATE:0
        +STWMOD=0
        +BTSTATE:1
        +BTSTATE:3
        WORK:SLAVER
        +BTSTATE:0
        +BTSTATE:1
        +BTSTATE:3
        CONNECT:FAIL
        +BTSTATE:1

      • #10 by Marco Minerva on May 8, 2012 - 3:45 AM

        Have you tried resetting your Gadgeteer device? Some times, the discover may fail, and the module takes some second to become discoverable.

  5. #11 by wintonlin on May 8, 2012 - 8:18 PM

    I use a usb bluetooth dongle in My PC.
    Its works.
    But why My ipad can’t find the Gadgeteer but the PC can.

    • #12 by Marco Minerva on May 9, 2012 - 1:32 AM

      I don’t know how iPad works, sorry. I think can may try asking this question directly to Eduardo Velloso, because it seems to be related to Bluetooth Module discoverability.

  6. #13 by wintonlin on May 9, 2012 - 6:56 PM

    Thanks, I have contacted Eduardo Velloso. He also don’t know the iOS too.
    I ask him help me to test if his phone can find the bluetooth spider.(My android phone can’t find)
    Maybe you can help me to check your phone also.
    Another question is , does the 32feet.NET can works on ASP.NET web Form?
    I am trying use website to control the Bluetooth NETMF device.
    Thanks.

    • #14 by Marco Minerva on May 10, 2012 - 12:22 AM

      No, you can’t use the 32feet.NET library with ASP .NET, because it needs direct access to hardware resources, that can’t be used from a Web Application.

    • #15 by Marco Minerva on May 19, 2012 - 5:33 AM

      Hi!

      I have discovered that iPhone and iPad devices can connect via Bluetooth only to other iPhone and iPad devices, so it is normal that your iPad can’t find Gadgeteer. It is by design.

  7. #16 by Ian Lee, Sr. (@ianlee74) on August 29, 2012 - 9:02 PM

    How can I add two-way data transfer to this example so that I can also send data back to the PC from the gadget?

    • #17 by Marco Minerva on August 30, 2012 - 3:09 AM

      Read my first comment to this article, I have described the methods you need to use.

  8. #18 by Jeevan on September 16, 2012 - 11:30 AM

    Dear Marco,
    Thank you for taking the time to create these tutorials and also to share your design. Having real world examples are especially helpful to persons such as myself who are beginners.

    I am new to C# and also to the Gadgeteer platform. My Main-board is the Fez Cerberus. I am attempting to connect to my PC (using a USB dongle) from the GHI Bluetooth module (as you have done in your example).

    I however do not have the Seeed oledDisplay (so I’ve commented out that part of your code).

    My first goal was to have my PC recognise that a device was trying to connect to it. However when I run my programme I get an error:
    “The type or namespace name ‘Serial’ does not exist in the namespace ‘Gadgeteer.Interfaces’ (are you missing an assembly reference?)”

    All I can figure is that I am missing a library file of some sort? I have downloaded the driver from Eduardo Velloso and pointed to the Bluetooth.cs file under resources in my MSVS Project.

    Also my system currently runs the .NET Micro Framework 4.2 SDK

    Thank you for taking a look at my issue, any assistance that you can provide would be appreciated.

    Jeevan

    • #19 by Marco Minerva on September 17, 2012 - 1:13 PM

      Hi! Can you show me the line of code that causes this error?

    • #20 by Chris Miller (@anotherlab) on September 25, 2012 - 9:17 PM

      The serial code was moved in NETMF 4.2 to Gadgeteer.Serial.dll, if you add a reference to that assembly, your code should compile just fine under 4.2

  9. #21 by rahul on February 27, 2014 - 9:04 PM

    bluetooth.Connect(gadgeteerDevice.DeviceAddress, BluetoothService.SerialPort);
    bluetoothStream = bluetooth.GetStream();

    I have an issue inth these 2 lines,Why this happen.
    why stream become null..

  1. 32feet.NET, Bluetooth and .Net Gadgeteer – Microsoft | windows7bluetooth.com

Leave a reply to wintonlin Cancel reply