LaosMotion.cpp
1 |
/**
|
---|---|
2 |
* LaosMotion.cpp
|
3 |
* Motion Controll functions for Laos system
|
4 |
*
|
5 |
* Copyright (c) 2011 Peter Brier
|
6 |
*
|
7 |
* This file is part of the LaOS project (see: http://laoslaser.org)
|
8 |
*spe
|
9 |
* LaOS is free software: you can redistribute it and/or modify
|
10 |
* it under the terms of the GNU General Public License as published by
|
11 |
* the Free Software Foundation, either version 3 of the License, or
|
12 |
* (at your option) any later version.
|
13 |
*
|
14 |
* LaOS is distributed in the hope that it will be useful,
|
15 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17 |
* GNU General Public License for more details.
|
18 |
*
|
19 |
* You should have received a copy of the GNU General Public License
|
20 |
* along with LaOS. If not, see <http://www.gnu.org/licenses/>.
|
21 |
*
|
22 |
*
|
23 |
*
|
24 |
*/
|
25 |
#include "global.h" |
26 |
#include "LaosMotion.h" |
27 |
#include "planner.h" |
28 |
#include "stepper.h" |
29 |
#include "pins.h" |
30 |
|
31 |
// #define DO_MOTION_TEST 1
|
32 |
|
33 |
// globals
|
34 |
unsigned int step=0; |
35 |
int command=0; |
36 |
int mark_speed = 100; // 100 [mm/sec] |
37 |
int bitmap_speed = 100; // 100 [mm/sec] |
38 |
int power = 10000 ; |
39 |
// next planner action to enqueue
|
40 |
tActionRequest action; |
41 |
|
42 |
// position offsets
|
43 |
static int ofsx=0, ofsy=0, ofsz=0; |
44 |
|
45 |
// Command interpreter
|
46 |
int param=0, val=0; |
47 |
|
48 |
// Bitmap buffer
|
49 |
#define BITMAP_PIXELS (8192) |
50 |
#define BITMAP_SIZE (BITMAP_PIXELS/32) |
51 |
unsigned long bitmap[BITMAP_SIZE]; |
52 |
unsigned long bitmap_width=0; // nr of pixels |
53 |
unsigned long bitmap_size=0; // nr of bytes |
54 |
unsigned char bitmap_bpp=1, bitmap_enable=0; |
55 |
|
56 |
/**
|
57 |
*** LaosMotion() Constructor
|
58 |
*** Make new motion object
|
59 |
**/
|
60 |
LaosMotion::LaosMotion() |
61 |
{ |
62 |
extern GlobalConfig *cfg;
|
63 |
#if DO_MOTION_TEST
|
64 |
tActionRequest act[2];
|
65 |
int i=0; |
66 |
Timer t; |
67 |
#endif
|
68 |
pwm.period(1.0 / cfg->pwmfreq); |
69 |
pwm = cfg->pwmmin/100.0; |
70 |
if ( laser == NULL ) laser = new DigitalOut(LASER_PIN); |
71 |
*laser = LASEROFF; |
72 |
|
73 |
mark_speed = cfg->speed; |
74 |
//start.mode(PullUp);
|
75 |
xhome.mode(PullUp); |
76 |
yhome.mode(PullUp); |
77 |
isHome = false;
|
78 |
plan_init(); |
79 |
st_init(); |
80 |
reset(); |
81 |
mark_speed = cfg->speed; |
82 |
bitmap_speed = cfg->xspeed; |
83 |
action.param = 0;
|
84 |
action.target.x = action.target.y = action.target.z = action.target.e =0;
|
85 |
action.target.feed_rate = 60*mark_speed;
|
86 |
|
87 |
#if DO_MOTION_TEST
|
88 |
t.start(); |
89 |
act[0].ActionType = act[1].ActionType = AT_MOVE; |
90 |
act[0].target.feed_rate = 60 * 100; |
91 |
act[1].target.feed_rate = 60 * 200; |
92 |
act[0].target.x = act[0].target.y = act[0].target.z = act[0].target.e = 0; |
93 |
act[1].target.x = act[1].target.y = act[1].target.z = act[1].target.e = 100; |
94 |
act[1].target.y = 200; |
95 |
while(1) |
96 |
{ |
97 |
while( plan_queue_full() ) led3 = !led3;
|
98 |
led1 = 1;
|
99 |
i++; |
100 |
if ( i )
|
101 |
printf("%d PING...\n", t.read_ms());
|
102 |
else
|
103 |
printf("%d PONG...\n", t.read_ms());
|
104 |
if ( i > 1 || i<0) i = 0; |
105 |
plan_buffer_line (&act[i]); |
106 |
led1 = 0;
|
107 |
} |
108 |
#endif
|
109 |
|
110 |
} |
111 |
|
112 |
|
113 |
/**
|
114 |
***Destructor
|
115 |
**/
|
116 |
LaosMotion::~LaosMotion() |
117 |
{ |
118 |
|
119 |
} |
120 |
|
121 |
|
122 |
/**
|
123 |
*** reset()
|
124 |
*** reset the state
|
125 |
**/
|
126 |
void LaosMotion::reset()
|
127 |
{ |
128 |
extern GlobalConfig *cfg;
|
129 |
#ifdef READ_FILE_DEBUG
|
130 |
printf("LaosMotion::reset()\n");
|
131 |
#endif
|
132 |
xstep = xdir = ystep = ydir = zstep = zdir = step = command = 0;
|
133 |
ofsx = ofsy = ofsz = 0;
|
134 |
*laser = LASEROFF; |
135 |
enable = cfg->enable; |
136 |
cover.mode(PullUp); |
137 |
} |
138 |
|
139 |
|
140 |
|
141 |
/**
|
142 |
*** ready()
|
143 |
*** ready to receive new commands
|
144 |
**/
|
145 |
int LaosMotion::ready()
|
146 |
{ |
147 |
return !plan_queue_full();
|
148 |
} |
149 |
|
150 |
|
151 |
/**
|
152 |
*** queue()
|
153 |
*** return nr of items in the queue (0 is empty)
|
154 |
**/
|
155 |
int LaosMotion::queue()
|
156 |
{ |
157 |
return plan_queue_items();
|
158 |
} |
159 |
|
160 |
|
161 |
|
162 |
|
163 |
/**
|
164 |
*** MoveTo()
|
165 |
**/
|
166 |
void LaosMotion::moveTo(int x, int y, int z) |
167 |
{ |
168 |
extern GlobalConfig *cfg;
|
169 |
action.target.x = ofsx + x/1000.0; |
170 |
action.target.y = ofsy + y/1000.0; |
171 |
action.target.z = ofsz + z/1000.0; |
172 |
action.ActionType = AT_MOVE; |
173 |
action.target.feed_rate = 60.0 * cfg->speed; |
174 |
plan_buffer_line(&action); |
175 |
//printf("To buffer: %d, %d, %d\n", x, y, z);
|
176 |
} |
177 |
|
178 |
/**
|
179 |
*** MoveTo() width specific speed (%)
|
180 |
**/
|
181 |
void LaosMotion::moveTo(int x, int y, int z, int speed) |
182 |
{ |
183 |
extern GlobalConfig *cfg;
|
184 |
action.target.x = ofsx + x/1000.0; |
185 |
action.target.y = ofsy + y/1000.0; |
186 |
action.target.z = ofsz + z/1000.0; |
187 |
action.ActionType = AT_MOVE; |
188 |
action.target.feed_rate = (speed * 60.0 * cfg->speed) / 100; |
189 |
plan_buffer_line(&action); |
190 |
//printf("To buffer: %d, %d, %d, %d\n", x, y,z,speed);
|
191 |
} |
192 |
|
193 |
/**
|
194 |
*** write()
|
195 |
*** Write command and parameters to motion controller
|
196 |
*** Parse all the integers found in the simplecode file per integer
|
197 |
**/
|
198 |
void LaosMotion::write(int i) |
199 |
{ |
200 |
extern GlobalConfig *cfg;
|
201 |
static int x=0,y=0,z=0; |
202 |
//if ( plan_queue_empty() )
|
203 |
//printf("Empty\n");
|
204 |
|
205 |
|
206 |
#ifdef READ_FILE_DEBUG_VERBOSE
|
207 |
printf(">%i (command: %i, step: %i)\n",i,command,step);
|
208 |
#endif
|
209 |
|
210 |
if ( step == 0 ) |
211 |
{ |
212 |
command = i; |
213 |
step++; |
214 |
} |
215 |
else
|
216 |
{ |
217 |
switch( command )
|
218 |
{ |
219 |
case 0: // move x,y (laser off) |
220 |
case 1: // line x,y (laser on) |
221 |
switch ( step )
|
222 |
{ |
223 |
case 1: |
224 |
action.target.x = i/1000.0; |
225 |
break;
|
226 |
case 2: |
227 |
action.target.y = i/1000.0;; |
228 |
step=0;
|
229 |
action.target.z = 0;
|
230 |
action.param = power; |
231 |
action.ActionType = (command ? AT_LASER : AT_MOVE); |
232 |
if ( bitmap_enable && (action.ActionType == AT_LASER))
|
233 |
{ |
234 |
action.ActionType = AT_BITMAP; |
235 |
bitmap_enable = 0;
|
236 |
} |
237 |
switch ( action.ActionType )
|
238 |
{ |
239 |
case AT_MOVE: action.target.feed_rate = 60 * cfg->speed; break; |
240 |
case AT_LASER: action.target.feed_rate = 60 * mark_speed; break; |
241 |
case AT_BITMAP: action.target.feed_rate = 60 * bitmap_speed; break; |
242 |
case AT_MOVE_ENDSTOP: break; |
243 |
case AT_WAIT: break; |
244 |
} |
245 |
|
246 |
if ( action.ActionType == AT_BITMAP )
|
247 |
{ |
248 |
while ( queue() );// printf("-"); // wait for queue to empty |
249 |
plan_set_accel(cfg->xaccel); |
250 |
plan_buffer_line(&action); |
251 |
while ( queue() ); // printf("*"); // wait for queue to empty |
252 |
plan_set_accel(cfg->accel); |
253 |
} |
254 |
else
|
255 |
plan_buffer_line(&action); |
256 |
|
257 |
break;
|
258 |
} |
259 |
break;
|
260 |
case 2: // move z |
261 |
switch(step)
|
262 |
{ |
263 |
case 1: |
264 |
step = 0;
|
265 |
z = action.target.z; |
266 |
action.param = power; |
267 |
action.ActionType = AT_MOVE; |
268 |
action.target.feed_rate = 60.0 * cfg->speed; |
269 |
plan_buffer_line(&action); |
270 |
break;
|
271 |
} |
272 |
break;
|
273 |
case 4: // set x,y,z (absolute) |
274 |
switch ( step )
|
275 |
{ |
276 |
case 1: |
277 |
x = i; |
278 |
break;
|
279 |
case 2: |
280 |
y = i; |
281 |
break;
|
282 |
case 3: |
283 |
z = i; |
284 |
setPosition(x,y,z); |
285 |
step=0;
|
286 |
break;
|
287 |
} |
288 |
break;
|
289 |
case 5: // nop |
290 |
step = 0;
|
291 |
break;
|
292 |
case 7: // set index,value |
293 |
switch ( step )
|
294 |
{ |
295 |
case 1: |
296 |
param = i; |
297 |
break;
|
298 |
case 2: |
299 |
val = i; |
300 |
step = 0;
|
301 |
switch( param )
|
302 |
{ |
303 |
case 100: |
304 |
if ( val < 1 ) val = 1; |
305 |
if ( val > 9999 ) val = 10000; |
306 |
mark_speed = val * cfg->speed / 10000;
|
307 |
bitmap_speed = val * cfg->xspeed / 10000;
|
308 |
#ifdef READ_FILE_DEBUG
|
309 |
printf("> speed: %i\n",mark_speed);
|
310 |
#endif
|
311 |
break;
|
312 |
case 101: |
313 |
power = val; |
314 |
#ifdef READ_FILE_DEBUG
|
315 |
printf("> power: %i\n",power);
|
316 |
#endif
|
317 |
break;
|
318 |
} |
319 |
break;
|
320 |
} |
321 |
break;
|
322 |
case 9: // Store bitmap mark data format: 9 <bpp> <width> <data-0> <data-1> ... <data-n> |
323 |
if ( step == 1 ) |
324 |
{ |
325 |
bitmap_bpp = i; |
326 |
} |
327 |
else if ( step == 2 ) |
328 |
{ |
329 |
// if ( queue() ) printf("Queue not empty... wait...\n\r");
|
330 |
while ( queue() );// printf("+"); // wait for queue to empty |
331 |
bitmap_width = i; |
332 |
bitmap_enable = 1;
|
333 |
bitmap_size = (bitmap_bpp * bitmap_width) / 32;
|
334 |
if ( (bitmap_bpp * bitmap_width) % 32 ) // padd to next 32-bit |
335 |
bitmap_size++; |
336 |
// printf("\n\rBitmap: read %d dwords\n\r", bitmap_size);
|
337 |
|
338 |
} |
339 |
else if ( step > 2 )// copy data |
340 |
{ |
341 |
bitmap[ (step-3) % BITMAP_SIZE ] = i;
|
342 |
// printf("[%ld] = %ld\n", (step-3) % BITMAP_SIZE, i);
|
343 |
if ( step-2 == bitmap_size ) // last dword received |
344 |
{ |
345 |
bitmap[ (step-2) % BITMAP_SIZE ] = 0; |
346 |
step = 0;
|
347 |
// printf("Bitmap: received %d dwords\n\r", bitmap_size);
|
348 |
} |
349 |
} |
350 |
break;
|
351 |
default: // I do not understand: stop motion |
352 |
step = 0;
|
353 |
break;
|
354 |
} |
355 |
if ( step )
|
356 |
step++; |
357 |
} |
358 |
} |
359 |
|
360 |
|
361 |
/**
|
362 |
*** Return true if start button is pressed
|
363 |
**/
|
364 |
bool LaosMotion::isStart()
|
365 |
{ |
366 |
return cover;
|
367 |
} |
368 |
|
369 |
|
370 |
/**
|
371 |
*** Hard set the absolute position
|
372 |
*** Warning: only call when the motion is not busy!
|
373 |
**/
|
374 |
void LaosMotion::setPosition(int x, int y, int z) |
375 |
{ |
376 |
plan_set_current_position_xyz(x/1000.0,y/1000.0,z/1000.0); |
377 |
ofsx = ofsy = ofsz = 0;
|
378 |
} |
379 |
|
380 |
/**
|
381 |
*** get the absolute position
|
382 |
**/
|
383 |
void LaosMotion::getPosition(int *x, int *y, int *z) |
384 |
{ |
385 |
float xx,yy,zz;
|
386 |
plan_get_current_position_xyz(&xx, &yy, &zz); |
387 |
*x = xx * 1000;
|
388 |
*y = yy * 1000;
|
389 |
*z = zz * 1000;
|
390 |
} |
391 |
|
392 |
|
393 |
|
394 |
/**
|
395 |
*** set the origin to this absolute position
|
396 |
*** set to (0,0,0) to reset the orgin back to its original position.
|
397 |
*** Note: Make sure you only call this at stand-still (motion queue is empty), otherwise strange things may happen
|
398 |
**/
|
399 |
void LaosMotion::setOrigin(int x, int y, int z) |
400 |
{ |
401 |
ofsx = x; |
402 |
ofsy = y; |
403 |
ofsz = z; |
404 |
} |
405 |
|
406 |
|
407 |
|
408 |
|
409 |
/**
|
410 |
*** Home the axis, stop when both home switches are pressed
|
411 |
**/
|
412 |
void LaosMotion::home(int x, int y, int z) |
413 |
{ |
414 |
extern GlobalConfig *cfg;
|
415 |
int i=0; |
416 |
printf("Homing %d,%d, with speed %d\n", x, y, cfg->homespeed);
|
417 |
xdir = cfg->xhomedir; |
418 |
ydir = cfg->yhomedir; |
419 |
zdir = cfg->zhomedir; |
420 |
led1 = 0;
|
421 |
isHome = false;
|
422 |
printf("Home Z...\n\r");
|
423 |
if (cfg->autozhome) {
|
424 |
printf("Homing %d with speed %d\n", z, cfg->zhomespeed);
|
425 |
while ((zmin ^ cfg->zpol) && (zmax ^ cfg->zpol)) {
|
426 |
zstep = 0;
|
427 |
wait(cfg->zhomespeed/1E6);
|
428 |
zstep = 1;
|
429 |
wait(cfg->zhomespeed/1E6);
|
430 |
} |
431 |
} |
432 |
printf("Home XY...\n\r");
|
433 |
while ( 1 ) |
434 |
{ |
435 |
xstep = ystep = 0;
|
436 |
wait(cfg->homespeed/1E6);
|
437 |
xstep = xhome ^ cfg->xpol; |
438 |
ystep = yhome ^ cfg->ypol; |
439 |
wait(cfg->homespeed/1E6);
|
440 |
|
441 |
led2 = !xhome; |
442 |
led3 = !yhome; |
443 |
led4 = ((i++) & 0x10000);
|
444 |
if ( !(xhome ^ cfg->xpol) && !(yhome ^ cfg->ypol) )
|
445 |
{ |
446 |
setPosition(x,y,z); |
447 |
moveTo(x,y,z); |
448 |
isHome = true;
|
449 |
printf("Home done.\n\r");
|
450 |
return;
|
451 |
} |
452 |
} |
453 |
|
454 |
} |
455 |
|
456 |
|
457 |
|