Pure Elixir library to interact with the sysfs interface to hardware PWM on Linux.
Add pwmx to your dependencies in mix.exs:
def deps do
[
{:pwmx, "~> 0.1.0"}
]
endIf you wish to just write and read to the sysfs Pwm interface, you can find path helpers in the Pwmx.Paths module.
File.read(Pwmx.Paths.duty_cycle_path("pwmchip0", "1"))If you want an Elixir interface instead of calling File.write/2 or File.read/1 yourself, the module Pwmx.Backend.Sysfs.Ops has a stateless interface that actually performs the reads and writes.
Pwmx.Backend.Sysfs.Ops.get_duty_cycle("pwmchip0", "1")The Pwmx.Output module can be used to spin up a genserver representing your output, managing its state.
{:ok, pid} = Pwmx.Output.start_link({"pwmchip0", 1})
Pwmx.Output.enable(pid) |> Pwmx.Output.set_period(1_000_000, :us) The setters cache the value they write rather than reading it back from the
backend, the achievable value by the driver can differ. Call get_period/1
or get_duty_cycle/1 to re-read if you need the actual timing.
In a test or non-linux environment, the Pwmx.Backend.Sysfs module is not used, and calls are instead dispatched to Pwmx.Backend.Virtual, which keeps track of your operations on PWM outputs with the Pwmx.State struct. This struct isn't meant to be used directly as it wouldn't be of particular help.
The application supervises a default backend registered as Pwmx.Backend. To test code that drives PWM outputs, start your own virtual backend and hand it to Pwmx.Output (or Pwmx.open/3). Each instance owns its state :
{:ok, backend} = Pwmx.Backend.start_link(mode: :virtual, virtual_chips: %{"virtualchip0" => 4})
{:ok, pid} = Pwmx.Output.start_link({"virtualchip0", 1}, backend: backend)
Pwmx.Output.enable(pid) |> Pwmx.Output.set_period(1_000, :ms)You can also fix the virtual board globally via configuration:
# config/test.exs
config :pwmx, virtual_chips: %{"virtualchip0" => 4}An helper function can help you. Note that this function actually exports then closes each output as it seems that after a bit of testing, it cannot be taken for granted that every output reported by /sys/class/pwm/chip/npwm is able to be opened. Note that already exported outputs by something else in your system will not show up in this list as the export will fail.
Pwmx.list_available_outputs()
[
{"virtualchip0", 0},
{"virtualchip0", 1},
{"virtualchip0", 2},
{"virtualchip0", 3}
]- Sample project showing behavior on a host & on a board