From 4fc004c6c23d57c92141263188b67b301059678c Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 31 Jan 2010 14:52:32 +1100 Subject: [PATCH] It's alive! (cue evil cackle). still has some bugs, eg small movements with large delta F cause weirdness, queueing lots of moves end-to-end causes some to not execute but appear as complete in the queue --- mendel/Makefile | 5 +++-- mendel/arduino.h | 28 ++++++++++++++++++++++++ mendel/clock.c | 3 +++ mendel/clock.h | 5 +++-- mendel/dda.c | 46 +++++++++++++++++++++++++++++----------- mendel/dda.h | 2 ++ mendel/gcode.c | 6 +++--- mendel/gcode.h | 6 +++--- mendel/machine.h | 12 +++++------ mendel/mendel.c | 55 +++++++++++++++++++++++++++++++++++------------- mendel/pinout.h | 36 ++++++++++++++++++++++--------- mendel/temp.c | 2 ++ mendel/timer.c | 13 +++++++----- 13 files changed, 161 insertions(+), 58 deletions(-) diff --git a/mendel/Makefile b/mendel/Makefile index 5dc45dd..30c8a0a 100644 --- a/mendel/Makefile +++ b/mendel/Makefile @@ -32,7 +32,7 @@ F_CPU = 16000000L ############################################################################## ARCH = avr- -OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=0 +OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=1 # OPTIMIZE = -O0 CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(F_CPU) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps LDFLAGS = -Wl,--as-needed -Wl,--gc-sections @@ -54,9 +54,10 @@ all: $(PROGRAM).hex $(PROGRAM).lst size program: $(PROGRAM).hex stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT) + @sleep 0.2 @stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT) $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C/etc/avrdude.conf -U flash:w:$^ - stty -hup -echo < $(PROGPORT) + stty 57600 raw ignbrk -hup -echo < $(PROGPORT) clean: rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~ diff --git a/mendel/arduino.h b/mendel/arduino.h index 486908e..f4840d8 100644 --- a/mendel/arduino.h +++ b/mendel/arduino.h @@ -26,6 +26,34 @@ #define SET_INPUT(IO) _SET_INPUT(IO) #define SET_OUTPUT(IO) _SET_OUTPUT(IO) +/* + ports and functions +*/ + +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +// TWI (I2C) +#define SCL AIO5 +#define SDA AIO4 + +// timers and PWM +#define OC0A DIO6 +#define OC0B DIO5 +#define OC1A DIO9 +#define OC1B DIO10 +#define OC2A DIO11 +#define OC2B DIO3 + +#define ICP1 DIO8 + /* pins */ diff --git a/mendel/clock.c b/mendel/clock.c index 9eb9486..d1df4d6 100644 --- a/mendel/clock.c +++ b/mendel/clock.c @@ -10,6 +10,7 @@ #include #include "arduino.h" +#include "pinout.h" // global clock #ifdef GLOBAL_CLOCK @@ -38,6 +39,7 @@ void clock_setup() { } ISR(TIMER2_COMPA_vect) { +// WRITE(SCK, 0); // global clock #ifdef GLOBAL_CLOCK clock++; @@ -47,6 +49,7 @@ ISR(TIMER2_COMPA_vect) { clock_flag_250ms = 255; clock_counter_250ms = 0; } +// WRITE(SCK, 1); } #ifdef GLOBAL_CLOCK diff --git a/mendel/clock.h b/mendel/clock.h index a0a5b17..15d3d78 100644 --- a/mendel/clock.h +++ b/mendel/clock.h @@ -11,7 +11,8 @@ uint32_t clock_read(void); extern volatile uint8_t clock_flag_250ms; -#define CLOCK_FLAG_250MS_TEMPCHECK 1 -#define CLOCK_FLAG_250MS_REPORT 2 +#define CLOCK_FLAG_250MS_TEMPCHECK 1 +#define CLOCK_FLAG_250MS_REPORT 2 +#define CLOCL_FLAG_250MS_STEPTIMEOUT 4 #endif /* _CLOCK_H */ diff --git a/mendel/dda.c b/mendel/dda.c index fa98230..01c1a7b 100644 --- a/mendel/dda.c +++ b/mendel/dda.c @@ -18,6 +18,12 @@ #define DEBUG 0 #endif +/* + step timeout +*/ + +uint8_t steptimeout = 0; + /* move queue */ @@ -201,6 +207,7 @@ void dda_create(TARGET *target, DDA *dda) { dda->f_delta = dda->total_steps; } else { + // if we boost the number of steps here, many will only be F-steps which take no time- maybe we should calculate move_distance first? dda->f_scale = 1; dda->total_steps = dda->f_delta; } @@ -253,6 +260,10 @@ void dda_create(TARGET *target, DDA *dda) { // not running yet, we fire up in dda_start() dda->live = 0; + // get steppers ready to go + steptimeout = 0; + enable_steppers(); + // fire up enableTimerInterrupt(); } @@ -269,16 +280,18 @@ void dda_start(DDA *dda) { return; } + // set direction outputs x_direction(dda->x_direction); y_direction(dda->y_direction); z_direction(dda->z_direction); e_direction(dda->e_direction); + // ensure steppers are ready to go + steptimeout = 0; enable_steppers(); - dda->firstep = 1; - - dda->live = 1; + // set timeout for first step + setTimer(dda->move_duration / current_position.F); } /* @@ -321,9 +334,10 @@ void dda_step(DDA *dda) { #define REAL_MOVE 32 #define F_REAL_STEP 64 - WRITE(SCK, 1); - do { + WRITE(SCK, 0); + + step_option = 0; // step_option |= can_step(x_min(), x_max(), current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP; // step_option |= can_step(y_min(), y_max(), current_position.Y, dda->endpoint.Y, dda->y_direction) & Y_CAN_STEP; // step_option |= can_step(z_min(), z_max(), current_position.Z, dda->endpoint.Z, dda->z_direction) & Z_CAN_STEP; @@ -417,7 +431,7 @@ void dda_step(DDA *dda) { } } - if (DEBUG) { + if (0 && DEBUG) { serial_writechar('['); serwrite_hex8(step_option); serial_writechar(':'); @@ -430,20 +444,28 @@ void dda_step(DDA *dda) { serwrite_uint32(dda->move_duration); serial_writechar(']'); } + + WRITE(SCK, 1); + } while ( ((step_option & REAL_MOVE ) == 0) && ((step_option & F_CAN_STEP) != 0) ); // turn off step outputs, hopefully they've been on long enough by now to register with the drivers unstep(); - // we have stepped in speed and now need to recalculate our delay - if (((step_option & REAL_MOVE) && (step_option & F_REAL_STEP)) || (dda->firstep)) { - setTimer(dda->move_duration / current_position.F); - dda->firstep = 0; + if (step_option & REAL_MOVE) { + // we stepped, reset timeout + steptimeout = 0; + + // we have stepped in speed and now need to recalculate our delay + // WARNING: this is a divide in interrupt context! (which unfortunately seems unavoidable) + // we simply don't have the memory to precalculate this for each step, + // can't use a simplified process because the denominator changes rather than the numerator so the curve is non-linear + // and don't have a process framework to force it to be done outside interrupt context within a usable period of time + if (step_option & F_REAL_STEP) + setTimer(dda->move_duration / current_position.F); } // if we could step, we're still running dda->live = (step_option & (X_CAN_STEP | Y_CAN_STEP | Z_CAN_STEP | E_CAN_STEP | F_CAN_STEP))?1:0; - - WRITE(SCK, 0); } diff --git a/mendel/dda.h b/mendel/dda.h index 368c693..04c088c 100644 --- a/mendel/dda.h +++ b/mendel/dda.h @@ -51,6 +51,8 @@ extern DDA movebuffer[MOVEBUFFER_SIZE]; extern TARGET startpoint; extern TARGET current_position; +extern uint8_t steptimeout; + uint8_t queue_full(void); uint8_t queue_empty(void); void enqueue(TARGET *t); diff --git a/mendel/gcode.c b/mendel/gcode.c index 9af2f93..2f1a7d4 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -45,7 +45,7 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) if (df->sign) r = -r; - // exponent- try to keep divides to a minimum at expense of slightly more code + // exponent- try to keep divides to a minimum for common (small) values at expense of slightly more code while (e >= 5) { r /= 100000; e -= 5; @@ -126,8 +126,8 @@ void scan_char(uint8_t c) { serwrite_uint32(next_target.target.E); break; case '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 = read_digit.mantissa; + // just use raw integer, 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 = decfloat_to_int(&read_digit, 1, 1); serwrite_uint32(next_target.target.F); break; case 'S': diff --git a/mendel/gcode.h b/mendel/gcode.h index 0db0018..29aab4b 100644 --- a/mendel/gcode.h +++ b/mendel/gcode.h @@ -6,9 +6,9 @@ #include "dda.h" typedef struct { - uint16_t sign :1; - uint16_t mantissa :11; - uint16_t exponent :4; + uint32_t sign :1; + uint32_t mantissa :24; + uint32_t exponent :7; } decfloat; typedef struct { diff --git a/mendel/machine.h b/mendel/machine.h index 7853ffd..2285f1e 100644 --- a/mendel/machine.h +++ b/mendel/machine.h @@ -12,7 +12,7 @@ axis calculations, adjust as necessary */ -#define X_STEPS_PER_REV 1600.0 +#define X_STEPS_PER_REV 3200.0 #define Y_STEPS_PER_REV X_STEPS_PER_REV // we need more speed than precision on Z, turn off microstepping #define Z_STEPS_PER_REV 200.0 @@ -26,7 +26,7 @@ // #define XY_COG_CIRCUMFERENCE (XY_COG_RADIUS * PI * 2) #define Z_GEAR_RATIO 1.0 -#define EXTRUDER_STEPS_PER_REV 3200.0 +#define EXTRUDER_STEPS_PER_REV E_STEPS_PER_REV #define EXTRUDER_SHAFT_RADIUS 5.0 #define EXTRUDER_INLET_DIAMETER 3.0 #define EXTRUDER_NOZZLE_DIAMETER 0.8 @@ -40,10 +40,10 @@ // does this refer to filament or extrudate? extrudate depends on layer thickness.. hm #define STEPS_PER_MM_E ((uint32_t) ((EXTRUDER_STEPS_PER_REV / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER / EXTRUDER_NOZZLE_DIAMETER)) + 0.5)) -#define FEEDRATE_FAST_XY 2400 -#define FEEDRATE_SLOW_XY 120 -#define FEEDRATE_FAST_Z 240 -#define FEEDRATE_SLOW_Z 12 +#define FEEDRATE_FAST_XY 6000 +#define FEEDRATE_SLOW_XY 300 +#define FEEDRATE_FAST_Z 6000 +#define FEEDRATE_SLOW_Z 300 #define E_STARTSTOP_STEPS 20 #define FEEDRATE_FAST_E 1200 diff --git a/mendel/mendel.c b/mendel/mendel.c index f34426e..cbc9d12 100644 --- a/mendel/mendel.c +++ b/mendel/mendel.c @@ -19,14 +19,7 @@ #define DEBUG 0 #endif -int main (void) -{ - uint8_t report; - - // set up serial - serial_init(); - - // set up inputs and outputs +inline void io_init(void) { WRITE(X_STEP_PIN, 0); SET_OUTPUT(X_STEP_PIN); WRITE(X_DIR_PIN, 0); SET_OUTPUT(X_DIR_PIN); WRITE(X_MIN_PIN, 1); SET_INPUT(X_MIN_PIN); @@ -42,15 +35,29 @@ int main (void) WRITE(E_STEP_PIN, 0); SET_OUTPUT(E_STEP_PIN); WRITE(E_DIR_PIN, 0); SET_OUTPUT(E_DIR_PIN); - WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN); - - #ifdef FAN_PIN - WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN); + #ifdef HEATER_PIN + disable_heater(); SET_OUTPUT(HEATER_PIN); #endif - WRITE(SCK, 0); SET_OUTPUT(SCK); - WRITE(MISO, 1); SET_INPUT(MISO); - WRITE(SS, 0); SET_OUTPUT(SS); + #ifdef FAN_PIN + disable_fan(); SET_OUTPUT(FAN_PIN); + #endif + + #ifdef STEPPER_ENABLE_PIN + disable_steppers(); SET_OUTPUT(STEPPER_ENABLE_PIN); + #endif + + WRITE(SCK, 1); SET_OUTPUT(SCK); + WRITE(MISO, 1); SET_INPUT(MISO); + WRITE(SS, 0); SET_OUTPUT(SS); +} + +inline void init(void) { + // set up serial + serial_init(); + + // set up inputs and outputs + io_init(); // set up timers setupTimerInterrupt(); @@ -66,6 +73,13 @@ int main (void) // start queue //enableTimerInterrupt(); +} + +int main (void) +{ + uint8_t report; + + init(); // main loop for (;;) @@ -81,6 +95,17 @@ int main (void) temp_tick(); } + if (clock_flag_250ms & CLOCK_FLAG_250MS_STEPTIMEOUT) { + clock_flag_250ms &= ~CLOCK_FLAG_250MS_STEPTIMEOUT; + + if (steptimeout > 25) { + disable_steppers(); + } + else { + steptimeout++; + } + } + if (clock_flag_250ms & CLOCK_FLAG_250MS_REPORT) { clock_flag_250ms &= ~CLOCK_FLAG_250MS_REPORT; report++; diff --git a/mendel/pinout.h b/mendel/pinout.h index c11e928..0465ffd 100644 --- a/mendel/pinout.h +++ b/mendel/pinout.h @@ -12,8 +12,14 @@ we NEED these for communication */ -// RXD DIO0 -// TXD DIO1 +#define RESERVED_RXD DIO0 +#define RESERVED_TXD DIO1 + +/* + user defined pins + adjust to suit your electronics, + or adjust your electronics to suit this +*/ #define X_STEP_PIN AIO0 #define X_DIR_PIN AIO1 @@ -30,7 +36,10 @@ #define E_STEP_PIN DIO7 #define E_DIR_PIN DIO8 +#define STEPPER_ENABLE_PIN DIO9 + // list of PWM-able pins and corresponding timers +// timer1 is reserved for step timing // OC0A DIO6 // OC0B DIO5 // OC1A DIO9 @@ -41,12 +50,7 @@ #define HEATER_PIN DIO6 #define HEATER_PIN_PWM OC0A -#define FAN_PIN DIO5 - -#define SCK DIO13 -#define MISO DIO12 -#define MOSI DIO11 -#define SS DIO10 +// #define FAN_PIN DIO5 /* X Stepper @@ -105,13 +109,25 @@ #define enable_heater() WRITE(HEATER_PIN, 1) #define disable_heater() WRITE(HEATER_PIN, 0) +/* + fan +*/ + +#ifdef FAN_PIN + #define enable_fan() WRITE(FAN_PIN, 1) + #define disable_fan() WRITE(FAN_PIN, 0) +#else + #define enable_fan() if (0) {} + #define disable_fan() if (0) {} +#endif + /* 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) + #define enable_steppers() WRITE(STEPPER_ENABLE_PIN, 0) + #define disable_steppers() WRITE(STEPPER_ENABLE_PIN, 1) #else #define enable_steppers() if (0) {} #define disable_steppers() if (0) {} diff --git a/mendel/temp.c b/mendel/temp.c index 6e4633a..ac20d16 100644 --- a/mendel/temp.c +++ b/mendel/temp.c @@ -71,6 +71,8 @@ uint16_t temp_read() { WRITE(SS, 0); + SPCR = 0; + return 0; } diff --git a/mendel/timer.c b/mendel/timer.c index bcec6fb..5795b55 100644 --- a/mendel/timer.c +++ b/mendel/timer.c @@ -9,16 +9,19 @@ ISR(TIMER1_COMPA_vect) { if(movebuffer[mb_tail].live) { // this interrupt can be interruptible // TODO: remove when not debugging - disableTimerInterrupt(); - sei(); +// disableTimerInterrupt(); +// sei(); +// WRITE(SCK, 0); dda_step(&(movebuffer[mb_tail])); +// WRITE(SCK, 1); - cli(); - enableTimerInterrupt(); +// cli(); +// enableTimerInterrupt(); } - else + else { next_move(); + } } void setupTimerInterrupt()