View Source Circuits.GPIO (circuits_gpio v2.0.0-pre.3)
Control GPIOs from Elixir
See the Readme for a tutorial and the porting guide if updating from Circuits.GPIO v1.x.
Simple example:
# GPIO 2 is connected to GPIO 3
iex> {:ok, my_output_gpio} = Circuits.GPIO.open({"gpiochip0", 2}, :output)
iex> {:ok, my_input_gpio} = Circuits.GPIO.open({"gpiochip0", 3}, :input)
iex> Circuits.GPIO.write(my_output_gpio, 1)
:ok
iex> Circuits.GPIO.read(my_input_gpio)
1
iex> Circuits.GPIO.close(my_output_gpio)
iex> Circuits.GPIO.close(my_input_gpio)
Summary
Types
Backends specify an implementation of a Circuits.GPIO.Backend behaviour
GPIO controller
The GPIO direction (input or output)
An identifier for a GPIO
Options for set_interrupt/2
A GPIO controller or line label
GPIO line offset on a controller
Options for open/3
Pull mode for platforms that support controllable pullups and pulldowns
Trigger edge for pin change notifications
GPIO logic value (low = 0 or high = 1)
Functions
Release the resources associated with a GPIO
Return info about the low level GPIO interface
Return information about a GPIO line
Open a GPIO
Get the GPIO pin number
Read a GPIO's value
Change the direction of the pin
Enable or disable GPIO value change notifications
Enable or disable an internal pull-up or pull-down resistor
Set the value of a GPIO
Types
Backends specify an implementation of a Circuits.GPIO.Backend behaviour
The second parameter of the Backend 2-tuple is a list of options. These are passed to the behaviour function call implementations.
@type controller() :: String.t()
GPIO controller
GPIO controllers manage one or more GPIO lines. They're referred to by
strings. For example, you'll mostly see "gpiochip0"
, etc. but they could be
anything or even empty strings there's no reason to differentiate controllers
on a device.
@type direction() :: :input | :output
The GPIO direction (input or output)
@type gpio_spec() :: non_neg_integer() | {controller(), line_offset()} | label() | {label(), label()}
An identifier for a GPIO
Call Circuits.GPIO.enumerate/0
to see what GPIOs are available on your
device. Several ways exist to refer to GPIOs due to variations in devices and
programmer preference. The Raspberry Pi, for example, labels many pins by
their physical location (e.g., "PIN37"
for GPIO 26.)
Options:
index
- Many examples exist where GPIOs are referred to by a GPIO number. There are issues with this strategy since GPIO indices can change. It is so common that it's still supported. Prefer other ways when you're able to change code.{controller, line_offset}
- Specify a line on a specific GPIO controller. E.g.,{"gpiochip0", 10}
label
- Specify a GPIO line label. The first controller that has a matching line is used. This lets you move the mapping of GPIOs to peripheral connections to a device tree file or other central place. E.g.,"LED_ENABLE"
{label, label}
- Specify both GPIO controller and line labels. E.g.,{"primary-gpios", "PIO4"}
Options for set_interrupt/2
@type label() :: String.t()
A GPIO controller or line label
Labels provide aliases for GPIO lines and controllers. They're system-specific. On Linux, labels are provided in device tree files.
@type line_offset() :: non_neg_integer()
GPIO line offset on a controller
GPIOs are numbered based on how they're connected to a controller. The
details are controller specific, but usually the first one is 0
, then 1
,
etc.
Options for open/3
@type pull_mode() :: :not_set | :none | :pullup | :pulldown
Pull mode for platforms that support controllable pullups and pulldowns
@type trigger() :: :rising | :falling | :both | :none
Trigger edge for pin change notifications
@type value() :: 0 | 1
GPIO logic value (low = 0 or high = 1)
Functions
@spec close(Circuits.GPIO.Handle.t()) :: :ok
Release the resources associated with a GPIO
This is optional. The garbage collector will free GPIO resources that aren't in use, but this will free them sooner.
Return info about the low level GPIO interface
This may be helpful when debugging issues.
@spec line_info(gpio_spec()) :: {:ok, Circuits.GPIO.Line.t()} | {:error, atom()}
Return information about a GPIO line
See gpio_spec/0
for the ways of referring to GPIOs. If the GPIO is found,
this function returns information about the GPIO.
@spec open(gpio_spec(), direction(), open_options()) :: {:ok, Circuits.GPIO.Handle.t()} | {:error, atom()}
Open a GPIO
See gpio_spec/0
for the ways of referring to GPIOs. Set direction
to
either :input
or :output
. If opening as an output, then be sure to set
the :initial_value
option to minimize the time the GPIO is in the default
state.
If you're having trouble, see enumerate/0
for available gpio_spec
's.
Circuits.GPIO.Diagnostics
might also be helpful.
Options:
- :initial_value - Set to
0
or1
. Only used for outputs. Defaults to0
. - :pull_mode - Set to
:not_set
,:pullup
,:pulldown
, or:none
for an input pin.:not_set
is the default.
Returns {:ok, handle}
on success.
@spec pin(Circuits.GPIO.Handle.t()) :: non_neg_integer()
Get the GPIO pin number
This function is for Circuits.GPIO v1.0 compatibility. It is recommended to
use other ways of identifying GPIOs going forward. See gpio_spec/0
.
@spec read(Circuits.GPIO.Handle.t()) :: value()
Read a GPIO's value
The value returned for GPIO's that are configured as outputs is undefined. Backends may choose not to support this.
@spec set_direction(Circuits.GPIO.Handle.t(), direction()) :: :ok | {:error, atom()}
Change the direction of the pin
@spec set_interrupts(Circuits.GPIO.Handle.t(), trigger(), interrupt_options()) :: :ok | {:error, atom()}
Enable or disable GPIO value change notifications
Notifications are sent based on the trigger:
- :none - No notifications are sent
- :rising - Send a notification when the pin changes from 0 to 1
- :falling - Send a notification when the pin changes from 1 to 0
- :both - Send a notification on all changes
Available Options:
:suppress_glitches
- Not supported in Circuits.GPIO v2:receiver
- Process which should receive the notifications. Defaults to the calling process (self()
)
Notification messages look like:
{:circuits_gpio, gpio_spec, timestamp, value}
Where gpio_spec
is the gpio_spec passed to open/3
, timestamp
is an OS
monotonic timestamp in nanoseconds, and value
is the new value.
Timestamps are not necessarily the same as from System.monotonic_time/0
.
For example, with the cdev backend, they're applied by the Linux kernel or
can be come from a hardware timer. Erlang's monotonic time is adjusted so
it's not the same as OS monotonic time. The result is that these timestamps
can be compared with each other, but not with anything else.
Notifications only get
NOTE: You will need to store the Circuits.GPIO
reference somewhere (like
your GenServer
's state) so that it doesn't get garbage collected. Event
messages stop when it gets collected. If you only get one message and you are
expecting more, this is likely the case.
@spec set_pull_mode(Circuits.GPIO.Handle.t(), pull_mode()) :: :ok | {:error, atom()}
Enable or disable an internal pull-up or pull-down resistor
@spec write(Circuits.GPIO.Handle.t(), value()) :: :ok
Set the value of a GPIO
The GPIO must be configured as an output.