rotor 0.1.00 → 0.1.1

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
1
  ---
2
2
  SHA1:
3
- metadata.gz: 85a4ae370eef40efc19bd9a1745a36e8dbb82943
4
- data.tar.gz: 9db5dfab12dc9abaad33fb8db53d3cb2a09e82b5
3
+ metadata.gz: 62d8ac2a05984d3d5d1db744a7dec78f88003e98
4
+ data.tar.gz: 98c73074be6a11b631df7351c4add650bb05d447
5
5
  SHA512:
6
- metadata.gz: 3380a0d8992f067736c53b0aa986a13b94f5aa9b807c33c1b9213ad4e6a5063a35653f00d3cf9815fd32826509ec4ad2cb87b7d964c011287ac7434034b4b3b4
7
- data.tar.gz: b74c20526d395f4890bb2b7b8b430a629aff4eb48c89f91f57a3e5d9ff60fd242f1bbc3a65c76d4ad2278538893c69bc37c43bc881e416fb17ad81914d989877
6
+ metadata.gz: 4c037e8f5cf5f319e20fcd8f317f0cf363617e187c09b7af23a3b564476d70017930ecc87e371a9d80a30237df5ec24d4dc540a5c266578d8a4ecff70d8ad0e1
7
+ data.tar.gz: bcf1702711ce5959aff917e5cf1562fc8cdc5ff262a2be2998325488bd06cbef1e43e2f2a2627af63977ae869788c833f83f67058f881d6324fabb36e82ca161
data/README.md CHANGED
@@ -12,33 +12,62 @@ or ULN2800 Integrated Controllers.
12
12
 
13
13
  gem install wiringpi
14
14
 
15
+ If you are using GPIO Pins from a A+/B+, you may need to update your
16
+ WiringPi libraries. You can pull from my repo https://github.com/kobaltz/WiringPi-Ruby
17
+
18
+ I did not write any of the WiringPi-Ruby platform. I simply pulled the latest C libraries
19
+ and recompiled the gem.
20
+
15
21
  Install Rotor
16
22
 
17
23
  gem install rotor
18
24
 
19
25
  # Notes
20
26
 
21
- Class Stepper
27
+ This gem has been built for my personal project. I do not and cannot know if this will
28
+ work with your setup. However, put in an issue if you're having troubles with this gem
29
+ and I will try to help you as best as I can.
30
+
31
+ I am using two stepper motors (NEMA17 Bipolar 20Ncm 12V) and two L293D motor drivers. This
32
+ gem has also been tested with a small 5V Unipolar Stepper Motor and 12V Unipolar Stepper Motor.
33
+
34
+ My Steps Per MM is based on a 200 step per revolution motor and a threaded rod with 20 threads per inch.
35
+ This means that I will have to step 4000 times to move the coupler one inch.
36
+
37
+ # Usage
38
+
39
+ ## Class Stepper
40
+
41
+ MAKE SURE THAT YOU HAVE CONFIGURED THE Rotor::Stepper WITH THE CORRECT GPIO PIN NUMBERS. CHECK AND
42
+ DOUBLE CHECK THESE BEFORE RUNNING YOUR CODE.
22
43
 
23
- stepper = Rotor::Stepper.new(initialize(coil_A_1_pin, coil_A_2_pin, coil_B_1_pin, coil_B_2_pin, enable_pin=nil, homing_switch, homing_normally)
24
- stepper.forward(delay=5,steps=100)
44
+ stepper = Rotor::Stepper.new(coil_A_1_pin, coil_A_2_pin, coil_B_1_pin, coil_B_2_pin, enable_pin=nil, homing_switch, homing_normally,steps_per_mm)
45
+ stepper.forward(delay=5,steps=100) # stepper.forward(1,100)
25
46
  stepper.backwards(delay=5,steps=100)
26
47
  stepper.set_home(direction) #:forward or :backwards
27
48
  stepper.at_home?
28
- stepper.at_safe_area? #opposite of at_home?
49
+ stepper.at_safe_area? # opposite of at_home?
29
50
 
30
- Class Servo
51
+ After running your GCode, you may want to consider to power down the motor by sending a
52
+ LOW to each step.
53
+
54
+ stepper.power_down
55
+
56
+ ## Class Servo
31
57
 
32
58
  servo = Rotor::Servo.new(pin=18)
33
59
  servo.rotate(direction) # :up or :down
34
60
 
35
- Class GCode
61
+ ## Class GCode
36
62
 
37
- gcode = Rotor::Gcode.new(stepper_x=nil,stepper_y=nil,stepper_z=nil,scale=1,servo=nil)
38
- gcode.open(file)
39
- gcode.simulate
63
+ The plot points are streamed to output.txt file on your computer.
40
64
 
41
- # Usage
65
+ You can test the outputs of your GCODE and the XY plots it creates by Rotor.
66
+
67
+ File.open("output.txt", 'wb') { |file| file.write("x,y,xm,ym\n") }
68
+ gcode = Rotor::Gcode.new(nil,nil,nil,1,nil)
69
+ gcode.open('output.nc')
70
+ gcode.simulate
42
71
 
43
72
  The goal of this gem is to make controlling your robotics easier than
44
73
  other solutions.
@@ -49,8 +78,8 @@ or ULN2800 Integrated Controllers.
49
78
  that the panel is moving in and therefore know which side it has hit. This
50
79
  was to reduce the number of GPIO pins required.
51
80
 
52
- stepper_x = Rotor::Stepper.new(23,12,17,24,nil,13,LOW)
53
- stepper_y = Rotor::Stepper.new(25, 4,21,22,nil,19,LOW)
81
+ stepper_x = Rotor::Stepper.new(23,12,17,24,nil,13,0,157.48)
82
+ stepper_y = Rotor::Stepper.new(25, 4,21,22,nil,19,0,157.48)
54
83
 
55
84
  You can use a servo to control the marker (or leave blank if you're using a Z Axis Stepper)
56
85
  This will be built out so that the strength control of the servo (for laser power) can be
@@ -65,8 +94,8 @@ or ULN2800 Integrated Controllers.
65
94
  # stepper_x.forward(1,100)
66
95
  # stepper_y.set_home(:forward)
67
96
 
68
- stepper_x = Rotor::Stepper.new(4,17,23,24,18)
69
- stepper_y = Rotor::Stepper.new(25,12,16,21,18)
97
+ stepper_x = Rotor::Stepper.new(23,12,17,24,nil,13,LOW,157.48)
98
+ stepper_y = Rotor::Stepper.new(25, 4,21,22,nil,19,LOW,157.48)
70
99
 
71
100
  loop do
72
101
  puts "Enter steps forward::"
@@ -114,6 +143,55 @@ keep this at 1).
114
143
  threads << Thread.new { stepper_y.forward(5,text.to_i) }
115
144
  threads.each { |thr| thr.join }
116
145
 
146
+ # Sample Code
147
+
148
+ ## Production (Moving Stepper and Servo)
149
+
150
+ Here is the real world sample code that I am using to plot
151
+
152
+ require 'rotor'
153
+ begin
154
+ stepper_x = Rotor::Stepper.new(23,12,17,24,nil,13,0,157.48)
155
+ stepper_y = Rotor::Stepper.new(25, 4,21,22,nil,19,0,157.48)
156
+ servo = Rotor::Servo.new(18)
157
+
158
+ stepper_x.set_home(:backwards)
159
+ stepper_y.set_home(:backwards)
160
+ stepper_x.forward(1,4000)
161
+ stepper_y.forward(1,4000)
162
+
163
+ gcode = Rotor::Gcode.new(stepper_x,stepper_y,nil,1,servo)
164
+ gcode.open('output.nc')
165
+ gcode.simulate
166
+
167
+ ensure
168
+ servo.rotate(:up)
169
+
170
+ stepper_x.set_home(:backwards)
171
+ stepper_y.set_home(:backwards)
172
+ stepper_x.forward(1,4000)
173
+ stepper_y.forward(1,4000)
174
+
175
+ stepper_x.power_down
176
+ stepper_y.power_down
177
+
178
+ [23,12,17,24,13,25,4,21,22,19,13].each do |pin|
179
+ `echo #{pin} > /sys/class/gpio/unexport`
180
+ end
181
+ end
182
+
183
+ ## Development (Exporting Plot Points for Graphing)
184
+
185
+ Before wasting more materials, I try to plot my points to a file and view them in Excel.
186
+ Within the root of this repository, there is an Excel file, called Visual.xlsx, and
187
+ you can import the output.txt into the first four columns. By doing so, you can see the
188
+ plot points and the scatter of movements.
189
+
190
+ File.open("output.txt", 'wb') { |file| file.write("x,y,xm,ym\n") }
191
+ gcode = Rotor::Gcode.new(nil,nil,nil,1,nil)
192
+ gcode.open('output.nc')
193
+ gcode.simulate
194
+
117
195
  # License
118
196
 
119
197
  Copyright (c) 2015 kobaltz
data/lib/rotor/gcode.rb CHANGED
@@ -17,8 +17,17 @@ module Rotor
17
17
  @y = 0
18
18
  @z = 0
19
19
 
20
+ line_num = 0
21
+ last_parsed_line = nil
22
+
20
23
  @file.each_line do |line|
24
+ puts "last_parsed_line::#{last_parsed_line}"
25
+ line = line.gsub("J-0.000000","J-0.000001") if last_parsed_line && last_parsed_line[:j] && last_parsed_line[:j] > 0.0
26
+ line = line.gsub("J-0.000000","J0.000001") if last_parsed_line && last_parsed_line[:j] && last_parsed_line[:j] < 0.0
27
+
21
28
  parsed_line = parse_line(line)
29
+
30
+ line_num += 1
22
31
  if parsed_line[:g]
23
32
  #Move to this origin point.
24
33
  if parsed_line[:g] == 0
@@ -39,13 +48,15 @@ module Rotor
39
48
  elsif parsed_line[:z] && parsed_line[:f].nil? && parsed_line[:x].nil? && parsed_line[:y].nil?
40
49
  puts "Raising marker::#{parsed_line}"
41
50
  @servo.rotate(:up) if @servo
51
+ elsif parsed_line[:z].nil? && parsed_line[:f] && parsed_line[:x].nil? && parsed_line[:y].nil?
52
+ # Set feed/spin rate
42
53
  else
43
54
  puts "Move Stepper::#{parsed_line}"
44
- move_stepper(parsed_line,25)
55
+ move_stepper(parsed_line,10)
45
56
  end
46
57
  elsif parsed_line[:g] == 2 || parsed_line[:g] == 3
47
58
  # Get my ARC on
48
- puts "DEBUG::#{parsed_line}"
59
+ # puts "DEBUG::#{parsed_line}"
49
60
  x_start = @x
50
61
  x_end = parsed_line[:x]
51
62
 
@@ -53,7 +64,11 @@ module Rotor
53
64
  y_end = parsed_line[:y]
54
65
 
55
66
  x_offset = parsed_line[:i]
67
+ x_offset = 0.0001 if x_offset == 0.0
68
+ x_offset = -0.0001 if x_offset == -0.0
56
69
  y_offset = parsed_line[:j]
70
+ y_offset = 0.0001 if y_offset == 0.0
71
+ y_offset = -0.0001 if y_offset == -0.0
57
72
 
58
73
  x_origin = x_offset + x_start
59
74
  y_origin = y_offset + y_start
@@ -63,23 +78,28 @@ module Rotor
63
78
  start_angle = Math.atan2((y_start - y_origin),(x_start - x_origin))
64
79
  end_angle = Math.atan2((y_end - y_origin),(x_end - x_origin))
65
80
 
66
- steps = (end_angle - start_angle) / 25
81
+ number_of_precision = 5
82
+
83
+ steps = (end_angle - start_angle) / number_of_precision
67
84
 
68
85
  current_degrees = start_angle
69
86
 
70
- 25.times do
71
- arc_line = {}
72
- arc_line[:x] = x_origin + radius * Math.cos(current_degrees)
73
- arc_line[:y] = y_origin + radius * Math.sin(current_degrees)
74
- arc_line[:z] = nil
75
- current_degrees += steps
76
- puts "Move Arc Stepper::#{arc_line}"
77
- move_stepper(arc_line,25)
87
+ number_of_precision.times do |i|
88
+ # unless i == (number_of_precision - 1)
89
+ current_degrees += steps
90
+ arc_line = {}
91
+ arc_line[:g] = parsed_line[:g]
92
+ arc_line[:x] = radius * Math.cos(current_degrees) + x_origin
93
+ arc_line[:y] = radius * Math.sin(current_degrees) + y_origin
94
+ arc_line[:z] = nil
95
+ puts "Move Arc Stepper (#{line_num})::#{arc_line},#{current_degrees}::#{y_offset}"
96
+ move_stepper(arc_line,10)
97
+ # end
78
98
  end
79
99
 
80
-
81
100
  else
82
101
  # puts "GLINE - Something else"
102
+ puts "DEBUG::GLINE - Something else::#{parsed_line}"
83
103
  end
84
104
  elsif parsed_line[:m]
85
105
  if line[0..2] == "M03"
@@ -90,10 +110,13 @@ module Rotor
90
110
  @servo.rotate(:up) if @servo
91
111
  else
92
112
  # puts "MLINE - Something else"
113
+ puts "DEBUG::MLINE - Something else::#{parsed_line}"
93
114
  end
94
115
  else
95
116
  # puts "Something else"
117
+ puts "DEBUG::????? - Something else::#{parsed_line}"
96
118
  end
119
+ last_parsed_line = parsed_line
97
120
  end
98
121
  end
99
122
 
@@ -101,31 +124,68 @@ module Rotor
101
124
 
102
125
  def move_stepper(parsed_line,delay)
103
126
  threads = []
104
- [:x,:y,:z].each do |element|
105
- ets = element.to_s
106
- instance_variable_set(:"@#{ets}_move",nil)
107
- if parsed_line[element]
108
- instance_variable_set(:"@#{ets}_move",parsed_line[element])
109
- instance_variable_set(:"@#{ets}_move",0) unless instance_variable_get(:"@#{ets}_move")
110
- instance_variable_set(:"@#{ets}_move",instance_variable_get(:"@#{ets}_move") * @scale)
111
-
112
- instance_variable_set(:"@#{ets}_movement", (instance_variable_get(:"@#{ets}_move") - instance_variable_get(:"@#{ets}")).abs)
113
-
114
- if instance_variable_get(:"@#{ets}_move").to_f > instance_variable_get(:"@#{ets}") #move to the right
115
- if instance_variable_get(:"@stepper_#{ets}") && instance_variable_get(:"@stepper_#{ets}").at_safe_area?
116
- threads << Thread.new { instance_variable_get(:"@stepper_#{ets}").forward(delay, instance_variable_get(:"@#{ets}_movement")) }
117
- end
118
- elsif instance_variable_get(:"@#{ets}_move").to_f < instance_variable_get(:"@#{ets}") #move to the left
119
- if instance_variable_get(:"@stepper_#{ets}") && instance_variable_get(:"@stepper_#{ets}").at_safe_area?
120
- threads << Thread.new { instance_variable_get(:"@stepper_#{ets}").backwards(delay, instance_variable_get(:"@#{ets}_movement")) }
121
- end
127
+ @x_move = nil
128
+ if parsed_line[:x]
129
+ @x_move = parsed_line[:x]
130
+ @x_move ||= 0
131
+ @x_move *= @scale
132
+
133
+ @x_movement = (@x_move - @x).abs
134
+
135
+ if @x_move.to_f > @x #move to the right
136
+ if @stepper_x # && @stepper_x.at_safe_area?
137
+ threads << Thread.new { @stepper_x.forward(delay, @x_movement) }
138
+ end
139
+ elsif @x_move.to_f < @x #move to the left
140
+ if @stepper_x # && @stepper_x.at_safe_area?
141
+ threads << Thread.new { @stepper_x.backwards(delay, @x_movement) }
122
142
  end
123
- instance_variable_set(:"@#{ets}",instance_variable_get(:"@#{ets}_move"))
124
143
  end
144
+ @x = @x_move
125
145
  end
126
146
 
127
- #puts "Moving to G#{parsed_line[:g]} #{instance_variable_get(:"@x_move")}, #{instance_variable_get(:"@y_move")}, #{instance_variable_get(:"@z_move")}"
147
+ @y_move = nil
148
+ if parsed_line[:y]
149
+ @y_move = parsed_line[:y]
150
+ @y_move ||= 0
151
+ @y_move *= @scale
152
+
153
+ @y_movement = (@y_move - @y).abs
154
+
155
+ if @y_move.to_f > @y #move to the right
156
+ if @stepper_y # && @stepper_y.at_safe_area?
157
+ threads << Thread.new { @stepper_y.forward(delay, @y_movement) }
158
+ end
159
+ elsif @y_move.to_f < @y #move to the left
160
+ if @stepper_y # && @stepper_y.at_safe_area?
161
+ threads << Thread.new { @stepper_y.backwards(delay, @y_movement) }
162
+ end
163
+ end
164
+ @y = @y_move
165
+ end
166
+
167
+ @z_move = nil
168
+ if parsed_line[:z]
169
+ @z_move = parsed_line[:z]
170
+ @z_move ||= 0
171
+ @z_move *= @scale
172
+
173
+ @z_movement = (@z_move - @z).abs
174
+
175
+ if @z_move.to_f > @z #move to the right
176
+ if @stepper_z # && @stepper_z.at_safe_area?
177
+ threads << Thread.new { @stepper_z.forward(delay, @z_movement) }
178
+ end
179
+ elsif @z_move.to_f < @z #move to the left
180
+ if @stepper_z # && @stepper_z.at_safe_area?
181
+ threads << Thread.new { @stepper_z.backwards(delay, @z_movement) }
182
+ end
183
+ end
184
+ @z = @z_move
185
+ end
186
+ # puts "Moving to G#{parsed_line[:g]} #{@x_move}(#{@x_movement}), #{@y_move}(#{@y_movement}), #{@z_move}(#{@z_movement})"
128
187
  threads.each { |thr| thr.join }
188
+ File.open("output.txt", 'a') { |file| file.write("#{@x_move},#{@y_move},#{@x_movement},#{@y_movement}\n") } if File.exists?("output.txt")
129
189
  end
130
190
 
131
191
  def parse_line(line)
@@ -142,6 +202,8 @@ module Rotor
142
202
  data = line.match /#{node}(?<data>\d+[,.]\d+)/
143
203
  data ||= line.match /#{node}(?<data>\d+)/
144
204
  data ||= line.match /#{node}(?<data>-\d+[,.]\d+)/
205
+ data ||= line.match /#{node}(?<data>\d+[,.])/
206
+ data ||= line.match /#{node}(?<data>-\d+[,.])/
145
207
  if data
146
208
  case element
147
209
  when :g, :m
data/lib/rotor/stepper.rb CHANGED
@@ -2,17 +2,20 @@ require 'wiringpi'
2
2
 
3
3
  module Rotor
4
4
  class Stepper
5
- def initialize(coil_A_1_pin, coil_A_2_pin, coil_B_1_pin, coil_B_2_pin, enable_pin=nil, homing_switch, homing_normally)
5
+ def initialize(coil_A_1_pin, coil_A_2_pin, coil_B_1_pin, coil_B_2_pin, enable_pin=nil, homing_switch, homing_normally,steps_per_mm)
6
6
  @io = WiringPi::GPIO.new(WPI_MODE_GPIO)
7
7
  @coil_A_1_pin = coil_A_1_pin
8
8
  @coil_A_2_pin = coil_A_2_pin
9
9
  @coil_B_1_pin = coil_B_1_pin
10
10
  @coil_B_2_pin = coil_B_2_pin
11
11
  @enable_pin = enable_pin
12
-
12
+ @steps_per_mm = steps_per_mm
13
13
  @homing_switch = homing_switch
14
14
  @homing_normally = homing_normally
15
15
 
16
+ @step = 0
17
+ @ps = [[1,0,1,0],[0,1,1,0],[0,1,0,1],[1,0,0,1]]
18
+
16
19
  [@coil_A_1_pin, @coil_A_2_pin, @coil_B_1_pin, @coil_B_2_pin].each do |pin|
17
20
  `echo #{pin} > /sys/class/gpio/unexport`
18
21
  @io.mode(pin,OUTPUT)
@@ -34,39 +37,32 @@ module Rotor
34
37
 
35
38
  def forward(delay=5,steps=100)
36
39
  delay_time = delay/1000.0
37
- (0..steps).each do |i|
38
- set_step(1, 0, 1, 0)
39
- sleep delay_time
40
- set_step(0, 1, 1, 0)
41
- sleep delay_time
42
- set_step(0, 1, 0, 1)
43
- sleep delay_time
44
- set_step(1, 0, 0, 1)
40
+ (0..(steps * @steps_per_mm)).each do |i|
41
+ set_step(@ps[@step][0],@ps[@step][1],@ps[@step][2],@ps[@step][3])
42
+ @step += 1
43
+ @step = 0 if @step == 4
45
44
  sleep delay_time
46
45
  end
47
46
  end
48
47
 
48
+
49
49
  def backwards(delay=5,steps=100)
50
50
  delay_time = delay/1000.0
51
- (0..steps).each do |i|
52
- set_step(1, 0, 0, 1)
53
- sleep delay_time
54
- set_step(0, 1, 0, 1)
55
- sleep delay_time
56
- set_step(0, 1, 1, 0)
57
- sleep delay_time
58
- set_step(1, 0, 1, 0)
51
+ (0..(steps * @steps_per_mm)).each do |i|
52
+ set_step(@ps[@step][0],@ps[@step][1],@ps[@step][2],@ps[@step][3])
53
+ @step -= 1
54
+ @step = 3 if @step == -1
59
55
  sleep delay_time
60
56
  end
61
- end
62
-
57
+
58
+ end
63
59
 
64
60
  def set_home(direction)
65
61
  puts "Setting #{direction} with Homing on GPIO #{@homing_switch}"
66
62
  @move = true
67
63
  while @move == true
68
- backwards(2,1) if direction == :backwards #&& @io.read(@homing_switch) == @homing_normally
69
- forward(2,1) if direction == :forward #&& @io.read(@homing_switch) == @homing_normally
64
+ backwards(1,1) if direction == :backwards #&& @io.read(@homing_switch) == @homing_normally
65
+ forward(1,1) if direction == :forward #&& @io.read(@homing_switch) == @homing_normally
70
66
  @move = false unless @io.read(@homing_switch) == @homing_normally
71
67
  end
72
68
  end
@@ -87,6 +83,10 @@ module Rotor
87
83
  end
88
84
  end
89
85
 
86
+ def power_down
87
+ set_step(0, 0, 0, 0)
88
+ end
89
+
90
90
  private
91
91
 
92
92
  def set_step(w1, w2, w3, w4)
@@ -94,6 +94,6 @@ module Rotor
94
94
  @io.write(@coil_A_2_pin, w2)
95
95
  @io.write(@coil_B_1_pin, w3)
96
96
  @io.write(@coil_B_2_pin, w4)
97
- end
97
+ end
98
98
  end
99
99
  end
data/lib/rotor/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rotor
2
- VERSION = "0.1.00"
2
+ VERSION = "0.1.1"
3
3
  end
data/visual.xlsx ADDED
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rotor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.00
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - kobaltz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-20 00:00:00.000000000 Z
11
+ date: 2015-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -74,6 +74,7 @@ files:
74
74
  - lib/rotor/version.rb
75
75
  - rotor.gemspec
76
76
  - sample.nc
77
+ - visual.xlsx
77
78
  homepage: https://github.com/kobaltz/rotor
78
79
  licenses:
79
80
  - MIT