Thomas Buck 3 роки тому
коміт
9c76454bac

+ 1
- 0
.gitignore Переглянути файл

@@ -0,0 +1 @@
1
+.pio

+ 186
- 0
hardware/common.scad Переглянути файл

@@ -0,0 +1,186 @@
1
+include <config.scad>;
2
+
3
+$fn = 42;
4
+
5
+module prism(l, w, h) {
6
+    polyhedron(
7
+        points = [[0,0,0], [l,0,0], [l,w,0], [0,w,0], [0,w,h], [l,w,h]],
8
+        faces = [[0,1,2,3],[5,4,3,2],[0,4,5,1],[0,3,4],[5,2,1]]
9
+    );
10
+}
11
+
12
+module roundedcylinder(d, h, r, top = false) {
13
+    hull() // needed, otherwise rendering fails
14
+    rotate_extrude(convexity = 10)
15
+    translate([d / 2, 0, 0])
16
+    rotate([0, 180, 0]) {
17
+        if (top) {
18
+            translate([0, r])
19
+            square([d / 2, h - r * 2]);
20
+        } else {
21
+            translate([0, r])
22
+            square([d / 2, h - r]);
23
+        }
24
+        
25
+        //translate([r, 0])
26
+        //square([d / 2 - r, r]);
27
+        
28
+        translate([r, r])
29
+        circle(r = r);
30
+        
31
+        if (top) {
32
+            translate([r, h - r])
33
+            circle(r = r);
34
+        
35
+            //translate([r, h - r])
36
+            //square([d / 2 - r, r]);
37
+        }
38
+    }
39
+}
40
+
41
+module rail_2020(l, n = "") {
42
+    translate([0, 10, 10])
43
+    difference() {
44
+        translate([0, -10, -10])
45
+        cube([l, 20, 20]);
46
+        
47
+        translate([-1, 0, 0])
48
+        rotate([0, 90, 0])
49
+        cylinder(d = 4.2, h = l + 2);
50
+        
51
+        for (i = [0, 90, 180, 270])
52
+        rotate([i, 0, 0]) {
53
+            translate([-1, -6.25 / 2, 10 - 4.3 - 1.8])
54
+            cube([l + 2, 6.25, 4.3 + 1.8 + 1]);
55
+            
56
+            for (j = [-1, 1])
57
+            scale([1, j, 1])
58
+            translate([-1, -6.25 / 2, 10 - 1.8])
59
+            rotate([45, 0, 0])
60
+            cube([l + 2, 6.25, 4.3 + 1.8 + 1]);
61
+        }
62
+    }
63
+}
64
+
65
+module rail_2020_x(l, n = "") {
66
+    echo("2020 rail", n, str(l));
67
+    rail_2020(l, n);
68
+}
69
+
70
+module rail_2020_y(l, n = "") {
71
+    translate([20, 0, 0])
72
+    rotate([0, 0, 90])
73
+    rail_2020_x(l, n);
74
+}
75
+
76
+module rail_2040_x(l, n = "") {
77
+    echo("2040 rail", n, str(l));
78
+    rail_2020(l, n);
79
+    translate([0, 0, -20])
80
+    rail_2020(l, n);
81
+}
82
+
83
+module rail_2040_y(l, n = "") {
84
+    translate([20, 0, 0])
85
+    rotate([0, 0, 90])
86
+    rail_2040_x(l, n);
87
+}
88
+
89
+module rail_wheel() {
90
+    difference() {
91
+        union() {
92
+            cylinder(d1 = rail_wheel_mid, d2 = rail_wheel_outer, h = (rail_wheel_height - rail_wheel_center_height) / 2);
93
+            
94
+            translate([0, 0, (rail_wheel_height - rail_wheel_center_height) / 2])
95
+            cylinder(d = rail_wheel_outer, h = rail_wheel_center_height);
96
+            
97
+            translate([0, 0, (rail_wheel_height - rail_wheel_center_height) / 2 + rail_wheel_center_height])
98
+            cylinder(d1 = rail_wheel_outer, d2 = rail_wheel_mid, h = (rail_wheel_height - rail_wheel_center_height) / 2);
99
+        }
100
+        translate([0, 0, -1])
101
+        cylinder(d = rail_wheel_inner, rail_wheel_height + 2);
102
+    }
103
+}
104
+
105
+module nema17_holes_face(height, length, hole) {
106
+    translate([nema17_size / 2, nema17_size / 2, height - 4.5])
107
+    for (i = [1, -1])
108
+    for (j = [1, -1])
109
+    translate([i * nema17_hole_off, j * nema17_hole_off, 0])
110
+    cylinder(d = hole, h = length);
111
+}
112
+
113
+module nema17(length) {
114
+    difference() {
115
+        cube([nema17_size, nema17_size, length]);
116
+        nema17_holes_face(length, 5.0, nema17_hole_size);
117
+    }
118
+    
119
+    translate([nema17_size / 2, nema17_size / 2, length]) {
120
+        cylinder(d = nema17_center_size, h = nema17_center_height);
121
+        cylinder(d = nema17_shaft_size, h = nema17_shaft_length);
122
+    }
123
+}
124
+
125
+module dispenser_arm() {
126
+    translate([0, dispenser_arm_tab_off, dispenser_arm_tab_hole_off])
127
+    rotate([90, 0, 0])
128
+    cylinder(d = dispenser_arm_dia, h = dispenser_arm_len);
129
+    
130
+    translate([0, dispenser_arm_tab_off, dispenser_arm_tab_hole_off - dispenser_arm_height])
131
+    cylinder(d = dispenser_arm_dia, h = dispenser_arm_height);
132
+    
133
+    translate([-dispenser_arm_handle_width / 2, dispenser_arm_tab_off - dispenser_arm_len - dispenser_arm_handle_len + dispenser_arm_handle_overlap, dispenser_arm_tab_hole_off + dispenser_arm_dia / 2])
134
+    cube([dispenser_arm_handle_width, dispenser_arm_handle_len, dispenser_arm_handle_height]);
135
+}
136
+
137
+module dispenser() {
138
+    difference() {
139
+        cylinder(d1 = dispenser_nozzle_end_dia_1, d2 = dispenser_nozzle_end_dia_2, h = dispenser_nozzle_end_length);
140
+        translate([0, 0, -0.01])
141
+        cylinder(d1 = dispenser_nozzle_end_dia_1 - dispenser_wall * 2, d2 = dispenser_nozzle_end_dia_2 - dispenser_wall * 2, h = dispenser_nozzle_end_length + 0.02);
142
+    }
143
+    
144
+    translate([0, 0, dispenser_nozzle_end_length])
145
+    difference() {
146
+        cylinder(d1 = dispenser_nozzle_cap_dia_1, d2 = dispenser_nozzle_cap_dia_2, h = dispenser_nozzle_cap_height);
147
+        translate([0, 0, -0.01])
148
+        cylinder(d1 = dispenser_nozzle_cap_dia_1 - dispenser_wall * 2, d2 = dispenser_nozzle_cap_dia_2 - dispenser_wall * 2, h = dispenser_nozzle_cap_height + 0.02);
149
+    }
150
+    
151
+    translate([0, 0, dispenser_nozzle_end_length + dispenser_nozzle_cap_height])
152
+    difference() {
153
+        cylinder(d = dispenser_nozzle_mid_dia, h = dispenser_nozzle_mid_height);
154
+        translate([0, 0, -0.01])
155
+        cylinder(d = dispenser_nozzle_mid_dia - dispenser_wall * 2, h = dispenser_nozzle_mid_height + 0.02);
156
+    }
157
+    
158
+    translate([0, 0, dispenser_nozzle_end_length + dispenser_nozzle_cap_height + dispenser_nozzle_mid_height])
159
+    difference() {
160
+        cylinder(d = dispenser_nozzle_top_dia, h = dispenser_nozzle_top_height);
161
+        translate([0, 0, -0.01])
162
+        cylinder(d = dispenser_nozzle_top_dia - dispenser_wall * 2, h = dispenser_nozzle_top_height + 0.02);
163
+    }
164
+    
165
+    translate([0, 0, dispenser_nozzle_end_length + dispenser_nozzle_cap_height + dispenser_nozzle_mid_height + dispenser_nozzle_top_height])
166
+    difference() {
167
+        cylinder(d1 = dispenser_mid_dia, d2 = dispenser_top_dia, h = dispenser_top_height);
168
+        translate([0, 0, -0.01])
169
+        cylinder(d1 = dispenser_mid_dia - dispenser_wall * 2, d2 = dispenser_top_dia - dispenser_wall * 2, h = dispenser_top_height + 0.02);
170
+    }
171
+    
172
+    translate([0, -dispenser_top_dia / 2, dispenser_nozzle_end_length + dispenser_nozzle_cap_height + dispenser_nozzle_mid_height + dispenser_nozzle_top_height + dispenser_top_height])
173
+    rotate([dispenser_handle_angle, 0, 0])
174
+    translate([0, 0, -dispenser_handle_dia / 2])
175
+    rotate([90, 0, 0])
176
+    cylinder(d = dispenser_handle_dia, h = dispenser_handle_length);
177
+    
178
+    translate([0, dispenser_top_dia / 2 + dispenser_arm_handle_y, dispenser_nozzle_end_length + dispenser_nozzle_cap_height + dispenser_nozzle_mid_height + dispenser_nozzle_top_height + dispenser_top_height + dispenser_arm_handle_z])
179
+    rotate([dispenser_arm_angle_bottom + anim_pos_extruder * (dispenser_arm_angle_top - dispenser_arm_angle_bottom), 0, 0])
180
+    dispenser_arm();
181
+}
182
+
183
+dispenser_arm_angle_top = -5;
184
+dispenser_arm_angle_bottom = 6;
185
+
186
+dispenser();

+ 238
- 0
hardware/config.scad Переглянути файл

@@ -0,0 +1,238 @@
1
+// 3d printer specific
2
+screw_gap = 0.3;
3
+nut_gap = -0.1;
4
+
5
+dispenser_top_dia = 200;
6
+dispenser_top_height = 108;
7
+dispenser_mid_dia = 35.5;
8
+dispenser_nozzle_top_height = 45;
9
+dispenser_nozzle_top_dia = 35.3;
10
+dispenser_nozzle_mid_height = 20;
11
+dispenser_nozzle_mid_dia = 40;
12
+dispenser_nozzle_cap_height = 17;
13
+dispenser_nozzle_cap_dia_1 = 5.8;
14
+dispenser_nozzle_cap_dia_2 = dispenser_nozzle_mid_dia;
15
+dispenser_nozzle_end_length = 10;
16
+dispenser_nozzle_end_dia_1 = 3.4;
17
+dispenser_nozzle_end_dia_2 = dispenser_nozzle_cap_dia_1;
18
+dispenser_wall = 3;
19
+dispenser_handle_dia = 21;
20
+dispenser_handle_length = 100;
21
+dispenser_handle_angle = 38;
22
+
23
+dispenser_arm_dia = 7.0;
24
+dispenser_arm_len = 250;
25
+dispenser_arm_height = 75;
26
+dispenser_arm_tab_off = 21;
27
+dispenser_arm_tab_hole_off = 14;
28
+dispenser_arm_handle_overlap = 20;
29
+dispenser_arm_handle_width = 20;
30
+dispenser_arm_handle_len = 30;
31
+dispenser_arm_handle_height = 2;
32
+dispenser_arm_handle_y = 10;
33
+dispenser_arm_handle_z = 15;
34
+
35
+rail_wheel_height = 11;
36
+rail_wheel_center_height = 5;
37
+rail_wheel_outer = 24;
38
+rail_wheel_mid = 18;
39
+rail_wheel_inner = 5;
40
+
41
+nema17_len = 40;
42
+nema17_size = 42.3;
43
+nema17_hole_off = 31.0 / 2;
44
+nema17_hole_size = 3.0;
45
+nema17_shaft_size = 5.0;
46
+nema17_shaft_length = 24.0;
47
+nema17_center_size = 22.0;
48
+nema17_center_height = 2.0;
49
+
50
+motor_mount_height = 8;
51
+motor_mount_length = 35;
52
+motor_mount_l = nema17_size + motor_mount_length;
53
+motor_mount_hole_size_nominal = 5;
54
+motor_mount_hole_size = motor_mount_hole_size_nominal + screw_gap;
55
+motor_mount_hole_off = motor_mount_length - 15;
56
+
57
+belt_width = 6;
58
+belt_pitch = 2;
59
+belt_thickness = 1.35;
60
+
61
+/**********************************
62
+ ************ Extruder ************
63
+ **********************************/
64
+
65
+function dia_from_teeth(teeth) = teeth * belt_pitch / 3.14159;
66
+
67
+pulley_teeth_height = belt_width + 4;
68
+pulley_mount_height = 5;
69
+pulley_mount_dia = 8;
70
+pulley_height = pulley_teeth_height + pulley_mount_height;
71
+
72
+large_teeth = 60;
73
+small_teeth = 20;
74
+
75
+large_dia = dia_from_teeth(large_teeth);
76
+small_dia = dia_from_teeth(small_teeth);
77
+perimeter_large_wheel = large_dia * 3.14159;
78
+perimeter_small_wheel = small_dia * 3.14159;
79
+
80
+axis_diameter = 5.0;
81
+axis_hole_diameter = axis_diameter + screw_gap;
82
+
83
+// MR115 2RS
84
+bearing_inner = axis_diameter;
85
+bearing_outer = 11.0 + 0.1;
86
+bearing_height = 4.0;
87
+
88
+belt_length = 200;
89
+belt_length_wheels = perimeter_large_wheel / 2 + perimeter_small_wheel / 2;
90
+belt_length_center = belt_length - belt_length_wheels;
91
+gears_dist = belt_length_center / 2;
92
+
93
+gear_stages = 1;
94
+gear_stage_height = pulley_height + 2;
95
+
96
+gear_stages_dist = (bearing_height + 1) * 2;
97
+gearbox_wall = gear_stages_dist; //bearing_height + 1;
98
+
99
+gearbox_gap = 2;
100
+gearbox_height = gears_dist + large_dia + (gearbox_wall + gearbox_gap) * 2;
101
+gearbox_width = large_dia + (gearbox_wall + gearbox_gap) * 2;
102
+gearbox_depth = 2 * gearbox_wall + gear_stages * gear_stage_height + (gear_stages - 1) * gear_stages_dist;
103
+
104
+extruder_travel = 60;
105
+
106
+piston_dia = 30;
107
+piston_height = 30;
108
+piston_gap = 0.1;
109
+piston_wall = 3;
110
+piston_radius = 3;
111
+piston_bottom_gap = piston_wall + 10;
112
+cylinder_dia = piston_dia + 2 * (piston_wall + piston_gap);
113
+cylinder_height = piston_height + extruder_travel;
114
+
115
+actuator_length = 100;
116
+
117
+extruder_lever_width = 10;
118
+extruder_lever_depth = 5;
119
+extruder_lever_holes = 4.2; // TODO
120
+extruder_lever_hole_dist = extruder_travel / 2;
121
+extruder_lever_length = extruder_lever_hole_dist + 10;
122
+
123
+extruder_wall_screw = 3.0;
124
+extruder_wall_hole_screw = extruder_wall_screw + screw_gap;
125
+extruder_wall_hole_nut = extruder_wall_screw + nut_gap;
126
+extruder_wall_hole_depth = 8.0;
127
+
128
+additional_piston_offset = 8;
129
+
130
+/***********************************
131
+ ************** Table **************
132
+ ***********************************/
133
+
134
+// size of woking area
135
+plate_x = 250;
136
+plate_y = 350;
137
+plate_z = 5;
138
+
139
+plate_mount_screws_nominal = 5.0;
140
+plate_mount_screws_distance_x = 60;
141
+plate_mount_screws_distance_y = 80;
142
+plate_mount_screw_hole = plate_mount_screws_nominal + screw_gap;
143
+
144
+belt_slot_width = belt_width + 4;
145
+belt_slot_depth = belt_thickness + 2;
146
+belt_mount_width = belt_slot_width + 2;
147
+belt_mount_depth = belt_slot_depth + 4;
148
+belt_mount_full_width = belt_mount_width * 3;
149
+
150
+y_carriage_add_material_around_holes = 10;
151
+y_carriage_h = 10;
152
+y_carriage_rail_dist = 6.5;
153
+
154
+y_carriage_post_dia = 2 * 13 / sqrt(3);
155
+y_carriage_post_screw = 5.0;
156
+y_carriage_post_hole_off = 2;
157
+y_carriage_post_center = 1;
158
+y_carriage_post_screw_hole = y_carriage_post_screw + nut_gap;
159
+y_carriage_post_len = y_carriage_rail_dist - rail_wheel_height / 2 + 10;
160
+
161
+y_carriage_wheel_off_x = 20.4;
162
+y_carriage_wheel_off_y = 28;
163
+
164
+y_carriage_pulley_off = y_carriage_rail_dist - rail_wheel_height / 2 + 10;
165
+
166
+y_carriage_x = plate_mount_screws_distance_x + 2 * y_carriage_add_material_around_holes;
167
+y_carriage_y = plate_mount_screws_distance_y + 2 * y_carriage_add_material_around_holes;
168
+
169
+y_carriage_wheel_x_dist = y_carriage_x - 2 * y_carriage_wheel_off_x;
170
+y_carriage_wheel_y_dist = y_carriage_y - 2 * y_carriage_wheel_off_y;
171
+
172
+x_carriage_holder_w = y_carriage_x;
173
+x_carriage_holder_l = (y_carriage_y - 20) / 2;
174
+x_carriage_holder_h = 4;
175
+x_carriage_holder_rail_hole_dist = x_carriage_holder_w - 20;
176
+x_carriage_holder_hole_off = x_carriage_holder_h + 10;
177
+
178
+ideal_belt_pulley_dia = 20 - belt_thickness * 2 + y_carriage_rail_dist + belt_thickness / 4;
179
+belt_pulley_off = y_carriage_rail_dist / 2 - belt_thickness / 4;
180
+
181
+teethcount = round((ideal_belt_pulley_dia + belt_thickness) * 3.14159 / belt_pitch);
182
+echo("belt pulley teeth count", teethcount);
183
+real_belt_pulley_dia = teethcount * belt_pitch / 3.14159;
184
+belt_pulley_width = belt_width + 4;
185
+belt_pulley_tooth_width = belt_width + 2;
186
+
187
+belt_pulley_rim = 1;
188
+belt_pulley_axis_hole = nema17_shaft_size + screw_gap;
189
+belt_pulley_fix_dia = 3.0 + nut_gap;
190
+
191
+belt_tensioner_screw = 3.0;
192
+belt_tensioner_screw_hole = belt_tensioner_screw + screw_gap;
193
+belt_tensioner_wall = 5;
194
+belt_tensioner_mount_depth = 20;
195
+belt_tensioner_travel = 15;
196
+belt_tensioner_moving_height = 10;
197
+belt_tensioner_moving_len = real_belt_pulley_dia / 2 + 20;
198
+belt_tensioner_moving_overlap = 10;
199
+belt_tensioner_moving_gap = 0.3;
200
+belt_tensioner_diff_len = real_belt_pulley_dia / 2 + belt_tensioner_moving_len - belt_tensioner_moving_overlap + belt_tensioner_travel + 5;
201
+belt_tensioner_diff_width = belt_pulley_width + 2 * belt_tensioner_moving_gap + 0.5;
202
+belt_tensioner_diff_height = belt_tensioner_moving_height + 0.5;
203
+
204
+y_axis_travel_len = plate_y + 15;
205
+y_axis_rail_len = y_axis_travel_len + y_carriage_y + motor_mount_length + belt_tensioner_mount_depth;
206
+
207
+x_axis_travel_len = plate_x + 15;
208
+x_axis_rail_len = x_axis_travel_len + y_carriage_y + motor_mount_length + belt_tensioner_mount_depth;
209
+
210
+// TODO!
211
+point_that_reaches_everywhere_x = -7.5;
212
+point_that_reaches_everywhere_y = -17.5;
213
+
214
+use_anim = true;
215
+x_axis_position = 1.0;
216
+y_axis_position = 0.5;
217
+
218
+anim_pos_x = use_anim ? sin($t * 360) * 0.5 + 0.5 : x_axis_position;
219
+anim_pos_y = use_anim ? sin($t * 360 + 90) * 0.5 + 0.5 : y_axis_position;
220
+echo("animation position x", anim_pos_x);
221
+echo("animation position y", anim_pos_y);
222
+
223
+x_axis_animation_position = anim_pos_x * x_axis_travel_len;
224
+y_axis_animation_position = anim_pos_y * y_axis_travel_len;
225
+
226
+extruder_axis_position = 1.0;
227
+
228
+anim_pos_extruder = use_anim ? sin($t * 360) * 0.5 + 0.5 : extruder_axis_position;
229
+extruder_axis_anim_position = anim_pos_extruder * extruder_travel;
230
+
231
+draw_pulleys = false;
232
+
233
+left_support_len = 200;
234
+left_support_off = 50;
235
+right_support_len = 200;
236
+right_support_off = 50;
237
+
238
+echo("distance between bottom support rails", x_axis_rail_len - left_support_off - right_support_off - 40, -left_support_off, -right_support_off);

+ 75
- 0
hardware/fuellfix.scad Переглянути файл

@@ -0,0 +1,75 @@
1
+include <config.scad>;
2
+use <table.scad>;
3
+use <gearbox.scad>;
4
+use <common.scad>;
5
+
6
+draw_assembly = true;
7
+
8
+module print() {
9
+    for (i = [1 : 4])
10
+    translate([0, (i - 2) * (real_belt_pulley_dia + 20), 0])
11
+    belt_pulley(teethcount, real_belt_pulley_dia);
12
+    
13
+    translate([y_carriage_x + real_belt_pulley_dia, 0, y_carriage_h])
14
+    rotate([0, 180, 0])
15
+    y_carriage(1); // x carriage
16
+    
17
+    translate([10 + 2 * y_carriage_x + real_belt_pulley_dia, 0, y_carriage_h])
18
+    rotate([0, 180, 0])
19
+    y_carriage(2); // y carriage
20
+    
21
+    translate([y_carriage_x / 2 + real_belt_pulley_dia, -10 - y_carriage_y / 2, 0])
22
+    y_carriage_posts();
23
+    
24
+    translate([10 + 3 * y_carriage_x / 2 + real_belt_pulley_dia, -10 - y_carriage_y / 2, 0])
25
+    y_carriage_posts();
26
+    
27
+    for (i = [1, -1])
28
+    scale([1, i, 1])
29
+    translate([20 + 2 * y_carriage_x + real_belt_pulley_dia, 5, 0])
30
+    x_carriage_holder();
31
+    
32
+    for (i = [0, 20 + 2 * belt_tensioner_wall + 10])
33
+    translate([-real_belt_pulley_dia - 10 - i, 0, 0]) {
34
+        translate([0, belt_tensioner_moving_len, belt_tensioner_moving_height / 2])
35
+        belt_tensioner_moving();
36
+        
37
+        translate([0, -20, 20 + belt_tensioner_wall])
38
+        rotate([0, 180, 0])
39
+        belt_tensioner_mount(2);
40
+    }
41
+    
42
+    for (i = [0, 70])
43
+    translate([-real_belt_pulley_dia - i, belt_tensioner_moving_len + 20, 0])
44
+    rotate([0, -90, 0])
45
+    motor_mount(2);
46
+}
47
+
48
+top_rail_len = x_axis_rail_len + plate_x - 70;
49
+top_rail_height = 200;
50
+top_rail_off = 150;
51
+
52
+echo("top rail length", top_rail_len);
53
+
54
+module fuellfix_assembly() {
55
+    xy_table();
56
+    
57
+    %color("magenta")
58
+    dispenser();
59
+    
60
+    translate([0, 0, 200 + 100])
61
+    whole_extruder();
62
+    
63
+    translate([-top_rail_len / 2, top_rail_off, top_rail_height])
64
+    rail_2020_x(top_rail_len, "top rail");
65
+}
66
+
67
+echo(); echo(); echo();    
68
+    
69
+if (draw_assembly) {
70
+    fuellfix_assembly();
71
+} else {
72
+    print();
73
+}
74
+    
75
+echo(); echo(); echo();

+ 239
- 0
hardware/gearbox.scad Переглянути файл

