Click here to Skip to main content
Click here to Skip to main content

Upgrading your car with .NET Micro Framework

, 27 Sep 2013 LGPL3
Rate this:
Please Sign up or sign in to vote.
Leaking the digital on our physical world for .NET Developers

Leaking the digital on our physical world, for .NET developers 

Requirement : .NET MicroFramework SDK + Gadgeteer Package see GHI help page for links.

Introduction  

Truth to be told… I failed my driver license. I don’t own a car, and I don’t like cars…
But while the Fez Spider I bought for a project long time ago were gathering dust, Robin Martin, an IT wizard I knew from my old days at school was interested to make something useful.

Robin does not like coding he is a real 100% IT guy except he does not drink coffee and eats only potatoes… but he likes his car, and doesn’t mind hacking some lines of code together to get things done as long as it stays simple.

That’s what he did… 50 lines of code later his home made Fuel Consumption Meter was born.

Dashboard

He took out the dashboard of his cars, made a hole inside and added his Fuel Consumption Meter like a vulgar plugin. That’s what I call hacking.

But let’s be clear. His hack works with 50 lines of plain old C# code, and no electronic knowledge is required.

This article will show how to do the same thing with an LCD display first (10 lines of code), then we will how to use 7-Segments leds instead right after.

Let’s dive in a field that few developers knows : .NET MicroFramework.

An overview of the .NET MicroFramework ecosystem

If you are not interested about the ecosystem, but only the project, be free to skip this part.

Gadgeteer

The Fez Spider and Fez Cerberus from this article are part of a family of device called Gadgeteer, an open source toolkit from Microsoft for building small electronics device.
The creator of Fez Spider, GHI Electronics create lots of  gadgeteers at all price.
Netduino Go is also a less powerfull but cheaper alternative.
If you know other gadgeteer makers, put them in comments, I’ll update the article.

And you can find tons of modules pluggable to your gadgeteers… even a printer !

Netduino

If you like hacking at the electronic level, then, classical netduino might be for you. (You can also do that on Gadgeteer, as you will see in this article)
Unlimited fun for something like 30$, you can find lots of community stuff about it since you can play with arduino compatible shields… an already well know microcontroller for hobbyists.

Be careful though… I killed many netduino by plugging things incorrectly… because I never learned real electronics at school. Actually I learn electronic by killing my netduinos.

Space is limited, your code need to fit into something like 200ko depending on the board you choose.

Secret labs, the creator of netduino and its community is awesome, they reply to questions in the forum very quickly, and post lots of interesting stuff.

Material and software requirements

For the software part, the help page on GHI Electronics get you started, but I’ll repeat it here, all is free:

  • Visual studio 2010/2012 express or better
  • .NET Microframework SDK (set project templates in Visual Studio and Micro framework libraries)
  • Gadgeteer package (Additional libraries and project templates specific to Gadgeteers)

For the hardware part, this article is divided into two parts, one part is using LCD display to show the fuel consumption meter, the second part use 7-Segment display:

Using LCD display

When you create a Gadgeteer project, you have nothing fancy… just a plain old project file without the mess we’re accustomed to.

Project

The interesting part is the Program.gadgeteer that help you to plug your modules in the right slot.

UnPlugged

Here you can see that my OBD II module can only plug in slot 4,8,9,11.
In fact on each slot you can see a letter.

image

And on each module the same letters.

image

This means that obd II can plug on any slot which holds the letter U or K… which include slot 11.
Then you can plug the display the same way.

Plugged

There is one plug for R, one for G and one for B colors, the last one is T, for Touch.
But we don’t use the Touch feature of the screen for this project so you don’t have to plug it.

In the code behind, you can see that the generated code reflects exactly how we plugged things in the designer.

 

private void InitializeModules() {
    this.obd_II = new GTM.GHIElectronics.OBD_II(11);
    this.display_T35 = new GTM.GHIElectronics.Display_T35(14, 13, 12, Socket.Unused);
}

 

The OBD_II class comes with information about your car.

image

Plugging it to your LCD display is about coding in WPF ! Really, not kidding.

 

