It's alive! (cue evil cackle). still has some bugs, eg small movements with large delta F cause weirdness, queueing lots of moves end-to-end causes some to not execute but appear as complete in the queue

This commit is contained in:
Michael Moon 2010-01-31 14:52:32 +11:00
parent d302329eee
commit 4fc004c6c2
13 changed files with 161 additions and 58 deletions

View File

@ -32,7 +32,7 @@ F_CPU = 16000000L
##############################################################################
ARCH = avr-
OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=0
OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=1
# OPTIMIZE = -O0
CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(F_CPU) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps
LDFLAGS = -Wl,--as-needed -Wl,--gc-sections
@ -54,9 +54,10 @@ all: $(PROGRAM).hex $(PROGRAM).lst size
program: $(PROGRAM).hex
stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT)
@sleep 0.2
@stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT)
$(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C/etc/avrdude.conf -U flash:w:$^
stty -hup -echo < $(PROGPORT)
stty 57600 raw ignbrk -hup -echo < $(PROGPORT)
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~

View File

@ -26,6 +26,34 @@
#define SET_INPUT(IO) _SET_INPUT(IO)
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
/*
ports and functions
*/
// UART
#define RXD DIO0
#define TXD DIO1
// SPI
#define SCK DIO13
#define MISO DIO12
#define MOSI DIO11
#define SS DIO10
// TWI (I2C)
#define SCL AIO5
#define SDA AIO4
// timers and PWM
#define OC0A DIO6
#define OC0B DIO5
#define OC1A DIO9
#define OC1B DIO10
#define OC2A DIO11
#define OC2B DIO3
#define ICP1 DIO8
/*
pins
*/

View File

@ -10,6 +10,7 @@
#include <avr/interrupt.h>
#include "arduino.h"
#include "pinout.h"
// global clock
#ifdef GLOBAL_CLOCK
@ -38,6 +39,7 @@ void clock_setup() {
}
ISR(TIMER2_COMPA_vect) {
// WRITE(SCK, 0);
// global clock
#ifdef GLOBAL_CLOCK
clock++;
@ -47,6 +49,7 @@ ISR(TIMER2_COMPA_vect) {
clock_flag_250ms = 255;
clock_counter_250ms = 0;
}
// WRITE(SCK, 1);
}
#ifdef GLOBAL_CLOCK

View File

@ -11,7 +11,8 @@ 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_TEMPCHECK 1
#define CLOCK_FLAG_250MS_REPORT 2
#define CLOCL_FLAG_250MS_STEPTIMEOUT 4
#endif /* _CLOCK_H */

View File

@ -18,6 +18,12 @@
#define DEBUG 0
#endif
/*
step timeout
*/
uint8_t steptimeout = 0;
/*
move queue
*/
@ -201,6 +207,7 @@ void dda_create(TARGET *target, DDA *dda) {
dda->f_delta = dda->total_steps;
}
else {
// if we boost the number of steps here, many will only be F-steps which take no time- maybe we should calculate move_distance first?
dda->f_scale = 1;
dda->total_steps = dda->f_delta;
}
@ -253,6 +260,10 @@ void dda_create(TARGET *target, DDA *dda) {
// not running yet, we fire up in dda_start()
dda->live = 0;
// get steppers ready to go
steptimeout = 0;
enable_steppers();
// fire up
enableTimerInterrupt();
}
@ -269,16 +280,18 @@ void dda_start(DDA *dda) {
return;
}
// set direction outputs
x_direction(dda->x_direction);
y_direction(dda->y_direction);
z_direction(dda->z_direction);
e_direction(dda->e_direction);
// ensure steppers are ready to go
steptimeout = 0;
enable_steppers();
dda->firstep = 1;
dda->live = 1;
// set timeout for first step
setTimer(dda->move_duration / current_position.F);
}
/*
@ -321,9 +334,10 @@ void dda_step(DDA *dda) {
#define REAL_MOVE 32
#define F_REAL_STEP 64
WRITE(SCK, 1);
do {
WRITE(SCK, 0);
step_option = 0;
// step_option |= can_step(x_min(), x_max(), current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP;
// step_option |= can_step(y_min(), y_max(), current_position.Y, dda->endpoint.Y, dda->y_direction) & Y_CAN_STEP;
// step_option |= can_step(z_min(), z_max(), current_position.Z, dda->endpoint.Z, dda->z_direction) & Z_CAN_STEP;
@ -417,7 +431,7 @@ void dda_step(DDA *dda) {
}
}
if (DEBUG) {
if (0 && DEBUG) {
serial_writechar('[');
serwrite_hex8(step_option);
serial_writechar(':');
@ -430,20 +444,28 @@ void dda_step(DDA *dda) {
serwrite_uint32(dda->move_duration);
serial_writechar(']');
}
WRITE(SCK, 1);
} while ( ((step_option & REAL_MOVE ) == 0) &&
((step_option & F_CAN_STEP) != 0) );
// turn off step outputs, hopefully they've been on long enough by now to register with the drivers
unstep();
// we have stepped in speed and now need to recalculate our delay
if (((step_option & REAL_MOVE) && (step_option & F_REAL_STEP)) || (dda->firstep)) {
setTimer(dda->move_duration / current_position.F);
dda->firstep = 0;
if (step_option & REAL_MOVE) {
// we stepped, reset timeout
steptimeout = 0;
// we have stepped in speed and now need to recalculate our delay
// WARNING: this is a divide in interrupt context! (which unfortunately seems unavoidable)
// we simply don't have the memory to precalculate this for each step,
// can't use a simplified process because the denominator changes rather than the numerator so the curve is non-linear
// and don't have a process framework to force it to be done outside interrupt context within a usable period of time
if (step_option & F_REAL_STEP)
setTimer(dda->move_duration / current_position.F);
}
// if we could step, we're still running
dda->live = (step_option & (X_CAN_STEP | Y_CAN_STEP | Z_CAN_STEP | E_CAN_STEP | F_CAN_STEP))?1:0;
WRITE(SCK, 0);
}

View File

@ -51,6 +51,8 @@ extern DDA movebuffer[MOVEBUFFER_SIZE];
extern TARGET startpoint;
extern TARGET current_position;
extern uint8_t steptimeout;
uint8_t queue_full(void);
uint8_t queue_empty(void);
void enqueue(TARGET *t);

View File

@ -45,7 +45,7 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator)
if (df->sign)
r = -r;
// exponent- try to keep divides to a minimum at expense of slightly more code
// exponent- try to keep divides to a minimum for common (small) values at expense of slightly more code
while (e >= 5) {
r /= 100000;
e -= 5;
@ -126,8 +126,8 @@ void scan_char(uint8_t c) {
serwrite_uint32(next_target.target.E);
break;
case 'F':
// 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;
// just use raw integer, 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 = decfloat_to_int(&read_digit, 1, 1);
serwrite_uint32(next_target.target.F);
break;
case 'S':

View File

@ -6,9 +6,9 @@
#include "dda.h"
typedef struct {
uint16_t sign :1;
uint16_t mantissa :11;
uint16_t exponent :4;
uint32_t sign :1;
uint32_t mantissa :24;
uint32_t exponent :7;
} decfloat;
typedef struct {

View File

@ -12,7 +12,7 @@
axis calculations, adjust as necessary
*/
#define X_STEPS_PER_REV 1600.0
#define X_STEPS_PER_REV 3200.0
#define Y_STEPS_PER_REV X_STEPS_PER_REV
// we need more speed than precision on Z, turn off microstepping
#define Z_STEPS_PER_REV 200.0
@ -26,7 +26,7 @@
// #define XY_COG_CIRCUMFERENCE (XY_COG_RADIUS * PI * 2)
#define Z_GEAR_RATIO 1.0
#define EXTRUDER_STEPS_PER_REV 3200.0
#define EXTRUDER_STEPS_PER_REV E_STEPS_PER_REV
#define EXTRUDER_SHAFT_RADIUS 5.0
#define EXTRUDER_INLET_DIAMETER 3.0
#define EXTRUDER_NOZZLE_DIAMETER 0.8
@ -40,10 +40,10 @@
// does this refer to filament or extrudate? extrudate depends on layer thickness.. hm
#define STEPS_PER_MM_E ((uint32_t) ((EXTRUDER_STEPS_PER_REV / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER / EXTRUDER_NOZZLE_DIAMETER)) + 0.5))
#define FEEDRATE_FAST_XY 2400
#define FEEDRATE_SLOW_XY 120
#define FEEDRATE_FAST_Z 240
#define FEEDRATE_SLOW_Z 12
#define FEEDRATE_FAST_XY 6000
#define FEEDRATE_SLOW_XY 300
#define FEEDRATE_FAST_Z 6000
#define FEEDRATE_SLOW_Z 300
#define E_STARTSTOP_STEPS 20
#define FEEDRATE_FAST_E 1200

View File

@ -19,14 +19,7 @@
#define DEBUG 0
#endif
int main (void)
{
uint8_t report;
// set up serial
serial_init();
// set up inputs and outputs
inline void io_init(void) {
WRITE(X_STEP_PIN, 0); SET_OUTPUT(X_STEP_PIN);
WRITE(X_DIR_PIN, 0); SET_OUTPUT(X_DIR_PIN);
WRITE(X_MIN_PIN, 1); SET_INPUT(X_MIN_PIN);
@ -42,15 +35,29 @@ int main (void)
WRITE(E_STEP_PIN, 0); SET_OUTPUT(E_STEP_PIN);
WRITE(E_DIR_PIN, 0); SET_OUTPUT(E_DIR_PIN);
WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN);
#ifdef FAN_PIN
WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN);
#ifdef HEATER_PIN
disable_heater(); SET_OUTPUT(HEATER_PIN);
#endif
WRITE(SCK, 0); SET_OUTPUT(SCK);
WRITE(MISO, 1); SET_INPUT(MISO);
WRITE(SS, 0); SET_OUTPUT(SS);
#ifdef FAN_PIN
disable_fan(); SET_OUTPUT(FAN_PIN);
#endif
#ifdef STEPPER_ENABLE_PIN
disable_steppers(); SET_OUTPUT(STEPPER_ENABLE_PIN);
#endif
WRITE(SCK, 1); SET_OUTPUT(SCK);
WRITE(MISO, 1); SET_INPUT(MISO);
WRITE(SS, 0); SET_OUTPUT(SS);
}
inline void init(void) {
// set up serial
serial_init();
// set up inputs and outputs
io_init();
// set up timers
setupTimerInterrupt();
@ -66,6 +73,13 @@ int main (void)
// start queue
//enableTimerInterrupt();
}
int main (void)
{
uint8_t report;
init();
// main loop
for (;;)
@ -81,6 +95,17 @@ int main (void)
temp_tick();
}
if (clock_flag_250ms & CLOCK_FLAG_250MS_STEPTIMEOUT) {
clock_flag_250ms &= ~CLOCK_FLAG_250MS_STEPTIMEOUT;
if (steptimeout > 25) {
disable_steppers();
}
else {
steptimeout++;
}
}
if (clock_flag_250ms & CLOCK_FLAG_250MS_REPORT) {
clock_flag_250ms &= ~CLOCK_FLAG_250MS_REPORT;
report++;

View File

@ -12,8 +12,14 @@
we NEED these for communication
*/
// RXD DIO0
// TXD DIO1
#define RESERVED_RXD DIO0
#define RESERVED_TXD DIO1
/*
user defined pins
adjust to suit your electronics,
or adjust your electronics to suit this
*/
#define X_STEP_PIN AIO0
#define X_DIR_PIN AIO1
@ -30,7 +36,10 @@
#define E_STEP_PIN DIO7
#define E_DIR_PIN DIO8
#define STEPPER_ENABLE_PIN DIO9
// list of PWM-able pins and corresponding timers
// timer1 is reserved for step timing
// OC0A DIO6
// OC0B DIO5
// OC1A DIO9
@ -41,12 +50,7 @@
#define HEATER_PIN DIO6
#define HEATER_PIN_PWM OC0A
#define FAN_PIN DIO5
#define SCK DIO13
#define MISO DIO12
#define MOSI DIO11
#define SS DIO10
// #define FAN_PIN DIO5
/*
X Stepper
@ -105,13 +109,25 @@
#define enable_heater() WRITE(HEATER_PIN, 1)
#define disable_heater() WRITE(HEATER_PIN, 0)
/*
fan
*/
#ifdef FAN_PIN
#define enable_fan() WRITE(FAN_PIN, 1)
#define disable_fan() WRITE(FAN_PIN, 0)
#else
#define enable_fan() if (0) {}
#define disable_fan() if (0) {}
#endif
/*
Stepper Enable (ATX PSU pwr_good signal?)
*/
#ifdef STEPPER_ENABLE_PIN
#define enable_steppers() WRITE(STEPPER_ENABLE_PIN, 1)
#define disable_steppers() WRITE(STEPPER_ENABLE_PIN, 0)
#define enable_steppers() WRITE(STEPPER_ENABLE_PIN, 0)
#define disable_steppers() WRITE(STEPPER_ENABLE_PIN, 1)
#else
#define enable_steppers() if (0) {}
#define disable_steppers() if (0) {}

View File

@ -71,6 +71,8 @@ uint16_t temp_read() {
WRITE(SS, 0);
SPCR = 0;
return 0;
}

View File

@ -9,16 +9,19 @@ ISR(TIMER1_COMPA_vect) {
if(movebuffer[mb_tail].live) {
// this interrupt can be interruptible
// TODO: remove when not debugging
disableTimerInterrupt();
sei();
// disableTimerInterrupt();
// sei();
// WRITE(SCK, 0);
dda_step(&(movebuffer[mb_tail]));
// WRITE(SCK, 1);
cli();
enableTimerInterrupt();
// cli();
// enableTimerInterrupt();
}
else
else {
next_move();
}
}
void setupTimerInterrupt()