@@ -0,0 +1,239 @@
1
+include <config.scad>;
2
+use <gt2_pulley.scad>;
3
+use <common.scad>
4
+
5
+$fn = 42;
6
+
7
+echo("extruder gear factor", pow(large_teeth / small_teeth, gear_stages));
8
+
9
+module gear_pulley(dia, teeth) {
10
+    if (draw_pulleys) {
11
+        gt2_2mm_pulley(teeth, pulley_teeth_height);
12
+    } else {
13
+        cylinder(d = dia, h = pulley_teeth_height);
14
+    }
15
+    
16
+    translate([0, 0, pulley_teeth_height])
17
+    cylinder(d = pulley_mount_dia, h = pulley_mount_height);
18
+}
19
+
20
+module gear_stage() {
21
+    translate([0, gears_dist / 2, (gear_stage_height - pulley_height) / 2]) {
22
+        %color("yellow")
23
+        rotate([0, 0, -acos(anim_pos_extruder * -2 + 1)])
24
+        gear_pulley(large_dia, large_teeth);
25
+        
26
+        %color("yellow")
27
+        translate([0, -gears_dist, 0])
28
+        rotate([0, 0, -acos(anim_pos_extruder * -2 + 1)])
29
+        gear_pulley(small_dia, small_teeth);
30
+    }
31
+}
32
+
33
+module center_plate() {
34
+    difference() {
35
+        cube([gearbox_width, gearbox_height, gear_stages_dist]);
36
+        
37
+        for(i = [-1, 1])
38
+        translate([gearbox_width / 2, gearbox_height / 2 + i * gears_dist / 2, 0]) {
39
+            for(j = [-1, gear_stages_dist - bearing_height])
40
+            translate([0, 0, j])
41
+            cylinder(d = bearing_outer, h = bearing_height + 1);
42
+        
43
+            translate([0, 0, -1])
44
+            cylinder(d = axis_hole_diameter, h = gear_stages_dist + 2);
45
+        }
46
+        
47
+        for (i = [0, gearbox_width - gear_stages_dist])
48
+        for (j = [-1, gearbox_height - extruder_wall_hole_depth])
49
+        translate([gear_stages_dist / 2 + i, j, gear_stages_dist / 2])
50
+        rotate([-90, 0, 0])
51
+        cylinder(d = extruder_wall_hole_nut, h = extruder_wall_hole_depth + 1);
52
+    }
53
+}
54
+
55
+module outer_plate() {
56
+    difference() {
57
+        cube([gearbox_width, gearbox_height, gearbox_wall]);
58
+        
59
+        for (i = [0, gearbox_width - gearbox_wall])
60
+        for (j = [-1, gearbox_height - extruder_wall_hole_depth])
61
+        translate([gearbox_wall / 2 + i, j, gearbox_wall / 2])
62
+        rotate([-90, 0, 0])
63
+        cylinder(d = extruder_wall_hole_nut, h = extruder_wall_hole_depth + 1);
64
+    }
65
+}
66
+
67
+module gearbox() {
68
+    // back wall
69
+    color("cyan")
70
+    translate([-gearbox_width / 2, -gearbox_height / 2, -gearbox_wall])
71
+    outer_plate();
72
+    
73
+    // front wall
74
+    color("cyan")
75
+    translate([-gearbox_width / 2, -gearbox_height / 2, gear_stage_height * gear_stages + gear_stages_dist * (gear_stages - 1)])
76
+    difference() {
77
+        outer_plate();
78
+        
79
+        translate([0, (gear_stages % 2) ? 0 : gears_dist, 0])
80
+        translate([(gearbox_width - nema17_size) / 2, -nema17_size / 2 + (gearbox_height - gears_dist) / 2, 0]) {
81
+            nema17_holes_face(3, motor_mount_height + 5, nema17_hole_size + screw_gap);
82
+            
83
+            translate([nema17_size / 2, nema17_size / 2, -1])
84
+            cylinder(d = nema17_center_size + 2, h = gearbox_wall + 2);
85
+        }
86
+    }
87
+
88
+    %color("yellow")
89
+    translate([0, (gear_stages % 2) ? 0 : gears_dist, 0])
90
+    translate([-gearbox_width / 2, -gearbox_height / 2, gear_stage_height * gear_stages + gear_stages_dist * (gear_stages - 1)])
91
+    translate([0, nema17_size, nema17_len + gearbox_wall])
92
+    translate([(gearbox_width - nema17_size) / 2, -nema17_size / 2 + (gearbox_height - gears_dist) / 2, 0])
93
+    rotate([180, 0, 0])
94
+    nema17(nema17_len);
95
+
96
+    for (i = [0 : gear_stages - 1])
97
+    translate([0, 0, i * (gear_stage_height + gear_stages_dist)])
98
+    rotate([0, 0, i * 180]) {
99
+        gear_stage();
100
+        
101
+        color("cyan")
102
+        if (i < (gear_stages - 1))
103
+        translate([-gearbox_width / 2, -gearbox_height / 2, gear_stage_height])
104
+        center_plate();
105
+    }
106
+}
107
+
108
+module outer_bearings() {
109
+    cylinder(d = bearing_outer, h = bearing_height + 0.1);
110
+    
111
+    translate([0, 0, -gearbox_wall + bearing_height - 1])
112
+    cylinder(d = axis_hole_diameter, h = gear_stages * gear_stage_height + gearbox_wall * 2 + gear_stages_dist * (gear_stages - 1) + 2);
113
+    
114
+    translate([0, 0, gear_stage_height * gear_stages + gear_stages_dist * (gear_stages - 1) + bearing_height - 0.1])
115
+    cylinder(d = bearing_outer, h = bearing_height + 0.1);
116
+}
117
+
118
+module top_cover() {
119
+    difference() {
120
+        cube([gearbox_width, gearbox_wall, gearbox_depth]);
121
+        
122
+        for (i = [0, gearbox_width - gearbox_wall])
123
+        for (j = [gearbox_wall / 2, gearbox_depth - gearbox_wall / 2])
124
+        translate([gearbox_wall / 2 + i, -1, j])
125
+        rotate([-90, 0, 0])
126
+        cylinder(d = extruder_wall_hole_screw, h = gearbox_wall + 2);
127
+        
128
+        for (i = [0, gearbox_width - gear_stages_dist])
129
+        if (gear_stages > 1)
130
+        for (j = [1 : gear_stages - 1])
131
+        translate([gear_stages_dist / 2 + i, -1, j * (gear_stage_height + gear_stages_dist) + gear_stages_dist / 2])
132
+        rotate([-90, 0, 0])
133
+        cylinder(d = extruder_wall_hole_screw, h = gearbox_wall + 2);
134
+    }
135
+}
136
+
137
+module gearbox_assembly() {
138
+    difference() {
139
+        gearbox();
140
+        
141
+        for (i = [-1, 1])
142
+        translate([0, i * gears_dist / 2, -bearing_height])
143
+        outer_bearings();
144
+    }
145
+    
146
+    color("green")
147
+    for (i = [-1, 1])
148
+    scale([1, i, 1])
149
+    translate([-gearbox_width / 2, gearbox_height / 2, -gearbox_wall])
150
+    top_cover();
151
+    
152
+    %color("grey")
153
+    for (i = [-1, 1])
154
+    translate([0, i * gears_dist / 2, -gearbox_wall - 1])
155
+    cylinder(d = axis_diameter, h = gear_stages * gear_stage_height + gearbox_wall * 2 + gear_stages_dist * (gear_stages - 1) + 2);
156
+}
157
+
158
+module piston() {
159
+    //cylinder(d = piston_dia, h = piston_height);
160
+    roundedcylinder(piston_dia, piston_height, piston_radius, true);
161
+}
162
+
163
+module piston_cyl() {
164
+    difference() {
165
+        cylinder(d = cylinder_dia, h = cylinder_height);
166
+        
167
+        translate([0, 0, piston_wall])
168
+        cylinder(d = piston_dia + 2 * piston_gap, h = cylinder_height + 2);
169
+    }
170
+}
171
+
172
+module piston_visual() {
173
+    color("blue")
174
+    difference() {
175
+        piston_cyl();
176
+        
177
+        translate([-cylinder_dia / 2, -cylinder_dia / 2 - 1, -1])
178
+        cube([cylinder_dia, cylinder_dia / 2 + 1, cylinder_height + 2]);
179
+    }
180
+    
181
+    translate([0, 0, piston_bottom_gap])
182
+    translate([0, 0, extruder_axis_anim_position]) {
183
+        color("green")
184
+        piston();
185
+        
186
+        %color("orange")
187
+        translate([0, 0, -actuator_length])
188
+        cylinder(d = 8, h = actuator_length);
189
+    }
190
+}
191
+
192
+module extruder_lever() {
193
+    translate([-extruder_lever_width / 2, 0, -extruder_lever_length + (extruder_lever_length - extruder_lever_hole_dist) / 2])
194
+    difference() {
195
+        cube([extruder_lever_width, extruder_lever_depth, extruder_lever_length]);
196
+        
197
+        translate([extruder_lever_width / 2, -1, (extruder_lever_length - extruder_lever_hole_dist) / 2])
198
+        rotate([-90, 0, 0]) {
199
+            for (i = [0, extruder_lever_hole_dist])
200
+            translate([0, -i, 0])
201
+            cylinder(d = extruder_lever_holes, h = extruder_lever_depth + 2);
202
+        }
203
+    }
204
+}
205
+
206
+module extruder() {
207
+    translate([0, gearbox_depth - gearbox_wall, -gears_dist / 2])
208
+    rotate([90, 0, 0])
209
+    translate([0, 0, gearbox_depth - gearbox_wall * 2])
210
+    rotate([0, 180, 0])
211
+    gearbox_assembly();
212
+    
213
+    translate([0, -cylinder_dia / 2, -cylinder_height - extruder_travel / 2]) {
214
+        translate([0, 0, -additional_piston_offset])
215
+        piston_visual();
216
+        
217
+        color("red")
218
+        translate([0, 0, cylinder_height + extruder_travel / 2])
219
+        rotate([0, -acos(anim_pos_extruder * -2 + 1), 0])
220
+        extruder_lever();
221
+    }
222
+}
223
+
224
+module whole_extruder() {
225
+    translate([0, 0, cylinder_height + extruder_travel / 2 + additional_piston_offset])
226
+    extruder();
227
+}
228
+
229
+//gearbox_assembly();
230
+//piston();
231
+//piston_cyl();
232
+//extruder_lever();
233
+//center_plate();
234
+//outer_plate();
235
+//top_cover();
236
+
237
+//piston_visual();
238
+
239
+whole_extruder();

+ 294
- 0
hardware/gt2_pulley.scad Переглянути файл

