time to save, also changed makefile to atmega328 because I fried my 168

This commit is contained in:
Michael Moon 2010-03-04 21:19:18 +11:00
parent 8575ae3480
commit 76834e6636
6 changed files with 120 additions and 170 deletions

View File

@ -22,7 +22,7 @@ SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dd
# #
##############################################################################
MCU_TARGET = atmega168
MCU_TARGET = atmega328p
F_CPU = 16000000L
##############################################################################
@ -73,7 +73,7 @@ clean:
size: $(PROGRAM).hex
@echo -n " SIZE "
@objdump -h mendel.elf | perl -ne '/.(data|text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf "%d bytes (%d%% of %dkb)\n", $$a, $$a * 100 / 16384, 16 }'
@objdump -h mendel.elf | perl -ne '/.(data|text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf "%d bytes (%d%% of %dkb)\n", $$a, $$a * 100 / (14 * 1024), 14 }'
%.o: %.c
@echo " CC $@"

View File

@ -73,102 +73,102 @@
pins
*/
#define DIO0_PIN PD0
#define DIO0_PIN PIND0
#define DIO0_RPORT PIND
#define DIO0_WPORT PORTD
#define DIO0_DDR DDRD
#define DIO1_PIN PD1
#define DIO1_PIN PIND1
#define DIO1_RPORT PIND
#define DIO1_WPORT PORTD
#define DIO1_DDR DDRD
#define DIO2_PIN PD2
#define DIO2_PIN PIND2
#define DIO2_RPORT PIND
#define DIO2_WPORT PORTD
#define DIO2_DDR DDRD
#define DIO3_PIN PD3
#define DIO3_PIN PIND3
#define DIO3_RPORT PIND
#define DIO3_WPORT PORTD
#define DIO3_DDR DDRD
#define DIO4_PIN PD4
#define DIO4_PIN PIND4
#define DIO4_RPORT PIND
#define DIO4_WPORT PORTD
#define DIO4_DDR DDRD
#define DIO5_PIN PD5
#define DIO5_PIN PIND5
#define DIO5_RPORT PIND
#define DIO5_WPORT PORTD
#define DIO5_DDR DDRD
#define DIO6_PIN PD6
#define DIO6_PIN PIND6
#define DIO6_RPORT PIND
#define DIO6_WPORT PORTD
#define DIO6_DDR DDRD
#define DIO7_PIN PD7
#define DIO7_PIN PIND7
#define DIO7_RPORT PIND
#define DIO7_WPORT PORTD
#define DIO7_DDR DDRD
#define DIO8_PIN PB0
#define DIO8_PIN PINB0
#define DIO8_RPORT PINB
#define DIO8_WPORT PORTB
#define DIO8_DDR DDRB
#define DIO9_PIN PB1
#define DIO9_PIN PINB1
#define DIO9_RPORT PINB
#define DIO9_WPORT PORTB
#define DIO9_DDR DDRB
#define DIO10_PIN PB2
#define DIO10_PIN PINB2
#define DIO10_RPORT PINB
#define DIO10_WPORT PORTB
#define DIO10_DDR DDRB
#define DIO11_PIN PB3
#define DIO11_PIN PINB3
#define DIO11_RPORT PINB
#define DIO11_WPORT PORTB
#define DIO11_DDR DDRB
#define DIO12_PIN PB4
#define DIO12_PIN PINB4
#define DIO12_RPORT PINB
#define DIO12_WPORT PORTB
#define DIO12_DDR DDRB
#define DIO13_PIN PB5
#define DIO13_PIN PINB5
#define DIO13_RPORT PINB
#define DIO13_WPORT PORTB
#define DIO13_DDR DDRB
#define AIO0_PIN PC0
#define AIO0_PIN PINC0
#define AIO0_RPORT PINC
#define AIO0_WPORT PORTC
#define AIO0_DDR DDRC
#define AIO1_PIN PC1
#define AIO1_PIN PINC1
#define AIO1_RPORT PINC
#define AIO1_WPORT PORTC
#define AIO1_DDR DDRC
#define AIO2_PIN PC2
#define AIO2_PIN PINC2
#define AIO2_RPORT PINC
#define AIO2_WPORT PORTC
#define AIO2_DDR DDRC
#define AIO3_PIN PC3
#define AIO3_PIN PINC3
#define AIO3_RPORT PINC
#define AIO3_WPORT PORTC
#define AIO3_DDR DDRC
#define AIO4_PIN PC4
#define AIO4_PIN PINC4
#define AIO4_RPORT PINC
#define AIO4_WPORT PORTC
#define AIO4_DDR DDRC
#define AIO5_PIN PC5
#define AIO5_PIN PINC5
#define AIO5_RPORT PINC
#define AIO5_WPORT PORTC
#define AIO5_DDR DDRC

View File

@ -127,7 +127,6 @@ void dda_create(DDA *dda, TARGET *target) {
uint32_t distance;
// initialise DDA to a known state
// dda->move_duration = 0;
dda->live = 0;
dda->total_steps = 0;
@ -141,13 +140,11 @@ void dda_create(DDA *dda, TARGET *target) {
dda->y_delta = abs32(target->Y - startpoint.Y);
dda->z_delta = abs32(target->Z - startpoint.Z);
dda->e_delta = abs32(target->E - startpoint.E);
// dda->f_delta = delta32(target->F, startpoint.F);
dda->x_direction = (target->X >= startpoint.X)?1:0;
dda->y_direction = (target->Y >= startpoint.Y)?1:0;
dda->z_direction = (target->Z >= startpoint.Z)?1:0;
dda->e_direction = (target->E >= startpoint.E)?1:0;
// dda->f_direction = (target->F >= startpoint.F)?1:0;
if (1) {
if (dda->x_direction == 0)
@ -161,10 +158,8 @@ void dda_create(DDA *dda, TARGET *target) {
serwrite_uint32(dda->z_delta); serial_writechar(',');
if (dda->e_direction == 0)
serial_writechar('-');
serwrite_uint32(dda->e_delta);/* serial_writechar(',');*/
// if (dda->f_direction == 0)
// serial_writechar('-');
// serwrite_uint32(dda->f_delta);
serwrite_uint32(dda->e_delta);
serial_writestr_P(PSTR("] ["));
}
@ -178,7 +173,7 @@ void dda_create(DDA *dda, TARGET *target) {
dda->total_steps = dda->e_delta;
if (1) {
serwrite_uint32(dda->total_steps); serial_writechar(',');
serial_writestr_P(PSTR("ts:")); serwrite_uint32(dda->total_steps);
}
if (dda->total_steps == 0) {
@ -189,7 +184,7 @@ void dda_create(DDA *dda, TARGET *target) {
steptimeout = 0;
power_on();
dda->x_counter = dda->y_counter = dda->z_counter = dda->e_counter = dda->f_counter =
dda->x_counter = dda->y_counter = dda->z_counter = dda->e_counter =
-(dda->total_steps >> 1);
// since it's unusual to combine X, Y and Z changes in a single move on reprap, check if we can use simpler approximations before trying the full 3d approximation.
@ -204,7 +199,7 @@ void dda_create(DDA *dda, TARGET *target) {
distance = dda->e_delta * UM_PER_STEP_E;
if (1) {
serwrite_uint32(distance); serial_writechar(',');
serial_writestr_P(PSTR(",ds:")); serwrite_uint32(distance);
}
// pre-calculate move speed in millimeter microseconds per step minute for less math in interrupt context
@ -221,15 +216,15 @@ void dda_create(DDA *dda, TARGET *target) {
// timer.c setTimer() routine altered for same reason
// changed distance * 6000 .. * F_CPU / 100000 to
// distance * 2400 .. * F_CPU / 40000 so we can move a distance of 1800mm without killing our registers
// distance * 2400 .. * F_CPU / 40000 so we can move a distance of up to 1800mm without overflowing
uint32_t move_duration = ((distance * 2400) / dda->total_steps) * (F_CPU / 40000);
// c is initial step time in IOclk ticks
dda->c = (move_duration / startpoint.F) << 8;
if (1) {
serwrite_uint32(move_duration); serial_writechar(',');
serwrite_uint32(dda->c); serial_writechar(',');
serial_writestr_P(PSTR(",md:")); serwrite_uint32(move_duration);
serial_writestr_P(PSTR(",c:")); serwrite_uint32(dda->c >> 8);
}
if (startpoint.F != target->F) {
@ -247,7 +242,7 @@ void dda_create(DDA *dda, TARGET *target) {
// the raw equation WILL overflow at high step rates, but 64 bit math routines take waay too much space
// at 65536 mm/min (1092mm/s), ssq/esq overflows, and dsq is also close to overflowing if esq/ssq is small
// but if ssq-esq is small, ssq/dsq is only a few bits
// we'll have to do it a few different ways depending on the msb location in each
// we'll have to do it a few different ways depending on the msb locations of each
if ((msb_tot + msb_ssq) <= 30) {
// we have room to do all the multiplies first
serial_writechar('A');
@ -265,8 +260,7 @@ void dda_create(DDA *dda, TARGET *target) {
}
if (1) {
serial_writestr_P(PSTR("\n{DDA:CA c:")); serwrite_uint32(dda->c >> 8);
serial_writestr_P(PSTR(", end_c:")); serwrite_uint32(dda->end_c >> 8);
serial_writestr_P(PSTR("\n{DDA:CA end_c:")); serwrite_uint32(dda->end_c >> 8);
serial_writestr_P(PSTR(", n:")); serwrite_int32(dda->n);
serial_writestr_P(PSTR(", md:")); serwrite_uint32(move_duration);
serial_writestr_P(PSTR(", ssq:")); serwrite_uint32(ssq);
@ -353,12 +347,6 @@ void dda_step(DDA *dda) {
#define Y_CAN_STEP 2
#define Z_CAN_STEP 4
#define E_CAN_STEP 8
// #define F_CAN_STEP 16
// #define REAL_MOVE 32
// #define F_REAL_STEP 64
// if (1)
// serial_writechar('!');
// step_option |= can_step(x_min(), x_max(), current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP;
step_option |= can_step(0 , 0 , current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP;
@ -372,8 +360,6 @@ void dda_step(DDA *dda) {
if (step_option & X_CAN_STEP) {
dda->x_counter -= dda->x_delta;
if (dda->x_counter < 0) {
// step_option |= REAL_MOVE;
x_step();
if (dda->x_direction)
current_position.X++;
@ -387,8 +373,6 @@ void dda_step(DDA *dda) {
if (step_option & Y_CAN_STEP) {
dda->y_counter -= dda->y_delta;
if (dda->y_counter < 0) {
// step_option |= REAL_MOVE;
y_step();
if (dda->y_direction)
current_position.Y++;
@ -402,8 +386,6 @@ void dda_step(DDA *dda) {
if (step_option & Z_CAN_STEP) {
dda->z_counter -= dda->z_delta;
if (dda->z_counter < 0) {
// step_option |= REAL_MOVE;
z_step();
if (dda->z_direction)
current_position.Z++;
@ -417,8 +399,6 @@ void dda_step(DDA *dda) {
if (step_option & E_CAN_STEP) {
dda->e_counter -= dda->e_delta;
if (dda->e_counter < 0) {
// step_option |= REAL_MOVE;
e_step();
if (dda->e_direction)
current_position.E++;
@ -432,33 +412,12 @@ void dda_step(DDA *dda) {
#if STEP_INTERRUPT_INTERRUPTIBLE
// since we have sent steps to all the motors that will be stepping and the rest of this function isn't so time critical,
// this interrupt can now be interruptible
// however we must ensure that we don't step again while computing the below, so disable *this* interrupt but allow others to fire
disableTimerInterrupt();
sei();
#endif
// if (step_option & F_CAN_STEP) {
// dda->f_counter -= dda->f_delta;
// // since we don't allow total_steps to be defined by F, we may need to step multiple times if f_delta is greater than total_steps
// // loops in interrupt context are a bad idea, but this is the best way to do this that I've come up with so far
// while (dda->f_counter < 0) {
//
// dda->f_counter += dda->total_steps;
//
// if (dda->f_direction) {
// current_position.F += 1;
// if (current_position.F > dda->endpoint.F)
// current_position.F = dda->endpoint.F;
// }
// else {
// current_position.F -= 1;
// if (current_position.F < dda->endpoint.F)
// current_position.F = dda->endpoint.F;
// }
//
// step_option |= F_REAL_STEP;
// }
// }
// linear acceleration magic, courtesy of http://www.embedded.com/columns/technicalinsights/56800129?printable=true
if (dda->accel) {
if (
((dda->n > 0) && (dda->c > dda->end_c)) ||
@ -468,11 +427,9 @@ void dda_step(DDA *dda) {
dda->n += 4;
setTimer(dda->c >> 8);
// debug
if (0) {
// serial_writestr_P(PSTR("nc:"));
serwrite_uint32(dda->c >> 8);
// serial_writestr_P(PSTR(", nn:"));
// serwrite_uint32(dda->n);
serial_writestr_P(PSTR("/"));
}
}
@ -487,27 +444,17 @@ void dda_step(DDA *dda) {
// 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 do anything at all, we're still running
// otherwise, must have finished
else {
dda->live = 0;
// linear acceleration code doesn't use F during a move, so we must update it here
// linear acceleration code doesn't alter F during a move, so we must update it here
// in theory, we *could* update F, but that would require a divide in interrupt context which should be avoided if at all possible
current_position.F = dda->endpoint.F;
}
// if (1) {
// serial_writechar('x'); serwrite_hex8(step_option);
// }
// turn off step outputs, hopefully they've been on long enough by now to register with the drivers
// if not, too bad. or insert a (very!) small delay here, or fire up a spare timer or something
// if not, too bad. or insert a (very!) small delay here, or fire up a spare timer or something.
// we also hope that we don't step before the drivers register the low- limit maximum speed if you think this is a problem.
unstep();
}

View File

@ -19,36 +19,38 @@ typedef struct {
uint32_t F;
} TARGET;
// this is a digital differential analyser data struct, holding both the initial values and the counters as it progresses
// this is a digital differential analyser data struct
typedef struct {
// this is where we should finish
TARGET endpoint;
uint8_t x_direction :1;
uint8_t y_direction :1;
uint8_t z_direction :1;
uint8_t e_direction :1;
uint8_t f_direction :1;
// status fields
uint8_t nullmove :1;
uint8_t live :1;
uint8_t accel :1;
// directions
uint8_t x_direction :1;
uint8_t y_direction :1;
uint8_t z_direction :1;
uint8_t e_direction :1;
// distances
uint32_t x_delta;
uint32_t y_delta;
uint32_t z_delta;
uint32_t e_delta;
uint32_t f_delta;
// bresenham counters
int32_t x_counter;
int32_t y_counter;
int32_t z_counter;
int32_t e_counter;
int32_t f_counter;
// total number of steps: set to max(x_delta, y_delta, z_delta, e_delta)
uint32_t total_steps;
// uint32_t move_duration;
// for linear acceleration
// linear acceleration variables: c and end_c are 24.8 fixed point timer values, n is the tracking variable
uint32_t c;
uint32_t end_c;
int32_t n;
@ -59,9 +61,10 @@ typedef struct {
*/
// steptimeout is set to zero when we step, and increases over time so we can turn the motors off when they've been idle for a while
extern uint8_t steptimeout;
extern uint8_t steptimeout;
// startpoint holds the end position of the most recently created DDA, so we know where the next one starts
// startpoint holds the endpoint of the most recently created DDA, so we know where the next one created starts
// could also be called last_endpoint
extern TARGET startpoint;
// current_position holds the machine's current position. this is only updated when we step, or when G92 (set home) is received.
@ -73,10 +76,17 @@ extern TARGET current_position;
uint32_t approx_distance( uint32_t dx, uint32_t dy ) __attribute__ ((hot));
uint32_t approx_distance_3( uint32_t dx, uint32_t dy, uint32_t dz ) __attribute__ ((hot));
// const because return value is always the same given the same v
const uint8_t msbloc (uint32_t v) __attribute__ ((const));
// create a DDA
void dda_create(DDA *dda, TARGET *target);
// start a created DDA (called from timer interrupt)
void dda_start(DDA *dda) __attribute__ ((hot));
// DDA takes one step (called from timer interrupt)
void dda_step(DDA *dda) __attribute__ ((hot));
#endif /* _DDA_H */

View File

@ -85,7 +85,7 @@ void init(void) {
// set up clock
clock_setup();
// set up feedrate
// set up default feedrate
current_position.F = startpoint.F = next_target.target.F = FEEDRATE_SLOW_Z;
// enable interrupts
@ -96,6 +96,7 @@ void init(void) {
// say hi to host
serial_writestr_P(PSTR("Start\nOK\n"));
}
void clock_250ms(void) {
@ -105,21 +106,13 @@ void clock_250ms(void) {
temp_tick();
if (steptimeout > (30 * 4)) {
if (temp_get_target() == 0)
power_off();
power_off();
}
else
else if (temp_get_target() == 0)
steptimeout++;
ifclock (CLOCK_FLAG_1S) {
ifclock(CLOCK_FLAG_1S) {
if (DEBUG) {
// current move
serial_writestr_P(PSTR("DDA: f#"));
serwrite_int32(movebuffer[mb_tail].f_counter);
serial_writechar('/');
serwrite_int16(movebuffer[mb_tail].f_delta);
serial_writechar('\n');
// current position
serial_writestr_P(PSTR("Pos: "));
serwrite_int32(current_position.X);

View File

@ -12,12 +12,12 @@
we NEED these for communication
*/
#define RESERVED_RXD DIO0
#define RESERVED_TXD DIO1
#define RESERVED_SCK DIO13
#define RESERVED_MISO DIO12
#define RESERVED_MOSI DIO11
#define RESERVED_SS DIO10
#define RESERVED_RXD DIO0
#define RESERVED_TXD DIO1
#define RESERVED_SCK DIO13
#define RESERVED_MISO DIO12
#define RESERVED_MOSI DIO11
#define RESERVED_SS DIO10
/*
user defined pins
@ -25,87 +25,87 @@
or adjust your electronics to suit this
*/
#define X_STEP_PIN AIO0
#define X_DIR_PIN AIO1
#define X_MIN_PIN AIO2
#define X_STEP_PIN AIO0
#define X_DIR_PIN AIO1
#define X_MIN_PIN AIO2
#define Y_STEP_PIN AIO3
#define Y_DIR_PIN AIO4
#define Y_MIN_PIN AIO5
#define Y_STEP_PIN AIO3
#define Y_DIR_PIN AIO4
#define Y_MIN_PIN AIO5
#define Z_STEP_PIN DIO2
#define Z_DIR_PIN DIO3
#define Z_MIN_PIN DIO4
#define Z_STEP_PIN DIO2
#define Z_DIR_PIN DIO3
#define Z_MIN_PIN DIO4
#define E_STEP_PIN DIO7
#define E_DIR_PIN DIO8
#define E_STEP_PIN DIO7
#define E_DIR_PIN DIO8
#define STEPPER_ENABLE_PIN DIO9
#define STEPPER_ENABLE_PIN DIO9
// list of PWM-able pins and corresponding timers
// timer1 is used for step timing so don't use OC1A/OC1B (DIO9/DIO10)
// OC0A DIO6
// OC0B DIO5
// OC1A DIO9
// OC1B DIO10
// OC2A DIO11
// OC2B DIO3
// OC0A DIO6
// OC0B DIO5
// OC1A DIO9
// OC1B DIO10
// OC2A DIO11
// OC2B DIO3
#define HEATER_PIN DIO6
#define HEATER_PWM OCR0A
#define HEATER_PIN DIO6
#define HEATER_PWM OCR0A
// #define FAN_PIN DIO5
#define FAN_PIN DIO5
// #define FAN_PIN_PWM OC0B
/*
X Stepper
*/
#define _x_step(st) WRITE(X_STEP_PIN, st)
#define x_step() _x_step(1);
#define x_direction(dir) WRITE(X_DIR_PIN, dir)
#define x_min() READ(X_MIN_PIN)
#define _x_step(st) WRITE(X_STEP_PIN, st)
#define x_step() _x_step(1);
#define x_direction(dir) WRITE(X_DIR_PIN, dir)
#define x_min() READ(X_MIN_PIN)
#ifdef X_MAX_PIN
#define x_max() READ(X_MAX_PIN)
#define x_max() READ(X_MAX_PIN)
#else
#define x_max() (0)
#define x_max() (0)
#endif
/*
Y Stepper
*/
#define _y_step(st) WRITE(Y_STEP_PIN, st)
#define y_step() _y_step(1);
#define y_direction(dir) WRITE(Y_DIR_PIN, dir)
#define y_min() READ(Y_MIN_PIN)
#define _y_step(st) WRITE(Y_STEP_PIN, st)
#define y_step() _y_step(1);
#define y_direction(dir) WRITE(Y_DIR_PIN, dir)
#define y_min() READ(Y_MIN_PIN)
#ifdef Y_MAX_PIN
#define y_max() READ(Y_MAX_PIN)
#define y_max() READ(Y_MAX_PIN)
#else
#define y_max() (0)
#define y_max() (0)
#endif
/*
Z Stepper
*/
#define _z_step(st) WRITE(Z_STEP_PIN, st)
#define z_step() _z_step(1);
#define z_direction(dir) WRITE(Z_DIR_PIN, dir)
#define z_min() READ(Z_MIN_PIN)
#define _z_step(st) WRITE(Z_STEP_PIN, st)
#define z_step() _z_step(1);
#define z_direction(dir) WRITE(Z_DIR_PIN, dir)
#define z_min() READ(Z_MIN_PIN)
#ifdef Z_MAX_PIN
#define z_max() READ(Z_MAX_PIN)
#define z_max() READ(Z_MAX_PIN)
#else
#define z_max() (0)
#define z_max() (0)
#endif
/*
Extruder
*/
#define _e_step(st) WRITE(E_STEP_PIN, st)
#define e_step() _e_step(1);
#define e_direction(dir) WRITE(E_DIR_PIN, dir)
#define _e_step(st) WRITE(E_STEP_PIN, st)
#define e_step() _e_step(1);
#define e_direction(dir) WRITE(E_DIR_PIN, dir)
/*
Heater
@ -140,11 +140,11 @@
// #define power_on() WRITE(STEPPER_ENABLE_PIN, 0)
// #define power_off() WRITE(STEPPER_ENABLE_PIN, 1)
// for connection to ATX PSU PWR_ON signal
#define power_on() do { WRITE(STEPPER_ENABLE_PIN, 0); SET_OUTPUT(STEPPER_ENABLE_PIN); } while (0)
#define power_off() SET_INPUT(STEPPER_ENABLE_PIN)
#define power_on() do { WRITE(STEPPER_ENABLE_PIN, 0); SET_OUTPUT(STEPPER_ENABLE_PIN); } while (0)
#define power_off() SET_INPUT(STEPPER_ENABLE_PIN)
#else
#define power_on() if (0) {}
#define power_off() if (0) {}
#define power_on() if (0) {}
#define power_off() if (0) {}
#endif
/*
@ -152,6 +152,6 @@
(so we don't have to delay in interrupt context)
*/
#define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0)
#define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0)
#endif /* _PINOUT_H */