Digital IO
Digital IO is often referred to as General Purpose, Input/Output or GPIO. GPIO ports can generally be set to be HIGH
(powered at 3.3V
), or LOW
(grounded at 0V
) which correspond to digital 1
and 0
, respectively. Additionally, those values can be read, if their state is changed by an external source, when the ports are configured for input mode.
Samples
For sample Meadow applications that illustrate the usage of digital ports, check out the IO Sample apps in the Meadow.Samples repo.
Digital Outputs
Setting the state of a digital output is done using an implementation of the IDigitalOutputPort
interface, available on any device that implements the IDigitalOutputController
interface, which provides a method called CreateDigitalOutputPort
:
IDigitalOutputPort CreateDigitalOutputPort(
IPin pin, bool initialState = false,
OutputType initialOutputType = OutputType.PushPull);
pin
- The pin on the device of which to configure to be a digital output.initialState
- A boolean value representing the default state of the port after configuring. Typically this is set tofalse
.initialOutputType
- By default this is set toPushPull
. See the Push-Pull vs. Open-Drain section below for more information.
Digital Output Port Example
For example, if you wanted to be able to control the state of the D05
pin on the Meadow board, you could use the following code to create an instance of the IDigitalOutputPort
with an initial state of LOW
:
IDigitalOutputPort output = Device.CreateDigitalOutputPort(Device.Pins.D05, false);
You could then assert a state on the pin to LOW
or HIGH
using one of the following:
output.State = false; // assert LOW
output.State = true; // assert HIGH
Push-Pull vs. Open-Drain
A digital output pin on the Meadow can be set to either OutputType.PushPull
or OutputType.OpenDrain
, by default, PushPull
is used.
When in Push-Pull mode the MCU can actively drive the pin either HIGH
(3.3V
) or LOW
(0V
), by utilizing two switches internally, requiring no external components.
When in Open-Drain mode, the MCU port utilizes only one switch internally, and can only actively drive the port LOW
. So an external pull-up resistor connected to the 3V3
rail is required to be able to set a logical HIGH
level. OpenDrain
is provided largely as a legacy feature and is hardly used anymore.
Digital Inputs
Reading the state of a digital input is done using an implementation of the IDigitalInputPort
interface, available on any device that implements the IDigitalInputController
interface, which provides a method called CreateDigitalOutputPort
:
IDigitalInputPort CreateDigitalInputPort(
IPin pin,
InterruptMode interruptMode = InterruptMode.None,
ResistorMode resistorMode = ResistorMode.Disabled,
double debounceDuration = 0,
double glitchDuration = 0);
The three most important arguments are:
pin
- The pin on the device of which to configure to be a digital input.interruptMode
- Whether or not the port should be configured to raise interrupt notifications, and what kind of change should trigger an interrupt.resistorMode
- TheResistorMode
specifying whether an external pull-up/pull-down resistor is used, or an internal pull-up/pull-down resistor should be configured for default state.
We'll examine debounce and glitch filtering in a moment.
Digital Input Port Example
For example, if you wanted to be able to read the state of the D03
pin on the Meadow, you could use the following code to create an instance of an IDigitalInputPort
:
IDigitalInputPort input = Device.CreateDigitalInputPort(Device.Pins.D03);
Once the port is configured, you can read the current digital value via the State
property:
bool currentState = input.State;
Interrupts
Interrupts allow your application to be notified of the change of state of a digital input without having to poll the value. Enabling interrupts requires two things from your application: setting the InterruptMode
of the IDigitalInputPort
and then subscribing to notifications either via the Changed
event, or using the IObservable
pattern.
Example
For example, if you wanted your application to get notified when the D03
input pin changed from LOW
to HIGH
(a rising interrupt), you could use the following code:
// create the InputPort with interrupts enabled
var input = Device.CreateDigitalInputPort(
Device.Pins.D03,
InterruptMode.EdgeRising);
// add an event handler
input.Changed += (s, e) =>
{
Console.WriteLine($"interrupt occurred");
};
For more information, check out the Events and IObservable guide.
Debounce and Glitch Filtering
Signal noise is spurious signal changes on a circuit that are induced either via normal mechanical imperfections, such as push buttons or switches, or sometimes through electromagnetic radiation. This noise can case unwanted level change notifications.
This noise typically manifests itself as spikes in the signal.
Noise can be filtered either with a hardware circuit known as a low-pass filter, or in software with a glitch filter and/or a debounce filter.
Meadow.Core has built-in support for both glitch and debounce filters, and when you call CreateDigitalInputPort()
, the last two parameters are:
debounceDuration
glitchDuration
To understand these settings, it helps to understand what these filters are.
Glitch Filter
A glitch is a spurious change before an intentional state change occurs. Because noise typically manifests itself as spikes, the glitch filter specifies the minimum duration, in microseconds (µs), of an initial state change to persist before it's notified as an intentional state change, rather than a spurious one.
This filter can be used to ensure that noise doesn't trigger an in interrupt. Set to 0
if no glitch filter is desired.
Debounce Filter
A bounce gets it's name from mechanical switches (like the common push button/tactile switch), and happens after an intentional state change, like the pushing of a button, in which an actual, mechanical bounce might cause the signal to change momentarily. The debounce filter then specifies the duration, in microseconds (µs), of the time to ignore state changes after a state change has occurred.
This filter can be used to prevent unwanted state changes due to noise. Set to 0
if no debounce filter is desired.
Interrupt Groups
One thing to bear in mind when creating interrupts on multiple pins is that input pins share interrupt groups, in which only one input within any given interrupt group can be enabled as an interrupt. So when choosing pins to use as interrupts, refer to the pinout diagram and make sure that for each interrupt you want to use, they're in a unique interrupt group:
Meadow F7v2 Feather Pinout
Meadow F7v1 Feather Pinout
Pulse-Width-Modulation PWM
Digital output ports can be used to generate a Pulse-Width-Modulation (PWM) signal, which approximates an intermediate voltage between LOW
or HIGH
by switching between ON and OFF very quickly:
PWM signals are frequently used to control the brightness of LEDs, as well as serve as the control signal for precision motors such as servos and stepper motors.
Communication Protocols
Digital IO also includes built-in support for a host of different types of common digital communication protocols including: