Click here to Skip to main content
15,918,003 members
Articles / Ultrabook


Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
28 Nov 2012CPOL9 min read 29.2K   9   8
Ultrabook vehicle dynamo

This article is an entry in our AppInnovation Contest. Articles in this sub-section are not required to be full articles so care should be taken when voting.


[Note: The link to the download for the app on the Intel AppUp store was removed due to Intel closing the AppUp store in March 2014, the source is still available on the post competition article I wrote. See this link.]

This article is a conceptual look at a proposed application to demonstrate the potential of the sensory devices embedded within the ultrabooks.

For those of you who enjoy motor-sport, and maybe watch the likes of the Formula 1, you will have probably noticed the on-screen graphics of vehicle performance.

Modern sports cars, such as the Nissan GT-R also have onboard visual displays to convey the vehicle performance to the driver.

What if you are a track day fanatic, or just a general petrol head or gear head (or whatever you call them in your area), what if you could just take your ultrabook into the car, secure on the dash, etc. and then have it display performance characteristics?

Well, that is the concept behind this app. (And yes, I am a petrol head!)

What are the Aims of this App

Using the GPS sensors, accelerometer, inclinometers, etc., it should be possible to display information to the vehicle occupants such as acceleration/deceleration data, positional data, and if you know the vehicles + occupants weight, it should be possible to calculate power characteristics.

Some of the statistics that you should be capable of displaying are:

  1. Acceleration/deceleration
  2. Cornering G
  3. 0 to 60 (62mph) / 100 km/h (or custom)
  4. 0 to 100 to 0
  5. Quarter mile (or custom)
  6. Sure there are others!

Using the GPS data, it should also be possible to map the data over your favourite mapping tools such as Google maps/earth.

Data can also be stored for historical reference, or comparison between vehicles or following modifications.


The data could potentially be displayed in a number of formats, e.g., numerical data, bar graphs, line graphs, analogue dials.

It may also be possible to allow the user to build custom dashboards to present the data as they see fit.

Using the Code

Project Update 1 (24th October, 2012)

I have been dipping in and out of this project over the last week, when I can. The main coding effort is going to take place when I get home in a week's time, but that will leave things a bit tight for the next deadline, so I need to be doing something now!

Initially, I am developing the code using Visual Studio 2012 Pro on a standard laptop, so I have no way to test the sensors, and had to come up with a suitable approach that could allow for the UI to be tested regardless of the underlying hardware. Can't wait to get my hands on the ultrabook to actually see if things move in the right direction, etc.!

After initially creating a blank Winforms C# application, I had to modify the project file to allow access to the Windows 8 Sensor APIs. This is covered in several articles, but in essence, you need to add a new property group to the project file containing:

<propertygroup />
    <targetplatformversion />8.0</targetplatformversion />
</propertygroup />

After doing this, you can then add suitable references to the runtime files; Windows.Devices.Sensors.dll and System.Runtime.InteropServices.WindowsRuntime.dll.

Sensor Wrappers

As mentioned above, I need a way to test the UI without having access to the live sensor data. In order to achieve this, I created some wrapper classes that act as a middle-man between the UI and the actual sensors. This allows me to enable a Simulate Mode and inject test data into the code. Also, if any sensor is not available, that particular sensor is automatically switched to simulate mode. So far, I have created wrappers for the AmbientLightSensor, Accelerometer, Compass, Gyrometer and Inclinometer. Still have to look at the GPS sensor.

Below is what the wrapper MyLightSensor looks like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Sensors;

namespace UltraDynamo.Sensors
    public class MyLightSensor
        public static bool Available { get; private set; }
        public static bool Simulated { get; private set; }

        public static float LightReading {get; private set; }
        public static float rawLightReading {get; private set; }
        public static float simLightReading {get; private set; }

        //Source Sensor
        private static LightSensor lightSensor;

        public static event ChangeHandler Change;
        public static EventArgs e = null;
        public delegate void ChangeHandler(MyLightSensor sender, EventArgs e);

        public MyLightSensor()
            //Base sensor
            lightSensor = LightSensor.GetDefault();

            if (lightSensor != null)

                lightSensor.ReadingChanged += lightSensor_ReadingChanged;

        void lightSensor_ReadingChanged(LightSensor sender, LightSensorReadingChangedEventArgs args)
             //throw new NotImplementedException();
            rawLightReading = args.Reading.IlluminanceInLux;
            if (!Simulated)

            //raise event
            if (Change != null)
                Change(this, e);

        private void setLightLevel(float value)
            LightReading = value;

        private void setAvailable(bool available)
            Available = available;

            if (Change != null)
                Change(this, e);

        public void setSimulated(bool simulated)
            Simulated = simulated;

            if (Change != null)
                Change(this, e);

        public void setSimulatedValue(float value)
            simLightReading = value;

            if (Simulated)

            if (Change != null)
                Change(this, e);

As you can see, there are a number of static properties, that show if the Sensor is currently Simulated and/or Available, as well as the Used, Raw and Simulated values. A couple of methods are provided to set simulated data values and switch modes between Simulated and Live. In the code, you can also see the private static field that is the actual sensor where the live data is accessed, as well as a change event for tracking sensor data updates.

Sensor Simulation Controller

After creating the sensor wrappers, the next step was to create a number of Forms that can be used to manipulate the sensor data. The image below shows the simulate form created for the Inclinometer:

Image 1

Sensor Data Presentation

Having the data available now, I have started to create UserControls that can be dropped into any part of the application, either on standalone forms so the user can customise the layout, or onto pre-defined dashboards. Below shows the three user controls created for the Inclinometer's Pitch, Roll and Yaw and show the data represented in the simulate form above.

Image 2Image 3Image 4

Graphics are not one of my strong areas, so I have used some crude image manipulation just to get the core functionality working, and can go back and enhance things with future updates. You will also notice on the forms above the status blobs on the top left and top right. The top left blue blob is a flag that the data is Simulated. The blob on the top right shows the real sensor status, Red=Unavailable, Green=Available.

Another control that has been created is a compass rose indicator, this is shown below:

Image 5

If we now take a look at one of the simpler controls, the CompassHeading control, this takes the Compass Heading and converts the numerical value to either of "N, NE, E, SE, S, SW, W, NW". You can see how this control listens to events from the Sensor wrapper:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using UltraDynamo.Sensors;

namespace UltraDynamo.Controls
    public partial class UICompassHeadingLetters : UserControl
        //Source Compass
        MyCompass myCompass;
        public UICompassHeadingLetters()

            //Initialise a compass
            myCompass = new MyCompass();

            //Track changes on the compass
            //Add a compass to the mainform
            MyCompass.Change += new MyCompass.ChangeHandler(myCompass_Change);
            myCompass_Change(myCompass, new EventArgs());

        void myCompass_Change(MyCompass sender, EventArgs e)

        private void UICompassHeadingLetters_Paint(object sender, PaintEventArgs e)
            String output = "N"; //Default to North removes need for two ifs below
            //Get the string representation of the heading
            double heading = MyCompass.Heading;

            if (heading >= 22.5 && heading < 67.5)
                output = "NE";

            if (heading >= 67.5 && heading < 112.5)
                output = "E";

            if (heading >= 112.5 && heading < 157.5)
                output = "SE";

            if (heading >= 157.5 && heading < 202.5)
                output = "S";

            if (heading >= 202.5 && heading < 247.5)
                output = "SW";

            if (heading >= 247.5 && heading < 292.5)
                output = "W";

            if (heading >= 292.5 && heading < 337.5)
                output = "NW";

            //Establish base fonts and graphics objects
            Graphics g = e.Graphics;

            Font f = this.Font;
            Font newFont = this.Font;
            SizeF testSize;
            float fHeight=0;
            float fWidth=0;
            bool fontGood = true;
            for (int newSize = 1; fontGood; newSize++)
                //Increase the size and test height again)
                newFont=new Font(f.Name,newSize,f.Style);
                testSize = g.MeasureString(output,newFont);
                //Determine boundary size for the text
                fHeight = testSize.Height;
                fWidth = testSize.Width;

                //Test the text height and width against control size
                if ((fHeight > (this.Height)) | (fWidth > (this.Width)))
                    fontGood = false;
                    newSize--;  //go back by 1 size, 
                                //recalculate size required for positioning central on control
                    if (newSize <6 ) { newSize=6;};
                    newFont = new Font(f.Name,newSize,f.Style);
                    testSize = g.MeasureString(output,newFont);
                    fHeight = testSize.Height;
                    fWidth = testSize.Width;

            //Draw the text heading on the control
            g.DrawString(output, newFont, Brushes.Green, 
                new Point((this.Width - (int)fWidth) / 2, (this.Height - (int)fHeight) / 2));

            if (MyCompass.Simulated)
                g.FillEllipse(Brushes.Blue, 0, 0, 5, 5);

            //Add a Red/Green dot to show sensor availability in top right corner
            if (MyCompass.Available)
                g.FillEllipse(Brushes.Green, this.Width - 5, 0, 5, 5);
                g.FillEllipse(Brushes.Red, this.Width - 5, 0, 5, 5);

The next stages of the development are to look at some real time trends, analog gauge dials and some of the other planned functionality as mentioned in the initial outline brief.

That is the end of Update 1. So far so good (I think!).

Project Update 2 (13th November, 2012)

Things have been a bit chaotic over the last couple of weeks working on this application.

Numerous problems have been encountered, and given the time frame, everything feels a bit rushed to get it "out the door". Some of the issues encountered are:

  • Typical cross threading problems
  • Sensors eventing conflicts
  • Inherent bugs in hardware/software
  • Code Signing and package creation

So where am I with things?

There was a big rewrite of some of the eventing to combat the cross threading problems. I still want to further improve this area, but can't risk breaking things at this stage. So maybe for a later date.

The simulation code shown above, was great for the initial testing, but given the rewrite of the sensor stuff, it no longer works, so has been tucked away in the background until it can be revisited at a later date.

There also appears to be a bug with the GPS subsystem at a hardware/driver level. So unfortunately, I cannot fully test or implement the features in the introduction list until this issue is resolved. However, the application still has useful functionality for an initial release.

A basic overview dashboard has been created which shows all the main sensor elements, as well as a net horsepower gauge. The HP is calculated by using the accelerometer and the vehicle (and occupants) weight. This is Net HP and does not take into account for drivetrain losses or drag losses. These can perhaps be factored in at a later date. The dashboard is shown below:

Image 6

There are also a number of realtime trends that show you what has been going on, for example, the one below is the accelerometer trend.

Image 7

I had problems getting a 'free' code signing certificate through and still waiting for the validation call. So I went on my own and got one through GlobalSign. That then introduced the problem of how to setup up Visual Studio to build the packages, code sign them in the post-build events. InstallShield was all new to me as well, so getting everything to package up nicely, sign the installers, etc. was a bit of a headache. This was followed by some pain of actually getting my hands on the MSI installer from setup wrapper.

Plenty of things to possibly write about at a later date, but in the meantime, I think my heads bust, and that concludes Update 2!

Project Update 3 (28th November, 2012)

After all, the hassle with submitting the app on the 14th, then the weeks delay waiting for it to be published, I just wanted to add a little update as I noticed I hadn't really mentioned it elsewhere already. In the dashboard display above, you will notice that the right hand dial indicator is displaying Net Horsepower. This is a calculated figure that is based on:

  1. The vehicle weight
  2. the Acceleration and
  3. the vehicle speed

If you refer to the wikipedia article and look at the calculations for the drawbar horsepower, you can see how they relate to each other.

James Watt introduced this unit of power in the 18th century and he stated that 1 horsepower was the power required to lift a 550lb weight in 1 second. It is possible to calculate this using the parameters shown and data from the Ultrabook sensors as:

Net HP = (Weight (in lbs) x Acceleration (g) x Speed (mph) ) / 375

The weight is provided by the user on the configuration page of the application, the other data is sensor derived. The 375 is a constant derived from the conversion of the 550 lb/second to miles per hour.

It would be easy to add in calculated constants for drivetrain losses and drag coefficients, but that is a job for another day.

After I had published the App, I noticed on the controls and displays, I had forgotten to enable "double buffering", so there is a bit of a flicker during updates. Since publishing, I have already also begun to rework the eventing system and various other parts of the application so hopefully get them out and released in a future update.

Other Blue Sky Idea

It may also be possible to further extend the core functionality to interface with the vehicles OBDII or CAN bus to make use of other reference data, e.g., vehicle parameters like speed, gear, throttle angles.

This is beyond the initial scope, but just a thought.

Points of Interest

This should provide plenty of research opportunity into the features of the ultrabooks and provide something interesting to get my teeth into.


  • 13th October, 2012 - First draft of conceptual app description
  • 24th October, 2012 - Project Update 1 added
  • 13th November, 2012 - Project Update 2 added
  • 28th November, 2013 - Project Update 3 added


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Scotland Scotland
I have been working in the Oil & Gas Industry for over 30 years now.

Core Discipline is Instrumentation and Control Systems.

Completed Bsc Honours Degree (B29 in Computing) with the Open University in 2012.

Currently, Offshore Installation Manager in the Al Shaheen oil field, which is located off the coast of Qatar. Prior to this, 25 years of North Sea Oil & Gas experience.

Comments and Discussions

QuestionSource code? Pin
Member 101955052-Sep-22 9:16
professionalMember 101955052-Sep-22 9:16 
AnswerRe: Source code? Pin
DaveAuld2-Sep-22 9:21
professionalDaveAuld2-Sep-22 9:21 
GeneralMy vote of 5 Pin
Jakub Szymanowski12-Dec-16 9:01
professionalJakub Szymanowski12-Dec-16 9:01 
GeneralRe: My vote of 5 Pin
DaveAuld12-Dec-16 18:20
professionalDaveAuld12-Dec-16 18:20 
GeneralAccuracy Pin
UberMeistro14-Jan-13 19:31
UberMeistro14-Jan-13 19:31 
GeneralRe: Accuracy Pin
DaveAuld14-Jan-13 20:44
professionalDaveAuld14-Jan-13 20:44 
QuestionMy vote of 5!! Pin
Abhishek Nandy7-Dec-12 18:05
professionalAbhishek Nandy7-Dec-12 18:05 
AnswerRe: My vote of 5!! Pin
DaveAuld7-Dec-12 23:49
professionalDaveAuld7-Dec-12 23:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.