@@ -0,0 +1,294 @@
1
+// Parametric Pulley with multiple belt profiles
2
+// by droftarts January 2012
3
+// slightly modified for easier module use by xythobuz, 2021
4
+
5
+// Based on pulleys by:
6
+// http://www.thingiverse.com/thing:11256 by me!
7
+// https://github.com/prusajr/PrusaMendel by Josef Prusa
8
+// http://www.thingiverse.com/thing:3104 by GilesBathgate
9
+// http://www.thingiverse.com/thing:2079 by nophead
10
+
11
+// dxf tooth data from http://oem.cadregister.com/asp/PPOW_Entry.asp?company=915217&elementID=07807803/METRIC/URETH/WV0025/F
12
+// pulley diameter checked and modelled from data at http://www.sdp-si.com/D265/HTML/D265T016.html
13
+
14
+/**
15
+ * @name Pulley
16
+ * @category Printed
17
+ * @using 1 x m3 nut, normal or nyloc
18
+ * @using 1 x m3x10 set screw or 1 x m3x8 grub screw
19
+ */
20
+
21
+
22
+// tuneable constants
23
+
24
+teeth_example = 20;			// Number of teeth, standard Mendel T5 belt = 8, gives Outside Diameter of 11.88mm
25
+profile = 12;		// 1=MXL 2=40DP 3=XL 4=H 5=T2.5 6=T5 7=T10 8=AT5 9=HTD_3mm 10=HTD_5mm 11=HTD_8mm 12=GT2_2mm 13=GT2_3mm 14=GT2_5mm
26
+
27
+motor_shaft = 0; //5.2;	// NEMA17 motor shaft exact diameter = 5
28
+m3_dia = 3.2;		// 3mm hole diameter
29
+m3_nut_hex = 1;		// 1 for hex, 0 for square nut
30
+m3_nut_flats = 5.7;	// normal M3 hex nut exact width = 5.5
31
+m3_nut_depth = 2.7;	// normal M3 hex nut exact depth = 2.4, nyloc = 4
32
+
33
+retainer = 0;		// Belt retainer above teeth, 0 = No, 1 = Yes
34
+retainer_ht = 1.5;	// height of retainer flange over pulley, standard = 1.5
35
+idler = 0;			// Belt retainer below teeth, 0 = No, 1 = Yes
36
+idler_ht = 1.5;		// height of idler flange over pulley, standard = 1.5
37
+
38
+pulley_t_ht_example = 10;	// length of toothed part of pulley, standard = 12
39
+pulley_b_ht = 0; //8;		// pulley base height, standard = 8. Set to same as idler_ht if you want an idler but no pulley.
40
+pulley_b_dia = 20;	// pulley base diameter, standard = 20
41
+no_of_nuts = 1;		// number of captive nuts required, standard = 1
42
+nut_angle = 90;		// angle between nuts, standard = 90
43
+nut_shaft_distance = 1.2;	// distance between inner face of nut and shaft, can be negative.
44
+
45
+
46
+//	********************************
47
+//	** Scaling tooth for good fit **
48
+//	********************************
49
+/*	To improve fit of belt to pulley, set the following constant. Decrease or increase by 0.1mm at a time. We are modelling the *BELT* tooth here, not the tooth on the pulley. Increasing the number will *decrease* the pulley tooth size. Increasing the tooth width will also scale proportionately the tooth depth, to maintain the shape of the tooth, and increase how far into the pulley the tooth is indented. Can be negative */
50
+
51
+additional_tooth_width = 0.2; //mm
52
+
53
+//	If you need more tooth depth than this provides, adjust the following constant. However, this will cause the shape of the tooth to change.
54
+
55
+additional_tooth_depth = 0; //mm
56
+
57
+// calculated constants
58
+
59
+nut_elevation = pulley_b_ht/2;
60
+m3_nut_points = 2*((m3_nut_flats/2)/cos(30)); // This is needed for the nut trap
61
+
62
+// The following set the pulley diameter for a given number of teeth
63
+
64
+MXL_pulley_dia = tooth_spacing (2.032,0.254);
65
+40DP_pulley_dia = tooth_spacing (2.07264,0.1778);
66
+XL_pulley_dia = tooth_spacing (5.08,0.254);
67
+H_pulley_dia = tooth_spacing (9.525,0.381);
68
+T2_5_pulley_dia = tooth_spaceing_curvefit (0.7467,0.796,1.026);
69
+T5_pulley_dia = tooth_spaceing_curvefit (0.6523,1.591,1.064);
70
+T10_pulley_dia = tooth_spacing (10,0.93);
71
+AT5_pulley_dia = tooth_spaceing_curvefit (0.6523,1.591,1.064);
72
+HTD_3mm_pulley_dia = tooth_spacing (3,0.381);
73
+HTD_5mm_pulley_dia = tooth_spacing (5,0.5715);
74
+HTD_8mm_pulley_dia = tooth_spacing (8,0.6858);
75
+GT2_2mm_pulley_dia = tooth_spacing (2,0.254);
76
+GT2_3mm_pulley_dia = tooth_spacing (3,0.381);
77
+GT2_5mm_pulley_dia = tooth_spacing (5,0.5715);
78
+
79
+// The following calls the pulley creation part, and passes the pulley diameter and tooth width to that module
80
+
81
+if ( profile == 1 ) { pulley ( "MXL" , MXL_pulley_dia , 0.508 , 1.321 ); }
82
+if ( profile == 2 ) { pulley ( "40 D.P." , 40DP_pulley_dia , 0.457 , 1.226 ); }
83
+if ( profile == 3 ) { pulley ( "XL" , XL_pulley_dia , 1.27, 3.051 ); }
84
+if ( profile == 4 ) { pulley ( "H" , H_pulley_dia ,1.905 , 5.359 ); }
85
+if ( profile == 5 ) { pulley ( "T2.5" , T2_5_pulley_dia , 0.7 , 1.678 ); }
86
+if ( profile == 6 ) { pulley ( "T5" , T5_pulley_dia , 1.19 , 3.264 ); }
87
+if ( profile == 7 ) { pulley ( "T10" , T10_pulley_dia , 2.5 , 6.13 ); }
88
+if ( profile == 8 ) { pulley ( "AT5" , AT5_pulley_dia , 1.19 , 4.268 ); }
89
+if ( profile == 9 ) { pulley ( "HTD 3mm" , HTD_3mm_pulley_dia , 1.289 , 2.27 ); }
90
+if ( profile == 10 ) { pulley ( "HTD 5mm" , HTD_5mm_pulley_dia , 2.199 , 3.781 ); }
91
+if ( profile == 11 ) { pulley ( "HTD 8mm" , HTD_8mm_pulley_dia , 3.607 , 6.603 ); }
92
+if ( profile == 12 ) { pulley ( "GT2 2mm" , GT2_2mm_pulley_dia , 0.764 , 1.494 ); }
93
+if ( profile == 13 ) { pulley ( "GT2 3mm" , GT2_3mm_pulley_dia , 1.169 , 2.31 ); }
94
+if ( profile == 14 ) { pulley ( "GT2 5mm" , GT2_5mm_pulley_dia , 1.969 , 3.952 ); }
95
+
96
+// Functions
97
+
98
+function tooth_spaceing_curvefit (b,c,d, teeth = teeth_example)
99
+	= ((c * pow(teeth,d)) / (b + pow(teeth,d))) * teeth ;
100
+
101
+function tooth_spacing(tooth_pitch,pitch_line_offset, teeth = teeth_example)
102
+	= (2*((teeth*tooth_pitch)/(3.14159265*2)-pitch_line_offset)) ;
103
+
104
+// Main Module
105
+
106
+module gt2_2mm_pulley(teeth, height) {
107
+    pulley("GT2 2mm", tooth_spacing (2,0.254, teeth), 0.764, 1.494, teeth, height);
108
+}
109
+
110
+module pulley( belt_type , pulley_OD , tooth_depth , tooth_width, teeth = teeth_example, pulley_t_ht = pulley_t_ht_example )
111
+	{
112
+	echo (str("Belt type = ",belt_type,"; Number of teeth = ",teeth,"; Pulley Outside Diameter = ",pulley_OD,"mm "));
113
+	tooth_distance_from_centre = sqrt( pow(pulley_OD/2,2) - pow((tooth_width+additional_tooth_width)/2,2));
114
+	tooth_width_scale = (tooth_width + additional_tooth_width ) / tooth_width;
115
+	tooth_depth_scale = ((tooth_depth + additional_tooth_depth ) / tooth_depth) ;
116
+
117
+
118
+//	************************************************************************
119
+//	*** uncomment the following line if pulley is wider than puller base ***
120
+//	************************************************************************
121
+
122
+//	translate ([0,0, pulley_b_ht + pulley_t_ht + retainer_ht ]) rotate ([0,180,0])
123
+
124
+	difference()
125
+	 {	 
126
+		union()
127
+		{
128
+			//base
129
+	
130
+			if ( pulley_b_ht < 2 ) {
131
+                //echo ("CAN'T DRAW PULLEY BASE, HEIGHT LESS THAN 2!!!");
132
+            } else {
133
+				rotate_extrude($fn=pulley_b_dia*2)
134
+				{
135
+						square([pulley_b_dia/2-1,pulley_b_ht]);
136
+						square([pulley_b_dia/2,pulley_b_ht-1]);
137
+						translate([pulley_b_dia/2-1,pulley_b_ht-1]) circle(1);
138
+				}
139
+			}
140
+	
141
+		difference()
142
+			{
143
+			//shaft - diameter is outside diameter of pulley
144
+			
145
+			translate([0,0,pulley_b_ht]) 
146
+			rotate ([0,0,360/(teeth*4)]) 
147
+			cylinder(r=pulley_OD/2,h=pulley_t_ht, $fn=teeth*4);
148
+	
149
+			//teeth - cut out of shaft
150
+		
151
+			for(i=[1:teeth]) 
152
+			rotate([0,0,i*(360/teeth)])
153
+			translate([0,-tooth_distance_from_centre,pulley_b_ht -1]) 
154
+			scale ([ tooth_width_scale , tooth_depth_scale , 1 ]) 
155
+			{
156
+			if ( profile == 1 ) { MXL(pulley_t_ht);}
157
+			if ( profile == 2 ) { 40DP(pulley_t_ht);}
158
+			if ( profile == 3 ) { XL(pulley_t_ht);}
159
+			if ( profile == 4 ) { H(pulley_t_ht);}
160
+			if ( profile == 5 ) { T2_5(pulley_t_ht);}
161
+			if ( profile == 6 ) { T5(pulley_t_ht);}
162
+			if ( profile == 7 ) { T10(pulley_t_ht);}
163
+			if ( profile == 8 ) { AT5(pulley_t_ht);}
164
+			if ( profile == 9 ) { HTD_3mm(pulley_t_ht);}
165
+			if ( profile == 10 ) { HTD_5mm(pulley_t_ht);}
166
+			if ( profile == 11 ) { HTD_8mm(pulley_t_ht);}
167
+			if ( profile == 12 ) { GT2_2mm(pulley_t_ht);}
168
+			if ( profile == 13 ) { GT2_3mm(pulley_t_ht);}
169
+			if ( profile == 14 ) { GT2_5mm(pulley_t_ht);}
170
+			}
171
+
172
+			}
173
+			
174
+		//belt retainer / idler
175
+		if ( retainer > 0 ) {translate ([0,0, pulley_b_ht + pulley_t_ht ]) 
176
+		rotate_extrude($fn=teeth*4)  
177
+		polygon([[0,0],[pulley_OD/2,0],[pulley_OD/2 + retainer_ht , retainer_ht],[0 , retainer_ht],[0,0]]);}
178
+		
179
+		if ( idler > 0 ) {translate ([0,0, pulley_b_ht - idler_ht ]) 
180
+		rotate_extrude($fn=teeth*4)  
181
+		polygon([[0,0],[pulley_OD/2 + idler_ht,0],[pulley_OD/2 , idler_ht],[0 , idler_ht],[0,0]]);}
182
+	
183
+		}
184
+	   
185
+		//hole for motor shaft
186
+		translate([0,0,-1])cylinder(r=motor_shaft/2,h=pulley_b_ht + pulley_t_ht + retainer_ht + 2,$fn=motor_shaft*4);
187
+				
188
+		//captive nut and grub screw holes
189
+	
190
+		if ( pulley_b_ht < m3_nut_flats ) {
191
+            //echo ("CAN'T DRAW CAPTIVE NUTS, HEIGHT LESS THAN NUT DIAMETER!!!");
192
+        } else {
193
+		if ( (pulley_b_dia - motor_shaft)/2 < m3_nut_depth + 3 ) {
194
+            //echo ("CAN'T DRAW CAPTIVE NUTS, DIAMETER TOO SMALL FOR NUT DEPTH!!!");
195
+        } else {
196
+	
197
+			for(j=[1:no_of_nuts]) rotate([0,0,j*nut_angle])
198
+			translate([0,0,nut_elevation])rotate([90,0,0])
199
+	
200
+			union()
201
+			{
202
+				//entrance
203
+				translate([0,-pulley_b_ht/4-0.5,motor_shaft/2+m3_nut_depth/2+nut_shaft_distance]) cube([m3_nut_flats,pulley_b_ht/2+1,m3_nut_depth],center=true);
204
+	
205
+				//nut
206
+				if ( m3_nut_hex > 0 )
207
+					{
208
+						// hex nut
209
+						translate([0,0.25,motor_shaft/2+m3_nut_depth/2+nut_shaft_distance]) rotate([0,0,30]) cylinder(r=m3_nut_points/2,h=m3_nut_depth,center=true,$fn=6);
210
+					} else {
211
+						// square nut
212
+						translate([0,0.25,motor_shaft/2+m3_nut_depth/2+nut_shaft_distance]) cube([m3_nut_flats,m3_nut_flats,m3_nut_depth],center=true);
213
+					}
214
+	
215
+				//grub screw hole
216
+				rotate([0,0,22.5])cylinder(r=m3_dia/2,h=pulley_b_dia/2+1,$fn=8);
217
+			}
218
+		}}
219
+	 }
220
+	   
221
+	}
222
+
223
+
224
+// Tooth profile modules
225
+
226
+module MXL(pulley_t_ht = pulley_t_ht_example)
227
+	{
228
+	linear_extrude(height=pulley_t_ht+2) polygon([[-0.660421,-0.5],[-0.660421,0],[-0.621898,0.006033],[-0.587714,0.023037],[-0.560056,0.049424],[-0.541182,0.083609],[-0.417357,0.424392],[-0.398413,0.458752],[-0.370649,0.48514],[-0.336324,0.502074],[-0.297744,0.508035],[0.297744,0.508035],[0.336268,0.502074],[0.370452,0.48514],[0.39811,0.458752],[0.416983,0.424392],[0.540808,0.083609],[0.559752,0.049424],[0.587516,0.023037],[0.621841,0.006033],[0.660421,0],[0.660421,-0.5]]);
229
+	}
230
+
231
+module 40DP(pulley_t_ht = pulley_t_ht_example)
232
+	{
233
+	linear_extrude(height=pulley_t_ht+2) polygon([[-0.612775,-0.5],[-0.612775,0],[-0.574719,0.010187],[-0.546453,0.0381],[-0.355953,0.3683],[-0.327604,0.405408],[-0.291086,0.433388],[-0.248548,0.451049],[-0.202142,0.4572],[0.202494,0.4572],[0.248653,0.451049],[0.291042,0.433388],[0.327609,0.405408],[0.356306,0.3683],[0.546806,0.0381],[0.574499,0.010187],[0.612775,0],[0.612775,-0.5]]);
234
+	}
235
+
236
+module XL(pulley_t_ht = pulley_t_ht_example)
237
+	{
238
+	linear_extrude(height=pulley_t_ht+2) polygon([[-1.525411,-1],[-1.525411,0],[-1.41777,0.015495],[-1.320712,0.059664],[-1.239661,0.129034],[-1.180042,0.220133],[-0.793044,1.050219],[-0.733574,1.141021],[-0.652507,1.210425],[-0.555366,1.254759],[-0.447675,1.270353],[0.447675,1.270353],[0.555366,1.254759],[0.652507,1.210425],[0.733574,1.141021],[0.793044,1.050219],[1.180042,0.220133],[1.239711,0.129034],[1.320844,0.059664],[1.417919,0.015495],[1.525411,0],[1.525411,-1]]);
239
+	}
240
+
241
+module H(pulley_t_ht = pulley_t_ht_example)
242
+	{
243
+	linear_extrude(height=pulley_t_ht+2) polygon([[-2.6797,-1],[-2.6797,0],[-2.600907,0.006138],[-2.525342,0.024024],[-2.45412,0.052881],[-2.388351,0.091909],[-2.329145,0.140328],[-2.277614,0.197358],[-2.234875,0.262205],[-2.202032,0.334091],[-1.75224,1.57093],[-1.719538,1.642815],[-1.676883,1.707663],[-1.62542,1.764693],[-1.566256,1.813112],[-1.500512,1.85214],[-1.4293,1.880997],[-1.353742,1.898883],[-1.274949,1.905021],[1.275281,1.905021],[1.354056,1.898883],[1.429576,1.880997],[1.500731,1.85214],[1.566411,1.813112],[1.625508,1.764693],[1.676919,1.707663],[1.719531,1.642815],[1.752233,1.57093],[2.20273,0.334091],[2.235433,0.262205],[2.278045,0.197358],[2.329455,0.140328],[2.388553,0.091909],[2.454233,0.052881],[2.525384,0.024024],[2.600904,0.006138],[2.6797,0],[2.6797,-1]]);
244
+	}
245
+
246
+module T2_5(pulley_t_ht = pulley_t_ht_example)
247
+	{
248
+	linear_extrude(height=pulley_t_ht+2) polygon([[-0.839258,-0.5],[-0.839258,0],[-0.770246,0.021652],[-0.726369,0.079022],[-0.529167,0.620889],[-0.485025,0.67826],[-0.416278,0.699911],[0.416278,0.699911],[0.484849,0.67826],[0.528814,0.620889],[0.726369,0.079022],[0.770114,0.021652],[0.839258,0],[0.839258,-0.5]]);
249
+	}
250
+
251
+module T5(pulley_t_ht = pulley_t_ht_example)
252
+	{
253
+	linear_extrude(height=pulley_t_ht+2) polygon([[-1.632126,-0.5],[-1.632126,0],[-1.568549,0.004939],[-1.507539,0.019367],[-1.450023,0.042686],[-1.396912,0.074224],[-1.349125,0.113379],[-1.307581,0.159508],[-1.273186,0.211991],[-1.246868,0.270192],[-1.009802,0.920362],[-0.983414,0.978433],[-0.949018,1.030788],[-0.907524,1.076798],[-0.859829,1.115847],[-0.80682,1.147314],[-0.749402,1.170562],[-0.688471,1.184956],[-0.624921,1.189895],[0.624971,1.189895],[0.688622,1.184956],[0.749607,1.170562],[0.807043,1.147314],[0.860055,1.115847],[0.907754,1.076798],[0.949269,1.030788],[0.9837,0.978433],[1.010193,0.920362],[1.246907,0.270192],[1.273295,0.211991],[1.307726,0.159508],[1.349276,0.113379],[1.397039,0.074224],[1.450111,0.042686],[1.507589,0.019367],[1.568563,0.004939],[1.632126,0],[1.632126,-0.5]]);
254
+	}
255
+
256
+module T10(pulley_t_ht = pulley_t_ht_example)
257
+	{
258
+	linear_extrude(height=pulley_t_ht+2) polygon([[-3.06511,-1],[-3.06511,0],[-2.971998,0.007239],[-2.882718,0.028344],[-2.79859,0.062396],[-2.720931,0.108479],[-2.651061,0.165675],[-2.590298,0.233065],[-2.539962,0.309732],[-2.501371,0.394759],[-1.879071,2.105025],[-1.840363,2.190052],[-1.789939,2.266719],[-1.729114,2.334109],[-1.659202,2.391304],[-1.581518,2.437387],[-1.497376,2.47144],[-1.408092,2.492545],[-1.314979,2.499784],[1.314979,2.499784],[1.408091,2.492545],[1.497371,2.47144],[1.581499,2.437387],[1.659158,2.391304],[1.729028,2.334109],[1.789791,2.266719],[1.840127,2.190052],[1.878718,2.105025],[2.501018,0.394759],[2.539726,0.309732],[2.59015,0.233065],[2.650975,0.165675],[2.720887,0.108479],[2.798571,0.062396],[2.882713,0.028344],[2.971997,0.007239],[3.06511,0],[3.06511,-1]]);
259
+	}
260
+
261
+module AT5(pulley_t_ht = pulley_t_ht_example)
262
+	{
263
+	linear_extrude(height=pulley_t_ht+2) polygon([[-2.134129,-0.75],[-2.134129,0],[-2.058023,0.005488],[-1.984595,0.021547],[-1.914806,0.047569],[-1.849614,0.082947],[-1.789978,0.127073],[-1.736857,0.179338],[-1.691211,0.239136],[-1.653999,0.305859],[-1.349199,0.959203],[-1.286933,1.054635],[-1.201914,1.127346],[-1.099961,1.173664],[-0.986896,1.18992],[0.986543,1.18992],[1.099614,1.173664],[1.201605,1.127346],[1.286729,1.054635],[1.349199,0.959203],[1.653646,0.305859],[1.690859,0.239136],[1.73651,0.179338],[1.789644,0.127073],[1.849305,0.082947],[1.914539,0.047569],[1.984392,0.021547],[2.057906,0.005488],[2.134129,0],[2.134129,-0.75]]);
264
+	}
265
+
266
+module HTD_3mm(pulley_t_ht = pulley_t_ht_example)
267
+	{
268
+	linear_extrude(height=pulley_t_ht+2) polygon([[-1.135062,-0.5],[-1.135062,0],[-1.048323,0.015484],[-0.974284,0.058517],[-0.919162,0.123974],[-0.889176,0.206728],[-0.81721,0.579614],[-0.800806,0.653232],[-0.778384,0.72416],[-0.750244,0.792137],[-0.716685,0.856903],[-0.678005,0.918199],[-0.634505,0.975764],[-0.586483,1.029338],[-0.534238,1.078662],[-0.47807,1.123476],[-0.418278,1.16352],[-0.355162,1.198533],[-0.289019,1.228257],[-0.22015,1.25243],[-0.148854,1.270793],[-0.07543,1.283087],[-0.000176,1.28905],[0.075081,1.283145],[0.148515,1.270895],[0.219827,1.252561],[0.288716,1.228406],[0.354879,1.19869],[0.418018,1.163675],[0.477831,1.123623],[0.534017,1.078795],[0.586276,1.029452],[0.634307,0.975857],[0.677809,0.91827],[0.716481,0.856953],[0.750022,0.792167],[0.778133,0.724174],[0.800511,0.653236],[0.816857,0.579614],[0.888471,0.206728],[0.919014,0.123974],[0.974328,0.058517],[1.048362,0.015484],[1.135062,0],[1.135062,-0.5]]);
269
+	}
270
+
271
+module HTD_5mm(pulley_t_ht = pulley_t_ht_example)
272
+	{
273
+	linear_extrude(height=pulley_t_ht+2) polygon([[-1.89036,-0.75],[-1.89036,0],[-1.741168,0.02669],[-1.61387,0.100806],[-1.518984,0.21342],[-1.467026,0.3556],[-1.427162,0.960967],[-1.398568,1.089602],[-1.359437,1.213531],[-1.310296,1.332296],[-1.251672,1.445441],[-1.184092,1.552509],[-1.108081,1.653042],[-1.024167,1.746585],[-0.932877,1.832681],[-0.834736,1.910872],[-0.730271,1.980701],[-0.62001,2.041713],[-0.504478,2.09345],[-0.384202,2.135455],[-0.259708,2.167271],[-0.131524,2.188443],[-0.000176,2.198511],[0.131296,2.188504],[0.259588,2.167387],[0.384174,2.135616],[0.504527,2.093648],[0.620123,2.04194],[0.730433,1.980949],[0.834934,1.911132],[0.933097,1.832945],[1.024398,1.746846],[1.108311,1.653291],[1.184308,1.552736],[1.251865,1.445639],[1.310455,1.332457],[1.359552,1.213647],[1.39863,1.089664],[1.427162,0.960967],[1.467026,0.3556],[1.518984,0.21342],[1.61387,0.100806],[1.741168,0.02669],[1.89036,0],[1.89036,-0.75]]);
274
+	}
275
+
276
+module HTD_8mm(pulley_t_ht = pulley_t_ht_example)
277
+	{
278
+	linear_extrude(height=pulley_t_ht+2) polygon([[-3.301471,-1],[-3.301471,0],[-3.16611,0.012093],[-3.038062,0.047068],[-2.919646,0.10297],[-2.813182,0.177844],[-2.720989,0.269734],[-2.645387,0.376684],[-2.588694,0.496739],[-2.553229,0.627944],[-2.460801,1.470025],[-2.411413,1.691917],[-2.343887,1.905691],[-2.259126,2.110563],[-2.158035,2.30575],[-2.041518,2.490467],[-1.910478,2.66393],[-1.76582,2.825356],[-1.608446,2.973961],[-1.439261,3.10896],[-1.259169,3.22957],[-1.069074,3.335006],[-0.869878,3.424485],[-0.662487,3.497224],[-0.447804,3.552437],[-0.226732,3.589341],[-0.000176,3.607153],[0.226511,3.589461],[0.447712,3.552654],[0.66252,3.497516],[0.870027,3.424833],[1.069329,3.33539],[1.259517,3.229973],[1.439687,3.109367],[1.608931,2.974358],[1.766344,2.825731],[1.911018,2.664271],[2.042047,2.490765],[2.158526,2.305998],[2.259547,2.110755],[2.344204,1.905821],[2.411591,1.691983],[2.460801,1.470025],[2.553229,0.627944],[2.588592,0.496739],[2.645238,0.376684],[2.720834,0.269734],[2.81305,0.177844],[2.919553,0.10297],[3.038012,0.047068],[3.166095,0.012093],[3.301471,0],[3.301471,-1]]);
279
+	}
280
+
281
+module GT2_2mm(pulley_t_ht = pulley_t_ht_example)
282
+	{
283
+	linear_extrude(height=pulley_t_ht+2) polygon([[0.747183,-0.5],[0.747183,0],[0.647876,0.037218],[0.598311,0.130528],[0.578556,0.238423],[0.547158,0.343077],[0.504649,0.443762],[0.451556,0.53975],[0.358229,0.636924],[0.2484,0.707276],[0.127259,0.750044],[0,0.76447],[-0.127259,0.750044],[-0.2484,0.707276],[-0.358229,0.636924],[-0.451556,0.53975],[-0.504797,0.443762],[-0.547291,0.343077],[-0.578605,0.238423],[-0.598311,0.130528],[-0.648009,0.037218],[-0.747183,0],[-0.747183,-0.5]]);
284
+	}
285
+
286
+module GT2_3mm(pulley_t_ht = pulley_t_ht_example)
287
+	{
288
+	linear_extrude(height=pulley_t_ht+2) polygon([[-1.155171,-0.5],[-1.155171,0],[-1.065317,0.016448],[-0.989057,0.062001],[-0.93297,0.130969],[-0.90364,0.217664],[-0.863705,0.408181],[-0.800056,0.591388],[-0.713587,0.765004],[-0.60519,0.926747],[-0.469751,1.032548],[-0.320719,1.108119],[-0.162625,1.153462],[0,1.168577],[0.162625,1.153462],[0.320719,1.108119],[0.469751,1.032548],[0.60519,0.926747],[0.713587,0.765004],[0.800056,0.591388],[0.863705,0.408181],[0.90364,0.217664],[0.932921,0.130969],[0.988924,0.062001],[1.065168,0.016448],[1.155171,0],[1.155171,-0.5]]);
289
+	}
290
+
291
+module GT2_5mm(pulley_t_ht = pulley_t_ht_example)
292
+	{
293
+	linear_extrude(height=pulley_t_ht+2) polygon([[-1.975908,-0.75],[-1.975908,0],[-1.797959,0.03212],[-1.646634,0.121224],[-1.534534,0.256431],[-1.474258,0.426861],[-1.446911,0.570808],[-1.411774,0.712722],[-1.368964,0.852287],[-1.318597,0.989189],[-1.260788,1.123115],[-1.195654,1.25375],[-1.12331,1.380781],[-1.043869,1.503892],[-0.935264,1.612278],[-0.817959,1.706414],[-0.693181,1.786237],[-0.562151,1.851687],[-0.426095,1.9027],[-0.286235,1.939214],[-0.143795,1.961168],[0,1.9685],[0.143796,1.961168],[0.286235,1.939214],[0.426095,1.9027],[0.562151,1.851687],[0.693181,1.786237],[0.817959,1.706414],[0.935263,1.612278],[1.043869,1.503892],[1.123207,1.380781],[1.195509,1.25375],[1.26065,1.123115],[1.318507,0.989189],[1.368956,0.852287],[1.411872,0.712722],[1.447132,0.570808],[1.474611,0.426861],[1.534583,0.256431],[1.646678,0.121223],[1.798064,0.03212],[1.975908,0],[1.975908,-0.75]]);
294
+	}

