-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ee2b4e1
commit 08251a2
Showing
15 changed files
with
323 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
defmodule Ev3.LegoMotor do | ||
@moduledoc "Lego motor access" | ||
|
||
alias Ev3.Device | ||
import Ev3.Sysfs | ||
require Logger | ||
|
||
@sys_path "/sys/class/tacho-motor" | ||
@prefix "motor" | ||
@driver_regex ~r/lego-ev3-(\w)-motor/i | ||
|
||
@doc "Generates a list of all plugged in motor devices" | ||
def motors() do | ||
if !Ev3.testing?() do | ||
File.ls!(@sys_path) | ||
|> Enum.filter(&(String.starts_with?(&1, @prefix))) | ||
|> Enum.map(&(init_motor("#{@sys_path}/#{&1}"))) | ||
else | ||
[Ev3.Mock.Tachomotor.new(:large), Ev3.Mock.Tachomotor.new(:medium)] | ||
end | ||
end | ||
|
||
defp dispatch(motor) do | ||
if !Ev3.testing?() do | ||
Ev3.Tachomotor | ||
else | ||
Ev3.Mock.Tachomotor | ||
end | ||
end | ||
|
||
@doc "Get the list of senses from a motor" | ||
def senses(motor) do | ||
apply(dispatch(motor), :senses, [motor]) | ||
end | ||
|
||
|
||
@doc "Read the value of a sense from a motor" | ||
def read(motor, sense) do # {value, updated_motor} - value can be nil | ||
try do | ||
apply(dispatch(motor), :read, [motor, sense]) | ||
rescue | ||
error -> | ||
Logger.warn("#{inspect error} when reading #{inspect sense} from #{inspect motor}") | ||
{nil, motor} | ||
end | ||
end | ||
|
||
@doc "Get how long to pause between reading a sense from a motor. In msecs" | ||
def pause(motor) do | ||
apply(dispatch(motor), :pause, [motor]) | ||
end | ||
|
||
@doc "Get the resolution of a motor (the delta between essentially identical readings). Nil or an integer." | ||
def sensitivity(motor, sense) do | ||
apply(dispatch(motor), :sensitivity, [motor, sense]) | ||
end | ||
|
||
@doc "Is this a large motor?" | ||
def large?(motor) do | ||
motor.type == :large | ||
end | ||
|
||
@doc "Is this a medium motor?" | ||
def medium?(motor) do | ||
motor.type == :medium | ||
end | ||
|
||
### PRIVATE | ||
|
||
defp init_motor(path) do | ||
port_name = read_sys(path, "port_name") | ||
driver_name = read_sys(path, "driver_name") | ||
[_, type_letter] = Regex.run(@driver_regex, driver_name) | ||
type = case type_letter do | ||
"l" -> :large | ||
"m" -> :medium | ||
end | ||
motor = %Device{class: :motor, | ||
path: path, | ||
port: port_name, | ||
type: type} | ||
count_per_rot = get_attribute(motor, "count_per_rot", :integer) | ||
commands = get_attribute(motor, "commands", :list) | ||
stop_commands = get_attribute(motor, "stop_commands", :list) | ||
%Device{motor | props: %{count_per_rot: count_per_rot, | ||
commands: commands, | ||
stop_commands: stop_commands, | ||
controls: Map.put_new(get_sys_controls(motor), | ||
:speed_mode, | ||
nil)}} | ||
end | ||
|
||
defp get_sys_controls(motor) do | ||
%{polarity: get_attribute(motor, "polarity", :atom), | ||
speed: get_attribute(motor, "speed_sp", :integer), # in counts/sec, | ||
duty_cycle: get_attribute(motor, "duty_cycle_sp", :integer), | ||
ramp_up: get_attribute(motor, "ramp_up_sp", :integer), | ||
ramp_down: get_attribute(motor, "ramp_down_sp", :integer), | ||
position: get_attribute(motor, "position_sp", :integer), # in counts, | ||
time: get_attribute(motor, "time_sp", :integer), | ||
speed_regulation: get_attribute(motor, "speed_regulation", :atom)} | ||
end | ||
|
||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
defmodule Ev3.Mock.Tachomotor do | ||
@moduledoc "A mock large tachomotor" | ||
|
||
@behaviour Ev3.Sensing | ||
|
||
def new(type) do | ||
%Ev3.Device{class: :motor, | ||
path: "/mock/#{type}_tachomotor", | ||
type: type} | ||
end | ||
|
||
# Sensing | ||
|
||
def senses(_) do | ||
[:speed, :position, :duty_cycle, :run_status] | ||
end | ||
|
||
def read(motor, sense) do | ||
case sense do | ||
:speed -> current_speed(motor) | ||
:position -> current_position(motor) | ||
:duty_cycle -> current_duty_cycle(motor) | ||
:run_status -> current_run_status(motor) | ||
end | ||
end | ||
|
||
def pause(_) do | ||
500 | ||
end | ||
|
||
def sensitivity(_motor, _sense) do | ||
nil | ||
end | ||
|
||
### PRIVATE | ||
|
||
defp current_speed(motor) do | ||
value = :random.uniform() * :random.uniform(10) | ||
{value, motor} | ||
end | ||
|
||
defp current_position(motor) do | ||
value = :random.uniform(200) - 100 | ||
{value, motor} | ||
end | ||
|
||
defp current_duty_cycle(motor) do | ||
value = :random.uniform(100) | ||
{value, motor} | ||
end | ||
|
||
defp current_run_status(motor) do | ||
value = case :random.uniform(3) do | ||
0 -> :running | ||
1 -> :stopped | ||
2 -> :stalled | ||
3 -> :holding | ||
end | ||
{value, motor} | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.