Archive for May, 2016

Windows 10 IoT Core – Setting Default App

The default startup app supplied with Windows 10 IoT core provides interesting information about your device and basic settings, but does not do anything and does not even provide a launcher for your app.

What we want is for our application to start when we power on the device. This will allow us to specialize the device, and its purpose essentially becomes to run our application and nothing else.

This procedure only deploys debug version applications. Its good for temporary setup AND to demonstrate Setting Default Application. Because the debug certificate is temporary, the application will eventually stop working. I will write a post about deploying release application at some point.

Updating the Manifest

This step is optional, but it makes things easier.

The first step is to identify our application. By default when we create the Universal Windows application, the identity of your application is set as a guid. The identity for our application was:

  • 234b35b2-e6d4-471c-8473-5d584ad0ee1a

To make it much easier to find our application in a list, I want to change it to:

  • ChristianLavigne-LogicGate

To change the identity you need to change the manifest. Here is how:

  1. Right Click on your Project (Windows Universal)
  2. Select ‘Properties’ you will get the following screen. Click on the ‘Package Manifest’ button, you will get the manifest page:
    Default-ProjectProperties
  3. Select the ‘Packaging’ tab:Default-PackageManifest
  4. Take note of the Package Name (to uninstall from the device later)Default-PackagePackaging
  5. Replace the Package Name, I used ‘ChristianLavigne-LogicGate’:
    Default-PackagePackaging_updated
    Note: The ‘Package family name’ contains the name as displayed on the device 
  6. Click the Visual Studio ‘Save’ button to save the manifest.

Deploying the Application

To do this, I will use Visual Studio to deploy a debug version of the application. Building release packages is a bit more complicated and will be the subject of another blog entry.

After updating the manifest, re-build the application (in debug) and start a debugging session by clicking run with remote machine selected. Same as we have done before.

When starting the debug process, Visual Studio will deploy a new version of our application on the device. Once started, you can stop the application from Visual Studio by using the menu Debug | Stop Debugging.

Setting the Device Default App

To update the default app, we start Windows Device Portal web page of our device.

  1. Navigate to the ‘Apps’ page.Default-SelectApp1
  2. In the Installed apps drop down lisbeforet, select your app, ChristianLavigne-LogicGate_1.0.0.0_arm_xxx in our case, and click the Set Default.Default-SelectApp2

What this does is interesting. With the Raspberry Pi on, we can see that our app immediately starts. If it shuts down for any reason, our app will re-start. When you reboot your Raspberry Pi, it will start our app again.

In essence it will only run this application, until we set a new default. If we want to go back to the original application supplied with the OS, select IoTCoreDefaultApp and set it as the default.

Removing Old Application

Because we renamed the application in the manifest, we now have a duplicate of the application installed. To remove the old version, we select it in the Installed apps and click the Remove button. I also had another application I created earlier, so I removed it.

Default-RemoveApp

Conclusion

Setting the Default App allows you to specialize your device to perform only a single task. You can use you Raspberry Pi to run hardware specific applications, or to run as a media player, or run kiosk software. Any Universal Windows application will work, so capability offers a wide range of possibilities.

 

 

, , ,

Leave a comment

GPIO Test Application Part 6 – Result

Previous: GPIO Test Application Part 5 – View

This post is part 6 of 6 of the GPIO Test Application. You can find the initial post here: GPIO Test Application part 1 – Overview.

In this post I will wrap up the project, make the source code available, and provide a final impression

Project Source Code

You can find the entire source code for this project right here:

You can run the application on your computer, but it will run in simulation mode (no GPOI). See the First Windows 10 IoT Core Windows Application post for information on how to run it on your Raspberry Pi.

The source code for the project has the same requirements as stated in my post: Setting up Visual Studio 2015 for Windows 10 IoT Core development

Gotchas

One of the gotchas that this project highlighted for  me is that the ValueUpdated event on the GpioPin is not the most reliable thing. On odd occasions and for not apparent reason, sometimes the event doesn’t get triggered at all??? Its good for most, non-critical applications, but it’s by no means reliable.

It also gave me a chance to play around with the DebounceTimeout value. What this does is that is inhibits the ValueUpdated event. Meaning, it might miss some of the state change. That will be usefull on slower more controlled system to prevent noise, but on near-real time system like a user controlled push button, not supplying a value was the best option.

Conclusion

I wanted to make this project work with event. Events in .NET are very useful because you don’t have to hang around trying to look for changes in values, you just register for an event and get notified when the value changes. I’m a bit disappointed that the event on the GPIO pins is not more reliable, or maybe my electronic is missing something???

Still, this was a fun project that, I find, turned out pretty good. I learned a number of things and I got to play with a neat new little device: Raspberry Pi.

Hopefully, next time around we’ll crank it up a notch and take this to the next level!!!

Leave a comment

GPIO Test Application Part 5 – View

Previous: GPIO Test Application Part 4 – ViewModel

This post is part 5 of 6 of the GPIO Test Application. You can find the initial post here: GPIO Test Application part 1 – Overview.

The View presents the information on screen. It allows the user to interact with the system and offers an up to date view of what is happening on the GPIO. It is written in XAML and binds directly to the Model and ViewModel.

A lot of the screen code is about creating the layout of how the different controls are organized on screen. We will ignore the layout as much as possible to focus on the functionality.

View Model

As seen before, the view model is declared as a page resource and is instantiated as the DataContext of the top level layout container for the page:

<Page.Resources>
        
    <vm:MainPageVM x:Key="PageViewModel" />

<!-- ... -->
        
</Page.Resources>
<Grid DataContext="{StaticResource PageViewModel}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

Logic Operation Selection

The list used for the selection of the Logic Operation by the user is quite simple. It looks like this:

LogicSelector

There is the code used to generate that view. Notice that I had to supply different templates to control the way the items are displayed.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="100"/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Margin="5" Text="Logic Operation" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold"/>
    <ListBox Grid.Row="1" ItemsSource="{Binding LogicList}" SelectedItem="{Binding Logic, Mode=TwoWay}" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.ColumnSpan="4" ItemTemplate="{StaticResource LogicItemTemplate}" ItemsPanel="{StaticResource LogicLayoutTemplate}" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="Black" />
</Grid>

The connection between the View and the ViewModel for the Logic Selection consist only in 2 bindings:

  • ItemsSource to MainPageVM.LogicList
  • SelectedItem to the MainPageVM.Logic

Device Visual Interface

The visual interface for the device inputs and outputs looks like this:

DeviceInterface

It is composed of:

  • Two ellipses, red and green, that represents the red LED (not shown), and the green LED.
  • Two blue rectangles that represents the switches.

Notice the databinding on the Visibility points directly to the Model properties. A converter is used to convert the Boolean value to a UIElement.Visibility.

Here is the code used to generate the Device Interface portion of the screen:

<Grid Margin="5">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="100"/>
        <RowDefinition Height="40"/>
        <RowDefinition Height="40"/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0"  Grid.Column="1" Grid.ColumnSpan="4" Margin="5" Text="Device Interface" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold"/>

    <!--Following are the objects representing the different hardware components-->
    <!--Notice the Visibility property binds directly to the Model properties-->
    <Rectangle Grid.Row="1" Grid.Column="1" Margin="15" Fill="Blue" Visibility="{Binding Model.LeftSwitch, Converter={StaticResource VisibilityValueConverter}}" />
    <Ellipse Grid.Row="1" Grid.Column="2" Margin="15" Fill="Red" Visibility="{Binding Model.RedLED, Converter={StaticResource VisibilityValueConverter}}" />
    <Ellipse Grid.Row="1" Grid.Column="3" Margin="15" Fill="Lime" Visibility="{Binding Model.GreenLED, Converter={StaticResource VisibilityValueConverter}}" />
    <Rectangle Grid.Row="1" Grid.Column="4" Margin="15" Fill="Blue" Visibility="{Binding Model.RightSwitch, Converter={StaticResource VisibilityValueConverter}}" />

    <!--Labels associated with the hardware components-->
    <TextBlock Grid.Row="2" Grid.Column="1" Text="Left Switch" HorizontalAlignment="Center" VerticalAlignment="Center" />
    <TextBlock Grid.Row="2" Grid.Column="2" Text="Red LED" HorizontalAlignment="Center" VerticalAlignment="Center" />
    <TextBlock Grid.Row="2" Grid.Column="3" Text="Green LED" HorizontalAlignment="Center" VerticalAlignment="Center" />
    <TextBlock Grid.Row="2" Grid.Column="4" Text="Right Switch" HorizontalAlignment="Center" VerticalAlignment="Center" />

    <!--Hardware simulation switches. Only visible when GPIO is not available IE when not running on the Raspberry Pi-->
    <ToggleButton Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="Sim Left Switch" Visibility="{Binding ShowSimulatedSwitches, Converter={StaticResource VisibilityValueConverter}}" IsChecked="{Binding Model.LeftSwitch, Mode=TwoWay}" HorizontalAlignment="Center" Margin="5" />
    <ToggleButton Grid.Row="3" Grid.Column="4" Grid.ColumnSpan="2" Content="Sim Right Switch" Visibility="{Binding ShowSimulatedSwitches, Converter={StaticResource VisibilityValueConverter}}" IsChecked="{Binding Model.RightSwitch, Mode=TwoWay}" HorizontalAlignment="Center" Margin="5" />
    
