Adding an Accelerometer to the Windows 8 Simulator

I have been busy developing for Windows 8 for a while now. Until Microsoft releases a WinRT “Surface” device (October?) I thought it would be nice to be able to test my apps transitions between ApplicationViewState.

I have an accelerometer in my .Net Gadgeteer kit…and a wifi module…hmm.

What I built is a gadget that exposes JSON formatted accelerometer data via a web service. Any Windows 8 (WinRT) applications can consume this service. There are a few details to getting this to work. I will briefly go over the main things to be aware of here. I will post the entire project later.

Here is what it looks like tacked on my laptop:

Accel

Across the top (from left to right): OLED Display, SEEED Studio Accelerometer, GHI Spider board, Wifi module
Across the Bottom: power module, battery pack.
On the table is a ClearWire wifi router.

Here are some of the main things to be aware of:

Time Series Graph
I added a OLED Display because it was very handy to have a time series graph to display the x,y,z axis’ for troubleshooting.

Time Series Graph

Here is the code for the graph:

 public class GraphHelper
    {
        uint currentX;
        uint MaxX;
        uint _y;
        uint _GraphHeight = 10;
        Gadgeteer.Modules.Seeed.OledDisplay _display;

        public GraphHelper(uint y, Gadgeteer.Modules.Seeed.OledDisplay display )
        {
            _y = y;
            _display = display;
            currentX = 0;
            MaxX = _display.Width;
            Clear();
        }
        private void Clear()
        {
            _display.SimpleGraphics.DisplayRectangle(Gadgeteer.Color.Gray, 1, Gadgeteer.Color.White, 0, _y, _display.Width, _GraphHeight);
        }
        float _maxG=1;
        public void AddDataPoint(float range)
        {
            //check if new values are larger than we expected.
            //I assume the range is between 1 and -1.
            //If the range is larger then we need to adjust.
            if (System.Math.Abs((int)System.Math.Ceiling(range)) > _maxG)
                _maxG = range;
            //shift all values to positive range.
            //TODO: fix variable names...
            float rangeNorm = range + _maxG;
            float integral = _GraphHeight / _maxG;
            rangeNorm = rangeNorm * integral;
            rangeNorm -= _GraphHeight;
            rangeNorm += _y +  (float)(_GraphHeight * 0.5);
            if(currentX==0)
                Clear();
            if ( rangeNorm < _y)
                rangeNorm = _y;
            if(rangeNorm > (_y + _GraphHeight))
                rangeNorm = _y + _GraphHeight;
            if (currentX <= MaxX)
            {
                _display.SimpleGraphics.SetPixel(Gadgeteer.Color.Green, currentX++, (uint)System.Math.Ceiling((uint)System.Math.Ceiling(rangeNorm)));
            }
            else
            {
                currentX = 0;
            }
        }

Here is how you would call its c’tor to put a graph halfway down the screen (display_height/2=64)and plot a point :

this.graphX = new GraphHelper(64, _display );
graphX.AddDataPoint( (float) averagedAcceleration.X );

Windows 8 Capabilities Panel in Visual Studio 12
Pay attention to the Capabilites tab in the Package.appxmanifest. I had enabled “Internet(Client)” and thought I was good to go. No so. There is also a “Home or Work Networking” capability. For connections to resources on a LAN you need to enable this.

Reactive Extensions for .Net are Very Cool
In my Win8 application I needed to call the sensor service on a timer. There are many ways I could have done this. I wanted a quick and easy solution that would work with the async nature of WinRT development and I knew for certain that this code would be not in a production system…ever. This isn’t to say RX .Net isn’t production worthy, just that this usage of a timer is probably not optimal for production but is great for demo code.

             var fivePerSecond = Observable.Interval(TimeSpan.FromMilliseconds(200))
                .ObserveOnDispatcher()
                .Subscribe(num =>
            {
                Get_Sensor_Data();
            });

Every 200 ms this will call Get_Sensor_Data()…which then calls MoveCube() here:

    HttpResponseMessage response = await rootPage.httpClient.GetAsync("http://192.168.1.10");
    await Helpers.MoveCube(response, renderer);
    Page.NotifyUser.Text = "Completed";

And finally, we get to the MoveCube()…

internal static class Helpers
    {
        internal static async Task MoveCube(HttpResponseMessage response, DxRenderer.Cube cube)
        {
            string responseBodyAsText;
            responseBodyAsText = await response.Content.ReadAsStringAsync();

            JsonValue value = JsonValue.Parse(responseBodyAsText);
            var c = value.GetObject();
            string sx = (c["Accel"] as JsonValue).GetObject()["x"].GetString();
            string sy = (c["Accel"] as JsonValue).GetObject()["y"].GetString();

            float.TryParse(sx, out cube.X);
            float.TryParse(sy, out cube.Y);
        }
    }

SharpDX is DirectX for C#
Finally, Jose Fajardo, who has published some very useful demos of SharpDX, provided the starting point for the Win8 cube rotation via accelerometer. I wasn’t able to get the SharpDX demos that come with SharpDX to run. But I was able to get Jose’s samples working. So thanks Jose! SharpDX is the only way I know of to do DirectX in WinRT apps using C#.

Advertisements

One thought on “Adding an Accelerometer to the Windows 8 Simulator

  1. Brilliant demo and you have just convinced me to start looking at .NET Gadgeteer. I’ve been putting it off for so long BUT your tricked out laptop has pushed me over the edge and im gonna look at it in the next couple of days 🙂

    Also really liked your use of Rx …

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s