BIN
hardware/nema17_mount_2040.stl Переглянути файл


+ 491
- 0
hardware/table.scad Переглянути файл

@@ -0,0 +1,491 @@
1
+/*
2
+ * Resources used:
3
+ * https://www.thingiverse.com/thing:16627
4
+ * https://www.chiefdelphi.com/t/timing-pulley-design-tutorial/383204
5
+ *
6
+ * Hardware required:
7
+ * https://www.banggood.com/15pcs-Transparent-Pulley-Wheel-with-625zz-Double-Bearing-for-V-slot-3D-Printer-p-1575067.html?cur_warehouse=CN&rmmds=search
8
+ * 2x NEMA17 stepper
9
+ * 2040 extrusions, lengths see console output
10
+ * 2020 extrusions, lengths see console output
11
+ * GT2 belt, lengths see console output
12
+ */
13
+
14
+include <config.scad>;
15
+use <gt2_pulley.scad>;
16
+use <common.scad>;
17
+
18
+$fn = 42;
19
+
20
+/***********************************
21
+ ********** Printed Parts **********
22
+ ***********************************/
23
+
24
+module belt_pulley(tc, dia, for_motor = 1) {
25
+    difference() {
26
+        union() {
27
+            cylinder(d = dia + belt_pulley_rim * 2, h = (belt_pulley_width - belt_pulley_tooth_width) / 2);
28
+            
29
+            translate([0, 0, (belt_pulley_width - belt_pulley_tooth_width) / 2])
30
+            gt2_2mm_pulley(tc, belt_pulley_tooth_width);
31
+            cylinder(d = dia, h = (belt_pulley_width - belt_pulley_tooth_width) / 2);
32
+            
33
+            translate([0, 0, (belt_pulley_width - belt_pulley_tooth_width) / 2 + belt_pulley_tooth_width])
34
+            cylinder(d = dia + belt_pulley_rim * 2, h = (belt_pulley_width - belt_pulley_tooth_width) / 2);
35
+        }
36
+        
37
+        if (for_motor) {
38
+            // motor shaft hole
39
+            translate([0, 0, -1])
40
+            cylinder(d = belt_pulley_axis_hole, h = belt_pulley_width + 2);
41
+        } else {
42
+            // bearing hole
43
+            translate([0, 0, -1])
44
+            cylinder(d = bearing_outer, h = belt_pulley_width + 2);
45
+        }
46
+        
47
+        // grub screw
48
+        for (i = [0, 90])
49
+        translate([0, 0, belt_pulley_width / 2])
50
+        rotate([90, 0, i])
51
+        cylinder(d = belt_pulley_fix_dia, h = dia / 2 + 1);
52
+    }
53
+}
54
+
55
+module belt_tensioner_diff() {
56
+    translate([-50, -belt_tensioner_diff_len, -belt_tensioner_diff_height / 2])
57
+    cube([100, belt_tensioner_diff_len, belt_tensioner_diff_height]);
58
+    
59
+    translate([-belt_tensioner_diff_width / 2, -belt_tensioner_diff_len, -50])
60
+    cube([belt_tensioner_diff_width, belt_tensioner_diff_len, 100]);
61
+}
62
+
63
+module belt_tensioner_mount_rail(height) {
64
+    echo("belt tensioner", "t-nut", str(height * 2, "x"), str(motor_mount_hole_size_nominal, "mm"));
65
+    
66
+    difference() {
67
+        if (height == 1) {
68
+            for (i = [ 10, -10 - belt_tensioner_wall ])
69
+            translate([i, 0, 0])
70
+            cube([belt_tensioner_wall, belt_tensioner_mount_depth, 20 + belt_tensioner_wall]);
71
+        } else {
72
+            for (i = [ 10, -10 - belt_tensioner_wall ])
73
+            translate([i, 0, -20])
74
+            cube([belt_tensioner_wall, belt_tensioner_mount_depth, 40 + belt_tensioner_wall]);
75
+        }
76
+        
77
+        for (i = [ 10, -10 ])
78
+        translate([-10 - belt_tensioner_wall - 1, belt_tensioner_mount_depth / 2, i])
79
+        rotate([0, 90, 0])
80
+        cylinder(d = motor_mount_hole_size, h = 20 + 2 * belt_tensioner_wall + 2);
81
+    }
82
+}
83
+
84
+module belt_tensioner_mount(height) {
85
+    echo("belt tensioner", "screw", "1x", str("M", belt_tensioner_screw), str(">", belt_tensioner_diff_len + belt_tensioner_wall + 5 - real_belt_pulley_dia, "mm"));
86
+    
87
+    echo("belt tensioner", "nut", "1x", str("M", belt_tensioner_screw));
88
+    
89
+    belt_tensioner_mount_rail(height);
90
+    
91
+    difference() {
92
+        hull() {
93
+            if (height == 1) {
94
+                for (i = [ 10, -10 - belt_tensioner_wall ])
95
+                translate([i, 0, 0])
96
+                cube([belt_tensioner_wall, 1, 20 + belt_tensioner_wall]);
97
+            } else {
98
+                for (i = [ 10, -10 - belt_tensioner_wall ])
99
+                translate([i, 0, -20])
100
+                cube([belt_tensioner_wall, 1, 40 + belt_tensioner_wall]);
101
+            }
102
+            
103
+            translate([-10, -belt_tensioner_diff_len - belt_tensioner_wall - 5, 25 - 21])
104
+            cube([20, belt_tensioner_wall, 20 + 1]);
105
+        }
106
+        
107
+        translate([-10 - belt_tensioner_wall - 1, 0, -22])
108
+        cube([20 + 2 * belt_tensioner_wall + 2, 50, 50]);
109
+        
110
+        translate([-10, 0, -22])
111
+        cube([20, 50, 50]);
112
+        
113
+        translate([0, 0, 10 + belt_pulley_off])
114
+        belt_tensioner_diff();
115
+        
116
+        translate([0, -belt_tensioner_diff_len - belt_tensioner_wall - 5 + 30 - 1, real_belt_pulley_dia / 2 + 0.175])
117
+        rotate([90, 0, 0])
118
+        cylinder(d = belt_tensioner_screw_hole, h = 30);
119
+    }
120
+}
121
+
122
+module belt_tensioner_moving() {
123
+    %color("red")
124
+    translate([-belt_pulley_width / 2, 0, 0])
125
+    rotate([0, 90, 0])
126
+    rotate([0, 0, -acos(anim_pos_x * -2 + 1)])
127
+    belt_pulley(teethcount, real_belt_pulley_dia, 0);
128
+    
129
+    color("cyan")
130
+    difference() {
131
+        for (i = [-1, 1])
132
+        scale([i, 1, 1])
133
+        translate([belt_pulley_width / 2 + belt_tensioner_moving_gap, belt_tensioner_moving_overlap - belt_tensioner_moving_len, -belt_tensioner_moving_height / 2])
134
+        cube([belt_tensioner_wall, belt_tensioner_moving_len, belt_tensioner_moving_height]);
135
+        
136
+        translate([-belt_pulley_width / 2 - belt_tensioner_wall - belt_tensioner_moving_gap - 1, 0, 0])
137
+        rotate([0, 90, 0])
138
+        cylinder(d = axis_hole_diameter, h = belt_pulley_width + 2 * (belt_tensioner_wall + belt_tensioner_moving_gap) + 2);
139
+    }
140
+    
141
+    color("cyan")
142
+    translate([-belt_pulley_width / 2 - belt_tensioner_moving_gap, -belt_tensioner_moving_len + belt_tensioner_moving_overlap, -belt_tensioner_moving_height / 2])
143
+    difference() {
144
+        cube([belt_pulley_width + 2 * belt_tensioner_moving_gap, belt_tensioner_wall, belt_tensioner_moving_height]);
145
+        
146
+        translate([belt_pulley_width / 2 + belt_tensioner_moving_gap, belt_tensioner_wall + 1, belt_tensioner_moving_height / 2])
147
+        rotate([90, 0, 0])
148
+        cylinder(d = belt_tensioner_screw_hole, h = belt_tensioner_wall + 2);
149
+    }
150
+}
151
+
152
+module belt_tensioner(height, length = 100, visual = 1) {
153
+    if (visual)
154
+    %translate([-10, 0, 0])
155
+    if (length > 0) {
156
+        if (height == 1) {
157
+            rail_2020_y(length, "only for visualization");
158
+        } else {
159
+            rail_2040_y(length, "only for visualization");
160
+        }
161
+    }
162
+    
163
+    translate([0, -belt_tensioner_travel * $t, 0])
164
+    translate([0, -real_belt_pulley_dia / 2, 10 + belt_pulley_off])
165
+    belt_tensioner_moving();
166
+    
167
+    color("orange")
168
+    belt_tensioner_mount(height);
169
+    
170
+    %color("yellow")
171
+    translate([-belt_width / 2, -real_belt_pulley_dia / 2, 10 + real_belt_pulley_dia / 2 + belt_pulley_off - belt_thickness / 2])
172
+    cube([belt_width, length + real_belt_pulley_dia / 2 + nema17_size / 2, belt_thickness]);
173
+    
174
+    %color("yellow")
175
+    translate([-belt_width / 2, -real_belt_pulley_dia / 2, 10 - real_belt_pulley_dia / 2 - belt_thickness / 2 + belt_pulley_off])
176
+    cube([belt_width, length + real_belt_pulley_dia / 2 + nema17_size / 2, belt_thickness]);
177
+}
178
+
179
+module motor_mount(height) {
180
+    echo("motor mount", "t-nut", str(height * 2, "x"), str(motor_mount_hole_size_nominal, "mm"));
181
+    
182
+    echo("motor mount", "screw", "4x", str("M", nema17_hole_size), str(motor_mount_height + 2, "-", motor_mount_height + 4, "mm"));
183
+    
184
+    %color("yellow")
185
+    translate([-nema17_len, 0, nema17_size - belt_pulley_off])
186
+    rotate([0, 90, 0])
187
+    nema17(nema17_len);
188
+    
189
+    %color("red")
190
+    translate([motor_mount_height - belt_pulley_width / 2 + 10, nema17_size / 2, nema17_size / 2 - belt_pulley_off])
191
+    rotate([0, 90, 0])
192
+        rotate([0, 0, -acos(anim_pos_x * -2 + 1)])
193
+    belt_pulley(teethcount, real_belt_pulley_dia, 1);
194
+    
195
+    color("cyan")
196
+    difference() {
197
+        hull() {
198
+            translate([0, 0, -belt_pulley_off])
199
+            cube([motor_mount_height, nema17_size, nema17_size]);
200
+            
201
+            translate([0, nema17_size, (nema17_size - 20) / 2])
202
+            cube([motor_mount_height, motor_mount_length, height * 20]);
203
+        }
204
+        
205
+        translate([0, 0, -belt_pulley_off])
206
+        translate([-nema17_len, 0, nema17_size])
207
+        rotate([0, 90, 0]) {
208
+            nema17_holes_face(nema17_len, motor_mount_height + 5, nema17_hole_size + screw_gap);
209
+            
210
+            translate([nema17_size / 2, nema17_size / 2, nema17_len - 1])
211
+            cylinder(d = nema17_center_size + 2, h = motor_mount_height + 2);
212
+        }
213
+        
214
+        for (i = [0, motor_mount_hole_off])
215
+        for (j = [0, 20 * (height - 1)])
216
+        translate([0, i, j])
217
+        translate([-1, nema17_size - motor_mount_hole_off / 2 + motor_mount_length / 2, nema17_size / 2])
218
+        rotate([0, 90, 0]) {
219
+            cylinder(d = motor_mount_hole_size, h = motor_mount_height + 2);
220
+        }
221
+    }
222
+}
223
+
224
+/***********************************
225
+ ************** Plate **************
226
+ ***********************************/
227
+
228
+module plate_holes(h) {
229
+    for (i = [-1, 1])
230
+    for (j = [-1, 1])
231
+    translate([i * plate_mount_screws_distance_x / 2, j * plate_mount_screws_distance_y / 2, -1])
232
+    cylinder(d = plate_mount_screw_hole, h = h + 2);
233
+}
234
+
235
+module plate() {
236
+    echo("alu plate", "bed", plate_x, plate_y, "holes", plate_mount_screws_distance_x, plate_mount_screws_distance_y);
237
+    
238
+    difference() {
239
+        cube([plate_x, plate_y, plate_z]);
240
+        
241
+        translate([plate_x / 2, plate_y / 2, 0])
242
+        plate_holes(plate_z);
243
+    }
244
+}
245
+
246
+/************************************
247
+ ************** Y-Axis **************
248
+ ************************************/
249
+
250
+module belt_mount(h) {
251
+    difference() {
252
+        hull() {
253
+            translate([-belt_mount_width / 2, -belt_mount_depth / 2, 0])
254
+            cube([belt_mount_width, belt_mount_depth, h]);
255
+            
256
+            translate([-belt_mount_full_width / 2, belt_mount_depth / 2, 0])
257
+            cube([belt_mount_full_width, 1, h]);
258
+        }
259
+        
260
+        translate([-belt_slot_width / 2, -belt_slot_depth / 2, -1])
261
+        cube([belt_slot_width, belt_slot_depth, h + 2]);
262
+        
263
+        translate([-belt_mount_full_width / 2, -belt_mount_depth / 2 - 0.1, h / 2])
264
+        rotate([-90, 0, 0])
265
+        prism(belt_mount_full_width, h / 2 + 0.1, belt_mount_depth + 0.1);
266
+    }
267
+}
268
+
269
+module y_carriage_post() {
270
+    rotate([0, 0, 90])
271
+    difference() {
272
+        cylinder(d = y_carriage_post_dia, h = y_carriage_post_len, $fn = 6);
273
+        
274
+        translate([0, 0, -1])
275
+        cylinder(d = y_carriage_post_screw_hole, h = (y_carriage_post_len - y_carriage_post_center) / 2 + 1);
276
+        
277
+        translate([y_carriage_post_hole_off, 0, (y_carriage_post_len + y_carriage_post_center) / 2])
278
+        cylinder(d = y_carriage_post_screw_hole, h = (y_carriage_post_len - y_carriage_post_center) / 2 + 1);
279
+    }
280
+}
281
+
282
+module y_carriage_posts() {
283
+    for (i = [-1, 1])
284
+    for (j = [-1, 1])
285
+    translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, 0]) {
286
+        color("blue")
287
+        y_carriage_post();
288
+        
289
+        %color("yellow")
290
+        translate([0, y_carriage_post_hole_off, y_carriage_pulley_off])
291
+        rail_wheel();
292
+    }
293
+}
294
+
295
+// also used as base for x-carriage
296
+// axis = 0 --> all holes, usable for both
297
+// axis = 1 --> holes for x-carriage
298
+// axis = 2 --> holes for y-carriage
299
+module y_carriage(axis = 0) {
300
+    if (axis == 1) {
301
+        echo("t-nut", "x-carriage", "2");
302
+    }
303
+
304
+    color("green")
305
+    difference() {
306
+        cube([y_carriage_x, y_carriage_y, y_carriage_h]);
307
+        
308
+        translate([y_carriage_x / 2, y_carriage_y / 2, 0])
309
+        plate_holes(y_carriage_h);
310
+        
311
+        // holes to mount y-axis to x-carriage
312
+        if ((axis == 0) || (axis == 1)) {
313
+            translate([(y_carriage_x - plate_mount_screws_distance_x) / 2, 0, 0])
314
+            for (i = [0, 1])
315
+            translate([i * plate_mount_screws_distance_x, y_carriage_y / 2, -1])
316
+            cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2);
317
+            
318
+            for (i = [x_carriage_holder_l - x_carriage_holder_hole_off, y_carriage_y - x_carriage_holder_l + x_carriage_holder_hole_off])
319
+            translate([y_carriage_x / 2, i, -1])
320
+            cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2);
321
+        }
322
+        
323
+        translate([y_carriage_x / 2, y_carriage_y / 2, 0])
324
+        for (i = [-1, 1])
325
+        for (j = [-1, 1])
326
+        translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, -1]) {
327
+            cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2);
328
+        }
329
+    }
330
+    
331
+    %translate([y_carriage_x / 2, y_carriage_y / 2, y_carriage_h])
332
+    y_carriage_posts();
333
+    
334
+    color("green")
335
+    translate([y_carriage_x / 2, -belt_mount_depth / 2, 0])
336
+    belt_mount(y_carriage_h);
337
+    
338
+    color("green")
339
+    translate([y_carriage_x / 2, y_carriage_y + belt_mount_depth / 2, 0])
340
+    scale([1, -1, 1])
341
+    belt_mount(y_carriage_h);
342
+}
343
+
344
+module y_axis() {
345
+    translate([y_carriage_x / 2, y_axis_animation_position, 20 + y_carriage_h + y_carriage_rail_dist])
346
+    rotate([0, 180, 0])
347
+    y_carriage(2);
348
+    
349
+    color("grey")
350
+    translate([-10, 0, 0])
351
+    rail_2040_y(y_axis_rail_len, "y-axis");
352
+    
353
+    translate([- motor_mount_height - 10, y_axis_rail_len + nema17_size, nema17_size / 2 + 10])
354
+    rotate([180, 0, 0])
355
+    motor_mount(2);
356
+    
357
+    belt_tensioner(2, y_axis_rail_len, 0);
358
+}
359
+
360
+/************************************
361
+ ************** X-Axis **************
362
+ ************************************/
363
+
364
+module x_carriage_holder() {
365
+    echo("t-nut", "x-carriage-holder", "2");
366
+
367
+    difference() {
368
+        union() {
369
+            cube([x_carriage_holder_l, x_carriage_holder_w, x_carriage_holder_h]);
370
+            cube([x_carriage_holder_h, x_carriage_holder_w, 20]);
371
+        }
372
+        
373
+        translate([0, (x_carriage_holder_w - x_carriage_holder_rail_hole_dist) / 2, 0])
374
+        for (i = [0, x_carriage_holder_rail_hole_dist])
375
+        translate([-1, i, 10])
376
+        rotate([0, 90, 0])
377
+        cylinder(d = y_carriage_post_screw_hole, h = x_carriage_holder_h + 2);
378
+        
379
+        translate([-(y_carriage_y - plate_mount_screws_distance_y) / 2, y_carriage_x / 2, 0])
380
+        rotate([0, 0, 90])
381
+        plate_holes(x_carriage_holder_h);
382
+        
383
+        translate([x_carriage_holder_hole_off, x_carriage_holder_w / 2, -1])
384
+        cylinder(d = y_carriage_post_screw_hole, h = x_carriage_holder_h + 2);
385
+    }
386
+}
387
+
388
+module x_carriage() {
389
+    translate([0, -y_carriage_x / 2, y_carriage_h + y_carriage_rail_dist + 20])
390
+    rotate([0, 180, -90])
391
+    y_carriage(1);
392
+    
393
+    color("purple")
394
+    for (i = [-1, 1])
395
+    translate([y_carriage_y / 2, 0, 0])
396
+    scale([i, 1, 1])
397
+    translate([y_carriage_y / 2 - x_carriage_holder_l, 0, 0])
398
+    translate([0, -x_carriage_holder_w / 2, 20 + y_carriage_h + y_carriage_rail_dist])
399
+    x_carriage_holder();
400
+}
401
+
402
+module x_axis() {
403
+    translate([x_axis_animation_position + 10, 0, 0])
404
+    x_carriage();
405
+    
406
+    color("grey")
407
+    translate([0, -10, 0])
408
+    rail_2040_x(x_axis_rail_len, "x-axis");
409
+    
410
+    translate([x_axis_rail_len + nema17_size, motor_mount_height + 10, nema17_size / 2 + 10])
411
+    rotate([0, 180, 90])
412
+    motor_mount(2);
413
+    
414
+    rotate([0, 0, -90])
415
+    belt_tensioner(2, x_axis_rail_len, 0);
416
+}
417
+
418
+/************************************
419
+ ************* Assembly *************
420
+ ************************************/
421
+
422
+module assembly_y_axis_plate() {
423
+    translate([0, -y_carriage_y / 2 - y_axis_animation_position, 0])
424
+    y_axis();
425
+    
426
+    %translate([-plate_x / 2, -plate_y / 2, 20 + y_carriage_h + y_carriage_rail_dist])
427
+    plate();
428
+}
429
+
430
+module assembly_x_axis() {
431
+    x_axis();
432
+    
433
+    translate([x_axis_animation_position + y_carriage_y / 2, -y_axis_rail_len / 2, 20 + y_carriage_h + y_carriage_rail_dist])
434
+    translate([10, y_axis_animation_position + y_carriage_y / 2, 20])
435
+    assembly_y_axis_plate();
436
+}
437
+
438
+module assembly() {
439
+    translate([-x_axis_rail_len / 2, 0, 20]) {
440
+        assembly_x_axis();
441
+        
442
+        color("grey")
443
+        for (i = [1, -1])
444
+        scale([1, i, 1])
445
+        translate([left_support_off, -left_support_len - 10, -20])
446
+        rail_2020_y(left_support_len, "left support");
447
+        
448
+        color("grey")
449
+        for (i = [1, -1])
450
+        scale([1, i, 1])
451
+        translate([x_axis_rail_len - 20 - right_support_off, -right_support_len - 10, -20])
452
+        rail_2020_y(right_support_len, "right support");
453
+    }
454
+}
455
+
456
+module xy_table() {
457
+    translate([-point_that_reaches_everywhere_x, -point_that_reaches_everywhere_y, -40 + -40 + (y_carriage_rail_dist + y_carriage_h) * -2 + -plate_z])
458
+    assembly();
459
+}
460
+
461
+/***********************************
462
+ ************ Rendering ************
463
+ ***********************************/
464
+
465
+//dispenser();
466
+//rail_2020_x(100);
467
+//rail_wheel();
468
+
469
+//motor_mount(1);
470
+//motor_mount(2);
471
+//belt_pulley(teethcount, real_belt_pulley_dia, 1);
472
+
473
+//belt_tensioner_mount(2);
474
+//belt_tensioner_moving();
475
+//belt_tensioner(1);
476
+//belt_tensioner(2);
477
+//belt_pulley(teethcount, real_belt_pulley_dia, 0);
478
+
479
+//y_carriage_post();
480
+//x_carriage_holder();
481
+
482
+//y_carriage(0);
483
+//y_carriage(1);
484
+//y_carriage(2);
485
+x_carriage();
486
+
487
+//y_axis();
488
+//x_axis();
489
+
490
+//assembly();
491
+//xy_table();