</Grid>

Other

The application offers more information on screen that are utilitarian in nature. There are some instructions for the user, a description of the status of the GPIO and there is an event log portion the shows all the events that occur inside the application.

Conclusion

Through the MVVM pattern and with minimal effort, the user interface portion of your device can display your device status almost in real time.

I kept the UI on the application very simple. But you can also use the full power of WPF and XAML to make your application UI really stand out and build very aesthetically pleasing user interfaces.

Next: GPIO Test Application Part 6 – Result

Leave a comment

GPIO Test Application Part 4 – ViewModel

Previous: GPIO Test Application Part 3 – Model

This post is part 4 of 6 of the GPIO Test Application. You can find the initial post here: GPIO Test Application part 1 – Overview.

The ViewModel (VM) encapsulate all the functionality provided by the application.Each page, user control or dialog should have it’s own VM to implement the page, user control or dialog functionality.

For our Main Page, we have a MainPageVM which is the view model for this page.

MainPageVM vs Model

The MainPageVM creates and maintains the current instance of the LogicGateModel and makes it available to the UI. MainPageVM also performs operations on the Model.

Here, we see the intialization code that creates the Model:

private void Initialize()
{
    Logger.AddLogEntry("Initializing Main Window VM!");

    InitializeCommands();

    m_Model = new LogicGateModel();
    m_Model.PropertyChanged += Model_PropertyChanged;
    RecalculateOutput();

    Logger.AddLogEntry("Done Initializing Main Window VM!");
}

...

private LogicGateModel m_Model = null;
/// <summary>
/// This is the instance of the Model.
/// </summary>
public LogicGateModel Model
{
    get
    {
        return m_Model;
    }
}

When the model is created, the MainPageVM attaches an event handler to the PropertyChanged event of the LogicGateModel.

The handler is used to detect and act uppon changes in the values of LeftSwitch and RightSwitch. When those properties are changed, the MainPageVM recalculates the required outputs and updates the Model accordingly.  It also recalculates on changes to the IsEnabled function.

Bellow is the Model_PropertyChanged event handler code:

private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "LeftSwitch" || e.PropertyName == "RightSwitch")
    {
        RecalculateOutput();
    }
    else if(e.PropertyName== "IsEnabled")
    {
        if(Model.IsEnabled)
        {
            OnPropertyChanged("ShowSimulatedSwitches");
            RecalculateOutput();
        }
    }
}

MainPageVM functionality

Calculations

The calculation portion of the MainPageVM is pretty simple. A case statement performs the actual logic operation on the RightSwitch and LeftSwitch of the Model, then the result is pushed back to the RedLED (false) and GreenLED (true) properties of the model.

private void RecalculateOutput()
{
    Logger.AddLogEntry("Recalculating output!");

    bool result = false;
    switch(Logic)
    {
        case LogicTypeEnum.AND:
            result = Model.LeftSwitch && Model.RightSwitch;
            break;
        case LogicTypeEnum.OR:
            result = Model.LeftSwitch || Model.RightSwitch;
            break;
        case LogicTypeEnum.NAND:
            result = !(Model.LeftSwitch && Model.RightSwitch);
            break;
        case LogicTypeEnum.NOR:
            result = !(Model.LeftSwitch || Model.RightSwitch);
            break;
        case LogicTypeEnum.XOR:
            result = Model.LeftSwitch ^ Model.RightSwitch;
            break;
    }

    Model.GreenLED = result;
    Model.RedLED = !result;

}

