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

This commit is contained in:
Michael Moon 2010-02-04 00:30:04 +11:00
parent 5b1245e41d
commit 8cc6fa6937
12 changed files with 270 additions and 148 deletions

View File

@ -14,7 +14,7 @@
PROGRAM = mendel 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
############################################################################## ##############################################################################
# # # #

View File

@ -11,9 +11,10 @@ uint32_t clock_read(void);
extern volatile uint8_t clock_flag_250ms; extern volatile uint8_t clock_flag_250ms;
#define CLOCK_FLAG_250MS_TEMPCHECK 1 #define CLOCK_FLAG_250MS 1
#define CLOCK_FLAG_250MS_REPORT 2 // #define CLOCK_FLAG_250MS_TEMPCHECK 1
#define CLOCK_FLAG_250MS_STEPTIMEOUT 4 // #define CLOCK_FLAG_250MS_REPORT 2
// #define CLOCK_FLAG_250MS_STEPTIMEOUT 4
/* /*
ifclock() {} ifclock() {}

View File

@ -5,6 +5,7 @@
#include "timer.h" #include "timer.h"
#include "serial.h" #include "serial.h"
#include "sermsg.h" #include "sermsg.h"
#include "dda_queue.h"
#ifndef ABS #ifndef ABS
#define ABS(v) (((v) >= 0)?(v):(-(v))) #define ABS(v) (((v) >= 0)?(v):(-(v)))
@ -31,78 +32,6 @@ uint8_t steptimeout = 0;
TARGET startpoint = { 0, 0, 0, 0, 0 }; TARGET startpoint = { 0, 0, 0, 0, 0 };
TARGET current_position = { 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 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 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; uint32_t distance;
// initialise DDA to a known state // initialise DDA to a known state

View File

@ -6,6 +6,10 @@
#include "pinout.h" #include "pinout.h"
#include "machine.h" #include "machine.h"
/*
types
*/
typedef struct { typedef struct {
int32_t X; int32_t X;
int32_t Y; int32_t Y;
@ -43,24 +47,23 @@ typedef struct {
uint32_t move_duration; uint32_t move_duration;
} DDA; } DDA;
extern uint8_t mb_head; /*
extern uint8_t mb_tail; variables
extern DDA movebuffer[MOVEBUFFER_SIZE]; */
extern TARGET startpoint;
extern TARGET current_position;
extern uint8_t steptimeout; extern uint8_t steptimeout;
uint8_t queue_full(void); extern TARGET startpoint;
uint8_t queue_empty(void); extern TARGET current_position;
void enqueue(TARGET *t);
void next_move(void); /*
void print_queue(void); methods
*/
uint32_t approx_distance( uint32_t dx, uint32_t dy ); uint32_t approx_distance( uint32_t dx, uint32_t dy );
uint32_t approx_distance_3( uint32_t dx, uint32_t dy, uint32_t dz ); 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_start(DDA *dda);
void dda_step(DDA *dda); void dda_step(DDA *dda);

73
mendel/dda_queue.c Normal file
View File

@ -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');
}

24
mendel/dda_queue.h Normal file
View File

@ -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 */

View File