+ 8
- 0
include/common.h Переглянути файл

@@ -0,0 +1,8 @@
1
+#ifndef _COMMON_H_
2
+#define _COMMON_H_
3
+
4
+void async_beep(int time, int freq);
5
+void blocking_beep(int time, int freq, int repeat = 0);
6
+void common_run(unsigned long t);
7
+
8
+#endif // _COMMON_H_

+ 44
- 0
include/config.h Переглянути файл

@@ -0,0 +1,44 @@
1
+#ifndef _CONFIG_H_
2
+#define _CONFIG_H_
3
+
4
+#define FIRMWARE_VERSION "0.1"
5
+
6
+#define LED_BLINK_INTERVAL 500
7
+#define DEBOUNCE_DELAY 50
8
+
9
+#define ENCODER_CLICK_BEEP_FREQ 2000
10
+#define ENCODER_CLICK_BEEP_TIME 50
11
+
12
+#define XY_BELT_PITCH 2.0
13
+#define XY_PULLEY_TEETH 40.0
14
+#define XY_MICRO_STEPS 16.0
15
+#define XY_MOTOR_STEPS_PER_REV (200.0 * XY_MICRO_STEPS)
16
+#define XY_STEPS_PER_MM (XY_MOTOR_STEPS_PER_REV / XY_PULLEY_TEETH / XY_BELT_PITCH)
17
+
18
+#define Z_ROD_PITCH 2.0
19
+#define Z_MICRO_STEPS 16.0
20
+#define Z_MOTOR_STEPS_PER_REV (200.0 * Z_MICRO_STEPS)
21
+#define Z_STEPS_PER_MM (Z_MOTOR_STEPS_PER_REV / Z_ROD_PITCH)
22
+
23
+#define E_MICRO_STEPS 16.0
24
+#define E_MOTOR_STEPS_PER_REV (200.0 * E_MICRO_STEPS)
25
+#define E_STEPS_PER_MM (E_MOTOR_STEPS_PER_REV / 42) // TODO
26
+
27
+#define XY_MAX_SPEED 50.0 // in mm/s
28
+#define Z_MAX_SPEED 20.0 // in mm/s
29
+#define E_MAX_SPEED 10.0 // in mm/s
30
+
31
+#define XY_MAX_ACCEL 100.0 // in mm/s^2
32
+#define Z_MAX_ACCEL 50.0 // in mm/s^2
33
+#define E_MAX_ACCEL 20.0 // in mm/s^2
34
+
35
+#define X_AXIS_MIN -5.0 // in mm
36
+#define X_AXIS_MAX 260.0 // in mm
37
+#define Y_AXIS_MIN -5.0 // in mm
38
+#define Y_AXIS_MAX 360.0 // in mm
39
+#define Z_AXIS_MIN 0.0 // TODO in mm
40
+#define Z_AXIS_MAX 100.0 // TODO in mm
41
+#define E_AXIS_MIN 0.0 // in mm
42
+#define E_AXIS_MAX 6.0 // in mm
43
+
44
+#endif // _CONFIG_H_