Note: We could have used a more powerful pattern, such as the Strategy pattern, to select and perform the logic operation. But in the spirit of keeping the code readable a case statement is better.

Logic Property

The formula used to calculate the output is dependent on user input. The user selects the logic operation to perform then the application uses it to calculate the output. The Logic property of the MainPageVM is used to define the operation currently used. The MainPageVM also provides a list of available operations so that the View is able to display a list to the user. Following is the code related to the Logic property.

LogicTypeEnum represents the available operations.

public enum LogicTypeEnum
{
    AND,
    OR,
    NAND,
    NOR,
    XOR
}

Logic and LogicList properties provide the functionality to the View. Notice the call to RecalculateOutput on the Logic setter.

private LogicTypeEnum m_Logic = LogicTypeEnum.AND;
/// <summary>
/// This is the logic applied to the inputs to define how calculation is done.
/// </summary>
public LogicTypeEnum Logic
{
    get
    {
        return m_Logic;
    }
    set
    {
        if(value != m_Logic)
        {
            m_Logic = value;
            OnPropertyChanged();
            RecalculateOutput();
        }
    }
}

private List<LogicTypeEnum> m_LogicList = null;
/// <summary>
/// This is the list to populate the list or ddl used to select
/// the logic to apply on the inputs. 
/// </summary>
public List<LogicTypeEnum> LogicList
{
    get
    {
        if(m_LogicList == null)
        {
            m_LogicList = new List<LogicTypeEnum>();
            Array a = Enum.GetValues(typeof(LogicTypeEnum));
            foreach(var v in a)
            {
                m_LogicList.Add((LogicTypeEnum)v);
            }
        }
        return m_LogicList;
    }
}

Other Functionality

Other functionality have also been added to the MainFormVM. For debugging purpose the UI can display buttons on the Main Page simulating the right and left switches. Those buttons are only available if the GPIO fails to initialize which in turn enables the ShowSimulatedSwitches property on the VM.

There is also an Exit command that will close the application. This is useful to stop debugging sessions from the Main Page.

Conclusion

The MainPageVM performs all the function related to the calculation and maintains the information related to the calculation. This allows the Model to focus on content and not worry about functionality.

Next: GPIO Test Application Part 5 – View

, , , , ,

Leave a comment

GPIO Test Application Part 3 – Model

Previous: GPIO Test Application Part 2 – Hardware

This post is part 3 of 6 of the GPIO Test Application. You can find the initial post here: GPIO Test Application part 1 – Overview.

The model of our application will provide the data used by the application. The data in this case represents the information that is sent and received on the GPOI.

Model Application Interface

The Model exposes a simple and easy to use interface to the application. This interface hides all the complexity of working with the GPIO. The properties for the interface look like regular content properties of an INotifyPropertyChange object.

The following properties compose this interface:

  • RightSwitch: bool value that returns true when the right switch is pressed.
  • LeftSwitch: bool value that returns true when the left switch is pressed.
  • RedLED: bool value that represents if the red LED is on / off. Setting this value will turn the green LED on.
  • GreenLED: bool value that represents if the green LED is on / off. Setting this value will turn the green LED on.
  • IsEnabled: read only bool value that specify if the GPIOs have been successfully initialized and are available. This property is used to enter simulation mode. In simulation mode, the application adds buttons on the screen to simulate the left and right push buttons on the screen. This is useful for debugging the application on your computer.

The switch properties looks like this:

private bool m_RightSwitch = true;

/// <summary>
/// Provides access to the value of the Right push switch on the hardware
/// </summary>
public bool RightSwitch
{
    get
    {
        return m_RightSwitch;
    }
    set
    {
        if (value != m_RightSwitch)
        {
            m_RightSwitch = value;
            OnPropertyChanged();
        }
    }
}

The LED properties looks like this:

private bool m_RedLED = false;

/// <summary>
/// Reads and Sets the value of the red LED
/// </summary>
public bool RedLED
{
    get
    {
        return m_RedLED;
    }
    set
    {
        if (value != m_RedLED)
        {
            m_RedLED = value;
            UpdateGPIO(m_RedLEDPin, value);
            OnPropertyChanged();
        }
    }
}

