Netduino Plus 2 with MCP23017 #1 – Basic Wiring and Writing/Reading an IO Port

What is the MCP23017?

mcp23017 chip

The MCP23017 integrated circuit (DATA SHEET) is a digital I/O port expander (16 ports).  Why would you need more ports?  Think about an application for your Netduino where you may want to control a lot of discrete items (ie. LEDs, Christmas Lights, pyrotechnics, etc).  This is the output side of I/O.  The input side may be for collecting data from numerous motion sensors, replacing your home alarm system, etc.  The Netduino Plus 2 has 12 digital I/O ports on the board and when this isn’t enough, the MCP23017 will provide a inexpensive solution to getting more.  The other thing about the MCP23017 is that it is uses the I2C bus for communications.  I2C is an addressable serial bus that can communicate with multiple I2C enabled devices.  The Netduino Plus 2 has an SC (clock) pin and an SD (data) pin that make up the connections for the I2C bus.  Using this bus, you can read the values of the 16 input ports or write to them to set their hi/lo states.  When you do the math, you use two pins on your Netduino to gain 16 more digital I/O ports.  With the ability to address multiple MCP23017 integrated circuits on the I2C bus, you can potentially gain up to 8 X 16 ports for a grand total of  128 ports.

The MCP23017 also has two on board interrupt pins that can signal the Netduino directly.  This is important when you are trying to write more efficient code.  This is important when working with small devices as you have limited CPU and may need to conserve your batteries.  When enabled, the MCP23017’s interrupt ports will notify you when ever one of its digital I/O ports experiences a state change.  I will cover how to work with the MCP23017’s interrupt ports in a later post.

The MCP23017 In Detail

Below is the MCP23017 in a schematic view showing all of its pin outs.

mcp23017_pinouts
Figure 1 – MCP23017 Pin Out

Pins 1-8 GPB0-7 - This is bank B of 8 bi-directional I/O pins.  These are what you will connect your digital sensors or output devices to.

Pins 21-28 GPA0-7 – This is bank A of 8 bi-directional I/O pins.  These are what you will connect your digital sensors or output devices to.

Pin 9 VDD - Voltage.  Will run on 3.3V or 5V.

Pin 10 Vss GND – Ground.

Port 12 SCL – Serial Clock Input (I2C bus).

Port 13 SDA – Serial Data I/O (I2C bus).

Port 20 INTA – Interrupt A for bank A of I/O ports in input mode.

Port 21 INTB – Interrupt B for bank B of I/O ports in input mode.

Port 18 RESET – Hardware Reset.  Must be externally biased (voltage applied to keep the chip from resetting)

Port 15-17 A0-2 – Hardware Address pins.  Must be externally biased as well.  In this case, they are used to set the address of the chip.  The formula for this is 0 1 0 0 A2 A1 A0.  When all three are set to ground (0 1 0 0 0 0 0), the address is 0x20.

Wiring Up the MCP23017

At this point, we will wire up the MCP23017 to our Netduino plus.  To do this I assume you have a prototyping breadboard, some wires, a couple of 4.4k Ohm resistors and an LED.  Below is the how to wire the whole thing up with a single LED for testing purposes.  Below are the breadboard layout and the schematic of the same.  A picture is worth a thousand words, so I will let the diagram and schematic speak for themselves.

part1_breadboard
Figure 2 – MCP23017 Project Breadboard Layout

part1_schematic
Figure 3 – MCP23017 Project Schematic

On the MCP23017:

Pins A0, A1, A2 – We are wiring up the address pins to GND so the address on the IC will be 0x20 (see above to review).

Pins SCL & SDA – These pins are the I2C bus and are connected to the same pins on the Netduino.  Note that they are connected to the 3.3V pin with a 4.4 kOhm resistor.  This is a pull up resistor.  The I2C bus pins are a “open drain” lines.  This means that the bus drives the signals to GND, so they will need to be pulled up with a connection to some DC voltage.  These resistors are critical to the bus operating correctly.  For more information on pull-up or pull-down resistors see this article.

GPA7 – We have connected the LED to the last pin in the A bank.  The LED that I am using has the following characteristics: 3.0-3.4V Forward Voltage, at 20mA current.  Since I am powering the MCP23017 with 3.3V at 20mA, I will not need a resistor in line with the LED.  If you are using 5V or a lower voltage LED, you will need to use a resistor to protect both your LED and your Netduino.   Sparkfun has a good explanation of LEDs and resistors here.

Next, we will be moving onto the code and will see how you did with the wiring.

Getting Some Libraries to talk to the MCP23017

To work with the MCP23017, we are going to use the .Net Micro Framework Toolbox library which can be found here.  Download the latest installer and run it.  This will load all of the library’s DLLs to your computer.  When the installer is complete, you can go ahead and start up Visual Studio 2012 and start a new Micro Framework project for a Netduino Plus 2 Application.  We will now bring in some components we will use from the .Net Micro Framework Toolbox.  Start by adding references to the following DLLs:

  • Toolbox.NETMF.Core
  • Toolbox.NETMF.Hardware.Core
  • Toolbox.NETMF.Hardware.Mcp23017