+ 82
- 0
include/config_pins.h Переглянути файл

@@ -0,0 +1,82 @@
1
+#ifndef _CONFIG_PINS_H_
2
+#define _CONFIG_PINS_H_
3
+
4
+// from https://reprap.org/wiki/RAMPS_1.4
5
+
6
+// For RAMPS 1.4
7
+#define X_STEP_PIN         54
8
+#define X_DIR_PIN          55
9
+#define X_ENABLE_PIN       38
10
+#define X_MIN_PIN           3
11
+#define X_MAX_PIN          -1 // 2
12
+
13
+#define Y_STEP_PIN         60
14
+#define Y_DIR_PIN          61
15
+#define Y_ENABLE_PIN       56
16
+#define Y_MIN_PIN          14
17
+#define Y_MAX_PIN          -1 // 15
18
+
19
+#define Z_STEP_PIN         46
20
+#define Z_DIR_PIN          48
21
+#define Z_ENABLE_PIN       62
22
+#define Z_MIN_PIN          -1 // 18
23
+#define Z_MAX_PIN          19
24
+
25
+//extruder 1
26
+#define E0_STEP_PIN        26
27
+#define E0_DIR_PIN         28
28
+#define E0_ENABLE_PIN      24
29
+
30
+//extruder 2
31
+#define E1_STEP_PIN        36
32
+#define E1_DIR_PIN         34
33
+#define E1_ENABLE_PIN      30
34
+
35
+//ChipSelect, Hardware SS Pin on Mega, 10 for Arduino Boards, always kept as output
36
+#define SDCS_PIN           53
37
+
38
+#define LED_PIN            13
39
+
40
+#define FAN_PIN            9
41
+
42
+#define PS_ON_PIN          12	//ATX , awake=LOW, SLEEP=High
43
+
44
+#define HEATER_0_PIN	10  // Extruder Heater
45
+#define HEATER_1_PIN	8
46
+
47
+#define TEMP_0_PIN		13   // ANALOG NUMBERING
48
+#define TEMP_1_PIN		14   // ANALOG NUMBERING
49
+
50
+// from https://reprap.org/wiki/RepRapDiscount_Smart_Controller
51
+
52
+//STOP / KILL button
53
+#define KILL_PIN 41 //[RAMPS14-SMART-ADAPTER]
54
+
55
+//lcd pins
56
+#define LCD_PINS_RS 16 //[RAMPS14-SMART-ADAPTER]
57
+#define LCD_PINS_ENABLE 17 //[RAMPS14-SMART-ADAPTER]
58
+#define LCD_PINS_D4 23 //[RAMPS14-SMART-ADAPTER]
59
+#define LCD_PINS_D5 25 //[RAMPS14-SMART-ADAPTER]
60
+#define LCD_PINS_D6 27 //[RAMPS14-SMART-ADAPTER]
61
+#define LCD_PINS_D7 29 //[RAMPS14-SMART-ADAPTER]
62
+
63
+//encoder pins
64
+#define BTN_EN1 31 //[RAMPS14-SMART-ADAPTER]
65
+#define BTN_EN2 33 //[RAMPS14-SMART-ADAPTER]
66
+#define BTN_ENC 35 //[RAMPS14-SMART-ADAPTER]
67
+
68
+//beeper
69
+#define BEEPER 37 //[RAMPS14-SMART-ADAPTER] / 37 = enabled; -1 = dissabled / (if you don't like the beep sound ;-)
70
+
71
+//SD card detect pin
72
+#define SDCARDDETECT 49 //[RAMPS14-SMART-ADAPTER]
73
+
74
+#endif // _CONFIG_PINS_H_
75
+
76
+#if ((X_MIN_PIN != -1) && (X_MAX_PIN != -1)) || ((X_MIN_PIN == -1) && (X_MAX_PIN == -1))
77
+#error define one of X_MIN_PIN and X_MAX_PIN
78
+#endif
79
+
80
+#if ((Y_MIN_PIN != -1) && (Y_MAX_PIN != -1)) || ((Y_MIN_PIN == -1) && (Y_MAX_PIN == -1))
81
+#error define one of Y_MIN_PIN and Y_MAX_PIN
82
+#endif

+ 17
- 0
include/debounce.h Переглянути файл

@@ -0,0 +1,17 @@
1
+#ifndef _DEBOUNCE_H_
2
+#define _DEBOUNCE_H_
3
+
4
+class Debouncer {
5
+  public:
6
+    Debouncer(int p);
7
+    int poll();
8
+
9
+  private:
10
+    int pin;
11
+    int currentState;
12
+    int lastState;
13
+    unsigned long lastTime;
14
+};
15
+
16
+#endif // _DEBOUNCE_H_
17
+

+ 11
- 0
include/encoder.h Переглянути файл

@@ -0,0 +1,11 @@
1
+#ifndef _ENCODER_H_
2
+#define _ENCODER_H_
3
+
4
+void encoder_init(void);
5
+void encoder_run(void);
6
+
7
+int encoder_change(void);
8
+int encoder_click(void);
9
+int kill_switch(void);
10
+
11
+#endif // _ENCODER_H_

+ 10
- 0
include/lcd.h Переглянути файл

@@ -0,0 +1,10 @@
1
+#ifndef _LCD_H_
2
+#define _LCD_H_
3
+
4
+#include <LiquidCrystal.h>
5
+
6
+extern LiquidCrystal lcd;
7
+
8
+void lcd_init(void);
9
+
10
+#endif // _LCD_H_

+ 7
- 0
include/statemachine.h Переглянути файл

@@ -0,0 +1,7 @@
1
+#ifndef _STATE_MACHINE_H_
2
+#define _STATE_MACHINE_H_
3
+
4
+void statemachine_run(int click, int encoder, int kill);
5
+void statemachine_motors_done(void);
6
+
7
+#endif // _STATE_MACHINE_H_

+ 15
- 0
include/steppers.h Переглянути файл

@@ -0,0 +1,15 @@
1
+#ifndef _STEPPERS_H_
2
+#define _STEPPERS_H_
3
+
4
+void steppers_init(void);
5
+bool steppers_run(void);
6
+
7
+bool steppers_homed(void);
8
+int steppers_start_homing(void);
9
+
10
+int steppers_move_x(long pos);
11
+int steppers_move_y(long pos);
12
+int steppers_move_z(long pos);
13
+int steppers_move_e(long pos);
14
+
15
+#endif // _STEPPERS_H_

+ 24
- 0
platformio.ini Переглянути файл

@@ -0,0 +1,24 @@
1
+; PlatformIO Project Configuration File
2
+;
3
+;   Build options: build flags, source filter
4
+;   Upload options: custom upload port, speed and extra flags
5
+;   Library options: dependencies, extra library storages
6
+;   Advanced options: extra scripting
7
+;
8
+; Please visit documentation for the other options and examples
9
+; https://docs.platformio.org/page/projectconf.html
10
+
11
+[platformio]
12
+default_envs = arduino
13
+
14
+[env:arduino]
15
+platform = atmelavr
16
+board = megaatmega2560
17
+framework = arduino
18
+upload_port = /dev/ttyUSB1
19
+monitor_port = /dev/ttyUSB1
20
+monitor_speed = 115200
21
+lib_deps =
22
+    arduino-libraries/LiquidCrystal
23
+    https://github.com/waspinator/AccelStepper
24
+    https://github.com/mathertel/RotaryEncoder

+ 38
- 0
src/common.cpp Переглянути файл

@@ -0,0 +1,38 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "config_pins.h"
5
+
6
+unsigned long last_led_blink_time = 0;
7
+unsigned long beep_stop_time = 0;
8
+
9
+void async_beep(int time, int freq) {
10
+    beep_stop_time = millis() + time;
11
+    tone(BEEPER, freq);
12
+}
13
+
14
+void blocking_beep(int time, int freq, int repeat = 0) {
15
+    for (int i = 0; i <= repeat; i++) {
16
+        tone(BEEPER, freq);
17
+        delay(time);
18
+        noTone(BEEPER);
19
+
20
+        if ((repeat > 0) && (i < repeat)) {
21
+            delay(time);
22
+        }
23
+    }
24
+}
25
+
26
+void common_run(unsigned long t) {
27
+    // stop async beep
28
+    if ((beep_stop_time > 0)  && (t > beep_stop_time)) {
29
+        noTone(BEEPER);
30
+        beep_stop_time = 0;
31
+    }
32
+
33
+    // blink heartbeat LED
34
+    if ((t - last_led_blink_time) >= LED_BLINK_INTERVAL) {
35
+        last_led_blink_time = millis();
36
+        digitalWrite(LED_PIN, !digitalRead(LED_PIN));
37
+    }
38
+}

+ 28
- 0
src/debounce.cpp Переглянути файл

@@ -0,0 +1,28 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "debounce.h"
5
+
6
+Debouncer::Debouncer(int p) : pin(p), currentState(0), lastState(0), lastTime(0) { }
7
+
8
+int Debouncer::poll() {
9
+    int ret = 0;
10
+    int state = digitalRead(pin);
11
+
12
+    if (state != lastState) {
13
+        lastTime = millis();
14
+    }
15
+
16
+    if ((millis() - lastTime) > DEBOUNCE_DELAY) {
17
+        if (state != currentState) {
18
+            currentState = state;
19
+            if (currentState == LOW) {
20
+                ret = 1;
21
+            }
22
+        }
23
+    }
24
+
25
+    lastState = state;
26
+    return ret;
27
+}
28
+

+ 61
- 0
src/encoder.cpp Переглянути файл

