View Source Circuits.GPIO (circuits_gpio v2.0.0-pre.1)

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

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

@type backend() :: {module(), keyword()}

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.

Options:

  1. 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.
  2. {controller, line_offset} - Specify a line on a specific GPIO controller. E.g., {"gpiochip0", 10}
  3. 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"
  4. {label, label} - Specify both GPIO controller and line labels. E.g., {"primary-gpios", "PIO4"}
@type interrupt_options() :: [suppress_glitches: boolean(), receiver: pid() | atom()]

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.

@type open_options() :: [initial_value: value(), pull_mode: pull_mode()]

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.

Link to this function

enumerate(backend \\ nil)

View Source
@spec enumerate(backend() | nil) :: map()
@spec info(backend() | nil) :: map()

Return info about the low level GPIO interface

This may be helpful when debugging issues.

Link to this function

open(gpio_spec, direction, options \\ [])

View Source
@spec open(gpio_spec(), direction(), open_options()) ::
  {:ok, Circuits.GPIO.Handle.t()} | {:error, atom()}

Open a GPIO

gpio_spec should be a valid GPIO pin number on the system and direction should be :input or :output. If opening as an output, then be sure to set the :initial_value option if you need the set to be glitch free.

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 or 1. Only used for outputs. Defaults to 0.
  • :pull_mode - Set to :not_set, :pullup, :pulldown, or :none for an input pin. :not_set is the default.

Returns {:ok, handle} on success.

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.

Link to this function

set_direction(handle, direction)

View Source
@spec set_direction(Circuits.GPIO.Handle.t(), direction()) :: :ok | {:error, atom()}

Change the direction of the pin

Link to this function

set_interrupts(handle, trigger, options \\ [])

View Source
@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.

Link to this function

set_pull_mode(gpio, pull_mode)

View Source
@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.