rintcore 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 25584e4760c4e1b347a2bd718be2d15ea3e6a3a8
4
- data.tar.gz: dc98357e1b8995492a12f18622dbfae6b0bab95b
5
- SHA512:
6
- metadata.gz: 630a045a5a1c463447b5d84c712bf313b9c0a14d080c1386d7b687963b7364ab36c0b023a079c4a8294094e9cdb7a2c7634087615a9ac5f66a4be021a9edc48a
7
- data.tar.gz: 679a641143bc7ffe4e3d95e80448bb575c45c16e5b8bbcbbac3729ce27c3bca07186cdf6eb7e7be24f4a98dd52638490f08e3855cc3105a6a3f65e64b4a780f6
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f672b74c95d07cfb62eb006d5209065f57c51bd2
4
+ data.tar.gz: 64b07a334627117937c29c59d863b0371df74160
5
+ SHA512:
6
+ metadata.gz: 874f9595f51204151351828eedcb403d679d608a8b04b611283a476a75872fe8711da16c4b25031628278425ce85d96080a69afadf0acff08622da80cb58d269
7
+ data.tar.gz: 84da65e8d7d6ed60c02c06e4b3dcba01d9ce3cd9479961105d0690769d19d2006c477f471069b9362c9958a8cd6f0dcafcb74d7b2a38ad18b4a7f2c7e540145e
data/.gitignore CHANGED
@@ -15,4 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- .ruby-version
18
+ .ruby-version
19
+ profiling.txt
data/README.md CHANGED
@@ -21,7 +21,8 @@ printer.port = '/dev/ttyUSB0' # Set to /dev/ttyACM0 by default
21
21
  printer.baud = 250000 # Set to 115200 by default
22
22
  printer.callbacks[:temperature] = Proc.new { |line| puts(line) }
23
23
  printer.connect!
24
- printer.start_print gcode```
24
+ printer.start_print gcode
25
+ ```
25
26
 
26
27
  ### TODO
27
28
  Documentation and spec writing.
data/bin/rintcore CHANGED
@@ -1,4 +1,7 @@
1
1
  #!env ruby
2
+ lib = File.expand_path('../../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
2
5
  require 'rubygems'
3
6
  require 'rint_core/cli'
4
7
 
data/lib/rint_core.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "rint_core/version"
2
2
 
3
+ # A collection of classes and modules for parsing, analyzing and sending GCode to a RepRap 3D printer.
3
4
  module RintCore
4
- # Your code goes here...
5
+
5
6
  end
data/lib/rint_core/cli.rb CHANGED
@@ -5,41 +5,54 @@ require 'thor'
5
5
  require 'active_support/core_ext/object/blank'
6
6
 
7
7
  module RintCore
8
+ # Provides command line interfaces for interacting with RintCore's classes.
8
9
  class Cli < Thor
9
10
  map '-a' => :analyze, '-p' => :print
10
11
 
11
12
  desc 'analyze FILE', 'Get statistics about the given GCode file.'
12
13
  method_option :decimals, default: 2, aliases: '-d', type: :numeric, desc: 'The number of decimal places given for measurements.'
14
+ # Analyze the given file, also sets the @object instance variable to a {RintCore::GCode::Object}.
15
+ # @param file [String] path to a GCode file on the system.
16
+ # @return [String] statistics about the given GCode file.
13
17
  def analyze(file)
14
18
  unless RintCore::GCode::Object.is_file?(file)
15
19
  puts "Non-exsitant file: #{file}"
16
20
  exit
17
21
  end
18
22
  @object = RintCore::GCode::Object.new(RintCore::GCode::Object.get_file(file))
23
+
24
+ unless @object.present?
25
+ puts "Non-GCode or empty file: #{file}"
26
+ exit
27
+ end
28
+
19
29
  decimals = options[:decimals]
20
30
  decimals ||= 2
21
- output = <<EOS
22
- Dimensions:
23
- \tX: #{@object.x_min.round(decimals)} - #{@object.x_max.round(decimals)} (#{@object.width.round(decimals)}mm)
24
- \tY: #{@object.y_min.round(decimals)} - #{@object.y_max.round(decimals)} (#{@object.depth.round(decimals)}mm)
25
- \tZ: #{@object.z_min.round(decimals)} - #{@object.z_max.round(decimals)} (#{@object.height.round(decimals)}mm)
26
- Total Travel:
27
- \tX: #{@object.x_travel.round(decimals)}mm
28
- \tY: #{@object.y_travel.round(decimals)}mm
29
- \tZ: #{@object.z_travel.round(decimals)}mm
30
- Filament used: #{@object.filament_used.round(decimals)}mm
31
- Number of layers: #{@object.layers}
32
- #{@object.raw_data.length} lines / #{@object.lines.length} commands
33
- EOS
34
- puts output
31
+
32
+ puts "Dimensions:\n"\
33
+ "\tX: #{@object.x_min.round(decimals)} - #{@object.x_max.round(decimals)} (#{@object.width.round(decimals)}mm)\n"\
34
+ "\tY: #{@object.y_min.round(decimals)} - #{@object.y_max.round(decimals)} (#{@object.depth.round(decimals)}mm)\n"\
35
+ "\tZ: #{@object.z_min.round(decimals)} - #{@object.z_max.round(decimals)} (#{@object.height.round(decimals)}mm)\n"\
36
+ "Total Travel:\n"\
37
+ "\tX: #{@object.x_travel.round(decimals)}mm\n"\
38
+ "\tY: #{@object.y_travel.round(decimals)}mm\n"\
39
+ "\tZ: #{@object.z_travel.round(decimals)}mm\n"\
40
+ "Filament used:\n"
41
+ @object.filament_used.each_with_index do |filament,extruder|
42
+ puts "\tExtruder #{extruder+1}: #{filament.round(decimals)}mm"
43
+ end
44
+ puts "Number of layers: #{@object.layers}\n"\
45
+ "#{@object.raw_data.length} lines / #{@object.lines.length} commands"
35
46
  end
36
47
 
37
48
  desc 'print FILE', 'Print the given GCode file.'
38
49
  method_option :port, aliases: '-p', type: :string, desc: 'The port that the printer is connected to.'
39
50
  method_option :baud, aliases: '-b', type: :numeric, desc: 'The baud rate at which the printer communicates at.'
40
51
  method_option :loud, aliases: '-l', default: false, type: :boolean, desc: 'Output additional info (temperature, progress, etc.)'
52
+ # Analyzes, then prints the given file.
53
+ # @param file [String] path to a GCode file on the system.
54
+ # @return [String] value of the disconnect callback in this function.
41
55
  def print(file)
42
- analyze(file)
43
56
  port = options[:port]
44
57
  baud = options[:baud]
45
58
  baud = baud.to_i unless baud.blank?
@@ -56,6 +69,7 @@ EOS
56
69
  baud = baud.to_i unless baud.blank?
57
70
  baud = nil unless RintCore::Printer.baud_rates.include?(baud)
58
71
  end
72
+ analyze(file)
59
73
  printer = RintCore::Printer.new
60
74
  printer.port = port
61
75
  printer.baud = baud
@@ -72,7 +86,6 @@ EOS
72
86
  until printer.online?
73
87
  sleep(printer.long_sleep)
74
88
  end
75
- start_time = Time.now
76
89
  printer.start_print(@object)
77
90
  while printer.printing?
78
91
  printer.send_now(RintCore::GCode::Codes::GET_EXT_TEMP)
@@ -5,6 +5,7 @@ require 'rint_core/driver/queueing'
5
5
  require 'rint_core/driver/operations'
6
6
 
7
7
  module RintCore
8
+ # Conatians the elements of the printer driver.
8
9
  module Driver
9
10
  include RintCore::Driver::OperatingSystem
10
11
  include RintCore::Driver::State
@@ -12,6 +13,7 @@ module RintCore
12
13
  include RintCore::Driver::Queueing
13
14
  include RintCore::Driver::Operations
14
15
 
16
+ # Calls the initialization functions of the submodules in the correct order
15
17
  def initialize_driver
16
18
  initialize_state
17
19
  initialize_queueing
@@ -1,6 +1,18 @@
1
1
  module RintCore
2
2
  module Driver
3
+ # Utilities for performing OS level tasks
3
4
  module OperatingSystem
5
+
6
+ # Return name of OS as a symbol.
7
+ # @return [Symbol] name of OS as symbol.
8
+ def get_os
9
+ return :linux if /linux/ =~ RUBY_PLATFORM
10
+ return :mac if /darwin/ =~ RUBY_PLATFORM
11
+ return :windows if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
12
+ return :unknown
13
+ end
14
+
15
+ private
4
16
  def control_ttyhup(port, disable_hup)
5
17
  if get_os == :linux
6
18
  if disable_hup
@@ -18,13 +30,6 @@ module RintCore
18
30
  def disable_hup(port)
19
31
  control_ttyhup(port, false)
20
32
  end
21
-
22
- def get_os
23
- return :linux if /linux/ =~ RUBY_PLATFORM
24
- return :mac if /darwin/ =~ RUBY_PLATFORM
25
- return :windows if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
26
- return :unknown
27
- end
28
33
  end
29
34
  end
30
35
  end
@@ -5,8 +5,11 @@ require 'active_support/core_ext/object/blank'
5
5
 
6
6
  module RintCore
7
7
  module Driver
8
+ # Provides the raw functionality of the printer.
8
9
  module Operations
9
10
 
11
+ # Connects to the printer.
12
+ # @return [Undefined] returns the value of the connect callback.
10
13
  def connect!
11
14
  return false if connected?
12
15
  if config.port.present? && config.baud.present?
@@ -20,6 +23,8 @@ module RintCore
20
23
  end
21
24
  end
22
25
 
26
+ # Disconnects to the printer.
27
+ # @return [Undefined] returns the value of the disconnect callback.
23
28
  def disconnect!
24
29
  if connected?
25
30
  if @listening_thread
@@ -36,29 +41,45 @@ module RintCore
36
41
  config.callbacks[:disconnect].call if config.callbacks[:disconnect].present?
37
42
  end
38
43
 
44
+ # Resets the printer.
45
+ # @return [false] if not connected.
46
+ # @return [1] if printer was reset.
39
47
  def reset!
48
+ return false unless connected?
40
49
  @connection.dtr = 0
41
50
  sleep(config.long_sleep)
42
51
  @connection.dtr = 1
43
52
  end
44
53
 
54
+ # Pauses printing.
55
+ # @return [Undefined] returns the value of the pause callback.
45
56
  def pause!
46
57
  return false unless printing?
47
58
  @paused = true
48
- not_printing!
49
- @print_thread.join
59
+ until @print_thread.alive?
60
+ sleep(config.sleep_time)
61
+ end
62
+ #@print_thread.join
50
63
  @print_thread = nil
64
+ not_printing!
51
65
  config.callbacks[:pause].call if config.callbacks[:pause].present?
52
66
  end
53
67
 
68
+ # Resumes printing.
69
+ # @return [Undefined] returns the value of the resume callback.
54
70
  def resume!
55
71
  return false unless paused?
56
- paused!
72
+ @paused = false
57
73
  printing!
58
74
  @print_thread = Thread.new{print!()}
59
75
  config.callbacks[:resume].call if config.callbacks[:resume].present?
60
76
  end
61
77
 
78
+ # Sends the given command to the printer, if printing, will send command after print completion.
79
+ # @param command [String] the command to send to the printer.
80
+ # @param wait [Fixnum] number of times to sleep ({RintCore::Printer.sleep_time}).
81
+ # @param priority [Boolean] defines if command is a priority.
82
+ # @todo finalize return value.
62
83
  def send(command, wait = 0, priority = false)
63
84
  if online?
64
85
  if printing?
@@ -80,10 +101,18 @@ module RintCore
80
101
  end
81
102
  end
82
103
 
104
+ # Sends command to the printer immediately by placing it in the priority queue.
105
+ # @see send
83
106
  def send_now(command, wait = 0)
84
107
  send(command, wait, true)
85
108
  end
86
109
 
110
+ # Starts a print.
111
+ # @param data [RintCore::GCode::Object] prints the given object.
112
+ # @param data [Array] executes the each command in the array.
113
+ # @param start_index [Fixnum] starts printing from the given index (used by {#pause!} and {#resume!}).
114
+ # @return [false] if printer isn't ready to print or already printing.
115
+ # @return [true] if print has been started.
87
116
  def start_print(data, start_index = 0)
88
117
  return false unless can_print?
89
118
  data = data.lines if data.class == RintCore::GCode::Object
@@ -104,7 +133,7 @@ private
104
133
  def initialize_operations
105
134
  @connection = nil
106
135
  @listening_thread = nil
107
- @printing_thread = nil
136
+ @print_thread = nil
108
137
  @full_history = []
109
138
  end
110
139
 
@@ -121,6 +150,7 @@ private
121
150
  config.callbacks[:start].call if config.callbacks[:start].present?
122
151
  while online? && printing? do
123
152
  advance_queue
153
+ return true if paused?
124
154
  end
125
155
  @print_thread.join
126
156
  @print_thread = nil
@@ -3,8 +3,10 @@ require 'active_support/core_ext/object/blank'
3
3
 
4
4
  module RintCore
5
5
  module Driver
6
+ # Handles the parsing of printer responses and formats commands sent to the printer.
6
7
  module Parsing
7
8
 
9
+ private
8
10
  def format_command(command)
9
11
  (command.strip + "\n").split(RintCore::GCode::Codes::COMMENT_SYMBOL).first.encode(config.encoding)
10
12
  end
@@ -23,9 +25,9 @@ module RintCore
23
25
  return :error if line.include?(config.error_response)
24
26
  return :debug if line.include?(config.debug_response)
25
27
  return :online if line.start_with?(*config.online_response)
26
- return :valid if line.start_with?(*config.good_response) && !line.include?(config.temperature_response)
27
- return :temperature_response if line.start_with?(*config.good_response) && line.include?(config.temperature_response)
28
- return :temperature if line.include?(config.temperature_response)
28
+ return :valid if line.start_with?(*config.good_response) && !line.include?(*config.temperature_response)
29
+ return :temperature_response if line.start_with?(*config.good_response) && line.include?(*config.temperature_response)
30
+ return :temperature if line.include?(*config.temperature_response)
29
31
  return :resend if line.start_with?(*config.resend_response)
30
32
  return :invalid
31
33
  end
@@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank'
3
3
 
4
4
  module RintCore
5
5
  module Driver
6
+ # Controls the print queue and manages the sending of commands while printing.
6
7
  module Queueing
7
8
 
8
9
  private
@@ -49,17 +50,14 @@ private
49
50
  end
50
51
 
51
52
  def run_priority_queue
52
- unless @priority_queue.blank?
53
- send!(@priority_queue.shift)
54
- # clear_to_send!
55
- end
53
+ send!(@priority_queue.shift) if @priority_queue.present?
56
54
  end
57
55
 
58
56
  def run_main_queue
59
57
  if !paused? && @queue_index < @main_queue.length
60
58
  current_line = @main_queue[@queue_index]
61
- current_line = current_line.to_s unless current_line.class == String
62
- unless current_line.blank?
59
+ current_line = apply_multipliers(current_line) unless current_line.class == String
60
+ if current_line.present?
63
61
  send!(current_line, @line_number, true)
64
62
  @line_number += 1
65
63
  end
@@ -68,6 +66,13 @@ private
68
66
  end
69
67
  end
70
68
 
69
+ def apply_multipliers(line)
70
+ line.speed_multiplier = config.speed_multiplier if config.speed_multiplier.present?
71
+ line.extrusion_multiplier = config.extrusion_multiplier if config.extrusion_multiplier.present?
72
+ line.travel_multiplier = config.travel_multiplier if config.travel_multiplier.present?
73
+ line.to_s
74
+ end
75
+
71
76
  end
72
77
  end
73
78
  end
@@ -3,32 +3,35 @@ require 'active_support/core_ext/object/blank'
3
3
 
4
4
  module RintCore
5
5
  module Driver
6
+ # keeps track of the driver's state
6
7
  module State
7
8
 
9
+ # Checks if the printer can start a print.
10
+ # @return [Boolean] true if printer is ready to print, false otherwise.
8
11
  def can_print?
9
12
  connected? && online? && !printing?
10
13
  end
11
14
 
15
+ # Checks if printer is connected.
16
+ # @return [Boolean] true if serial port connection is present, false otherwise.
12
17
  def connected?
13
18
  @connection.present?
14
19
  end
15
20
 
16
- def clear_to_send?
17
- @clear && online?
18
- end
19
-
20
- def listen_can_continue?
21
- !@stop_listening && connected?
22
- end
23
-
21
+ # Checks if the printer is online.
22
+ # @return [Boolean] true if online, false otherwise.
24
23
  def online?
25
24
  connected? && @online
26
25
  end
27
26
 
27
+ # Checks if printing is paused.
28
+ # @return [Boolean] true if pause, false otherwise.
28
29
  def paused?
29
30
  @paused
30
31
  end
31
32
 
33
+ # Checks if the printer is currently printing.
34
+ # @return [Boolean] true if printing, false otherwise.
32
35
  def printing?
33
36
  @printing
34
37
  end
@@ -43,10 +46,18 @@ private
43
46
  @stop_listening = false
44
47
  end
45
48
 
49
+ def clear_to_send?
50
+ @clear && online?
51
+ end
52
+
46
53
  def clear_to_send!
47
54
  @clear = true
48
55
  end
49
56
 
57
+ def listen_can_continue?
58
+ !@stop_listening && connected?
59
+ end
60
+
50
61
  def not_clear_to_send!
51
62
  @clear = false
52
63
  end
@@ -1,5 +1,6 @@
1
1
  require 'rint_core/g_code/codes'
2
2
  module RintCore
3
+ # Contains classes for analyzing and parsing GCode.
3
4
  module GCode
4
5
 
5
6
  end
@@ -1,49 +1,105 @@
1
+ #require 'active_support/core_ext/string/inflections'
2
+
1
3
  module RintCore
2
4
  module GCode
5
+ # Contains GCodes.
3
6
  module Codes
7
+ # Do a rapid move.
4
8
  RAPID_MOVE = 'G0'
9
+ # Do a move at the given or previously given acceleration (F).
5
10
  CONTROLLED_MOVE = 'G1'
11
+ # Pause for (P) a given number of milliseconds.
6
12
  DWELL = 'G4'
13
+ # Set head offset (for multiple extruders).
7
14
  HEAD_OFFSET = 'G10'
15
+ # Set units in following commands to be imperial.
8
16
  USE_INCHES = 'G20'
17
+ # Set units in following commands to be metric (default).
9
18
  USE_MILLIMETRES = 'G21'
19
+ # Home axes.
10
20
  HOME = 'G28'
21
+ # Set following commands to use absolute coordinates.
11
22
  ABS_POSITIONING = 'G90'
23
+ # Set following commands to use relative coordinates.
12
24
  REL_POSITIONING = 'G91'
25
+ # Set current position.
13
26
  SET_POSITION = 'G92'
27
+ # Finish moves, then shutdown (reset required to wake machine).
14
28
  STOP = 'M0'
29
+ # Finish moves the shutdown (sending commands will wake machine).
15
30
  SLEEP = 'M1'
31
+ # Enable motors.
16
32
  ENABLE_MOTORS = 'M17'
33
+ # Disable motors.
17
34
  DISABLE_MOTORS = 'M18'
35
+ # List contents of SD card.
18
36
  LIST_SD = 'M20'
37
+ # Initialize SD card (needed if card wasn't present at bootup).
19
38
  INIT_SD = 'M21'
39
+ # Release SD (safe removal of SD).
20
40
  RELEASE_SD = 'M22'
41
+ # Select SD file (require to print from SD).
21
42
  SELECT_SD_FILE = 'M23'
43
+ # Print selected file from SD (requires file to be selected).
22
44
  START_SD_PRINT = 'M24'
45
+ # Pause printing from SD card.
23
46
  PAUSE_SD_PRINT = 'M25'
47
+ # Set SD position in bytes.
24
48
  SET_SD_POSITION = 'M26'
49
+ # Report SD printing status.
25
50
  SD_PRINT_STATUS = 'M27'
51
+ # Write following GCodes to given file (requires 8.3 file name).
26
52
  START_SD_WRITE = 'M28'
53
+ # Signal end of SD write, following commands will be executed as normal.
27
54
  STOP_SD_WRITE = 'M29'
55
+ # Power on.
28
56
  POWER_ON = 'M80'
57
+ # Power off.
29
58
  POWER_OFF = 'M81'
59
+ # Set extrusion units in following commands to absolute coordinates.
30
60
  ABS_EXT_MODE = 'M82'
61
+ # Set extrusion units in following commands to relative coordinates.
31
62
  REL_EXT_MODE = 'M83'
63
+ # Trun off powered holding of motors when idle.
32
64
  IDLE_HOLD_OFF = 'M84'
65
+ # Set Extruder tmeperature and return control to host.
33
66
  SET_EXT_TEMP_NW = 'M104'
67
+ # Report temperatures
34
68
  GET_EXT_TEMP = 'M105'
69
+ # Trun fans on to given value (S, 0-255).
35
70
  FAN_ON = 'M106'
71
+ # Turn off fans
36
72
  FAN_OFF = 'M107'
73
+ # Set extruder temperature and wait for it to reach temperature.
37
74
  SET_EXT_TEMP_W = 'M109'
75
+ # Reset the line number for the following commands.
38
76
  SET_LINE_NUM = 'M110'
77
+ # Emergency stop.
39
78
  EMRG_STOP = 'M112'
79
+ # Report position.
40
80
  GET_POSITION = 'M114'
81
+ # Report firmware details.
41
82
  GET_FW_DETAILS = 'M115'
83
+ # Wait for temperature (all extruders and bed) to reach the temerature they were set to.
42
84
  WIAT_FOR_TEMP = 'M116'
43
- # ... Left out codes that probably won't be used
85
+ # Set bed temperature and return control to host.
44
86
  SET_BED_TEMP_NW = 'M140'
87
+ # Set bed temperature and wait for it to reach temperature.
45
88
  SET_BED_TEMP_W = 'M190'
89
+ # Comment symbol
90
+ # @todo Move this to a configurable option.
46
91
  COMMENT_SYMBOL = ';'
92
+
93
+ # An array of the constant's values.
94
+ # @return [Array] of GCode commands.
95
+ # REMOVED: major performance issues
96
+ # def available_commands
97
+ # commands = []
98
+ # RintCore::GCode::Codes.constants.each do |constant|
99
+ # commands << ('RintCore::GCode::Codes::'+constant.to_s).constantize
100
+ # end
101
+ # commands
102
+ # end
47
103
  end
48
104
  end
49
105
  end