├── .gitignore ├── PathTesting ├── Verilog_VCD │ ├── Verilog_VCD.py │ └── __init__.py ├── grbl1.vcd └── vcd_step.py ├── README.md ├── firmware ├── cnc_robot.atsln └── cnc_robot │ ├── Axis.c │ ├── Axis.h │ ├── avr_compiler.h │ ├── buffers │ ├── ring.c │ └── ring.h │ ├── clksys_driver.c │ ├── clksys_driver.h │ ├── cnc_robot.c │ ├── location.h │ ├── robot.cproj │ └── serial │ ├── Serial.c │ ├── Serial.h │ ├── SerialProtocol.c │ └── SerialProtocol.h └── software ├── CNC_Machine.sln ├── CNC_Machine.v11.suo ├── Clipper ├── Properties │ └── AssemblyInfo.cs ├── clipper.cs └── clipper_library.csproj ├── GCode ├── CircleRout.cs ├── GCode.cs ├── IClickable.cs ├── IClickable3D.cs ├── IHasRouts.cs ├── IIsUseful.cs ├── InvoluteGear.cs ├── MoveTool.cs ├── Properties │ └── AssemblyInfo.cs ├── PulleyRout.cs ├── Rout.cs ├── Router.cs ├── Router.csproj ├── RouterCommand.cs └── SimpleClickable.cs ├── GUI ├── App.config ├── COMPortForm.Designer.cs ├── COMPortForm.cs ├── COMPortForm.resx ├── GUI.csproj ├── Icon.ico ├── ObjLoader.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── RouterDrawing.Designer.cs ├── RouterDrawing.cs ├── RouterDrawing.resx ├── RouterUI.Designer.cs ├── RouterUI.cs ├── RouterUI.resx └── Viewport3d.cs ├── Icon.ico ├── OpenTK ├── OpenTK.GLControl.dll └── OpenTK.dll ├── Robot ├── IHardware.cs ├── IRobotCommand.cs ├── MoveCommand.cs ├── Properties │ └── AssemblyInfo.cs ├── ResetCommand.cs ├── Robot.cs ├── Robot.csproj └── StatusCommand.cs ├── Serial ├── Properties │ └── AssemblyInfo.cs ├── Serial.csproj ├── SerialPacket.cs └── SerialPortWrapper.cs └── Utilities ├── CoolDrawing.cs ├── IOpenGLDrawable.cs ├── LineMath.cs ├── MathHelper.cs ├── Properties └── AssemblyInfo.cs ├── Utilities.csproj └── Vector3i.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.hex 4 | *.mk 5 | *.d 6 | *.eep 7 | *.elf 8 | *.lss 9 | *.map 10 | *.srec 11 | 12 | # Libraries 13 | *.lib 14 | *.a 15 | 16 | # Shared objects (inc. Windows DLLs) 17 | *.dll 18 | *.so 19 | *.so.* 20 | *.dylib 21 | 22 | # Executables 23 | *.exe 24 | *.out 25 | *.app 26 | 27 | # Repo specific files 28 | TcfTransactionLog.csv 29 | firmware/cnc_robot/Debug/* 30 | firmware/cnc_robot/Release/* 31 | software/*/*/Debug/* 32 | software/*/*/Release/* 33 | *.csproj.user 34 | *.atsuo 35 | -------------------------------------------------------------------------------- /PathTesting/Verilog_VCD/__init__.py: -------------------------------------------------------------------------------- 1 | from Verilog_VCD import * -------------------------------------------------------------------------------- /PathTesting/vcd_step.py: -------------------------------------------------------------------------------- 1 | from Verilog_VCD import * 2 | from optparse import OptionParser 3 | import os 4 | 5 | import plotly 6 | from plotly.graph_objs import Scatter, Layout, Figure 7 | from plotly import tools 8 | import numpy as np 9 | 10 | x_times = [] 11 | x_values = [] 12 | 13 | class step_path(object): 14 | ''' 15 | Encapsulates a path defined by a number of unit-spaced steps occurring at specific times. 16 | ''' 17 | def __init__(self, times, values): 18 | self.time_value = zip(times, values) 19 | 20 | def append(self, time, value): 21 | self.time_value.append((time, value)) 22 | 23 | def steps_exact(self, step = True): 24 | ''' 25 | Returns a line which follows the steps taken as accurately as possible. 26 | Set "step" to true to include two points per value change: 27 | - one at T 28 | ''' 29 | last_v = None 30 | for (t, v) in self.time_value: 31 | if last_v is not None and step: 32 | yield (t, last_v) 33 | yield (t, v) 34 | last_v = v; 35 | 36 | def sample(self, rate): 37 | (last_t, last_v) = self.time_value[0] 38 | (this_t, this_v) = self.time_value[1] 39 | time = last_t # First time 40 | index = 2 41 | while (time < self.time_value[-1][0]): 42 | while time > this_t and index < len(self.time_value): 43 | (last_t, last_v) = (this_t, this_v) 44 | (this_t, this_v) = self.time_value[index] 45 | index = index + 1 46 | 47 | factor = (time - last_t) / (this_t - last_t) 48 | v = (1.0 - factor) * last_v + factor * this_v 49 | yield (time, v) 50 | time = time + rate 51 | 52 | def times(self): 53 | return [time for (time, value) in self.time_value] 54 | 55 | def values(self): 56 | return [value for (time, value) in self.time_value] 57 | 58 | class step_path_vcd(step_path): 59 | ''' 60 | Encapsulates a path defined by a number of unit-spaced steps occurring at specific times. 61 | ''' 62 | def __init__(self, step_signal, dir_signal): 63 | self.time_value = [(0, 0)] # Assume the signal begins at time 0. The initial value is always 0. 64 | x = 0 65 | dir_index = 0 66 | for (time, value) in step_signal: 67 | if value == '1': 68 | # Rising Edge, what's the "dir" signal say? 69 | while dir_index + 1 < len(dir_signal) and dir_signal[dir_index + 1][0] < time: 70 | dir_index = dir_index + 1 71 | dir = dir_signal[dir_index][1] 72 | if dir == '1': 73 | x = x + 1 74 | else: 75 | x = x - 1 76 | self.time_value.append((time, x)) 77 | 78 | def cleanup(self): 79 | ''' 80 | A step signal might remain inactive for a long period of time, 81 | (I.E, the axis has stopped). The value will remain high or low 82 | for this period of time though, and add some interesting artifacts 83 | to the graphs. Attempt to clean up sections with no step activity 84 | for a long period of time. 85 | ''' 86 | 87 | i = 0 88 | while (i < len(self.time_value)-1): 89 | tn1 = self.time_value[i-1][0] if i > 0 else None 90 | t0 = self.time_value[i][0] 91 | t1 = self.time_value[i+1][0] 92 | t2 = self.time_value[i+2][0] if i < len(self.time_value) - 2 else None 93 | if (t1 - t0 > 0.1): 94 | v = self.time_value[i][1] 95 | d0 = t0 - tn1 if tn1 is not None else None 96 | d1 = t2 - t1 if t2 is not None else None 97 | 98 | # They won't both be none 99 | d1 = d0 if d1 is None else d1 100 | d0 = d1 if d0 is None else d0 101 | 102 | if ((d0 + d1) * 4 < (t1 - t0)): 103 | self.time_value.insert(i+1, (t1 - d0 * 4, v)) 104 | self.time_value.insert(i+1, (d0 * 4 + t0, v)) 105 | i = i + 2 106 | i = i + 1 107 | 108 | 109 | def gen_axis_graphs(vcd_dict, step_signal_name, dir_signal_name, axis_name, hue): 110 | x_steps = None 111 | x_dir = None 112 | for key in vcd_dict.keys(): 113 | name = vcd_dict[key]['nets'][0]['name'] 114 | print("Key {0} name is {1}".format(key, name)) 115 | if step_signal_name in vcd_dict[key]['nets'][0]['name'].lower(): 116 | x_steps = vcd_dict[key]['tv'] 117 | if dir_signal_name in vcd_dict[key]['nets'][0]['name'].lower(): 118 | x_dir = vcd_dict[key]['tv'] 119 | 120 | if x_steps is None or x_dir is None: 121 | return [None, None, None, None] 122 | 123 | x_path = step_path_vcd(x_steps, x_dir) 124 | 125 | # Ignore any axis with no data 126 | if len(x_path.times()) < 5: 127 | return [None, None, None, None] 128 | 129 | x_path.cleanup() 130 | 131 | 132 | # Sample velocity at a consistent interval of 25uS 133 | sample_period = 0.000025 134 | 135 | 136 | # Low pass filter code from here: https://tomroelandts.com/articles/how-to-create-a-simple-low-pass-filter 137 | fc = sample_period * 75 # Cutoff frequency as a fraction of the sampling rate (in (0, 0.5)) 138 | b = sample_period * 150 # Transition band, as a fraction of the sampling rate (in (0, 0.5)). 139 | N = int(np.ceil((4 / b))) 140 | if not N % 2: N += 1 # Make sure that N is odd. 141 | n = np.arange(N) 142 | 143 | # Compute sinc filter. 144 | h = np.sinc(2 * fc * (n - (N - 1) / 2.)) 145 | 146 | # Compute Blackman window. 147 | w = 0.42 - 0.5 * np.cos(2 * np.pi * n / (N - 1)) + \ 148 | 0.08 * np.cos(4 * np.pi * n / (N - 1)) 149 | 150 | # Multiply sinc filter with window. 151 | h = h * w 152 | 153 | # Normalize to get unity gain. 154 | h = h / np.sum(h) 155 | 156 | print("Shift: {0}".format((N - 1) / 2)) 157 | vraw = step_path([], []) 158 | (lt, lv) = (None, None) 159 | for (t, v) in x_path.steps_exact(False): 160 | if lt is not None and lv is not None: 161 | vraw.append(t, (v - lv) / (t - lt)) 162 | (lt, lv) = (t, v) 163 | 164 | 165 | 166 | v_sampled_t = [] 167 | v_sampled_v = [] 168 | (lt, lv) = (None, None) 169 | for (t, v) in vraw.sample(sample_period): 170 | v_sampled_t.append(t) 171 | v_sampled_v.append(v) 172 | 173 | # Pass the sampled velocity values through a low-pass filter 174 | vel_filtered_v = np.convolve(v_sampled_v, h)[(N - 1) / 2:] 175 | vel_filtered_t = v_sampled_t[:len(v_sampled_t) - (N - 1) / 2] 176 | 177 | acc = [] 178 | for i in range(1, len(vel_filtered_v)): 179 | acc.append((vel_filtered_v[i] - vel_filtered_v[i-1]) / sample_period) 180 | acc.insert(0, acc[0]) 181 | 182 | return [ 183 | Scatter(yaxis='y1', x=x_path.times(), y=x_path.values(), mode = 'lines', name="{0} position".format(axis_name), 184 | line=dict(shape='hv', color='hsv({0}, 0.7, 1.0)'.format(hue % 360))), 185 | 186 | Scatter(yaxis='y1', x=vraw.times(), y=vraw.values(), mode = 'lines', name="{0} velocity".format(axis_name), 187 | line=dict(color='hsv({0}, 0.7, 1.0)'.format((hue) % 360, width=1))), 188 | 189 | Scatter(yaxis='y1', x=vel_filtered_t, y=vel_filtered_v, mode = 'lines', name="{0} v. filtered".format(axis_name), 190 | line=dict(color='hsv({0}, 0.7, 1.0)'.format((hue) % 360))), 191 | 192 | Scatter(yaxis='y1', x=vel_filtered_t, y=acc, mode = 'lines', name="{0} acceleration".format(axis_name), 193 | line=dict(color='hsv({0}, 0.7, 1.0)'.format((hue) % 360))), 194 | ] 195 | 196 | 197 | if __name__ == "__main__": 198 | parser = OptionParser() 199 | parser.add_option("-v", "--vcd", dest="vcd_filename", 200 | help="Name of the VCD file to load", metavar="FILE") 201 | (options, args) = parser.parse_args() 202 | 203 | vcd_dict = Verilog_VCD.parse_vcd(options.vcd_filename, opt_timescale="s") 204 | print vcd_dict.keys() 205 | 206 | 207 | 208 | 209 | x_axis_data = gen_axis_graphs(vcd_dict, "x_step", "x_dir", "X", 15) 210 | y_axis_data = gen_axis_graphs(vcd_dict, "y_step", "y_dir", "Y", 150) 211 | z_axis_data = gen_axis_graphs(vcd_dict, "z_step", "z_dir", "Z", 255) 212 | 213 | axis_data = [x_axis_data, y_axis_data, z_axis_data] 214 | 215 | fig = tools.make_subplots(rows=5, cols=1, specs=[[{'rowspan': 2}], # Row 1 216 | [None], # Row 2 217 | [{'rowspan': 2}], # Row 3 218 | [None], # Row 4 219 | [{}]], # Row 5 220 | shared_xaxes=True, shared_yaxes=True, vertical_spacing=0.001) 221 | 222 | filename = os.path.splitext(os.path.split(options.vcd_filename)[-1])[0]; 223 | fig['layout'].update(title="Motion Profile from Steps ({0})".format(filename)) 224 | fig['layout']['yaxis1'].update(title="Position (steps)") 225 | fig['layout']['yaxis3'].update(title="Velocity (steps/s)") 226 | fig['layout']['yaxis5'].update(title="Acceleration (steps/s^2)") 227 | 228 | for trace in [p for (p, v, vf, a) in axis_data]: 229 | if trace is not None: 230 | fig.append_trace(trace, 1, 1) 231 | 232 | for trace in [t for (p, v, vf, a) in axis_data for t in [v, vf]]: 233 | if trace is not None: 234 | fig.append_trace(trace, 3, 1) 235 | 236 | for trace in [a for (p, v, vf, a) in axis_data]: 237 | if trace is not None: 238 | fig.append_trace(trace, 5, 1) 239 | 240 | #fig.append_trace(x_axis_data[1], 2, 1) 241 | #fig.append_trace(y_axis_data[1], 2, 1) 242 | #fig.append_trace(z_axis_data[1], 2, 1) 243 | # 244 | #fig.append_trace(x_axis_data[2], 2, 1) 245 | #fig.append_trace(y_axis_data[2], 2, 1) 246 | #fig.append_trace(z_axis_data[2], 2, 1) 247 | # 248 | # 249 | #fig.append_trace(x_axis_data[3], 3, 1) 250 | #fig.append_trace(y_axis_data[3], 3, 1) 251 | #fig.append_trace(z_axis_data[3], 3, 1) 252 | 253 | 254 | #fig = Figure( 255 | # data=axis_data, 256 | # #Scatter(yaxis='y1', x=bt, y=bv, mode = 'lines', name="vel_sampled2"), 257 | # #Scatter(yaxis='y1', x=time, y=vel_filtered, mode = 'lines', name="vel_filtered2"), 258 | # #Scatter(yaxis='y1', x=time, y=av, mode = 'lines', name="acc_sampled2"), 259 | # 260 | # #Scatter(yaxis='y1', x=x_times, y=x_values, mode = 'lines', name="raw position"), 261 | # #Scatter(yaxis='y1', x=x_times, y=vel_raw, mode = 'lines', marker=dict(maxdisplayed=1000), name="raw vel"), 262 | # 263 | # #], 264 | # layout=Layout(title="VCD Decoded Steps", 265 | # yaxis=dict( 266 | # title='Position (steps) -- Velocity (steps/sec) -- Acceleration (steps/sec^2)' 267 | # ), 268 | #)) 269 | plotly.offline.plot(fig, filename="{0}.html".format(filename)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CNC Machine 2 | =========== 3 | 4 | Software, Firmware, and Hardware for a 3 axis CNC Router 5 | 6 | Software 7 | ======== 8 | The software is written in C# and set up to build/run on Windows (possibly Mono). The program does the following things: 9 | * Load GCode (limited functionality) 10 | * Display the router path with an estimation of cut area 11 | * Add/Edit gcode in a visual fashion 12 | * Various control options for manual movement of CNC axis 13 | * Abstracts the specific robot control enabling multiple robots 14 | 15 | Firmware 16 | ======== 17 | The CNC machine uses an XMega128a1. The firmware directory contains AVR studio projects and C code which can be compiled with AVR-GCC. 18 | 19 | Hardware 20 | ======== 21 | Coming Sometime! 22 | -------------------------------------------------------------------------------- /firmware/cnc_robot.atsln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Atmel Studio Solution File, Format Version 11.00 4 | Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "robot", "cnc_robot\robot.cproj", "{F399A07F-26C5-43DF-8A99-F303C18E808B}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|AVR = Debug|AVR 9 | Release|AVR = Release|AVR 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {F399A07F-26C5-43DF-8A99-F303C18E808B}.Debug|AVR.ActiveCfg = Debug|AVR 13 | {F399A07F-26C5-43DF-8A99-F303C18E808B}.Debug|AVR.Build.0 = Debug|AVR 14 | {F399A07F-26C5-43DF-8A99-F303C18E808B}.Release|AVR.ActiveCfg = Release|AVR 15 | {F399A07F-26C5-43DF-8A99-F303C18E808B}.Release|AVR.Build.0 = Release|AVR 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /firmware/cnc_robot/Axis.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Axis.c 3 | * 4 | * Created: 4/15/2012 3:47:48 PM 5 | * Author: xeno 6 | */ 7 | 8 | #include "Axis.h" 9 | 10 | void AxisInit (volatile AXIS_t * axis) 11 | { 12 | axis->pwm_timer->CTRLA = TC_CLKSEL_DIV1_gc; 13 | axis->pwm_timer->CTRLB = TC_WGMODE_SS_gc | axis->compare_mask; /* Single Slope PWM, Top at PER, Output Compares Enabled */ 14 | axis->pwm_timer->CTRLD = TC_EVSEL_OFF_gc; /* No Event Action */ 15 | axis->pwm_timer->PER = axis->axis_run_power; 16 | *axis->phase_pwm_cmp1 = 0; 17 | *axis->phase_pwm_cmp2 = 0; 18 | 19 | axis->delta = 0; 20 | axis->location = 0; 21 | 22 | axis->state = 0; 23 | 24 | axis->can_update_output = true; 25 | axis->current_location_buffer = 0; 26 | } 27 | int32_t AxisGetCurrentPosition (volatile AXIS_t * axis) 28 | { 29 | /* If it's moving, use the buffered value for interrupt safe access */ 30 | if (IsMoving(axis)) 31 | { 32 | axis->can_update_output = false; 33 | uint32_t return_value = axis->current_location_buffer; 34 | axis->can_update_output = true; 35 | return return_value; 36 | } 37 | else 38 | { 39 | return axis->location; 40 | } 41 | } 42 | volatile bool IsOnLimit (volatile AXIS_t * a) 43 | { 44 | /* TODO: read limit switch pin multiple times */ 45 | return (a->limit_switch_port->IN & a->limit_switch_mask); /* Active high */ 46 | } 47 | volatile bool IsMoving (volatile AXIS_t * axis) 48 | { 49 | /* TODO: Return something reasonable here... */ 50 | return (axis->delta != 0); 51 | } 52 | void AxisRun (volatile AXIS_t * axis, int32_t location, uint16_t speed) 53 | { 54 | // TODO: Re-implement! 55 | ///* Make sure the axis is stopped before updating values and running again */ 56 | //if (IsMoving (axis)) 57 | //{ 58 | // AxisStop(axis); 59 | //} 60 | // 61 | ///* Clamp the period to the minimum defined period (fastest speed) */ 62 | //if (speed < axis->min_period) 63 | //{ 64 | // speed = axis->min_period; 65 | //} 66 | // 67 | ///* Update location */ 68 | //axis->delta = location; 69 | 70 | /* Update and restart the timers */ 71 | //axis->pwm_timer->PER = axis->axis_run_power; 72 | //axis->pwm_timer->CTRLFSET = TC_CMD_RESTART_gc; 73 | } 74 | void AxisStop (volatile AXIS_t * axis) 75 | { 76 | // TODO: Re-implement! 77 | /* Set the axis to idle power */ 78 | //axis->pwm_timer->PER = axis->axis_idle_power; 79 | //axis->pwm_timer->CTRLFSET = TC_CMD_RESTART_gc; 80 | 81 | /* Update the current position buffer */ 82 | //axis->current_location_buffer = axis->location; 83 | } 84 | void ZeroLocation (volatile AXIS_t * axis) 85 | { 86 | AxisStop(axis); 87 | axis->delta = 0; 88 | axis->location = 0; 89 | axis->current_location_buffer = 0; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /firmware/cnc_robot/Axis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Axis.h 3 | * 4 | * Created: 4/15/2012 3:48:17 PM 5 | * Author: xeno 6 | */ 7 | 8 | #ifndef AXIS_H 9 | #define AXIS_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /* 16 | * Each axis is associated with two counters: 17 | * - TC0 for PWM, using an output compare 18 | * - TC1 for updates to the PWM duty cycle 19 | */ 20 | typedef struct 21 | { 22 | volatile int32_t location; 23 | volatile int32_t delta; 24 | 25 | //TC0_t * step_timer; /* TC0 for step timing (increment/decrement on overflow */ 26 | TC1_t * pwm_timer; /* TC1 for Sinusoidal Commutated PWM */ 27 | 28 | //uint8_t pwm_prescaler; 29 | 30 | volatile PORT_t * limit_switch_port; /* Port attached to the limit switch */ 31 | uint8_t limit_switch_mask; /* Pin on the limit switch port */ 32 | 33 | PORT_t * sign_select_port; /* Port for sign select pins */ 34 | uint8_t sign_switch_mask1; /* Sign switch mask for phase 1 */ 35 | uint8_t sign_switch_mask2; /* Sign switch mask for phase 2 */ 36 | 37 | /* Compare registers for PWM output */ 38 | uint16_t * phase_pwm_cmp1; 39 | uint16_t * phase_pwm_cmp2; 40 | 41 | //uint8_t axis_idle_power; 42 | uint8_t axis_run_power; 43 | 44 | //uint16_t min_period; 45 | 46 | uint8_t compare_mask; 47 | 48 | char state; 49 | 50 | /* Some private data ... */ 51 | bool can_update_output; 52 | int32_t current_location_buffer; 53 | 54 | } AXIS_t; 55 | 56 | int32_t AxisGetCurrentPosition (volatile AXIS_t * axis); 57 | bool IsAxisInterruptEnabled (volatile AXIS_t * axis); 58 | volatile bool IsOnLimit (volatile AXIS_t * a); 59 | volatile bool IsMoving (volatile AXIS_t * axis); 60 | void AxisRun (volatile AXIS_t * axis, int32_t location, uint16_t speed); 61 | void AxisStop (volatile AXIS_t * axis); 62 | void ZeroLocation (volatile AXIS_t * axis); 63 | 64 | #endif -------------------------------------------------------------------------------- /firmware/cnc_robot/avr_compiler.h: -------------------------------------------------------------------------------- 1 | /* This file has been prepared for Doxygen automatic documentation generation.*/ 2 | /*! \file ********************************************************************* 3 | * 4 | * \brief This file implements some macros that makes the IAR C-compiler and 5 | * avr-gcc work with the same code base for the AVR architecture. 6 | * 7 | * \par Documentation 8 | * For comprehensive code documentation, supported compilers, compiler 9 | * settings and supported devices see readme.html 10 | * 11 | * \author 12 | * Atmel Corporation: http://www.atmel.com \n 13 | * Support email: avr@atmel.com 14 | * 15 | * $Revision: 2772 $ 16 | * $Date: 2009-09-11 12:40:26 +0200 (fr, 11 sep 2009) $ \n 17 | * 18 | * Copyright (c) 2008, Atmel Corporation All rights reserved. 19 | * 20 | * Redistribution and use in source and binary forms, with or without 21 | * modification, are permitted provided that the following conditions are met: 22 | * 23 | * 1. Redistributions of source code must retain the above copyright notice, 24 | * this list of conditions and the following disclaimer. 25 | * 26 | * 2. Redistributions in binary form must reproduce the above copyright notice, 27 | * this list of conditions and the following disclaimer in the documentation 28 | * and/or other materials provided with the distribution. 29 | * 30 | * 3. The name of ATMEL may not be used to endorse or promote products derived 31 | * from this software without specific prior written permission. 32 | * 33 | * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 34 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 35 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND 36 | * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, 37 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 39 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 40 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 41 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 42 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | ******************************************************************************/ 44 | 45 | #ifndef COMPILER_AVR_H 46 | #define COMPILER_AVR_H 47 | 48 | #ifndef F_CPU 49 | /*! \brief Define default CPU frequency, if this is not already defined. */ 50 | #define F_CPU 2000000UL 51 | #endif 52 | 53 | #include 54 | #include 55 | #include 56 | 57 | /*! \brief This macro will protect the following code from interrupts. */ 58 | #define AVR_ENTER_CRITICAL_REGION( ) uint8_t volatile saved_sreg = SREG; \ 59 | cli(); 60 | 61 | /*! \brief This macro must always be used in conjunction with AVR_ENTER_CRITICAL_REGION 62 | * so the interrupts are enabled again. 63 | */ 64 | #define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg; 65 | 66 | #if defined( __ICCAVR__ ) 67 | 68 | #include 69 | #include 70 | #include 71 | #include 72 | 73 | #ifndef __HAS_ELPM__ 74 | #define _MEMATTR __flash 75 | #else /* __HAS_ELPM__ */ 76 | #define _MEMATTR __farflash 77 | #endif /* __HAS_ELPM__ */ 78 | 79 | /*! \brief Perform a delay of \c us microseconds. 80 | * 81 | * The macro F_CPU is supposed to be defined to a constant defining the CPU 82 | * clock frequency (in Hertz). 83 | * 84 | * The maximal possible delay is 262.14 ms / F_CPU in MHz. 85 | * 86 | * \note For the IAR compiler, currently F_CPU must be a 87 | * multiple of 1000000UL (1 MHz). 88 | */ 89 | #define delay_us( us ) ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) ) 90 | 91 | /*! \brief Preprocessor magic. 92 | * 93 | * Some preprocessor magic to allow for a header file abstraction of 94 | * interrupt service routine declarations for the IAR compiler. This 95 | * requires the use of the C99 _Pragma() directive (rather than the 96 | * old #pragma one that could not be used as a macro replacement), as 97 | * well as two different levels of preprocessor concetanations in 98 | * order to do both, assign the correct interrupt vector name, as well 99 | * as construct a unique function name for the ISR. 100 | * 101 | * \note Do *NOT* try to reorder the macros below, as this will only 102 | * work in the given order. 103 | */ 104 | #define PRAGMA(x) _Pragma( #x ) 105 | #define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void) 106 | #define sei( ) (__enable_interrupt( )) 107 | #define cli( ) (__disable_interrupt( )) 108 | 109 | /*! \brief Define the no operation macro. */ 110 | #define nop( ) (__no_operation()) 111 | 112 | /*! \brief Define the watchdog reset macro. */ 113 | #define watchdog_reset( ) (__watchdog_reset( )) 114 | 115 | 116 | #define INLINE PRAGMA( inline=forced ) static 117 | 118 | #define FLASH_DECLARE(x) _MEMATTR x 119 | #define FLASH_STRING(x) ((_MEMATTR const char *)(x)) 120 | #define FLASH_STRING_T char const _MEMATTR * 121 | #define FLASH_BYTE_ARRAY_T uint8_t const _MEMATTR * 122 | #define PGM_READ_BYTE(x) *(x) 123 | #define PGM_READ_WORD(x) *(x) 124 | 125 | #define SHORTENUM /**/ 126 | 127 | #elif defined( __GNUC__ ) 128 | 129 | #include 130 | #include 131 | #include 132 | #include 133 | 134 | /*! \brief Define the delay_us macro for GCC. */ 135 | #define delay_us( us ) (_delay_us( us )) 136 | 137 | #define INLINE static inline 138 | 139 | /*! \brief Define the no operation macro. */ 140 | #define nop() do { __asm__ __volatile__ ("nop"); } while (0) 141 | 142 | #define MAIN_TASK_PROLOGUE int 143 | 144 | 145 | #define MAIN_TASK_EPILOGUE() return -1; 146 | 147 | #define SHORTENUM __attribute__ ((packed)) 148 | 149 | #else 150 | #error Compiler not supported. 151 | #endif 152 | 153 | #endif 154 | 155 | -------------------------------------------------------------------------------- /firmware/cnc_robot/buffers/ring.c: -------------------------------------------------------------------------------- 1 | #include "ring.h" 2 | 3 | void RingBufferInit(RingBuffer * r, uint8_t length, elem_type * buffer) 4 | { 5 | r->head = 0; 6 | r->count = 0; 7 | r->max_length = length - 1; 8 | r->buffer = buffer; 9 | } 10 | 11 | bool RingBufferIsEmpty(RingBuffer * r) 12 | { 13 | return r->count == 0; 14 | } 15 | 16 | bool RingBufferIsFull(RingBuffer * r) 17 | { 18 | return r->count > r->max_length; 19 | } 20 | 21 | uint8_t RingBufferCount(RingBuffer * r) 22 | { 23 | return r->count; 24 | } 25 | 26 | void RingBufferAdd(RingBuffer * r, elem_type element) 27 | { 28 | r->buffer[r->head & r->max_length] = element; 29 | r->head++; 30 | r->count++; 31 | } 32 | 33 | elem_type RingBufferGet(RingBuffer * r) 34 | { 35 | elem_type e = r->buffer[(r->head - r->count) & r->max_length]; 36 | r->count--; 37 | return e; 38 | } 39 | -------------------------------------------------------------------------------- /firmware/cnc_robot/buffers/ring.h: -------------------------------------------------------------------------------- 1 | #ifndef RING_BUFFER_H_INCLUDED 2 | #define RING_BUFFER_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include "../location.h" 7 | 8 | typedef Location_t elem_type; 9 | 10 | typedef struct RingBuffer_T 11 | { 12 | uint8_t max_length; 13 | uint8_t head; 14 | uint8_t count; 15 | elem_type * buffer; 16 | } RingBuffer; 17 | 18 | /** 19 | * Initialize the ring buffer 20 | * @param RingBuffer * r Ring buffer to initialize 21 | * @param uint8_t length Number of elements in the ring buffer. 22 | * Must be a power of 2 in the range [2, 128] 23 | * @param elem_type * buffer Pointer to the raw storage array 24 | */ 25 | void RingBufferInit(RingBuffer * r, uint8_t length, elem_type * buffer); 26 | 27 | bool RingBufferIsEmpty(RingBuffer * r); 28 | 29 | bool RingBufferIsFull(RingBuffer * r); 30 | 31 | uint8_t RingBufferCount(RingBuffer * r); 32 | 33 | void RingBufferAdd(RingBuffer * r, elem_type element); 34 | 35 | elem_type RingBufferGet(RingBuffer * r); 36 | 37 | 38 | #endif // RING_BUFFER_H_INCLUDED 39 | -------------------------------------------------------------------------------- /firmware/cnc_robot/clksys_driver.h: -------------------------------------------------------------------------------- 1 | /* This file has been prepared for Doxygen automatic documentation generation.*/ 2 | /*! \file ********************************************************************* 3 | * 4 | * \brief XMEGA Clock System driver header file. 5 | * 6 | * This file contains the function prototypes and enumerator definitions 7 | * for various configuration parameters for the XMEGA Clock System driver. 8 | * 9 | * The driver is not intended for size and/or speed critical code, since 10 | * most functions are just a few lines of code, and the function call 11 | * overhead would decrease code performance. The driver is intended for 12 | * rapid prototyping and documentation purposes for getting started with 13 | * the XMEGA Clock System. 14 | * 15 | * For size and/or speed critical code, it is recommended to copy the 16 | * function contents directly into your application instead of making 17 | * a function call. 18 | * 19 | * \par Application note: 20 | * AVR1003: Using the XMEGA Clock System 21 | * 22 | * \par Documentation 23 | * For comprehensive code documentation, supported compilers, compiler 24 | * settings and supported devices see readme.html 25 | * 26 | * \author 27 | * Atmel Corporation: http://www.atmel.com \n 28 | * Support email: avr@atmel.com 29 | * 30 | * $Revision: 1665 $ 31 | * $Date: 2008-06-05 09:21:50 +0200 (to, 05 jun 2008) $ \n 32 | * 33 | * Copyright (c) 2008, Atmel Corporation All rights reserved. 34 | * 35 | * Redistribution and use in source and binary forms, with or without 36 | * modification, are permitted provided that the following conditions are met: 37 | * 38 | * 1. Redistributions of source code must retain the above copyright notice, 39 | * this list of conditions and the following disclaimer. 40 | * 41 | * 2. Redistributions in binary form must reproduce the above copyright notice, 42 | * this list of conditions and the following disclaimer in the documentation 43 | * and/or other materials provided with the distribution. 44 | * 45 | * 3. The name of ATMEL may not be used to endorse or promote products derived 46 | * from this software without specific prior written permission. 47 | * 48 | * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 49 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 50 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND 51 | * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, 52 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 53 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 54 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 57 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 | *****************************************************************************/ 59 | #ifndef CLKSYS_DRIVER_H 60 | #define CLKSYS_DRIVER_H 61 | 62 | #include "avr_compiler.h" 63 | 64 | 65 | /* Definitions of macros. */ 66 | 67 | /*! \brief This macro enables the selected oscillator. 68 | * 69 | * \note Note that the oscillator cannot be used as a main system clock 70 | * source without being enabled and stable first. Check the ready flag 71 | * before using the clock. The function CLKSYS_IsReady( _oscSel ) 72 | * can be used to check this. 73 | * 74 | * \param _oscSel Bitmask of selected clock. Can be one of the following 75 | * OSC_RC2MEN_bm, OSC_RC32MEN_bm, OSC_RC32KEN_bm, OSC_XOSCEN_bm, 76 | * OSC_PLLEN_bm. 77 | */ 78 | #define CLKSYS_Enable( _oscSel ) ( OSC.CTRL |= (_oscSel) ) 79 | 80 | /*! \brief This macro check if selected oscillator is ready. 81 | * 82 | * This macro will return non-zero if is is running, regardless if it is 83 | * used as a main clock source or not. 84 | * 85 | * \param _oscSel Bitmask of selected clock. Can be one of the following 86 | * OSC_RC2MEN_bm, OSC_RC32MEN_bm, OSC_RC32KEN_bm, OSC_XOSCEN_bm, 87 | * OSC_PLLEN_bm. 88 | * 89 | * \return Non-zero if oscillator is ready and running. 90 | */ 91 | #define CLKSYS_IsReady( _oscSel ) ( OSC.STATUS & (_oscSel) ) 92 | 93 | /*! \brief This macro disables routing of clock signals to the Real-Time 94 | * Counter (RTC). 95 | * 96 | * Disabling the RTC saves power if the RTC is not in use. 97 | */ 98 | #define CLKSYS_RTC_ClockSource_Disable() ( CLK.RTCCTRL &= ~CLK_RTCEN_bm ) 99 | 100 | /*! \brief This macro disables the automatic calibration of the selected 101 | * internal oscillator. 102 | * 103 | * \param _clk Clock source calibration to disable, either DFLLRC2M or DFLLRC32M. 104 | */ 105 | #define CLKSYS_AutoCalibration_Disable( _clk ) ( (_clk).CTRL &= ~DFLL_ENABLE_bm ) 106 | 107 | 108 | /* Prototyping of function. Detailed information is found in source file. */ 109 | void CCPWrite( volatile uint8_t * address, uint8_t value ); 110 | void CLKSYS_XOSC_Config( OSC_FRQRANGE_t freqRange, 111 | bool lowPower32kHz, 112 | OSC_XOSCSEL_t xoscModeSelection ); 113 | void CLKSYS_PLL_Config( OSC_PLLSRC_t clockSource, uint8_t factor ); 114 | uint8_t CLKSYS_Disable( uint8_t oscSel ); 115 | void CLKSYS_Prescalers_Config( CLK_PSADIV_t PSAfactor, 116 | CLK_PSBCDIV_t PSBCfactor ); 117 | uint8_t CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_t clockSource ); 118 | void CLKSYS_RTC_ClockSource_Enable( CLK_RTCSRC_t clockSource ); 119 | void CLKSYS_AutoCalibration_Enable( uint8_t clkSource, bool extReference ); 120 | void CLKSYS_XOSC_FailureDetection_Enable( void ); 121 | void CLKSYS_Configuration_Lock( void ); 122 | 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /firmware/cnc_robot/location.h: -------------------------------------------------------------------------------- 1 | /* 2 | * location.h 3 | * 4 | * Created: 7/1/2013 9:59:40 PM 5 | * Author: xeno 6 | */ 7 | 8 | 9 | #ifndef LOCATION_H_ 10 | #define LOCATION_H_ 11 | 12 | 13 | typedef struct 14 | { 15 | uint16_t time; 16 | int32_t x; 17 | int32_t y; 18 | int32_t z; 19 | } Location_t; 20 | 21 | 22 | #endif /* LOCATION_H_ */ -------------------------------------------------------------------------------- /firmware/cnc_robot/robot.cproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 2.0 5 | 6.0 6 | com.Atmel.AVRGCC8 7 | {f399a07f-26c5-43df-8a99-f303c18e808b} 8 | ATxmega128A1 9 | none 10 | Executable 11 | C 12 | $(MSBuildProjectName) 13 | .elf 14 | $(MSBuildProjectDirectory)\$(Configuration) 15 | cnc_robot 16 | robot 17 | cnc_robot 18 | Native 19 | 2.11.1 20 | 21 | 22 | com.atmel.avrdbg.tool.simulator 23 | 24 | com.atmel.avrdbg.tool.ispmk2 25 | AVRISP mkII 26 | 000200012345 27 | 28 | 127.0.0.1 29 | 49225 30 | False 31 | 32 | 33 | PDI 34 | 35 | 1000000 36 | 1000000 37 | 150000 38 | false 39 | false 40 | 0 41 | 0 42 | 0 43 | 0 44 | 45 | 46 | 47 | 48 | com.atmel.avrdbg.tool.simulator 49 | AVR Simulator 50 | 51 | 52 | 53 | 127.0.0.1 54 | 49225 55 | False 56 | 57 | 58 | true 59 | false 60 | 61 | 0 62 | 63 | 64 | 65 | 66 | True 67 | True 68 | True 69 | True 70 | True 71 | True 72 | 73 | 74 | F_CPU=16000000UL 75 | 76 | 77 | Optimize for size (-Os) 78 | True 79 | True 80 | True 81 | 82 | 83 | m 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | True 93 | True 94 | True 95 | True 96 | True 97 | True 98 | 99 | 100 | F_CPU=16000000UL 101 | 102 | 103 | Optimize (-O1) 104 | True 105 | True 106 | Default (-g2) 107 | True 108 | 109 | 110 | m 111 | 112 | 113 | Default (-Wa,-g) 114 | 115 | 116 | 117 | 118 | 119 | compile 120 | 121 | 122 | compile 123 | 124 | 125 | compile 126 | 127 | 128 | compile 129 | 130 | 131 | compile 132 | 133 | 134 | compile 135 | 136 | 137 | compile 138 | 139 | 140 | compile 141 | 142 | 143 | compile 144 | 145 | 146 | compile 147 | 148 | 149 | compile 150 | 151 | 152 | compile 153 | 154 | 155 | compile 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /firmware/cnc_robot/serial/Serial.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "Serial.h" 4 | 5 | // Set to 1 when data is available 6 | volatile char serialPacketReady = 0; 7 | 8 | // For sending and receiving serial packets 9 | SerialData ser; 10 | 11 | void SerialInit(void) 12 | { 13 | SerialDataInitialize(&ser); 14 | 15 | // Setup function pointers 16 | ser.TransmitPacketComplete = &TransmitPacketComplete; 17 | ser.Transmit = &Transmit; 18 | ser.ReceivePacketComplete = &ReceivePacketComplete; 19 | ser.ReceiveDataError = &ReceiveDataError; 20 | 21 | USART_Init(); 22 | } 23 | 24 | void USART_Init(void) 25 | { 26 | // USART Configuration 27 | PORTC.DIRSET = PIN3_bm; 28 | PORTC.DIRCLR = PIN2_bm; 29 | 30 | // RX Interrupt Level 31 | char rxd_int_level = USART_RXCINTLVL_LO_gc; 32 | 33 | 34 | USARTC0.CTRLA = (USARTC0.CTRLA & ~USART_RXCINTLVL_gm) | rxd_int_level; 35 | 36 | // Format Set: 8 data bits, no parity, 1 stop bit 37 | char two_stop_bits = 0; 38 | char char_size = USART_CHSIZE_8BIT_gc; 39 | char parity_mode = USART_PMODE_DISABLED_gc; 40 | USARTC0.CTRLC = (char_size | parity_mode | (two_stop_bits ? USART_SBMODE_bm : 0)); 41 | 42 | // Baud Rate Setup 43 | // Baudrate select = (1/16) * (((I/O clock frequency)/Baudrate) -1) 44 | 45 | // BSEL = fper / (16 * BaudRate) - 1 46 | // = 12 47 | // 48 | uint8_t bsel_value = BSEL; 49 | uint8_t bscale_factor = 0; 50 | USARTC0.BAUDCTRLA = (uint8_t) bsel_value; 51 | USARTC0.BAUDCTRLB = (bscale_factor << USART_BSCALE0_bp) | (bsel_value >> 8); 52 | 53 | // USART RX enable 54 | USARTC0.CTRLB |= (USART_RXEN_bm | USART_TXEN_bm); 55 | } 56 | 57 | 58 | SerialData * SerialDataTransmitStruct (void) 59 | { 60 | if (SerialTransferInProgress (&ser)) 61 | { 62 | return 0; 63 | } 64 | else 65 | { 66 | return &ser; 67 | } 68 | } 69 | 70 | SerialData * SerialDataAvailable (void) 71 | { 72 | if (serialPacketReady != 0) 73 | { 74 | serialPacketReady = 0; 75 | return &ser; 76 | } 77 | else 78 | { 79 | return 0; 80 | } 81 | } 82 | 83 | void Transmit(byte data) 84 | { 85 | //if (RS485_IS_INPUT()) 86 | //{ 87 | // Disable Receiver 88 | // UCSR0B &= ~(1<receive_address == ADDRESS) 111 | { 112 | serialPacketReady = 1; 113 | } 114 | } 115 | 116 | void ReceiveDataError (byte errCode) 117 | { 118 | } 119 | 120 | void USART_Transmit( unsigned char data ) 121 | { 122 | // Wait for empty transmit buffer 123 | while((USARTC0.STATUS & USART_DREIF_bm) == 0) {} 124 | 125 | USARTC0.DATA = data; 126 | 127 | /* Enable DRE interrupt if not already enabled. */ 128 | uint8_t tempCTRLA = USARTC0.CTRLA; 129 | if (!(tempCTRLA & USART_TXCINTLVL_LO_gc)) 130 | { 131 | tempCTRLA = (tempCTRLA & ~USART_DREINTLVL_gm) | USART_DREINTLVL_LO_gc; 132 | USARTC0.CTRLA = tempCTRLA; 133 | } 134 | 135 | 136 | } 137 | 138 | // USART Receive Interrupt 139 | ISR (USARTC0_RXC_vect) 140 | { 141 | //uint8_t data = UDR0; 142 | uint8_t data = USARTC0.DATA; 143 | ProcessDataChar (&ser, data); // 6-12 uS 144 | } 145 | 146 | // USART Transmit Complete (Data Register Empty) 147 | ISR (USARTC0_DRE_vect) 148 | { 149 | // Disable the DRE interrupt 150 | //USART_DataRegEmpty( &USART_data ); 151 | //uint8_t d = USARTC0.DATA; 152 | // Send out the next byte 153 | SerialByteTransmitComplete (&ser); // 6 uS 154 | } -------------------------------------------------------------------------------- /firmware/cnc_robot/serial/Serial.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef SERIAL_H 4 | #define SERIAL_H 5 | 6 | #include 7 | #include 8 | #include "SerialProtocol.h" 9 | 10 | #define ADDRESS 0x21 11 | 12 | 13 | #ifndef F_CPU 14 | /* Don't allow compiling if F_CPU is not defined */ 15 | #error "F_CPU not defined for serial.h" 16 | #endif 17 | 18 | #define BAUD_RATE 9600 19 | #define BSEL (((F_CPU/16)/BAUD_RATE) - 1) 20 | 21 | // Public Functions // 22 | void SerialInit(void); 23 | 24 | SerialData * SerialDataAvailable (void); 25 | SerialData * SerialDataTransmitStruct (void); 26 | 27 | // Private Functions // 28 | 29 | void USART_Init(void); 30 | void TransmitPacketComplete (void); 31 | void Transmit(byte data); 32 | void ReceivePacketComplete (volatile SerialData * s); 33 | void ReceiveDataError (byte errCode); 34 | void USART_Transmit(unsigned char data); 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /firmware/cnc_robot/serial/SerialProtocol.c: -------------------------------------------------------------------------------- 1 | 2 | #include "SerialProtocol.h" 3 | 4 | 5 | /** Serial Packet Definition: 6 | // 7 | // START_BYTE start byte 8 | // address 9 | // length 10 | // data(n bytes) 11 | // Checksum ~(address + length + data) 12 | 13 | // Escape Character and Byte Stuffing: 14 | // Any control character is replaced 15 | // with an escape character followed 16 | // by it's "escaped" value. All data 17 | // in the transmission except for the 18 | // start byte can be escaped. This 19 | // means the transmission may take up 20 | // to twice as long as expected from 21 | // just transmitting escape characters. 22 | **/ 23 | 24 | 25 | /* Private helper function declarations */ 26 | void SerialStateMachineProcess(volatile SerialData *s, byte data); 27 | byte * SerialEscapeData(volatile SerialData * s, byte address, byte length); 28 | void SerialError(volatile SerialData *s, byte errCode); 29 | 30 | /** 31 | * Helper Function: Distribute error codes to 32 | * handling functions, if they exist. 33 | */ 34 | void SerialError(volatile SerialData *s, byte errCode) 35 | { 36 | if (s->ReceiveDataError!=0) 37 | { 38 | s->ReceiveDataError(errCode); 39 | } 40 | } 41 | 42 | /** 43 | * Initialize the serial data structure. 44 | * Call once before any other methods. 45 | */ 46 | void SerialDataInitialize(volatile SerialData * s) 47 | { 48 | /* Receive State Variables */ 49 | s->receive_state = PROC_STATE_AWAITING_START_BYTE; 50 | s->receive_next_char_is_escaped = false; 51 | 52 | /* Function Pointers */ 53 | s->Transmit = 0; 54 | s->TransmitPacketComplete = 0; 55 | s->ReceivePacketComplete = 0; 56 | s->ReceiveDataError = 0; 57 | 58 | /* Transmit State Variables */ 59 | s->transmit_state = PROC_STATE_TRANSMIT_COMPLETE; 60 | s->transmit_address = 0; 61 | s->transmit_length = 0; 62 | s->transmit_checksum = 0; 63 | s->transmit_data_ptr = 0; 64 | 65 | } 66 | 67 | /** Processes a character from a serial stream 68 | * and reconstructs packets. 69 | * @param data The next character in the stream 70 | */ 71 | void ProcessDataChar (volatile SerialData * s, byte data) 72 | { 73 | /* Unstuff bytes and locate start bytes here */ 74 | 75 | /* See if the data received is value to ignore 76 | * This most likely occurs in conjunction with 77 | * a frame error: start byte detected, but no 78 | * valid data afterwards. */ 79 | if (data == NULL_BYTE || data == MAX_BYTE) 80 | { 81 | SerialError(s, ERR_RECEIVED_IGNORE_BYTE); 82 | return; 83 | } 84 | 85 | 86 | /* If any start byte is found, any current data 87 | * transfer will be reset, and a new data transfer 88 | * will begin. 89 | */ 90 | if (data == START_BYTE) /* Start byte */ 91 | { 92 | if (s->receive_state != PROC_STATE_AWAITING_START_BYTE) 93 | { 94 | SerialError(s, ERR_START_BYTE_INSIDE_PACKET); 95 | } 96 | 97 | /* Reset state */ 98 | s->receive_state = PROC_STATE_AWAITING_ADDRESS; 99 | s->receive_data_count = 0; 100 | s->receive_next_char_is_escaped = false; 101 | } 102 | else 103 | { 104 | if (s->receive_state == PROC_STATE_AWAITING_START_BYTE) 105 | { 106 | SerialError(s, ERR_UNEXPECTED_START_BYTE); 107 | //printf("Unexpected Start Byte: Expected 0x%x, Got 0x%x\n", START_BYTE, data); 108 | } 109 | else 110 | { 111 | /* Otherwise, unstuff bytes and send data to the state machine */ 112 | if (data == ESCAPE_CHAR) // Escape Character 113 | { 114 | s->receive_next_char_is_escaped = true; 115 | } 116 | else 117 | { 118 | if (s->receive_next_char_is_escaped) 119 | { 120 | s->receive_next_char_is_escaped = false; 121 | switch (data) 122 | { 123 | case ESCAPE_CHAR_ESCAPED: 124 | data = ESCAPE_CHAR; 125 | break; 126 | 127 | case START_BYTE_ESCAPED: 128 | data = START_BYTE; 129 | break; 130 | 131 | case NULL_BYTE_ESCAPED: 132 | data = NULL_BYTE; 133 | break; 134 | 135 | case MAX_BYTE_ESCAPED: 136 | data = MAX_BYTE; 137 | break; 138 | } 139 | } 140 | SerialStateMachineProcess(s, data); 141 | } 142 | } 143 | } 144 | } 145 | 146 | void SerialStateMachineProcess(volatile SerialData *s, byte data) 147 | { 148 | switch (s->receive_state) 149 | { 150 | case PROC_STATE_AWAITING_ADDRESS: 151 | s->receive_address = data; 152 | s->receive_checksum = data; 153 | s->receive_state = PROC_STATE_AWAITING_LENGTH; 154 | break; 155 | 156 | case PROC_STATE_AWAITING_LENGTH: 157 | if (data > SERIAL_RECEIVE_BUFFER_SIZE) 158 | { 159 | /* Error, length too long. Ignore packet. */ 160 | s->receive_state = PROC_STATE_AWAITING_START_BYTE; 161 | 162 | /* Look for the next start byte. Note: this 163 | * will likey produce unexpected start byte errors. 164 | */ 165 | SerialError(s, ERR_EXCESSIVE_PACKET_LENGTH); 166 | } 167 | else 168 | { 169 | s->receive_length = data; 170 | s->receive_checksum += data; 171 | s->receive_state = PROC_STATE_AWAITING_DATA; 172 | } 173 | break; 174 | 175 | case PROC_STATE_AWAITING_DATA: 176 | 177 | s->receive_length--; 178 | 179 | s->receive_checksum += data; 180 | s->receive_data[s->receive_data_count] = data; 181 | s->receive_data_count++; 182 | 183 | if (s->receive_length == 0) 184 | { 185 | s->receive_state = PROC_STATE_AWAITING_CHECKSUM; 186 | } 187 | 188 | break; 189 | 190 | case PROC_STATE_AWAITING_CHECKSUM: 191 | s->receive_checksum = ~s->receive_checksum; 192 | if (data == s->receive_checksum) 193 | { 194 | if (s->ReceivePacketComplete != 0) 195 | { 196 | s->ReceivePacketComplete (s); 197 | } 198 | } 199 | else 200 | { 201 | SerialError(s, ERR_CHECKSUM_MISMATCH); 202 | //printf("Error: Checksum Mismatch. Expected 0x%x, Got 0x%x\n", s->receive_checksum, data); 203 | } 204 | s->receive_state = PROC_STATE_AWAITING_START_BYTE; 205 | break; 206 | 207 | default: 208 | // (It'll never get here) 209 | break; 210 | } 211 | } 212 | 213 | 214 | 215 | /** Call this method on USART data 216 | * transmit complete. 217 | */ 218 | void SerialByteTransmitComplete(volatile SerialData * s) 219 | { 220 | byte dataToTx = 0; 221 | 222 | // Check if we need to transmit an escaped character: 223 | if (s->transmit_escaped_char != 0) 224 | { 225 | dataToTx = s->transmit_escaped_char; 226 | s->transmit_escaped_char = 0; 227 | 228 | } 229 | else 230 | { 231 | switch (s->transmit_state) 232 | { 233 | case PROC_STATE_TRANSMIT_ADDRESS: 234 | dataToTx = s->transmit_address; 235 | s->transmit_checksum = dataToTx; 236 | s->transmit_state = PROC_STATE_TRANSMIT_LENGTH; 237 | break; 238 | 239 | case PROC_STATE_TRANSMIT_LENGTH: 240 | dataToTx = s->transmit_length; 241 | s->transmit_checksum += dataToTx; 242 | s->transmit_state = PROC_STATE_TRANSMIT_DATA; 243 | break; 244 | 245 | case PROC_STATE_TRANSMIT_DATA: 246 | dataToTx = *(s->transmit_data_ptr); 247 | s->transmit_checksum += dataToTx; 248 | s->transmit_data_ptr++; 249 | s->transmit_length--; 250 | if (s->transmit_length == 0) 251 | { 252 | s->transmit_state = PROC_STATE_TRANSMIT_CHECKSUM; 253 | } 254 | break; 255 | 256 | case PROC_STATE_TRANSMIT_CHECKSUM: 257 | dataToTx = ~s->transmit_checksum; 258 | s->transmit_state = PROC_STATE_TRANSMIT_ALMOST_COMPLETE; 259 | break; 260 | 261 | case PROC_STATE_TRANSMIT_ALMOST_COMPLETE: 262 | // Done transmitting! 263 | s->transmit_state = PROC_STATE_TRANSMIT_COMPLETE; 264 | if (s->TransmitPacketComplete!=0) 265 | { 266 | s->TransmitPacketComplete(); 267 | } 268 | return; 269 | break; 270 | 271 | default: 272 | // Shouldn't ever get here. 273 | break; 274 | } 275 | 276 | // Check for control characters 277 | switch(dataToTx) 278 | { 279 | case START_BYTE: 280 | s->transmit_escaped_char = START_BYTE_ESCAPED; 281 | dataToTx = ESCAPE_CHAR; 282 | break; 283 | 284 | case ESCAPE_CHAR: 285 | s->transmit_escaped_char = ESCAPE_CHAR_ESCAPED; 286 | dataToTx = ESCAPE_CHAR; 287 | break; 288 | 289 | case NULL_BYTE: 290 | s->transmit_escaped_char = NULL_BYTE_ESCAPED; 291 | dataToTx = ESCAPE_CHAR; 292 | break; 293 | 294 | case MAX_BYTE: 295 | s->transmit_escaped_char = MAX_BYTE_ESCAPED; 296 | dataToTx = ESCAPE_CHAR; 297 | break; 298 | 299 | default: 300 | s->transmit_escaped_char = 0; 301 | break; 302 | } 303 | } 304 | 305 | // Transmit the data! 306 | if (s->Transmit!=0) 307 | { 308 | s->Transmit(dataToTx); 309 | } 310 | 311 | } 312 | 313 | /** Serial Packet Transfer Query Function 314 | * @return true if a packet transfer is currently 315 | * in progress, false otherwise. 316 | */ 317 | char SerialTransferInProgress(volatile SerialData * s) 318 | { 319 | return (s->transmit_state != PROC_STATE_TRANSMIT_COMPLETE); 320 | } 321 | 322 | /** 323 | * Transmit serial data 324 | * @param address The address to send the data to 325 | * @param length Number of bytes in data to be sent 326 | * @param maxLength Number of bytes allocated for 327 | * the data array. 328 | * @return 0 for success, nonzero for failure. 329 | */ 330 | char SerialTransmit(volatile SerialData * s, byte address, byte length) 331 | { 332 | if (SerialTransferInProgress(s)) 333 | { 334 | return -1; 335 | } 336 | 337 | if (s->Transmit == 0) 338 | { 339 | return -2; 340 | } 341 | 342 | if (length > SERIAL_TRANSMIT_BUFFER_SIZE) 343 | { 344 | return -3; 345 | } 346 | 347 | s->transmit_address = address; 348 | s->transmit_length = length; 349 | s->transmit_data_ptr = (byte *)s->transmit_data; 350 | s->transmit_escaped_char = 0; 351 | s->transmit_state = PROC_STATE_TRANSMIT_ADDRESS; 352 | 353 | s->Transmit(START_BYTE); 354 | 355 | return 0; 356 | } 357 | -------------------------------------------------------------------------------- /firmware/cnc_robot/serial/SerialProtocol.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _SERIAL_PROTOCOL_H 3 | #define _SERIAL_PROTOCOL_H 4 | 5 | //#include 6 | #include 7 | 8 | 9 | /* Control Characters and their Escaped Equivalents */ 10 | #define START_BYTE 0xCA 11 | #define ESCAPE_CHAR '\\' 12 | #define NULL_BYTE 0 13 | #define MAX_BYTE 255 14 | #define START_BYTE_ESCAPED 2 15 | #define ESCAPE_CHAR_ESCAPED 3 16 | #define NULL_BYTE_ESCAPED 4 17 | #define MAX_BYTE_ESCAPED 5 18 | 19 | /* Receive State Machine States */ 20 | #define PROC_STATE_AWAITING_START_BYTE 0 21 | #define PROC_STATE_AWAITING_ADDRESS 1 22 | #define PROC_STATE_AWAITING_LENGTH 2 23 | #define PROC_STATE_AWAITING_DATA 3 24 | #define PROC_STATE_AWAITING_CHECKSUM 4 25 | 26 | /* Transmit State Machine States */ 27 | #define PROC_STATE_TRANSMIT_ADDRESS 15 28 | #define PROC_STATE_TRANSMIT_LENGTH 16 29 | #define PROC_STATE_TRANSMIT_DATA 17 30 | #define PROC_STATE_TRANSMIT_CHECKSUM 18 31 | #define PROC_STATE_TRANSMIT_ALMOST_COMPLETE 19 32 | #define PROC_STATE_TRANSMIT_COMPLETE 20 33 | 34 | /* Error Codes */ 35 | #define ERR_START_BYTE_INSIDE_PACKET 1 36 | #define ERR_UNEXPECTED_START_BYTE 2 37 | #define ERR_UNKNOWN_ESCAPED_CHARACTER 3 38 | #define ERR_EXCESSIVE_PACKET_LENGTH 4 39 | #define ERR_CHECKSUM_MISMATCH 5 40 | #define ERR_BUFFER_INSUFFICIENT 6 41 | #define ERR_RECEIVED_IGNORE_BYTE 7 42 | 43 | /* Buffer Sizes */ 44 | #define SERIAL_RECEIVE_BUFFER_SIZE 50 45 | #define SERIAL_TRANSMIT_BUFFER_SIZE 50 46 | 47 | #ifndef byte 48 | typedef unsigned char byte; 49 | #endif 50 | 51 | typedef struct SSerialData SerialData; 52 | 53 | struct SSerialData 54 | { 55 | /* Receiving Variables */ 56 | byte receive_data [SERIAL_RECEIVE_BUFFER_SIZE]; 57 | byte receive_data_count; /* Number of bytes received so far */ 58 | byte receive_length; /* Expected number of bytes to receive */ 59 | byte receive_next_char_is_escaped; /* need to unstuff next char? */ 60 | byte receive_address; /* address of the received packet */ 61 | byte receive_checksum; /* Checksum of the received packet */ 62 | byte receive_state; /* Serial receive state variable */ 63 | 64 | /* Transmission Variables */ 65 | byte transmit_data [SERIAL_TRANSMIT_BUFFER_SIZE]; 66 | byte transmit_state; 67 | byte transmit_address; 68 | byte transmit_length; 69 | byte transmit_checksum; 70 | byte transmit_escaped_char; 71 | byte * transmit_data_ptr; 72 | 73 | /* Function Pointers */ 74 | void (*Transmit)(byte data); 75 | void (*TransmitPacketComplete)(void); 76 | void (*ReceivePacketComplete)(volatile SerialData * s); 77 | void (*ReceiveDataError)(byte errCode); 78 | }; 79 | 80 | /* Returns true if a transfer is in progress, 81 | * false otherwise */ 82 | char SerialTransferInProgress (volatile SerialData * s); 83 | 84 | /* Call this method when a byte transmit is complete */ 85 | void SerialByteTransmitComplete(volatile SerialData * s); 86 | 87 | /* Call this when creating a new data structure */ 88 | void SerialDataInitialize(volatile SerialData * s); 89 | 90 | /* Call to begin transmission of whatever is in the transmit buffer */ 91 | char SerialTransmit(volatile SerialData * s, byte address, byte length); 92 | 93 | /* Pass whatever comes in on the serial interface to this function */ 94 | void ProcessDataChar(volatile SerialData * s, byte data); 95 | 96 | 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /software/CNC_Machine.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2012 for Windows Desktop 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Router", "GCode\Router.csproj", "{6A2ED2BC-1FEA-46E3-8403-3C484A7BCCA5}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robot", "Robot\Robot.csproj", "{C7BBABF0-0698-4C5F-A510-7E160C8771A5}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serial", "Serial\Serial.csproj", "{9477FD2C-FE8F-4653-AB25-BFA14338A932}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utilities", "Utilities\Utilities.csproj", "{3C91D012-845B-411D-83F7-C16C4C71D97B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUI", "GUI\GUI.csproj", "{7BA42A6E-9E73-43E4-9461-B98C8D50AED1}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "clipper_library", "Clipper\clipper_library.csproj", "{9B062971-A88E-4A3D-B3C9-12B78D15FA66}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {6A2ED2BC-1FEA-46E3-8403-3C484A7BCCA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {6A2ED2BC-1FEA-46E3-8403-3C484A7BCCA5}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {6A2ED2BC-1FEA-46E3-8403-3C484A7BCCA5}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {6A2ED2BC-1FEA-46E3-8403-3C484A7BCCA5}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {C7BBABF0-0698-4C5F-A510-7E160C8771A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {C7BBABF0-0698-4C5F-A510-7E160C8771A5}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {C7BBABF0-0698-4C5F-A510-7E160C8771A5}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {C7BBABF0-0698-4C5F-A510-7E160C8771A5}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {9477FD2C-FE8F-4653-AB25-BFA14338A932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {9477FD2C-FE8F-4653-AB25-BFA14338A932}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {9477FD2C-FE8F-4653-AB25-BFA14338A932}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {9477FD2C-FE8F-4653-AB25-BFA14338A932}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {3C91D012-845B-411D-83F7-C16C4C71D97B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {3C91D012-845B-411D-83F7-C16C4C71D97B}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {3C91D012-845B-411D-83F7-C16C4C71D97B}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {3C91D012-845B-411D-83F7-C16C4C71D97B}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {7BA42A6E-9E73-43E4-9461-B98C8D50AED1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {7BA42A6E-9E73-43E4-9461-B98C8D50AED1}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {7BA42A6E-9E73-43E4-9461-B98C8D50AED1}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {7BA42A6E-9E73-43E4-9461-B98C8D50AED1}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {9B062971-A88E-4A3D-B3C9-12B78D15FA66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {9B062971-A88E-4A3D-B3C9-12B78D15FA66}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {9B062971-A88E-4A3D-B3C9-12B78D15FA66}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {9B062971-A88E-4A3D-B3C9-12B78D15FA66}.Release|Any CPU.Build.0 = Release|Any CPU 46 | EndGlobalSection 47 | GlobalSection(SolutionProperties) = preSolution 48 | HideSolutionNode = FALSE 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /software/CNC_Machine.v11.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xenovacivus/cnc_machine/9452474f29858127e500ce7bf9f20a763117aebb/software/CNC_Machine.v11.suo -------------------------------------------------------------------------------- /software/Clipper/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("clipper_library")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("clipper_library")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("51a6bdca-bc4e-4b2c-ae69-36e2497204f2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /software/Clipper/clipper_library.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {9B062971-A88E-4A3D-B3C9-12B78D15FA66} 9 | Library 10 | Properties 11 | ClipperLib 12 | clipper_library 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 54 | -------------------------------------------------------------------------------- /software/GCode/CircleRout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using OpenTK; 6 | using System.Drawing; 7 | using System.Windows.Forms; 8 | using Utilities; 9 | 10 | namespace Router 11 | { 12 | public class CircleRout : Rout 13 | { 14 | protected Vector2 center = new Vector2 (0, 0); 15 | protected float radius = 50; 16 | protected int pointCount; 17 | 18 | public override float Width 19 | { 20 | get 21 | { 22 | return base.Width; 23 | } 24 | set 25 | { 26 | base.Width = value; 27 | this.ComputePoints(); 28 | } 29 | } 30 | 31 | public float Radius 32 | { 33 | get 34 | { 35 | return radius; 36 | } 37 | set 38 | { 39 | radius = value; 40 | if (radius < 1) 41 | { 42 | radius = 1; 43 | } 44 | this.ComputePoints(); 45 | } 46 | } 47 | 48 | public float X 49 | { 50 | get 51 | { 52 | return center.X; 53 | } 54 | set 55 | { 56 | center.X = value; 57 | this.ComputePoints(); 58 | } 59 | } 60 | 61 | public float Y 62 | { 63 | get 64 | { 65 | return center.Y; 66 | } 67 | set 68 | { 69 | center.Y = value; 70 | this.ComputePoints(); 71 | } 72 | } 73 | 74 | public int PointCount 75 | { 76 | set 77 | { 78 | this.pointCount = value; 79 | this.ComputePoints(); 80 | } 81 | get 82 | { 83 | return this.pointCount; 84 | } 85 | } 86 | 87 | public CircleRout() 88 | { 89 | ComputePoints(); 90 | } 91 | 92 | public CircleRout(Vector2 center, float radius) 93 | { 94 | this.center = center; 95 | this.radius = radius; 96 | ComputePoints(); 97 | } 98 | 99 | public override void Draw() 100 | { 101 | for (int i = 0; i < (Points.Count - 1); i++) 102 | { 103 | Color c = Color.OrangeRed; 104 | CoolDrawing.DrawLine(width, new Vector2(Points[i].X, Points[i].Y), new Vector2(Points[i + 1].X, Points[i + 1].Y), c); 105 | CoolDrawing.DrawFilledCircle(width / 2, new Vector2(Points[i].X, Points[i].Y), c); 106 | } 107 | 108 | CoolDrawing.DrawFilledCircle(width / 2, center, Color.LightGreen); 109 | CoolDrawing.DrawCircle(width / 2, center, Color.Black); 110 | } 111 | 112 | public override float DistanceTo(Vector2 p) 113 | { 114 | float d = base.DistanceTo(p); 115 | Vector2 v = new Vector2(p.X, p.Y); 116 | float length = (center - v).Length; 117 | if (length < width / 2 && length < d) 118 | { 119 | d = length; 120 | base.closestIsPoint = false; 121 | } 122 | else 123 | { 124 | base.closestIsPoint = true; 125 | } 126 | return d; 127 | } 128 | 129 | private void ComputePoints() 130 | { 131 | this.Points = new List(); 132 | 133 | float circumference = (float)Math.PI * 2 * radius; 134 | 135 | 136 | 137 | 138 | int _pointCount = pointCount; 139 | if (_pointCount <= 1) 140 | { 141 | pointCount = (int)(0.5f * circumference / width); 142 | if (_pointCount <= 12) 143 | { 144 | _pointCount = 12; 145 | } 146 | } 147 | 148 | 149 | for (int i = 0; i <= _pointCount; i++) 150 | { 151 | Vector2 p = new Vector2((float)Math.Cos(Math.PI * 2 * i / _pointCount) * radius, (float)Math.Sin(Math.PI * 2 * i / _pointCount) * radius); 152 | p += center; 153 | Points.Add(new Vector2(p.X, p.Y)); 154 | } 155 | 156 | base.HasChanged = true; 157 | } 158 | 159 | public override void MouseDrag(Vector2 point) 160 | { 161 | if (isMouseLDown) 162 | { 163 | Vector2 v = new Vector2((int)((point.X) / gridScale + .5) * gridScale, 164 | (int)((point.Y) / gridScale + .5) * gridScale); 165 | Vector2 delta = v - mouseClickPoint; 166 | 167 | 168 | if (closestIsPoint) 169 | { 170 | radius = (center - point).Length; 171 | radius = gridScale * ((int)(radius / gridScale + .5)); 172 | ComputePoints(); 173 | } 174 | else 175 | { 176 | center = v; 177 | ComputePoints(); 178 | } 179 | 180 | base.mouseClickPoint = v; 181 | } 182 | } 183 | 184 | public override void MouseUp(OpenTK.Vector2 location, Control parent, System.Drawing.Point mousePoint) 185 | { 186 | if (isMouseRDown && null != parent) 187 | { 188 | ContextMenu c = new ContextMenu(); 189 | c.MenuItems.Add(new MenuItem("Delete Circle", new EventHandler(DeleteRout))); 190 | c.Show(parent, mousePoint); 191 | } 192 | isMouseRDown = false; 193 | isMouseLDown = false; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /software/GCode/GCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Drawing; 7 | using OpenTK; 8 | 9 | namespace Router 10 | { 11 | public class GCode 12 | { 13 | public GCode () 14 | { 15 | lastx = 0; 16 | lasty = 0; 17 | lastz = 0; 18 | linear_routs = new List(); 19 | } 20 | 21 | List linear_routs; 22 | public Rout[] GetRouts() 23 | { 24 | Console.WriteLine("Returning " + linear_routs.Count() + " Linear Routs"); 25 | return linear_routs.ToArray(); 26 | } 27 | 28 | float lastx, lasty, lastz; 29 | public void Parse(string[] lines) 30 | { 31 | foreach (string s in lines) 32 | { 33 | Regex r = new Regex("^G(?\\d+)"); 34 | if (r.IsMatch (s)) 35 | { 36 | Match m = r.Match(s); 37 | Int32 g_value = Int32.Parse (m.Groups["G_VALUE"].Value); 38 | 39 | if (g_value == 0) 40 | { 41 | // Rapid Positioning, go to (x, y, z) as fast as possible 42 | Vector3 fromPoint = new Vector3(lastx, lasty, lastz); 43 | GetFloat(s, "X", ref lastx); 44 | GetFloat(s, "Y", ref lasty); 45 | GetFloat(s, "Z", ref lastz); 46 | Vector3 toPoint = new Vector3(lastx, lasty, lastz); 47 | 48 | Rout rout = new Rout(); 49 | rout.just_moving = true; 50 | rout.Width = 5; 51 | rout.Points = new List(new Vector2[] { new Vector2(fromPoint.X * 1000, fromPoint.Y * 1000), new Vector2(toPoint.X * 1000, toPoint.Y * 1000) }); 52 | rout.Depth = toPoint.Z * 1000; 53 | linear_routs.Add(rout); 54 | 55 | } 56 | else if (g_value == 1) 57 | { 58 | // Linear Interpolation 59 | Vector3 fromPoint = new Vector3(lastx, lasty, lastz); 60 | GetFloat(s, "X", ref lastx); 61 | GetFloat(s, "Y", ref lasty); 62 | GetFloat(s, "Z", ref lastz); 63 | Vector3 toPoint = new Vector3(lastx, lasty, lastz); 64 | 65 | Rout rout = new Rout(); 66 | 67 | rout.Width = 20; 68 | rout.Points = new List(new Vector2[] { new Vector2(fromPoint.X * 1000, fromPoint.Y * 1000), new Vector2(toPoint.X * 1000, toPoint.Y * 1000) }); 69 | rout.Depth = toPoint.Z * 1000; 70 | linear_routs.Add(rout); 71 | 72 | //Console.WriteLine("From " + fromPoint + " To " + toPoint); 73 | } 74 | else if (g_value == 4) 75 | { 76 | // Dwell Time (X, U, or P): dwell time in milliseconds 77 | } 78 | else if (g_value == 20) 79 | { 80 | // Inch Mode 81 | Console.WriteLine("Units are Inches"); 82 | } 83 | else if (g_value == 21) 84 | { 85 | // Metric Mode 86 | throw new NotSupportedException("Metric GCode is not supported!"); 87 | } 88 | else if (g_value == 90) 89 | { 90 | // Absolute Programming 91 | Console.WriteLine("Absolute Programming"); 92 | } 93 | else 94 | { 95 | Console.WriteLine("G code is not understood: " + s); 96 | } 97 | //string groupName = r.GroupNumberFromName("G_VALUE").ToString(); 98 | //MatchCollection m = r.Matches; 99 | //Console.WriteLine(s + ", Group Name = " + groupName); 100 | } 101 | } 102 | } 103 | 104 | /// 105 | /// Get a float in the format of "G01 Z-0.0100 F2.00", where string is Z, F, or other preceding character 106 | /// 107 | /// 108 | /// 109 | /// 110 | public bool GetFloat(string input, string find, ref float f) 111 | { 112 | Regex r = new Regex(find + @"(?-?[\d\.]+)"); 113 | if (r.IsMatch(input)) 114 | { 115 | Match m = r.Match(input); 116 | string value_string = m.Groups["VALUE"].Value; 117 | 118 | f = float.Parse(value_string); 119 | //Console.WriteLine("Value for " + find + " is " + f); 120 | return true; 121 | } 122 | return false; 123 | } 124 | 125 | 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /software/GCode/IClickable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using OpenTK; 6 | using System.Windows.Forms; 7 | using System.Drawing; 8 | 9 | namespace Router 10 | { 11 | public interface IClickable 12 | { 13 | void MouseDownLeft(Vector2 location); 14 | void MouseDownRight(Vector2 location); 15 | void MouseDrag(Vector2 point); 16 | void MouseUp(Vector2 location, Control parent, Point mouseLocation); 17 | //void MouseUp(Vector2 location, Point mouseLocation); 18 | 19 | float IsPointOnObject(Vector2 location); 20 | 21 | //void Hover(Vector2 location); 22 | 23 | //void UnHover(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /software/GCode/IClickable3D.cs: -------------------------------------------------------------------------------- 1 | using OpenTK; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Router 9 | { 10 | public interface IClickable3D 11 | { 12 | //void MouseDownLeft(Vector3 location); 13 | //void MouseDownRight(Vector3 location); 14 | //void MouseDrag(Vector3 point); 15 | //void MouseUp(Vector2 location, Control parent, Point mouseLocation); 16 | //void MouseUp(Vector2 location, Point mouseLocation); 17 | 18 | float IsPointOnObject(Vector3 location, Vector3 direction); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /software/GCode/IHasRouts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Router 7 | { 8 | public interface IHasRouts 9 | { 10 | List GetRouts(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /software/GCode/IIsUseful.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Router 7 | { 8 | public interface IIsUseful 9 | { 10 | bool IsUseful(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /software/GCode/MoveTool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK; 7 | using Robot; 8 | 9 | namespace Router 10 | { 11 | public class MoveTool : RouterCommand 12 | { 13 | private Vector3 toPoint; 14 | private float tool_speed; 15 | 16 | public Vector3 Location 17 | { 18 | get 19 | { 20 | return toPoint; 21 | } 22 | } 23 | 24 | public override Vector3 FinalPosition() 25 | { 26 | return toPoint; 27 | } 28 | 29 | public MoveTool(Vector3 toPoint, float tool_speed) 30 | { 31 | // TODO: Complete member initialization 32 | this.toPoint = toPoint; 33 | this.tool_speed = tool_speed; 34 | } 35 | public override void Execute(IHardware d) 36 | { 37 | Console.WriteLine("Going to " + toPoint); 38 | Vector3 p = new Vector3(toPoint.X, toPoint.Y, toPoint.Z); 39 | d.GoTo(p, tool_speed); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /software/GCode/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GCode")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GCode")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c60b66e6-786f-45a3-b107-3b8d8d9029da")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /software/GCode/Rout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using OpenTK; 6 | using OpenTK.Graphics.OpenGL; 7 | using System.Windows.Forms; 8 | using System.Drawing; 9 | using Utilities; 10 | 11 | namespace Router 12 | { 13 | public class Rout : IHasRouts, IClickable, IOpenGLDrawable, IIsUseful 14 | { 15 | protected List points; 16 | protected float width = 25; 17 | protected float depth = -5; 18 | 19 | public List Points 20 | { 21 | get 22 | { 23 | return points; 24 | } 25 | set 26 | { 27 | points = value; 28 | } 29 | } 30 | public float Depth 31 | { 32 | get 33 | { 34 | return depth; 35 | } 36 | set 37 | { 38 | depth = value; 39 | HasChanged = true; 40 | } 41 | } 42 | public virtual float Width 43 | { 44 | get 45 | { 46 | return width; 47 | } 48 | set 49 | { 50 | width = value; 51 | if (width < 1f) 52 | { 53 | width = 1f; 54 | } 55 | HasChanged = true; 56 | } 57 | } 58 | 59 | protected bool isMouseRDown = false; 60 | protected bool isMouseLDown = false; 61 | 62 | protected int closestPoint = -1; 63 | protected bool closestIsPoint = false; 64 | public bool just_moving = false; 65 | 66 | protected float gridScale = 5; 67 | protected Vector2 mouseClickPoint; 68 | 69 | 70 | protected bool is_display_list_good = false; 71 | protected int displayList = -1; 72 | 73 | private bool bounding_box_is_good = false; 74 | Box2 boundingBox = new Box2(); 75 | 76 | public Rout() 77 | { 78 | Points = new List(); 79 | } 80 | 81 | protected bool HasChanged 82 | { 83 | set 84 | { 85 | bounding_box_is_good = false; 86 | is_display_list_good = false; 87 | } 88 | } 89 | 90 | #region IDrawable Interface 91 | 92 | public virtual void Draw() 93 | { 94 | if (is_display_list_good) 95 | { 96 | GL.CallList(displayList); 97 | } 98 | else 99 | { 100 | if (displayList < 0) 101 | { 102 | displayList = GL.GenLists(1); 103 | } 104 | 105 | GL.NewList(displayList, ListMode.CompileAndExecute); 106 | List lines = new List(); 107 | if (Points.Count >= 2) 108 | { 109 | 110 | for (int i = 0; i < (Points.Count - 1); i++) 111 | { 112 | lines.Add(new CoolDrawing.Line (new Vector2(Points[i].X, Points[i].Y), new Vector2(Points[i + 1].X, Points[i + 1].Y))); 113 | 114 | } 115 | CoolDrawing.DrawDepthLine(width, lines.ToArray(), this.Depth); 116 | } 117 | for (int i = 0; i < Points.Count; i++) 118 | { 119 | Vector2 p = Points[i]; 120 | 121 | 122 | if (closestIsPoint && (i == closestPoint) && isMouseLDown) 123 | { 124 | CoolDrawing.DrawFilledCircle(width / 2, new Vector2(p.X, p.Y), Color.FromArgb(100, Color.Purple)); 125 | } 126 | else 127 | { 128 | //CoolDrawing.DrawFilledCircle(width / 2, new Vector2(p.X, p.Y), Color.White); 129 | } 130 | CoolDrawing.DrawCircle(width / 2, new Vector2(p.X, p.Y), Color.Black); 131 | } 132 | GL.EndList(); 133 | is_display_list_good = true; 134 | } 135 | } 136 | 137 | #endregion 138 | 139 | 140 | 141 | private Box2 BoundingBox() 142 | { 143 | if (!bounding_box_is_good) 144 | { 145 | boundingBox = new Box2(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity, float.PositiveInfinity); 146 | foreach (Vector2 p in Points) 147 | { 148 | if (p.X > boundingBox.Right) 149 | { 150 | boundingBox.Right = p.X; 151 | } 152 | if (p.X < boundingBox.Left) 153 | { 154 | boundingBox.Left = p.X; 155 | } 156 | if (p.Y > boundingBox.Top) 157 | { 158 | boundingBox.Top = p.Y; 159 | } 160 | if (p.Y < boundingBox.Bottom) 161 | { 162 | boundingBox.Bottom = p.Y; 163 | } 164 | } 165 | boundingBox.Bottom -= width / 2; 166 | boundingBox.Top += width / 2; 167 | boundingBox.Left -= width / 2; 168 | boundingBox.Right += width / 2; 169 | bounding_box_is_good = true; 170 | } 171 | return boundingBox; 172 | } 173 | 174 | 175 | /// 176 | /// Returns the distance to the closest line on the rout 177 | /// 178 | /// 179 | public virtual float DistanceTo(Vector2 p) 180 | { 181 | 182 | Box2 b = BoundingBox(); 183 | if ((p.X > b.Right || p.X < b.Left) && (p.Y > b.Top || p.Y < b.Bottom)) 184 | { 185 | return float.PositiveInfinity; 186 | } 187 | 188 | float closest = float.PositiveInfinity; 189 | for (int i = 0; i < Points.Count; i++) 190 | { 191 | float l = LineMath.Length(Points[i], p); 192 | if (closest > l) 193 | { 194 | closest = l; 195 | closestPoint = i; 196 | } 197 | } 198 | if (closest < width/2) 199 | { 200 | closestIsPoint = true; 201 | return closest; 202 | } 203 | closestIsPoint = false; 204 | 205 | closest = float.PositiveInfinity; 206 | for (int i = 0; i < (Points.Count - 1); i++) 207 | { 208 | float newValue = LineMath.DistanceTo(Points[i], Points[i + 1], p); 209 | if (newValue < closest) 210 | { 211 | closest = newValue; 212 | closestPoint = i; 213 | } 214 | } 215 | return closest; 216 | } 217 | 218 | internal Rout Delete() 219 | { 220 | if (closestIsPoint && closestPoint >= 0 && closestPoint < Points.Count) 221 | { 222 | Points.RemoveAt(closestPoint); 223 | } 224 | else if (closestPoint >=0 && closestPoint < (Points.Count-1)) 225 | { 226 | Rout r = new Rout(); 227 | for (int i = closestPoint + 1; i < Points.Count; i++) 228 | { 229 | r.Points.Add(Points[i]); 230 | } 231 | Points.RemoveRange(closestPoint + 1, r.Points.Count) ; 232 | if (r.Points.Count > 1) 233 | return r; 234 | } 235 | HasChanged = true; 236 | return null; 237 | } 238 | 239 | public bool IsUseful() 240 | { 241 | return Points.Count >= 2; 242 | } 243 | 244 | public void MouseDownLeft(Vector2 location) 245 | { 246 | mouseClickPoint = location; 247 | 248 | // Update what's selected, only consider it clicked if there's something to click on 249 | isMouseLDown = (IsPointOnObject(mouseClickPoint) < width / 2); 250 | } 251 | 252 | public void MouseDownRight(Vector2 location) 253 | { 254 | mouseClickPoint = location; 255 | isMouseRDown = (IsPointOnObject(mouseClickPoint) < width / 2); 256 | } 257 | 258 | public virtual void MouseDrag(Vector2 point) 259 | { 260 | Vector2 v = new Vector2((int)((point.X) / gridScale + .5) * gridScale, 261 | (int)((point.Y) / gridScale + .5) * gridScale); 262 | 263 | mouseClickPoint = v; 264 | 265 | if (isMouseLDown) 266 | { 267 | if (closestIsPoint) 268 | { 269 | Points[closestPoint] = new Vector2(v.X, v.Y); //(points[closestPoint].X + rounded.X, points[closestPoint].Y + rounded.Y); 270 | } 271 | else 272 | { 273 | this.Points.Insert(closestPoint + 1, new Vector2(v.X, v.Y)); //mouseClickPoint.X, mouseClickPoint.Y)); 274 | this.closestIsPoint = true; 275 | this.closestPoint++; 276 | } 277 | HasChanged = true; 278 | } 279 | } 280 | 281 | 282 | public virtual void MouseUp(Vector2 location, Control parent, System.Drawing.Point mousePoint) 283 | { 284 | if (isMouseRDown) 285 | { 286 | ContextMenu c = new ContextMenu(); 287 | c.MenuItems.Add(new MenuItem("Delete Rout", new EventHandler(DeleteRout))); 288 | c.Show(parent, mousePoint); 289 | } 290 | isMouseRDown = false; 291 | isMouseLDown = false; 292 | HasChanged = true; 293 | } 294 | 295 | protected void DeleteRout (object sender, EventArgs e) 296 | { 297 | Points = new List(); // Remove all points... any list containing this item should check if there are no points, and remove if necessary. 298 | Console.WriteLine("Delete Rout Clicked!"); 299 | HasChanged = true; 300 | } 301 | 302 | public float IsPointOnObject(Vector2 location) 303 | { 304 | Vector2 p = new Vector2(location.X, location.Y); 305 | float distance = DistanceTo(p); 306 | if (distance < width / 2) 307 | { 308 | return distance; 309 | } 310 | return float.PositiveInfinity; 311 | } 312 | 313 | public List GetRouts() 314 | { 315 | return new List { this }; 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /software/GCode/Router.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | using OpenTK; 8 | using OpenTK.Graphics.OpenGL; 9 | using System.ComponentModel; 10 | using Utilities; 11 | using Robot; 12 | 13 | namespace Router 14 | { 15 | public class Router : IOpenGLDrawable 16 | { 17 | PointF currentPosition; 18 | PointF actualPosition; 19 | IHardware device = null; 20 | private List commands; 21 | 22 | Vector3 finalPosition = new Vector3(0, 0, 0); 23 | 24 | public Router(IHardware d) 25 | { 26 | commands = new List(); 27 | device = d; 28 | d.onRobotReady += new EventHandler(this.RobotReady); 29 | d.onPositionUpdate += new EventHandler(RouterPositionUpdate); 30 | currentPosition = new PointF(0, 0); 31 | actualPosition = new PointF(0, 0); 32 | } 33 | 34 | void RouterPositionUpdate(object o, EventArgs e) 35 | { 36 | if (o is IHardware) 37 | { 38 | IHardware hw = o as IHardware; 39 | Vector3 position = hw.GetPosition(); 40 | //Console.WriteLine("Router New Position = " + position); 41 | if ((lastPosition - position).Length > float.Epsilon) 42 | { 43 | previousPoints.Add(new PreviousPoint(DateTime.Now, lastPosition)); 44 | lastPosition = position; 45 | } 46 | } 47 | } 48 | 49 | class PreviousPoint 50 | { 51 | public PreviousPoint(DateTime time, Vector3 location) 52 | { 53 | this.createTime = time; 54 | this.location = location; 55 | } 56 | public DateTime createTime; 57 | public Vector3 location; 58 | } 59 | List previousPoints = new List(); 60 | 61 | void RobotReady(object o, EventArgs e) 62 | { 63 | lock (commands) 64 | { 65 | if (commands.Count > 0) 66 | { 67 | RouterCommand c = commands[0]; 68 | Console.WriteLine("Executing Command {0}", commands.Count); 69 | commands.RemoveAt(0); 70 | c.Execute(device); 71 | } 72 | else 73 | { 74 | finalPosition = device.GetPosition(); 75 | } 76 | } 77 | } 78 | 79 | public void AddRouterCommands(RouterCommand[] router_commands) 80 | { 81 | lock (commands) 82 | { 83 | this.commands.AddRange(router_commands); 84 | Console.WriteLine("Now Has " + commands.Count + " Router Commands"); 85 | } 86 | } 87 | 88 | Vector3 lastPosition = new Vector3(0, 0, 0); 89 | public void Draw() 90 | { 91 | GL.PushMatrix(); 92 | 93 | GL.Translate(0, 0, -0.1); 94 | Vector3 p = device.GetPosition(); 95 | 96 | CoolDrawing.DrawCircle(12.5f, new OpenTK.Vector2(p.X * 1000, p.Y * 1000), Color.DarkGreen); 97 | 98 | for (int i = 0; i < commands.Count(); i++) 99 | { 100 | if (commands[i] is MoveTool) 101 | { 102 | MoveTool m = commands[i] as MoveTool; 103 | Vector3 finalPosition = m.FinalPosition(); 104 | CoolDrawing.DrawCircle(5.0f, new Vector2 (finalPosition.X * 1000, finalPosition.Y * 1000), Color.Blue); 105 | } 106 | } 107 | 108 | for (int i = 0; i 5000) 112 | { 113 | previousPoints.RemoveAt(i); 114 | i--; 115 | } 116 | else 117 | { 118 | int alpha = (int)(255 - 255 * age / 5000.0f); 119 | CoolDrawing.DrawCircle(5.0f, new Vector2(previousPoints[i].location.X * 1000, previousPoints[i].location.Y * 1000), Color.FromArgb(alpha, Color.DarkGreen)); 120 | } 121 | } 122 | 123 | float w = 0; 124 | // Assume full bit penetrates at 20 mills depth 125 | if (p.Z < 0) 126 | { 127 | w = -p.Z / .020f * 12.5f; 128 | if (w > 12.5f) 129 | { 130 | w = 12.5f; 131 | } 132 | CoolDrawing.DrawFilledCircle(w, new OpenTK.Vector2(p.X * 1000, p.Y * 1000), Color.FromArgb(100, Color.OrangeRed)); 133 | if (p.Z < -.020) 134 | { 135 | float t = (p.Z + .020f) / .040f * 12.5f; 136 | CoolDrawing.DrawFilledCircle(t, new OpenTK.Vector2(p.X * 1000, p.Y * 1000), Color.FromArgb(100, Color.DarkRed)); 137 | } 138 | } 139 | else 140 | { 141 | w = p.Z / move_height * 12.5f; 142 | CoolDrawing.DrawFilledCircle(w, new OpenTK.Vector2(p.X * 1000, p.Y * 1000), Color.FromArgb(100, Color.LightGreen)); 143 | } 144 | 145 | GL.PopMatrix(); 146 | } 147 | 148 | public void AddCommand(RouterCommand r) 149 | { 150 | lock (commands) 151 | { 152 | commands.Add(r); 153 | finalPosition = r.FinalPosition(); 154 | } 155 | } 156 | 157 | float move_height = 0.03f; // How high above the surface to move the router 158 | float move_speed = 4; // Moving speed (inches per minute) 159 | float rout_speed = 2; // Routing speed (inches per minute) 160 | float maxCutDepth = 10; // 10 mil max depth per cut 161 | 162 | [DescriptionAttribute ("Rout Speed (inches per minute")] 163 | [DisplayNameAttribute ("Routing Speed")] 164 | public float RoutSpeed 165 | { 166 | get 167 | { 168 | return rout_speed; 169 | } 170 | set 171 | { 172 | if (value > 0) 173 | { 174 | rout_speed = value; 175 | } 176 | } 177 | } 178 | 179 | [DescriptionAttribute ("Moving speed (inches per minute")] 180 | [DisplayNameAttribute ("Moving Speed")] 181 | public float MoveSpeed 182 | { 183 | get { return move_speed; } 184 | set { if (value > 0) { move_speed = value; } } 185 | } 186 | 187 | [DescriptionAttribute ("Height above zero to while moving between cuts")] 188 | [DisplayNameAttribute ("Move Height")] 189 | public float MoveHeight 190 | { 191 | get { return move_height; } 192 | set { move_height = value; } 193 | } 194 | 195 | [DescriptionAttribute ("Maximum cut depth in mills")] 196 | [DisplayNameAttribute ("Max Cut Depth")] 197 | public float MaxCutDepth 198 | { 199 | get { return maxCutDepth; } 200 | set { maxCutDepth = value; } 201 | } 202 | 203 | 204 | public void RoutPath(Rout r, bool backwards) 205 | { 206 | List mine = new List(); 207 | foreach (Vector2 p in (r.Points)) 208 | { 209 | mine.Add(new Vector2(p.X, p.Y)); 210 | } 211 | 212 | if (backwards) 213 | { 214 | mine.Reverse(); 215 | } 216 | 217 | for (int i = 0; i < mine.Count; i++) 218 | { 219 | float x = mine[i].X / 1000.0f; 220 | float y = mine[i].Y / 1000.0f; 221 | float z = r.Depth / 1000.0f; 222 | 223 | MoveTool m = new MoveTool(new Vector3(x, y, z), rout_speed); 224 | if (i == 0) 225 | { 226 | if ((finalPosition.Xy - m.Location.Xy).Length > .0001) 227 | { 228 | // Need to move the router up, over to new position, then down again. 229 | MoveTool m1 = new MoveTool(new Vector3(finalPosition.X, finalPosition.Y, move_height), move_speed); 230 | MoveTool m2 = new MoveTool(new Vector3(m.Location.X, m.Location.Y, move_height), move_speed); 231 | AddCommand(m1); 232 | AddCommand(m2); 233 | } 234 | } 235 | AddCommand(m); 236 | } 237 | } 238 | 239 | // Move to (0, 0, move_height) 240 | public void Complete() 241 | { 242 | if (finalPosition.Z < move_height) 243 | { 244 | AddCommand(new MoveTool(new Vector3(finalPosition.X, finalPosition.Y, move_height), move_speed)); 245 | } 246 | AddCommand(new MoveTool(new Vector3(0, 0, move_height), move_speed)); 247 | } 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /software/GCode/Router.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6A2ED2BC-1FEA-46E3-8403-3C484A7BCCA5} 8 | Library 9 | Properties 10 | GCode 11 | GCode 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\OpenTK\OpenTK.dll 35 | 36 | 37 | ..\OpenTK\OpenTK.GLControl.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | {c7bbabf0-0698-4c5f-a510-7e160c8771a5} 68 | Robot 69 | 70 | 71 | {3c91d012-845b-411d-83f7-c16c4c71d97b} 72 | Utilities 73 | 74 | 75 | 76 | 83 | -------------------------------------------------------------------------------- /software/GCode/RouterCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Robot; 7 | using OpenTK; 8 | 9 | namespace Router 10 | { 11 | public abstract class RouterCommand 12 | { 13 | public abstract void Execute(IHardware d); 14 | public abstract Vector3 FinalPosition(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /software/GCode/SimpleClickable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using OpenTK; 7 | using OpenTK.Graphics.OpenGL; 8 | //using Machine.Interfaces; 9 | using System.Windows.Forms; 10 | 11 | namespace Router 12 | { 13 | public class SimpleClickable : IClickable 14 | { 15 | protected bool isMouseRDown = false; 16 | protected bool isMouseLDown = false; 17 | 18 | protected int closestPoint = -1; 19 | protected bool closestIsPoint = false; 20 | public bool just_moving = false; 21 | 22 | protected float gridScale = 5; 23 | protected Vector2 mouseClickPoint; 24 | protected Vector2 mousePoint; 25 | protected Vector2 MouseDragVector 26 | { 27 | get 28 | { 29 | return roundVec(mousePoint - mouseClickPoint); 30 | } 31 | } 32 | 33 | 34 | protected Vector2 roundVec (Vector2 v) 35 | { 36 | Vector2 v2 = new Vector2((int)((v.X) / gridScale + .5) * gridScale, 37 | (int)((v.Y) / gridScale + .5) * gridScale); 38 | return v2; 39 | } 40 | 41 | public void MouseDownLeft(Vector2 location) 42 | { 43 | Console.WriteLine("MouseDownLeft" + location); 44 | mouseClickPoint = location; 45 | mousePoint = location; 46 | isMouseLDown = true; 47 | } 48 | 49 | public void MouseDownRight(Vector2 location) 50 | { 51 | mouseClickPoint = location; 52 | mousePoint = location; 53 | isMouseRDown = true; 54 | } 55 | 56 | public virtual void MouseDrag(Vector2 point) 57 | { 58 | mousePoint = point; 59 | 60 | 61 | //Vector2 v = new Vector2((int)((point.X) / gridScale + .5) * gridScale, 62 | // (int)((point.Y) / gridScale + .5) * gridScale); 63 | 64 | //mouseClickPoint = v; 65 | } 66 | 67 | 68 | public virtual void MouseUp(Vector2 location, Control parent, Point mousePoint) 69 | { 70 | isMouseRDown = false; 71 | isMouseLDown = false; 72 | mouseClickPoint = location; 73 | this.mousePoint = location; 74 | } 75 | public float IsPointOnObject(Vector2 p) 76 | { 77 | return float.PositiveInfinity; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /software/GUI/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /software/GUI/COMPortForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace RoverEmulator 2 | { 3 | partial class COMPortForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label2 = new System.Windows.Forms.Label(); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.baudBox = new System.Windows.Forms.TextBox(); 34 | this.connect = new System.Windows.Forms.Button(); 35 | this.listBox1 = new System.Windows.Forms.ListBox(); 36 | this.SuspendLayout(); 37 | // 38 | // label2 39 | // 40 | this.label2.AutoSize = true; 41 | this.label2.Location = new System.Drawing.Point(138, 9); 42 | this.label2.Name = "label2"; 43 | this.label2.Size = new System.Drawing.Size(58, 13); 44 | this.label2.TabIndex = 12; 45 | this.label2.Text = "Baud Rate"; 46 | // 47 | // label1 48 | // 49 | this.label1.AutoSize = true; 50 | this.label1.Location = new System.Drawing.Point(12, 9); 51 | this.label1.Name = "label1"; 52 | this.label1.Size = new System.Drawing.Size(26, 13); 53 | this.label1.TabIndex = 11; 54 | this.label1.Text = "Port"; 55 | this.label1.Click += new System.EventHandler(this.label1_Click); 56 | // 57 | // baudBox 58 | // 59 | this.baudBox.Location = new System.Drawing.Point(141, 25); 60 | this.baudBox.Name = "baudBox"; 61 | this.baudBox.Size = new System.Drawing.Size(121, 20); 62 | this.baudBox.TabIndex = 10; 63 | this.baudBox.Text = "9600"; 64 | // 65 | // connect 66 | // 67 | this.connect.Location = new System.Drawing.Point(141, 51); 68 | this.connect.Name = "connect"; 69 | this.connect.Size = new System.Drawing.Size(121, 23); 70 | this.connect.TabIndex = 8; 71 | this.connect.Text = "Connect"; 72 | this.connect.UseVisualStyleBackColor = true; 73 | this.connect.Click += new System.EventHandler(this.connect_Click); 74 | // 75 | // listBox1 76 | // 77 | this.listBox1.FormattingEnabled = true; 78 | this.listBox1.Location = new System.Drawing.Point(12, 25); 79 | this.listBox1.Name = "listBox1"; 80 | this.listBox1.Size = new System.Drawing.Size(120, 69); 81 | this.listBox1.TabIndex = 14; 82 | this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); 83 | // 84 | // COMPortForm 85 | // 86 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 87 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 88 | this.ClientSize = new System.Drawing.Size(292, 103); 89 | this.Controls.Add(this.listBox1); 90 | this.Controls.Add(this.label2); 91 | this.Controls.Add(this.label1); 92 | this.Controls.Add(this.baudBox); 93 | this.Controls.Add(this.connect); 94 | this.Name = "COMPortForm"; 95 | this.Text = "COMPort"; 96 | this.ResumeLayout(false); 97 | this.PerformLayout(); 98 | 99 | } 100 | 101 | #endregion 102 | 103 | private System.Windows.Forms.Label label2; 104 | private System.Windows.Forms.Label label1; 105 | private System.Windows.Forms.TextBox baudBox; 106 | private System.Windows.Forms.Button connect; 107 | private System.Windows.Forms.ListBox listBox1; 108 | } 109 | } -------------------------------------------------------------------------------- /software/GUI/COMPortForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using System.IO.Ports; 10 | using Serial; 11 | using Robot; 12 | using Router; 13 | using Utilities; 14 | 15 | namespace RoverEmulator 16 | { 17 | public partial class COMPortForm : Form 18 | { 19 | SerialPortWrapper port; 20 | Timer t; 21 | String[] portNames = new String [0]; 22 | 23 | 24 | public COMPortForm(SerialPortWrapper p) 25 | { 26 | if (p == null) 27 | { 28 | throw new NullReferenceException("Serial Port Wrapper object cannot be null"); 29 | } 30 | 31 | InitializeComponent(); 32 | port = p; 33 | 34 | t_Tick(null, EventArgs.Empty); 35 | baudBox.Text = port.BaudRate.ToString(); 36 | SelectPortName(port.PortName); 37 | if (port.IsOpen) 38 | { 39 | connect.Text = "Disconnect"; 40 | } 41 | else 42 | { 43 | if (listBox1.SelectedItem == null) 44 | { 45 | connect.Enabled = false; 46 | } 47 | } 48 | 49 | t = new Timer(); 50 | t.Interval = 100; 51 | t.Tick += new EventHandler(t_Tick); 52 | t.Start(); 53 | } 54 | 55 | void t_Tick(object sender, EventArgs e) 56 | { 57 | string [] s = port.PortNames; 58 | bool matched = true; 59 | if (s.Length != portNames.Length) 60 | { 61 | matched = false; 62 | } 63 | else 64 | { 65 | for (int i = 0; i < s.Length; i++) 66 | { 67 | matched = false; 68 | break; 69 | } 70 | } 71 | 72 | if (!matched) 73 | { 74 | object selectedObject = listBox1.SelectedItem; 75 | 76 | portNames = s; 77 | listBox1.Items.Clear(); 78 | listBox1.Items.AddRange(portNames); 79 | 80 | if (selectedObject != null) 81 | { 82 | string str = selectedObject.ToString(); 83 | SelectPortName(str); 84 | } 85 | if (listBox1.SelectedItem == null && !port.IsOpen) 86 | { 87 | connect.Enabled = false; 88 | } 89 | } 90 | } 91 | 92 | private void SelectPortName(string name) 93 | { 94 | for (int i = 0; i < listBox1.Items.Count; i++) 95 | { 96 | if (listBox1.Items[i].ToString() == name) 97 | { 98 | listBox1.SelectedIndex = i; 99 | } 100 | } 101 | } 102 | 103 | private void button2_Click(object sender, EventArgs e) 104 | { 105 | 106 | } 107 | 108 | private void label1_Click(object sender, EventArgs e) 109 | { 110 | 111 | } 112 | 113 | private void connect_Click(object sender, EventArgs e) 114 | { 115 | if (port.IsOpen) 116 | { 117 | port.Close(); 118 | connect.Text = "Connect"; 119 | } 120 | else 121 | { 122 | try 123 | { 124 | int baudRate = Convert.ToInt32(this.baudBox.Text); 125 | string portName = listBox1.SelectedItem.ToString(); 126 | port.Open(portName, baudRate); 127 | connect.Text = "Disconnect"; 128 | } 129 | catch (NullReferenceException ex) 130 | { 131 | MessageBox.Show("Error Opening Com Port: No Port Name Selected!"); 132 | } 133 | catch (FormatException ex) 134 | { 135 | MessageBox.Show("Error Opening Com Port: Invalid Baud Rate!"); 136 | } 137 | catch (Exception ex) 138 | { 139 | MessageBox.Show("Error Opening Com Port: " + ex.Message); 140 | } 141 | } 142 | } 143 | 144 | private void listBox1_SelectedIndexChanged(object sender, EventArgs e) 145 | { 146 | if (!port.IsOpen) 147 | { 148 | if (listBox1.SelectedItem != null) 149 | { 150 | this.connect.Enabled = true; 151 | } 152 | else 153 | { 154 | this.connect.Enabled = false; 155 | } 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /software/GUI/COMPortForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /software/GUI/GUI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7BA42A6E-9E73-43E4-9461-B98C8D50AED1} 8 | WinExe 9 | Properties 10 | GUI 11 | GUI 12 | v4.5 13 | 512 14 | publish\ 15 | true 16 | Disk 17 | false 18 | Foreground 19 | 7 20 | Days 21 | false 22 | false 23 | true 24 | 0 25 | 1.0.0.%2a 26 | false 27 | false 28 | true 29 | 30 | 31 | AnyCPU 32 | true 33 | full 34 | false 35 | bin\Debug\ 36 | DEBUG;TRACE 37 | prompt 38 | 4 39 | 40 | 41 | AnyCPU 42 | pdbonly 43 | true 44 | bin\Release\ 45 | TRACE 46 | prompt 47 | 4 48 | 49 | 50 | 51 | ..\OpenTK\OpenTK.dll 52 | 53 | 54 | ..\OpenTK\OpenTK.GLControl.dll 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | Form 70 | 71 | 72 | COMPortForm.cs 73 | 74 | 75 | 76 | Form 77 | 78 | 79 | RouterUI.cs 80 | 81 | 82 | 83 | 84 | UserControl 85 | 86 | 87 | RouterDrawing.cs 88 | 89 | 90 | 91 | COMPortForm.cs 92 | 93 | 94 | RouterUI.cs 95 | Designer 96 | 97 | 98 | ResXFileCodeGenerator 99 | Resources.Designer.cs 100 | Designer 101 | 102 | 103 | True 104 | Resources.resx 105 | 106 | 107 | RouterDrawing.cs 108 | 109 | 110 | SettingsSingleFileGenerator 111 | Settings.Designer.cs 112 | 113 | 114 | True 115 | Settings.settings 116 | True 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | {9b062971-a88e-4a3d-b3c9-12b78d15fa66} 128 | clipper_library 129 | 130 | 131 | {6a2ed2bc-1fea-46e3-8403-3c484a7bcca5} 132 | Router 133 | 134 | 135 | {c7bbabf0-0698-4c5f-a510-7e160c8771a5} 136 | Robot 137 | 138 | 139 | {9477fd2c-fe8f-4653-ab25-bfa14338a932} 140 | Serial 141 | 142 | 143 | {3c91d012-845b-411d-83f7-c16c4c71d97b} 144 | Utilities 145 | 146 | 147 | 148 | 149 | False 150 | Microsoft .NET Framework 4.5 %28x86 and x64%29 151 | true 152 | 153 | 154 | False 155 | .NET Framework 3.5 SP1 Client Profile 156 | false 157 | 158 | 159 | False 160 | .NET Framework 3.5 SP1 161 | false 162 | 163 | 164 | 165 | 172 | -------------------------------------------------------------------------------- /software/GUI/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xenovacivus/cnc_machine/9452474f29858127e500ce7bf9f20a763117aebb/software/GUI/Icon.ico -------------------------------------------------------------------------------- /software/GUI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace GUI 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new RouterUI()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /software/GUI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GUI")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GUI")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ad935126-6e14-4d00-9e21-e3c4745a49e2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /software/GUI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18047 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace GUI.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GUI.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /software/GUI/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /software/GUI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18047 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace GUI.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /software/GUI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software/GUI/RouterDrawing.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GUI 2 | { 3 | partial class RouterDrawing 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // UserControl1 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.Name = "UserControl1"; 38 | this.Load += new System.EventHandler(this.UserControl1_Load); 39 | this.ResumeLayout(false); 40 | 41 | } 42 | 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /software/GUI/RouterDrawing.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /software/GUI/RouterUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using System.IO; 10 | using System.Xml.Serialization; 11 | using System.Drawing.Drawing2D; 12 | using RoverEmulator; 13 | using System.Text.RegularExpressions; 14 | using System.Runtime.Serialization; 15 | using Robot; 16 | using Serial; 17 | using Utilities; 18 | using Router; 19 | using OpenTK; 20 | 21 | namespace GUI 22 | { 23 | public partial class RouterUI : Form 24 | { 25 | Robot.Robot robot; 26 | IHardware hw; 27 | Router.Router router; 28 | SerialPortWrapper serial; 29 | Timer t; 30 | 31 | void PosUpdate(object o, EventArgs e) 32 | { 33 | if (this.InvokeRequired && !this.Disposing) 34 | { 35 | try 36 | { 37 | this.Invoke(new EventHandler(PosUpdate), new object[] { o, e }); 38 | } 39 | catch (ObjectDisposedException ex) 40 | { 41 | } 42 | } 43 | else 44 | { 45 | userControl11.Invalidate(); 46 | } 47 | } 48 | 49 | public RouterUI() 50 | { 51 | InitializeComponent(); 52 | serial = new SerialPortWrapper(); 53 | robot = new Robot.Robot(serial); 54 | hw = robot as IHardware; 55 | router = new Router.Router(hw); 56 | hw.onPositionUpdate += new EventHandler(PosUpdate); 57 | 58 | // Setup for doing our own form painting 59 | //this.SetStyle( 60 | // ControlStyles.AllPaintingInWmPaint | 61 | // ControlStyles.UserPaint | 62 | // ControlStyles.DoubleBuffer, true); 63 | t = new Timer(); 64 | t.Interval = 25; 65 | t.Tick += new EventHandler(t_Tick); 66 | t.Enabled = false; 67 | //t.Start(); 68 | 69 | this.propertyGrid.SelectedGridItemChanged += new SelectedGridItemChangedEventHandler(propertyGrid_SelectedGridItemChanged); 70 | 71 | userControl11.SelectedItemChanged += new EventHandler(userControl11_SelectedItemChanged); 72 | userControl11.AddObject(router); 73 | //g1 = new InvoluteGear(); 74 | //g2 = new InvoluteGear(); 75 | //userControl11.AddObject(g1); 76 | //g2.X = 122.5493f * 2; 77 | //g2.Rotation = 180.0f / 11.0f + 0.425f; 78 | //userControl11.AddObject(g2); 79 | } 80 | //InvoluteGear g1; 81 | //InvoluteGear g2; 82 | 83 | void propertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e) 84 | { 85 | userControl11.Invalidate(); 86 | } 87 | 88 | void userControl11_SelectedItemChanged(object sender, EventArgs e) 89 | { 90 | this.radioButton1.Checked = true; 91 | this.propertyGrid.SelectedObject = sender; 92 | } 93 | 94 | private void RoutAllClick(object sender, EventArgs e) 95 | { 96 | //if (g_code != null) 97 | //{ 98 | // RouterCommand[] router_commands = g_code.GetRouterCommands(); 99 | // router.AddRouterCommands(router_commands); 100 | //} 101 | 102 | List rts = userControl11.GetObjects(); 103 | foreach (Object o in rts) 104 | { 105 | IHasRouts ihs = o as IHasRouts; 106 | if (ihs != null) 107 | { 108 | foreach (Rout r in ihs.GetRouts()) 109 | { 110 | bool backwards = false; 111 | float originalDepth = r.Depth; 112 | float currentDepth = 0; // Surface depth 113 | 114 | float maxCutDepth = router.MaxCutDepth; 115 | while (originalDepth < (currentDepth - maxCutDepth)) 116 | { 117 | r.Depth = currentDepth - maxCutDepth; 118 | router.RoutPath(r, backwards); 119 | backwards = !backwards; 120 | currentDepth = currentDepth - maxCutDepth; 121 | } 122 | 123 | // Final Cut 124 | r.Depth = originalDepth; 125 | router.RoutPath(r, backwards); 126 | } 127 | } 128 | } 129 | router.Complete(); 130 | } 131 | 132 | private void CompleteClick(object sender, EventArgs e) 133 | { 134 | router.Complete(); 135 | } 136 | 137 | COMPortForm comPortForm = null; 138 | private void button4_Click(object sender, EventArgs e) 139 | { 140 | if (comPortForm == null || comPortForm.IsDisposed) 141 | { 142 | comPortForm = new COMPortForm(serial); 143 | } 144 | 145 | if (!comPortForm.Visible) 146 | { 147 | comPortForm.Show(null); 148 | } 149 | else 150 | { 151 | comPortForm.Focus(); 152 | } 153 | } 154 | 155 | float last_x = 0; 156 | float last_y = 0; 157 | float last_z = 0; 158 | void t_Tick(object sender, EventArgs e) 159 | { 160 | //float z = (float)up_down_z.Value; // float.Parse(box_z.Text); 161 | 162 | //g1.Rotation = -z * 100; 163 | //g2.Rotation = z * 100 + 180.0f / 11.0f + 0.425f; 164 | 165 | float toolSpeed = (float)this.toolSpeedUpDown.Value; 166 | //lock (hw) 167 | //{ 168 | // if (hw.IsMoving()) 169 | // { 170 | // } 171 | // else 172 | // { 173 | // float x = (float)up_down_x.Value; // float.Parse(box_x.Text); 174 | // float y = (float)up_down_y.Value; // float.Parse(box_y.Text); 175 | // float z = (float)up_down_z.Value; // float.Parse(box_z.Text); 176 | // if (last_x != x || last_y != y || last_z != z) 177 | // { 178 | // hw.SetOffset(new Vector3(-x, -y, -z)); 179 | // hw.GoTo(new Vector3(0, 0, 0), toolSpeed); 180 | // last_x = x; 181 | // last_y = y; 182 | // last_z = z; 183 | // } 184 | // } 185 | //} 186 | } 187 | 188 | private void robot_button_Click(object sender, EventArgs e) 189 | { 190 | if (!checkBox1.Checked) 191 | { 192 | t_Tick(sender, e); 193 | } 194 | //if (hw.IsMoving()) 195 | //{ 196 | //} 197 | //else 198 | //{ 199 | // float x = (float)up_down_x.Value; // float.Parse(box_x.Text); 200 | // float y = (float)up_down_y.Value; // float.Parse(box_y.Text); 201 | // float z = (float)up_down_z.Value; // float.Parse(box_z.Text); 202 | // if (last_x != x || last_y != y || last_z != z) 203 | // { 204 | // hw.SetOffset(new Point3F(-x, -y, -z)); 205 | // hw.GoTo(new Point3F(0, 0, 0), 5); 206 | // last_x = x; 207 | // last_y = y; 208 | // last_z = z; 209 | // } 210 | //} 211 | } 212 | 213 | private void button1_Click_2(object sender, EventArgs e) 214 | { 215 | robot.Reset(); 216 | } 217 | 218 | private void box_x_TextChanged(object sender, EventArgs e) 219 | { 220 | 221 | } 222 | 223 | GCode g_code; 224 | private void button5_Click(object sender, EventArgs e) 225 | { 226 | OpenFileDialog d = new OpenFileDialog(); 227 | d.Filter = "Drill Files (*.nc)|*.nc"; 228 | if (DialogResult.OK == d.ShowDialog()) 229 | { 230 | string[] lines = System.IO.File.ReadAllLines(d.FileName); 231 | g_code = new GCode(); 232 | g_code.Parse(lines); 233 | Rout [] routs = g_code.GetRouts(); 234 | foreach (Rout r in routs) 235 | { 236 | userControl11.AddObject(r); 237 | } 238 | } 239 | } 240 | 241 | private void checkBox1_CheckedChanged(object sender, EventArgs e) 242 | { 243 | t.Enabled = checkBox1.Checked; 244 | robot_button.Enabled = !checkBox1.Checked; 245 | } 246 | 247 | private void radioButton2_CheckedChanged(object sender, EventArgs e) 248 | { 249 | if (radioButton2.Checked) 250 | { 251 | this.propertyGrid.SelectedObject = this.router; 252 | } 253 | } 254 | 255 | private void button6_Click(object sender, EventArgs e) 256 | { 257 | OpenFileDialog d = new OpenFileDialog(); 258 | d.Filter = "Drill Files (*.obj)|*.obj"; 259 | if (DialogResult.OK == d.ShowDialog()) 260 | { 261 | ObjLoader o = new ObjLoader(); 262 | o.LoadObj(d.FileName); 263 | userControl11.AddObject(o); 264 | //string[] lines = System.IO.File.ReadAllLines(d.FileName); 265 | //g_code = new GCode(); 266 | //g_code.Parse(lines); 267 | //Rout[] routs = g_code.GetRouts(); 268 | //foreach (Rout r in routs) 269 | //{ 270 | // userControl11.AddObject(r); 271 | //} 272 | } 273 | } 274 | 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /software/GUI/RouterUI.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 100, 17 122 | 123 | 124 | 252, 17 125 | 126 | 127 | 407, 17 128 | 129 | 130 | 513, 17 131 | 132 | 133 | 134 | 135 | AAABAAIAEBAQAAAABAAoAQAAJgAAACAgEAAAAAQA6AIAAE4BAAAoAAAAEAAAACAAAAABAAQAAAAAAIAA 136 | AAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ 137 | AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAd////////wB5mZmf////8H///5n////wf///+Z// 138 | //B8z///mZmZkH/M///////wf/zP//////B//8z///zMwH///MzPzP/wf////8zP//ByIv//////8H/y 139 | Iv/////wf//yIiIiIiB3////////cAd3d3d3d3dwgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 140 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAACgAAAAgAAAAQAAAAAEABAAAAAAAAAIAAAAA 141 | AAAAAAAAEAAAABAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD/ 142 | /wD/AAAA/wD/AP//AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3f/////////// 143 | //////AAd///////////////////AHeZmZmZmZ///////////wB3mZmZmZmZ//////////8Ad/////// 144 | mZ//////////AHf///////mZ/////////wB3////////mZ////////8Ad/////////mZ////////AHfM 145 | z///////mZmZmZmZmQB3zMz///////mZmZmZmZkAd//Mz///////////////AHf//Mz///////////// 146 | /wB3///Mz/////////////8Ad////Mz/////////////AHf////Mz////////MzMzAB3/////MzM//// 147 | /8zMzMwAd//////MzMzM//zM////AHf///////zMzMzMz////wB3/////////8zMzP////8Ad/////// 148 | ////////////AHciIv///////////////wB3IiIi//////////////8Ad///IiL/////////////AHf/ 149 | //8iIv///////////wB3/////yIiIiIiIiIiIiIAd///////IiIiIiIiIiIiAHf///////////////// 150 | /wB3f/////////////////cAd3d3d3d3d3d3d3d3d3d3AAd3d3d3d3d3d3d3d3d3dwCAAAABAAAAAAAA 151 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 152 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAQ== 153 | 154 | 155 | -------------------------------------------------------------------------------- /software/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xenovacivus/cnc_machine/9452474f29858127e500ce7bf9f20a763117aebb/software/Icon.ico -------------------------------------------------------------------------------- /software/OpenTK/OpenTK.GLControl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xenovacivus/cnc_machine/9452474f29858127e500ce7bf9f20a763117aebb/software/OpenTK/OpenTK.GLControl.dll -------------------------------------------------------------------------------- /software/OpenTK/OpenTK.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xenovacivus/cnc_machine/9452474f29858127e500ce7bf9f20a763117aebb/software/OpenTK/OpenTK.dll -------------------------------------------------------------------------------- /software/Robot/IHardware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using OpenTK; 6 | 7 | namespace Robot 8 | { 9 | public abstract class IHardware 10 | { 11 | public EventHandler onRobotReady; 12 | public abstract Vector3 GetPosition(); 13 | public abstract void GoTo(Vector3 p, float tool_speed); 14 | public EventHandler onPositionUpdate; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /software/Robot/IRobotCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Robot 8 | { 9 | internal abstract class IRobotCommand 10 | { 11 | public abstract byte[] GenerateCommand(); 12 | public abstract void ProcessResponse(byte[] data); 13 | public abstract bool IsDataValid(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /software/Robot/MoveCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Utilities; 7 | 8 | namespace Robot 9 | { 10 | internal class MoveCommand : IRobotCommand 11 | { 12 | private bool data_valid; 13 | private Int32 x, y, z; 14 | private UInt16 time_milliseconds; 15 | private static byte commandCode = 0x32; 16 | private byte locations; 17 | public byte Locations 18 | { 19 | get 20 | { 21 | return locations; 22 | } 23 | } 24 | public MoveCommand(Vector3i location, UInt16 time_milliseconds) 25 | { 26 | this.x = (Int32)location.x; 27 | this.y = (Int32)location.y; 28 | this.z = (Int32)location.z; 29 | this.time_milliseconds = time_milliseconds; 30 | data_valid = false; 31 | } 32 | public override byte[] GenerateCommand() 33 | { 34 | return new byte[] { commandCode, 35 | (byte)(time_milliseconds & 0xFF), (byte)((time_milliseconds >> 8) & 0xFF), 36 | (byte)(x & 0xFF), (byte)((x >> 8) & 0xFF), (byte)((x >> 16) & 0xFF), (byte)((x >> 24) & 0xFF), 37 | (byte)(y & 0xFF), (byte)((y >> 8) & 0xFF), (byte)((y >> 16) & 0xFF), (byte)((y >> 24) & 0xFF), 38 | (byte)(z & 0xFF), (byte)((z >> 8) & 0xFF), (byte)((z >> 16) & 0xFF), (byte)((z >> 24) & 0xFF)}; 39 | } 40 | public override void ProcessResponse(byte[] data) 41 | { 42 | if (data.Length > 0 && data[0] == commandCode) 43 | { 44 | data_valid = true; 45 | locations = data[1]; 46 | //Console.WriteLine("Response from MoveCommand: locations = {0}", locations); 47 | } 48 | else 49 | { 50 | Console.WriteLine("Error processing move command data!"); 51 | foreach (byte b in data) 52 | { 53 | Console.WriteLine(b); 54 | } 55 | } 56 | } 57 | public override bool IsDataValid() 58 | { 59 | return data_valid; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /software/Robot/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Robot")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Robot")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ff96beb0-6ea8-4dca-b8da-0d8feab45fb9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /software/Robot/ResetCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Robot 8 | { 9 | internal class ResetCommand : IRobotCommand 10 | { 11 | private bool data_valid; 12 | private static byte commandCode = 0x88; 13 | public ResetCommand() 14 | { 15 | data_valid = false; 16 | } 17 | public override byte[] GenerateCommand() 18 | { 19 | return new byte[] { commandCode }; 20 | } 21 | public override void ProcessResponse(byte[] data) 22 | { 23 | if (data.Length > 0 && data[0] == commandCode) 24 | { 25 | data_valid = true; 26 | } 27 | else 28 | { 29 | Console.WriteLine("Error processing reset command data!"); 30 | foreach (byte b in data) 31 | { 32 | Console.WriteLine(b); 33 | } 34 | } 35 | } 36 | public override bool IsDataValid() 37 | { 38 | return data_valid; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /software/Robot/Robot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Serial; 6 | using System.Timers; 7 | using OpenTK; 8 | using Utilities; 9 | 10 | namespace Robot 11 | { 12 | public class Robot : IHardware 13 | { 14 | IRobotCommand currentCommand = null; 15 | SerialPortWrapper serial; 16 | Timer t; 17 | int elapsedCounter = 0; 18 | 19 | Vector3 currentPosition = new Vector3(0, 0, 0); 20 | 21 | Vector3 lastPosition = new Vector3(0, 0, 0); 22 | 23 | public Robot(SerialPortWrapper serial) 24 | { 25 | this.serial = serial; 26 | serial.newDataAvailable += new SerialPortWrapper.newDataAvailableDelegate(NewDataAvailable); 27 | serial.receiveDataError += new SerialPortWrapper.receiveDataErrorDelegate(ReceiveDataError); 28 | t = new Timer(); 29 | t.Interval = 50; 30 | t.Start(); 31 | t.Elapsed += new ElapsedEventHandler(t_Elapsed); 32 | } 33 | 34 | /// 35 | /// Gets the X, Y, Z Scale Factors for converting Inches to Stepper Ticks 36 | /// X Axis: 12.5 inches per tooth, 15 tooth pulley, 100 phases per revolution, 32 ticks per phase 37 | /// Y Axis: 12.5 inches per tooth, 15 tooth pulley, 100 phases per revolution, 32 ticks per phase 38 | /// Z Axis: 32 threads per inch * 32 ticks per phase * 100 phases per revolution 39 | /// 40 | /// 41 | private static Vector3 ScaleFactors 42 | { 43 | get 44 | { 45 | return new Vector3( 46 | 12.5f * (1.0f / 15f) * 100f * 32.0f, 47 | 12.5f * (1.0f / 15f) * 100f * 32.0f, 48 | 32 * 32 * 100 * 1.0f); 49 | } 50 | } 51 | 52 | void t_Elapsed(object sender, ElapsedEventArgs e) 53 | { 54 | t.Stop(); 55 | lock (thisLock) 56 | { 57 | if (serial != null && serial.IsOpen) 58 | { 59 | elapsedCounter++; 60 | if ((elapsedCounter * 50) > (1000)) // More than 1 second to reply 61 | { 62 | Console.WriteLine("Device Timeout!"); 63 | 64 | // Send a status command 65 | currentCommand = new StatusCommand(); 66 | 67 | serial.Transmit(currentCommand.GenerateCommand(), 0x21); 68 | elapsedCounter = 0; 69 | } 70 | } 71 | } 72 | t.Start(); 73 | } 74 | 75 | #region Serial Interface Callbacks 76 | 77 | private void ReceiveDataError(byte err) 78 | { 79 | Console.WriteLine("Data Error: " + err); 80 | } 81 | 82 | Object thisLock = new Object(); 83 | private void NewDataAvailable(SerialPortWrapper.SimpleSerialPacket packet) 84 | { 85 | lock (thisLock) 86 | { 87 | if (currentCommand == null) 88 | { 89 | Console.WriteLine("Error: Received data, but no command was sent!"); 90 | foreach (byte b in packet.Data) 91 | { 92 | Console.Write(b.ToString("x") + ", "); 93 | } 94 | Console.WriteLine(); 95 | } 96 | else 97 | { 98 | currentCommand.ProcessResponse(packet.Data); 99 | if (currentCommand.IsDataValid()) 100 | { 101 | // See if there's any state information in the command used to 102 | // update location or other fields... 103 | byte locations = MaxLocations; 104 | if (currentCommand is StatusCommand) 105 | { 106 | StatusCommand c = currentCommand as StatusCommand; 107 | currentPosition = Vector3.Divide (c.CurrentPosition.ToVector3(), ScaleFactors); 108 | locations = c.Locations; 109 | if (onPositionUpdate != null) 110 | { 111 | onPositionUpdate(this, EventArgs.Empty); 112 | } 113 | } 114 | if (currentCommand is MoveCommand) 115 | { 116 | MoveCommand m = currentCommand as MoveCommand; 117 | locations = m.Locations; 118 | } 119 | 120 | currentCommand = GetNextCommand(locations); 121 | 122 | elapsedCounter = 0; 123 | serial.Transmit(currentCommand.GenerateCommand(), 0x21); 124 | } 125 | else 126 | { 127 | Console.WriteLine("Error: Did not process data correctly!"); 128 | } 129 | } 130 | } 131 | } 132 | 133 | static byte MaxLocations 134 | { 135 | get 136 | { 137 | return 4; 138 | } 139 | } 140 | 141 | #endregion 142 | 143 | private IRobotCommand GetNextCommand(byte locations) 144 | { 145 | currentCommand = null; 146 | if (locations < MaxLocations) 147 | { 148 | // Ok to pass in another movement command 149 | 150 | // TODO: rework this to use a local buffer... 151 | if (onRobotReady != null) 152 | { 153 | onRobotReady(this, EventArgs.Empty); 154 | } 155 | } 156 | 157 | if (currentCommand == null) 158 | { 159 | currentCommand = new StatusCommand(); 160 | } 161 | 162 | return currentCommand; 163 | } 164 | 165 | public override Vector3 GetPosition() 166 | { 167 | return currentPosition; 168 | } 169 | 170 | /// 171 | /// Run the router from the current position to the given position 172 | /// 173 | /// Destination location in inches 174 | /// Tool speed in inches per second 175 | public override void GoTo(Vector3 p, float inches_per_minute) 176 | { 177 | lock (thisLock) 178 | { 179 | Vector3 delta = lastPosition - p; 180 | 181 | // Z axis has a slower maximum speed. 182 | // TODO: implement clamping to a maximum speed for each axis. 183 | delta.Z = delta.Z * 10; 184 | 185 | float inches = delta.Length; 186 | 187 | Vector3i pointInt = new Vector3i(Vector3.Multiply(p, ScaleFactors)); 188 | 189 | UInt16 time_milliseconds = (UInt16)(1000 * 60 * inches / inches_per_minute); 190 | 191 | if (time_milliseconds > 0) 192 | { 193 | 194 | Console.WriteLine("Moving ({0}, {1}, {2}) to ({3}, {4}, {5}) in {6} milliseconds", 195 | lastPosition.X, 196 | lastPosition.Y, 197 | lastPosition.Z, 198 | pointInt.x, 199 | pointInt.y, 200 | pointInt.z, 201 | time_milliseconds); 202 | 203 | lastPosition = p; 204 | 205 | currentCommand = new MoveCommand(pointInt, time_milliseconds); 206 | } 207 | else 208 | { 209 | Console.WriteLine("Ignoring command with time of 0"); 210 | } 211 | } 212 | } 213 | 214 | public void Reset() 215 | { 216 | throw new NotImplementedException("Hey this isn't implemented yet or is broken or something dont use it yet"); 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /software/Robot/Robot.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C7BBABF0-0698-4C5F-A510-7E160C8771A5} 8 | Library 9 | Properties 10 | Robot 11 | Robot 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\..\..\..\CNC Machine\CNC2\Repo\DataLogger\OpenTK\OpenTK.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {9477fd2c-fe8f-4653-ab25-bfa14338a932} 56 | Serial 57 | 58 | 59 | {3c91d012-845b-411d-83f7-c16c4c71d97b} 60 | Utilities 61 | 62 | 63 | 64 | 71 | -------------------------------------------------------------------------------- /software/Robot/StatusCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Utilities; 7 | 8 | namespace Robot 9 | { 10 | internal class StatusCommand : IRobotCommand 11 | { 12 | private bool data_valid = false; 13 | private static byte commandCode = 0x77; 14 | public StatusCommand() 15 | { 16 | } 17 | public override byte[] GenerateCommand() 18 | { 19 | return new byte[] { commandCode }; 20 | } 21 | public override void ProcessResponse(byte[] data) 22 | { 23 | data_valid = (data[0] == commandCode); 24 | if (data.Length <= 14) 25 | { 26 | data_valid = false; 27 | return; 28 | } 29 | 30 | Int32 x = 0; 31 | Int32 y = 0; 32 | Int32 z = 0; 33 | for (int i = 4; i >= 1; i--) 34 | { 35 | x = (x << 8) | data[i]; 36 | y = (y << 8) | data[i + 4]; 37 | z = (z << 8) | data[i + 8]; 38 | } 39 | 40 | byte status_bits = data[13]; 41 | bool x_moving = (status_bits & 0x01) > 0; 42 | bool y_moving = (status_bits & 0x02) > 0; 43 | bool z_moving = (status_bits & 0x04) > 0; 44 | 45 | is_moving = x_moving | y_moving | z_moving; 46 | locations = data[14]; 47 | currentPosition = new Vector3i(x, y, z); 48 | 49 | //Console.WriteLine("Location = ({0}, {1}, {2}), Moving = ({3}, {4}, {5})", x, y, z, x_moving, y_moving, z_moving); 50 | } 51 | public override bool IsDataValid() 52 | { 53 | return data_valid; 54 | } 55 | private byte locations; 56 | public byte Locations 57 | { 58 | get 59 | { 60 | return locations; 61 | } 62 | } 63 | 64 | private Vector3i currentPosition; 65 | 66 | public Vector3i CurrentPosition 67 | { 68 | get 69 | { 70 | return currentPosition; 71 | } 72 | } 73 | 74 | bool is_moving = false; 75 | internal bool IsMoving() 76 | { 77 | return is_moving; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /software/Serial/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Serial")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Serial")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ab673d94-f09a-4642-b54a-f7e25de282d1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /software/Serial/Serial.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9477FD2C-FE8F-4653-AB25-BFA14338A932} 8 | Library 9 | Properties 10 | Serial 11 | Serial 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 54 | -------------------------------------------------------------------------------- /software/Serial/SerialPortWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO.Ports; 6 | 7 | namespace Serial 8 | { 9 | public class SerialPortWrapper 10 | { 11 | public SerialPort port; 12 | SerialPacket packet; 13 | 14 | public class SimpleSerialPacket 15 | { 16 | public SimpleSerialPacket(byte[] data, byte address) 17 | { 18 | this.data = data; 19 | this.address = address; 20 | } 21 | 22 | private byte[] data; 23 | private byte address; 24 | 25 | public byte[] Data 26 | { 27 | get 28 | { 29 | return data; 30 | } 31 | } 32 | 33 | public byte Address 34 | { 35 | get 36 | { 37 | return address; 38 | } 39 | } 40 | 41 | public byte Length 42 | { 43 | get 44 | { 45 | return (byte)data.Length; 46 | } 47 | } 48 | } 49 | 50 | private void RxPacketComplete(SerialPacket s) 51 | { 52 | //Console.WriteLine("Receive Packet Complete:"); 53 | for (int i = 0; i < s.receive_length; i++) 54 | { 55 | } 56 | 57 | SimpleSerialPacket simple = new SimpleSerialPacket(s.receive_data.Take(s.receive_data_count).ToArray(), s.receive_address); 58 | if (newDataAvailable != null) 59 | { 60 | newDataAvailable(simple); 61 | } 62 | } 63 | 64 | public delegate void newDataAvailableDelegate(SimpleSerialPacket s); 65 | public newDataAvailableDelegate newDataAvailable; 66 | 67 | public delegate void receiveDataErrorDelegate(byte err); 68 | public receiveDataErrorDelegate receiveDataError; 69 | 70 | private void TxPacketComplete() 71 | { 72 | } 73 | 74 | private void TxByte(byte data) 75 | { 76 | if (port.IsOpen) 77 | { 78 | try 79 | { 80 | port.Write(new byte[] { data }, 0, 1); 81 | } 82 | catch (Exception ex) 83 | { 84 | Console.WriteLine(ex.Message); 85 | } 86 | } 87 | packet.SerialByteTransmitComplete(); 88 | } 89 | 90 | private void RxPacketError(byte err) 91 | { 92 | //Console.WriteLine("Error! Byte Stream: "); 93 | //foreach (byte b in packet.receive_data) 94 | //{ 95 | // Console.Write(b + ", "); 96 | //} 97 | 98 | if (receiveDataError != null) 99 | { 100 | receiveDataError(err); 101 | } 102 | } 103 | 104 | public SerialPortWrapper() 105 | { 106 | // Setup method delegates 107 | packet = new SerialPacket(); 108 | packet.ReceiveDataError = new SerialPacket.ReceiveDataErrorDelegate (RxPacketError); 109 | packet.Transmit = new SerialPacket.TransmitDelegate(TxByte); 110 | packet.TransmitPacketComplete = new SerialPacket.TransmitPacketeCompleteDelegate(TxPacketComplete); 111 | packet.ReceivePacketComplete = new SerialPacket.ReceivePacketCOmpleteDelegate(RxPacketComplete); 112 | 113 | // Setup the serial port defaults 114 | port = new SerialPort(); 115 | port.BaudRate = 9600; 116 | port.DataBits = 8; 117 | port.Parity = Parity.None; 118 | port.Handshake = Handshake.None; 119 | port.StopBits = StopBits.One; 120 | port.DiscardNull = false; 121 | port.DtrEnable = false; 122 | port.RtsEnable = false; 123 | port.Encoding = System.Text.Encoding.Default; 124 | port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 125 | } 126 | 127 | public void Transmit(byte[] data, byte address) 128 | { 129 | // Wait until all pending data is sent 130 | while (packet.SerialTransferInProgress()) 131 | { 132 | } 133 | data.CopyTo(packet.transmit_data, 0); 134 | packet.SerialTransmit(address, (byte)data.Length); 135 | } 136 | 137 | void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 138 | { 139 | while (port.BytesToRead > 0) 140 | { 141 | byte data = (byte)port.ReadByte(); 142 | packet.ProcessDataChar(data); 143 | } 144 | } 145 | 146 | public void Open(string portName, int baudRate) 147 | { 148 | Close(); 149 | port.BaudRate = baudRate; 150 | port.PortName = portName; 151 | port.Open(); 152 | 153 | } 154 | 155 | public void Close() 156 | { 157 | if (port.IsOpen) 158 | { 159 | port.Close(); 160 | } 161 | } 162 | 163 | public bool IsOpen 164 | { 165 | get 166 | { 167 | return port.IsOpen; 168 | } 169 | } 170 | 171 | public string[] PortNames 172 | { 173 | get 174 | { 175 | return SerialPort.GetPortNames(); 176 | } 177 | } 178 | 179 | public int BaudRate 180 | { 181 | get 182 | { 183 | return port.BaudRate; 184 | } 185 | } 186 | 187 | public string PortName 188 | { 189 | get 190 | { 191 | return port.PortName; 192 | } 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /software/Utilities/CoolDrawing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using OpenTK; 7 | using OpenTK.Graphics.OpenGL; 8 | 9 | namespace Utilities 10 | { 11 | public class CoolDrawing 12 | { 13 | public static void DrawFilledCircle(float radius, Vector2 position, Color color) 14 | { 15 | GL.PushMatrix(); 16 | 17 | GL.Translate(position.X, position.Y, 0); 18 | 19 | GL.Color4(color); 20 | 21 | GL.Begin(BeginMode.TriangleFan); 22 | for (int x = 0; x < 20; x++) 23 | { 24 | GL.Vertex2 (Math.Sin(Math.PI * x / 10.0f) * radius, Math.Cos(Math.PI * x / 10.0f) * radius); 25 | } 26 | GL.End(); 27 | 28 | GL.PopMatrix(); 29 | } 30 | 31 | 32 | public static void DrawCircle(float radius, Vector2 position, Color color) 33 | { 34 | GL.PushMatrix(); 35 | 36 | GL.Translate(position.X, position.Y, 0); 37 | 38 | GL.Color4(color); 39 | 40 | GL.Begin(BeginMode.LineLoop); 41 | for (int x = 0; x < 60; x++) 42 | { 43 | GL.Vertex2(Math.Sin(Math.PI * x * 6.0f / 180.0f) * radius, Math.Cos(Math.PI * x * 6.0f / 180.0f) * radius); 44 | } 45 | GL.End(); 46 | 47 | GL.PopMatrix(); 48 | } 49 | 50 | 51 | static float max_cut_depth = -10; 52 | static float max_rout_depth = -60; 53 | static float max_move_height = 30; 54 | 55 | public class Line 56 | { 57 | public Vector2 a; 58 | public Vector2 b; 59 | public Line(Vector2 a, Vector2 b) 60 | { 61 | this.a = a; 62 | this.b = b; 63 | } 64 | } 65 | public static void DrawDepthLine(float width, Line [] lines, float depth) 66 | { 67 | DrawLines(width, lines, Color.FromArgb(100, Color.Orange)); 68 | 69 | if (depth < 0) 70 | { 71 | float w = width * (depth / max_cut_depth); 72 | if (w > width) 73 | { 74 | w = width; 75 | } 76 | DrawLines(w, lines, Color.FromArgb(255, Color.OrangeRed)); 77 | } 78 | if (depth < max_cut_depth) 79 | { 80 | float w = width * (depth / max_rout_depth); 81 | if (w > width) 82 | { 83 | w = width; 84 | } 85 | DrawLines(w, lines, Color.FromArgb(200, Color.DarkRed)); 86 | } 87 | if (depth > 0) 88 | { 89 | float w = width * (depth / max_move_height); 90 | if (w > width) 91 | { 92 | w = width; 93 | } 94 | DrawLines(w, lines, Color.FromArgb(50, Color.Green)); 95 | } 96 | } 97 | 98 | public static void DrawLines(float width, Line[] lines, Color c) 99 | { 100 | foreach (Line l in lines) 101 | { 102 | DrawLine(width, l.a, l.b, c); 103 | } 104 | } 105 | public static void DrawLine(double width, Vector2d a, Vector2d b, Color c) 106 | { 107 | DrawLine((float)width, new Vector2((float)a.X, (float)a.Y), new Vector2((float)b.X, (float)b.Y), c); 108 | } 109 | public static void DrawLine(float width, Vector2 a, Vector2 b, Color c) 110 | { 111 | float angle = (float)(180.0f / Math.PI * Math.Atan2(b.Y - a.Y, b.X - a.X)); 112 | 113 | GL.PushMatrix(); 114 | GL.Translate(a.X, a.Y, 0); 115 | GL.Rotate(angle, new Vector3(0, 0, 1)); 116 | 117 | float length = (a - b).Length; 118 | GL.Color4(c); 119 | FillBox(new Box2(-width / 2, length, width / 2, 0)); 120 | FillHalfCircle(width / 2, -180); 121 | GL.Translate(length, 0, 0); 122 | FillHalfCircle(width / 2, 0); 123 | 124 | GL.PopMatrix(); 125 | } 126 | 127 | public static void FillHalfCircle(float radius, float startAngle) 128 | { 129 | float start_angle_radians = (float)(Math.PI * startAngle / 180.0f); 130 | GL.Begin(BeginMode.TriangleFan); 131 | for (int x = 0; x <= 10; x++) 132 | { 133 | GL.Vertex2(Math.Sin(Math.PI * x / 10.0f + start_angle_radians) * radius, Math.Cos(Math.PI * x / 10.0f + start_angle_radians) * radius); 134 | } 135 | GL.End(); 136 | } 137 | 138 | public static void FillBox(Box2 b) 139 | { 140 | GL.Begin(BeginMode.Quads); 141 | GL.Vertex2(b.Bottom, b.Left); 142 | GL.Vertex2(b.Bottom, b.Right); 143 | GL.Vertex2(b.Top, b.Right); 144 | GL.Vertex2(b.Top, b.Left); 145 | GL.End(); 146 | } 147 | 148 | public static void DrawLine(Graphics g, float width, Vector2 a, Vector2 b, Color c) 149 | { 150 | System.Drawing.Drawing2D.GraphicsState s = g.Save(); 151 | 152 | //g.DrawLine(Pens.DarkGreen, a, b); 153 | 154 | float angle = (float)(180.0f / Math.PI * Math.Atan2(b.Y - a.Y, b.X - a.X)); 155 | Font f = new Font(FontFamily.GenericSansSerif, 80, FontStyle.Bold); 156 | 157 | g.TranslateTransform(a.X, a.Y); 158 | g.RotateTransform(angle); 159 | float length = LineMath.Length(a, b); 160 | 161 | Color transparent = Color.FromArgb(200, c.R, c.G, c.B); 162 | 163 | //Brush br = new System.Drawing.Drawing2D.HatchBrush (System.Drawing.Drawing2D.HatchStyle.Sphere, Color.FromArgb(128, 100, 50, 25), Color.FromArgb(0, 0, 0, 0)); 164 | Brush br = new SolidBrush(transparent); 165 | g.FillRectangle(br, new RectangleF (0, -width/2, length, width)); 166 | 167 | //g.DrawArc(Pens.Black, new RectangleF(-width / 2, -width / 2, width, width), 90, 180); 168 | g.FillEllipse(Brushes.White, new RectangleF(-width / 2, -width / 2, width, width)); 169 | g.DrawEllipse(Pens.Black, new RectangleF(-width / 2, -width / 2, width, width)); 170 | //g.DrawLine(Pens.Orange, new PointF(0, width / 2.0f), new PointF(length, width / 2.0f)); 171 | //g.DrawLine(Pens.Orange, new PointF(0, -width / 2.0f), new PointF(length, -width / 2.0f)); 172 | //g.TranslateTransform(p2.X - p1.X, p2.Y - p1.Y); 173 | 174 | g.TranslateTransform(length, 0); 175 | //g.DrawArc(Pens.Black, new RectangleF(-width / 2, -width / 2, width, width), 270, 180); 176 | g.FillEllipse(Brushes.White, new RectangleF(-width / 2, -width / 2, width, width)); 177 | g.DrawEllipse(Pens.Black, new RectangleF(-width / 2, -width / 2, width, width)); 178 | 179 | g.Restore(s); 180 | } 181 | 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /software/Utilities/IOpenGLDrawable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Utilities 7 | { 8 | public interface IOpenGLDrawable 9 | { 10 | void Draw(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /software/Utilities/LineMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using OpenTK; 7 | 8 | namespace Utilities 9 | { 10 | public class LineMath 11 | { 12 | public static float DistanceTo(Vector2 line1, Vector2 line2, Vector2 a) 13 | { 14 | float r = Math.Min(Length(line1, a), Length(line2, a)); 15 | 16 | float length = LineMath.Length(line1, line2); 17 | if (length == 0) 18 | return r; 19 | 20 | Vector2 n = LineMath.Scale(LineMath.Sub(line1, line2), 1.0f / length); 21 | float d1 = LineMath.Mult(line1, n) - LineMath.Mult(a, n); 22 | n = new Vector2(-n.Y, n.X); 23 | float d2 = LineMath.Mult(line1, n) - LineMath.Mult(a, n); 24 | 25 | if (d1 <= length && d1 >= 0) 26 | { 27 | return Math.Min(Math.Abs(d2), r); 28 | } 29 | return r; 30 | } 31 | public static Vector2 Scale(Vector2 a, float b) 32 | { 33 | return new Vector2(a.X * b, a.Y * b); 34 | } 35 | public static Vector2 Sub(Vector2 a, Vector2 b) 36 | { 37 | return new Vector2(a.X - b.X, a.Y - b.Y); 38 | } 39 | public static float Mult(Vector2 a, Vector2 b) 40 | { 41 | return a.X * b.X + a.Y * b.Y; 42 | } 43 | public static float Length(Vector2 a, Vector2 b) 44 | { 45 | return (float)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2)); 46 | } 47 | 48 | internal static Vector2 Add(Vector2 actualPosition, Vector2 pointF) 49 | { 50 | return new Vector2(actualPosition.X + pointF.X, actualPosition.Y + pointF.Y); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /software/Utilities/MathHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utilities 8 | { 9 | public class MathHelper 10 | { 11 | public static bool NearlyEqual(float a, float b) 12 | { 13 | // IEEE 754 floats have about 7 decimal digits, compare to about 4 (compensate for a few calculation errors) 14 | float compare_range = 0.0001f; 15 | float difference = (float)Math.Abs (a - b); 16 | return (difference < compare_range * a && difference < compare_range * b); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /software/Utilities/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Utilities")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Utilities")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b931e7dd-c870-4e73-985b-048ef144d8c0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /software/Utilities/Utilities.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3C91D012-845B-411D-83F7-C16C4C71D97B} 8 | Library 9 | Properties 10 | Utilities 11 | Utilities 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\OpenTK\OpenTK.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 61 | -------------------------------------------------------------------------------- /software/Utilities/Vector3i.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK; 7 | 8 | namespace Utilities 9 | { 10 | /// 11 | /// Minimal class mimicking the behavior of a Vector3 for integer types 12 | /// Currently only instrumented for container purposes 13 | /// 14 | public class Vector3i 15 | { 16 | public int x = 0; 17 | public int y = 0; 18 | public int z = 0; 19 | public Vector3i(int x, int y, int z) 20 | { 21 | this.x = x; 22 | this.y = y; 23 | this.z = z; 24 | } 25 | 26 | public Vector3i(Vector3 v) 27 | { 28 | this.x = (int)Math.Round (v.X); 29 | this.y = (int)Math.Round (v.Y); 30 | this.z = (int)Math.Round (v.Z); 31 | } 32 | 33 | public Vector3 ToVector3() 34 | { 35 | return new Vector3(x, y, z); 36 | } 37 | } 38 | } 39 | --------------------------------------------------------------------------------