BBB 0.0.10 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/BBB.rb +13 -17
- data/lib/BBB/application.rb +4 -21
- data/lib/BBB/circuit.rb +18 -33
- data/lib/BBB/components/analog_component.rb +29 -6
- data/lib/BBB/components/led.rb +39 -9
- data/lib/BBB/components/pinnable.rb +90 -4
- data/lib/BBB/components/servo.rb +43 -0
- data/lib/BBB/pins/analog_pin.rb +39 -0
- data/lib/BBB/pins/digital_pin.rb +106 -0
- data/lib/BBB/pins/io/ain.rb +58 -0
- data/lib/BBB/pins/io/gpio.rb +77 -0
- data/lib/BBB/pins/io/mapped.rb +39 -0
- data/lib/BBB/pins/io/pin_mapper.rb +224 -0
- data/lib/BBB/pins/io/pwm.rb +61 -0
- data/lib/BBB/pins/pinnable.rb +78 -0
- data/lib/BBB/pins/pwm_pin.rb +43 -0
- data/lib/BBB/version.rb +1 -1
- data/spec/application_spec.rb +1 -26
- data/spec/circuit_spec.rb +0 -1
- data/spec/components/analog_component_spec.rb +36 -0
- data/spec/components/led_spec.rb +14 -19
- data/spec/components/pinnable_spec.rb +73 -8
- data/spec/components/servo_spec.rb +6 -0
- data/spec/pins/analog_pin_spec.rb +33 -0
- data/spec/pins/digital_input_pin_spec.rb +13 -0
- data/spec/pins/digital_output_pin_spec.rb +14 -0
- data/spec/pins/digital_pin_spec.rb +66 -0
- data/spec/pins/io/mapped_spec.rb +41 -0
- data/spec/{board → pins/io}/pin_mapper_spec.rb +2 -2
- data/spec/pins/pinnable_spec.rb +68 -0
- data/spec/pins/pwm_pin_spec.rb +29 -0
- metadata +34 -37
- data/lib/BBB/adc/analog_pin.rb +0 -42
- data/lib/BBB/adc/setup.rb +0 -20
- data/lib/BBB/board/base.rb +0 -45
- data/lib/BBB/board/json_pin_mapper.rb +0 -203
- data/lib/BBB/board/pin_mapper.rb +0 -20
- data/lib/BBB/board/test_board.rb +0 -12
- data/lib/BBB/gpio/base.rb +0 -56
- data/lib/BBB/gpio/digital_pin.rb +0 -69
- data/lib/BBB/gpio/pin_converter.rb +0 -28
- data/lib/BBB/io/analog_pin.rb +0 -24
- data/lib/BBB/io/digital_pin.rb +0 -67
- data/lib/BBB/io/mock_pin.rb +0 -8
- data/lib/BBB/io/pinnable.rb +0 -12
- data/spec/adc/analog_pin_spec.rb +0 -100
- data/spec/adc/setup_spec.rb +0 -9
- data/spec/board/board_spec.rb +0 -49
- data/spec/gpio/base_spec.rb +0 -48
- data/spec/gpio/digital_pin_spec.rb +0 -100
- data/spec/gpio/pin_converter_spec.rb +0 -19
- data/spec/io/digital_pin_spec.rb +0 -14
- data/spec/io/mock_pin_spec.rb +0 -13
- data/spec/io/pinnable_spec.rb +0 -13
data/lib/BBB.rb
CHANGED
@@ -1,30 +1,26 @@
|
|
1
|
-
require "BBB/version"
|
2
|
-
|
3
1
|
require "json"
|
2
|
+
require "stringio"
|
4
3
|
|
5
|
-
require "BBB/
|
6
|
-
require "BBB/board/test_board"
|
7
|
-
require "BBB/board/json_pin_mapper"
|
8
|
-
require "BBB/board/pin_mapper"
|
4
|
+
require "BBB/version"
|
9
5
|
|
10
6
|
require "BBB/circuit"
|
11
7
|
require "BBB/exceptions"
|
12
8
|
|
13
|
-
require "BBB/
|
14
|
-
require "BBB/
|
15
|
-
require "BBB/
|
9
|
+
require "BBB/pins/io/pin_mapper"
|
10
|
+
require "BBB/pins/io/mapped"
|
11
|
+
require "BBB/pins/io/ain"
|
12
|
+
require "BBB/pins/io/gpio"
|
13
|
+
require "BBB/pins/io/pwm"
|
16
14
|
|
17
|
-
require "BBB/
|
18
|
-
require "BBB/
|
19
|
-
|
20
|
-
require "BBB/
|
21
|
-
require "BBB/io/digital_pin"
|
22
|
-
require "BBB/io/analog_pin"
|
23
|
-
require "BBB/io/mock_pin"
|
15
|
+
require "BBB/pins/pinnable"
|
16
|
+
require "BBB/pins/digital_pin"
|
17
|
+
require "BBB/pins/analog_pin"
|
18
|
+
require "BBB/pins/pwm_pin"
|
24
19
|
|
25
20
|
require "BBB/components/pinnable"
|
26
|
-
require "BBB/components/led"
|
27
21
|
require "BBB/components/analog_component"
|
22
|
+
require "BBB/components/led"
|
23
|
+
require "BBB/components/servo"
|
28
24
|
|
29
25
|
require "BBB/application"
|
30
26
|
|
data/lib/BBB/application.rb
CHANGED
@@ -1,42 +1,25 @@
|
|
1
1
|
module BBB
|
2
2
|
class Application
|
3
3
|
|
4
|
-
def self.board(board)
|
5
|
-
@_board = board
|
6
|
-
connect unless @_circuit.nil?
|
7
|
-
end
|
8
|
-
|
9
4
|
def self.circuit(circuit)
|
10
5
|
@_circuit = circuit
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
def self._board
|
15
|
-
@_board
|
6
|
+
define_convenience_methods(circuit)
|
16
7
|
end
|
17
8
|
|
18
9
|
def self._circuit
|
19
10
|
@_circuit
|
20
11
|
end
|
21
12
|
|
22
|
-
def self.
|
23
|
-
|
24
|
-
component.pins.each do |pin|
|
25
|
-
@_board.connect_io_pin(pin)
|
26
|
-
end
|
27
|
-
|
13
|
+
def self.define_convenience_methods(c)
|
14
|
+
c.components.keys.each do |name|
|
28
15
|
define_method(name) do
|
29
16
|
circuit.send(name)
|
30
17
|
end
|
31
18
|
end
|
32
19
|
end
|
33
20
|
|
34
|
-
def board
|
35
|
-
@board ||= self.class._board
|
36
|
-
end
|
37
|
-
|
38
21
|
def circuit
|
39
|
-
|
22
|
+
self.class._circuit
|
40
23
|
end
|
41
24
|
|
42
25
|
def start
|
data/lib/BBB/circuit.rb
CHANGED
@@ -1,56 +1,49 @@
|
|
1
1
|
module BBB
|
2
2
|
##
|
3
|
-
# The idea here is to attach a piece of equipment to a circuit.
|
4
|
-
# will later be connected to a board.
|
3
|
+
# The idea here is to attach a piece of equipment to a circuit.
|
5
4
|
#
|
6
5
|
# A component (e.g. Led or Servo) will define generic pins, like
|
7
|
-
# DigitalInput or AnalogOutput. And then, when the
|
8
|
-
# the
|
9
|
-
# on the board.
|
10
|
-
#
|
11
|
-
# This allows you to develop generic circuits that can be attached to any
|
12
|
-
# board. At least, in theory :-)
|
6
|
+
# DigitalInput or AnalogOutput. And then, when the component gets attached to
|
7
|
+
# the circuit those pins will be initialized using the file system.
|
13
8
|
#
|
14
9
|
# For now the attachment will be made onto specific pin numbers. For the BBB
|
15
10
|
# this might for example be :P8_3, however, the plan is to, in a future
|
16
11
|
# release, make sure that there are converters between the different kind of
|
17
12
|
# boards. For example by mapping P8_3 on BBB to P1 on an Arduino.
|
18
13
|
#
|
19
|
-
# As of now, the act of "attaching" something onto the circuit equals
|
20
|
-
# setting up a component with generic pins.
|
21
|
-
#
|
22
14
|
class Circuit
|
23
|
-
attr_reader :components
|
15
|
+
attr_reader :components, :mock
|
24
16
|
|
25
17
|
def components
|
26
18
|
@components ||= {}
|
27
19
|
end
|
28
20
|
|
21
|
+
def mock?
|
22
|
+
@mock == true
|
23
|
+
end
|
24
|
+
|
29
25
|
##
|
30
26
|
# Attach a component of a certain type to the circuit
|
31
27
|
#
|
32
28
|
# @param component [Class] The class of the object you # want to attach.
|
33
29
|
# @param opts [Hash] Hash of options that setup the component
|
34
30
|
#
|
31
|
+
# @option opts [Symbol] :pin The pin position for the component
|
35
32
|
# @option opts [Array<Symbol>] :pins The list of pin numbers used on the
|
36
|
-
#
|
33
|
+
# circuit.
|
34
|
+
# @options opts [Symbol] :as The name of the component
|
37
35
|
#
|
38
36
|
def attach(component, opts={})
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
name = opts.delete(:as)
|
38
|
+
component = component.new if component.kind_of?(Class)
|
39
|
+
pin_positions = opts.delete(:pins) || [opts.delete(:pin)]
|
40
|
+
pin_options = {:mock=>self.mock?}.merge!(opts)
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
verify_pin_argument_count(component_pins.count, pin_positions.count)
|
46
|
-
component.register_pin_positions(pin_positions)
|
47
|
-
end
|
48
|
-
|
49
|
-
name = opts.fetch(:as)
|
50
|
-
register_component(component, name)
|
42
|
+
component.initialize_pins(pin_positions, pin_options)
|
43
|
+
define_method_for_component(component, name)
|
51
44
|
end
|
52
45
|
|
53
|
-
def
|
46
|
+
def define_method_for_component(component, name)
|
54
47
|
components[name] = component
|
55
48
|
eigenclass = class << self; self; end
|
56
49
|
eigenclass.class_eval do
|
@@ -60,13 +53,5 @@ module BBB
|
|
60
53
|
end
|
61
54
|
end
|
62
55
|
|
63
|
-
def verify_pin_argument_count(type_count, position_count)
|
64
|
-
if type_count != position_count
|
65
|
-
raise PinsDoNotMatchException,
|
66
|
-
"#{object.to_s} requires #{types_count} but received #{position_count} pin arguments."
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
56
|
end
|
72
57
|
end
|
@@ -1,22 +1,45 @@
|
|
1
1
|
module BBB
|
2
2
|
module Components
|
3
|
+
##
|
4
|
+
# An AnalogComponent is a component that reads from an analog input (AIN) on
|
5
|
+
# the board. You can use a generic analog component for, for example,
|
6
|
+
# temperature or light sensors.
|
7
|
+
#
|
8
|
+
# The BeagleBoneBlack has 12 bit (4096) AIN pins. So the expected value of
|
9
|
+
# an analog pin is between 0 and 4096.
|
10
|
+
#
|
3
11
|
class AnalogComponent
|
4
12
|
include Pinnable
|
5
13
|
|
6
|
-
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@pin = BBB::IO::AnalogPin.new
|
10
|
-
@pins = [@pin]
|
11
|
-
end
|
14
|
+
uses BBB::Pins::AnalogPin
|
12
15
|
|
16
|
+
##
|
17
|
+
# Read from an initialized pin, if the pins have not been initialized yet,
|
18
|
+
# this method might actually raise an exception.
|
19
|
+
#
|
20
|
+
# @raise MethodNotFoundException
|
21
|
+
#
|
22
|
+
# @return Integer
|
23
|
+
#
|
13
24
|
def read
|
14
25
|
pin.read
|
15
26
|
end
|
16
27
|
|
28
|
+
##
|
29
|
+
# @see #read
|
30
|
+
#
|
17
31
|
def value
|
18
32
|
read
|
19
33
|
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Convenience method to grab the first pin in the pins array
|
37
|
+
#
|
38
|
+
# @return BBB::Pins::AnalogPin
|
39
|
+
#
|
40
|
+
def pin
|
41
|
+
pins.first
|
42
|
+
end
|
20
43
|
end
|
21
44
|
end
|
22
45
|
end
|
data/lib/BBB/components/led.rb
CHANGED
@@ -1,31 +1,61 @@
|
|
1
1
|
module BBB
|
2
2
|
module Components
|
3
|
+
##
|
4
|
+
# The LED class is the component interface into a digital pin. In a way it's
|
5
|
+
# nothing more than a straight forward port of a digital pin. You can use a
|
6
|
+
# led component when you want to use digital pins, or simply define your own
|
7
|
+
# class and extend it from the LED.
|
8
|
+
#
|
9
|
+
# The Led class does not perform any sort of caching or smart calls, it
|
10
|
+
# forwards everything to the pin. In your own applications you might want to
|
11
|
+
# tune this behavior by adding some kind of caching.
|
12
|
+
#
|
3
13
|
class Led
|
4
14
|
include Pinnable
|
5
|
-
attr_reader :state, :pin
|
6
15
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
16
|
+
uses BBB::Pins::DigitalOutputPin
|
17
|
+
|
18
|
+
##
|
19
|
+
# Convenience method to grab the first pin in the pins array
|
20
|
+
#
|
21
|
+
# @return BBB::Pins::DigitalOutputPin
|
22
|
+
#
|
23
|
+
def pin
|
24
|
+
pins.first
|
11
25
|
end
|
12
26
|
|
27
|
+
##
|
28
|
+
# Turns on the LED
|
29
|
+
# @return void
|
30
|
+
#
|
13
31
|
def on!
|
14
32
|
pin.on!
|
15
|
-
@state = :high
|
16
33
|
end
|
17
34
|
|
35
|
+
##
|
36
|
+
# Turns off the LED
|
37
|
+
# @return void
|
38
|
+
#
|
18
39
|
def off!
|
19
40
|
pin.off!
|
20
|
-
@state = :low
|
21
41
|
end
|
22
42
|
|
43
|
+
##
|
44
|
+
# Checks if the LED is turned on.
|
45
|
+
#
|
46
|
+
# @return Boolean
|
47
|
+
#
|
23
48
|
def on?
|
24
|
-
|
49
|
+
pin.on?
|
25
50
|
end
|
26
51
|
|
52
|
+
##
|
53
|
+
# Checks if the LED is turned off.
|
54
|
+
#
|
55
|
+
# @return Boolean
|
56
|
+
#
|
27
57
|
def off?
|
28
|
-
|
58
|
+
pin.off?
|
29
59
|
end
|
30
60
|
|
31
61
|
end
|
@@ -3,13 +3,99 @@ module BBB
|
|
3
3
|
module Pinnable
|
4
4
|
attr_reader :pins
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
pins.
|
9
|
-
|
6
|
+
module ClassMethods
|
7
|
+
##
|
8
|
+
# Register the use of classes of pins to a class. These classes will be
|
9
|
+
# initialized upon #initialize_pins
|
10
|
+
#
|
11
|
+
# @param pin_classes [Array<Class>] the classes to register on class
|
12
|
+
# level.
|
13
|
+
#
|
14
|
+
def uses(*pin_classes)
|
15
|
+
pins.concat(pin_classes)
|
10
16
|
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Attribute reader to the class level @pins
|
20
|
+
#
|
21
|
+
# @return Array<Class>
|
22
|
+
#
|
23
|
+
def pins
|
24
|
+
@pins ||= []
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.extend(ClassMethods)
|
11
30
|
end
|
12
31
|
|
32
|
+
##
|
33
|
+
# Initialize the pin classes with their positions and options. Turning
|
34
|
+
# them from their Classes into working pin instances.
|
35
|
+
#
|
36
|
+
# The argument list of the methods is a bit odd. Since it's not
|
37
|
+
# possible to have both a splat and an option array as arguments, the
|
38
|
+
# method signature only shows a splat of positions. The options are then
|
39
|
+
# taken out of the positions, if the last position is actually a Hash as
|
40
|
+
# opposed to a Symbol. If the last element of the positions list is not
|
41
|
+
# a Hash, the options are set to an empty hash.
|
42
|
+
#
|
43
|
+
# @param positions [Array<Symbol>] positions the pins should be
|
44
|
+
# initialized with.
|
45
|
+
# @param opts [Hash] Options to pass along to the pins during
|
46
|
+
# initialization.
|
47
|
+
#
|
48
|
+
# @return Array[Pins]
|
49
|
+
#
|
50
|
+
def initialize_pins(*positions)
|
51
|
+
opts = positions.last.kind_of?(Hash) ? positions.pop : {}
|
52
|
+
|
53
|
+
verify_pin_position_count(positions)
|
54
|
+
|
55
|
+
@pins = []
|
56
|
+
self.class.pins.each_with_index do |pin, index|
|
57
|
+
@pins << pin.new(positions[index], opts)
|
58
|
+
end
|
59
|
+
after_pin_initialization
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Verifies if the number of pins registered in the @pins array match with
|
64
|
+
# the number of pins provided as an argument to the method. This function
|
65
|
+
# normally gets called as part of the initialize pins method to verify if
|
66
|
+
# the positions given to the initialize_pins method matches the number of
|
67
|
+
# registered pins.
|
68
|
+
#
|
69
|
+
# @param positions [Array<Symbol>] The array of positions
|
70
|
+
#
|
71
|
+
# @raise [PinsDoNotMatchException] If the pin counts between the positions
|
72
|
+
# provided as an argument and the pins in the pins array do not match,
|
73
|
+
# this exception gets raised, to prevent hard to debug situations later
|
74
|
+
# on in the lifecycle of an application.
|
75
|
+
#
|
76
|
+
# @return Void
|
77
|
+
def verify_pin_position_count(positions)
|
78
|
+
if self.class.pins.count != positions.count
|
79
|
+
raise PinsDoNotMatchException,
|
80
|
+
"#{self.class.to_s} requires #{self.class.pins.count} but received #{positions.count} pin position."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Method which classes can overwrite to hook into the after pin
|
86
|
+
# initialization
|
87
|
+
#
|
88
|
+
def after_pin_initialization
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Method that is used in the test suite to test if the pinnable module is
|
93
|
+
# included in an object
|
94
|
+
#
|
95
|
+
# @return true
|
96
|
+
def pinnable?
|
97
|
+
true
|
98
|
+
end
|
13
99
|
end
|
14
100
|
end
|
15
101
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module BBB
|
2
|
+
module Components
|
3
|
+
class Servo
|
4
|
+
include Pinnable
|
5
|
+
#uses Pins::PWMPin
|
6
|
+
attr_reader :min_duty, :max_duty, :period
|
7
|
+
|
8
|
+
def initialize(period=17e6, min_duty=14.6e6, max_duty=16.6e6)
|
9
|
+
@period = period
|
10
|
+
@min_duty = min_duty
|
11
|
+
@max_duty = max_duty
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_pin_initialization
|
15
|
+
pin.period = 17e6
|
16
|
+
pin.duty = (min_duty + duty_range / 2)
|
17
|
+
pin.run = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def angle(degrees)
|
21
|
+
value = degrees / 180.to_f * duty_range + min_duty
|
22
|
+
pin.duty = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def activate!
|
26
|
+
pin.run = 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def deactivate!
|
30
|
+
pin.run = 0
|
31
|
+
end
|
32
|
+
|
33
|
+
def pin
|
34
|
+
pins.first
|
35
|
+
end
|
36
|
+
|
37
|
+
def duty_range
|
38
|
+
max_duty - min_duty
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|