Notice that in the setter of the LED properties, a call is made to UpdateGPIO to send the value to the GPIO.

GPIO processing

In the case of our application, the Model is encapsulating all the GPIO access. The flow of GPIO runs something like this:

  1. Initialize the GPIO
  2. While the application is running:
    1. Wait for events on the Input pins
    2. Write Outputs to the Output pins
  3. Shut down the GPIO

We keep the instance of the GpioPin for each pin that we use. The GpioPin are created in the initialization process and released in the dispose. For simplicity, we keep the pin numbers in constants fields.

private const int GPIO_LEFT_SWITCH = 21;
private const int GPIO_RIGHT_SWITCH = 20;
private const int GPIO_RED_LED = 6;
private const int GPIO_GREEN_LED = 5;

private GpioController m_Controller = null;
private GpioPin m_LeftSwitchPin = null;
private GpioPin m_RightSwitchPin = null;
private GpioPin m_RedLEDPin = null;
private GpioPin m_GreenLEDPin = null;

Initializing / Shutting down the GPIO

During the initialization process the following sequence occurs:

  1. The application attempts to retrieve the default GpioController. If the controller cannot be retrieved, this means that the device does not support GPIO.
  2. All the pins are initialized.
  3. If all the pins are initialized correctly, the IsEnabled property is set to true.
  4. If one of the pins fails to initialize, the Release() function is called to free up all the allocated resources.
private void Initialize()
{
    Logger.AddLogEntry("Initializing GPIO on LogicGateModel");

    m_Controller = GpioController.GetDefault();
    if (m_Controller != null)
    {
        string startupMessage = "Startup:\r\n";
        bool success = true;

        success &= InitializeLEDPin(GPIO_GREEN_LED, "green LED", out m_GreenLEDPin, ref startupMessage);
        success &= InitializeLEDPin(GPIO_RED_LED, "red LED", out m_RedLEDPin, ref startupMessage);

        success &= InitializeSwitchPin(GPIO_LEFT_SWITCH, "left switch", out m_LeftSwitchPin, ref startupMessage);
        success &= InitializeSwitchPin(GPIO_RIGHT_SWITCH, "right switch", out m_RightSwitchPin, ref startupMessage);

        Message = startupMessage;
        if (!success)
        {
            Release();
        }
        else
        {
            // Read the current values...
            LeftSwitch = m_LeftSwitchPin.Read() == GpioPinValue.High;
            RightSwitch = m_RightSwitchPin.Read() == GpioPinValue.High;

            IsEnabled = true;
        }
    }
    else
    {
        Message = "Unable to access the GpioController!";
    }

    Logger.AddLogEntry("Initialization of GPIO on LogicGateModel complete!");
}

When the LED pins are created:

  1. We use the controller to try to open up the pin
  2. If that succeeds, we make sure the pins supports the Output Drive Mode.
  3. Then we set the Drive Mode to Output
  4. If any of the operations do not succeed, we set the result to false to indicate that there was an error initializing the GPIO
private bool InitializeLEDPin(int pin, string pinName, out GpioPin output, ref string message)
{
    bool result = true;

    Logger.AddLogEntry("Initializing Pin #{0}, {1}", pin, pinName);

    GpioOpenStatus status;
    if (m_Controller.TryOpenPin(pin, GpioSharingMode.Exclusive, out output, out status))
    {
        if (output.IsDriveModeSupported(GpioPinDriveMode.Output))
        {
            output.SetDriveMode(GpioPinDriveMode.Output);
            message += string.Format("   Pin {0} initialized: status = {1}\r\n", pinName, status.ToString());
        }
        else
        {
            message += string.Format("   Pin {0} error: Drive mode {1} not supported.\r\n", pinName, status.ToString());
            result = false;
        }
    }
    else
    {
        message += string.Format("   Can't initialize {0}: status = {1}\r\n", pinName, status.ToString());
        result = false;
    }

    return result;
}

When the switch pins are created:

  1. We use the controller to try to open up the pin
  2. If that succeeds, we make sure the pins supports the Output Drive Mode.
  3. Then we set the Drive Mode to Output
  4. Then we attach an event handler to the ValueChanged event of the GpioPinto  to receive notification whenever there is a change of state on the pin.
  5. If any of the operations do not succeed, we set the result to false to indicate that there was an error initializing the GPIO
