Controlling a Netduino over Bluetooth with WP8

TwitterFacebookRedditGoogle+EmailPinterest

The last time I touched my Netduino was about 5 months ago (due to work-load), around the time of my wedding to make the wedding tank. So this weekend I decided to dust it off and introduce it to my Lumia 920.

Disclosure: I didn’t actually dust it off.

They are now lovers.

Here is a video of what this post aims to explain how to make. It’s hard to see the actual color of things in the video – so let’s just trust me that it works Smile

I’m going to start by explaining the entire Netduino side of things then move to WP8. I’ve pretty much explained it as simply as possible.

First was to get the Netduino updated. Surprisingly, the Netduino didn’t update itself sitting in the cupboard. I’m running Windows 8 – but besides mistakenly flashing it with the Netduino Plus rom the drivers all work fine and there’s nothing special you need to do. Next I picked up this awesome little Bluetooth module from DX:

http://www.dx.com/p/jy-mcu-arduino-bluetooth-wireless-serial-port-module-104299#.UzwNF1ezzxQ

To power it, VCC goes to the Netduino’s 5v and GND goes to…ground.
Then I put TXD into Digital port 0 and RXD into Digital port 1.

//declare the port
static SerialPort bt;

//in Main, initialize it
bt = new SerialPort(SerialPorts.COM1, 9600, Parity.None, 8, StopBits.One);
bt.DataReceived += new SerialDataReceivedEventHandler(rec_DataReceived);
bt.Open();

That will make it “discoverable” by other devices. To make sure it is, on your phone goto Settings –> Bluetooth, and look for “linvor”.

wp_ss_20130113_0002

Tap to pair with it, and use the default code of 1234. It should connect, and will disconnect after 10 seconds or so (because it’s not being used). Once you pair, the little flashing red LED on the BT module will go solid.

OK, now we need to setup the event handler we declared earlier for when it receives data. The first mistake I made was to presume that every message I sent would get delivered in one go. That’s wrong. So if I send “ping” from my phone, I actually will usually come through in two separate messages of “p” and “ing”. The simplest way to work around that is to just have a delimiter that marks the end of a message. So send the message as “ping|” with a pipe at the end. Below is the code I used to keep a buffer and build up the message.

What that does is build up the buffer until it sees a “|” and then sends the string to the DoSomething method. It’s probably not the best way to do it, but it does work perfectly for what we need. It also doesn’t take into account that messages could come in the wrong order (I mean two messages that get sent at the same time could be mixed up). That being said even with sending hundreds of messages within MS’s of each other, it hasn’t failed yet.

Next up is the RGB LED. In my example the pins (all to Digital) are as follows:
Red: 9
Green: 6
Blue: 5
Cathode (long pin): GND
The RGB pins all have 330 Ohm resistors (the red pin should have a slightly higher Ohm but I didn’t have any).

I made a dead simple RGB LED helper class that will take in 0-100 for each color. Here it is:

 

In your main class declare an instance of that:

 

To change the color you can now just use rgbControl.Set(100,100,100); where each value is a uint from 0 to 100 (basically a percent).

What we’re going to do is send RGB values from WP8 to the Netduino in the following format: “50,60,70|”. So here is the DoSomething method mentioned earlier that will actually handle  that. It also checks if the message is “ping” and if so, just sends back “ping” to the phone. I added that to test the roundtrip time.

Yay! Netduino side done! So far your Netduino should turn on, initialize the RGB LED and BT module, and then sit waiting data. Once it receives it, it will build up a buffer until it has a whole message, work out whether it is a ping, and if so return the ping. If it’s not a ping it will attempt to split out 3 numbers, one for each color, and then set the RGB LED.

NOTE: I’ve got almost no error handling. If something goes wrong it’s going to crash and you will need to restart the Netduino. It won’t shouldn’t crash with what we are doing, but in the real world please never do that.

Onto Windows Phone 8.

Create a new WP8 application in VS2012. Yes, this is only possible in WP8, not 7.

I’ve made a simple UI which has 3 sliders, one for each color. By default, the color of the sliders on the left of the handle will be the phone’s accent color, so I overrode the style and changed that. Below that is a Rectangle that shows the color. Then there are 3 radio buttons: Still, Strobe, and Ambient. Still will just send the slider values and strobe will randomize the sliders every 100MS (essentially flickering the LED). Ambient is a bit more complicated. I am using the [back] camera on the device to get the average color of what the phone is looking at, and then it sends that color through to the Netduino. To force the camera to initialize I needed to put a hidden rectangle on the UI and bind it’s Brush to the camera.

Above all of that is a Grid with a ProgressBar to show that it’s connecting. If the connection fails (or the first time it connects), it will display this overlay until it’s successfully reconnected and has sent and received a test ping.

wp_ss_20130113_0003

And a MessageBox is used to show the ping time:

wp_ss_20130113_0004

Against my better judgment, below is the lengthy XAML:

<phone:PhoneApplicationPage.Resources>
<Style x:Key=”SliderStyle” TargetType=”Slider”>
<Setter Property=”BorderThickness” Value=”0″/>
<Setter Property=”BorderBrush” Value=”Transparent”/>
<Setter Property=”Maximum” Value=”10″/>
<Setter Property=”Minimum” Value=”0″/>
<Setter Property=”Value” Value=”0″/>
<Setter Property=”Background” Value=”{StaticResource PhoneChromeBrush}”/>
<Setter Property=”Foreground” Value=”{StaticResource PhoneAccentBrush}”/>
<Setter Property=”Template”>
<Setter.Value>
<ControlTemplate TargetType=”Slider”>
<Grid Background=”Transparent”>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name=”CommonStates”>
<VisualState x:Name=”Normal”/>
<VisualState x:Name=”MouseOver”/>
<VisualState x:Name=”Disabled”>
<Storyboard>
<DoubleAnimation Duration=”0″ To=”0.1″ Storyboard.TargetProperty=”Opacity” Storyboard.TargetName=”HorizontalTrack”/>
<DoubleAnimation Duration=”0″ To=”0.1″ Storyboard.TargetProperty=”Opacity” Storyboard.TargetName=”VerticalTrack”/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=”Fill” Storyboard.TargetName=”HorizontalFill”>
<DiscreteObjectKeyFrame KeyTime=”0″ Value=”{StaticResource PhoneDisabledBrush}”/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=”Fill” Storyboard.TargetName=”VerticalFill”>
<DiscreteObjectKeyFrame KeyTime=”0″ Value=”{StaticResource PhoneDisabledBrush}”/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name=”HorizontalTemplate” Margin=”{StaticResource PhoneHorizontalMargin}”>
<Rectangle x:Name=”HorizontalTrack” Fill=”{TemplateBinding Background}” Height=”12″ IsHitTestVisible=”False” Margin=”0,22,0,50″/>
<Rectangle x:Name=”HorizontalFill” Fill=”{TemplateBinding Background}” Height=”12″ IsHitTestVisible=”False” Margin=”0,22,0,50″>
<Rectangle.Clip>
<RectangleGeometry Rect=”0, 0, 6, 12″/>
</Rectangle.Clip>
</Rectangle>
<Rectangle x:Name=”HorizontalCenterElement” Fill=”{StaticResource PhoneForegroundBrush}” HorizontalAlignment=”Left” Height=”24″ Margin=”0,16,0,44″ Width=”12″>
<Rectangle.RenderTransform>
<TranslateTransform/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<Grid x:Name=”VerticalTemplate” Margin=”{StaticResource PhoneVerticalMargin}”>
<Rectangle x:Name=”VerticalTrack” Fill=”{TemplateBinding Background}” IsHitTestVisible=”False” Margin=”18,0,18,0″ Width=”12″/>
<Rectangle x:Name=”VerticalFill” Fill=”{TemplateBinding Foreground}” IsHitTestVisible=”False” Margin=”18,0,18,0″ Width=”12″>
<Rectangle.Clip>
<RectangleGeometry Rect=”0, 0, 12, 6″/>
</Rectangle.Clip>
</Rectangle>
<Rectangle x:Name=”VerticalCenterElement” Fill=”{StaticResource PhoneForegroundBrush}” Height=”12″ Margin=”12,0,12,0″ VerticalAlignment=”Top” Width=”24″>
<Rectangle.RenderTransform>
<TranslateTransform/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Resources>

<!–LayoutRoot is the root grid where all page content is placed–>
<Grid x:Name=”LayoutRoot” Background=”Transparent”>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”*”/>
</Grid.RowDefinitions>

<StackPanel x:Name=”TitlePanel” Grid.Row=”0″ Margin=”12,17,0,28″>
<TextBlock Text=”BLUETOOTH TEST” Style=”{StaticResource PhoneTextNormalStyle}” Margin=”12,0″/>
<TextBlock Text=”colors” Margin=”9,-7,0,0″ Style=”{StaticResource PhoneTextTitle1Style}”/>
</StackPanel>

<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>
<StackPanel>
<Slider Minimum=”0″ Maximum=”100″ x:Name=”redSlider” Background=”Red” ValueChanged=”redSlider_ValueChanged” Style=”{StaticResource SliderStyle}”></Slider>
<Slider Minimum=”0″ Maximum=”100″ x:Name=”greenSlider” Background=”Green” ValueChanged=”greenSlider_ValueChanged” Style=”{StaticResource SliderStyle}”></Slider>
<Slider Minimum=”0″ Maximum=”100″ x:Name=”blueSlider” Background=”Blue” ValueChanged=”blueSlider_ValueChanged” Style=”{StaticResource SliderStyle}”></Slider>
<Rectangle x:Name=”colorRect” Height=”100″></Rectangle>
<StackPanel Orientation=”Horizontal”>
<RadioButton IsChecked=”True” Content=”Still” x:Name=”stillRadio” Checked=”stillRadio_Checked_1″></RadioButton>
<RadioButton Content=”Strobe” x:Name=”strobeRadio” Checked=”strobeRadio_Checked_1″></RadioButton>
<RadioButton Content=”Ambient” x:Name=”ambientRadio” Checked=”ambientRadio_Checked_1″></RadioButton>
<Rectangle Visibility=”Collapsed” x:Name=”rectPreview” Width=”1″ Height=”1″ Margin=”10″>
<Rectangle.Fill>
<VideoBrush x:Name=”previewVideo”/>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
<Button Margin=”-12,0,-12,0″ x:Name=”pingBtn” Content=”Ping device” Click=”pingBtn_Click”></Button>

</StackPanel>
<Grid Visibility=”Collapsed” x:Name=”connectingOverlay” Background=”#CC000000″>
<StackPanel VerticalAlignment=”Center”>
<TextBlock HorizontalAlignment=”Center” Text=”Connecting”></TextBlock>
<ProgressBar IsIndeterminate=”True”></ProgressBar>
</StackPanel>
</Grid>
</Grid>

</Grid>

 

Now that the UI is setup we need to initialize some things:

And then in the Loaded event of the page start the connection. In the code below I’m just using the first paired device it returns. You should obviously allow the user to choose the right one. Also, before running this code you would have had to pair the device with the phone.

When it starts to connect the overlay is displayed. After connecting it sends a ping. When the ping is received back the overlay is hidden. The WaitForData method will continually loop round getting messages.  Finally there is a small method to send data.

Next up we need to create event handlers for the slider change events. Each time a slider is moved it sends the RGB values to the Netduino. This isn’t the best way of doing it because you are repeating the other two values even though they haven’t changed. However, for clarity, it’s definitely the simplest, and BT is very fast and we don’t need to worry about bandwidth consumption.

The pumpEffectedFrames bool is to do with the camera. I’m not going to go into the camera stuff in this post as it’s a bit beyond the scope, plus you can just checkout the source to see that. One thing I should say is that the way I am determining the average color isn’t the best way. I’m just resizing the preview image to 1px X 1px. The problem is that resizing kills off a lot of pixels. I did originally take a method from Project Mosaic which was very accurate but the loss in performance wasn’t worth the accuracy.

Also to filter out fluctuations in the image color I’m using a Kalman filter.

If you’ve got question you can ask me here or on the Twitter machine: @roguecode

Here is the source:
WP8 project
Netduino project

TwitterFacebookRedditGoogle+EmailPinterest
  • Mario Vernari

    Nice job Matt.
    However you actually can do WP7.1 (Mango) apps with VS2012: I done it and tested on my Lumia 800.
    Sincerely I don’t know whether the BT support is the same on my phone: I’ll dig on it.
    Cheers

    • RogueCode

      Thanks!
      Yeah, I know. I was actually referring to the Bluetooth stuff only being available in WP8 not 7.1 – nothing to do with 2012. Sorry if I wrote that confusingly.

  • Scott

    Great post!

    The only thing I would like to add is, in your WP8 project, in order to get the bluetooth to work, make sure that you have both ID_CAP_PROXIMITY and ID_CAP_NETWORKING checked on the capabilities tab of your manifest file. Otherwise, you’ll get the error “An attempt was made to access a socket in a way forbidden by its access permissions.” I didn’t have the proximity capability checked because I thought that was only for NFC. Apparently it’s required for bluetooth as well.

    Thanks again Matt for posting this.

  • Turner

    Hi
    I learnd a lot from this code… So thank’s for bloging it!

    in “WaitForData(socket)”:

    ————————————————
    finally
    {
    WaitForData(socket);
    }
    ———————————————–
    will this not result in a StackOverflowException??

    • RogueCode

      No it won’t because it’s an async method so waits to receive data, then only runs itself again. Data is received in blocks so for each message it might run a few times, but after that it will just sit waiting on a background thread.

      • Turner

        That, makes sence..
        Thanks for the answer.