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
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;
#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() {}

View File

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

View File

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

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 "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;

View File

@ -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!

View File

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

View File

@ -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) {

View File

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

View File

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