@@ -0,0 +1,61 @@
1
+#include <Arduino.h>
2
+#include <RotaryEncoder.h>
3
+
4
+#include "config.h"
5
+#include "config_pins.h"
6
+#include "debounce.h"
7
+#include "encoder.h"
8
+
9
+static Debouncer click(BTN_ENC);
10
+static int click_state = 0;
11
+static bool ignore_until_next_unclick = false;
12
+
13
+static Debouncer kill(KILL_PIN);
14
+static int kill_state = 0;
15
+
16
+static RotaryEncoder encoder(BTN_EN1, BTN_EN2, RotaryEncoder::LatchMode::TWO03);
17
+static int pos = 0;
18
+
19
+void encoder_init(void) {
20
+    pinMode(BTN_ENC, INPUT);
21
+    pinMode(KILL_PIN, INPUT);
22
+}
23
+
24
+void encoder_run(void) {
25
+    int cs = click.poll();
26
+    if (ignore_until_next_unclick) {
27
+        // dont set to 1 again until it was 0 once
28
+        if (cs == 0) {
29
+            ignore_until_next_unclick = false;
30
+        }
31
+    } else {
32
+        click_state = cs;
33
+    }
34
+
35
+    kill_state = kill.poll();
36
+
37
+    encoder.tick();
38
+}
39
+
40
+int encoder_change(void) {
41
+    int new_pos = encoder.getPosition();
42
+    int diff = new_pos - pos;
43
+    pos = new_pos;
44
+    return diff;
45
+}
46
+
47
+int encoder_click(void) {
48
+    int r = click_state;
49
+
50
+    // only return 1 once for each click
51
+    if (r == 1) {
52
+        click_state = 0;
53
+        ignore_until_next_unclick = true;
54
+    }
55
+
56
+    return r;
57
+}
58
+
59
+int kill_switch(void) {
60
+    return kill_state;
61
+}

+ 17
- 0
src/lcd.cpp Переглянути файл

@@ -0,0 +1,17 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "config_pins.h"
5
+#include "lcd.h"
6
+
7
+LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5, LCD_PINS_D6, LCD_PINS_D7);
8
+
9
+void lcd_init(void) {
10
+    lcd.begin(20, 4);
11
+
12
+    lcd.print(F("    Fuellfix  v2    "));
13
+    lcd.print(F("    Initializing    "));
14
+    lcd.print(F("Software Version "));
15
+    lcd.print(F(FIRMWARE_VERSION));
16
+    lcd.print(F("made by: xythobuz.de"));
17
+}

+ 141
- 0
src/main.cpp Переглянути файл

@@ -0,0 +1,141 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "config_pins.h"
5
+#include "common.h"
6
+#include "encoder.h"
7
+#include "lcd.h"
8
+#include "steppers.h"
9
+#include "statemachine.h"
10
+
11
+void setup() {
12
+    pinMode(LED_PIN, OUTPUT);
13
+    digitalWrite(LED_PIN, HIGH);
14
+
15
+    pinMode(BEEPER, OUTPUT);
16
+    blocking_beep(100, 1000);
17
+    
18
+    Serial.begin(115200);
19
+    Serial.println(F("Initializing Fuellfix v2"));
20
+    Serial.print(F("Version: "));
21
+    Serial.println(FIRMWARE_VERSION);
22
+
23
+    Serial.println(F("Init encoder"));
24
+    encoder_init();
25
+
26
+    Serial.println(F("Init LCD"));
27
+    lcd_init();
28
+
29
+    Serial.println(F("Init stepper motors"));
30
+    steppers_init();
31
+
32
+    // ----------------------------------
33
+
34
+    Serial.println(F("XY:"));
35
+
36
+    Serial.print(F("\t X: "));
37
+    Serial.print(X_AXIS_MIN);
38
+    Serial.print(F(" mm - "));
39
+    Serial.print(X_AXIS_MAX);
40
+    Serial.println(F(" mm"));
41
+
42
+    Serial.print(F("\t Y: "));
43
+    Serial.print(Y_AXIS_MIN);
44
+    Serial.print(F(" mm - "));
45
+    Serial.print(Y_AXIS_MAX);
46
+    Serial.println(F(" mm"));
47
+
48
+    Serial.print(F("\t"));
49
+    Serial.print(XY_STEPS_PER_MM);
50
+    Serial.println(F(" steps/mm"));
51
+
52
+    Serial.print(F("\t"));
53
+    Serial.print(XY_MAX_SPEED);
54
+    Serial.println(F(" mm/s"));
55
+
56
+    Serial.print(F("\t"));
57
+    Serial.print(XY_MAX_ACCEL);
58
+    Serial.println(F(" mm/s^2"));
59
+
60
+    Serial.println();
61
+
62
+    // ----------------------------------
63
+
64
+    Serial.println(F("Z:"));
65
+
66
+    Serial.print(F("\t"));
67
+    Serial.print(Z_AXIS_MIN);
68
+    Serial.print(F(" mm - "));
69
+    Serial.print(Z_AXIS_MAX);
70
+    Serial.println(F(" mm"));
71
+
72
+    Serial.print(F("\t"));
73
+    Serial.print(Z_STEPS_PER_MM);
74
+    Serial.println(F(" steps/mm"));
75
+
76
+    Serial.print(F("\t"));
77
+    Serial.print(Z_MAX_SPEED);
78
+    Serial.println(F(" mm/s"));
79
+
80
+    Serial.print(F("\t"));
81
+    Serial.print(Z_MAX_ACCEL);
82
+    Serial.println(F(" mm/s^2"));
83
+
84
+    Serial.println();
85
+
86
+    // ----------------------------------
87
+
88
+    Serial.println(F("E:"));
89
+
90
+    Serial.print(F("\t"));
91
+    Serial.print(E_AXIS_MIN);
92
+    Serial.print(F(" mm - "));
93
+    Serial.print(E_AXIS_MAX);
94
+    Serial.println(F(" mm"));
95
+
96
+    Serial.print(F("\t"));
97
+    Serial.print(E_STEPS_PER_MM);
98
+    Serial.println(F(" steps/mm"));
99
+
100
+    Serial.print(F("\t"));
101
+    Serial.print(E_MAX_SPEED);
102
+    Serial.println(F(" mm/s"));
103
+
104
+    Serial.print(F("\t"));
105
+    Serial.print(E_MAX_ACCEL);
106
+    Serial.println(F(" mm/s^2"));
107
+
108
+    Serial.println();
109
+
110
+    // ----------------------------------
111
+
112
+    Serial.println(F("ready, showing splash screen"));
113
+    digitalWrite(LED_PIN, LOW);
114
+    blocking_beep(100, 2000);
115
+
116
+    // wait some time to show splash screen
117
+    delay(2000);
118
+    blocking_beep(100, 2000);
119
+    Serial.println(F("starting main loop"));
120
+}
121
+
122
+void loop() {
123
+    unsigned long t = millis();
124
+
125
+    common_run(t);
126
+    encoder_run();
127
+
128
+    int click = encoder_click();
129
+    if (click) {
130
+        async_beep(ENCODER_CLICK_BEEP_TIME, ENCODER_CLICK_BEEP_FREQ);
131
+    }
132
+
133
+    int kill = kill_switch();
134
+
135
+    statemachine_run(click, encoder_change(), kill);
136
+
137
+    bool still_running = steppers_run();
138
+    if (!still_running) {
139
+        statemachine_motors_done();
140
+    }
141
+}

+ 57
- 0
src/statemachine.cpp Переглянути файл

@@ -0,0 +1,57 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "config_pins.h"
5
+#include "common.h"
6
+#include "lcd.h"
7
+#include "steppers.h"
8
+#include "statemachine.h"
9
+
10
+enum states {
11
+    sm_init,
12
+    sm_ask_homing,
13
+    sm_do_homing,
14
+    sm_menu
15
+};
16
+
17
+static states state = sm_init;
18
+
19
+static void switch_state(states s) {
20
+    state = s;
21
+
22
+    if (state == sm_ask_homing) {
23
+        lcd.clear();
24
+        lcd.print(F("  Homing Required!"));
25
+        lcd.setCursor(0, 2);
26
+        lcd.print(F(" Click to home XYZE"));
27
+    } else if (state == sm_do_homing) {
28
+
29
+    } else if (state == sm_menu) {
30
+
31
+    }
32
+}
33
+
34
+void statemachine_run(int click, int encoder, int kill) {
35
+    if (state == sm_init) {
36
+        if (click) {
37
+            switch_state(sm_ask_homing);
38
+        }
39
+    } else if (state == sm_ask_homing) {
40
+        if (click) {
41
+            switch_state(sm_do_homing);
42
+        }
43
+    } else if (state == sm_do_homing) {
44
+
45
+    } else if (state == sm_menu) {
46
+
47
+    }
48
+}
49
+
50
+void statemachine_motors_done(void) {
51
+    if (state == sm_do_homing) {
52
+        if (steppers_homed()) {
53
+            async_beep(100, 2000);
54
+            switch_state(sm_menu);
55
+        }
56
+    }
57
+}

+ 135
- 0
src/steppers.cpp Переглянути файл

@@ -0,0 +1,135 @@
1
+#include <Arduino.h>
2
+#include <AccelStepper.h>
3
+
4
+#include "config.h"
5
+#include "config_pins.h"
6
+#include "steppers.h"
7
+
8
+static AccelStepper stepper_x(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN, 0, 0, false);
9
+static AccelStepper stepper_y(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN, 0, 0, false);
10
+static AccelStepper stepper_z(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN, 0, 0, false);
11
+static AccelStepper stepper_e(AccelStepper::DRIVER, E0_STEP_PIN, E0_DIR_PIN, 0, 0, false);
12
+
13
+enum stepper_states {
14
+    step_disabled,
15
+    step_not_homed,
16
+    step_homing_x_fast,
17
+    step_homing_x_back,
18
+    step_homing_x_slow,
19
+    step_homing_y_fast,
20
+    step_homing_y_back,
21
+    step_homing_y_slow,
22
+    step_homing_z_fast,
23
+    step_homing_z_back,
24
+    step_homing_z_slow,
25
+    step_homing_e_fast,
26
+    step_homing_e_back,
27
+    step_homing_e_slow,
28
+    step_homed
29
+};
30
+
31
+static stepper_states state = step_disabled;
32
+
33
+void steppers_init(void) {
34
+    stepper_x.setEnablePin(X_ENABLE_PIN);
35
+    stepper_x.setMaxSpeed(XY_MAX_SPEED * XY_STEPS_PER_MM);
36
+    stepper_x.setAcceleration(XY_MAX_ACCEL * XY_STEPS_PER_MM);
37
+
38
+    stepper_y.setEnablePin(Y_ENABLE_PIN);
39
+    stepper_y.setMaxSpeed(XY_MAX_SPEED * XY_STEPS_PER_MM);
40
+    stepper_y.setAcceleration(XY_MAX_ACCEL * XY_STEPS_PER_MM);
41
+
42
+    stepper_z.setEnablePin(Z_ENABLE_PIN);
43
+    stepper_z.setMaxSpeed(Z_MAX_SPEED * Z_STEPS_PER_MM);
44
+    stepper_z.setAcceleration(Z_MAX_ACCEL * Z_STEPS_PER_MM);
45
+
46
+    stepper_e.setEnablePin(E0_ENABLE_PIN);
47
+    stepper_e.setMaxSpeed(E_MAX_SPEED * E_STEPS_PER_MM);
48
+    stepper_e.setAcceleration(E_MAX_ACCEL * E_STEPS_PER_MM);
49
+}
50
+
51
+bool steppers_run(void) {
52
+    if (state == step_homing_x_fast) {
53
+    } else if (state == step_homing_x_back) {
54
+    } else if (state == step_homing_x_slow) {
55
+    } else if (state == step_homing_y_fast) {
56
+    } else if (state == step_homing_y_back) {
57
+    } else if (state == step_homing_y_slow) {
58
+    } else if (state == step_homing_z_fast) {
59
+    } else if (state == step_homing_z_back) {
60
+    } else if (state == step_homing_z_slow) {
61
+    } else if (state == step_homing_e_fast) {
62
+    } else if (state == step_homing_e_back) {
63
+    } else if (state == step_homing_e_slow) {
64
+    }
65
+
66
+    boolean x = stepper_x.run();
67
+    boolean y = stepper_y.run();
68
+    boolean z = stepper_z.run();
69
+    boolean e = stepper_e.run();
70
+
71
+    return x || y || z || e;
72
+}
73
+
74
+bool steppers_homed(void) {
75
+    return (state == step_homed);
76
+}
77
+
78
+int steppers_start_homing(void) {
79
+    state = step_homing_x_fast;
80
+
81
+}
82
+
83
+static int steppers_move_axis(AccelStepper &axis, long pos) {
84
+    if (state == step_disabled) {
85
+        Serial.println(F("Enabling stepper drivers"));
86
+
87
+        stepper_x.enableOutputs();
88
+        stepper_y.enableOutputs();
89
+        stepper_z.enableOutputs();
90
+        stepper_e.enableOutputs();
91
+        state = step_not_homed;
92
+    }
93
+
94
+    axis.moveTo(pos);
95
+}
96
+
97
+int steppers_move_x(long pos) {
98
+    Serial.print(F("Moving X to "));
99
+    Serial.print(pos);
100
+    Serial.print(F(" mm ("));
101
+    Serial.print(pos * XY_STEPS_PER_MM);
102
+    Serial.println(F(" steps)"));
103
+
104
+    return steppers_move_axis(stepper_x, pos * XY_STEPS_PER_MM);
105
+}
106
+
107
+int steppers_move_y(long pos) {
108
+    Serial.print(F("Moving Y to "));
109
+    Serial.print(pos);
110
+    Serial.print(F(" mm ("));
111
+    Serial.print(pos * XY_STEPS_PER_MM);
112
+    Serial.println(F(" steps)"));
113
+
114
+    return steppers_move_axis(stepper_y, pos * XY_STEPS_PER_MM);
115
+}
116
+
117
+int steppers_move_z(long pos) {
118
+    Serial.print(F("Moving Z to "));
119
+    Serial.print(pos);
120
+    Serial.print(F(" mm ("));
121
+    Serial.print(pos * Z_STEPS_PER_MM);
122
+    Serial.println(F(" steps)"));
123
+
124
+    return steppers_move_axis(stepper_z, pos * Z_STEPS_PER_MM);
125
+}
126
+
127
+int steppers_move_e(long pos) {
128
+    Serial.print(F("Moving E to "));
129
+    Serial.print(pos);
130
+    Serial.print(F(" mm ("));
131
+    Serial.print(pos * E_STEPS_PER_MM);
132
+    Serial.println(F(" steps)"));
133
+
134
+    return steppers_move_axis(stepper_e, pos * E_STEPS_PER_MM);
135
+}

Завантаження…
Відмінити
Зберегти