Bicycle Computer #7 – Working with the Emulator when you have new Peripherals

This is the seventh in a series of articles demonstrating how someone with modest .NET programming capabilities can now write applications for embedded devices using the .NET Micro Framework and Visual Studio.  To jump to the initial article, click here. The project source code is posted on Codeplex.com and can be downloaded from https://netmfbikecomputer.codeplex.com/.  Remember, you can help determine what we cover in the series with your questions and suggestions. 

We started the earlier articles with several pictures of the application running in the emulator – that’s where I first deployed and ran the application.  It gave me the ability to start writing the application while still defining the requirements and selecting the hardware.  I shifted to the hardware only when I started connecting physical devices to the application

If you are following along, you may have noticed that I have created a problem for myself by adding the sensor logic.  When the application running in the emulator goes out to read the SPI port, I get an exception because that port is not defined in the sample emulator. Even if I work around that,  the application now expects interrupts coming from the sensors that drive the UI but clearly, that is not happening in the sample emulator supplied with the SDK – all the values will stay /n/a’.  The emulator doesn’t know anything about magnetic switches or inclinometers.  So, I can either decide not to use the emulator anymore or I can take one of several strategies to keep it functional.  The emulator is pretty handy for several reasons.  To get input on the UI, I don’t have to ship the hardware around  -  I can email the project instead.  Also, it is faster to deploy to the emulator so I can try things out at a faster rate when I am working on the UI.  And you already know that I am no UI designer so I will be iterating a lot on that.  

Jens Kühner devotes two full chapters (nearly 100 pages) of his book “Expert .NET Micro Framework” to the emulator so this article will only scratch the surface but it will give you some idea of how you might approach the emulator. 

Option #1 – a custom emulator.   The emulator can be fully replaced by an emulator of your design that supports any peripheral and visual experience that you want.  This option seems most likely to be useful for someone building a device that others will build applications for. That way, you can ship the emulator to your customers for them to try out the hardware and build their applications in it as I started with the bicycle computer.  This is an elegant solution but it is a lot of work and more than I need for my own purposes.  There is a full description of how to do this here

Option #2 – extend the emulator.   This is relatively easy to do.  Here you work with the components that are in the sample emulator and delete, replace, or add as needed.  There is a good example of this in the samples – the temperature emulator sample (brought to us by our long term NETMF friend – Tony Pitman).  In this emulator extension, he adds the SPI port that is causing my exception.  This is the way to go when you don’t need a really customized user experience but it is important to really support your real-world emulation or to test your driver logic.  For example, if you read something from the serial port on your device, you can hook that up with a serial port on your development machine and get end-to-end testing.

Option #3 – virtualizing the world.   I want to continue to do my UI development but it is not essential that the real world be represented in the application while I do that.  Instead, I can simply mimic (in a reasonable manner) the data coming in and do my serious testing of the drivers and real world input on the device itself.  I can do this because it is possible to know whether I am running on the emulator. 

Virtualizing the world

There are three external devices that I need to connect with – the inclinometer (SPI) for incline and temperature and the two magnetic switches for tire and pedal rotation.  In addition, the plan is to use the inclinometer to trigger the UI updates.  That will let me leave the processor without even a timer running hopefully.  The plan is to test for what environment I am running in (device or emulator) and either hook to the real work or send out a set of dummy values from the sensor classes.  First I create am interface that contains all the public methods for my sensor – in this case the inclinometer:

public interface IInclineSensor
{
    void ZeroInclinometer();
    double GetIncline();
    double GetTemperature();
}

Then I create a fake sensor class that contains the dummy implementations for the sensor: (I get both incline and temperature from the same sensor so I just use the same index to iterate through both)

public class FakeInclineSensor: IPausable, IInclineSensor
{
    static int i = 0;
    public void ZeroInclinometer()
    {
        // do nothing here
    }
    public double GetIncline()
    {
        double[] returnValues = new double[] {12.3,13.2,10.5,9.8,4.2,2.1,1.3,-1.9,-2.7 };
        if (i++ > 8) i = 0;
        return returnValues[i];
    }
    public double GetTemperature()
    {
        double[] returnValues = new double[] {22.3,25.2,18.5,19.8,24.2,22.1,21.3,-1.3,-2.7 };
        return returnValues[i];
    }
    #region IPausable
    [MethodImpl(MethodImplOptions.Synchronized)]
    void IPausable.Pause()
    {
       // don’t need to do anything
    }
    [MethodImpl(MethodImplOptions.Synchronized)]
    void IPausable.Resume()
    {
        //don’t need to do anything
    }
    #endregion
}

Note that since the sensors use two interfaces, I need to implement them both.  Then when I create my instance of an incline sensor I have to first declare it as IInclineSensor instead of InclineSensor:

public IInclineSensor _inclineSensor;

and when I call the constructor, I call the right one based on whether I am running on the emulator or the device:

if (Microsoft.SPOT.Hardware.SystemInfo.SystemID.SKU == 3)   //we are running on the emulator
{
    _inclineSensor = new FakeInclineSensor();
}

else
{
    _inclineSensor = new InclineSensor(this);
}

That is only the one sensor but fortunately, the other two sensors are implemented with a single class so I can get through that easily.

Configuring the emulator

I don't want to leave the emulator without talking about how much you an do just by changing the configuration settings in the emulator.  This file is out in the tools directory – look for the Microsoft.SPOT.Emulator.Sample.SampleEmulator.exe.emulatorconfig file.  This is all XML so it is easily changed and the changes are all absorbed by the configuration parser.  Let’s look at some of what you can do here.  My RideView layout is visually very busy and I am thinking that the whole thing may look better on a slightly larger display.  I am waiting for a 4.3 inch display to try this out on but I don’t have to wait.  I can try it in the emulator by changing two lines.

<LcdDisplay id="mydisplay">
  <Width>480</Width>
  <Height>272</Height>
  <BitsPerPixel>16</BitsPerPixel>
</LcdDisplay>

Done!  Start the emulator and you are working on the equivalent of the 4.3 inch display.  If I like it there, I can move forward with the larger task of integrating a new display.  If I don’t like it, I’ve saved myself a good bit of effort and expense.

Other things that you can change – the amount of memory on the device:

<RamManager>
  <Size>8388608</Size>
</RamManager>

the processor speed:

<TimingServices>
   <SystemClockFrequency>32000000</SystemClockFrequency>
</TimingServices>

or a really useful one, the battery charge management.  One day, our bicycle computer will leave my desk and be running on batteries.  Users will expect battery charge status battery state warnings.  Icould spend sleepless nights waiting for the battery to discharge sufficiently to see if they come up or Ican simulate your battery in the emulator and manage its state in the configuration. 

   <Battery>
      <Voltage>5123</Voltage>         <! -- 5.123 V--->
      <Temperature>234<Temperature>    <! -- 23.4 C--->
      <StateOfCharge>35<StateOfCharge>    <! -- 35%--->
    ....
   </Battery>

Take a leisurely stroll through Microsoft.SPOT.Emulator.Sample.SampleEmulator.exe.emulatorconfig and see for yourself what you can do. 

And again – check out Jen’s excellent description “Expert .NET Micro Framework”.