-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EV3 Bluetooth connection and tone working
- Loading branch information
1 parent
682a366
commit 45b31b5
Showing
15 changed files
with
481 additions
and
16 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ _yardoc | |
coverage | ||
doc/ | ||
lib/bundler/man | ||
local_helpers | ||
pkg | ||
rdoc | ||
spec/reports | ||
|
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 |
---|---|---|
@@ -1 +1,10 @@ | ||
require "bundler/gem_tasks" | ||
|
||
desc "Open an irb session preloaded with this library" | ||
task :console do | ||
sh "irb -rubygems -I lib -r ev3.rb" | ||
end | ||
|
||
Dir["tasks/**/*.rake"].each do |file| | ||
load(file) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
require "ev3/brick" | ||
require "ev3/commands" | ||
require "ev3/constants" | ||
require "ev3/version" | ||
|
||
module EV3 | ||
# Helper to reload the gem in dev. | ||
def self.reload! | ||
$".grep(/lib\/ev3/).each{ |f| load(f) if File.exists?(f) } | ||
end | ||
end | ||
|
||
class Integer | ||
# Convert to EV3 variable data | ||
def to_ev3_data | ||
[0b1000_0011] + self.to_little_endian_byte_array(4) | ||
end | ||
|
||
# Convert the number to an array of little endian bytes | ||
# | ||
# @param [Integer] number_of_bytes that should represent the integer | ||
def to_little_endian_byte_array(number_of_bytes = 4) | ||
raise NotImplementedError if self < 0 | ||
bytes = [] | ||
tmp_number = self | ||
while tmp_number.abs > 0 | ||
bytes << (tmp_number & 0xFF) | ||
tmp_number = tmp_number >> 8 | ||
end | ||
bytes = bytes[0..(number_of_bytes - 1)] | ||
until bytes.size == number_of_bytes | ||
bytes << 0 | ||
end | ||
bytes | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module EV3 | ||
class Brick | ||
attr_reader :connection | ||
|
||
# Create a new brick connection | ||
# | ||
# @param [instance subclassing Connections::Base] connection to the brick | ||
def initialize(connection) | ||
@connection = connection | ||
end | ||
|
||
# Connect to the EV3 | ||
def connect | ||
self.connection.connect | ||
end | ||
|
||
# Play a short beep on the EV3 | ||
def beep | ||
self.execute(Commands::SoundTone.new) | ||
end | ||
|
||
# Play a tone on the EV3 using the specified options | ||
def play_tone(volume, frequency, duration) | ||
command = Commands::SoundTone.new(volume, frequency, duration) | ||
self.execute(command) | ||
end | ||
|
||
# Execute the command | ||
# | ||
# @param [instance subclassing Commands::Base] command to execute | ||
def execute(command) | ||
self.connection.write(command) | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
require 'ev3/commands/base' | ||
|
||
require 'ev3/commands/sound_tone' |
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 @@ | ||
module EV3 | ||
module Commands | ||
class Base | ||
attr_accessor :sequence_number | ||
|
||
def initialize(local_variables = 0, global_variables = 0) | ||
@local_variables = local_variables | ||
@global_variables = global_variables | ||
|
||
# Sequence number is currently unused, so I am setting it to zero | ||
self.sequence_number = 0 | ||
@bytes = [] | ||
end | ||
|
||
# Converts the command to an array of bytes to send to the EV3 | ||
def to_bytes | ||
message = self.sequence_number.to_little_endian_byte_array(2) + variable_size_bytes + @bytes.clone | ||
|
||
# The message is proceeded by the message length | ||
message.size.to_little_endian_byte_array(2) + message | ||
end | ||
|
||
# Append a byte or multiple bytes to the command | ||
# | ||
# @param [Integer, Array<Integer>] byte_or_bytes to append to the command | ||
def <<(byte_or_bytes) | ||
bytes = byte_or_bytes.is_a?(Array) ? byte_or_bytes : [byte_or_bytes] | ||
bytes.each { |byte| @bytes << byte } | ||
end | ||
|
||
# String representation of the command | ||
def to_s | ||
"#{self.class.name}: #{self.to_bytes.map{|byte| byte.to_s(16)}.join(', ')}" | ||
end | ||
|
||
# Raises an exception if the value isn't found in the range | ||
# | ||
# @param [Integer] value to check against the range | ||
# @param [String] name of the variable, for the exception message | ||
# @param [Range(Integer)] range the value should be in | ||
def validate_range!(value, variable_name, range) | ||
raise(ArgumentError, "#{variable_name} should be between #{range.min} and #{range.max}") unless range.include?(value) | ||
end | ||
|
||
private | ||
|
||
def variable_size_bytes | ||
# Byte 6 Byte 5 | ||
# 76543210 76543210 | ||
# -------- -------- | ||
# llllllgg gggggggg | ||
# | ||
# gg gggggggg Global variables [0..MAX_COMMAND_GLOBALS] | ||
# llllll Local variables [0..MAX_COMMAND_LOCALS] | ||
[ | ||
(@global_variables & 0xFF), | ||
(((@local_variables << 2) & 0b1111_1100) | (((@global_variables >> 8) & 0b0000_0011))) | ||
] | ||
end | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module EV3 | ||
module Commands | ||
class SoundTone < Base | ||
# Creates a new sound tone command | ||
# | ||
# @param [Integer] Volume of the sound [0..100] | ||
# @param [Integer] Frequency in Hertz [0..50,000] | ||
# @param [Integer] Duration in miliseconds [0..1 Year] | ||
def initialize(volume = 50, frequency = 1000, duration = 500) | ||
super() | ||
|
||
validate_range!(volume, 'volume', 0..100) | ||
validate_range!(frequency, 'frequency', 0..50_000) # 0 - 50,000 Hz | ||
validate_range!(duration, 'duration', 0..(1000 * 60 * 60 * 24 * 365)) # Up to a year | ||
|
||
self << CommandType::DIRECT_COMMAND_NO_REPLY | ||
self << ByteCodes::SOUND | ||
self << SoundSubCodes::TONE | ||
self << volume.to_ev3_data | ||
self << frequency.to_ev3_data | ||
self << duration.to_ev3_data | ||
end | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module EV3 | ||
module Connections | ||
class Base | ||
|
||
def connect | ||
raise NotImplementedError | ||
end | ||
|
||
def write(command) | ||
raise NotImplementedError | ||
end | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
require 'ev3/connections/base' | ||
require 'serialport' | ||
|
||
module EV3 | ||
module Connections | ||
|
||
class Bluetooth < Base | ||
attr_reader :device | ||
|
||
# Create a new bluetooth device | ||
# | ||
# @param [String] device on the Mac, a dev device, and on windows a com port | ||
def initialize(device = '/dev/tty.EV3-SerialPort') | ||
@device = device | ||
@commands_sent = 0 | ||
end | ||
|
||
def connect | ||
@serial_port = ::SerialPort.new(@device, 57600, 8, 1, SerialPort::NONE) | ||
@serial_port.flow_control = ::SerialPort::HARD | ||
@serial_port.read_timeout = 5000 | ||
end | ||
|
||
# Set the sequence number on the command and write it to the bluetooth connection | ||
# | ||
# @param [instance subclassing Commands::Base] command to execute | ||
def write(command) | ||
command.sequence_number = @commands_sent | ||
command.to_bytes.each do |b| | ||
@serial_port.putc b | ||
end | ||
@commands_sent += 1 | ||
end | ||
end | ||
|
||
end | ||
end |
Oops, something went wrong.