WPF Sonar application using Arduino and PING))) sensor

I’ve been playing around with the Arduino more and more lately and really wanted to find a way to make it work with my other world of C# and WPF.   The idea was to make an application that changes the screen based on how far away the user is.  The only way that I could easily think about doing it was to use an Arduino as a serial device to help communicate with the sonar sensor. 

I picked up the PING))) from Parallax to use as the sensor from the Makershed and searched on the Arduino site for some samples and quickly found two great resources first is was this Ultrasound Sensor Tutorial and second was this fantastic Ping Library for Arduino by Caleb Zulawski, recipe which made it even easier to work with.

Here’s a top view of the setup mounted on a Wooduino

Here’s the sketch code for the Arduino:

/*  This code initializes a Ping))) sensor on pin 13 and
outputs the information over a serial connection */
#include <Ping.h>

Ping ping = Ping(13,0,0);

void setup(){
Serial.begin(9600);
}

void loop(){
ping.fire();
Serial.print(ping.microseconds());
Serial.print(",");
Serial.print(ping.inches());
Serial.print(",");
Serial.print(ping.centimeters());
Serial.println();
delay(1000);
}

This sketch sends out microseconds, inches and centimeters.  I have them sent as one comma delimited line per sonar pulse.  The code on the WPF side reads in that line and converts it as needed.

Here’s the XAML for the WPF app:

<Window x:Class="PingArduino.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" Loaded="Window_Loaded" Unloaded="Window_Unloaded">
<Grid>
<StackPanel VerticalAlignment="Center">
<TextBlock x:Name="tbJustData" HorizontalAlignment="Center" FontFamily="Segoe UI">0</TextBlock>
<TextBlock x:Name="tbPingMessage" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Segoe UI" FontSize="30pt">Waiting...</TextBlock>
</StackPanel>
</Grid>
</Window>

It’s a very simple StackPanel with two TextBlocks. 

Here we can walk through the code behind:

using System.IO.Ports;
using System.Windows.Threading;

I’m using System.IO.Ports to easily access the Arduino over the serial port.

It’s fairly simple to create the serial port in the code and then interact with a device over the serial port.  I have a couple of Arduino devices and each time I plug one in Windows defaults by adding it to a new COM port.  In the example below I’m on COM9 you’re mileage my vary here.  You can see which port your Arduino is using from the Sketch editor under Tools > Serial Port.

//create a Serial Port object
SerialPort sp = new SerialPort("COM9", 9600);

//Create a DispatcherTimer
DispatcherTimer timer = new DispatcherTimer();

string pingStatus;
public Window1()
{
InitializeComponent();

//enables the Data Terminal Ready (DTR) signal during serial communication
sp.DtrEnable = true;
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Open Serial Port
sp.Open();

//give it 2 seconds for the sketch to start up
System.Threading.Thread.Sleep(2000);

//Setup interval of DispatcherTimer
timer.Interval = TimeSpan.FromMilliseconds(500);

//configure and start the thread
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
//throw new NotImplementedException();
string pingData = sp.ReadLine();
string[] datapoints = pingData.Split(',');
pingStatus = datapoints[1];
double pingInches = Convert.ToDouble(pingStatus);

tbJustData.Text = pingStatus + " inches away";

if (pingInches > 50)
{
tbPingMessage.Text = "Hey I'm over here!";
}
else if (pingInches <= 50 && pingInches > 30)
{
tbPingMessage.Text = "Hello there how can I help you?";
}
else if (pingInches <= 30 && pingInches > 5)
{
tbPingMessage.Text = "Let me show you a few things";
}
else if (pingInches <= 5 && pingInches > 2)
{
tbPingMessage.Text = "I'm getting a little uncomfortable here.";
}
else if (pingInches <= 2 && pingInches > 0)
{
tbPingMessage.Text = "Stop touching me!";
}
else
{
tbPingMessage.Text = "You are " + pingInches + "inches away" ;
}
}

Here’s a little video of everything in action:

Tags: , , , , ,

6 Responses to “WPF Sonar application using Arduino and PING))) sensor”

  1. […] including sensors, controller boards and drivers and sample app etc. (see Ryan’s post here: http://www.futile.com/2010/02/wpf-sonar-application-using-arduino-and-ping-sensor/  ) That aside I wanted to be able to talk about this kind of technology at MIX around integrating […]

  2. […] application. This was built using the Arduino Ping prototype mentioned in my previous post WPF Sonar application using Arduino and PING))) sensor Share and […]

  3. Great to see someone’s using my library!

  4. Nick says:

    Awesome job, I’ve been working with WPF & Silverlight over the past year & bit, recently getting into Arduino & couple of other frameworks, although wondering how to use Arduino with WPF & Silverlight, thanks for the knowledge.
    Have you tried this with Silverlight OOB app? Wondering if you know if this is possible

    cheers

  5. Nick says:

    Hi ,
    In your XAML there’s a Unloaded event on the window, although in your code behind there isn’t a definition for that event, what should happen on unloaded?

  6. Nick says:

    I’ve added an unloaded event definition to the code behind, releases the timer event & closes serial port.

    private void Window_UnLoaded(object sender, RoutedEventArgs e)
    {
    //Close Serial Port
    sp.Close();

    //stop and release the thread
    timer.Stop();
    timer.Tick -= new EventHandler(timer_Tick);
    }

Leave a Reply