rintcore 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,73 @@
1
+ require 'rint_core/g_code/codes'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ module RintCore
5
+ module Driver
6
+ module Queueing
7
+
8
+ private
9
+
10
+ def initialize_queueing
11
+ @main_queue = []
12
+ @priority_queue = []
13
+ @queue_index = 0
14
+ @line_number = 0
15
+ @resend_from = -1
16
+ @machine_history = []
17
+ end
18
+
19
+ def advance_queue
20
+ return false unless online? && printing?
21
+ until clear_to_send? do
22
+ sleep(config.sleep_time)
23
+ end
24
+ not_clear_to_send!
25
+ return true if resend_line
26
+ return true if run_priority_queue
27
+ if run_main_queue
28
+ return true
29
+ else
30
+ not_printing!
31
+ unless paused?
32
+ @queue_index = 0
33
+ @line_number = 0
34
+ send!(RintCore::GCode::Codes::SET_LINE_NUM, -1, true)
35
+ end
36
+ return true
37
+ end
38
+ end
39
+
40
+ def resend_line
41
+ if @resend_from == @line_number
42
+ @resend_from = -1
43
+ return nil
44
+ elsif @resend_from < @line_number && @resend_from > -1
45
+ send!(@machine_history[@resend_from], @resend_from, false)
46
+ @resend_from += 1
47
+ return true
48
+ end
49
+ end
50
+
51
+ def run_priority_queue
52
+ unless @priority_queue.blank?
53
+ send!(@priority_queue.shift)
54
+ # clear_to_send!
55
+ end
56
+ end
57
+
58
+ def run_main_queue
59
+ if !paused? && @queue_index < @main_queue.length
60
+ current_line = @main_queue[@queue_index]
61
+ current_line = current_line.to_s unless current_line.class == String
62
+ unless current_line.blank?
63
+ send!(current_line, @line_number, true)
64
+ @line_number += 1
65
+ end
66
+ @queue_index += 1
67
+ return true
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,71 @@
1
+ require 'rint_core/g_code/codes'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ module RintCore
5
+ module Driver
6
+ module State
7
+
8
+ def can_print?
9
+ connected? && online? && !printing?
10
+ end
11
+
12
+ def connected?
13
+ @connection.present?
14
+ end
15
+
16
+ def clear_to_send?
17
+ @clear && online?
18
+ end
19
+
20
+ def listen_can_continue?
21
+ !@stop_listening && connected?
22
+ end
23
+
24
+ def online?
25
+ connected? && @online
26
+ end
27
+
28
+ def paused?
29
+ @paused
30
+ end
31
+
32
+ def printing?
33
+ @printing
34
+ end
35
+
36
+ private
37
+
38
+ def initialize_state
39
+ @clear = false
40
+ @online = false
41
+ @printing = false
42
+ @paused = false
43
+ @stop_listening = false
44
+ end
45
+
46
+ def clear_to_send!
47
+ @clear = true
48
+ end
49
+
50
+ def not_clear_to_send!
51
+ @clear = false
52
+ end
53
+
54
+ def online!
55
+ @online = true
56
+ end
57
+
58
+ def offline!
59
+ @online = false
60
+ end
61
+
62
+ def printing!
63
+ @printing = true
64
+ end
65
+
66
+ def not_printing!
67
+ @printing = false
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,6 @@
1
+ require 'rint_core/g_code/codes'
1
2
  module RintCore
2
- class GCode
3
-
3
+ module GCode
4
+
4
5
  end
5
6
  end
@@ -1,12 +1,12 @@
1
1
  module RintCore
2
2
  module GCode
3
- class Codes
3
+ module Codes
4
4
  RAPID_MOVE = 'G0'
5
5
  CONTROLLED_MOVE = 'G1'
6
6
  DWELL = 'G4'
7
7
  HEAD_OFFSET = 'G10'
8
8
  USE_INCHES = 'G20'
9
- USE_MILIMETRES = 'G21'
9
+ USE_MILLIMETRES = 'G21'
10
10
  HOME = 'G28'
11
11
  ABS_POSITIONING = 'G90'
12
12
  REL_POSITIONING = 'G91'
