From f27e79aaf2726013e2f17393eceaa1850cea5e1f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 20 Jan 2010 12:06:06 +1100 Subject: [PATCH] time to save again, added delay_ms, implemented cooling fan, tons of updates in gcode interpreter --- mendel/gcode.c | 87 ++++++++++++++++++++++++++++++++++++++++--------- mendel/gcode.h | 4 ++- mendel/mendel.c | 4 +++ mendel/pinout.h | 6 ++-- mendel/temp.c | 12 ++++++- mendel/timer.c | 10 +++++- mendel/timer.h | 4 +++ 7 files changed, 107 insertions(+), 20 deletions(-) diff --git a/mendel/gcode.c b/mendel/gcode.c index f794f4c..d7a2e6a 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -7,6 +7,7 @@ #include "serial.h" #include "sermsg.h" #include "temp.h" +#include "timer.h" uint8_t option_bitfield; @@ -94,7 +95,7 @@ void scan_char(uint8_t c) { c &= ~32; // process field - if (indexof(c, "GMXYZEFS\n") >= 0) { + if (indexof(c, "GMXYZEFSP\n") >= 0) { if (last_field) { switch (last_field) { case 'G': @@ -120,7 +121,20 @@ void scan_char(uint8_t c) { next_target.target.F = read_digit.mantissa; break; case 'S': - next_target.S = decfloat_to_int(&read_digit, 1, 1); + // if this is temperature, multiply by 4 to convert to quarter-degree units + // cosmetically this should be done in the temperature section, + // but it takes less code, less memory and loses no precision if we do it here instead + if (next_target.M == 104) + next_target.S = decfloat_to_int(&read_digit, 4, 1); + else + next_target.S = decfloat_to_int(&read_digit, 1, 1); + break; + case 'P': + // if this is dwell, multiply by 1 million to convert seconds to milliseconds + if (next_target.G == 4) + next_target.P = decfloat_to_int(&read_digit, 1000, 1); + else + next_target.P = decfloat_to_int(&read_digit, 1, 1); break; } read_digit.sign = 0; @@ -152,6 +166,10 @@ void scan_char(uint8_t c) { break; case 'S': next_target.seen |= SEEN_S; + break; + case 'P': + next_target.seen |= SEEN_P; + break; case '\n': // process process_gcode_command(&next_target); @@ -161,9 +179,7 @@ void scan_char(uint8_t c) { // reset variables last_field = 0; -// memset(&next_target, 0, sizeof(GCODE_COMMAND)); next_target.seen = 0; -// next_target.option = option_bitfield; serial_writeblock((uint8_t *) "OK\n", 3); break; @@ -189,40 +205,44 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { 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 + // since it would be a major hassle to force the dda to not synchronise, just provide a fast feedrate and hope it's close enough to what host expects case 0: gcmd->target.F = FEEDRATE_FAST_XY; enqueue(&gcmd->target); break; + // G1 - synchronised motion case 1: enqueue(&gcmd->target); break; + // G2 - Arc Clockwise + // G3 - Arc Counter-clockwise + // G4 - Dwell + case 4: + delay_ms(gcmd->P); + break; + // 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); + // no break here, G30 is move and then go home // G28 - go home case 28: /* @@ -269,18 +289,22 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { startpoint.E = current_position.E = 0; break; + // G90 - absolute positioning case 90: gcmd->option &= ~OPTION_RELATIVE; break; + // G91 - relative positioning case 91: gcmd->option |= OPTION_RELATIVE; 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); @@ -294,20 +318,53 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { case 101: SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E); break; + + // M102- extruder reverse + // 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'); + // do .. while block here to provide local scope for temp + do { + uint16_t t = temp_get(); + serial_writeblock((uint8_t *) "T: ", 3); + serwrite_uint16(t >> 2); + serial_writechar('.'); + if (t & 3) { + if ((t & 3) == 1) + serial_writechar('2'); + else if ((t & 3) == 3) + serial_writechar('7'); + serial_writechar('5'); + } + else { + serial_writechar('0'); + } + serial_writechar('\n'); + } while (0); break; + + // M106- fan on + #ifdef FAN_PIN + case 106: + WRITE(FAN_PIN, 1); + break; + + // M107- fan off + case 107: + WRITE(FAN_PIN, 0); + break; + #endif + // TODO: spit an error default: serial_writeblock((uint8_t *) "E: Bad M-code ", 14); diff --git a/mendel/gcode.h b/mendel/gcode.h index 9857d5c..2fcbed1 100644 --- a/mendel/gcode.h +++ b/mendel/gcode.h @@ -18,7 +18,7 @@ typedef struct { } decfloat; typedef struct { - uint8_t seen; + uint16_t seen; #define SEEN_G 1 #define SEEN_M 2 #define SEEN_X 4 @@ -27,6 +27,7 @@ typedef struct { #define SEEN_E 32 #define SEEN_F 64 #define SEEN_S 128 +#define SEEN_P 256 uint8_t option; #define OPTION_RELATIVE 1 @@ -38,6 +39,7 @@ typedef struct { TARGET target; uint16_t S; + uint16_t P; } GCODE_COMMAND; int8_t indexof(uint8_t c, char *string); diff --git a/mendel/mendel.c b/mendel/mendel.c index 65928d9..590378f 100644 --- a/mendel/mendel.c +++ b/mendel/mendel.c @@ -37,6 +37,10 @@ int main (void) WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN); + #ifdef FAN_PIN + WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN); + #endif + WRITE(SCK, 0); SET_OUTPUT(SCK); WRITE(MISO, 1); SET_INPUT(MISO); WRITE(SS, 0); SET_OUTPUT(SS); diff --git a/mendel/pinout.h b/mendel/pinout.h index 526e842..64a0701 100644 --- a/mendel/pinout.h +++ b/mendel/pinout.h @@ -24,8 +24,8 @@ #define Y_MIN_PIN AIO5 #define Z_STEP_PIN DIO5 -#define Z_DIR_PIN DIO6 -#define Z_MIN_PIN DIO7 +#define Z_DIR_PIN DIO7 +#define Z_MIN_PIN DIO8 #define E_STEP_PIN DIO2 #define E_DIR_PIN DIO3 @@ -41,6 +41,8 @@ #define HEATER_PIN DIO6 #define HEATER_PIN_PWM OC0A +#define FAN_PIN DIO9 + #define SCK DIO13 #define MISO DIO12 #define MOSI DIO11 diff --git a/mendel/temp.c b/mendel/temp.c index 6dbfb41..c650774 100644 --- a/mendel/temp.c +++ b/mendel/temp.c @@ -1,7 +1,17 @@ /* temp.c - This file currently reads temp from a MAX6675 on the SPI bus + This file currently reads temp from a MAX6675 on the SPI bus. + + ALL VALUES are in units of 0.25 degrees celsius, so temp_set(500) will set the temperature to 125 celsius, and temp_get() = 600 is reporting a temperature of 150 celsius. + + the conversion to/from this unit is done in gcode.c, near: + if (next_target.M == 104) + next_target.S = decfloat_to_int(&read_digit, 4, 1); + and + // M105- get temperature + case 105: + uint16_t t = temp_get(); */ #include "temp.h" diff --git a/mendel/timer.c b/mendel/timer.c index 6e2a913..162d294 100644 --- a/mendel/timer.c +++ b/mendel/timer.c @@ -135,12 +135,20 @@ void setTimer(uint32_t delay) void delay(uint32_t delay) { while (delay > 65535) { - delayMicrosecondsInterruptible(delay); + delayMicrosecondsInterruptible(65534); delay -= 65535; } delayMicrosecondsInterruptible(delay & 0xFFFF); } +void delay_ms(uint32_t delay) { + while (delay > 65) { + delayMicrosecondsInterruptible(64999); + delay -= 65; + } + delayMicrosecondsInterruptible(delay * 1000); +} + // from reprap project 5D firmware void delayMicrosecondsInterruptible(uint16_t us) { diff --git a/mendel/timer.h b/mendel/timer.h index 542ec28..975c1aa 100644 --- a/mendel/timer.h +++ b/mendel/timer.h @@ -19,6 +19,10 @@ uint16_t getTimerCeiling(const uint32_t delay); void setTimer(uint32_t delay); void delay(uint32_t delay); + +void delay_ms(uint32_t delay); + +#define delay_us(d) delayMicrosecondsInterruptible(d) void delayMicrosecondsInterruptible(unsigned int us); inline void enableTimerInterrupt(void)