From ef09d62c00b13e19ee3f48927c5c42c75e915a94 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 20 Jan 2010 10:48:40 +1100 Subject: [PATCH] time to save again, tightened up gcode interpreter, added preliminary extruder pullback code --- mendel/Makefile | 4 +- mendel/dda.c | 18 +++--- mendel/dda.h | 3 +- mendel/gcode.c | 163 ++++++++++++++++++++++++++++++++++++++++------- mendel/gcode.h | 23 +++++-- mendel/machine.h | 10 ++- mendel/mendel.c | 10 --- mendel/sermsg.c | 43 +++++++++++++ mendel/sermsg.h | 9 +++ mendel/target.h | 14 ---- mendel/temp.c | 4 ++ mendel/temp.h | 1 + 12 files changed, 235 insertions(+), 67 deletions(-) create mode 100644 mendel/sermsg.c create mode 100644 mendel/sermsg.h delete mode 100644 mendel/target.h diff --git a/mendel/Makefile b/mendel/Makefile index 8564494..7d50286 100644 --- a/mendel/Makefile +++ b/mendel/Makefile @@ -14,7 +14,7 @@ PROGRAM = mendel -SOURCES = $(PROGRAM).c ringbuffer.c serial.c dda.c gcode.c timer.c clock.c temp.c +SOURCES = $(PROGRAM).c ringbuffer.c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c ############################################################################## # # @@ -34,7 +34,7 @@ F_CPU = 16000000L ARCH = avr- OPTIMIZE = -Os CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(F_CPU) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -save-temps -LDFLAGS = -lprintf_min -Wl,--as-needed -Wl,--gc-sections -finline-functions-called-once +LDFLAGS = -Wl,--as-needed -Wl,--gc-sections -finline-functions-called-once CC = $(ARCH)gcc OBJDUMP = $(ARCH)objdump diff --git a/mendel/dda.c b/mendel/dda.c index aaa529e..f54f589 100644 --- a/mendel/dda.c +++ b/mendel/dda.c @@ -5,14 +5,6 @@ #include "pinout.h" #include "timer.h" -extern struct { - volatile int32_t X; - volatile int32_t Y; - volatile int32_t Z; - volatile int32_t E; - volatile int32_t F; -} current_position; - /* move queue */ @@ -21,6 +13,13 @@ uint8_t mb_head = 0; uint8_t mb_tail = 0; DDA movebuffer[MOVEBUFFER_SIZE]; +/* + position tracking +*/ + +TARGET startpoint = { 0, 0, 0, 0, 0 }; +TARGET current_position = { 0, 0, 0, 0, 0 }; + uint8_t queue_full() { if (mb_tail == 0) return mb_head == (MOVEBUFFER_SIZE - 1); @@ -41,7 +40,7 @@ void enqueue(TARGET *t) { } void next_move() { - if ((mb_tail == mb_head) && (!movebuffer[mb_tail].live)) { + if (queue_empty()) { // queue is empty disable_steppers(); setTimer(DEFAULT_TICK); @@ -129,7 +128,6 @@ 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 }; uint32_t distance; // we start at the previous endpoint diff --git a/mendel/dda.h b/mendel/dda.h index 0491963..2210d40 100644 --- a/mendel/dda.h +++ b/mendel/dda.h @@ -3,7 +3,6 @@ #include -#include "target.h" #include "pinout.h" #include "gcode.h" #include "machine.h" @@ -41,6 +40,8 @@ typedef struct { extern uint8_t mb_head; extern uint8_t mb_tail; extern DDA movebuffer[MOVEBUFFER_SIZE]; +extern TARGET startpoint; +extern TARGET current_position; uint8_t queue_full(void); inline uint8_t queue_empty(void) { return (mb_tail == mb_head) && !movebuffer[mb_tail].live; } diff --git a/mendel/gcode.c b/mendel/gcode.c index de7e233..f794f4c 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -5,8 +5,10 @@ #include "machine.h" #include "dda.h" #include "serial.h" +#include "sermsg.h" +#include "temp.h" -extern uint8_t option_bitfield; +uint8_t option_bitfield; decfloat read_digit; @@ -16,24 +18,30 @@ decfloat read_digit; utility functions */ -uint8_t indexof(uint8_t c, char *string) { - uint8_t i; +int8_t indexof(uint8_t c, char *string) { + int8_t i; for (i = 0;string[i];i++) { if (c == string[i]) return i; } - return 255; + return -1; } int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) { int32_t r = df->mantissa; uint8_t e = df->exponent - 1; + // scale factors if (multiplicand != 1) r *= multiplicand; if (denominator != 1) r /= denominator; + // sign + if (df->sign) + r = -r; + + // exponent- try to keep divides to a minimum at expense of slightly more code while (e >= 5) { r /= 100000; e -= 5; @@ -51,14 +59,34 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) return r; } +void SpecialMoveXY(int32_t x, int32_t y, uint32_t f) { + TARGET t = startpoint; + t.X = x; + t.Y = y; + t.F = f; + enqueue(&t); +} + +void SpecialMoveZ(int32_t z, uint32_t f) { + TARGET t = startpoint; + t.Z = z; + t.F = f; + enqueue(&t); +} + +void SpecialMoveE(int32_t e, uint32_t f) { + TARGET t = startpoint; + t.E = e; + t.F = f; + enqueue(&t); +} + /* public functions */ void scan_char(uint8_t c) { static uint8_t last_field = 0; -// static uint32_t mantissa = 0; -// static uint8_t exp = 0; static GCODE_COMMAND next_target = { 0, 0, 0, 0, { 0, 0, 0, 0, 0 } }; // uppercase @@ -66,7 +94,7 @@ void scan_char(uint8_t c) { c &= ~32; // process field - if (indexof(c, "GMXYZEF\n") != 255) { + if (indexof(c, "GMXYZEFS\n") >= 0) { if (last_field) { switch (last_field) { case 'G': @@ -91,6 +119,9 @@ void scan_char(uint8_t c) { // 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; break; + case 'S': + next_target.S = decfloat_to_int(&read_digit, 1, 1); + break; } read_digit.sign = 0; read_digit.mantissa = 0; @@ -119,6 +150,8 @@ void scan_char(uint8_t c) { case 'F': next_target.seen |= SEEN_F; break; + case 'S': + next_target.seen |= SEEN_S; case '\n': // process process_gcode_command(&next_target); @@ -128,8 +161,9 @@ void scan_char(uint8_t c) { // reset variables last_field = 0; - memset(&next_target, 0, sizeof(GCODE_COMMAND)); - next_target.option = option_bitfield; +// memset(&next_target, 0, sizeof(GCODE_COMMAND)); + next_target.seen = 0; +// next_target.option = option_bitfield; serial_writeblock((uint8_t *) "OK\n", 3); break; @@ -149,31 +183,91 @@ void scan_char(uint8_t c) { } void process_gcode_command(GCODE_COMMAND *gcmd) { - uint8_t do_move; + if (gcmd->option & OPTION_RELATIVE) { + gcmd->target.X += startpoint.X; + gcmd->target.Y += startpoint.Y; + gcmd->target.Z += startpoint.Z; + gcmd->target.E += startpoint.E; + } +// if ((gcmd->seen & SEEN_X) == 0) +// gcmd->target.X = startpoint.X; +// if ((gcmd->seen & SEEN_Y) == 0) +// gcmd->target.X = startpoint.Y; +// if ((gcmd->seen & SEEN_Z) == 0) +// gcmd->target.X = startpoint.Z; +// if ((gcmd->seen & SEEN_E) == 0) +// gcmd->target.X = startpoint.E; + if (gcmd->seen & SEEN_G) { switch (gcmd->G) { // G0 - rapid, unsynchronised motion case 0: - gcmd->option &= ~OPTION_SYNCHRONISE; - do_move = 1; + gcmd->target.F = FEEDRATE_FAST_XY; + enqueue(&gcmd->target); break; - // G30 - go home via point - case 30: - gcmd->option |= OPTION_HOME_WHEN_COMPLETE; // G1 - synchronised motion case 1: - gcmd->option |= OPTION_SYNCHRONISE; - do_move = 1; + enqueue(&gcmd->target); break; // G2 - Arc Clockwise // G3 - Arc Counter-clockwise // G4 - Dwell // G20 - inches as units + case 20: + gcmd->option |= OPTION_UNIT_INCHES; + break; // G21 - mm as units + case 21: + gcmd->option &= ~OPTION_UNIT_INCHES; + break; + // G30 - go home via point + case 30: + enqueue(&gcmd->target); // G28 - go home case 28: - gcmd->option &= ~OPTION_SYNCHRONISE; - do_move = 1; + /* + Home XY first + */ + // hit endstops + SpecialMoveXY(-250L * STEPS_PER_MM_X, -250L * STEPS_PER_MM_Y, FEEDRATE_FAST_XY); + startpoint.X = startpoint.Y = 0; + + SpecialMoveXY(5 * STEPS_PER_MM_X, 5 * STEPS_PER_MM_Y, FEEDRATE_SLOW_XY); + + // move back in to endstops slowly + SpecialMoveXY(-20 * STEPS_PER_MM_X, -20 * STEPS_PER_MM_Y, FEEDRATE_SLOW_XY); + + // wait for queue to complete + for (;!queue_empty();); + + // this is our home point + startpoint.X = startpoint.Y = current_position.X = current_position.Y = 0; + + /* + Home Z + */ + // hit endstop + SpecialMoveZ(-250L * STEPS_PER_MM_Z, FEEDRATE_FAST_Z); + startpoint.Z = 0; + + // move out a bit + SpecialMoveZ(5 * STEPS_PER_MM_Z, FEEDRATE_SLOW_Z); + + // move back into endstop slowly + SpecialMoveZ(-20L * STEPS_PER_MM_Z, FEEDRATE_SLOW_Z); + + // wait for queue to complete + for (;queue_empty();); + + // this is our home point + startpoint.Z = current_position.Z = 0; + + /* + Home E + */ + // extruder only runs one way anyway + startpoint.E = current_position.E = 0; + break; // G90 - absolute positioning case 90: @@ -185,17 +279,40 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { break; // G92 - set home case 92: + startpoint.X = startpoint.Y = startpoint.Z = 0; break; // TODO: spit an error + default: + serial_writeblock((uint8_t *) "E: Bad G-code ", 14); + serwrite_uint8(gcmd->G); + serial_writechar('\n'); } } if (gcmd->seen & SEEN_M) { switch (gcmd->M) { + // M101- extruder on + case 101: + SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E); + break; + // M103- extruder off + case 103: + SpecialMoveE(-E_STARTSTOP_STEPS, FEEDRATE_FAST_E); + break; + // M104- set temperature + case 104: + temp_set(gcmd->S); + break; + // M105- get temperature + case 105: + serial_writeblock((uint8_t *) "T: ", 3); + serwrite_uint16(temp_get()); + serial_writechar('\n'); + break; // TODO: spit an error + default: + serial_writeblock((uint8_t *) "E: Bad M-code ", 14); + serwrite_uint8(gcmd->M); + serial_writechar('\n'); } } - - if (do_move) { - dda_create(&gcmd->target, movebuffer); - } } diff --git a/mendel/gcode.h b/mendel/gcode.h index 5000811..9857d5c 100644 --- a/mendel/gcode.h +++ b/mendel/gcode.h @@ -1,10 +1,16 @@ #ifndef _GCODE_H #define _GCODE_H -#include "target.h" - #include +typedef struct { + int32_t X; + int32_t Y; + int32_t Z; + uint32_t E; + uint32_t F; +} TARGET; + typedef struct { uint16_t sign :1; uint16_t mantissa :11; @@ -12,7 +18,7 @@ typedef struct { } decfloat; typedef struct { - uint16_t seen; + uint8_t seen; #define SEEN_G 1 #define SEEN_M 2 #define SEEN_X 4 @@ -20,19 +26,24 @@ typedef struct { #define SEEN_Z 16 #define SEEN_E 32 #define SEEN_F 64 +#define SEEN_S 128 uint8_t option; #define OPTION_RELATIVE 1 #define OPTION_SYNCHRONISE 2 -#define OPTION_HOME_WHEN_COMPLETE 4 -#define OPTION_UNIT_INCHES 8 +#define OPTION_UNIT_INCHES 4 uint8_t G; uint8_t M; TARGET target; + + uint16_t S; } GCODE_COMMAND; +int8_t indexof(uint8_t c, char *string); +int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator); + void scan_char(uint8_t c); void process_gcode_command(GCODE_COMMAND *gcmd); -#endif /* _GCODE_H */ \ No newline at end of file +#endif /* _GCODE_H */ diff --git a/mendel/machine.h b/mendel/machine.h index a50c1ab..056e274 100644 --- a/mendel/machine.h +++ b/mendel/machine.h @@ -21,7 +21,15 @@ #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_Z (200L) #define STEPS_PER_MM_E (EXTRUDER_STEPS_PER_REV * EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER / EXTRUDER_NOZZLE_DIAMETER) +#define FEEDRATE_FAST_XY 2400 +#define FEEDRATE_SLOW_XY 120 +#define FEEDRATE_FAST_Z 240 +#define FEEDRATE_SLOW_Z 12 + +#define E_STARTSTOP_STEPS 20 +#define FEEDRATE_FAST_E 1200 + #endif /* _MACHINE_H */ diff --git a/mendel/mendel.c b/mendel/mendel.c index e8b2234..65928d9 100644 --- a/mendel/mendel.c +++ b/mendel/mendel.c @@ -14,16 +14,6 @@ #include "clock.h" #include "temp.h" -uint8_t option_bitfield; - -struct { - volatile int32_t X; - volatile int32_t Y; - volatile int32_t Z; - volatile int32_t E; - volatile int32_t F; -} current_position = { 0, 0, 0, 0, 0 }; - int main (void) { // set up serial diff --git a/mendel/sermsg.c b/mendel/sermsg.c new file mode 100644 index 0000000..3c3ba7f --- /dev/null +++ b/mendel/sermsg.c @@ -0,0 +1,43 @@ +#include "sermsg.h" + +#include "serial.h" + +void serwrite_uint8(uint8_t v) { + uint8_t t; + if (v > 100) { + t = v / 100; + serial_writechar(t + '0'); + v -= t; + } + if (v > 10) { + t = v / 10; + serial_writechar(t + '0'); + v -= t; + } + serial_writechar(v + '0'); +} + +void serwrite_uint16(uint16_t v) { + uint16_t t; + if (v > 10000) { + t = v / 10000; + serial_writechar(t + '0'); + v -= t; + } + if (v > 1000) { + t = v / 1000; + serial_writechar(t + '0'); + v -= t; + } + if (v > 100) { + t = v / 100; + serial_writechar(t + '0'); + v -= t; + } + if (v > 10) { + t = v / 10; + serial_writechar(t + '0'); + v -= t; + } + serial_writechar(v + '0'); +} diff --git a/mendel/sermsg.h b/mendel/sermsg.h new file mode 100644 index 0000000..57684ea --- /dev/null +++ b/mendel/sermsg.h @@ -0,0 +1,9 @@ +#ifndef _SERMSG_H +#define _SERMSG_H + +#include + +void serwrite_uint8(uint8_t v); +void serwrite_uint16(uint16_t v); + +#endif /* _SERMSG_H */ \ No newline at end of file diff --git a/mendel/target.h b/mendel/target.h deleted file mode 100644 index c18b0a5..0000000 --- a/mendel/target.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _TARGET_H -#define _TARGET_H - -#include - -typedef struct { - int32_t X; - int32_t Y; - int32_t Z; - uint32_t E; - uint32_t F; -} TARGET; - -#endif /* _TARGET_H */ \ No newline at end of file diff --git a/mendel/temp.c b/mendel/temp.c index 192ecfd..6dbfb41 100644 --- a/mendel/temp.c +++ b/mendel/temp.c @@ -57,6 +57,10 @@ void temp_set(uint16_t t) { target_temp = t; } +uint16_t temp_get() { + return current_temp; +} + void temp_tick() { uint16_t last_temp = current_temp; temp_read(); diff --git a/mendel/temp.h b/mendel/temp.h index d1ca5bf..3441512 100644 --- a/mendel/temp.h +++ b/mendel/temp.h @@ -5,6 +5,7 @@ uint16_t temp_read(void); void temp_set(uint16_t t); +uint16_t temp_get(void); void temp_tick(void); #endif /* _TIMER_H */