@ -7,6 +7,9 @@
#include "sermsg.h" #include "sermsg.h"
#include "temp.h" #include "temp.h"
#include "timer.h" #include "timer.h"
#include "dda_queue.h"
#include "dda.h"
#include "clock.h"
uint8_t option_bitfield; uint8_t option_bitfield;
#define OPTION_COMMENT 128 #define OPTION_COMMENT 128
@ -382,6 +385,14 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
switch (gcmd->M) { switch (gcmd->M) {
// M101- extruder on // M101- extruder on
case 101: 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); SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
break; break;

View File

@ -47,6 +47,12 @@
#define E_STARTSTOP_STEPS 20 #define E_STARTSTOP_STEPS 20
#define FEEDRATE_FAST_E 1200 #define FEEDRATE_FAST_E 1200
/*
extruder settings
*/
#define TEMP_HYSTERESIS 2
/* /*
calculated values - you shouldn't need to touch these 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! 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!

View File

@ -8,6 +8,7 @@
#include "machine.h" #include "machine.h"
#include "serial.h" #include "serial.h"
#include "dda_queue.h"
#include "dda.h" #include "dda.h"
#include "gcode.h" #include "gcode.h"
#include "timer.h" #include "timer.h"
@ -87,79 +88,141 @@ inline void init(void) {
//enableTimerInterrupt(); //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) int main (void)
{ {
uint8_t report = 0;
init(); init();
// main loop // main loop
for (;;) 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(); uint8_t c = serial_popchar();
scan_char(c); scan_char(c);
} }
ifclock(CLOCK_FLAG_250MS_TEMPCHECK) { ifclock(CLOCK_FLAG_250MS) {
temp_tick(); clock_250ms();
} }
ifclock(CLOCK_FLAG_250MS_STEPTIMEOUT) { // ifclock(CLOCK_FLAG_250MS_TEMPCHECK) {
if (steptimeout > (30 * 4)) // temp_tick();
disable_steppers(); // }
else //
steptimeout++; // ifclock(CLOCK_FLAG_250MS_STEPTIMEOUT) {
} // if (steptimeout > (30 * 4))
// disable_steppers();
ifclock(CLOCK_FLAG_250MS_REPORT) { // else
report++; // steptimeout++;
if (report == 4) { // }
report = 0; //
// ifclock(CLOCK_FLAG_250MS_REPORT) {
if (DEBUG) { // report++;
// current move // if (report == 4) {
serial_writestr_P(PSTR("DDA: f#")); // report = 0;
serwrite_int32(movebuffer[mb_head].f_counter); //
serial_writechar('/'); // if (DEBUG) {
// serwrite_uint16(movebuffer[mb_head].f_scale); // // current move
// serial_writestr_P(PSTR("DDA: f#"));
// serwrite_int32(movebuffer[mb_head].f_counter);
// serial_writechar('/'); // serial_writechar('/');
serwrite_int16(movebuffer[mb_head].f_delta); // // serwrite_uint16(movebuffer[mb_head].f_scale);
serial_writechar('\n'); // // serial_writechar('/');
// serwrite_int16(movebuffer[mb_head].f_delta);
// current position // serial_writechar('\n');
serial_writestr_P(PSTR("Pos: ")); //
serwrite_int32(current_position.X); // // current position
serial_writechar(','); // serial_writestr_P(PSTR("Pos: "));
serwrite_int32(current_position.Y); // serwrite_int32(current_position.X);
serial_writechar(','); // serial_writechar(',');
serwrite_int32(current_position.Z); // serwrite_int32(current_position.Y);
serial_writechar(','); // serial_writechar(',');
serwrite_int32(current_position.E); // serwrite_int32(current_position.Z);
serial_writechar(','); // serial_writechar(',');
serwrite_uint32(current_position.F); // serwrite_int32(current_position.E);
serial_writechar('\n'); // serial_writechar(',');
// serwrite_uint32(current_position.F);
// target position // serial_writechar('\n');
serial_writestr_P(PSTR("Dst: ")); //
serwrite_int32(movebuffer[mb_tail].endpoint.X); // // target position
serial_writechar(','); // serial_writestr_P(PSTR("Dst: "));
serwrite_int32(movebuffer[mb_tail].endpoint.Y); // serwrite_int32(movebuffer[mb_tail].endpoint.X);
serial_writechar(','); // serial_writechar(',');
serwrite_int32(movebuffer[mb_tail].endpoint.Z); // serwrite_int32(movebuffer[mb_tail].endpoint.Y);
serial_writechar(','); // serial_writechar(',');
serwrite_int32(movebuffer[mb_tail].endpoint.E); // serwrite_int32(movebuffer[mb_tail].endpoint.Z);
serial_writechar(','); // serial_writechar(',');
serwrite_uint32(movebuffer[mb_tail].endpoint.F); // serwrite_int32(movebuffer[mb_tail].endpoint.E);
serial_writechar('\n'); // serial_writechar(',');
} // serwrite_uint32(movebuffer[mb_tail].endpoint.F);
// serial_writechar('\n');
// Queue // }
print_queue(); //
// // Queue
// temperature // print_queue();
temp_print(); //
} // // temperature
} // temp_print();
// }
// }
} }
} }

View File

@ -84,6 +84,16 @@ uint16_t temp_get() {
return current_temp; 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() { void temp_print() {
serial_writestr_P(PSTR("T: ")); serial_writestr_P(PSTR("T: "));
if (temp_flags & TEMP_FLAG_TCOPEN) { if (temp_flags & TEMP_FLAG_TCOPEN) {

View File

@ -6,6 +6,7 @@
uint16_t temp_read(void); uint16_t temp_read(void);
void temp_set(uint16_t t); void temp_set(uint16_t t);
uint16_t temp_get(void); uint16_t temp_get(void);
uint8_t temp_achieved(void);
void temp_print(void); void temp_print(void);
void temp_tick(void); void temp_tick(void);

View File

@ -3,6 +3,7 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "pinout.h" #include "pinout.h"
#include "dda_queue.h"
#include "dda.h" #include "dda.h"
ISR(TIMER1_COMPA_vect) { ISR(TIMER1_COMPA_vect) {