lego-nxt 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e972fae0b3659e85c16a77bf735809a97b0c9bf0
4
+ data.tar.gz: bc3d2844376e99a2f4fb55f3001beef1a9a36ab1
5
+ SHA512:
6
+ metadata.gz: e08a116ed02b6d2a38856b29e6e23489543bdedcfcf3ade4c0f33c58b835c31f0a1e9ddea0d78cabadca5f8a8829e7c8553b733cc3e39001b9462b15b3b766b1
7
+ data.tar.gz: f90c8c66c8f1390d5ed6ef4d41d7ea7268c356de0ee656e35e5fc312013a2308e942b21c2e6c610211d3d97aa5f03ac7fb00f09838375a344239cadd28b441be
@@ -0,0 +1,107 @@
1
+ # Lego NXT
2
+
3
+ Control a Lego NXT 2.0 brick using Ruby code. This library works by piping commands over a serialport connection to the brick, allowing you to write Ruby scripts to control your bot. This means you can use both the Bluetooth and USB serial ports provided on the brick as interfaces within your code.
4
+
5
+ This project used to be based on "ruby-nxt", and Tony Buser's subsequent rewrite "nxt". It is now a complete rewrite, based heavily in some parts on the aforesaid projects internally, but with a brand new external API that should prove cleaner and easier to work with.
6
+
7
+ This code implements direct command, as outlined in "Appendix 2-LEGO MINDSTORMS NXT Direct Commands.pdf". Not all functionality is implemented yet!
8
+
9
+ ## Getting Started
10
+
11
+ ### Connect to Your NXT Brick
12
+
13
+ In order to start coding with your NXT, you'll need to set up either a USB or Bluetooth connection to it. Follow one of the below sets of steps; if you go for a Bluetooth connection, you'll need to remember the `/dev/*` address you end up using, as you'll need to provide it when making a connection with this library.
14
+
15
+ ### Connecting Via USB
16
+
17
+ Simply plug in the NXT, and that's it! This library will take care of enumerating the USB host devices to find the NXT device for you, no effort required on your behalf!
18
+
19
+ #### Connecting Via Bluetooth
20
+
21
+ ##### Linux
22
+
23
+ Make sure you have the `bluez` package installed, which should include the `rfcomm` and `hcitool` commands. We start by searching for the MAC address of our NXT:
24
+
25
+ ```sh
26
+ $ hcitool scan
27
+ Scanning ...
28
+ 90-8E-E0-C1-2A-7B NXT
29
+ ```
30
+
31
+ Then open the `/etc/bluetooth/rfcomm.conf` file and add an entry as follows:
32
+
33
+ ```
34
+ rfcomm0 {
35
+ bind yes;
36
+ # Bluetooth address of the device
37
+ device 90-8E-E0-C1-2A-7B;
38
+ # RFCOMM channel for the connection
39
+ channel 1;
40
+ # Description of the connection
41
+ comment "NXT";
42
+ }
43
+ ```
44
+
45
+ If you're on a distro which has a Bluetoth daemon running automatically, you can simply restart it. For Ubuntu, that will look something like:
46
+
47
+ ```sh
48
+ $ sudo /etc/init.d/bluez-utils
49
+ ```
50
+
51
+ On other distros where you manage the Bluetooth daemon yourself, you'll need to do the bind calls yourself:
52
+
53
+ ```sh
54
+ $ sudo rfcomm bind /dev/rfcomm0 '90-8E-E0-C1-2A-7B'
55
+ ```
56
+
57
+ After that, the Bluetooth connection should be established. Check that by running the `rfcomm` command with no arguments:
58
+
59
+ ```sh
60
+ $ rfcomm
61
+ rfcomm0: 90-8E-E0-C1-2A-7B channel 1 clean
62
+ ```
63
+
64
+ The NXT should now be accessible from `/dev/rfcomm0`!
65
+
66
+ ##### Mac OS X
67
+
68
+ Turn on the NXT and make sure Bluetooth is turned on. Click the bluetooth icon in the menubar of your Mac and select "Setup bluetooth device". It will prompt you for a device type; choose "Any device". Select the NXT from the list and click continue.
69
+
70
+ The NXT will beep and ask for a passkey. Choose `1234` and press orange button. Enter the `1234` passcode on your Mac when promted. The NXT will beep again; press the orange button to use `1234` again.
71
+
72
+ Your Mac will then alert you that "There were no supported services found on your device". Ignore and click "Continue", followed by "Quit".
73
+
74
+ Now click the Bluetooth icon and select "Open bluetooth preferences"; you should see the NXT listed. Select it, then click "Edit Serial Ports".
75
+ It should show `NXT-DevB-1`; if not, click "Add", and use:
76
+
77
+ ```
78
+ Port Name: NXT-DevB-1
79
+ Device Service: Dev B
80
+ Port type: RS-232
81
+ ```
82
+
83
+ Click "Apply". The NXT should now be accessible from `/dev/tty.NXT-DevB-1`!
84
+
85
+ ## Documentation and Examples
86
+
87
+ The NXT project has been heavily documented using nice, clean, human readable markdown. YARD is used to generated the docs, and the options have been included in our `.yardopts` file, so simply run a YARD server to read them:
88
+
89
+ ```sh
90
+ $ yard server
91
+ ```
92
+
93
+ This documents the API, both internal and external. For bite-sized chunks of NXT code that is much more appropriate for beginners, [have a look at the examples](https://github.com/nathankleyn/nxt/tree/master/examples).
94
+
95
+ In addition to this, you might find the tests quite helpful. There are currently only RSpec unit tests, which can be found in the [`spec`](spec) directory; the plan is to add some decent feature tests soon.
96
+
97
+ ## License
98
+
99
+ The MIT License
100
+
101
+ Copyright (c) 2013 Nathan Kleyn
102
+
103
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
104
+
105
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
106
+
107
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rdoc/task'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RDoc::Task.new do |rdoc|
7
+ files = ['README.markdown', 'lib/**/*.rb']
8
+ rdoc.rdoc_files.add(files)
9
+ rdoc.main = 'README.markdown'
10
+ rdoc.title = 'ruby_events Docs'
11
+ rdoc.rdoc_dir = 'doc/rdoc'
12
+ rdoc.options << '--line-numbers'
13
+ end
14
+
15
+ RSpec::Core::RakeTask.new(:spec)
16
+
17
+ desc 'NXT related tasks'
18
+ namespace :nxt do
19
+ desc 'Detect a connected NXT brick within /dev.'
20
+ task :detect do
21
+ unless $DEV ||= ENV['NXT'] || ENV['DEV']
22
+ begin
23
+ devices = Dir['/dev/*NXT*']
24
+ if devices.size > 0
25
+ $DEV = devices[0]
26
+ puts "Detected a NXT brick at '#{$DEV}'."
27
+ else
28
+ puts 'Could not detect any connected NXT bricks.'
29
+ end
30
+ rescue
31
+ # FIXME: The /dev directory isn't there, possibly running on Windows.
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'active_support/inflector'
4
+
5
+ require 'nxt/patches/module'
6
+
7
+ require 'nxt/exceptions'
8
+
9
+ require 'nxt/interfaces/base'
10
+ require 'nxt/interfaces/usb'
11
+ require 'nxt/interfaces/serial_port'
12
+
13
+ require 'nxt/commands/base'
14
+ require 'nxt/commands/input'
15
+ require 'nxt/commands/output'
16
+ require 'nxt/commands/program'
17
+ require 'nxt/commands/sound'
18
+ require 'nxt/commands/tone'
19
+
20
+ require 'nxt/connectors/input/color'
21
+ require 'nxt/connectors/input/touch'
22
+ require 'nxt/connectors/input/ultrasonic'
23
+ require 'nxt/connectors/output/motor'
24
+
25
+ require 'nxt/nxt_brick'
26
+
27
+ require 'pry'
@@ -0,0 +1,36 @@
1
+ module NXT
2
+ module Command
3
+ module Base
4
+ private
5
+
6
+ COMMAND_TYPES = {
7
+ direct: 0x00,
8
+ system: 0x01,
9
+ reply: 0x02
10
+ }.freeze
11
+
12
+ PORTS = {
13
+ a: 0x00,
14
+ b: 0x01,
15
+ c: 0x02,
16
+ one: 0x00,
17
+ two: 0x01,
18
+ three: 0x02,
19
+ four: 0x03,
20
+ all: 0xFF
21
+ }
22
+
23
+ def send_and_receive(command_identifier, payload = [], response_required = true)
24
+ @interface.send_and_receive([
25
+ command_type,
26
+ command_identifier,
27
+ port_as_byte(self.port)
28
+ ] + payload, response_required)
29
+ end
30
+
31
+ def port_as_byte(port)
32
+ PORTS[port]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,89 @@
1
+ require 'nxt/utils/accessors'
2
+
3
+ module NXT
4
+ module Command
5
+ # An implementation of all the input related NXT commands:
6
+ #
7
+ # * SETINPUTMODE
8
+ # * GETINPUTVALUES
9
+ # * RESETINPUTSCALEDVALUE
10
+ #
11
+ # This class can also be used to talk to other third-party accessories
12
+ # connected in the input ports on the NXT brick.
13
+ module Input
14
+ include NXT::Command::Base
15
+ extend NXT::Utils::Accessors
16
+
17
+ COMMAND_IDENTIFIER = {
18
+ set_input_mode: 0x05,
19
+ get_input_values: 0x07,
20
+ reset_input_scaled_value: 0x08
21
+ }.freeze
22
+
23
+ # The sensor type enum. This is a list of possible values when setting the
24
+ # sensor type byte.
25
+ #
26
+ # Reference: Appendix 2, Page 7
27
+ SENSOR_TYPE = {
28
+ no_sensor: 0x00,
29
+ switch: 0x01,
30
+ temperature: 0x02,
31
+ reflection: 0x03,
32
+ angle: 0x04,
33
+ light_active: 0x05,
34
+ light_inactive: 0x06,
35
+ sound_db: 0x07,
36
+ sound_dba: 0x08,
37
+ custom: 0x09,
38
+ lowspeed: 0x0A,
39
+ lowspeed_9v: 0x0B,
40
+ no_of_sensor_types: 0x0C
41
+ }.freeze
42
+
43
+ # The sensor mode enum. This is a list of possible values when setting the
44
+ # sensor mode byte.
45
+ #
46
+ # Reference: Appendix 2, Page 7
47
+ SENSOR_MODE = {
48
+ raw: 0x00,
49
+ boolean: 0x20,
50
+ transition_cnt: 0x40,
51
+ period_counter: 0x60,
52
+ pct_full_scale: 0x80,
53
+ celsius: 0xA0,
54
+ fahrenheit: 0xC0,
55
+ angle_steps: 0xE0,
56
+ slope: 0x1F,
57
+ mode_mask: 0XE0
58
+ }.freeze
59
+
60
+ attr_combined_accessor :sensor_type, :no_sensor
61
+ attr_combined_accessor :sensor_mode, :raw
62
+
63
+ attr_setter :sensor_type, is_key_in: SENSOR_TYPE
64
+ attr_setter :sensor_mode, is_key_in: SENSOR_MODE
65
+
66
+ def command_type
67
+ COMMAND_TYPES[:direct]
68
+ end
69
+
70
+ def set_input_mode(response_required = false)
71
+ send_and_receive(COMMAND_IDENTIFIER[:set_input_mode], [
72
+ self.power,
73
+ SENSOR_TYPE[self.sensor_type],
74
+ SENSOR_MODE[self.sensor_mode]
75
+ ], response_required)
76
+ end
77
+
78
+ def get_input_values
79
+ # TODO: Parse this response and return hash or something similar.
80
+ send_and_receive(COMMAND_IDENTIFIER[:get_input_values])
81
+ end
82
+
83
+ def reset_input_scaled_value
84
+ # TODO: Parse this response and return hash or something similar.
85
+ send_and_receive(COMMAND_IDENTIFIER[:reset_input_scaled_value])
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,110 @@
1
+ require 'nxt/utils/accessors'
2
+
3
+ module NXT
4
+ module Command
5
+ # An implementation of all the output related NXT commands:
6
+ #
7
+ # * SETOUTPUTSTATE
8
+ # * GETOUTPUTSTATE
9
+ #
10
+ # This is used predominantly to interface with the servo-motor connectors
11
+ # that come prepackaged with NXT kits.
12
+ #
13
+ # This class can also be used to talk to other third-party accessories
14
+ # connected in the output ports on the NXT brick.
15
+ module Output
16
+ include NXT::Command::Base
17
+ extend NXT::Utils::Accessors
18
+
19
+ COMMAND_IDENTIFIER = {
20
+ set_output_state: 0x04,
21
+ get_output_state: 0x06
22
+ }.freeze
23
+
24
+ # The mode enum. This is a list of possible values when setting the mode
25
+ # byte.
26
+ #
27
+ # Reference: Appendix 2, Page 6
28
+ MODE = {
29
+ # Motor will rotate freely.
30
+ # NOTE: This is not documented in the Appendixes.
31
+ coast: 0x00,
32
+ # Turn on the specified motor.
33
+ motor_on: 0x01,
34
+ # Use run/brake instead of run/float in PWM. This means the voltage is
35
+ # not allowed to float between PWM pulses, improving accuracy at the
36
+ # expense of greater power usage.
37
+ brake: 0x02,
38
+ # Turns on the regulation. This is required when setting a regulation
39
+ # mode setting.
40
+ regulated: 0x04
41
+ }.freeze
42
+
43
+ # The regulation mode enum. This is a list of possible values when
44
+ # setting the regulation mode byte.
45
+ #
46
+ # Reference: Appendix 2, Page 6
47
+ REGULATION_MODE = {
48
+ # No regulation will be enabled.
49
+ idle: 0x00,
50
+ # Power control will be enabled on specific output.
51
+ motor_speed: 0x01,
52
+ # Synchronisation will be enabled. This requires two output ports to
53
+ # have this enabled before it will work.
54
+ motor_sync: 0x02
55
+ }.freeze
56
+
57
+ # The run state enum. This is a list of possible values when setting the
58
+ # run state byte.
59
+ #
60
+ # Reference: Appendix 2, Page 6
61
+ RUN_STATE = {
62
+ # Output will be idle.
63
+ idle: 0x00,
64
+ # Output will ramp-up to the desired speed.
65
+ ramp_up: 0x10,
66
+ # Output will be running.
67
+ running: 0x20,
68
+ # Output will ramp-down to the desired speed.
69
+ ramp_down: 0x40
70
+ }.freeze
71
+
72
+ attr_combined_accessor :power, 75
73
+ attr_combined_accessor :mode, :motor_on
74
+ attr_combined_accessor :regulation_mode, :idle
75
+ attr_combined_accessor :run_state, :running
76
+ attr_combined_accessor :tacho_limit, 0
77
+
78
+ attr_setter :power, is: Integer
79
+ attr_setter :mode, is_key_in: MODE
80
+ attr_setter :regulation_mode, is_key_in: REGULATION_MODE
81
+ attr_setter :run_state, is_key_in: RUN_STATE
82
+ attr_setter :tacho_limit, is: Integer
83
+
84
+ def command_type
85
+ COMMAND_TYPES[:direct]
86
+ end
87
+
88
+ def set_output_state(response_required = false)
89
+ # Pack this value into a 32-bit unsigned little-endian binary string,
90
+ # then unpack it into 4 8 bit unsigned integer chunks. We are
91
+ # converting the passed in value to a little endian, unsigned long
92
+ # value.
93
+ tacho_limit_as_bytes = [self.tacho_limit].pack('V').unpack('C4')
94
+
95
+ send_and_receive(COMMAND_IDENTIFIER[:set_output_state], [
96
+ self.power,
97
+ MODE[self.mode],
98
+ REGULATION_MODE[self.regulation_mode],
99
+ 0, # turn ratio
100
+ RUN_STATE[self.run_state]
101
+ ] + tacho_limit_as_bytes, response_required)
102
+ end
103
+
104
+ def get_output_state
105
+ # TODO: Parse this response and return hash or something similar.
106
+ send_and_receive(COMMAND_IDENTIFIER[:get_output_state])
107
+ end
108
+ end
109
+ end
110
+ end
File without changes
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ module NXT
2
+ module Connector
3
+ module Input
4
+ class Color
5
+ def initialize(port)
6
+ @port = port
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module NXT
2
+ module Connector
3
+ module Input
4
+ class Touch
5
+ def initialize(port)
6
+ @port = port
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end