From 8cc6fa693747ea539db42f8df930fbcd10b05ab6 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 4 Feb 2010 00:30:04 +1100 Subject: [PATCH] split up dda and its queue, moved clock tick functions from main loop so I can call them from M101 while waiting for heater to reach target temperature, added thermal hysteresis setting --- mendel/Makefile | 2 +- mendel/clock.h | 7 +- mendel/dda.c | 75 +------------------ mendel/dda.h | 25 ++++--- mendel/dda_queue.c | 73 ++++++++++++++++++ mendel/dda_queue.h | 24 ++++++ mendel/gcode.c | 11 +++ mendel/machine.h | 6 ++ mendel/mendel.c | 183 ++++++++++++++++++++++++++++++--------------- mendel/temp.c | 10 +++ mendel/temp.h | 1 + mendel/timer.c | 1 + 12 files changed, 270 insertions(+), 148 deletions(-) create mode 100644 mendel/dda_queue.c create mode 100644 mendel/dda_queue.h diff --git a/mendel/Makefile b/mendel/Makefile index 51f4d24..f6c5c77 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 sermsg.c +SOURCES = $(PROGRAM).c ringbuffer.c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c ############################################################################## # # diff --git a/mendel/clock.h b/mendel/clock.h index 9f12804..2edf7ef 100644 --- a/mendel/clock.h +++ b/mendel/clock.h @@ -11,9 +11,10 @@ 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_STEPTIMEOUT 4 +#define CLOCK_FLAG_250MS 1 +// #define CLOCK_FLAG_250MS_TEMPCHECK 1 +// #define CLOCK_FLAG_250MS_REPORT 2 +// #define CLOCK_FLAG_250MS_STEPTIMEOUT 4 /* ifclock() {} diff --git a/mendel/dda.c b/mendel/dda.c index cc27358..703e18b 100644 --- a/mendel/dda.c +++ b/mendel/dda.c @@ -5,6 +5,7 @@ #include "timer.h" #include "serial.h" #include "sermsg.h" +#include "dda_queue.h" #ifndef ABS #define ABS(v) (((v) >= 0)?(v):(-(v))) @@ -31,78 +32,6 @@ uint8_t steptimeout = 0; TARGET startpoint = { 0, 0, 0, 0, 0 }; TARGET current_position = { 0, 0, 0, 0, 0 }; -/* - move queue -*/ - -uint8_t mb_head = 0; -uint8_t mb_tail = 0; -DDA movebuffer[MOVEBUFFER_SIZE]; - - -uint8_t queue_full() { - if (mb_tail == 0) - return mb_head == (MOVEBUFFER_SIZE - 1); - else - return mb_head == (mb_tail - 1); -} - -uint8_t queue_empty() { - return ((mb_tail == mb_head) && (movebuffer[mb_tail].live == 0))?255:0; -} - -void enqueue(TARGET *t) { - while (queue_full()) - delay(WAITING_DELAY); - - uint8_t h = mb_head; - h++; - if (h == MOVEBUFFER_SIZE) - h = 0; - - dda_create(t, &movebuffer[h]); - - // if queue only has one space left, stop transmition - if (((h + 2) & (MOVEBUFFER_SIZE - 1)) == mb_tail) - xoff(); - - mb_head = h; - - // fire up in case we're not running yet - enableTimerInterrupt(); -} - -void next_move() { - if (queue_empty()) { - // queue is empty -// disable_steppers(); -// setTimer(DEFAULT_TICK); - disableTimerInterrupt(); - } - else { - uint8_t t = mb_tail; - t++; - if (t == MOVEBUFFER_SIZE) - t = 0; - dda_start(&movebuffer[t]); - mb_tail = t; - } - // restart transmission - xon(); -} - -void print_queue() { - serial_writechar('Q'); - serwrite_uint8(mb_tail); - serial_writechar('/'); - serwrite_uint8(mb_head); - if (queue_full()) - serial_writechar('F'); - if (queue_empty()) - serial_writechar('E'); - serial_writechar('\n'); -} - /* utility functions */ @@ -180,7 +109,7 @@ uint32_t delta32(uint32_t v1, uint32_t v2) { CREATE a dda given current_position and a target, save to passed location so we can write directly into the queue */ -void dda_create(TARGET *target, DDA *dda) { +void dda_create(DDA *dda, TARGET *target) { uint32_t distance; // initialise DDA to a known state diff --git a/mendel/dda.h b/mendel/dda.h index fd4a705..4249810 100644 --- a/mendel/dda.h +++ b/mendel/dda.h @@ -6,6 +6,10 @@ #include "pinout.h" #include "machine.h" +/* + types +*/ + typedef struct { int32_t X; int32_t Y; @@ -43,24 +47,23 @@ typedef struct { uint32_t move_duration; } DDA; -extern uint8_t mb_head; -extern uint8_t mb_tail; -extern DDA movebuffer[MOVEBUFFER_SIZE]; -extern TARGET startpoint; -extern TARGET current_position; +/* + variables +*/ extern uint8_t steptimeout; -uint8_t queue_full(void); -uint8_t queue_empty(void); -void enqueue(TARGET *t); -void next_move(void); -void print_queue(void); +extern TARGET startpoint; +extern TARGET current_position; + +/* + methods +*/ uint32_t approx_distance( uint32_t dx, uint32_t dy ); uint32_t approx_distance_3( uint32_t dx, uint32_t dy, uint32_t dz ); -void dda_create(TARGET *target, DDA *dda); +void dda_create(DDA *dda, TARGET *target); void dda_start(DDA *dda); void dda_step(DDA *dda); diff --git a/mendel/dda_queue.c b/mendel/dda_queue.c new file mode 100644 index 0000000..b2dbc78 --- /dev/null +++ b/mendel/dda_queue.c @@ -0,0 +1,73 @@ +#include "dda_queue.h" + +#include "timer.h" +#include "serial.h" +#include "sermsg.h" + +uint8_t mb_head = 0; +uint8_t mb_tail = 0; +DDA movebuffer[MOVEBUFFER_SIZE]; + + +uint8_t queue_full() { + if (mb_tail == 0) + return mb_head == (MOVEBUFFER_SIZE - 1); + else + return mb_head == (mb_tail - 1); +} + +uint8_t queue_empty() { + return ((mb_tail == mb_head) && (movebuffer[mb_tail].live == 0))?255:0; +} + +void enqueue(TARGET *t) { + while (queue_full()) + delay(WAITING_DELAY); + + uint8_t h = mb_head; + h++; + if (h == MOVEBUFFER_SIZE) + h = 0; + + dda_create(&movebuffer[h], t); + + // if queue only has one space left, stop transmition + if (((h + 2) & (MOVEBUFFER_SIZE - 1)) == mb_tail) + xoff(); + + mb_head = h; + + // fire up in case we're not running yet + enableTimerInterrupt(); +} + +void next_move() { + if (queue_empty()) { + // queue is empty +// disable_steppers(); +// setTimer(DEFAULT_TICK); + disableTimerInterrupt(); + } + else { + uint8_t t = mb_tail; + t++; + if (t == MOVEBUFFER_SIZE) + t = 0; + dda_start(&movebuffer[t]); + mb_tail = t; + } + // restart transmission + xon(); +} + +void print_queue() { + serial_writechar('Q'); + serwrite_uint8(mb_tail); + serial_writechar('/'); + serwrite_uint8(mb_head); + if (queue_full()) + serial_writechar('F'); + if (queue_empty()) + serial_writechar('E'); + serial_writechar('\n'); +} diff --git a/mendel/dda_queue.h b/mendel/dda_queue.h new file mode 100644 index 0000000..86a7185 --- /dev/null +++ b/mendel/dda_queue.h @@ -0,0 +1,24 @@ +#ifndef _DDA_QUEUE +#define _DDA_QUEUE + +#include "dda.h" + +/* + variables +*/ + +extern uint8_t mb_head; +extern uint8_t mb_tail; +extern DDA movebuffer[MOVEBUFFER_SIZE]; + +/* + methods +*/ + +uint8_t queue_full(void); +uint8_t queue_empty(void); +void enqueue(TARGET *t); +void next_move(void); +void print_queue(void); + +#endif /* _DDA_QUEUE */ diff --git a/mendel/gcode.c b/mendel/gcode.c index 2072472..594dc79 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -7,6 +7,9 @@ #include "sermsg.h" #include "temp.h" #include "timer.h" +#include "dda_queue.h" +#include "dda.h" +#include "clock.h" uint8_t option_bitfield; #define OPTION_COMMENT 128 @@ -382,6 +385,14 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { switch (gcmd->M) { // M101- extruder on case 101: + // here we wait until target temperature is reached, and emulate main loop so the temperature can actually be updated + while (!temp_achieved()) { + ifclock(CLOCK_FLAG_250MS) { + // this is cosmetically nasty, but exactly what needs to happen + void clock_250ms(void); + clock_250ms(); + } + } SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E); break; diff --git a/mendel/machine.h b/mendel/machine.h index 8fe6202..9e29dc6 100644 --- a/mendel/machine.h +++ b/mendel/machine.h @@ -47,6 +47,12 @@ #define E_STARTSTOP_STEPS 20 #define FEEDRATE_FAST_E 1200 +/* + extruder settings +*/ + +#define TEMP_HYSTERESIS 2 + /* calculated values - you shouldn't need to touch these however feel free to put in your own values if they can be more precise than the calculated approximations, remembering that they must end up being integers- floating point by preprocessor only thanks! diff --git a/mendel/mendel.c b/mendel/mendel.c index eedbc61..901e433 100644 --- a/mendel/mendel.c +++ b/mendel/mendel.c @@ -8,6 +8,7 @@ #include "machine.h" #include "serial.h" +#include "dda_queue.h" #include "dda.h" #include "gcode.h" #include "timer.h" @@ -87,79 +88,141 @@ inline void init(void) { //enableTimerInterrupt(); } +void clock_250ms() { + static uint8_t report = 0; + + temp_tick(); + + if (steptimeout > (30 * 4)) + disable_steppers(); + else + steptimeout++; + + report++; + if (report == 4) { + report = 0; + + if (DEBUG) { + // current move + serial_writestr_P(PSTR("DDA: f#")); + serwrite_int32(movebuffer[mb_head].f_counter); + serial_writechar('/'); + // serwrite_uint16(movebuffer[mb_head].f_scale); + // serial_writechar('/'); + serwrite_int16(movebuffer[mb_head].f_delta); + serial_writechar('\n'); + + // current position + serial_writestr_P(PSTR("Pos: ")); + serwrite_int32(current_position.X); + serial_writechar(','); + serwrite_int32(current_position.Y); + serial_writechar(','); + serwrite_int32(current_position.Z); + serial_writechar(','); + serwrite_int32(current_position.E); + serial_writechar(','); + serwrite_uint32(current_position.F); + serial_writechar('\n'); + + // target position + serial_writestr_P(PSTR("Dst: ")); + serwrite_int32(movebuffer[mb_tail].endpoint.X); + serial_writechar(','); + serwrite_int32(movebuffer[mb_tail].endpoint.Y); + serial_writechar(','); + serwrite_int32(movebuffer[mb_tail].endpoint.Z); + serial_writechar(','); + serwrite_int32(movebuffer[mb_tail].endpoint.E); + serial_writechar(','); + serwrite_uint32(movebuffer[mb_tail].endpoint.F); + serial_writechar('\n'); + + // Queue + print_queue(); + } + + // temperature + temp_print(); + } +} + int main (void) { - uint8_t report = 0; - init(); // main loop for (;;) { - if (serial_rxchars()) { + // if queue is full, no point in reading chars- host will just have to wait + if (serial_rxchars() && !queue_full()) { uint8_t c = serial_popchar(); scan_char(c); } - ifclock(CLOCK_FLAG_250MS_TEMPCHECK) { - temp_tick(); + ifclock(CLOCK_FLAG_250MS) { + clock_250ms(); } - ifclock(CLOCK_FLAG_250MS_STEPTIMEOUT) { - if (steptimeout > (30 * 4)) - disable_steppers(); - else - steptimeout++; - } - - ifclock(CLOCK_FLAG_250MS_REPORT) { - report++; - if (report == 4) { - report = 0; - - if (DEBUG) { - // current move - serial_writestr_P(PSTR("DDA: f#")); - serwrite_int32(movebuffer[mb_head].f_counter); - serial_writechar('/'); -// serwrite_uint16(movebuffer[mb_head].f_scale); +// ifclock(CLOCK_FLAG_250MS_TEMPCHECK) { +// temp_tick(); +// } +// +// ifclock(CLOCK_FLAG_250MS_STEPTIMEOUT) { +// if (steptimeout > (30 * 4)) +// disable_steppers(); +// else +// steptimeout++; +// } +// +// ifclock(CLOCK_FLAG_250MS_REPORT) { +// report++; +// if (report == 4) { +// report = 0; +// +// if (DEBUG) { +// // current move +// serial_writestr_P(PSTR("DDA: f#")); +// serwrite_int32(movebuffer[mb_head].f_counter); // serial_writechar('/'); - serwrite_int16(movebuffer[mb_head].f_delta); - serial_writechar('\n'); - - // current position - serial_writestr_P(PSTR("Pos: ")); - serwrite_int32(current_position.X); - serial_writechar(','); - serwrite_int32(current_position.Y); - serial_writechar(','); - serwrite_int32(current_position.Z); - serial_writechar(','); - serwrite_int32(current_position.E); - serial_writechar(','); - serwrite_uint32(current_position.F); - serial_writechar('\n'); - - // target position - serial_writestr_P(PSTR("Dst: ")); - serwrite_int32(movebuffer[mb_tail].endpoint.X); - serial_writechar(','); - serwrite_int32(movebuffer[mb_tail].endpoint.Y); - serial_writechar(','); - serwrite_int32(movebuffer[mb_tail].endpoint.Z); - serial_writechar(','); - serwrite_int32(movebuffer[mb_tail].endpoint.E); - serial_writechar(','); - serwrite_uint32(movebuffer[mb_tail].endpoint.F); - serial_writechar('\n'); - } - - // Queue - print_queue(); - - // temperature - temp_print(); - } - } +// // serwrite_uint16(movebuffer[mb_head].f_scale); +// // serial_writechar('/'); +// serwrite_int16(movebuffer[mb_head].f_delta); +// serial_writechar('\n'); +// +// // current position +// serial_writestr_P(PSTR("Pos: ")); +// serwrite_int32(current_position.X); +// serial_writechar(','); +// serwrite_int32(current_position.Y); +// serial_writechar(','); +// serwrite_int32(current_position.Z); +// serial_writechar(','); +// serwrite_int32(current_position.E); +// serial_writechar(','); +// serwrite_uint32(current_position.F); +// serial_writechar('\n'); +// +// // target position +// serial_writestr_P(PSTR("Dst: ")); +// serwrite_int32(movebuffer[mb_tail].endpoint.X); +// serial_writechar(','); +// serwrite_int32(movebuffer[mb_tail].endpoint.Y); +// serial_writechar(','); +// serwrite_int32(movebuffer[mb_tail].endpoint.Z); +// serial_writechar(','); +// serwrite_int32(movebuffer[mb_tail].endpoint.E); +// serial_writechar(','); +// serwrite_uint32(movebuffer[mb_tail].endpoint.F); +// serial_writechar('\n'); +// } +// +// // Queue +// print_queue(); +// +// // temperature +// temp_print(); +// } +// } } } diff --git a/mendel/temp.c b/mendel/temp.c index ac20d16..524f18e 100644 --- a/mendel/temp.c +++ b/mendel/temp.c @@ -84,6 +84,16 @@ uint16_t temp_get() { return current_temp; } +uint8_t temp_achieved() { + if (current_temp >= target_temp) + if ((current_temp - target_temp) < TEMP_HYSTERESIS) + return 255; + if (current_temp < target_temp) + if ((target_temp - current_temp) < TEMP_HYSTERESIS) + return 255; + return 0; +} + void temp_print() { serial_writestr_P(PSTR("T: ")); if (temp_flags & TEMP_FLAG_TCOPEN) { diff --git a/mendel/temp.h b/mendel/temp.h index b2eaca0..7b8312a 100644 --- a/mendel/temp.h +++ b/mendel/temp.h @@ -6,6 +6,7 @@ uint16_t temp_read(void); void temp_set(uint16_t t); uint16_t temp_get(void); +uint8_t temp_achieved(void); void temp_print(void); void temp_tick(void); diff --git a/mendel/timer.c b/mendel/timer.c index 484e56a..0dce8f9 100644 --- a/mendel/timer.c +++ b/mendel/timer.c @@ -3,6 +3,7 @@ #include #include "pinout.h" +#include "dda_queue.h" #include "dda.h" ISR(TIMER1_COMPA_vect) {