gen_gcode/
lib.rs

1//! Generate G-Code with funcational operation describing motion of the machine that the created gcode should produce
2
3#[cfg(test)]
4mod tests {
5    use super::*;
6
7    #[test]
8    fn it_works() {
9        assert_eq!(2 + 2, 4);
10    }
11
12    #[test]
13    fn test_move_xy() {
14        let p = Point2d { x: 10.0, y: 5.0 };
15        let gcode = move_xy(p, false, None, None);
16        assert_eq!("G0 X10 Y5", gcode);
17    }
18
19    #[test]
20    fn test_arc_ij() {
21        let p = Point2d { x: 125.0, y: 0.0 };
22        let gcode = move_xy_arc_ij(Some(p), Some(62.5), None, None, false);
23        assert_eq!("G2 X125 Y0 I62.5", gcode);
24    }
25
26    #[test]
27    fn test_set_pos_2d() {
28        let p = Point2d { x: 125.0, y: 125.0 };
29        let gcode = set_pos_2d(p, None);
30        assert_eq!("G92 X125 Y125", gcode);
31    }
32
33    #[test]
34    fn test_set_pos_2d_with_e() {
35        let p = Point2d { x: 125.0, y: 125.0 };
36        let gcode = set_pos_2d(p, Some(90));
37        assert_eq!("G92 X125 Y125 E90", gcode);
38    }
39
40    #[test]
41    fn test_set_pos_3d() {
42        let p = Point3d { x: 125.0, y: 125.0, z: 25.0};
43        let gcode = set_pos_3d(p, None);
44        assert_eq!("G92 X125 Y125 Z25", gcode);
45    }
46
47    #[test]
48    fn test_set_pos_3d_with_e() {
49        let p = Point3d { x: 125.0, y: 125.0, z: 25.0 };
50        let gcode = set_pos_3d(p, Some(90));
51        assert_eq!("G92 X125 Y125 Z25 E90", gcode);
52    }
53}
54
55
56/// Defines a 2 dimentional point in the XY catersian coordanant system
57/// 
58/// # Examples
59/// ```
60/// extern crate gen_gcode;
61/// use gen_gcode::Point2d;
62/// 
63/// let p1 = Point2d { x: 0.0, y: 0.0 };
64/// let p2 = Point2d { x: 10.0, y: 0.0 };
65/// let p3 = Point2d { x: 10.0, y: 10.0 };
66/// let p4 = Point2d { x: 0.0, y: 10.0 };
67/// let square: Vec<Point2d> = vec!(p1, p2, p3, p4);
68/// ```
69#[derive(Debug, Copy, Clone)]
70pub struct Point2d {
71    pub x: f32,
72    pub y: f32,
73}
74
75/// Defines a 3 dimentional point in the XYZ catersian coordanant system
76/// 
77/// # Examples
78/// ```
79/// extern crate gen_gcode;
80/// use gen_gcode::Point3d;
81/// 
82/// let p1 = Point3d { x: 0.0, y: 0.0, z: 0.0 };
83/// let p2 = Point3d { x: 10.0, y: 0.0, z: 0.0 };
84/// let p3 = Point3d { x: 10.0, y: 10.0, z: 0.0 };
85/// let p4 = Point3d { x: 0.0, y: 10.0, z: 0.0 };
86/// let p5 = Point3d { x: 0.0, y: 10.0, z: 10.0 };
87/// let p6 = Point3d { x: 10.0, y: 10.0, z: 10.0 };
88/// let p7 = Point3d { x: 10.0, y: 0.0, z: 10.0 };
89/// let p8 = Point3d { x: 0.0, y: 0.0, z: 10.0 };
90/// let cube: Vec<Point3d> = vec!(p1, p2, p3, p4, p5, p6, p7, p8);
91/// ```
92#[derive(Debug, Copy, Clone)]
93pub struct Point3d {
94    pub x: f32,
95    pub y: f32,
96    pub z: f32,
97}
98
99/// Returns a G1 or G0 command as a String
100/// 
101/// # Examples
102/// ```
103/// extern crate gen_gcode;
104/// use gen_gcode::{Point2d, move_xy};
105/// 
106/// let p = Point2d { x: 10.0, y: 5.0 };
107/// // move without extruding
108/// let gcode = move_xy(p, false, None, None);
109/// assert_eq!("G0 X10 Y5", gcode);
110/// ```
111/// 
112/// ```
113/// extern crate gen_gcode;
114/// use gen_gcode::{Point2d, move_xy};
115/// 
116/// let p = Point2d { x: 10.0, y: 5.0 };
117/// // move with extrude
118/// let gcode = move_xy(p, true, None, None);
119/// assert_eq!("G1 X10 Y5", gcode);
120/// ```
121/// 
122pub fn move_xy(dest:Point2d, extrude: bool, feed_rate: Option<u32>, flow_rate: Option<f32>) -> String {
123    let f_str: String;
124    let e_str: String;
125    if let Some(maybe_feed_rate) = feed_rate {
126        f_str = format!(" F{}", maybe_feed_rate);
127    } else {
128        f_str = format!("");
129    }
130    
131    if extrude {
132        if let Some(maybe_flow_rate) = flow_rate {
133            e_str = format!(" E{}", maybe_flow_rate);
134        } else {
135            e_str = format!("");
136        }
137        return format!("G1 X{x} Y{y}{e}{f}\n", x=dest.x, y=dest.y, e=e_str, f=f_str)
138    } else {
139        return format!("G0 X{x} Y{y}{f}\n", x=dest.x, y=dest.y, f=f_str)
140    }
141
142}
143
144pub fn move_xyz(dest:Point3d, extrude: bool, feed_rate: Option<u32>, flow_rate: Option<f32>) -> String {
145    let f_str: String;
146    let e_str: String;
147    if let Some(maybe_feed_rate) = feed_rate {
148        f_str = format!(" F{}", maybe_feed_rate);
149    } else {
150        f_str = format!("");
151    }
152    
153    if extrude {
154        if let Some(maybe_flow_rate) = flow_rate {
155            e_str = format!(" E{}", maybe_flow_rate);
156        } else {
157            e_str = format!("");
158        }
159        return format!("G1 X{x} Y{y} Z{z}{e}{f}\n", x=dest.x, y=dest.y, z=dest.z, e=e_str, f=f_str)
160    } else {
161        return format!("G0 X{x} Y{y} Z{z}{f}\n", x=dest.x, y=dest.y, z=dest.z, f=f_str)
162    }
163
164}
165
166pub fn move_z(z: f32) -> String {
167    return format!("G0 Z{}", z)
168}
169
170/// Returns a G2 or G3 command as a String
171/// 
172/// # Examples
173/// ```
174/// extern crate gen_gcode;
175/// use gen_gcode::{Point2d, move_xy};
176/// 
177/// let p = Point2d { x: 125.0, y: 0.0 };
178/// // Create a Clockwise 180 degree Arc starting at 0,0 ending at 125,0 with center point 62.5,0
179/// let gcode = move_xy_arc_ij(Some(p), Some(62.5), None, None, false);
180/// assert_eq!("G2 X125 Y0 I62.5", gcode);
181/// ```
182pub fn move_xy_arc_ij(dest: Option<Point2d>, x_offset: Option<f32>, y_offset: Option<f32>, flow_rate: Option<f32>, ccw: bool) -> String {
183    let x_str: String;
184    let y_str: String;
185    let i_str: String;
186    let j_str: String;
187    let e_str: String;
188    if let Some(maybe_dest) = dest {
189        x_str = format!(" X{}", maybe_dest.x);
190        y_str = format!(" Y{}", maybe_dest.y);
191    } else {
192        x_str = format!("");
193        y_str = format!("");
194    }
195    if let Some(maybe_x_offset) = x_offset {
196        i_str = format!(" I{}", maybe_x_offset);
197    } else {
198        i_str = format!("");
199    }
200    if let Some(maybe_y_offset) = y_offset {
201        j_str = format!(" J{}", maybe_y_offset);
202    } else {
203        j_str = format!("");
204    }
205    if let Some(maybe_flow_rate) = flow_rate {
206        e_str = format!(" E{}", maybe_flow_rate);
207    } else {
208        e_str = format!("");
209    }
210    if ccw {
211        return format!("G3{x}{y}{i}{j}{e}\n", i=i_str, j=j_str, x=x_str, y=y_str, e=e_str);
212    } else {
213        return format!("G2{x}{y}{i}{j}{e}\n", i=i_str, j=j_str, x=x_str, y=y_str, e=e_str);
214    }
215}
216
217/// Returns a G21 command as a String
218///
219/// Sets units to millimeters
220pub fn use_millimeters() -> String {
221    return format!("G21 ; set units to millimeters\n")
222}
223
224/// Returns a G20 command as a String
225/// 
226/// Sets units to inches
227pub fn use_inches() -> String {
228    return format!("G20 ; set units to inches\n")
229}
230
231/// Returns a G90 command as a String
232/// 
233/// sets all axes to absolute positioning (relative to home, ie. (0,0))
234pub fn absolute_positioning() -> String {
235    return format!("G90 ; Set all axes to absolute\n")
236}
237
238/// Returns a G91 command as a String
239/// 
240/// sets all axes to relative positioning (relative to nozzle/tool position)
241pub fn relative_positioning() -> String {
242    return format!("G91 ; Set all axes to relative\n")
243}
244
245/// Returns a G92 command to set the current nozzle/tool possition in the XY plane as a String
246/// 
247/// # Examples
248/// ```
249/// extern crate gen_gcode;
250/// use gen_gcode::{Point2d, move_xy};
251/// 
252/// let p = Point2d { x: 125.0, y: 125.0 };
253/// let gcode = set_pos_2d(p, None);
254/// assert_eq!("G92 X125 Y125", gcode);
255/// ```
256pub fn set_pos_2d(pos: Point2d, extrude_pos: Option<f32>) -> String {
257    let e_str: String;
258    if let Some(maybe_extrude_pos) = extrude_pos {
259        e_str = format!(" E{}", maybe_extrude_pos);
260    } else {
261        e_str = format!("");
262    }
263    return format!("G92 X{x} Y{y}{e}\n", x=pos.x, y=pos.y, e=e_str)
264}
265
266/// Returns a G92 command to set the current nozzle/tool possition in 3 dimentions (XYZ) as a String
267/// 
268/// # Examples
269/// ```
270/// extern crate gen_gcode;
271/// use gen_gcode::{Point2d, move_xy};
272/// 
273/// let p = Point3d { x: 125.0, y: 125.0, z: 25.0};
274/// let gcode = set_pos_3d(p, None);
275/// assert_eq!("G92 X125 Y125 Z25", gcode);
276/// ```
277pub fn set_pos_3d(pos: Point3d, extrude_pos: Option<f32>) -> String {
278    let e_str: String;
279    if let Some(maybe_extrude_pos) = extrude_pos {
280        e_str = format!(" E{}", maybe_extrude_pos);
281    } else {
282        e_str = format!("");
283    }
284    return format!("G92 X{x} Y{y} Z{z}{e}\n", x=pos.x, y=pos.y, z=pos.z, e=e_str)
285}
286
287pub fn reset_extruder(extrude_pos: f32) -> String {
288    return format!("G92 E{}\n", extrude_pos)
289}
290
291/// Returns a G92.1 command to reset to machine's native possitioning offsets as a String
292pub fn reset_pos() -> String {
293    return format!("G92.1\n")
294}
295
296pub fn set_hotend_temp(temp: u16, hotend: Option<u8>) -> String {
297    let t_str: String;
298    if let Some(maybe_hotend) = hotend {
299        t_str = format!(" T{}", maybe_hotend);
300    } else {
301        t_str = format!("");
302    }
303    return format!("M104 S{s}{t}\n", s=temp, t=t_str)
304}
305
306pub fn wait_hotend_temp(temp: u16, hotend: Option<u8>) -> String {
307    let t_str: String;
308    if let Some(maybe_hotend) = hotend {
309        t_str = format!(" T{}", maybe_hotend);
310    } else {
311        t_str = format!("");
312    }
313    return format!("M109 S{s}{t}\n", s=temp, t=t_str)
314}
315
316pub fn set_fan_speed(speed: u8, fan: Option<u8>) -> String {
317    let p_str: String;
318    if let Some(maybe_fan) = fan {
319        p_str = format!(" P{}", maybe_fan);
320    } else {
321        p_str = format!("");
322    }
323    return format!("M106 S{s}{p}\n", s=speed, p=p_str)
324}
325
326pub fn fan_off(fan: Option<u8>) -> String {
327    let p_str: String;
328    if let Some(maybe_fan) = fan {
329        p_str = format!(" P{}", maybe_fan);
330    } else {
331        p_str = format!("");
332    }
333    return format!("M107{p}\n", p=p_str)
334}
335
336pub fn set_bed_temp(temp: u8) -> String {
337    return format!("M140 S{}\n", temp)
338}
339
340pub fn wait_bed_temp(temp: u8) -> String {
341    return format!("M190 S{}\n", temp)
342}
343
344pub fn set_chamber_temp(temp: u8) -> String {
345    return format!("M141 S{}\n", temp)
346}
347
348pub fn wait_chamber_temp(temp: u8) -> String {
349    return format!("M191 S{}\n", temp)
350}
351
352pub fn auto_home() -> String {
353    return format!("G28\n")
354}
355
356pub fn absolute_extrution() -> String {
357    return format!("M82")
358}
359
360pub fn relative_extrution() -> String {
361    return format!("M83")
362}