Michael Spencer / Mbed 2 deprecated LaOS

Dependencies:   mbed

Committer:
Michael J. Spencer
Date:
Wed Mar 05 06:14:02 2014 -0800
Revision:
1:f5ac63519541
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Michael J. Spencer 1:f5ac63519541 1 /*
Michael J. Spencer 1:f5ac63519541 2 stepper.c - stepper motor driver: executes motion plans using stepper motors
Michael J. Spencer 1:f5ac63519541 3 Part of Grbl
Michael J. Spencer 1:f5ac63519541 4 Taken from R2C2 project and modified for Laos by Peter Brier
Michael J. Spencer 1:f5ac63519541 5 stripped, included some Marlin changes from Erik van de Zalm
Michael J. Spencer 1:f5ac63519541 6
Michael J. Spencer 1:f5ac63519541 7 Copyright (c) 2009-2011 Simen Svale Skogsrud
Michael J. Spencer 1:f5ac63519541 8 Modifications Copyright (c) 2011 Sungeun K. Jeon
Michael J. Spencer 1:f5ac63519541 9 Modifications Copyright (c) 2011 Peter Brier
Michael J. Spencer 1:f5ac63519541 10
Michael J. Spencer 1:f5ac63519541 11 Grbl is free software: you can redistribute it and/or modify
Michael J. Spencer 1:f5ac63519541 12 it under the terms of the GNU General Public License as published by
Michael J. Spencer 1:f5ac63519541 13 the Free Software Foundation, either version 3 of the License, orc
Michael J. Spencer 1:f5ac63519541 14 (at your option) any later version.
Michael J. Spencer 1:f5ac63519541 15
Michael J. Spencer 1:f5ac63519541 16 Grbl is distributed in the hope that it will be useful,
Michael J. Spencer 1:f5ac63519541 17 but WITHOUT ANY WARRANTY; without even the implied warrlaanty of
Michael J. Spencer 1:f5ac63519541 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Michael J. Spencer 1:f5ac63519541 19 GNU General Public License for more details.
Michael J. Spencer 1:f5ac63519541 20
Michael J. Spencer 1:f5ac63519541 21 You should have received a copy of the GNU General Public License
Michael J. Spencer 1:f5ac63519541 22 along with Grbl. If not, see <http://www.gnu.org/licenses/>.
Michael J. Spencer 1:f5ac63519541 23 */
Michael J. Spencer 1:f5ac63519541 24
Michael J. Spencer 1:f5ac63519541 25 /* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith
Michael J. Spencer 1:f5ac63519541 26 and Philipp Tiefenbacher. */
Michael J. Spencer 1:f5ac63519541 27
Michael J. Spencer 1:f5ac63519541 28 /* The acceleration profiles are derived using the techniques descibed in the paper
Michael J. Spencer 1:f5ac63519541 29 "Generate stepper-motor speed profiles in real time" David Austin 2004
Michael J. Spencer 1:f5ac63519541 30 published at http://www.eetimes.com/design/embedded/4006438/Generate-stepper-motor-speed-profiles-in-real-time and others.
Michael J. Spencer 1:f5ac63519541 31 */
Michael J. Spencer 1:f5ac63519541 32 #include <LaosMotion.h>
Michael J. Spencer 1:f5ac63519541 33 #include "pins.h"
Michael J. Spencer 1:f5ac63519541 34
Michael J. Spencer 1:f5ac63519541 35 #include <math.h>
Michael J. Spencer 1:f5ac63519541 36 #include <stdlib.h>
Michael J. Spencer 1:f5ac63519541 37 #include <string.h>
Michael J. Spencer 1:f5ac63519541 38
Michael J. Spencer 1:f5ac63519541 39 #include "fixedpt.h"
Michael J. Spencer 1:f5ac63519541 40 #include "stepper.h"
Michael J. Spencer 1:f5ac63519541 41 #include "config.h"
Michael J. Spencer 1:f5ac63519541 42 #include "planner.h"
Michael J. Spencer 1:f5ac63519541 43
Michael J. Spencer 1:f5ac63519541 44
Michael J. Spencer 1:f5ac63519541 45 #define TICKS_PER_MICROSECOND (1) // Ticker uses 1usec units
Michael J. Spencer 1:f5ac63519541 46 // #define CYCLES_PER_ACCELERATION_TICK ((TICKS_PER_MICROSECOND*1000000)/ACCELERATION_TICKS_PER_SECOND)
Michael J. Spencer 1:f5ac63519541 47 #define STEP_TIMER_FREQ 1000000 // 1 MHz
Michael J. Spencer 1:f5ac63519541 48
Michael J. Spencer 1:f5ac63519541 49 // types: ramp state
Michael J. Spencer 1:f5ac63519541 50 typedef enum {RAMP_UP, RAMP_MAX, RAMP_DOWN} tRamp;
Michael J. Spencer 1:f5ac63519541 51
Michael J. Spencer 1:f5ac63519541 52 // Prototypes
Michael J. Spencer 1:f5ac63519541 53 static void st_interrupt ();
Michael J. Spencer 1:f5ac63519541 54 static void set_step_timer (uint32_t cycles);
Michael J. Spencer 1:f5ac63519541 55 static void st_go_idle();
Michael J. Spencer 1:f5ac63519541 56
Michael J. Spencer 1:f5ac63519541 57 // Globals
Michael J. Spencer 1:f5ac63519541 58 volatile unsigned char busy = 0;
Michael J. Spencer 1:f5ac63519541 59 volatile int32_t actpos_x, actpos_y, actpos_z, actpos_e; // actual position
Michael J. Spencer 1:f5ac63519541 60
Michael J. Spencer 1:f5ac63519541 61 // Locals
Michael J. Spencer 1:f5ac63519541 62 static block_t *current_block; // A pointer to the block currently being traced
Michael J. Spencer 1:f5ac63519541 63 static Ticker timer; // the periodic timer used to step
Michael J. Spencer 1:f5ac63519541 64 static tFixedPt pwmofs; // the offset of the PWM value
Michael J. Spencer 1:f5ac63519541 65 static tFixedPt pwmscale; // the scaling of the PWM value
Michael J. Spencer 1:f5ac63519541 66 static volatile int running = 0; // stepper irq is running
Michael J. Spencer 1:f5ac63519541 67
Michael J. Spencer 1:f5ac63519541 68 static uint32_t direction_inv; // invert mask for direction bits
Michael J. Spencer 1:f5ac63519541 69 static uint32_t direction_bits; // all axes direction (different ports)
Michael J. Spencer 1:f5ac63519541 70 static uint32_t step_bits; // all axis step bits
Michael J. Spencer 1:f5ac63519541 71 static uint32_t step_inv; // invert mask for the stepper bits
Michael J. Spencer 1:f5ac63519541 72 static uint32_t nominal_rate; // [steps/min]
Michael J. Spencer 1:f5ac63519541 73 static int32_t counter_x, // Counter variables for the bresenham line tracer
Michael J. Spencer 1:f5ac63519541 74 counter_y,
Michael J. Spencer 1:f5ac63519541 75 counter_z;
Michael J. Spencer 1:f5ac63519541 76 static int32_t counter_e, counter_l, pos_l; // extruder and laser
Michael J. Spencer 1:f5ac63519541 77 static uint32_t step_events_completed; // The number of step events executed in the current block
Michael J. Spencer 1:f5ac63519541 78
Michael J. Spencer 1:f5ac63519541 79 // Variables used by the trapezoid generation
Michael J. Spencer 1:f5ac63519541 80 //static uint32_t cycles_per_step_event; // The number of machine cycles between each step event
Michael J. Spencer 1:f5ac63519541 81 static uint32_t trapezoid_tick_cycle_counter; // The cycles since last trapezoid_tick. Used to generate ticks at a steady
Michael J. Spencer 1:f5ac63519541 82 // pace without allocating a separate timer
Michael J. Spencer 1:f5ac63519541 83 static uint32_t trapezoid_adjusted_rate; // The current rate of step_events according to the trapezoid generator
Michael J. Spencer 1:f5ac63519541 84
Michael J. Spencer 1:f5ac63519541 85 static tFixedPt c; // current clock cycle count [1/speed]
Michael J. Spencer 1:f5ac63519541 86 static int32_t c_min; // minimal clock cycle count [at vnominal for this block]
Michael J. Spencer 1:f5ac63519541 87 static int32_t n;
Michael J. Spencer 1:f5ac63519541 88 static int32_t decel_n;
Michael J. Spencer 1:f5ac63519541 89 static tRamp ramp; // state of state machine for ramping up/down
Michael J. Spencer 1:f5ac63519541 90
Michael J. Spencer 1:f5ac63519541 91 extern unsigned char bitmap_bpp;
Michael J. Spencer 1:f5ac63519541 92 extern unsigned long bitmap[], bitmap_width, bitmap_size;
Michael J. Spencer 1:f5ac63519541 93
Michael J. Spencer 1:f5ac63519541 94
Michael J. Spencer 1:f5ac63519541 95 // __________________________
Michael J. Spencer 1:f5ac63519541 96 // /| |\ _________________ ^
Michael J. Spencer 1:f5ac63519541 97 // / | | \ /| |\ |
Michael J. Spencer 1:f5ac63519541 98 // / | | \ / | | \ s
Michael J. Spencer 1:f5ac63519541 99 // / | | | | | \ p
Michael J. Spencer 1:f5ac63519541 100 // / | | | | | \ e
Michael J. Spencer 1:f5ac63519541 101 // +-----+------------------------+---+--+---------------+----+ e
Michael J. Spencer 1:f5ac63519541 102 // | BLOCK 1 | BLOCK 2 | d
Michael J. Spencer 1:f5ac63519541 103 //
Michael J. Spencer 1:f5ac63519541 104 // time ----->
Michael J. Spencer 1:f5ac63519541 105 //
Michael J. Spencer 1:f5ac63519541 106 // The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates by block->rate_delta
Michael J. Spencer 1:f5ac63519541 107 // during the first block->accelerate_until step_events_completed, then keeps going at constant speed until
Michael J. Spencer 1:f5ac63519541 108 // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
Michael J. Spencer 1:f5ac63519541 109 // The slope of acceleration is always +/- block->rate_delta and is applied at a constant rate following the midpoint rule
Michael J. Spencer 1:f5ac63519541 110 // by the trapezoid generator, which is called ACCELERATION_TICKS_PER_SECOND times per second.
Michael J. Spencer 1:f5ac63519541 111
Michael J. Spencer 1:f5ac63519541 112
Michael J. Spencer 1:f5ac63519541 113
Michael J. Spencer 1:f5ac63519541 114 // Initialize and start the stepper motor subsystem
Michael J. Spencer 1:f5ac63519541 115 void st_init(void)
Michael J. Spencer 1:f5ac63519541 116 {
Michael J. Spencer 1:f5ac63519541 117 direction_inv =
Michael J. Spencer 1:f5ac63519541 118 (cfg->xscale<0 ? (1<<X_DIRECTION_BIT) : 0) |
Michael J. Spencer 1:f5ac63519541 119 (cfg->yscale<0 ? (1<<Y_DIRECTION_BIT) : 0) |
Michael J. Spencer 1:f5ac63519541 120 (cfg->zscale<0 ? (1<<Z_DIRECTION_BIT) : 0) |
Michael J. Spencer 1:f5ac63519541 121 (cfg->escale<0 ? (1<<E_DIRECTION_BIT) : 0);
Michael J. Spencer 1:f5ac63519541 122 step_inv =
Michael J. Spencer 1:f5ac63519541 123 (cfg->xinv ? (1<<X_STEP_BIT) : 0) |
Michael J. Spencer 1:f5ac63519541 124 (cfg->yinv ? (1<<Y_STEP_BIT) : 0) |
Michael J. Spencer 1:f5ac63519541 125 (cfg->zinv ? (1<<Z_STEP_BIT) : 0) |
Michael J. Spencer 1:f5ac63519541 126 (cfg->einv ? (1<<E_STEP_BIT) : 0);
Michael J. Spencer 1:f5ac63519541 127
Michael J. Spencer 1:f5ac63519541 128 printf("Direction: %d\n", direction_inv);
Michael J. Spencer 1:f5ac63519541 129 pwmofs = to_fixed(cfg->pwmmin) / 100; // offset (0 .. 1.0)
Michael J. Spencer 1:f5ac63519541 130 if ( cfg->pwmmin == cfg->pwmmax )
Michael J. Spencer 1:f5ac63519541 131 pwmscale = 0;
Michael J. Spencer 1:f5ac63519541 132 else
Michael J. Spencer 1:f5ac63519541 133 pwmscale = div_f(to_fixed(cfg->pwmmax - cfg->pwmmin), to_fixed(100) );
Michael J. Spencer 1:f5ac63519541 134 printf("ofs: %d, scale: %d\n", pwmofs, pwmscale);
Michael J. Spencer 1:f5ac63519541 135 actpos_x = actpos_y = actpos_z = actpos_e = 0;
Michael J. Spencer 1:f5ac63519541 136 st_wake_up();
Michael J. Spencer 1:f5ac63519541 137 trapezoid_tick_cycle_counter = 0;
Michael J. Spencer 1:f5ac63519541 138 st_go_idle(); // Start in the idle state
Michael J. Spencer 1:f5ac63519541 139 }
Michael J. Spencer 1:f5ac63519541 140
Michael J. Spencer 1:f5ac63519541 141 // output the direction bits to the appropriate output pins
Michael J. Spencer 1:f5ac63519541 142 static inline void set_direction_pins (void)
Michael J. Spencer 1:f5ac63519541 143 {
Michael J. Spencer 1:f5ac63519541 144 xdir = ( (direction_bits & (1<<X_DIRECTION_BIT))? 0 : 1 );
Michael J. Spencer 1:f5ac63519541 145 ydir = ( (direction_bits & (1<<Y_DIRECTION_BIT))? 0 : 1 );
Michael J. Spencer 1:f5ac63519541 146 zdir = ( (direction_bits & (1<<Z_DIRECTION_BIT))? 0 : 1 );
Michael J. Spencer 1:f5ac63519541 147 // edir = ( (direction_bits & (1<<E_DIRECTION_BIT))?0:1);
Michael J. Spencer 1:f5ac63519541 148 }
Michael J. Spencer 1:f5ac63519541 149
Michael J. Spencer 1:f5ac63519541 150 // output the step bits on the appropriate output pins
Michael J. Spencer 1:f5ac63519541 151 static inline void set_step_pins (uint32_t bits)
Michael J. Spencer 1:f5ac63519541 152 {
Michael J. Spencer 1:f5ac63519541 153 xstep = ( (bits & (1<<X_STEP_BIT))?1:0 );
Michael J. Spencer 1:f5ac63519541 154 ystep = ( (bits & (1<<Y_STEP_BIT))?1:0 );
Michael J. Spencer 1:f5ac63519541 155 zstep = ( (bits & (1<<Z_STEP_BIT))?1:0 );
Michael J. Spencer 1:f5ac63519541 156 // estep = ( (bits & (1<<E_STEP_BIT))?1:0 );
Michael J. Spencer 1:f5ac63519541 157 }
Michael J. Spencer 1:f5ac63519541 158
Michael J. Spencer 1:f5ac63519541 159 // unstep all stepper pins (output low)
Michael J. Spencer 1:f5ac63519541 160 static inline void clear_all_step_pins (void)
Michael J. Spencer 1:f5ac63519541 161 {
Michael J. Spencer 1:f5ac63519541 162
Michael J. Spencer 1:f5ac63519541 163 xstep =( (step_inv & (1<<X_STEP_BIT)) ? 1 : 0 );
Michael J. Spencer 1:f5ac63519541 164 ystep =( (step_inv & (1<<Y_STEP_BIT)) ? 1 : 0 );
Michael J. Spencer 1:f5ac63519541 165 zstep =( (step_inv & (1<<Z_STEP_BIT)) ? 1 : 0 );
Michael J. Spencer 1:f5ac63519541 166 // estep =( (step_inv & (1<<E_STEP_BIT)) ? 0 : 1 );
Michael J. Spencer 1:f5ac63519541 167 }
Michael J. Spencer 1:f5ac63519541 168
Michael J. Spencer 1:f5ac63519541 169
Michael J. Spencer 1:f5ac63519541 170 // check home sensor
Michael J. Spencer 1:f5ac63519541 171 int hit_home_stop_x(int axis)
Michael J. Spencer 1:f5ac63519541 172 {
Michael J. Spencer 1:f5ac63519541 173 return 1;
Michael J. Spencer 1:f5ac63519541 174 }
Michael J. Spencer 1:f5ac63519541 175 // check home sensor
Michael J. Spencer 1:f5ac63519541 176 int hit_home_stop_y(int axis)
Michael J. Spencer 1:f5ac63519541 177 {
Michael J. Spencer 1:f5ac63519541 178 return 1;
Michael J. Spencer 1:f5ac63519541 179 }
Michael J. Spencer 1:f5ac63519541 180 // check home sensor
Michael J. Spencer 1:f5ac63519541 181 int hit_home_stop_z(int axis)
Michael J. Spencer 1:f5ac63519541 182 {
Michael J. Spencer 1:f5ac63519541 183 return 1;
Michael J. Spencer 1:f5ac63519541 184 }
Michael J. Spencer 1:f5ac63519541 185
Michael J. Spencer 1:f5ac63519541 186 // Start stepper again from idle state, starts the step timer at a default rate
Michael J. Spencer 1:f5ac63519541 187 void st_wake_up()
Michael J. Spencer 1:f5ac63519541 188 {
Michael J. Spencer 1:f5ac63519541 189 if ( ! running )
Michael J. Spencer 1:f5ac63519541 190 {
Michael J. Spencer 1:f5ac63519541 191 running = 1;
Michael J. Spencer 1:f5ac63519541 192 set_step_timer(2000);
Michael J. Spencer 1:f5ac63519541 193 // printf("wake_up()..\n");
Michael J. Spencer 1:f5ac63519541 194 }
Michael J. Spencer 1:f5ac63519541 195 }
Michael J. Spencer 1:f5ac63519541 196
Michael J. Spencer 1:f5ac63519541 197 // When not stepping, go to idle mode. Steppers can be switched off, or set to reduced current
Michael J. Spencer 1:f5ac63519541 198 // (some delay might have to be implemented). Currently no motor switchoff is done.
Michael J. Spencer 1:f5ac63519541 199 static void st_go_idle()
Michael J. Spencer 1:f5ac63519541 200 {
Michael J. Spencer 1:f5ac63519541 201 timer.detach();
Michael J. Spencer 1:f5ac63519541 202 running = 0;
Michael J. Spencer 1:f5ac63519541 203 clear_all_step_pins();
Michael J. Spencer 1:f5ac63519541 204 *laser = LASEROFF;
Michael J. Spencer 1:f5ac63519541 205 pwm = cfg->pwmmax / 100.0; // set pwm to max;
Michael J. Spencer 1:f5ac63519541 206 // printf("idle()..\n");
Michael J. Spencer 1:f5ac63519541 207 }
Michael J. Spencer 1:f5ac63519541 208
Michael J. Spencer 1:f5ac63519541 209 // return number of steps to perform: n = (v^2) / (2*a)
Michael J. Spencer 1:f5ac63519541 210 // alpha is a adjustment factor for ?? (alsways 1! in this source)
Michael J. Spencer 1:f5ac63519541 211 static inline int32_t calc_n (float speed, float alpha, float accel)
Michael J. Spencer 1:f5ac63519541 212 {
Michael J. Spencer 1:f5ac63519541 213 return speed * speed / (2.0 * alpha * accel);
Michael J. Spencer 1:f5ac63519541 214 }
Michael J. Spencer 1:f5ac63519541 215
Michael J. Spencer 1:f5ac63519541 216 // Initializes the trapezoid generator from the current block. Called whenever a new
Michael J. Spencer 1:f5ac63519541 217 // block begins. Calculates the length ofc the block (in events), step rate, slopes and trigger positions (when to accel, decel, etc.)
Michael J. Spencer 1:f5ac63519541 218 static inline void trapezoid_generator_reset()
Michael J. Spencer 1:f5ac63519541 219 {
Michael J. Spencer 1:f5ac63519541 220 tFixedPt c0;
Michael J. Spencer 1:f5ac63519541 221 #define alpha (1.0)
Michael J. Spencer 1:f5ac63519541 222
Michael J. Spencer 1:f5ac63519541 223 // float alpha = 1.0;
Michael J. Spencer 1:f5ac63519541 224 float accel;
Michael J. Spencer 1:f5ac63519541 225 int32_t accel_until;
Michael J. Spencer 1:f5ac63519541 226 int32_t decel_after;
Michael J. Spencer 1:f5ac63519541 227
Michael J. Spencer 1:f5ac63519541 228 accel = current_block->rate_delta*ACCELERATION_TICKS_PER_SECOND / 60.0;
Michael J. Spencer 1:f5ac63519541 229
Michael J. Spencer 1:f5ac63519541 230 c0 = (float)STEP_TIMER_FREQ * sqrt (2.0*alpha/accel);
Michael J. Spencer 1:f5ac63519541 231 n = calc_n (current_block->initial_rate/60.0, alpha, accel);
Michael J. Spencer 1:f5ac63519541 232 if (n==0)
Michael J. Spencer 1:f5ac63519541 233 {
Michael J. Spencer 1:f5ac63519541 234 n = 1;
Michael J. Spencer 1:f5ac63519541 235 c = c0*0.676;
Michael J. Spencer 1:f5ac63519541 236 }
Michael J. Spencer 1:f5ac63519541 237 else
Michael J. Spencer 1:f5ac63519541 238 {
Michael J. Spencer 1:f5ac63519541 239 c = c0 * (sqrt(n+1.0)-sqrt((float)n));
Michael J. Spencer 1:f5ac63519541 240 }
Michael J. Spencer 1:f5ac63519541 241
Michael J. Spencer 1:f5ac63519541 242 ramp = RAMP_UP;
Michael J. Spencer 1:f5ac63519541 243
Michael J. Spencer 1:f5ac63519541 244 accel_until = calc_n (current_block->nominal_rate/60.0, alpha, accel);
Michael J. Spencer 1:f5ac63519541 245 c_min = c0 * (sqrt(accel_until+1.0)-sqrt((float)accel_until));
Michael J. Spencer 1:f5ac63519541 246 accel_until = accel_until - n;
Michael J. Spencer 1:f5ac63519541 247
Michael J. Spencer 1:f5ac63519541 248 decel_n = - calc_n (current_block->nominal_rate/60.0, alpha, accel);
Michael J. Spencer 1:f5ac63519541 249 decel_after = current_block->step_event_count + decel_n + calc_n (current_block->final_rate/60.0, alpha, accel);
Michael J. Spencer 1:f5ac63519541 250
Michael J. Spencer 1:f5ac63519541 251 if (decel_after < accel_until)
Michael J. Spencer 1:f5ac63519541 252 {
Michael J. Spencer 1:f5ac63519541 253 decel_after = (decel_after + accel_until) / 2;
Michael J. Spencer 1:f5ac63519541 254 decel_n = decel_after - current_block->step_event_count - calc_n (current_block->final_rate/60.0, alpha, accel);
Michael J. Spencer 1:f5ac63519541 255 }
Michael J. Spencer 1:f5ac63519541 256 current_block->decelerate_after = decel_after;
Michael J. Spencer 1:f5ac63519541 257
Michael J. Spencer 1:f5ac63519541 258 c = to_fixed(c);
Michael J. Spencer 1:f5ac63519541 259 c_min = to_fixed (c_min);
Michael J. Spencer 1:f5ac63519541 260 #undef alpha
Michael J. Spencer 1:f5ac63519541 261 }
Michael J. Spencer 1:f5ac63519541 262
Michael J. Spencer 1:f5ac63519541 263
Michael J. Spencer 1:f5ac63519541 264 // get step rate (steps/min) from time cycles
Michael J. Spencer 1:f5ac63519541 265 //static inline uint32_t get_step_rate (uint64_t cycles)
Michael J. Spencer 1:f5ac63519541 266 //{
Michael J. Spencer 1:f5ac63519541 267 // return (TICKS_PER_MICROSECOND*1000000*6) / cycles * 10;
Michael J. Spencer 1:f5ac63519541 268 //}
Michael J. Spencer 1:f5ac63519541 269
Michael J. Spencer 1:f5ac63519541 270 // Set the step timer. Note: this starts the ticker at an interval of "cycles"
Michael J. Spencer 1:f5ac63519541 271 static inline void set_step_timer (uint32_t cycles)
Michael J. Spencer 1:f5ac63519541 272 {
Michael J. Spencer 1:f5ac63519541 273 volatile static double p;
Michael J. Spencer 1:f5ac63519541 274 timer.attach_us(&st_interrupt,cycles);
Michael J. Spencer 1:f5ac63519541 275 // p = to_double(pwmofs + mul_f( pwmscale, ((power>>6) * c_min) / ((10000>>6)*cycles) ) );
Michael J. Spencer 1:f5ac63519541 276 // p = ( to_double(c_min) * current_block->power) / ( 10000.0 * (double)cycles);
Michael J. Spencer 1:f5ac63519541 277 // p = (60E6/nominal_rate) / cycles; // nom_rate is steps/minute,
Michael J. Spencer 1:f5ac63519541 278 //printf("%f,%f,%f\n\r", (float)(60E6/nominal_rate), (float)cycles, (float)p);
Michael J. Spencer 1:f5ac63519541 279 // printf("%d: %f %f\n\r", (int)current_block->power, (float)p, (float)c_min/(float(c) ));
Michael J. Spencer 1:f5ac63519541 280 p = (double)(cfg->pwmmin/100.0 + ((current_block->power/10000.0)*((cfg->pwmmax - cfg->pwmmin)/100.0)));
Michael J. Spencer 1:f5ac63519541 281 pwm = p;
Michael J. Spencer 1:f5ac63519541 282 }
Michael J. Spencer 1:f5ac63519541 283
Michael J. Spencer 1:f5ac63519541 284 // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse of Grbl. It is executed at the rate set with
Michael J. Spencer 1:f5ac63519541 285 // set_step_timer. It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
Michael J. Spencer 1:f5ac63519541 286 // It is supported by The Stepper Port Reset Interrupt which it uses to reset the stepper port after each pulse.
Michael J. Spencer 1:f5ac63519541 287 // The bresenham line tracer algorithm controls all three stepper outputs simultaneously with these two interrupts.
Michael J. Spencer 1:f5ac63519541 288 static void st_interrupt (void)
Michael J. Spencer 1:f5ac63519541 289 {
Michael J. Spencer 1:f5ac63519541 290 // TODO: Check if the busy-flag can be eliminated by just disabeling this interrupt while we are in it
Michael J. Spencer 1:f5ac63519541 291
Michael J. Spencer 1:f5ac63519541 292 if(busy){ /*printf("busy!\n"); */ return; } // The busy-flag is used to avoid reentering this interrupt
Michael J. Spencer 1:f5ac63519541 293 busy = 1;
Michael J. Spencer 1:f5ac63519541 294
Michael J. Spencer 1:f5ac63519541 295 // Set the direction pins a cuple of nanoseconds before we step the steppers
Michael J. Spencer 1:f5ac63519541 296 //STEPPING_PORT = (STEPPING_PORT & ~DIRECTION_MASK) | (out_bits & DIRECTION_MASK);
Michael J. Spencer 1:f5ac63519541 297 // set_direction_pins (out_bits);
Michael J. Spencer 1:f5ac63519541 298
Michael J. Spencer 1:f5ac63519541 299 // Then pulse the stepping pins
Michael J. Spencer 1:f5ac63519541 300 //STEPPING_PORT = (STEPPING_PORT & ~STEP_MASK) | out_bits;
Michael J. Spencer 1:f5ac63519541 301 // led2 = 1;
Michael J. Spencer 1:f5ac63519541 302 set_step_pins (step_bits ^ step_inv);
Michael J. Spencer 1:f5ac63519541 303
Michael J. Spencer 1:f5ac63519541 304 // If there is no current block, attempt to pop one from the buffer
Michael J. Spencer 1:f5ac63519541 305 if (current_block == NULL)
Michael J. Spencer 1:f5ac63519541 306 {
Michael J. Spencer 1:f5ac63519541 307 // Anything in the buffer?
Michael J. Spencer 1:f5ac63519541 308 current_block = plan_get_current_block();
Michael J. Spencer 1:f5ac63519541 309 if (current_block != NULL) {
Michael J. Spencer 1:f5ac63519541 310 trapezoid_generator_reset();
Michael J. Spencer 1:f5ac63519541 311 counter_x = -(current_block->step_event_count >> 1);
Michael J. Spencer 1:f5ac63519541 312 counter_y = counter_x;
Michael J. Spencer 1:f5ac63519541 313 counter_z = counter_x;
Michael J. Spencer 1:f5ac63519541 314 counter_e = counter_x;
Michael J. Spencer 1:f5ac63519541 315 counter_l = counter_x;
Michael J. Spencer 1:f5ac63519541 316 pos_l = 0; // reset laser bitmap counter
Michael J. Spencer 1:f5ac63519541 317 step_events_completed = 0;
Michael J. Spencer 1:f5ac63519541 318 direction_bits = current_block->direction_bits ^ direction_inv;
Michael J. Spencer 1:f5ac63519541 319 set_direction_pins ();
Michael J. Spencer 1:f5ac63519541 320 step_bits = 0;
Michael J. Spencer 1:f5ac63519541 321 }
Michael J. Spencer 1:f5ac63519541 322 else
Michael J. Spencer 1:f5ac63519541 323 {
Michael J. Spencer 1:f5ac63519541 324 st_go_idle();
Michael J. Spencer 1:f5ac63519541 325 }
Michael J. Spencer 1:f5ac63519541 326 }
Michael J. Spencer 1:f5ac63519541 327
Michael J. Spencer 1:f5ac63519541 328 // process the current block
Michael J. Spencer 1:f5ac63519541 329 if (current_block != NULL)
Michael J. Spencer 1:f5ac63519541 330 {
Michael J. Spencer 1:f5ac63519541 331
Michael J. Spencer 1:f5ac63519541 332 // this block is a bitmap engraving line, read laser on/off status from buffer
Michael J. Spencer 1:f5ac63519541 333 if ( current_block->options & OPT_BITMAP )
Michael J. Spencer 1:f5ac63519541 334 {
Michael J. Spencer 1:f5ac63519541 335 *laser = ! (bitmap[pos_l / 32] & (1 << (pos_l % 32)));
Michael J. Spencer 1:f5ac63519541 336 counter_l += bitmap_width;
Michael J. Spencer 1:f5ac63519541 337 // printf("%d %d %d: %d %d %c\n\r", bitmap_width, pos_l, counter_l, pos_l / 32, pos_l % 32, (*laser ? '1' : '0' ));
Michael J. Spencer 1:f5ac63519541 338 if (counter_l > 0)
Michael J. Spencer 1:f5ac63519541 339 {
Michael J. Spencer 1:f5ac63519541 340 counter_l -= current_block->step_event_count;
Michael J. Spencer 1:f5ac63519541 341 // putchar ( (*laser ? '1' : '0' ) );
Michael J. Spencer 1:f5ac63519541 342 pos_l++;
Michael J. Spencer 1:f5ac63519541 343 }
Michael J. Spencer 1:f5ac63519541 344 }
Michael J. Spencer 1:f5ac63519541 345 else
Michael J. Spencer 1:f5ac63519541 346 {
Michael J. Spencer 1:f5ac63519541 347 *laser = ( current_block->options & OPT_LASER_ON ? LASERON : LASEROFF);
Michael J. Spencer 1:f5ac63519541 348 }
Michael J. Spencer 1:f5ac63519541 349
Michael J. Spencer 1:f5ac63519541 350 if (current_block->action_type == AT_MOVE)
Michael J. Spencer 1:f5ac63519541 351 {
Michael J. Spencer 1:f5ac63519541 352 // Execute step displacement profile by bresenham line algorithm
Michael J. Spencer 1:f5ac63519541 353 step_bits = 0;
Michael J. Spencer 1:f5ac63519541 354 counter_x += current_block->steps_x;
Michael J. Spencer 1:f5ac63519541 355 if (counter_x > 0) {
Michael J. Spencer 1:f5ac63519541 356 actpos_x += ( (current_block->direction_bits & (1<<X_DIRECTION_BIT))? -1 : 1 );
Michael J. Spencer 1:f5ac63519541 357 step_bits |= (1<<X_STEP_BIT);
Michael J. Spencer 1:f5ac63519541 358 counter_x -= current_block->step_event_count;
Michael J. Spencer 1:f5ac63519541 359 }
Michael J. Spencer 1:f5ac63519541 360 counter_y += current_block->steps_y;
Michael J. Spencer 1:f5ac63519541 361 if (counter_y > 0) {
Michael J. Spencer 1:f5ac63519541 362 actpos_y += ( (current_block->direction_bits & (1<<Y_DIRECTION_BIT))? -1 : 1 );
Michael J. Spencer 1:f5ac63519541 363 step_bits |= (1<<Y_STEP_BIT);
Michael J. Spencer 1:f5ac63519541 364 counter_y -= current_block->step_event_count;
Michael J. Spencer 1:f5ac63519541 365 }
Michael J. Spencer 1:f5ac63519541 366 counter_z += current_block->steps_z;
Michael J. Spencer 1:f5ac63519541 367 if (counter_z > 0) {
Michael J. Spencer 1:f5ac63519541 368 actpos_z += ( (current_block->direction_bits & (1<<Z_DIRECTION_BIT))? -1 : 1 );
Michael J. Spencer 1:f5ac63519541 369 step_bits |= (1<<Z_STEP_BIT);
Michael J. Spencer 1:f5ac63519541 370 counter_z -= current_block->step_event_count;
Michael J. Spencer 1:f5ac63519541 371 }
Michael J. Spencer 1:f5ac63519541 372
Michael J. Spencer 1:f5ac63519541 373 counter_e += current_block->steps_e;
Michael J. Spencer 1:f5ac63519541 374 if (counter_e > 0) {
Michael J. Spencer 1:f5ac63519541 375 actpos_e += ( (current_block->direction_bits & (1<<E_DIRECTION_BIT))? -1 : 1 );
Michael J. Spencer 1:f5ac63519541 376 step_bits |= (1<<E_STEP_BIT);
Michael J. Spencer 1:f5ac63519541 377 counter_e -= current_block->step_event_count;
Michael J. Spencer 1:f5ac63519541 378 }
Michael J. Spencer 1:f5ac63519541 379
Michael J. Spencer 1:f5ac63519541 380 //clear_step_pins (); // clear the pins, assume that we spend enough CPU cycles in the previous statements for the steppers to react (>1usec)
Michael J. Spencer 1:f5ac63519541 381 step_events_completed++; // Iterate step events
Michael J. Spencer 1:f5ac63519541 382
Michael J. Spencer 1:f5ac63519541 383 // This is a homing block, keep moving until all end-stops are triggered
Michael J. Spencer 1:f5ac63519541 384 if (current_block->check_endstops)
Michael J. Spencer 1:f5ac63519541 385 {
Michael J. Spencer 1:f5ac63519541 386 if ( (current_block->steps_x && hit_home_stop_x (direction_bits & (1<<X_DIRECTION_BIT)) ) ||
Michael J. Spencer 1:f5ac63519541 387 (current_block->steps_y && hit_home_stop_y (direction_bits & (1<<Y_DIRECTION_BIT)) ) ||
Michael J. Spencer 1:f5ac63519541 388 (current_block->steps_z && hit_home_stop_z (direction_bits & (1<<Z_DIRECTION_BIT)) )
Michael J. Spencer 1:f5ac63519541 389 )
Michael J. Spencer 1:f5ac63519541 390 {
Michael J. Spencer 1:f5ac63519541 391 step_events_completed = current_block->step_event_count;
Michael J. Spencer 1:f5ac63519541 392 step_bits = 0;
Michael J. Spencer 1:f5ac63519541 393 }
Michael J. Spencer 1:f5ac63519541 394 }
Michael J. Spencer 1:f5ac63519541 395
Michael J. Spencer 1:f5ac63519541 396
Michael J. Spencer 1:f5ac63519541 397 // While in block steps, update acceleration profile
Michael J. Spencer 1:f5ac63519541 398 if (step_events_completed < current_block->step_event_count)
Michael J. Spencer 1:f5ac63519541 399 {
Michael J. Spencer 1:f5ac63519541 400 tFixedPt new_c;
Michael J. Spencer 1:f5ac63519541 401
Michael J. Spencer 1:f5ac63519541 402 switch (ramp)
Michael J. Spencer 1:f5ac63519541 403 {
Michael J. Spencer 1:f5ac63519541 404 case RAMP_UP:
Michael J. Spencer 1:f5ac63519541 405 {
Michael J. Spencer 1:f5ac63519541 406 new_c = c - (c<<1) / (4*n+1);
Michael J. Spencer 1:f5ac63519541 407 if (step_events_completed >= current_block->decelerate_after)
Michael J. Spencer 1:f5ac63519541 408 {
Michael J. Spencer 1:f5ac63519541 409 ramp = RAMP_DOWN;
Michael J. Spencer 1:f5ac63519541 410 n = decel_n;
Michael J. Spencer 1:f5ac63519541 411 }
Michael J. Spencer 1:f5ac63519541 412 else if (new_c <= c_min)
Michael J. Spencer 1:f5ac63519541 413 {
Michael J. Spencer 1:f5ac63519541 414 new_c = c_min;
Michael J. Spencer 1:f5ac63519541 415 ramp = RAMP_MAX;
Michael J. Spencer 1:f5ac63519541 416 }
Michael J. Spencer 1:f5ac63519541 417
Michael J. Spencer 1:f5ac63519541 418 if (to_int(new_c) != to_int(c))
Michael J. Spencer 1:f5ac63519541 419 {
Michael J. Spencer 1:f5ac63519541 420 set_step_timer (to_int(new_c));
Michael J. Spencer 1:f5ac63519541 421 }
Michael J. Spencer 1:f5ac63519541 422 c = new_c;
Michael J. Spencer 1:f5ac63519541 423 }
Michael J. Spencer 1:f5ac63519541 424 break;
Michael J. Spencer 1:f5ac63519541 425
Michael J. Spencer 1:f5ac63519541 426 case RAMP_MAX:
Michael J. Spencer 1:f5ac63519541 427 if (step_events_completed >= current_block->decelerate_after)
Michael J. Spencer 1:f5ac63519541 428 {
Michael J. Spencer 1:f5ac63519541 429 ramp = RAMP_DOWN;
Michael J. Spencer 1:f5ac63519541 430 n = decel_n;
Michael J. Spencer 1:f5ac63519541 431 }
Michael J. Spencer 1:f5ac63519541 432 break;
Michael J. Spencer 1:f5ac63519541 433
Michael J. Spencer 1:f5ac63519541 434 case RAMP_DOWN:
Michael J. Spencer 1:f5ac63519541 435 new_c = c - (c<<1) / (4*n+1);
Michael J. Spencer 1:f5ac63519541 436 if (to_int(new_c) != to_int(c))
Michael J. Spencer 1:f5ac63519541 437 {
Michael J. Spencer 1:f5ac63519541 438 set_step_timer (to_int(c));
Michael J. Spencer 1:f5ac63519541 439 }
Michael J. Spencer 1:f5ac63519541 440 c = new_c;
Michael J. Spencer 1:f5ac63519541 441 break;
Michael J. Spencer 1:f5ac63519541 442 }
Michael J. Spencer 1:f5ac63519541 443
Michael J. Spencer 1:f5ac63519541 444 n++;
Michael J. Spencer 1:f5ac63519541 445 } else {
Michael J. Spencer 1:f5ac63519541 446 // If current block is finished, reset pointer
Michael J. Spencer 1:f5ac63519541 447 current_block = NULL;
Michael J. Spencer 1:f5ac63519541 448 plan_discard_current_block();
Michael J. Spencer 1:f5ac63519541 449 }
Michael J. Spencer 1:f5ac63519541 450 }
Michael J. Spencer 1:f5ac63519541 451 }
Michael J. Spencer 1:f5ac63519541 452 else
Michael J. Spencer 1:f5ac63519541 453 {
Michael J. Spencer 1:f5ac63519541 454 // Still no block? Set the stepper pins to low before sleeping.
Michael J. Spencer 1:f5ac63519541 455 // printf("block == NULL\n");
Michael J. Spencer 1:f5ac63519541 456 step_bits = 0;
Michael J. Spencer 1:f5ac63519541 457 }
Michael J. Spencer 1:f5ac63519541 458
Michael J. Spencer 1:f5ac63519541 459 clear_all_step_pins (); // clear the pins, assume that we spend enough CPU cycles in the previous statements for the steppers to react (>1usec)
Michael J. Spencer 1:f5ac63519541 460 busy=0;
Michael J. Spencer 1:f5ac63519541 461
Michael J. Spencer 1:f5ac63519541 462 }
Michael J. Spencer 1:f5ac63519541 463
Michael J. Spencer 1:f5ac63519541 464
Michael J. Spencer 1:f5ac63519541 465 // Block until all buffered steps are executed
Michael J. Spencer 1:f5ac63519541 466 void st_synchronize()
Michael J. Spencer 1:f5ac63519541 467 {
Michael J. Spencer 1:f5ac63519541 468 while(plan_get_current_block()) { sleep_mode(); }
Michael J. Spencer 1:f5ac63519541 469 }
Michael J. Spencer 1:f5ac63519541 470