Fri, 17 Nov 2017 10:13:31 +0100
proper configuration, homing and planner optimization
0 | 1 | /* |
2 | stepper.c - stepper motor driver: executes motion plans using stepper motors | |
3 | Part of Grbl | |
4 | ||
5 | Copyright (c) 2009-2011 Simen Svale Skogsrud | |
6 | ||
7 | Grbl is free software: you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation, either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | Grbl is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with Grbl. If not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
20 | ||
21 | /* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith | |
22 | and Philipp Tiefenbacher. */ | |
23 | ||
24 | #include "Marlin.h" | |
25 | #include "stepper.h" | |
26 | #include "planner.h" | |
27 | #include "temperature.h" | |
28 | #include "ultralcd.h" | |
29 | #include "language.h" | |
30 | #include "led.h" | |
31 | #include "speed_lookuptable.h" | |
32 | ||
33 | ||
34 | ||
35 | //=========================================================================== | |
36 | //=============================public variables ============================ | |
37 | //=========================================================================== | |
38 | block_t *current_block; // A pointer to the block currently being traced | |
39 | volatile bool endstop_z_hit=false; | |
40 | bool old_z_min_endstop=false; | |
41 | ||
42 | ||
43 | //=========================================================================== | |
44 | //=============================private variables ============================ | |
45 | //=========================================================================== | |
46 | //static makes it inpossible to be called from outside of this file by extern.! | |
47 | ||
48 | // Variables used by The Stepper Driver Interrupt | |
49 | static unsigned char out_bits; // The next stepping-bits to be output | |
50 | static long counter_x, // Counter variables for the bresenham line tracer | |
51 | counter_y, | |
52 | counter_z, | |
53 | counter_e; | |
54 | volatile static unsigned long step_events_completed; // The number of step events executed in the current block | |
55 | #ifdef ADVANCE | |
56 | static long advance_rate, advance, final_advance = 0; | |
57 | static long old_advance = 0; | |
58 | #endif | |
59 | static long e_steps[3]; | |
60 | static long acceleration_time, deceleration_time; | |
61 | //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; | |
62 | static unsigned short acc_step_rate; // needed for deccelaration start point | |
63 | static char step_loops; | |
64 | static unsigned short OCR1A_nominal; | |
65 | ||
66 | volatile long endstops_trigsteps[3]={0,0,0}; | |
67 | volatile long endstops_stepsTotal,endstops_stepsDone; | |
68 | static volatile bool endstop_x_hit=false; | |
69 | static volatile bool endstop_y_hit=false; | |
70 | ||
71 | static bool old_x_min_endstop=false; | |
72 | static bool old_x_max_endstop=false; | |
73 | static bool old_y_min_endstop=false; | |
74 | static bool old_y_max_endstop=false; | |
75 | static bool old_z_max_endstop=false; | |
76 | ||
77 | static bool check_endstops = true; | |
78 | ||
79 | volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; | |
80 | volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; | |
81 | ||
82 | //=========================================================================== | |
83 | //=============================functions ============================ | |
84 | //=========================================================================== | |
85 | ||
86 | #define CHECK_ENDSTOPS if(check_endstops) | |
87 | ||
88 | // intRes = intIn1 * intIn2 >> 16 | |
89 | // uses: | |
90 | // r26 to store 0 | |
91 | // r27 to store the byte 1 of the 24 bit result | |
92 | #define MultiU16X8toH16(intRes, charIn1, intIn2) \ | |
93 | asm volatile ( \ | |
94 | "clr r26 \n\t" \ | |
95 | "mul %A1, %B2 \n\t" \ | |
96 | "movw %A0, r0 \n\t" \ | |
97 | "mul %A1, %A2 \n\t" \ | |
98 | "add %A0, r1 \n\t" \ | |
99 | "adc %B0, r26 \n\t" \ | |
100 | "lsr r0 \n\t" \ | |
101 | "adc %A0, r26 \n\t" \ | |
102 | "adc %B0, r26 \n\t" \ | |
103 | "clr r1 \n\t" \ | |
104 | : \ | |
105 | "=&r" (intRes) \ | |
106 | : \ | |
107 | "d" (charIn1), \ | |
108 | "d" (intIn2) \ | |
109 | : \ | |
110 | "r26" \ | |
111 | ) | |
112 | ||
113 | // intRes = longIn1 * longIn2 >> 24 | |
114 | // uses: | |
115 | // r26 to store 0 | |
116 | // r27 to store the byte 1 of the 48bit result | |
117 | #define MultiU24X24toH16(intRes, longIn1, longIn2) \ | |
118 | asm volatile ( \ | |
119 | "clr r26 \n\t" \ | |
120 | "mul %A1, %B2 \n\t" \ | |
121 | "mov r27, r1 \n\t" \ | |
122 | "mul %B1, %C2 \n\t" \ | |
123 | "movw %A0, r0 \n\t" \ | |
124 | "mul %C1, %C2 \n\t" \ | |
125 | "add %B0, r0 \n\t" \ | |
126 | "mul %C1, %B2 \n\t" \ | |
127 | "add %A0, r0 \n\t" \ | |
128 | "adc %B0, r1 \n\t" \ | |
129 | "mul %A1, %C2 \n\t" \ | |
130 | "add r27, r0 \n\t" \ | |
131 | "adc %A0, r1 \n\t" \ | |
132 | "adc %B0, r26 \n\t" \ | |
133 | "mul %B1, %B2 \n\t" \ | |
134 | "add r27, r0 \n\t" \ | |
135 | "adc %A0, r1 \n\t" \ | |
136 | "adc %B0, r26 \n\t" \ | |
137 | "mul %C1, %A2 \n\t" \ | |
138 | "add r27, r0 \n\t" \ | |
139 | "adc %A0, r1 \n\t" \ | |
140 | "adc %B0, r26 \n\t" \ | |
141 | "mul %B1, %A2 \n\t" \ | |
142 | "add r27, r1 \n\t" \ | |
143 | "adc %A0, r26 \n\t" \ | |
144 | "adc %B0, r26 \n\t" \ | |
145 | "lsr r27 \n\t" \ | |
146 | "adc %A0, r26 \n\t" \ | |
147 | "adc %B0, r26 \n\t" \ | |
148 | "clr r1 \n\t" \ | |
149 | : \ | |
150 | "=&r" (intRes) \ | |
151 | : \ | |
152 | "d" (longIn1), \ | |
153 | "d" (longIn2) \ | |
154 | : \ | |
155 | "r26" , "r27" \ | |
156 | ) | |
157 | ||
158 | // Some useful constants | |
159 | ||
160 | #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<<OCIE1A) | |
161 | #define DISABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 &= ~(1<<OCIE1A) | |
162 | ||
163 | ||
164 | void checkHitEndstops() | |
165 | { | |
166 | if( endstop_x_hit || endstop_y_hit || endstop_z_hit) { | |
167 | SERIAL_ECHO_START; | |
168 | SERIAL_ECHOPGM(MSG_ENDSTOPS_HIT); | |
169 | if(endstop_x_hit) { | |
170 | SERIAL_ECHOPAIR(" X:",(float)endstops_trigsteps[X_AXIS]/axis_steps_per_unit[X_AXIS]); | |
171 | } | |
172 | if(endstop_y_hit) { | |
173 | SERIAL_ECHOPAIR(" Y:",(float)endstops_trigsteps[Y_AXIS]/axis_steps_per_unit[Y_AXIS]); | |
174 | } | |
175 | if(endstop_z_hit) { | |
176 | SERIAL_ECHOPAIR(" Z:",(float)endstops_trigsteps[Z_AXIS]/axis_steps_per_unit[Z_AXIS]); | |
177 | } | |
178 | SERIAL_ECHOLN(""); | |
179 | endstop_x_hit=false; | |
180 | endstop_y_hit=false; | |
181 | endstop_z_hit=false; | |
182 | } | |
183 | } | |
184 | ||
185 | void endstops_hit_on_purpose() | |
186 | { | |
187 | endstop_x_hit=false; | |
188 | endstop_y_hit=false; | |
189 | endstop_z_hit=false; | |
190 | } | |
191 | ||
192 | void enable_endstops(bool check) | |
193 | { | |
194 | check_endstops = check; | |
195 | } | |
196 | ||
197 | // __________________________ | |
198 | // /| |\ _________________ ^ | |
199 | // / | | \ /| |\ | | |
200 | // / | | \ / | | \ s | |
201 | // / | | | | | \ p | |
202 | // / | | | | | \ e | |
203 | // +-----+------------------------+---+--+---------------+----+ e | |
204 | // | BLOCK 1 | BLOCK 2 | d | |
205 | // | |
206 | // time -----> | |
207 | // | |
208 | // The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates | |
209 | // first block->accelerate_until step_events_completed, then keeps going at constant speed until | |
210 | // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. | |
211 | // The slope of acceleration is calculated with the leib ramp alghorithm. | |
212 | ||
213 | void st_wake_up() { | |
214 | // TCNT1 = 0; | |
215 | ENABLE_STEPPER_DRIVER_INTERRUPT(); | |
216 | } | |
217 | ||
218 | FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { | |
219 | unsigned short timer; | |
220 | if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; | |
221 | ||
222 | if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times | |
223 | step_rate = (step_rate >> 2)&0x3fff; | |
224 | step_loops = 4; | |
225 | } | |
226 | else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times | |
227 | step_rate = (step_rate >> 1)&0x7fff; | |
228 | step_loops = 2; | |
229 | } | |
230 | else { | |
231 | step_loops = 1; | |
232 | } | |
233 | ||
234 | if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000); | |
235 | step_rate -= (F_CPU/500000); // Correct for minimal speed | |
236 | if(step_rate >= (8*256)){ // higher step rate | |
237 | unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; | |
238 | unsigned char tmp_step_rate = (step_rate & 0x00ff); | |
239 | unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); | |
240 | MultiU16X8toH16(timer, tmp_step_rate, gain); | |
241 | timer = (unsigned short)pgm_read_word_near(table_address) - timer; | |
242 | } | |
243 | else { // lower step rates | |
244 | unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; | |
245 | table_address += ((step_rate)>>1) & 0xfffc; | |
246 | timer = (unsigned short)pgm_read_word_near(table_address); | |
247 | timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); | |
248 | } | |
249 | if(timer < 100) { timer = 100; MYSERIAL.print(MSG_STEPPER_TO_HIGH); MYSERIAL.println(step_rate); }//(20kHz this should never happen) | |
250 | return timer; | |
251 | } | |
252 | ||
253 | // Initializes the trapezoid generator from the current block. Called whenever a new | |
254 | // block begins. | |
255 | FORCE_INLINE void trapezoid_generator_reset() { | |
256 | #ifdef ADVANCE | |
257 | advance = current_block->initial_advance; | |
258 | final_advance = current_block->final_advance; | |
259 | // Do E steps + advance steps | |
260 | e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); | |
261 | old_advance = advance >>8; | |
262 | #endif | |
263 | deceleration_time = 0; | |
264 | // step_rate to timer interval | |
265 | acc_step_rate = current_block->initial_rate; | |
266 | acceleration_time = calc_timer(acc_step_rate); | |
267 | OCR1A = acceleration_time; | |
268 | OCR1A_nominal = calc_timer(current_block->nominal_rate); | |
269 | ||
270 | ||
271 | ||
272 | // SERIAL_ECHO_START; | |
273 | // SERIAL_ECHOPGM("advance :"); | |
274 | // SERIAL_ECHO(current_block->advance/256.0); | |
275 | // SERIAL_ECHOPGM("advance rate :"); | |
276 | // SERIAL_ECHO(current_block->advance_rate/256.0); | |
277 | // SERIAL_ECHOPGM("initial advance :"); | |
278 | // SERIAL_ECHO(current_block->initial_advance/256.0); | |
279 | // SERIAL_ECHOPGM("final advance :"); | |
280 | // SERIAL_ECHOLN(current_block->final_advance/256.0); | |
281 | ||
282 | } | |
283 | ||
284 | // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. | |
285 | // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. | |
286 | ISR(TIMER1_COMPA_vect) | |
287 | { | |
288 | // If there is no current block, attempt to pop one from the buffer | |
289 | if (current_block == NULL) { | |
290 | // Anything in the buffer? | |
291 | current_block = plan_get_current_block(); | |
292 | if (current_block != NULL) { | |
293 | current_block->busy = true; | |
1
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
294 | |
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
295 | if (current_block->laser_on) { |
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
296 | WRITE(M571_PIN, HIGH);// Fire the laser! |
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
297 | } else { |
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
298 | WRITE(M571_PIN, LOW);// Shutdown the laser! |
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
299 | } |
b584642d4f58
several modifications to support laser enable - still needs cleanup
mbayer
parents:
0
diff
changeset
|
300 | |
0 | 301 | trapezoid_generator_reset(); |
302 | counter_x = -(current_block->step_event_count >> 1); | |
303 | counter_y = counter_x; | |
304 | counter_z = counter_x; | |
305 | counter_e = counter_x; | |
306 | step_events_completed = 0; | |
307 | ||
308 | #ifdef Z_LATE_ENABLE | |
309 | if(current_block->steps_z > 0) { | |
310 | enable_z(); | |
311 | OCR1A = 2000; //1ms wait | |
312 | return; | |
313 | } | |
314 | #endif | |
315 | ||
316 | // #ifdef ADVANCE | |
317 | // e_steps[current_block->active_extruder] = 0; | |
318 | // #endif | |
319 | } | |
320 | else { | |
321 | OCR1A=2000; // 1kHz. | |
322 | } | |
323 | } | |
324 | ||
325 | if (current_block != NULL) { | |
326 | // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt | |
327 | out_bits = current_block->direction_bits; | |
328 | ||
329 | // Set direction en check limit switches | |
330 | if ((out_bits & (1<<X_AXIS)) != 0) { // -direction | |
331 | WRITE(X_DIR_PIN, INVERT_X_DIR); | |
332 | count_direction[X_AXIS]=-1; | |
333 | CHECK_ENDSTOPS | |
334 | { | |
335 | #if X_MIN_PIN > -1 | |
336 | bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); | |
337 | if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { | |
338 | endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; | |
339 | endstop_x_hit=true; | |
340 | step_events_completed = current_block->step_event_count; | |
341 | } | |
342 | old_x_min_endstop = x_min_endstop; | |
343 | #endif | |
344 | } | |
345 | } | |
346 | else { // +direction | |
347 | WRITE(X_DIR_PIN,!INVERT_X_DIR); | |
348 | count_direction[X_AXIS]=1; | |
349 | CHECK_ENDSTOPS | |
350 | { | |
351 | #if X_MAX_PIN > -1 | |
352 | bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); | |
353 | if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ | |
354 | endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; | |
355 | endstop_x_hit=true; | |
356 | step_events_completed = current_block->step_event_count; | |
357 | } | |
358 | old_x_max_endstop = x_max_endstop; | |
359 | #endif | |
360 | } | |
361 | } | |
362 | ||
363 | if ((out_bits & (1<<Y_AXIS)) != 0) { // -direction | |
364 | WRITE(Y_DIR_PIN,INVERT_Y_DIR); | |
365 | count_direction[Y_AXIS]=-1; | |
366 | CHECK_ENDSTOPS | |
367 | { | |
368 | #if Y_MIN_PIN > -1 | |
369 | bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); | |
370 | if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { | |
371 | endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; | |
372 | endstop_y_hit=true; | |
373 | step_events_completed = current_block->step_event_count; | |
374 | } | |
375 | old_y_min_endstop = y_min_endstop; | |
376 | #endif | |
377 | } | |
378 | } | |
379 | else { // +direction | |
380 | WRITE(Y_DIR_PIN,!INVERT_Y_DIR); | |
381 | count_direction[Y_AXIS]=1; | |
382 | CHECK_ENDSTOPS | |
383 | { | |
384 | #if Y_MAX_PIN > -1 | |
385 | bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); | |
386 | if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ | |
387 | endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; | |
388 | endstop_y_hit=true; | |
389 | step_events_completed = current_block->step_event_count; | |
390 | } | |
391 | old_y_max_endstop = y_max_endstop; | |
392 | #endif | |
393 | } | |
394 | } | |
395 | ||
396 | if ((out_bits & (1<<Z_AXIS)) != 0) { // -direction | |
397 | WRITE(Z_DIR_PIN,INVERT_Z_DIR); | |
398 | count_direction[Z_AXIS]=-1; | |
399 | CHECK_ENDSTOPS | |
400 | { | |
401 | #if Z_MIN_PIN > -1 | |
402 | bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); | |
403 | if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { | |
404 | endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; | |
405 | endstop_z_hit=true; | |
406 | step_events_completed = current_block->step_event_count; | |
407 | } | |
408 | old_z_min_endstop = z_min_endstop; | |
409 | #endif | |
410 | } | |
411 | } | |
412 | else { // +direction | |
413 | WRITE(Z_DIR_PIN,!INVERT_Z_DIR); | |
414 | count_direction[Z_AXIS]=1; | |
415 | CHECK_ENDSTOPS | |
416 | { | |
417 | #if Z_MAX_PIN > -1 | |
418 | bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); | |
419 | if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { | |
420 | endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; | |
421 | endstop_z_hit=true; | |
422 | step_events_completed = current_block->step_event_count; | |
423 | } | |
424 | old_z_max_endstop = z_max_endstop; | |
425 | #endif | |
426 | } | |
427 | } | |
428 | ||
429 | #ifndef ADVANCE | |
430 | if ((out_bits & (1<<E_AXIS)) != 0) { // -direction | |
431 | REV_E_DIR(); | |
432 | ||
433 | if (m571_enabled) WRITE(M571_PIN, LOW);// M571 disable, never on retract! | |
434 | count_direction[E_AXIS]=-1; | |
435 | } | |
436 | else { // +direction | |
437 | NORM_E_DIR(); | |
438 | count_direction[E_AXIS]=1; | |
439 | } | |
440 | #endif //!ADVANCE | |
441 | ||
442 | ||
443 | ||
444 | for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) | |
445 | #ifndef REPRAPPRO_MULTIMATERIALS | |
446 | #if MOTHERBOARD != 8 // !teensylu | |
447 | MSerial.checkRx(); // Check for serial chars. | |
448 | #endif | |
449 | #endif | |
450 | ||
451 | #ifdef ADVANCE | |
452 | counter_e += current_block->steps_e; | |
453 | if (counter_e > 0) { | |
454 | counter_e -= current_block->step_event_count; | |
455 | if ((out_bits & (1<<E_AXIS)) != 0) { // - direction | |
456 | e_steps[current_block->active_extruder]--; | |
457 | } | |
458 | else { | |
459 | e_steps[current_block->active_extruder]++; | |
460 | } | |
461 | } | |
462 | #endif //ADVANCE | |
463 | ||
464 | counter_x += current_block->steps_x; | |
465 | if (counter_x > 0) { | |
466 | WRITE(X_STEP_PIN, HIGH); | |
467 | counter_x -= current_block->step_event_count; | |
468 | WRITE(X_STEP_PIN, LOW); | |
469 | count_position[X_AXIS]+=count_direction[X_AXIS]; | |
470 | } | |
471 | ||
472 | counter_y += current_block->steps_y; | |
473 | if (counter_y > 0) { | |
474 | WRITE(Y_STEP_PIN, HIGH); | |
475 | counter_y -= current_block->step_event_count; | |
476 | WRITE(Y_STEP_PIN, LOW); | |
477 | count_position[Y_AXIS]+=count_direction[Y_AXIS]; | |
478 | } | |
479 | ||
480 | counter_z += current_block->steps_z; | |
481 | if (counter_z > 0) { | |
482 | WRITE(Z_STEP_PIN, HIGH); | |
483 | counter_z -= current_block->step_event_count; | |
484 | WRITE(Z_STEP_PIN, LOW); | |
485 | count_position[Z_AXIS]+=count_direction[Z_AXIS]; | |
486 | } | |
487 | ||
488 | #ifndef ADVANCE | |
489 | counter_e += current_block->steps_e; | |
490 | if (counter_e > 0) { | |
491 | // M571 enable, since extruder motor active | |
492 | if (m571_enabled) WRITE(M571_PIN, HIGH); | |
493 | // N571 disables real E drive! (ie. on laser operations) | |
494 | if (!n571_enabled) { | |
495 | WRITE_E_STEP(HIGH); | |
496 | counter_e -= current_block->step_event_count; | |
497 | WRITE_E_STEP(LOW); | |
498 | } else counter_e -= current_block->step_event_count; | |
499 | count_position[E_AXIS]+=count_direction[E_AXIS]; | |
500 | } else { | |
501 | // M571 disable, no more E_steps to do | |
502 | if (m571_enabled) WRITE(M571_PIN, LOW); | |
503 | ||
504 | } | |
505 | #endif //!ADVANCE | |
506 | step_events_completed += 1; | |
507 | if(step_events_completed >= current_block->step_event_count) break; | |
508 | } | |
509 | // Calculare new timer value | |
510 | unsigned short timer; | |
511 | unsigned short step_rate; | |
512 | if (step_events_completed <= (unsigned long int)current_block->accelerate_until) { | |
513 | ||
514 | MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); | |
515 | acc_step_rate += current_block->initial_rate; | |
516 | ||
517 | // upper limit | |
518 | if(acc_step_rate > current_block->nominal_rate) | |
519 | acc_step_rate = current_block->nominal_rate; | |
520 | ||
521 | // step_rate to timer interval | |
522 | timer = calc_timer(acc_step_rate); | |
523 | OCR1A = timer; | |
524 | acceleration_time += timer; | |
525 | #ifdef ADVANCE | |
526 | for(int8_t i=0; i < step_loops; i++) { | |
527 | advance += advance_rate; | |
528 | } | |
529 | //if(advance > current_block->advance) advance = current_block->advance; | |
530 | // Do E steps + advance steps | |
531 | e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); | |
532 | old_advance = advance >>8; | |
533 | ||
534 | #endif | |
535 | } | |
536 | else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { | |
537 | MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); | |
538 | ||
539 | if(step_rate > acc_step_rate) { // Check step_rate stays positive | |
540 | step_rate = current_block->final_rate; | |
541 | } | |
542 | else { | |
543 | step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. | |
544 | } | |
545 | ||
546 | // lower limit | |
547 | if(step_rate < current_block->final_rate) | |
548 | step_rate = current_block->final_rate; | |
549 | ||
550 | // step_rate to timer interval | |
551 | timer = calc_timer(step_rate); | |
552 | OCR1A = timer; | |
553 | deceleration_time += timer; | |
554 | #ifdef ADVANCE | |
555 | for(int8_t i=0; i < step_loops; i++) { | |
556 | advance -= advance_rate; | |
557 | } | |
558 | if(advance < final_advance) advance = final_advance; | |
559 | // Do E steps + advance steps | |
560 | e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); | |
561 | old_advance = advance >>8; | |
562 | #endif //ADVANCE | |
563 | } | |
564 | else { | |
565 | OCR1A = OCR1A_nominal; | |
566 | } | |
567 | ||
568 | // If current block is finished, reset pointer | |
569 | if (step_events_completed >= current_block->step_event_count) { | |
570 | current_block = NULL; | |
571 | plan_discard_current_block(); | |
572 | } | |
573 | } | |
574 | } | |
575 | ||
576 | #ifdef ADVANCE | |
577 | unsigned char old_OCR0A; | |
578 | // Timer interrupt for E. e_steps is set in the main routine; | |
579 | // Timer 0 is shared with millies | |
580 | ISR(TIMER0_COMPA_vect) | |
581 | { | |
582 | old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz) | |
583 | OCR0A = old_OCR0A; | |
584 | // Set E direction (Depends on E direction + advance) | |
585 | for(unsigned char i=0; i<4;i++) { | |
586 | if (e_steps[0] != 0) { | |
587 | WRITE(E0_STEP_PIN, LOW); | |
588 | if (e_steps[0] < 0) { | |
589 | WRITE(E0_DIR_PIN, INVERT_E0_DIR); | |
590 | e_steps[0]++; | |
591 | WRITE(E0_STEP_PIN, HIGH); | |
592 | } | |
593 | else if (e_steps[0] > 0) { | |
594 | WRITE(E0_DIR_PIN, !INVERT_E0_DIR); | |
595 | e_steps[0]--; | |
596 | WRITE(E0_STEP_PIN, HIGH); | |
597 | } | |
598 | } | |
599 | #if EXTRUDERS > 1 | |
600 | if (e_steps[1] != 0) { | |
601 | WRITE(E1_STEP_PIN, LOW); | |
602 | if (e_steps[1] < 0) { | |
603 | WRITE(E1_DIR_PIN, INVERT_E1_DIR); | |
604 | e_steps[1]++; | |
605 | WRITE(E1_STEP_PIN, HIGH); | |
606 | } | |
607 | else if (e_steps[1] > 0) { | |
608 | WRITE(E1_DIR_PIN, !INVERT_E1_DIR); | |
609 | e_steps[1]--; | |
610 | WRITE(E1_STEP_PIN, HIGH); | |
611 | } | |
612 | } | |
613 | #endif | |
614 | #if EXTRUDERS > 2 | |
615 | if (e_steps[2] != 0) { | |
616 | WRITE(E2_STEP_PIN, LOW); | |
617 | if (e_steps[2] < 0) { | |
618 | WRITE(E2_DIR_PIN, INVERT_E2_DIR); | |
619 | e_steps[2]++; | |
620 | WRITE(E2_STEP_PIN, HIGH); | |
621 | } | |
622 | else if (e_steps[2] > 0) { | |
623 | WRITE(E2_DIR_PIN, !INVERT_E2_DIR); | |
624 | e_steps[2]--; | |
625 | WRITE(E2_STEP_PIN, HIGH); | |
626 | } | |
627 | } | |
628 | #endif | |
629 | } | |
630 | } | |
631 | #endif // ADVANCE | |
632 | ||
633 | void st_init() | |
634 | { | |
635 | //Initialize Dir Pins | |
636 | #if X_DIR_PIN > -1 | |
637 | SET_OUTPUT(X_DIR_PIN); | |
638 | #endif | |
639 | #if Y_DIR_PIN > -1 | |
640 | SET_OUTPUT(Y_DIR_PIN); | |
641 | #endif | |
642 | #if Z_DIR_PIN > -1 | |
643 | SET_OUTPUT(Z_DIR_PIN); | |
644 | #endif | |
645 | #if E0_DIR_PIN > -1 | |
646 | SET_OUTPUT(E0_DIR_PIN); | |
647 | #endif | |
648 | #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1) | |
649 | SET_OUTPUT(E1_DIR_PIN); | |
650 | #endif | |
651 | #if defined(E2_DIR_PIN) && (E2_DIR_PIN > -1) | |
652 | SET_OUTPUT(E2_DIR_PIN); | |
653 | #endif | |
654 | ||
655 | //Initialize Enable Pins - steppers default to disabled. | |
656 | ||
657 | #if (X_ENABLE_PIN > -1) | |
658 | SET_OUTPUT(X_ENABLE_PIN); | |
659 | if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); | |
660 | #endif | |
661 | #if (Y_ENABLE_PIN > -1) | |
662 | SET_OUTPUT(Y_ENABLE_PIN); | |
663 | if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); | |
664 | #endif | |
665 | #if (Z_ENABLE_PIN > -1) | |
666 | SET_OUTPUT(Z_ENABLE_PIN); | |
667 | if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); | |
668 | #endif | |
669 | #if (E0_ENABLE_PIN > -1) | |
670 | SET_OUTPUT(E0_ENABLE_PIN); | |
671 | if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH); | |
672 | #endif | |
673 | #if defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1) | |
674 | SET_OUTPUT(E1_ENABLE_PIN); | |
675 | if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH); | |
676 | #endif | |
677 | #if defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1) | |
678 | SET_OUTPUT(E2_ENABLE_PIN); | |
679 | if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH); | |
680 | #endif | |
681 | ||
682 | //endstops and pullups | |
683 | #ifdef ENDSTOPPULLUPS | |
684 | #if X_MIN_PIN > -1 | |
685 | SET_INPUT(X_MIN_PIN); | |
686 | WRITE(X_MIN_PIN,HIGH); | |
687 | #endif | |
688 | #if X_MAX_PIN > -1 | |
689 | SET_INPUT(X_MAX_PIN); | |
690 | WRITE(X_MAX_PIN,HIGH); | |
691 | #endif | |
692 | #if Y_MIN_PIN > -1 | |
693 | SET_INPUT(Y_MIN_PIN); | |
694 | WRITE(Y_MIN_PIN,HIGH); | |
695 | #endif | |
696 | #if Y_MAX_PIN > -1 | |
697 | SET_INPUT(Y_MAX_PIN); | |
698 | WRITE(Y_MAX_PIN,HIGH); | |
699 | #endif | |
700 | #if Z_MIN_PIN > -1 | |
701 | SET_INPUT(Z_MIN_PIN); | |
702 | WRITE(Z_MIN_PIN,HIGH); | |
703 | #endif | |
704 | #if Z_MAX_PIN > -1 | |
705 | SET_INPUT(Z_MAX_PIN); | |
706 | WRITE(Z_MAX_PIN,HIGH); | |
707 | #endif | |
708 | #else //ENDSTOPPULLUPS | |
709 | #if X_MIN_PIN > -1 | |
710 | SET_INPUT(X_MIN_PIN); | |
711 | #endif | |
712 | #if X_MAX_PIN > -1 | |
713 | SET_INPUT(X_MAX_PIN); | |
714 | #endif | |
715 | #if Y_MIN_PIN > -1 | |
716 | SET_INPUT(Y_MIN_PIN); | |
717 | #endif | |
718 | #if Y_MAX_PIN > -1 | |
719 | SET_INPUT(Y_MAX_PIN); | |
720 | #endif | |
721 | #if Z_MIN_PIN > -1 | |
722 | SET_INPUT(Z_MIN_PIN); | |
723 | #endif | |
724 | #if Z_MAX_PIN > -1 | |
725 | SET_INPUT(Z_MAX_PIN); | |
726 | #endif | |
727 | #endif //ENDSTOPPULLUPS | |
728 | ||
729 | ||
730 | //Initialize Step Pins | |
731 | #if (X_STEP_PIN > -1) | |
732 | SET_OUTPUT(X_STEP_PIN); | |
733 | #if X_ENABLE_PIN > -1 | |
734 | if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); | |
735 | #endif | |
736 | #endif | |
737 | #if (Y_STEP_PIN > -1) | |
738 | SET_OUTPUT(Y_STEP_PIN); | |
739 | #if Y_ENABLE_PIN > -1 | |
740 | if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); | |
741 | #endif | |
742 | #endif | |
743 | #if (Z_STEP_PIN > -1) | |
744 | SET_OUTPUT(Z_STEP_PIN); | |
745 | #if Z_ENABLE_PIN > -1 | |
746 | if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); | |
747 | #endif | |
748 | #endif | |
749 | #if (E0_STEP_PIN > -1) | |
750 | SET_OUTPUT(E0_STEP_PIN); | |
751 | #if E0_ENABLE_PIN > -1 | |
752 | if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH); | |
753 | #endif | |
754 | #endif | |
755 | #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) | |
756 | SET_OUTPUT(E1_STEP_PIN); | |
757 | #if E1_ENABLE_PIN > -1 | |
758 | if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH); | |
759 | #endif | |
760 | #endif | |
761 | #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) | |
762 | SET_OUTPUT(E2_STEP_PIN); | |
763 | #if E2_ENABLE_PIN > -1 | |
764 | if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH); | |
765 | #endif | |
766 | #endif | |
767 | ||
768 | #ifdef CONTROLLERFAN_PIN | |
769 | SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan | |
770 | #endif | |
771 | ||
772 | // M571 disable, switch off default | |
773 | if (m571_enabled) WRITE(M571_PIN, LOW); | |
774 | ||
775 | ||
776 | // waveform generation = 0100 = CTC | |
777 | TCCR1B &= ~(1<<WGM13); | |
778 | TCCR1B |= (1<<WGM12); | |
779 | TCCR1A &= ~(1<<WGM11); | |
780 | TCCR1A &= ~(1<<WGM10); | |
781 | ||
782 | // output mode = 00 (disconnected) | |
783 | TCCR1A &= ~(3<<COM1A0); | |
784 | TCCR1A &= ~(3<<COM1B0); | |
785 | ||
786 | // Set the timer pre-scaler | |
787 | // Generally we use a divider of 8, resulting in a 2MHz timer | |
788 | // frequency on a 16MHz MCU. If you are going to change this, be | |
789 | // sure to regenerate speed_lookuptable.h with | |
790 | // create_speed_lookuptable.py | |
791 | TCCR1B = (TCCR1B & ~(0x07<<CS10)) | (2<<CS10); | |
792 | ||
793 | OCR1A = 0x4000; | |
794 | TCNT1 = 0; | |
795 | ENABLE_STEPPER_DRIVER_INTERRUPT(); | |
796 | ||
797 | #ifdef ADVANCE | |
798 | #if defined(TCCR0A) && defined(WGM01) | |
799 | TCCR0A &= ~(1<<WGM01); | |
800 | TCCR0A &= ~(1<<WGM00); | |
801 | #endif | |
802 | e_steps[0] = 0; | |
803 | e_steps[1] = 0; | |
804 | e_steps[2] = 0; | |
805 | TIMSK0 |= (1<<OCIE0A); | |
806 | #endif //ADVANCE | |
807 | ||
808 | #ifdef ENDSTOPS_ONLY_FOR_HOMING | |
809 | enable_endstops(false); | |
810 | #else | |
811 | enable_endstops(true); | |
812 | #endif | |
813 | ||
814 | sei(); | |
815 | } | |
816 | ||
817 | ||
818 | // Block until all buffered steps are executed | |
819 | void st_synchronize() | |
820 | { | |
821 | while( blocks_queued()) { | |
822 | manage_heater(); | |
823 | manage_inactivity(1); | |
824 | LCD_STATUS; | |
825 | } | |
826 | } | |
827 | ||
828 | void st_set_position(const long &x, const long &y, const long &z, const long &e) | |
829 | { | |
830 | CRITICAL_SECTION_START; | |
831 | count_position[X_AXIS] = x; | |
832 | count_position[Y_AXIS] = y; | |
833 | count_position[Z_AXIS] = z; | |
834 | count_position[E_AXIS] = e; | |
835 | CRITICAL_SECTION_END; | |
836 | } | |
837 | ||
838 | void st_set_e_position(const long &e) | |
839 | { | |
840 | CRITICAL_SECTION_START; | |
841 | count_position[E_AXIS] = e; | |
842 | CRITICAL_SECTION_END; | |
843 | } | |
844 | ||
845 | long st_get_position(uint8_t axis) | |
846 | { | |
847 | long count_pos; | |
848 | CRITICAL_SECTION_START; | |
849 | count_pos = count_position[axis]; | |
850 | CRITICAL_SECTION_END; | |
851 | return count_pos; | |
852 | } | |
853 | ||
854 | void finishAndDisableSteppers() | |
855 | { | |
856 | st_synchronize(); | |
857 | LCD_MESSAGEPGM(MSG_STEPPER_RELEASED); | |
858 | disable_x(); | |
859 | disable_y(); | |
860 | disable_z(); | |
861 | disable_e0(); | |
862 | disable_e1(); | |
863 | disable_e2(); | |
864 | } | |
865 | ||
866 | void quickStop() | |
867 | { | |
868 | DISABLE_STEPPER_DRIVER_INTERRUPT(); | |
869 | ||
870 | while(blocks_queued()) | |
871 | plan_discard_current_block(); | |
872 | current_block = NULL; | |
873 | ||
874 | // M571 disable, switch off default | |
875 | if (m571_enabled) WRITE(M571_PIN, LOW); | |
876 | ||
877 | ENABLE_STEPPER_DRIVER_INTERRUPT(); | |
878 | } | |
879 |