Saturday, December 31, 2016

External Keypad For Windows controlled by .NET code


Overview

This keypad below is very cheap, so i bought 2 just to try them with Nusbio.net. Though it is a very simple device, it is not easy to explain how this work and moreover the theory behind the source code.
It is a little bit tricky and requires to understand sourcing and sinking current.
If you do not get it right away it is normal.
But you should be able to understand the basic idea just by reading the source code and my comments below.
With an Arduino you will find tutorial and library already made, but for .NET and Nusbio I had to write my own class (that is part of the open source samples that come with the Nusbio device).


First

There are plenty of tutorial on the internet about it, here is one I like the most to read first Arduino with Keypad Tutorial

Here is my take on it for software developers.

We have a grid of 4 rows and 3 colums. Each rows and columns connect to each other when one of the 12 buttons is pressed. We are going use 4+3 == 7 GPIO pins and monitor the connection between rows and the columns.

From a software point of view we have to constantly polled the state of the 12 buttons.

Initialization


The 4 GPIO pins connected to the 4 rows are open in input pull up mode, simply said this mean that the state of the pin is Readable (Input) and default state value is HIGH (AKA 1 or 5 Volts) and could be come a LOW (AKA 0 or 0 Volt) if there is a path to ground.
The 3 GPIO pins connected to the 3 columns are open in output mode, (the state can be set to HIGH or LOW programmatically) and set first to HIGH (1).
In this state nothing will happen, no current flow even if one button is pressed because current only flow from HIGH to LOW.

For one specific column if one button is pressed a connection is made between the column and the row and the state of the row will change from HIGH to LOW.

In a function called constantly we going one at time 
  1. Change the state of one the column GPIO pin to LOW (so now we know the column)
  2. Then we are going to read the state of the 4 GPIO pins rows one after the other,
    if the state is HIGH the button matching the current column and row is not pressed,
    but if the state is LOW, then this mean there is a connection because the button is pressed and the current flowing from HIGH to LOW changing the state of the row GPIO pins (which is readable, because it was open as input)

Source Code

Initialization

private List _gpioRow;
private List _gpioCol;
private Nusbio           _nusbio;
private List<List<char>> _keys;

private void Init()
{
    for (var r = 0; r < this._gpioRow.Count; r++)
    {
        this._nusbio.SetPinMode(this._gpioRow[r], PinMode.Input);
    }
    for (var c = 0; c < this._gpioCol.Count; c++)
    {
        this._nusbio.SetPinMode(this._gpioCol[c], PinMode.Output);
        _nusbio.GPIOS[this._gpioCol[c]].High();
    }
}

Check() function


public KeypadPressedInfo Check()
{
    KeypadPressedInfo rr = null;
    var found            = false;
    for (var c = 0; c < this._gpioCol.Count; c++)
    {
        _nusbio.GPIOS[this._gpioCol[c]].Low();
        for (var r = 0; r < this._gpioRow.Count; r++)
        {
            var pressed = _nusbio.GPIOS[this._gpioRow[r]].DigitalRead() == PinState.Low;
            if (pressed)
            {
                rr = new KeypadPressedInfo {
                    Row = r, Col = c, Key = this._keys[r][c]
                };
                break;
            }
        }
        _nusbio.GPIOS[this._gpioCol[c]].High();
        if (rr!=null)
            break;
    }
    return rr;
}

See on github the C# project. and the Keypad.cs class.

About the Wiring

One electricity rule that you may know is that if the + touch the - directly, you create a short circuit and it is not good. In between the + and - you must have a load, something that consume current. Therefore in between the 3 GPIO pins column and the 3 wires of the keypad I inserted 3 10 K Ohm resistor.