@@ -0,0 +1,83 @@
1
+ require 'rint_core/g_code/codes'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ module RintCore
5
+ module GCode
6
+ class Line
7
+ include RintCore::GCode::Codes
8
+
9
+ attr_accessor :imperial, :relative, :f
10
+ attr_reader :raw
11
+ attr_writer :x, :y, :z, :e
12
+
13
+ def initialize(line)
14
+ @coordinates = ['X','Y','Z','E','F']
15
+ @number_pattern = /[-]?\d+[.]?\d*/
16
+ @raw = line.upcase.strip
17
+ @raw = @raw.split(COMMENT_SYMBOL).first.strip if line.include?(COMMENT_SYMBOL)
18
+
19
+ parse_coordinates
20
+ end
21
+
22
+ def to_mm(number)
23
+ number *= 25.4 if number.present? && @imperial
24
+ number
25
+ end
26
+
27
+ def x
28
+ to_mm @x
29
+ end
30
+
31
+ def y
32
+ to_mm @y
33
+ end
34
+
35
+ def z
36
+ to_mm @z
37
+ end
38
+
39
+ def e
40
+ to_mm @e
41
+ end
42
+
43
+ def command
44
+ if @raw.present?
45
+ @raw.split(' ').first
46
+ else
47
+ ''
48
+ end
49
+ end
50
+
51
+ def get_float(axis)
52
+ @raw.split(axis).last.scan(@number_pattern).first.to_f
53
+ end
54
+
55
+ def parse_coordinates
56
+ @coordinates.each do |axis|
57
+ send(axis.downcase+'=', get_float(axis)) if @raw.include?(axis)
58
+ end
59
+ end
60
+
61
+ def is_move?
62
+ @raw.start_with?(RAPID_MOVE) || @raw.start_with?(CONTROLLED_MOVE)
63
+ end
64
+
65
+ def travel_move?
66
+ is_move? && !@e.present?
67
+ end
68
+
69
+ def extrusion_move?
70
+ is_move? && @e.present? && @e > 0
71
+ end
72
+
73
+ def full_home?
74
+ command == HOME && @x.blank? && @y.blank? && @z.blank?
75
+ end
76
+
77
+ def to_s
78
+ @raw
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,173 @@
1
+ require 'rint_core/g_code/codes'
2
+ require 'rint_core/g_code/line'
3
+ require 'active_support/core_ext/object/blank'
4
+
5
+ module RintCore
6
+ module GCode
7
+ class Object
8
+ include RintCore::GCode::Codes
9
+
10
+ attr_accessor :raw_data, :layers
11
+ attr_reader :lines, :x_min, :x_max, :y_min, :y_max, :z_min, :z_max,
12
+ :filament_used, :x_travel, :y_travel, :z_travel, :e_travel,
13
+ :width, :depth, :height
14
+
15
+ def initialize(data = nil)
16
+ if data.class == String && self.class.is_file?(data)
17
+ data = self.class.get_file(data)
18
+ end
19
+ return false if data.blank? || data.class != Array
20
+ @raw_data = data
21
+ @imperial = false
22
+ @relative = false
23
+ @lines = []
24
+ data.each do |line|
25
+ line = RintCore::GCode::Line.new(line)
26
+ @lines << line if line.raw.present?
27
+ end
28
+ process
29
+ end
30
+
31
+ def self.is_file?(file)
32
+ file.present? && File.exist?(file) && File.file?(file)
33
+ end
34
+
35
+ def self.get_file(file)
36
+ IO.readlines(file)
37
+ end
38
+
39
+ private
40
+
41
+ def process
42
+ set_variables
43
+
44
+ @lines.each do |line|
45
+ case line.command
46
+ when USE_INCHES
47
+ @imperial = true
48
+ when USE_MILLIMETRES
49
+ @imperial = false
50
+ when ABS_POSITIONING
51
+ @relative = false
52
+ when REL_POSITIONING
53
+ @relative = true
54
+ when SET_POSITION
55
+ set_positions(line)
56
+ when HOME
57
+ home_axes(line)
58
+ when RAPID_MOVE
59
+ movement_line(line)
60
+ when CONTROLLED_MOVE
61
+ count_layers(line)
62
+ movement_line(line)
63
+ end
64
+ end
65
+
66
+ @width = @x_max - @x_min
67
+ @depth = @y_max - @y_min
68
+ @height = @z_max - @z_min
69
+ end
70
+
71
+ def count_layers(line)
72
+ if line.z.present? && line.z > @current_z
73
+ @layers += 1
74
+ end
75
+ end
76
+
77
+ def movement_line(line)
78
+ line.imperial = @imperial
79
+ line.relative = @relative
80
+ measure_travel(line)
81
+ set_current_position(line)
82
+ set_limits(line)
83
+ end
84
+
85
+ def measure_travel(line)
86
+ if line.relative
87
+ @x_travel += line.x.abs if line.x.present?
88
+ @y_travel += line.y.abs if line.y.present?
89
+ @z_travel += line.z.abs if line.z.present?
90
+ else
91
+ @x_travel += (@current_x - line.x).abs if line.x.present?
92
+ @y_travel += (@current_y - line.y).abs if line.y.present?
93
+ @z_travel += (@current_z - line.z).abs if line.z.present?
94
+ end
95
+ end
96
+
97
+ def home_axes(line)
98
+ if line.x.present? || line.full_home?
99
+ @x_travel += @current_x
100
+ @current_x = 0
101
+ end
102
+ if line.y.present? || line.full_home?
103
+ @y_travel += @current_y
104
+ @current_y = 0
105
+ end
106
+ if line.z.present? || line.full_home?
107
+ @z_travel += @current_z
108
+ @current_z = 0
109
+ end
110
+ end
111
+
112
+ def set_positions(line)
113
+ @current_x = line.x if line.x.present?
114
+ @current_y = line.y if line.y.present?
115
+ @current_z = line.z if line.z.present?
116
+ if line.e.present?
117
+ @filament_used += @current_e
118
+ @current_e = line.e
119
+ end
120
+ end
121
+
122
+ def set_current_position(line)
123
+ if line.relative
124
+ @current_x += line.x if line.x.present?
125
+ @current_y += line.y if line.y.present?
126
+ @current_z += line.z if line.z.present?
127
+ @current_e += line.e if line.e.present?
128
+ else
129
+ @current_x = line.x if line.x.present?
130
+ @current_y = line.y if line.y.present?
131
+ @current_z = line.z if line.z.present?
132
+ @current_e = line.e if line.e.present?
133
+ end
134
+ end
135
+
136
+ def set_limits(line)
137
+ if line.extrusion_move?
138
+ if line.x.present? && !line.x.zero?
139
+ @x_min = @current_x if @current_x < @x_min
140
+ @x_max = @current_x if @current_x > @x_max
141
+ end
142
+ if line.y.present? && !line.y.zero?
143
+ @y_min = @current_y if @current_y < @y_min
144
+ @y_max = @current_y if @current_y > @y_max
145
+ end
146
+ end
147
+ if line.z.present?
148
+ @z_min = @current_z if @current_z < @z_min
149
+ @z_max = @current_z if @current_z > @z_max
150
+ end
151
+ end
152
+
153
+ def set_variables
154
+ @x_travel = 0
155
+ @y_travel = 0
156
+ @z_travel = 0
157
+ @current_x = 0
158
+ @current_y = 0
159
+ @current_z = 0
160
+ @current_e = 0
161
+ @x_min = 999999999
162
+ @y_min = 999999999
163
+ @z_min = 0
164
+ @x_max = -999999999
165
+ @y_max = -999999999
166
+ @z_max = -999999999
167
+ @filament_used = 0
168
+ @layers = 0
169
+ end
170
+
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,59 @@
1
+ require 'rint_core/driver'
2
+ require 'active_support/configurable'
3
+
4
+ module RintCore
5
+ class Printer
6
+ include RintCore::Driver
7
+ include ActiveSupport::Configurable
8
+
9
+ # Callbacks are typically given a string argument, usually the current line
10
+ config_accessor :port, :baud, :callbacks, :error_response, :debug_response,
11
+ :online_response, :good_response, :temperature_response,
12
+ :resend_response, :encoding, :sleep_time, :wait_period,
13
+ :read_timeout, :long_sleep
14
+
15
+ self.port = "/dev/ttyACM0"
16
+ self.baud = 115200
17
+ self.callbacks = {}
18
+ self.error_response = 'Error'
19
+ self.debug_response = 'DEBUG_'
20
+ self.online_response = ['start','Grbl']
21
+ self.good_response = ['ok']
22
+ self.temperature_response = 'T:'
23
+ self.resend_response = ['rs','resend']
24
+ self.encoding = 'us-ascii'
25
+ self.sleep_time = 0.001
26
+ self.wait_period = 0
27
+ self.read_timeout = 0
28
+ self.long_sleep = 0.25
29
+
30
+ attr_reader :last_line_received, :main_queue, :queue_index, :resend_from, :machine_history, :full_history
31
+
32
+ def initialize(auto_connect = false)
33
+ initialize_driver
34
+ connect! if auto_connect
35
+ end
36
+
37
+ def time_from_start
38
+ @start_time ||= Time.now
39
+ secs = Time.now - @start_time
40
+ [[60, :seconds], [60, :minutes], [24, :hours], [1000, :days]].map{ |count, name|
41
+ if secs > 0
42
+ secs, n = secs.divmod(count)
43
+ "#{n.to_i} #{name}"
44
+ end
45
+ }.compact.reverse.join(' ')
46
+ end
47
+
48
+ class << self
49
+ def baud_rates
50
+ [2400, 9600, 19200, 38400, 57600, 115200, 250000]
51
+ end
52
+
53
+ def is_port?(port)
54
+ port.present? && File.exist?(port) && File.new(port).isatty
55
+ end
56
+ end
57
+
58
+ end
59
+ end