private bool InitializeSwitchPin(int pin, string pinName, out GpioPin output, ref string message)
{
    bool result = true;

    Logger.AddLogEntry("Initializing Pin #{0}, {1}", pin, pinName);

    GpioOpenStatus status;
    if (m_Controller.TryOpenPin(pin, GpioSharingMode.Exclusive, out output, out status))
    {
        if (output.IsDriveModeSupported(GpioPinDriveMode.Input))
        {
            output.SetDriveMode(GpioPinDriveMode.Input);

            //Intentional, we do not use debounce this time but this is where you would set it
            //output.DebounceTimeout = TimeSpan.FromMilliseconds(5);

            output.ValueChanged += PinValueChanged;
            message += string.Format("   Pin {0} initialized: status = {1}\r\n", pinName, status.ToString());
        }
        else
        {
            message += string.Format("   Pin {0} error: Drive mode {1} not supported.\r\n", pinName, status.ToString());
            result = false;
        }
    }
    else
    {
        message += string.Format("   Can't initialize {0}: status = {1}\r\n", pinName, status.ToString());
        result = false;
    }

    return result;
}

The Release function is strait forward, it disconnects the event handler from the input pins and calls Dispose on each of the pins.

private void Release()
{
    Logger.AddLogEntry("Releasing GPIO on LogicGateModel");

    if (m_Controller != null)
    {
        // Release all the GPIO pins used
        if (m_LeftSwitchPin != null)
        {
            m_LeftSwitchPin.ValueChanged -= PinValueChanged;
            m_LeftSwitchPin.Dispose();
        }

        if (m_RightSwitchPin != null)
        {
            m_RightSwitchPin.ValueChanged -= PinValueChanged;
            m_RightSwitchPin.Dispose();
        }

        if (m_GreenLEDPin != null)
        {
            m_GreenLEDPin.Dispose();
        }

        if (m_RedLEDPin != null)
        {
            m_RedLEDPin.Dispose();
        }
    }
    Logger.AddLogEntry("Completed Releasing GPIO on LogicGateModel");
}

Handling OnChange event on the input PINs

When initializing the pins we assigned an event handler to the ValueChanged event of the input pins. The following code shows the OnValueChanged function:

private void PinValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
    // normally we would use the arg to get the value, as follow:
    //    (args.Edge == GpioPinEdge.FallingEdge);
    // but at this point it is completely unreliable and returns garbage
    bool value = sender.Read() == GpioPinValue.High;

    if (sender == m_LeftSwitchPin)
    {
        CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
        {
            LeftSwitch = value;
        });
    }
    else if (sender == m_RightSwitchPin)
    {
        CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
        {
            RightSwitch = value;
        });
    }
}

We first read the value of the pin by calling the Read() function. The GpioPin that raised the event is received as the sender parameter, so we use it to identify which button was pressed. Then we just set the value on the appropriate property.

One particularity of this code is that the ValueChange event is raised on a separate thread. In order to interact with the User Interface, we need to bring the call back on the UI thread. That is done here with the CoreApplication.MainView.Dispatcher.RunAsync call.

Turning LEDs On/Off

When the ViewModel sets the value of the RedLED or GreenLED, we need to send that value GPIO, the UpdateGPOI function does that for us:

private void UpdateGPIO(GpioPin pin, bool value)
{
    if (IsEnabled && pin != null)
    {
        GpioPinValue v = value ? GpioPinValue.Low : GpioPinValue.High;
        pin.Write(v);
    }
}

Conclusion

The Model already provides a big portion of the overall functionality we require. It reads inputs from the GPIO, maintains the current state of Input/Outputs and provides a way to turn LEDs on and off. All that using a simple interface that the rest of the application can use.

Next: GPIO Test Application Part 4 – ViewModel

, , , ,

Leave a comment

GPIO Test Application Part 2 – Hardware

This post is part 2 of 6 of the GPIO Test Application. You can find the initial post here: GPIO Test Application part 1 – Overview.

The hardware portion of this project is quite simple. It uses just enough components to be able to test the different aspects of the GPIO, input, output and events monitoring.

This project can be easily realized with the components supplied in the Microsoft IoT Pack for Raspberry Pi 2 starter pack.

Components

