elixir_ale v1.2.1 ElixirALE.I2C View Source

This module allows Elixir code to communicate with devices on an I2C bus.

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor

Scan the I2C bus for devices by performing a read at each device address and returning a list of device addresses that respond

Return a list of available I2C bus device names. If nothing is returned, it’s possible that the kernel driver for that I2C bus is not enabled or the kernel’s device tree is not configured. On Raspbian, run raspi-config and look in the advanced options

Invoked when the server is started. start_link/3 or start/3 will block until it returns

Initiate a read transaction on the I2C bus of count bytes

Initiate a read transaction to the device at the specified address. This is the same as read/2 except that an arbitrary device address may be given

Stop the GenServer and release all resources

Start and link the I2c GenServer

Write the specified data to the device

Write the specified data to the device at address

Write the specified data to the device and then read the specified number of bytes

Write the specified data to the device and then read the specified number of bytes. This is similar to write_read/3 except with an I2C device address

Link to this section Types

Link to this type i2c_address() View Source
i2c_address() :: 0..127

Link to this section Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function detect_devices(pid_or_devname) View Source
detect_devices(pid() | binary()) :: [integer()] | {:error, term()}

Scan the I2C bus for devices by performing a read at each device address and returning a list of device addresses that respond.

WARNING: This is intended to be a debugging aid. Reading bytes from devices can advance internal state machines and might cause them to get out of sync with other code.

iex> ElixirALE.I2C.detect_devices("i2c-1")
[4]

The return value is a list of device addresses that were detected on the specified I2C bus. If you get back 'Hh' or other letters, then IEx converted the list to an Erlang string. Run i v() to get information about the return value and look at the raw string representation for addresses.

If you already have an ElixirALE.I2C GenServer running, then you may pass its pid to detect_devices/1 instead.

Link to this function device_names() View Source
device_names() :: [String.t()]

Return a list of available I2C bus device names. If nothing is returned, it’s possible that the kernel driver for that I2C bus is not enabled or the kernel’s device tree is not configured. On Raspbian, run raspi-config and look in the advanced options.

iex> ElixirALE.I2C.device_names
["i2c-1"]

Invoked when the server is started. start_link/3 or start/3 will block until it returns.

args is the argument term (second argument) passed to start_link/3.

Returning {:ok, state} will cause start_link/3 to return {:ok, pid} and the process to enter its loop.

Returning {:ok, state, timeout} is similar to {:ok, state} except handle_info(:timeout, state) will be called after timeout milliseconds if no messages are received within the timeout.

Returning {:ok, state, :hibernate} is similar to {:ok, state} except the process is hibernated before entering the loop. See c:handle_call/3 for more information on hibernation.

Returning {:ok, state, {:continue, continue}} is similar to {:ok, state} except that immediately after entering the loop the c:handle_continue/2 callback will be invoked with the value continue as first argument.

Returning :ignore will cause start_link/3 to return :ignore and the process will exit normally without entering the loop or calling c:terminate/2. If used when part of a supervision tree the parent supervisor will not fail to start nor immediately try to restart the GenServer. The remainder of the supervision tree will be started and so the GenServer should not be required by other processes. It can be started later with Supervisor.restart_child/2 as the child specification is saved in the parent supervisor. The main use cases for this are:

  • The GenServer is disabled by configuration but might be enabled later.
  • An error occurred and it will be handled by a different mechanism than the Supervisor. Likely this approach involves calling Supervisor.restart_child/2 after a delay to attempt a restart.

Returning {:stop, reason} will cause start_link/3 to return {:error, reason} and the process to exit with reason reason without entering the loop or calling c:terminate/2.

Callback implementation for GenServer.init/1.

Initiate a read transaction on the I2C bus of count bytes.

Link to this function read_device(pid, address, count) View Source
read_device(GenServer.server(), i2c_address(), non_neg_integer()) ::
  binary() | {:error, term()}

Initiate a read transaction to the device at the specified address. This is the same as read/2 except that an arbitrary device address may be given.

Stop the GenServer and release all resources.

Link to this function start_link(devname, address, opts \\ []) View Source
start_link(binary(), i2c_address(), [term()]) :: GenServer.on_start()

Start and link the I2c GenServer.

devname is the I2C bus name (e.g., “i2c-1”) address is the device’s 7-bit address on the I2C bus

Note that address can be confusing when reading a datasheet since sometimes the datasheet mentions the 8-bit address. For an 8-bit address the least significant bit indicates whether the access is for a read or a write. Microcontrollers like those on Arduinos often use the 8-bit address. To convert an 8-bit address to a 7-bit one, divide the address by two.

All calls to read/2, write/2, and write_read/3 access the device specified by address. Some I2C devices can be switched into different modes where they respond to an alternate address. Rather than having to create a second I2c process, see read_device/3 and related routines. If your application is interacting with many devices on the bus and you’re only going to call read_device/3, etc., then pass in any number for the i2c_address here.

Link to this function write(pid, data) View Source
write(GenServer.server(), binary()) :: :ok | {:error, term()}

Write the specified data to the device.

Link to this function write_device(pid, address, data) View Source
write_device(GenServer.server(), i2c_address(), binary()) ::
  :ok | {:error, term()}

Write the specified data to the device at address.

Link to this function write_read(pid, write_data, read_count) View Source
write_read(GenServer.server(), binary(), non_neg_integer()) ::
  binary() | {:error, term()}

Write the specified data to the device and then read the specified number of bytes.

Link to this function write_read_device(pid, address, write_data, read_count) View Source
write_read_device(
  GenServer.server(),
  i2c_address(),
  binary(),
  non_neg_integer()
) :: binary() | {:error, term()}

Write the specified data to the device and then read the specified number of bytes. This is similar to write_read/3 except with an I2C device address.