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