Mattroberts' Firmware
Revision as of 14:18, 19 May 2011 by Mattroberts (talk | contribs) (Created page with '{{Development |status = Beta |description = Firmware |license = [http://creativecommons.org/licenses/by/3.0/ CC-by-3.0] |author = Mattroberts |reprap = Mendel }} == Introduction…')
Mattroberts' Firmware
Release status: Beta
Description | Firmware
|
License | |
Author | |
Contributors | |
Based-on | |
Categories | |
CAD Models | |
External Link |
Introduction
This page will describe my firmware. At the moment it just contains my acceleration / extruder code. The licence for this code sample is CC-by-3.0. The extruder pressure code is in red. The acceleration code is in green.
Config.h
// X and Y are direct drive... // 16 * 200 steps per revolution, 10 teeth, 5.08mm per tooth // 16 * 200 / 10 / 5.08 = 62.992126 steps per mm #define STEPS_PER_MM_X 62.992126 #define STEPS_PER_MM_Y 62.992126 // Z is geared... // drive gear: 16 * 200 steps per revolution, 10 teeth // driven gear: 25 teeth, 1.25 mm per revolution (M8 pitch) // 16 * 200 / 10 * 25 / 1.25 = 6400 steps per mm #define STEPS_PER_MM_Z 6400 // E... #define STEPS_PER_CUBIC_MM_E 180 #define INIT_EXTRUSION_AREA (0.465 * 0.31) // extruder advance constant (s2/mm3) // // advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 // // hooke's law says: force = k * distance // bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant // so: v ^ 2 is proportional to number of steps we advance the extruder #define EXTRUDER_ADVANCE_K 0.019 // feedrates (mm/min) #define INIT_FEEDRATE_MM 4000 #define HOME_FEEDRATE_MM_XY 4000 #define HOME_FEEDRATE_MM_Z 150 #define MIN_FEEDRATE_MM 30 // acceleration (mm/min/s) #define ACCELERATION 150000L // steppers to disable after every move #define AUTO_DISABLE_X 0 #define AUTO_DISABLE_Y 0 #define AUTO_DISABLE_Z 1 #define AUTO_DISABLE_E 0 // stepper directions #define INVERT_X 1 #define INVERT_Y 1 #define INVERT_Z 0 #define INVERT_E 0 // minimum stepper pulse widths (us) #define STEP_HIGH_US 1 #define STEP_LOW_US 1 // thermistor // +ve --- R2 -+- THERMISTOR -+- gnd // | | // adc --------+----- R1 -----+ #define THERMISTOR_R0_OHMS 100000 #define THERMISTOR_T0_DEG_C 25 #define THERMISTOR_BETA 4036 #define THERMISTOR_R1_OHMS 0 // 0 means missing #define THERMISTOR_R2_OHMS 4500 // comms #define UART_BAUD 115200
dda.c
#include <stdint.h> #include "config.h" #include "convert.h" #include "dda.h" #include "delay.h" #include "dist.h" #include "motor.h" #include "state.h" #include "uart.h" #ifdef DEBUG #undef DEBUG #define DEBUG(...) __VA_ARGS__ #else #define DEBUG(...) #endif #define q_n 32 // must be a power of 2 #define STATE_IDLE 2 #define STATE_IDLE_SPEEDCHANGE 0 #define STATE_SPEEDCHANGE 1 #define STATE_DDA 3 #define STATE_XYZ 4 #define STATE_E 5 #define STATE_T 6 static struct dda { int32_t delta[5], d, f, max_xyze; } q[q_n]; static uint8_t q_h, q_t; static int32_t steps_left = -1; DEBUG(static int32_t count[5];) static int32_t current_f, step_decel; static int32_t max(int32_t a, int32_t b) { return a > b ? a : b; } void dda_q(int32_t *fxyze) { int32_t d; while (q_h == q_t && steps_left != -1) dda_tick(); DEBUG(uart_puts("dda_q"); FOREACH_XYZE(i) { uart_puts(" "); uart_puti(fxyze[i]); } uart_puts(" f"); uart_putd(fxyze[F]); uart_putc('\n');) if (fxyze[X] == 0 && fxyze[Y] == 0 && fxyze[Z] == 0) { if (fxyze[E] == 0 || fxyze[E] == UNSEEN) return; d = convert(fxyze[E], INV_E); if (d < 0) d = -d; } else { d = dist_steps(fxyze); if (fxyze[E] == UNSEEN) fxyze[E] = convert(d, E); } dda_tick(); q[q_t].d = 293L * d; q[q_t].f = fxyze[F]; FOREACH_XYZE(i) { q[q_t].delta[i] = fxyze[i]; s.fxyze[i] += fxyze[i]; } DEBUG(uart_puts("d"); uart_putd(d); uart_puts(" e"); uart_puti(fxyze[E]); uart_puts("\n");) q_t = (q_t + 1) & (q_n - 1); } void dda_tick(void) { static int8_t state = STATE_IDLE; static int32_t delta[5], error[5], d, max_xyzet, max_xyze, max_f, e, advance, old_advance, extrusion_rate; switch(state++) { case STATE_IDLE: case STATE_IDLE_SPEEDCHANGE: if (q_h == q_t && steps_left == -1) { state = STATE_IDLE; return; } if (steps_left == 0) { delay_tick(0); DEBUG(uart_puts("dda_done"); FOREACH_XYZE(i) { uart_puts(" "); uart_puti(count[i]); count[i] = 0; } uart_puts(" "); uart_puti(count[T]); count[T] = 0; uart_puts("\n");) if (AUTO_DISABLE_X) motor_enable(X, 0); if (AUTO_DISABLE_Y) motor_enable(Y, 0); if (AUTO_DISABLE_Z) motor_enable(Z, 0); if (AUTO_DISABLE_E) motor_enable(E, 0); steps_left = -1; q_h = (q_h + 1) & (q_n - 1); if (q_h == q_t) { state = STATE_IDLE; return; } } if (steps_left == -1) { delay_tick(0); FOREACH_TXYZE(i) { delta[i] = q[q_h].delta[i]; error[i] = 0; } max_f = q[q_h].f; d = q[q_h].d; max_xyzet = 0; max_xyze = 0; steps_left = 0; FOREACH_XYZE(i) { motor_dir(i, delta[i] >= 0); if (delta[i] < 0) delta[i] = -delta[i]; if (delta[i] != 0) motor_enable(i, 1); steps_left += delta[i]; if (max_xyze < delta[i]) max_xyze = delta[i]; } motor_dir(E, 1); step_decel = steps_left / 2; current_f = MIN_FEEDRATE_MM * 10000L; state = STATE_SPEEDCHANGE; } return; case STATE_SPEEDCHANGE: state = STATE_DDA; delta[T] = d / (current_f >> 11); { int32_t a = max_xyzet; max_xyzet = max(max_xyze, delta[T]); a -= max_xyzet; a /= 2; FOREACH_TXYZE(i) error[i] += a; } return; case STATE_DDA: FOREACH_TXYZE(a) error[a] += delta[a]; return; case STATE_XYZ: FOREACH_XYZ(a) if (error[a] > 0) { error[a] -= max_xyzet; DEBUG(count[a]++); motor_step(a); steps_left--; } return; case STATE_E: e = 0; if (error[E] > 0) { error[E] -= max_xyzet; DEBUG(count[E]++); e++; steps_left--; } extrusion_rate = current_f / 600000L; extrusion_rate *= s.extrusion_area; if (delta[E]) advance = (int32_t)(STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * extrusion_rate * extrusion_rate / 10000L; else advance = 0; e += advance - old_advance; old_advance = advance; if (e != 0) { if (e < 0) { motor_dir(E, 0); e = -e; } while (e-- > 0) { motor_step(E); motor_step_done(); } motor_dir(E, 1); } motor_step_done(); return; case STATE_T: state = STATE_IDLE; if (error[T] > 0) { error[T] -= max_xyzet; DEBUG(count[T]++); delay_tick(1); if (steps_left < step_decel) { if (current_f > MIN_FEEDRATE_MM * 10000L) { current_f -= ACCELERATION; if (current_f < MIN_FEEDRATE_MM * 10000L) current_f = MIN_FEEDRATE_MM * 10000L; state = STATE_IDLE_SPEEDCHANGE; } } else if (current_f < max_f) { current_f += ACCELERATION; if (current_f >= max_f) { current_f = max_f; step_decel = step_decel * 2 - steps_left; } state = STATE_IDLE_SPEEDCHANGE; } } return; } } void dda_drain(void) { while (steps_left != -1) dda_tick(); }