Packages
circuits_gpio
0.4.2
2.3.0
2.2.0
2.1.3
2.1.2
retired
2.1.1
retired
2.1.0
retired
2.0.2
retired
2.0.1
retired
2.0.0
retired
2.0.0-pre.6
retired
2.0.0-pre.5
retired
2.0.0-pre.4
retired
2.0.0-pre.3
retired
2.0.0-pre.2
retired
2.0.0-pre.1
retired
2.0.0-pre.0
retired
1.2.2
1.2.1
1.2.0
1.1.0
1.0.1
1.0.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.1
0.3.0
0.2.0
0.1.0
Use GPIOs in Elixir
Current section
Files
Jump to
Current section
Files
lib/gpio.ex
defmodule Circuits.GPIO do
alias Circuits.GPIO.Nif
@moduledoc """
Control GPIOs from Elixir
If you're coming from Elixir/ALE, check out our [porting guide](PORTING.md).
`Circuits.GPIO` works great with LEDs, buttons, many kinds of sensors, and
simple control of motors. In general, if a device requires high speed
transactions or has hard real-time constraints in its interactions, this is not
the right library. For those devices, see if there's a Linux kernel driver.
"""
@typedoc "A GPIO pin number. See your device's documentation for how these connect to wires"
@type pin_number :: non_neg_integer()
@typedoc "The GPIO direction (input or output)"
@type pin_direction :: :input | :output
@typedoc "GPIO logic value (low = 0 or high = 1)"
@type value :: 0 | 1
@typedoc "Trigger edge for pin change notifications"
@type trigger :: :rising | :falling | :both | :none
@typedoc "Pull mode for platforms that support controllable pullups and pulldowns"
@type pull_mode :: :not_set | :none | :pullup | :pulldown
@typedoc "Options for open/3"
@type open_option :: {:initial_value, value() | :not_set} | {:pull_mode, pull_mode()}
# Public API
@doc """
Open a GPIO for use.
`pin` should be a valid GPIO pin number on the system and `pin_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.
Options:
* :initial_value - Set to `:not_set`, `0` or `1` if this is an output.
`:not_set` is the default.
* :pull_mode - Set to `:not_set`, `:pullup`, `:pulldown`, or `:none` for an
input pin. `:not_set` is the default.
"""
@spec open(pin_number(), pin_direction(), [open_option()]) ::
{:ok, reference()} | {:error, atom()}
def open(pin_number, pin_direction, options \\ []) do
check_open_options(options)
value = Keyword.get(options, :initial_value, :not_set)
pull_mode = Keyword.get(options, :pull_mode, :not_set)
Nif.open(pin_number, pin_direction, value, pull_mode)
end
defp check_open_options([]), do: :ok
defp check_open_options([{:initial_value, value} | rest]) when value in [:not_set, 0, 1] do
check_open_options(rest)
end
defp check_open_options([{:pull_mode, value} | rest])
when value in [:not_set, :pullup, :pulldown, :none] do
check_open_options(rest)
end
defp check_open_options([bad_option | _]) do
raise ArgumentError.exception("Unsupported option to GPIO.open/3: #{inspect(bad_option)}")
end
@doc """
Release the resources associated with the GPIO.
This is optional. The garbage collector will free GPIO resources that aren't in
use, but this will free them sooner.
"""
@spec close(reference()) :: :ok
def close(gpio) do
Nif.close(gpio)
end
@doc """
Read the current value on a pin.
"""
@spec read(reference()) :: value()
def read(gpio) do
Nif.read(gpio)
end
@doc """
Set the value of a pin. The pin should be configured to an output
for this to work.
"""
@spec write(reference(), value()) :: :ok
def write(gpio, value) do
Nif.write(gpio, value)
end
@doc """
Enable or disable pin value change notifications. The notifications
are sent based on the trigger parameter:
* :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` - It is possible that the pin transitions to a value
and back by the time that Circuits GPIO gets to process it. This controls
whether a notification is sent. Set this to `false` to receive notifications.
* `receiver` - Process which should receive the notifications.
Defaults to the calling process (`self()`)
Notifications look like:
```
{:circuits_gpio, pin_number, timestamp, value}
```
Where `pin_number` is the pin that changed values, `timestamp` is roughly when
the transition occurred in nanoseconds since host system boot time,
and `value` is the new value.
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_interrupts(reference(), trigger(), list()) :: :ok | {:error, atom()}
def set_interrupts(gpio, trigger, opts \\ []) do
suppress_glitches = Keyword.get(opts, :suppress_glitches, true)
receiver =
case Keyword.get(opts, :receiver) do
pid when is_pid(pid) -> pid
name when is_atom(name) -> Process.whereis(name) || self()
_ -> self()
end
Nif.set_interrupts(gpio, trigger, suppress_glitches, receiver)
end
@doc """
Change the direction of the pin.
"""
@spec set_direction(reference(), pin_direction()) :: :ok | {:error, atom()}
def set_direction(gpio, pin_direction) do
Nif.set_direction(gpio, pin_direction)
end
@doc """
Enable or disable internal pull-up or pull-down resistor to GPIO pin
"""
@spec set_pull_mode(reference(), pull_mode()) :: :ok | {:error, atom()}
def set_pull_mode(gpio, pull_mode) do
Nif.set_pull_mode(gpio, pull_mode)
end
@doc """
Get the GPIO pin number
"""
@spec pin(reference) :: pin_number
def pin(gpio) do
Nif.pin(gpio)
end
@doc """
Return info about the low level GPIO interface
This may be helpful when debugging issues.
"""
@spec info() :: map()
defdelegate info(), to: Nif
defmodule :circuits_gpio do
@moduledoc """
Erlang interface to Circuits.GPIO
Example Erlang code: `circuits_gpio:open(5, output)`
"""
defdelegate open(pin_number, pin_direction), to: Circuits.GPIO
defdelegate read(gpio), to: Circuits.GPIO
defdelegate write(gpio, value), to: Circuits.GPIO
defdelegate set_interrupts(gpio, trigger), to: Circuits.GPIO
defdelegate set_interrupts(gpio, trigger, opts), to: Circuits.GPIO
defdelegate set_direction(gpio, pin_direction), to: Circuits.GPIO
defdelegate set_pull_mode(gpio, pull_mode), to: Circuits.GPIO
defdelegate pin(gpio), to: Circuits.GPIO
end
end