On my computer, they were installed in the C:\Program Files (x86)\Netmftoolbox.com\.NET Micro Framework Toolbox\Assemblies\v4.2\ directory.  This should also be accompanied with a:

using Toolbox.NETMF.Hardware;

Now that this is done, we are set to start making the LED blink.

Turning on the LED

This first little program will alternate lighting the LED hanging off of the MCP23017 and the Netduino On Board LED.

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using Toolbox.NETMF.Hardware;

namespace NetduinoApplication4
{
    public class Program
    {
        static OutputPort led;
        static Mcp23017 mux;

        public static void Main()
        {
            bool bState = true;

            mux = new Mcp23017(32, 400);
            led = new OutputPort(Pins.ONBOARD_LED, true);

            while (true)
            {
                mux.Pins[7].Write(bState);
                led.Write(!bState);

                bState = !bState;

                Thread.Sleep(1000);
            }
        }
    }
}

Starting with line 22, we declare an instance, mux, of the Toolbox.NETMF.Hardware.Mcp23017 class. In the constructor we pass 32 (0x20) as the address of our chip in the I2C bus. We also tell the buss to run at 400 kHz.  Then at line 27, we set the state of Pin 7 to true or false to set the state of the LED to on or off.  The loop simply alternates the on state between the LED on our chip and the Netduino on board LED.  It is that simple.

If you want to have a little fun, wire up the rest of the 7 pins on that side of the chip with LEDs and run this to get this:

public static void Main()
{
    mux = new Mcp23017(32, 400);
    led = new OutputPort(Pins.ONBOARD_LED, true);

    int last = -1;

    while (true)
    {
        for (int i = 0; i < 7; i++)
        {
            mux.Pins[i].Write(true);
            if (last > -1)
            {
                mux.Pins[last].Write(false);
            }
            last = i;
            Thread.Sleep(50);
        }
        for (int i = 7; i > -1; i--)
        {
            mux.Pins[i].Write(true);
            if (last > -1)
            {
                mux.Pins[last].Write(false);
            }
            last = i;
            Thread.Sleep(50);
        }
    }
 }

Reading from a PIN

Now that we’ve covered the basics of setting the output state of a pin, let’s start looking at the basic technique for reading the pins state as input.  To do this, we are going to add a switch to GPB0.  This switch will be a pull-down switch.  When the switch is engaged, it will connect GPB0 to GND.  When the switch is not engaged, it will leave the pin floating (this means unattached to anything).  A floating pin is bad and can sometimes cause false readings.  Fortunately, the MCP23017 has a built in weak pull-up resistor.  This will connect the pin to a voltage source so it holds high when floating.

Go ahead and add a switch to your board to connect GPB0 to GND.  I am using a small toggle switch to do this.  Use whatever switch you have in your inventory.

 part1_1_breadboard
Figure 4 – MCP23017 Project Breadboard Layout with Switch

part1_1_schematic
Figure 5 – MCP23017 Project Schematic with Switch

Now we will write some code to read the state of the input on Pin 8 (GPB0) and set the LED to that state.  See below:

public class Program
{
    static OutputPort led;
    static Mcp23017 mux;

    public static void Main()
    {
        mux = new Mcp23017(32, 400);
        led = new OutputPort(Pins.ONBOARD_LED, true);

        bool bState;

        mux.EnablePullup(8, true);

        while (true)
        {
            bState = mux.Pins[8].Read();
            mux.Pins[7].Write(bState);
            led.Write(bState);
            Thread.Sleep(250);
        }
    }
}

Starting at Line 13, you’ll see the call used to turn on the PullUp for pin 8. If you omit this little line of code, the switch will not work as the pin will toggle between a GND and floating state. This is not seen as a change by the chip.  At line 17, we read the state of pin 8 (GPB0) and then set the On Board LED and the LED hanging off of the MCP23017.  We have this enclosed in a loop that executes every 250 ms.

Next Steps

In my next blog posts, I will be covering a more efficient way to read inputs from the MCP23017.  The above process works fine, but it does now allow the main thread to sleep for very long.  This results in a very active program that can drain battery.  We will also cover ways to more efficiently write to multiple pins.  Right now, you would have to iterate through each of the 16 pins and set their state one by one.  We will look at how we can set the state using bytes.

About these ads

About christianloris
Chris Loris is a Software Engineer working with .Net, BizTalk, Data Warehousing, and BI. In the past, Chris has worked as an ASP.Net developer, Engineering Manager, Professional Services Engineer, Test Engineer and a Technical Writer. He's active in the Space Coast SQL User Group and has been active in the Microsoft Developer Community for over 8 years. He's spoken at several SQL Saturdays and hopes to speak at a Code Camp this year. He lives in Viera, Florida with his wife & daughters.

One Response to Netduino Plus 2 with MCP23017 #1 – Basic Wiring and Writing/Reading an IO Port

  1. Pingback: Netduino Plus 2 with MCP23017 #2 – Reading & Writing Using the I2C Bus | Christian Loris' Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: