dino 0.10.0 → 0.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG.md +67 -0
  2. data/README.md +24 -8
  3. data/bin/dino +108 -0
  4. data/dino.gemspec +2 -1
  5. data/examples/button/button.rb +3 -2
  6. data/examples/ethernet.rb +15 -0
  7. data/examples/{ir_receiver.rb → ir_receiver/ir_receiver.rb} +3 -2
  8. data/examples/led/led.rb +3 -3
  9. data/examples/{potentiometer.rb → potentiometer/potentiometer.rb} +4 -6
  10. data/examples/{rgb_led.rb → rgb_led/rgb_led.rb} +4 -6
  11. data/examples/{sensor.rb → sensor/sensor.rb} +5 -6
  12. data/examples/ser2net.rb +31 -0
  13. data/examples/servo/servo.rb +16 -0
  14. data/examples/stepper/stepper.rb +3 -3
  15. data/lib/dino/board.rb +69 -59
  16. data/lib/dino/components/base_component.rb +8 -7
  17. data/lib/dino/components/rgb_led.rb +19 -17
  18. data/lib/dino/components/sensor.rb +2 -2
  19. data/lib/dino/components/servo.rb +8 -5
  20. data/lib/dino/components/stepper.rb +9 -9
  21. data/lib/dino/tx_rx.rb +5 -4
  22. data/lib/dino/tx_rx/base.rb +64 -0
  23. data/lib/dino/tx_rx/serial.rb +44 -0
  24. data/lib/dino/tx_rx/tcp.rb +23 -0
  25. data/lib/dino/version.rb +1 -1
  26. data/spec/lib/board_spec.rb +53 -39
  27. data/spec/lib/components/led_spec.rb +1 -1
  28. data/spec/lib/components/rgb_led_spec.rb +49 -4
  29. data/spec/lib/components/sensor_spec.rb +14 -10
  30. data/spec/lib/components/servo_spec.rb +9 -4
  31. data/spec/lib/components/stepper_spec.rb +2 -2
  32. data/spec/lib/tx_rx/serial_spec.rb +111 -0
  33. data/spec/lib/tx_rx/tcp_spec.rb +37 -0
  34. data/spec/spec_helper.rb +10 -1
  35. data/src/du/du.ino +19 -0
  36. data/src/du_ethernet/du_ethernet.ino +71 -0
  37. data/src/lib/Dino.cpp +257 -0
  38. data/src/lib/Dino.h +85 -0
  39. metadata +25 -17
  40. data/examples/servo.rb +0 -13
  41. data/examples/telnet.rb +0 -28
  42. data/lib/dino/tx_rx/telnet.rb +0 -53
  43. data/lib/dino/tx_rx/usb_serial.rb +0 -69
  44. data/spec/lib/tx_rx/telnet_spec.rb +0 -66
  45. data/spec/lib/tx_rx/usb_serial_spec.rb +0 -101
  46. data/src/du.ino +0 -251
@@ -1,12 +1,13 @@
1
1
  module Dino
2
2
  module Components
3
3
  class BaseComponent
4
- attr_reader :pin, :board
4
+ attr_reader :board, :pin, :pullup
5
5
  alias :pins :pin
6
6
 
7
7
  def initialize(options={})
8
- self.pin = options[:pin] || options[:pins]
9
8
  self.board = options[:board]
9
+ self.pin = options[:pin] || options[:pins]
10
+ self.pullup = options[:pullup]
10
11
 
11
12
  raise 'board and pin or pins are required for a component' if self.board.nil? || self.pin.nil?
12
13
  after_initialize(options)
@@ -23,19 +24,19 @@ module Dino
23
24
 
24
25
  protected
25
26
 
26
- attr_writer :pin, :board
27
+ attr_writer :board, :pin, :pullup
27
28
  alias :pins= :pin=
28
29
 
29
- def digital_write(value, pin = self.pin)
30
+ def digital_write(pin=self.pin, value)
30
31
  self.board.digital_write(pin, value)
31
32
  end
32
33
 
33
- def analog_write(value, pin = self.pin)
34
+ def analog_write(pin=self.pin, value)
34
35
  self.board.analog_write(pin, value)
35
36
  end
36
37
 
37
- def set_pin_mode(mode, pin = self.pin)
38
- self.board.set_pin_mode(pin, mode)
38
+ def set_pin_mode(pin=self.pin, mode)
39
+ self.board.set_pin_mode(pin, mode, pullup)
39
40
  end
40
41
  end
41
42
  end
@@ -8,27 +8,29 @@ module Dino
8
8
  raise 'missing pins[:blue] pin' unless self.pins[:blue]
9
9
 
10
10
  pins.each do |color, pin|
11
- set_pin_mode(:out, pin)
12
- analog_write(Board::LOW, pin)
11
+ set_pin_mode(pin, :out)
12
+ analog_write(pin, Board::LOW)
13
13
  end
14
14
  end
15
15
 
16
- def blue
17
- analog_write(Board::LOW, pins[:red])
18
- analog_write(Board::LOW, pins[:green])
19
- analog_write(Board::HIGH, pins[:blue])
20
- end
21
-
22
- def red
23
- analog_write(Board::HIGH, pins[:red])
24
- analog_write(Board::LOW, pins[:green])
25
- analog_write(Board::LOW, pins[:blue])
26
- end
16
+ # Format: [R, G, B]
17
+ COLORS = {
18
+ red: [255, 000, 000],
19
+ green: [000, 255, 000],
20
+ blue: [000, 000, 255],
21
+ cyan: [000, 255, 255],
22
+ yellow: [255, 255, 000],
23
+ magenta: [255, 000, 255],
24
+ white: [255, 255, 255],
25
+ off: [000, 000, 000]
26
+ }
27
27
 
28
- def green
29
- analog_write(Board::LOW, pins[:red])
30
- analog_write(Board::HIGH, pins[:green])
31
- analog_write(Board::LOW, pins[:blue])
28
+ COLORS.each_key do |color|
29
+ define_method(color) do
30
+ analog_write(pins[:red], COLORS[color][0])
31
+ analog_write(pins[:green], COLORS[color][1])
32
+ analog_write(pins[:blue], COLORS[color][2])
33
+ end
32
34
  end
33
35
 
34
36
  def blinky
@@ -7,8 +7,8 @@ module Dino
7
7
  @board.start_read
8
8
  end
9
9
 
10
- def when_data_received(callback)
11
- @data_callbacks << callback
10
+ def when_data_received(&block)
11
+ @data_callbacks << block
12
12
  end
13
13
 
14
14
  def update(data)
@@ -5,14 +5,17 @@ module Dino
5
5
 
6
6
  def after_initialize(options={})
7
7
  set_pin_mode(:out)
8
- self.position = 0
8
+ board.servo_toggle(pin, 1)
9
+ self.position = options[:position] || 0
9
10
  end
10
11
 
11
- def position=(new_position)
12
- @position = new_position % 180
13
- analog_write(@position)
12
+ def position=(value)
13
+ board.servo_write(pin, @position = angle(value))
14
+ end
15
+
16
+ def angle(value)
17
+ value == 180 ? value : value % 180
14
18
  end
15
19
  end
16
20
  end
17
21
  end
18
-
@@ -6,21 +6,21 @@ module Dino
6
6
  raise 'missing pins[:step] pin' unless self.pins[:step]
7
7
  raise 'missing pins[:direction] pin' unless self.pins[:direction]
8
8
 
9
- set_pin_mode(:out, pins[:step])
10
- set_pin_mode(:out, pins[:direction])
11
- digital_write(Board::LOW, pins[:step])
9
+ set_pin_mode(pins[:step], :out)
10
+ set_pin_mode(pins[:direction], :out)
11
+ digital_write(pins[:step], Board::LOW)
12
12
  end
13
13
 
14
14
  def step_cc
15
- digital_write(Board::HIGH, self.pins[:direction])
16
- digital_write(Board::HIGH, self.pins[:step])
17
- digital_write(Board::LOW, self.pins[:step])
15
+ digital_write(self.pins[:direction], Board::HIGH)
16
+ digital_write(self.pins[:step], Board::HIGH)
17
+ digital_write(self.pins[:step], Board::LOW)
18
18
  end
19
19
 
20
20
  def step_cw
21
- digital_write(Board::LOW, self.pins[:direction])
22
- digital_write(Board::HIGH, self.pins[:step])
23
- digital_write(Board::LOW, self.pins[:step])
21
+ digital_write(self.pins[:direction], Board::LOW)
22
+ digital_write(self.pins[:step], Board::HIGH)
23
+ digital_write(self.pins[:step], Board::LOW)
24
24
  end
25
25
  end
26
26
  end
@@ -1,10 +1,11 @@
1
1
  module Dino
2
2
  module TxRx
3
- require 'dino/tx_rx/usb_serial'
4
- require 'dino/tx_rx/telnet'
3
+ require 'dino/tx_rx/base'
4
+ require 'dino/tx_rx/serial'
5
+ require 'dino/tx_rx/tcp'
5
6
 
6
- def self.new
7
- self::USBSerial.new
7
+ def self.new(options={})
8
+ self::Serial.new(options)
8
9
  end
9
10
  end
10
11
  end
@@ -0,0 +1,64 @@
1
+ require 'observer'
2
+ require 'timeout'
3
+
4
+ module Dino
5
+ module TxRx
6
+ class Base
7
+ include Observable
8
+
9
+ def read
10
+ @thread ||= Thread.new do
11
+ loop do
12
+ line = gets
13
+ if line && line.match(/\A\d+:/)
14
+ pin, message = line.chop.split(/:/)
15
+ pin && message && changed && notify_observers(pin, message)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ def close_read
22
+ return nil if @thread.nil?
23
+ Thread.kill(@thread)
24
+ @thread = nil
25
+ end
26
+
27
+ def write(message)
28
+ loop do
29
+ if IO.select(nil, [io], nil)
30
+ io.syswrite(message)
31
+ break
32
+ end
33
+ end
34
+ end
35
+
36
+ def handshake
37
+ flush_read
38
+ 100.times do
39
+ begin
40
+ write("!9000000.")
41
+ Timeout::timeout(0.1) do
42
+ line = gets.to_s
43
+ if line.match /ACK:/
44
+ flush_read
45
+ return line.chop.split(/:/)[1].to_i
46
+ end
47
+ end
48
+ rescue
49
+ nil
50
+ end
51
+ end
52
+ raise BoardNotFound
53
+ end
54
+
55
+ def flush_read
56
+ gets until gets == nil
57
+ end
58
+
59
+ def gets
60
+ IO.select([io], nil, nil, 0.005) && io.gets
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,44 @@
1
+ require 'serialport'
2
+
3
+ module Dino
4
+ module TxRx
5
+ class Serial < Base
6
+ BAUD = 115200
7
+
8
+ def initialize(options={})
9
+ @device = options[:device]
10
+ @baud = options[:baud] || BAUD
11
+ @first_write = true
12
+ end
13
+
14
+ def io
15
+ @io ||= connect
16
+ end
17
+
18
+ def handshake
19
+ if on_windows?
20
+ io; sleep 3
21
+ end
22
+
23
+ super
24
+ end
25
+
26
+ private
27
+
28
+ def connect
29
+ tty_devices.each { |device| return SerialPort.new(device, @baud) rescue nil }
30
+ raise BoardNotFound
31
+ end
32
+
33
+ def tty_devices
34
+ return [@device] if @device
35
+ return (1..256).map { |n| "COM#{n}" } if on_windows?
36
+ `ls /dev`.split("\n").grep(/usb|ACM/i).map{ |d| "/dev/#{d}" }
37
+ end
38
+
39
+ def on_windows?
40
+ RUBY_PLATFORM.match /mswin|mingw/i
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ require 'socket'
2
+
3
+ module Dino
4
+ module TxRx
5
+ class TCP < Base
6
+ def initialize(host, port=3466)
7
+ @host, @port = host, port
8
+ end
9
+
10
+ def io
11
+ @io ||= connect
12
+ end
13
+
14
+ private
15
+
16
+ def connect
17
+ Timeout::timeout(10) { TCPSocket.open(@host, @port) }
18
+ rescue
19
+ raise BoardNotFound
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Dino
2
- VERSION = "0.10.0"
2
+ VERSION = "0.11.2"
3
3
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module Dino
4
4
  describe Dino::Board do
5
5
  def io_mock(methods = {})
6
- @io ||= mock(:io, {write: nil, add_observer: nil}.merge(methods))
6
+ @io ||= mock(:io, {write: nil, add_observer: nil, flush_read: nil, handshake: "14"}.merge(methods))
7
7
  end
8
8
 
9
9
  subject { Board.new(io_mock) }
@@ -20,14 +20,8 @@ module Dino
20
20
  subject.send(:initialize, io_mock)
21
21
  end
22
22
 
23
- it 'should start the heart beat' do
24
- io_mock.should_receive(:write).with('!0212000.')
25
- subject.add_digital_hardware(mock(:part, pin: 12))
26
- sleep 0.01
27
- end
28
-
29
- it 'should send clearing bytes to the io' do
30
- io_mock.should_receive(:write).with("00000000")
23
+ it 'should initiate the handshake' do
24
+ io_mock.should_receive(:handshake)
31
25
  subject
32
26
  end
33
27
  end
@@ -47,9 +41,9 @@ module Dino
47
41
 
48
42
  context 'when the given pin connects to an digital hardware part' do
49
43
  it 'should call update with the message on the part' do
50
- part = mock(:part, pin: 5)
44
+ part = mock(:part, pin: 5, pullup: nil)
51
45
  subject.add_digital_hardware(part)
52
- other_part = mock(:part, pin: 11)
46
+ other_part = mock(:part, pin: 11, pullup: nil)
53
47
  subject.add_digital_hardware(other_part)
54
48
 
55
49
  part.should_receive(:update).with('wake up!')
@@ -82,21 +76,23 @@ module Dino
82
76
 
83
77
  describe '#add_digital_hardware' do
84
78
  it 'should add digital hardware to the board' do
85
- subject.add_digital_hardware(mock1 = mock(:part1, pin: 12))
86
- subject.add_digital_hardware(mock2 = mock(:part2, pin: 14))
79
+ subject.add_digital_hardware(mock1 = mock(:part1, pin: 12, pullup: nil))
80
+ subject.add_digital_hardware(mock2 = mock(:part2, pin: 14, pullup: nil))
87
81
  subject.digital_hardware.should =~ [mock1, mock2]
88
82
  end
89
83
 
90
- it 'should set the mode for the given pin to "in"' do
84
+ it 'should set the mode for the given pin to "in" and add a digital listener' do
91
85
  subject
92
- subject.should_receive(:write).with("0012000")
93
- subject.add_digital_hardware(mock1 = mock(:part1, pin: 12))
86
+ subject.should_receive(:write).with("0012001")
87
+ subject.should_receive(:write).with("0112000")
88
+ subject.should_receive(:write).with("0512000")
89
+ subject.add_digital_hardware(mock1 = mock(:part1, pin: 12, pullup: nil))
94
90
  end
95
91
  end
96
92
 
97
93
  describe '#remove_digital_hardware' do
98
94
  it 'should remove the given part from the hardware of the board' do
99
- mock = mock(:part1, pin: 12)
95
+ mock = mock(:part1, pin: 12, pullup: nil)
100
96
  subject.add_digital_hardware(mock)
101
97
  subject.remove_digital_hardware(mock)
102
98
  subject.digital_hardware.should == []
@@ -105,21 +101,23 @@ module Dino
105
101
 
106
102
  describe '#add_analog_hardware' do
107
103
  it 'should add analog hardware to the board' do
108
- subject.add_analog_hardware(mock1 = mock(:part1, pin: 12))
109
- subject.add_analog_hardware(mock2 = mock(:part2, pin: 14))
104
+ subject.add_analog_hardware(mock1 = mock(:part1, pin: 12, pullup: nil))
105
+ subject.add_analog_hardware(mock2 = mock(:part2, pin: 14, pullup: nil))
110
106
  subject.analog_hardware.should =~ [mock1, mock2]
111
107
  end
112
108
 
113
- it 'should set the mode for the given pin to "in"' do
109
+ it 'should set the mode for the given pin to "in" and add an analog listener' do
114
110
  subject
115
- subject.should_receive(:write).with("0012000")
116
- subject.add_analog_hardware(mock1 = mock(:part1, pin: 12))
111
+ subject.should_receive(:write).with("0012001")
112
+ subject.should_receive(:write).with("0112000")
113
+ subject.should_receive(:write).with("0612000")
114
+ subject.add_analog_hardware(mock1 = mock(:part1, pin: 12, pullup: nil))
117
115
  end
118
116
  end
119
117
 
120
118
  describe '#remove_analog_hardware' do
121
119
  it 'should remove the given part from the hardware of the board' do
122
- mock = mock(:part1, pin: 12)
120
+ mock = mock(:part1, pin: 12, pullup: nil)
123
121
  subject.add_analog_hardware(mock)
124
122
  subject.remove_analog_hardware(mock)
125
123
  subject.analog_hardware.should == []
@@ -167,7 +165,7 @@ module Dino
167
165
  end
168
166
 
169
167
  describe '#digital_read' do
170
- it 'should tell the board to start reading from the given pin' do
168
+ it 'should tell the board to read once from the given pin' do
171
169
  io_mock.should_receive(:write).with('!0213000.')
172
170
  subject.digital_read(13)
173
171
  end
@@ -181,33 +179,49 @@ module Dino
181
179
  end
182
180
 
183
181
  describe '#analog_read' do
184
- it 'should tell the board to start reading from the given pin' do
182
+ it 'should tell the board to read once from the given pin' do
185
183
  io_mock.should_receive(:write).with('!0413000.')
186
184
  subject.analog_read(13)
187
185
  end
188
186
  end
189
187
 
188
+ describe '#digital_listen' do
189
+ it 'should tell the board to continuously read from the given pin' do
190
+ io_mock.should_receive(:write).with('!0513000.')
191
+ subject.digital_listen(13)
192
+ end
193
+ end
194
+
195
+ describe '#analog_listen' do
196
+ it 'should tell the board to continuously read from the given pin' do
197
+ io_mock.should_receive(:write).with('!0613000.')
198
+ subject.analog_listen(13)
199
+ end
200
+ end
201
+
202
+ describe '#stop_listener' do
203
+ it 'should tell the board to stop sending values for the given pin' do
204
+ io_mock.should_receive(:write).with('!0713000.')
205
+ subject.stop_listener(13)
206
+ end
207
+ end
208
+
190
209
  describe '#set_pin_mode' do
191
- it 'should send a value of 1 if the pin mode is set to out' do
192
- io_mock.should_receive(:write).with('!0013001.')
210
+ it 'should send a value of 0 if the pin mode is set to out' do
211
+ io_mock.should_receive(:write).with('!0013000.')
193
212
  subject.set_pin_mode(13, :out)
194
213
  end
195
214
 
196
- it 'should send a value of 0 if the pin mode is set to in' do
197
- io_mock.should_receive(:write).with('!0013000.')
215
+ it 'should send a value of 1 if the pin mode is set to in' do
216
+ io_mock.should_receive(:write).with('!0013001.')
198
217
  subject.set_pin_mode(13, :in)
199
218
  end
200
219
  end
201
220
 
202
- describe '#set_debug' do
203
- it 'should set the boards debug on when passed on' do
204
- io_mock.should_receive(:write).with('!9900001.')
205
- subject.set_debug(:on)
206
- end
207
-
208
- it 'should set the boards debug off when passed off' do
209
- io_mock.should_receive(:write).with('!9900000.')
210
- subject.set_debug(:off)
221
+ describe '#handshake' do
222
+ it 'should tell the board to reset to defaults' do
223
+ io_mock.should_receive(:handshake)
224
+ subject.handshake
211
225
  end
212
226
  end
213
227
 
@@ -221,7 +235,7 @@ module Dino
221
235
  end
222
236
 
223
237
  it 'should raise if a number larger than two digits are given' do
224
- expect { subject.normalize_pin(1000) }.to raise_exception 'pins can only be two digits'
238
+ expect { subject.normalize_pin(1000) }.to raise_exception 'pin number must be in 0-99'
225
239
  end
226
240
  end
227
241