diff --git a/mendel/arduino.h b/mendel/arduino.h index cd60eb9..3da3c6e 100644 --- a/mendel/arduino.h +++ b/mendel/arduino.h @@ -3,6 +3,31 @@ #include +/* + utility functions +*/ + +#ifndef MASK +#define MASK(PIN) (1 << PIN) +#endif + +#define _READ(IO) (RPORT_ ## IO & MASK(PIN_ ## IO)) +#define _WRITE(IO, v) if (v) { WPORT_ ## IO |= MASK(PIN_ ## IO); } else { WPORT_ ## IO &= ~MASK(PIN_ ## IO); } + +#define _SET_INPUT(IO) (DDR_ ## IO |= MASK(PIN_ ## IO)) +#define _SET_OUTPUT(IO) (DDR_ ## IO &= ~MASK(PIN_ ## IO)) + +// why double up on macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html + +#define READ(IO) _READ(IO) +#define WRITE(IO, v) _WRITE(IO, v) +#define SET_INPUT(IO) _SET_INPUT(IO) +#define SET_OUTPUT(IO) _SET_OUTPUT(IO) + +/* + pins +*/ + #define PIN_DIO0 PD0 #define RPORT_DIO0 PIND #define WPORT_DIO0 PORTD diff --git a/mendel/dda.c b/mendel/dda.c index e4c3aa8..aaa529e 100644 --- a/mendel/dda.c +++ b/mendel/dda.c @@ -2,6 +2,7 @@ #include +#include "pinout.h" #include "timer.h" extern struct { @@ -128,7 +129,8 @@ uint32_t approx_distance_3( int32_t dx, int32_t dy, int32_t dz ) */ void dda_create(TARGET *target, DDA *dda) { - static TARGET startpoint = { 0, 0, 0, 0, 0 }; + static TARGET startpoint = { 0, 0, 0, 0, 0 }; + uint32_t distance; // we start at the previous endpoint // memcpy(&dda->currentpoint, &startpoint, sizeof(TARGET)); @@ -145,16 +147,16 @@ void dda_create(TARGET *target, DDA *dda) { // since it's unusual to combine X, Y and Z changes in a single move on reprap, check if we can use simpler approximations before trying the full 3d approximation. if (dda->z_delta == 0) - dda->distance = approx_distance(dda->x_delta, dda->y_delta); + distance = approx_distance(dda->x_delta, dda->y_delta); else if (dda->x_delta == 0 && dda->y_delta == 0) - dda->distance = dda->z_delta; + distance = dda->z_delta; else - dda->distance = approx_distance_3(dda->x_delta, dda->y_delta, dda->z_delta); + distance = approx_distance_3(dda->x_delta, dda->y_delta, dda->z_delta); - if (dda->distance < 2) - dda->distance = dda->e_delta; - if (dda->distance < 2) - dda->distance = dda->f_delta; + if (distance < 2) + distance = dda->e_delta; + if (distance < 2) + distance = dda->f_delta; dda->total_steps = dda->x_delta; if (dda->y_delta > dda->total_steps) @@ -194,7 +196,7 @@ void dda_create(TARGET *target, DDA *dda) { // mm (distance) * 60000000 us/min / step (total_steps) = mm.us per step.min // so in the interrupt we must simply calculate // mm.us per step.min / mm per min (F) = us per step - dda->move_duration = dda->distance * 60000000 / dda->total_steps; + dda->move_duration = distance * 60000000 / dda->total_steps; // next dda starts where we finish memcpy(&startpoint, &dda->endpoint, sizeof(TARGET)); diff --git a/mendel/dda.h b/mendel/dda.h index 0c3b742..0491963 100644 --- a/mendel/dda.h +++ b/mendel/dda.h @@ -35,7 +35,6 @@ typedef struct { uint32_t total_steps; uint16_t f_scale; - uint32_t distance; uint32_t move_duration; } DDA; diff --git a/mendel/gcode.c b/mendel/gcode.c index b46b868..69029eb 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -4,6 +4,7 @@ #include "machine.h" #include "dda.h" +#include "serial.h" extern uint8_t option_bitfield; @@ -76,13 +77,8 @@ void scan_char(uint8_t c) { next_target.target.E = manexp_to_float(mantissa, exp) * STEPS_PER_MM_E; break; case 'F': - // TODO: calculate end speed in microseconds per step from millimeters per minute - // MM = sqrt(X^2 + Y^2) - // STEPS = max(X * STEPS_PER_MM_X, Y * STEPS_PER_MM_Y) - // DURATION = MM / MM_PER_MIN * 60 SEC_PER_MIN * 1000000 US_PER_SEC - // US/STEP = DURATION / STEPS - // intF = sqrt(X^2 + Y^2) / max(X * STEPS_PER_MM_X, Y * STEPS_PER_MM_Y) - next_target.target.F = manexp_to_float(mantissa, exp) * STEPS_PER_MM_F; + // just save an integer value for F, we need move distance and n_steps to convert it to a useful value, so wait until we have those to convert it + next_target.target.F = mantissa; break; } mantissa = 0; @@ -122,6 +118,8 @@ void scan_char(uint8_t c) { last_field = 0; memset(&next_target, 0, sizeof(GCODE_COMMAND)); next_target.option = option_bitfield; + + serial_writeblock((uint8_t *) "OK\n", 3); break; } } diff --git a/mendel/machine.h b/mendel/machine.h index c4804d9..c0dd3e9 100644 --- a/mendel/machine.h +++ b/mendel/machine.h @@ -4,7 +4,9 @@ /* machine variables */ + #define MOVEBUFFER_SIZE 8 + /* axis calculations, adjust as necessary */ @@ -17,27 +19,18 @@ #define EXTRUDER_INLET_DIAMETER 3 #define EXTRUDER_NOZZLE_DIAMETER 0.8 - #define STEPS_PER_MM_X (XY_STEPS_PER_REV * XY_COG_CIRCUMFERENCE) #define STEPS_PER_MM_Y (XY_STEPS_PER_REV * XY_COG_CIRCUMFERENCE) #define STEPS_PER_MM_Z (3200) #define STEPS_PER_MM_E (EXTRUDER_STEPS_PER_REV * EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER / EXTRUDER_NOZZLE_DIAMETER) -#define STEPS_PER_MM_PER_S_F (3200) - -#define STEPS_PER_MM_F STEPS_PER_MM_PER_S_F - /* - F is sent in units of millimeters per second - and implemented as microseconds per step - - MM/S * steps/mm * 1000000us/s = steps per microsecond + heater PID variables + used as int16_t * FACTOR so don't put brackets around them */ - -#define FAST_MM_PER_SEC 40 -#define SLOW_MM_PER_SEC 20 -#define ACCEL 10 - +#define P_FACTOR 133 / 1024 +#define I_FACTOR 17 / 1024 +#define D_FACTOR 180 / 1024 #endif /* _MACHINE_H */ diff --git a/mendel/pinout.h b/mendel/pinout.h index 8b69263..b92a169 100644 --- a/mendel/pinout.h +++ b/mendel/pinout.h @@ -3,58 +3,118 @@ #include "arduino.h" -#ifndef MASK -#define MASK(PIN) (1 << PIN) -#endif +/* + Machine Pin Definitions +*/ -#define READ(IO) (RPORT_ ## IO & MASK(PIN_ ## IO)) -#define WRITE(IO, v) if (v) { WPORT_ ## IO |= MASK(PIN_ ## IO); } else { WPORT_ ## IO &= ~MASK(PIN_ ## IO); } +// RXD DIO0 +// TXD DIO1 -#define SET_INPUT(IO) (DDR_ ## IO |= MASK(PIN_ ## IO)) -#define SET_OUTPUT(IO) (DDR_ ## IO &= ~MASK(PIN ## IO)) +#define X_STEP_PIN AIO0 +#define X_DIR_PIN AIO1 +#define X_MIN_PIN AIO2 -#define _x_step(st) WRITE(AIO0, st) +#define Y_STEP_PIN AIO3 +#define Y_DIR_PIN AIO4 +#define Y_MIN_PIN AIO5 + +#define Z_STEP_PIN DIO5 +#define Z_DIR_PIN DIO6 +#define Z_MIN_PIN DIO7 + +#define E_STEP_PIN DIO2 +#define E_DIR_PIN DIO3 + +// list of PWM-able pins +// OC0A DIO6 +// OC0B DIO5 +// OC1A DIO9 +// OC1B DIO10 +// OC2A DIO11 +// OC2B DIO3 + +#define HEATER_PIN DIO6 +#define HEATER_PIN_PWM OC0A + +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +/* + X Stepper +*/ + +#define _x_step(st) WRITE(X_STEP_PIN, st) #define x_step() _x_step(1); -#define x_direction(dir) WRITE(AIO1, dir) -#define x_min() READ(AIO2) -#ifdef MAX_ENDSTOPS -#define x_max() READ(AIO3) +#define x_direction(dir) WRITE(X_DIR_PIN, dir) +#define x_min() READ(X_MIN_PIN) +#ifdef X_MAX_PIN + #define x_max() READ(X_MAX_PIN) #else -#define x_max() (0) + #define x_max() (0) #endif -#define _y_step(st) WRITE(DIO2, st) +/* + Y Stepper +*/ + +#define _y_step(st) WRITE(Y_STEP_PIN, st) #define y_step() _y_step(1); -#define y_direction(dir) WRITE(DIO3, dir) -#define y_min() READ(DIO4) -#ifdef MAX_ENDSTOPS -#define y_max() READ(DIO5) +#define y_direction(dir) WRITE(Y_DIR_PIN, dir) +#define y_min() READ(Y_MIN_PIN) +#ifdef Y_MAX_PIN + #define y_max() READ(Y_MAX_PIN) #else -#define y_max() (0) + #define y_max() (0) #endif -#define _z_step(st) WRITE(DIO6, st) +/* + Z Stepper +*/ + +#define _z_step(st) WRITE(Z_STEP_PIN, st) #define z_step() _z_step(1); -#define z_direction(dir) WRITE(DIO7, dir) -#define z_min() READ(DIO8) -#ifdef MAX_ENDSTOPS -#define z_max() READ(DIO9) +#define z_direction(dir) WRITE(Z_DIR_PIN, dir) +#define z_min() READ(Z_MIN_PIN) +#ifdef Z_MAX_PIN + #define z_max() READ(Z_MAX_PIN) #else -#define z_max() (0) + #define z_max() (0) #endif -#define _e_step(st) WRITE(AIO4, st) +/* + Extruder +*/ + +#define _e_step(st) WRITE(E_STEP_PIN, st) #define e_step() _e_step(1); -#define e_direction(dir) WRITE(AIO5, dir) +#define e_direction(dir) WRITE(E_DIR_PIN, dir) -#define enable_steppers() WRITE(DIO10, 1) -#define disable_steppers() WRITE(DIO10, 0) +/* + Heater +*/ -inline void unstep(void) { - _x_step(0); - _y_step(0); - _z_step(0); - _e_step(0); -} +#define enable_heater() WRITE(HEATER_PIN, 1) +#define disable_heater() WRITE(HEATER_PIN, 0) + +/* + Stepper Enable (ATX PSU pwr_good signal?) +*/ + +#ifdef STEPPER_ENABLE_PIN + #define enable_steppers() WRITE(STEPPER_ENABLE_PIN, 1) + #define disable_steppers() WRITE(STEPPER_ENABLE_PIN, 0) +#else + #define enable_steppers() if (0) {} + #define disable_steppers() if (0) {} +#endif + +/* + End Step - All Steppers + (so we don't have to delay in interrupt context) +*/ + +#define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0) #endif /* _PINOUT_H */ diff --git a/mendel/temp.c b/mendel/temp.c new file mode 100644 index 0000000..4e3c2d5 --- /dev/null +++ b/mendel/temp.c @@ -0,0 +1,76 @@ +#include "temp.h" + +#include "machine.h" +#include "pinout.h" + +uint16_t current_temp; +uint16_t target_temp; + +int16_t heater_p; +int16_t heater_i; +int16_t heater_d; + +void temp_setup() { + SET_OUTPUT(SCK); + SET_INPUT(MISO); + SET_OUTPUT(SS); + + WRITE(SS, 0); + WRITE(SCK, 0); +} + +uint16_t temp_read() { + uint16_t temp; + SPCR = MASK(MSTR) | MASK(SPE); + + SPDR = 0; + for (;(SPSR & MASK(SPIF)) == 0;); + temp = SPDR << 8; + + SPDR = 0; + for (;(SPSR & MASK(SPIF)) == 0;); + temp |= SPDR; + + if ((temp & 0x8002) == 0) { + // got "device id" + if (temp & 4) { + // thermocouple open + } + else { + current_temp = temp >> 3; + return current_temp; + } + } + + return 0; +} + +void temp_set(uint16_t t) { + target_temp = t; +} + +void temp_tick() { + uint16_t last_temp = current_temp; + temp_read(); + + int16_t t_delta = target_temp - current_temp; + + // PID stuff + heater_p = t_delta; + heater_i += t_delta; + // note: D follows temp rather than error so there's no large derivative when the target temperature changes + heater_d = (current_temp - last_temp); + + int16_t pid_output = (heater_p * P_FACTOR) + (heater_i * I_FACTOR) + (heater_d * D_FACTOR); + +#ifdef HEATER_PIN_PWMABLE + HEATER_PIN_PWMABLE = pid_output +#else + if (pid_output > 0) { + enable_heater(); + } + else { + disable_heater(); + } +#endif +} diff --git a/mendel/temp.h b/mendel/temp.h new file mode 100644 index 0000000..217748a --- /dev/null +++ b/mendel/temp.h @@ -0,0 +1,11 @@ +#ifndef _TEMP_H +#define _TEMP_H + +#include + +void temp_setup(void); +uint16_t temp_read(void); +void temp_set(uint16_t t); +void temp_tick(void); + +#endif /* _TIMER_H */ diff --git a/mendel/timer.h b/mendel/timer.h index abe4960..542ec28 100644 --- a/mendel/timer.h +++ b/mendel/timer.h @@ -31,9 +31,6 @@ inline void disableTimerInterrupt(void) TIMSK1 &= ~(1<