remove the unhandled gcode hack, and all the cruft it required
[clinton/Smoothieware.git] / src / modules / tools / scaracal / SCARAcal.cpp
CommitLineData
ed866a4b
QH
1/*
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
6*/
7
8#include "SCARAcal.h"
9
10#include "Kernel.h"
11#include "BaseSolution.h"
12#include "Config.h"
13#include "Robot.h"
14#include "StepperMotor.h"
15#include "StreamOutputPool.h"
16#include "Gcode.h"
17#include "Conveyor.h"
18#include "Stepper.h"
19#include "checksumm.h"
20#include "ConfigValue.h"
21#include "SerialMessage.h"
22#include "EndstopsPublicAccess.h"
23#include "PublicData.h"
983e6549
QH
24#include <algorithm>
25#include <map>
ed866a4b 26
33bacc39
QH
27#define scaracal_checksum CHECKSUM("scaracal")
28#define enable_checksum CHECKSUM("enable")
29#define slow_feedrate_checksum CHECKSUM("slow_feedrate")
ed866a4b
QH
30
31#define X_AXIS 0
32#define Y_AXIS 1
33#define Z_AXIS 2
34
35#define STEPPER THEKERNEL->robot->actuators
36#define STEPS_PER_MM(a) (STEPPER[a]->get_steps_per_mm())
ed866a4b
QH
37
38void SCARAcal::on_module_loaded()
39{
40 // if the module is disabled -> do nothing
33bacc39 41 if(!THEKERNEL->config->value( scaracal_checksum, enable_checksum )->by_default(false)->as_bool()) {
ed866a4b
QH
42 // as this module is not needed free up the resource
43 delete this;
44 return;
45 }
46
47 // load settings
48 this->on_config_reload(this);
49 // register event-handlers
50 register_for_event(ON_GCODE_RECEIVED);
ed866a4b
QH
51}
52
53void SCARAcal::on_config_reload(void *argument)
54{
33bacc39 55 this->slow_rate = THEKERNEL->config->value( scaracal_checksum, slow_feedrate_checksum )->by_default(5)->as_number(); // feedrate in mm/sec
ed866a4b
QH
56
57}
58
ed866a4b
QH
59
60// issue home command
61void SCARAcal::home()
62{
63 Gcode gc("G28", &(StreamOutput::NullStream));
64 THEKERNEL->call_event(ON_GCODE_RECEIVED, &gc);
65}
66
157d2308
QH
67bool SCARAcal::get_trim(float& x, float& y, float& z)
68{
69 void *returned_data;
70 bool ok = PublicData::get_value( endstops_checksum, trim_checksum, &returned_data );
71
72 if (ok) {
73 float *trim = static_cast<float *>(returned_data);
74 x= trim[0];
75 y= trim[1];
76 z= trim[2];
77 return true;
78 }
79 return false;
80}
81
ed866a4b
QH
82bool SCARAcal::set_trim(float x, float y, float z, StreamOutput *stream)
83{
84 float t[3]{x, y, z};
85 bool ok= PublicData::set_value( endstops_checksum, trim_checksum, t);
86
87 if (ok) {
88 stream->printf("set trim to X:%f Y:%f Z:%f\n", x, y, z);
89 } else {
90 stream->printf("unable to set trim, is endstops enabled?\n");
91 }
92
93 return ok;
94}
95
157d2308 96bool SCARAcal::get_home_offset(float& x, float& y, float& z)
ed866a4b
QH
97{
98 void *returned_data;
157d2308 99 bool ok = PublicData::get_value( endstops_checksum, home_offset_checksum, &returned_data );
ed866a4b
QH
100
101 if (ok) {
157d2308
QH
102 float *home_offset = static_cast<float *>(returned_data);
103 x= home_offset[0];
104 y= home_offset[1];
105 z= home_offset[2];
ed866a4b
QH
106 return true;
107 }
108 return false;
109}
110
157d2308
QH
111bool SCARAcal::set_home_offset(float x, float y, float z, StreamOutput *stream)
112{
113 char cmd[64];
114
115 // Assemble Gcode to add onto the queue
116 snprintf(cmd, sizeof(cmd), "M206 X%1.3f Y%1.3f Z%1.3f", x, y, z); // Send saved Z homing offset
117
118 Gcode gc(cmd, &(StreamOutput::NullStream));
119 THEKERNEL->call_event(ON_GCODE_RECEIVED, &gc);
120
983e6549 121 stream->printf("Set home_offset to X:%f Y:%f Z:%f\n", x, y, z);
157d2308
QH
122
123 return true;//ok;
124}
125
126bool SCARAcal::translate_trim(StreamOutput *stream)
127{
128 float S_trim[3],
129 home_off[3],
130 actuator[3];;
131
132 this->get_home_offset(home_off[0], home_off[1], home_off[2]); // get home offsets
133 this->get_trim(S_trim[0], S_trim[1], S_trim[2]); // get current trim
134
135 THEKERNEL->robot->arm_solution->cartesian_to_actuator( home_off, actuator ); // convert current home offset to actuator angles
136
137 // Subtract trim values from actuators to determine the real home offset actuator position for X and Y.
138
139 actuator[0] -= S_trim[0];
140 actuator[1] -= S_trim[1];
141
142 // Clear X and Y trims internally
143 S_trim[0] = 0.0F;
144 S_trim[1] = 0.0F;
145
146 // convert back to get the real cartesian home offsets
147
148 THEKERNEL->robot->arm_solution->actuator_to_cartesian( actuator, home_off );
149
150 this->set_home_offset(home_off[0], home_off[1], home_off[2],stream); // get home offsets
151 // Set the correct home offsets;
152
153 this->set_trim(S_trim[0], S_trim[1], S_trim[2], stream); // Now Clear relevant trims
154
155 return true;
156}
157
ed866a4b
QH
158void SCARAcal::SCARA_ang_move(float theta, float psi, float z, float feedrate)
159{
ed866a4b 160 char cmd[64];
ed866a4b
QH
161 float actuator[3],
162 cartesian[3];
163
164 // Assign the actuator angles from input
165 actuator[0] = theta;
166 actuator[1] = psi;
167 actuator[2] = z;
168
169 // Calculate the physical position relating to the arm angles
170 THEKERNEL->robot->arm_solution->actuator_to_cartesian( actuator, cartesian );
171
172 // Assemble Gcode to add onto the queue
c2663be2 173 snprintf(cmd, sizeof(cmd), "G0 X%1.3f Y%1.3f Z%1.3f F%1.1f", cartesian[0], cartesian[1], cartesian[2], feedrate * 60); // use specified feedrate (mm/sec)
ed866a4b 174
33bacc39 175 //THEKERNEL->streams->printf("DEBUG: move: %s\n", cmd);
ed866a4b 176
e0c008fe
QH
177 Gcode gc(cmd, &(StreamOutput::NullStream));
178 THEKERNEL->robot->on_gcode_received(&gc); // send to robot directly
ed866a4b
QH
179}
180
181//A GCode has been received
182//See if the current Gcode line has some orders for us
183void SCARAcal::on_gcode_received(void *argument)
184{
185 Gcode *gcode = static_cast<Gcode *>(argument);
186
187 if( gcode->has_m) {
188 switch( gcode->m ) {
189
190 case 114: { // Extra stuff for Morgan calibration
191 char buf[32];
192 float cartesian[3],
193 actuators[3];
194
195 THEKERNEL->robot->get_axis_position(cartesian); // get actual position from robot
196 THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators ); // translate to get actuator position
197
e0c008fe 198 int n = snprintf(buf, sizeof(buf), " A: Th:%1.3f Ps:%1.3f",
ed866a4b 199 actuators[0],
33bacc39 200 actuators[1]); // display actuator angles Theta and Psi.
ed866a4b 201 gcode->txt_after_ok.append(buf, n);
ed866a4b 202 }
6e92ab91 203 break;
157d2308 204
ed866a4b
QH
205 case 360: {
206 float target[2] = {0.0F, 120.0F},
207 S_trim[3];
208
209 this->get_trim(S_trim[0], S_trim[1], S_trim[2]); // get current trim to conserve other calbration values
210
211 if(gcode->has_letter('P')) {
212 // Program the current position as target
213 float cartesian[3],
214 actuators[3],
215 S_delta[2],
216 S_trim[3];
217
218 THEKERNEL->robot->get_axis_position(cartesian); // get actual position from robot
219 THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators ); // translate to get actuator position
220
221 S_delta[0] = actuators[0] - target[0];
222
223 set_trim(S_delta[0], S_trim[1], 0, gcode->stream);
224 } else {
225 set_trim(0, S_trim[1], 0, gcode->stream); // reset trim for calibration move
226 this->home(); // home
227 SCARA_ang_move(target[0], target[1], 100.0F, slow_rate * 3.0F); // move to target
228 }
ed866a4b 229 }
6e92ab91
JM
230 break;
231
ed866a4b
QH
232 case 361: {
233 float target[2] = {90.0F, 130.0F};
234 if(gcode->has_letter('P')) {
235 // Program the current position as target
236 float cartesian[3],
237 actuators[3];
238
239 THEKERNEL->robot->get_axis_position(cartesian); // get actual position from robot
240 THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators ); // translate to get actuator position
241
33bacc39 242 STEPPER[0]->change_steps_per_mm(actuators[0] / target[0] * STEPPER[0]->get_steps_per_mm()); // Find angle difference
157d2308 243 STEPPER[1]->change_steps_per_mm(STEPPER[0]->get_steps_per_mm()); // and change steps_per_mm to ensure correct steps per *angle*
ed866a4b
QH
244 } else {
245 this->home(); // home - This time leave trims as adjusted.
246 SCARA_ang_move(target[0], target[1], 100.0F, slow_rate * 3.0F); // move to target
247 }
6e92ab91 248
ed866a4b 249 }
6e92ab91
JM
250 break;
251
252 case 364: {
ed866a4b
QH
253 float target[2] = {45.0F, 135.0F},
254 S_trim[3];
255
256 this->get_trim(S_trim[0], S_trim[1], S_trim[2]); // get current trim to conserve other calbration values
257
258 if(gcode->has_letter('P')) {
259 // Program the current position as target
260 float cartesian[3],
261 actuators[3],
262 S_delta[2];
263
33bacc39
QH
264 THEKERNEL->robot->get_axis_position(cartesian); // get actual position from robot
265 THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators ); // translate it to get actual actuator angles
ed866a4b 266
1a15649d
QH
267 S_delta[1] = ( actuators[1] - actuators[0]) - ( target[1] - target[0] ); // Find difference in angle - not actuator difference, and
268 set_trim(S_trim[0], S_delta[1], 0, gcode->stream); // set trim to reflect the difference
ed866a4b 269 } else {
1a15649d
QH
270 set_trim(S_trim[0], 0, 0, gcode->stream); // reset trim for calibration move
271 this->home(); // home
272 SCARA_ang_move(target[0], target[1], 100.0F, slow_rate * 3.0F); // move to target
ed866a4b 273 }
ed866a4b 274 }
6e92ab91 275 break;
157d2308 276
983e6549
QH
277 /* TODO case 365: { // set scara scaling
278 std::map<char, float> buf = gcode->get_args();
279 //algorithm::replace(buf.begin, buf.end , 'X', 'A');
280 //algorithm::algorithm::replace(buf.begin, buf.end , 'Y', 'B');
281 //algorithm::replace(buf.begin, buf.end , 'Z', 'C');
282
283 buf = string("M665 ") + buf;
284
285 Gcode gc(buf, &(StreamOutput::NullStream));
286 THEKERNEL->call_event(ON_GCODE_RECEIVED, &gc);
287
288 //stream->printf("Set scaling to X:%f Y:%f Z:%f\n", x, y, z);
289
6e92ab91 290 */
983e6549 291
6e92ab91 292 case 366: // Translate trims to the actual endstop offsets for SCARA
157d2308 293 this->translate_trim(gcode->stream);
6e92ab91 294 break;
983e6549 295
ed866a4b 296 }
157d2308 297 }
ed866a4b
QH
298}
299