The following components are required:

  • 1 – Raspberry Pi 2
  • 1 – Breadboard
  • 2 – Push switch
  • 1 – Green LED
  • 1 – Red LED
  • 2 – 560Ω resistors
  • Wires

Diagram

Here is the wiring diagram I created:

LogicGate Hardware_bb

I used the application Fritzing to draw my electronic diagram. I found it to be very adequate to put together a quick wiring diagram. The nice part about it is that it already contains the Raspberry Pi 2 as a component and you can just drag the wires to/from the pin you want to use.

Next

Next step we’ll look at the Model portion of the application code. The model is used to control the GPIOs used to manipulate the electrical components supplied here.

Next: GPIO Test Application Part 3 – Model

, ,

Leave a comment

GPIO Test Application part 1 – Overview

This post is part 1 of 6 of the GPIO Test Application. The following parts together compose the full article:

As a first application that involves hardware, I decided to keep things simple. The idea is just to hook up a couple Inputs and Outputs and have a program that will work with the GPIO to read/write the values.

Source Code

To follow along, you might want to download the full solution right here:

You can run the application on your computer, but it will run in simulation mode (no GPOI). See the First Windows 10 IoT Core Windows Application post for information on how to run it on your Raspberry Pi.

The source code for the project has the same requirements as stated in my post: Setting up Visual Studio 2015 for Windows 10 IoT Core development

Requirements

The requirements that I chose for this application will allow us to explore the GPIO and programming model associated with creating User Interface on the Raspberry Pi 2 under the Windows 10 IoT Core operating system. The application should incorporate:

  • Hardware components accessed through the GPIO
  • A responsive UI that will display the status of the hardware components as it changes.
  • And some control by the user to set how the output are calculated.

For simplicity, this application assumes the Raspberry Pi is configured for user interactivity and that it is connected to a full size screen and has an input pointing device. I will explore different form factors as well as headless device development at another time.

Solution

To achieve these requirements I will create a programmable LogicGate application that will take input from 2 push buttons, will calculate a result based on a logic operation applied to the 2 inputs, and will light up a green LED for true and a red LED for false.

In addition, we will include UI to control the calculation by selecting which logic operation is used. We will also include UI to visually display the status of the Inputs and Outputs.

Whenever any of the inputs or logic operation parameter changes, the application should update the displayed status, recalculate the output and light up the appropriate LED.

Application Components Overview

The application will be based on the MVVM pattern that we have shown earlier. This pattern is well adapted to the creation of reactive WPF applications. It this case, the application is composed of 4 main components that are:

  • Hardware
  • Model
  • View Model
  • View

The components are organized as follow:

LogicGateOverview

Hardware

The hardware is composed of:

  • 2 switches (right / left)
  • 1 red LED
  • 1 green LED

More details about the electronic circuit will be available in the following post GPIO Test Application Part 2 – Hardware.

Model

On this application , we will used the model to encapsulate the access to the hardware through the GPIOs.

The model will provide a comprehensive Model API that allows seamless access to read the Inputs and write to the Outputs. The interface will contain the following Properties:

  • SwitchRight
  • SwitchLeft
  • RedLED
  • GreenLED

More details about the Model will be available in the post GPIO Test Application Part 3 – Model.

ViewModel

The ViewModel contains an instance of the Model and makes it available to the View. It also provides the functionality to calculate the Output based on the Logic Operation selected by the user on the View.

The available Logic Operations are:

  • AND
  • OR
  • NAND
  • NOR
  • XOR

More details about the ViewModel will be available in the post GPIO Test Application Part 4 – ViewModel.

View

The View provides the User Interface that the user to view the hardware status and to select the Logic Operation that determines the output. The user interface will look something like this:ViewScreenShot

Where:

  • Logic Operation: Section that allows the user to select which logic operation is used to calculate the output.
  • Device Interface: Displays the symboles that represents the different hardware components. The symbol is only displayed when the switch is pressed or the LED is lit. The symbols are:
    • Blue Square: for the switches
    • Red Circle: for the red LED
    • Green Circle: for the green LED

More details about the View will be available in the post GPIO Test Application Part 5 – View.

Results

In the last section, GPIO Test Application Part 6 – Result,  I will provide access to the full source code of this application and we’ll see the resulting application in action.

Next: GPIO Test Application Part 2 – Hardware

, , , , , ,

Leave a comment