void ProgramStarted()
{
    obd_II.Connect(Elm327.Core.ElmDriver.ElmObdProtocolType.Automatic, Elm327.Core.ElmDriver.ElmMeasuringUnitType.Metric);
    var panel = new Panel();
    display_T35.WPFWindow.Child = panel;
    display_T35.WPFWindow.Background = new SolidColorBrush(Colors.Black);
    var txtBlock = new Text();
    txtBlock.ForeColor = Color.White;
    txtBlock.Font = Resources.GetFont(Resources.FontResources.NinaB);
    txtBlock.HorizontalAlignment = HorizontalAlignment.Center;
    txtBlock.VerticalAlignment = VerticalAlignment.Center;
    panel.Children.Add(txtBlock);
    txtBlock.TextContent = "80.4 L/100Km";
    do
    {
        double speed = obd_II.GetVehicleSpeed();
        if(speed < 5)
        {
            txtBlock.TextContent = "Too slow to know";
            continue;
        }
        else
        {
            double distPerGallon = obd_II.elm.ObdMode01.EstimatedDistancePerGallon;
            double literPer100km = 378 / distPerGallon;
            txtBlock.TextContent = literPer100km.ToString() + " L/100km";
        }
    } while(true);
}

 

Some people made tools for coding your display in XAML.
Anyway, we don’t need Xaml for this project, here is what we get :

image

This is all there is to know… now you just have to plug the OBD II module to your car, and drive.

Robin also made a real dash meter, unfortunately his code is censured by the CodeProject chart as “Harmful to the humanity”… you know the kind of boilerplate code an IT guy can make… he drew the whole interface  by using display_T35.SimpleGraphics.SetPixel(color,x,y); instead of WPF. 

Believe me, you don’t want to know how it looks like.

BadCode

Nevertheless I secretly attached his source to this article, don’t tell to CodeProject admins I polluted their servers ! But the result looked great.

image

The cost is :

Total : 275$

From LCD display to 7-Segment Leds

image

Things worked well, but the problem is that the LCD display is too big to be plugged into the dashboard, and that the meter cost is high.

Here, we will replace the Display module to use 7-segments leds instead, by doing that we can use a Fez Cerberus -less slots- instead of Fez Spider, so the cost will be :

Total : 140$ (or almost 2 times less than with the display)

Robin’s code will be a little more complicated, and we will need to plug the leds to the MaxO module manually.

So first how does one 7-Segment works ?

image

As a developer, the only thing you need to know is that we have 7 segments + 1 digital point to switch on or switch off.

There is one pin per led and 2 pins to connect to the ground.

How do we connect 3 of these 7-segments leds to the gadgeteer ? We use a MaxO module.

The MaxO module is nothing more than an adapter which convert a gadgeteer slot S into 32 switches.

image

MaxO module can output 32 switches, this mean that you can completely describe its state with 4 bytes. (4 bytes = 32 binary digit)

image

You can chain MaxO modules to reach 128 switches on one Socket S.
In our case, we need only one MaxO because each 7-Segment led requires 8 switches, that is 24 switches (pins) for the 3 7-Segments.

imageimage

Once understood, the code is straightforward, the conditional blocks put the decimal separator at the right place depending on the consumption level. (eg : “02.5” for less than 10 L/100km, “12.5” for more than 10 and “123” for more than 100)

 

void ProgramStarted()
{
    Debug.Print("Program Started");
    maxO.NumBoards = 1;
    maxO.EnableOutputs();
    byte[] nodata = { 255, Digitcode((char)'-'), Digitcode((char)'-'), Digitcode((char)'-') };
    maxO.WriteArray(nodata);
    obd_II.Connect(Elm327.Core.ElmDriver.ElmObdProtocolType.Automatic, Elm327.Core.ElmDriver.ElmMeasuringUnitType.Metric);
    do
    {
        double speed = obd_II.GetVehicleSpeed();
        if(speed > 5)
        {
            byte[] switches = { 255, 255, 255, 255 };
            double distPerGallon = obd_II.elm.ObdMode01.EstimatedDistancePerGallon;
            double literPer100km = 378 / distPerGallon;
            char[] digits = literPer100km.ToString().ToCharArray();
            if(literPer100km >= 100)
            {
                //Over 100, no digital point
                switches[1] = Digitcode(digits[0]);
                switches[2] = Digitcode(digits[1]);
                switches[3] = Digitcode(digits[2]);
            }
            else if(literPer100km >= 10)
            {
                //From 10 to 100, add a digital point eg : "80.4"
                switches[1] = Digitcode(digits[0]);
                switches[2] = PointCode(Digitcode(digits[1]));
                switches[3] = Digitcode(digits[3]);
            }
            else
            {
                //Under 10, dot after the second digit eg : "02.4"
                switches[1] = Digitcode((char)'0');
                switches[2] = PointCode(Digitcode(digits[0]));
                switches[3] = Digitcode(digits[2]);
            }
            maxO.WriteArray(switches);
        }
        else
        {
            maxO.WriteArray(nodata);
        }
    } while(true);
}

 

And here is the mapping for converting a digit to the correct byte value of its 7-Segment led.

 

byte PointCode(byte code)
{
    return (byte)(code - 128);
}
byte Digitcode(char digit)
{
    switch(digit)
    {
        case (char)'0':
            return 132;
        case (char)'1':
            return 159;
        case (char)'2':
            return 194;
        case (char)'3':
            return 138;
        case (char)'4':
            return 153;
        case (char)'5':
            return 168;
        case (char)'6':
            return 160;
        case (char)'7':
            return 158;
        case (char)'8':
            return 128;
        case (char)'9':
            return 136;
    }
    //Else, show "-" 
    return 251;
}

 

That’s all there is to say about this code.

Robin took advantage of the 8 wires there is inside a cheap phone cable to connect a 7-Segment to the MaxO module.

image

Conclusion

Thanks to Robin Martin for sending me his project, and giving a second life to my fez spider.
Thanks to Microsoft, Secret Labs, and GHI Electronics for giving me power and to
SparkFun, MakerShed and Adafruit excellent distributors of arduino/netduino/gadgeteer/electronic components.

I hope you got a glimpse of the power .NET MF give you, as a modest developer.
If you always asked if a gadgeteer or netduino were worth your money and time, I hope I convinced you. YES it is worth your time, the community is great, the tool are great, modules are plentiful, vendors and makers align well together. .NET MF is a success.

The pricing range depends on your need (30$ for cerberus, 120$ for Fez Spider), and, as you have seen, gadgeteer allows you to plug to normal electronic devices if you really need to.

.NET MF is also moving to a smart watch soon, can’t wait for that. Sourire

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

Nicolas Dorier
Software Developer Freelance
France France
I am a trainer and a curious developer.
 
CEO of AO-IS, we created a tool to make IaaS on Azure more easy IaaS Management Studio.
 
If you are interested for working with me, for fun coding stuff, for freelance stuff, or interested in using our cloud training infrastructure freely for a kickass presentation for the dev community ? this way Smile | :)

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHumayun Kabir Mamun3-Nov-14 22:39 
QuestionVery good PinmemberRugbyLeague3-Oct-14 5:27 
QuestionExcellent article PinmemberAdil Ali Asghar2-May-14 21:28 
AnswerRe: Excellent article PinprofessionalNicolas Dorier3-May-14 6:54 
QuestionExcellent PinmemberWhiteKnight16-Oct-13 9:30 
GeneralMy vote of 5 PinmemberShakeel Iqbal8-Oct-13 20:42 
Questionhere is my 5 PinmemberThatsAlok7-Oct-13 20:25 
GeneralMy vote of 5 PinprofessionalK K Kodoth4-Oct-13 20:23 
GeneralMy vote of 5 Pinmemberpwasser4-Oct-13 15:04 
QuestionNice PinmvpSacha Barber30-Sep-13 23:21 
AnswerInteresting PinprofessionalKillBot Project28-Sep-13 17:21 
GeneralRe: Interesting PinmemberNicolas Dorier28-Sep-13 17:30 
GeneralMy vote of 5 PinmemberGiles28-Sep-13 1:03 
GeneralMy vote of 5 PinmemberMladen Borojevic25-Sep-13 8:07 
GeneralMy vote of 5 Pinmembervalery possoz25-Sep-13 6:18 
GeneralRe: My vote of 5 PinmemberNicolas Dorier25-Sep-13 6:24 
GeneralRe: My vote of 5 Pinmembervalery possoz25-Sep-13 7:00 
GeneralMy vote of 5 Pinmemberbestdealex25-Sep-13 5:32 
GeneralRe: My vote of 5 PinmemberNicolas Dorier25-Sep-13 5:48 
GeneralMy vote of 5 PinadminChris Maunder25-Sep-13 4:51 
GeneralRe: My vote of 5 PinmemberNicolas Dorier25-Sep-13 5:46 
GeneralMy vote of 5 PinmvpMika Wendelius25-Sep-13 4:03 
GeneralMy vote of 5 Pinmemberfredatcodeproject25-Sep-13 3:14 
GeneralMy vote of 5 PinprofessionalPaulo Zemek22-Sep-13 11:40 
GeneralRe: My vote of 5 PinmemberNicolas Dorier22-Sep-13 12:09 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141216.1 | Last Updated 28 Sep 2013
Article Copyright 2013 by Nicolas Dorier
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid