time to save, added a tiny printf implementation which actually gives less code than printing everything out manually, waiting for temperature is now queueable so subsequent moves can be buffered ahead of time, and a debug flags system for dynamic enable/disable of debug. btw, atmega168 doesn't have enough space for debug so turn it off if you have one.
This commit is contained in:
parent
06cdfaa251
commit
bce08901d8
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
PROGRAM = mendel
|
||||
|
||||
SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c watchdog.c
|
||||
SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c
|
||||
|
||||
##############################################################################
|
||||
# #
|
||||
|
|
@ -41,7 +41,7 @@ DEFS = -DF_CPU=$(F_CPU)
|
|||
# DEFS += "-DREQUIRE_LINENUMBER"
|
||||
# DEFS += "-DREQUIRE_CHECKSUM"
|
||||
|
||||
OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=0
|
||||
OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG
|
||||
# OPTIMIZE = -O0
|
||||
CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps
|
||||
LDFLAGS = -Wl,--as-needed -Wl,--gc-sections
|
||||
|
|
|
|||
112
mendel/dda.c
112
mendel/dda.c
|
|
@ -7,6 +7,8 @@
|
|||
#include "serial.h"
|
||||
#include "sermsg.h"
|
||||
#include "dda_queue.h"
|
||||
#include "debug.h"
|
||||
#include "sersendf.h"
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(v) (((v) >= 0)?(v):(-(v)))
|
||||
|
|
@ -16,10 +18,6 @@
|
|||
#define ABSDELTA(a, b) (((a) >= (b))?((a) - (b)):((b) - (a)))
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
step timeout
|
||||
*/
|
||||
|
|
@ -30,8 +28,8 @@ uint8_t steptimeout = 0;
|
|||
position tracking
|
||||
*/
|
||||
|
||||
TARGET startpoint = { 0, 0, 0, 0, 0 };
|
||||
TARGET current_position = { 0, 0, 0, 0, 0 };
|
||||
TARGET startpoint __attribute__ ((__section__ (".bss")));
|
||||
TARGET current_position __attribute__ ((__section__ (".bss")));
|
||||
|
||||
/*
|
||||
utility functions
|
||||
|
|
@ -129,8 +127,9 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
// initialise DDA to a known state
|
||||
dda->live = 0;
|
||||
dda->total_steps = 0;
|
||||
dda->waitfor_temp = 0;
|
||||
|
||||
if (1)
|
||||
if (debug_flags & DEBUG_DDA)
|
||||
serial_writestr_P(PSTR("\n{DDA_CREATE: ["));
|
||||
|
||||
// we end at the passed target
|
||||
|
|
@ -146,7 +145,7 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
dda->z_direction = (target->Z >= startpoint.Z)?1:0;
|
||||
dda->e_direction = (target->E >= startpoint.E)?1:0;
|
||||
|
||||
if (1) {
|
||||
if (debug_flags & DEBUG_DDA) {
|
||||
if (dda->x_direction == 0)
|
||||
serial_writechar('-');
|
||||
serwrite_uint32(dda->x_delta); serial_writechar(',');
|
||||
|
|
@ -172,7 +171,7 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
if (dda->e_delta > dda->total_steps)
|
||||
dda->total_steps = dda->e_delta;
|
||||
|
||||
if (1) {
|
||||
if (debug_flags & DEBUG_DDA) {
|
||||
serial_writestr_P(PSTR("ts:")); serwrite_uint32(dda->total_steps);
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +197,7 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
if (distance < 2)
|
||||
distance = dda->e_delta * UM_PER_STEP_E;
|
||||
|
||||
if (1) {
|
||||
if (debug_flags & DEBUG_DDA) {
|
||||
serial_writestr_P(PSTR(",ds:")); serwrite_uint32(distance);
|
||||
}
|
||||
|
||||
|
|
@ -222,7 +221,7 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
// c is initial step time in IOclk ticks
|
||||
dda->c = (move_duration / startpoint.F) << 8;
|
||||
|
||||
if (1) {
|
||||
if (debug_flags & DEBUG_DDA) {
|
||||
serial_writestr_P(PSTR(",md:")); serwrite_uint32(move_duration);
|
||||
serial_writestr_P(PSTR(",c:")); serwrite_uint32(dda->c >> 8);
|
||||
}
|
||||
|
|
@ -245,30 +244,34 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
// 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');
|
||||
if (debug_flags & DEBUG_DDA)
|
||||
serial_writechar('A');
|
||||
dda->n = ((int32_t) (dda->total_steps * ssq) / dsq) + 1;
|
||||
}
|
||||
else if (msb_tot >= msb_ssq) {
|
||||
// total steps has more precision
|
||||
serial_writechar('B');
|
||||
if (debug_flags & DEBUG_DDA)
|
||||
serial_writechar('B');
|
||||
dda->n = (((int32_t) dda->total_steps / dsq) * (int32_t) ssq) + 1;
|
||||
}
|
||||
else {
|
||||
// otherwise
|
||||
serial_writechar('C');
|
||||
if (debug_flags & DEBUG_DDA)
|
||||
serial_writechar('C');
|
||||
dda->n = (((int32_t) ssq / dsq) * (int32_t) dda->total_steps) + 1;
|
||||
}
|
||||
|
||||
if (1) {
|
||||
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);
|
||||
serial_writestr_P(PSTR(", esq:")); serwrite_uint32(esq);
|
||||
serial_writestr_P(PSTR(", dsq:")); serwrite_int32(dsq);
|
||||
serial_writestr_P(PSTR(", msbssq:")); serwrite_uint8(msb_ssq);
|
||||
serial_writestr_P(PSTR(", msbtot:")); serwrite_uint8(msb_tot);
|
||||
serial_writestr_P(PSTR("}\n"));
|
||||
if (debug_flags & DEBUG_DDA) {
|
||||
// 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);
|
||||
// serial_writestr_P(PSTR(", esq:")); serwrite_uint32(esq);
|
||||
// serial_writestr_P(PSTR(", dsq:")); serwrite_int32(dsq);
|
||||
// serial_writestr_P(PSTR(", msbssq:")); serwrite_uint8(msb_ssq);
|
||||
// serial_writestr_P(PSTR(", msbtot:")); serwrite_uint8(msb_tot);
|
||||
// serial_writestr_P(PSTR("}\n"));
|
||||
sersendf_P(PSTR("\n{DDA:CA end_c:%lu, n:%ld, md:%lu, ssq:%lu, esq:%lu, dsq:%lu, msbssq:%u, msbtot:%u}\n"), dda->end_c >> 8, dda->n, move_duration, ssq, esq, dsq, msb_ssq, msb_tot);
|
||||
}
|
||||
|
||||
dda->accel = 1;
|
||||
|
|
@ -277,11 +280,13 @@ void dda_create(DDA *dda, TARGET *target) {
|
|||
dda->accel = 0;
|
||||
}
|
||||
|
||||
if (1)
|
||||
if (debug_flags & DEBUG_DDA)
|
||||
serial_writestr_P(PSTR("] }\n"));
|
||||
|
||||
// next dda starts where we finish
|
||||
memcpy(&startpoint, target, sizeof(TARGET));
|
||||
// E is always relative, reset it here
|
||||
startpoint.E = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -293,21 +298,26 @@ void dda_start(DDA *dda) {
|
|||
if (dda->nullmove) {
|
||||
// just change speed?
|
||||
current_position.F = dda->endpoint.F;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (dda->waitfor_temp) {
|
||||
serial_writestr_P(PSTR("Waiting for target temp\n"));
|
||||
}
|
||||
else {
|
||||
// ensure steppers are ready to go
|
||||
steptimeout = 0;
|
||||
power_on();
|
||||
|
||||
// ensure steppers are ready to go
|
||||
steptimeout = 0;
|
||||
power_on();
|
||||
// set direction outputs
|
||||
x_direction(dda->x_direction);
|
||||
y_direction(dda->y_direction);
|
||||
z_direction(dda->z_direction);
|
||||
e_direction(dda->e_direction);
|
||||
}
|
||||
|
||||
// set direction outputs
|
||||
x_direction(dda->x_direction);
|
||||
y_direction(dda->y_direction);
|
||||
z_direction(dda->z_direction);
|
||||
e_direction(dda->e_direction);
|
||||
|
||||
// ensure this dda starts
|
||||
dda->live = 1;
|
||||
// ensure this dda starts
|
||||
dda->live = 1;
|
||||
}
|
||||
|
||||
// set timeout for first step
|
||||
setTimer(dda->c >> 8);
|
||||
|
|
@ -347,6 +357,7 @@ void dda_step(DDA *dda) {
|
|||
#define Y_CAN_STEP 2
|
||||
#define Z_CAN_STEP 4
|
||||
#define E_CAN_STEP 8
|
||||
#define DID_STEP 128
|
||||
|
||||
// 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;
|
||||
|
|
@ -361,6 +372,7 @@ void dda_step(DDA *dda) {
|
|||
dda->x_counter -= dda->x_delta;
|
||||
if (dda->x_counter < 0) {
|
||||
x_step();
|
||||
step_option |= DID_STEP;
|
||||
if (dda->x_direction)
|
||||
current_position.X++;
|
||||
else
|
||||
|
|
@ -374,6 +386,7 @@ void dda_step(DDA *dda) {
|
|||
dda->y_counter -= dda->y_delta;
|
||||
if (dda->y_counter < 0) {
|
||||
y_step();
|
||||
step_option |= DID_STEP;
|
||||
if (dda->y_direction)
|
||||
current_position.Y++;
|
||||
else
|
||||
|
|
@ -387,6 +400,7 @@ void dda_step(DDA *dda) {
|
|||
dda->z_counter -= dda->z_delta;
|
||||
if (dda->z_counter < 0) {
|
||||
z_step();
|
||||
step_option |= DID_STEP;
|
||||
if (dda->z_direction)
|
||||
current_position.Z++;
|
||||
else
|
||||
|
|
@ -400,6 +414,7 @@ void dda_step(DDA *dda) {
|
|||
dda->e_counter -= dda->e_delta;
|
||||
if (dda->e_counter < 0) {
|
||||
e_step();
|
||||
step_option |= DID_STEP;
|
||||
if (dda->e_direction)
|
||||
current_position.E++;
|
||||
else
|
||||
|
|
@ -410,11 +425,11 @@ 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();
|
||||
// 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
|
||||
|
||||
// linear acceleration magic, courtesy of http://www.embedded.com/columns/technicalinsights/56800129?printable=true
|
||||
|
|
@ -426,12 +441,6 @@ void dda_step(DDA *dda) {
|
|||
dda->c = (int32_t) dda->c - ((int32_t) (dda->c * 2) / dda->n);
|
||||
dda->n += 4;
|
||||
setTimer(dda->c >> 8);
|
||||
|
||||
// debug
|
||||
if (0) {
|
||||
serwrite_uint32(dda->c >> 8);
|
||||
serial_writestr_P(PSTR("/"));
|
||||
}
|
||||
}
|
||||
else if (dda->c != dda->end_c) {
|
||||
dda->c = dda->end_c;
|
||||
|
|
@ -440,16 +449,19 @@ void dda_step(DDA *dda) {
|
|||
// else we are already at target speed
|
||||
}
|
||||
|
||||
if (step_option)
|
||||
if (step_option & DID_STEP) {
|
||||
// we stepped, reset timeout
|
||||
steptimeout = 0;
|
||||
|
||||
// if we could do anything at all, we're still running
|
||||
// otherwise, must have finished
|
||||
}
|
||||
else {
|
||||
dda->live = 0;
|
||||
// reset E- always relative
|
||||
current_position.E = 0;
|
||||
// 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
|
||||
// in theory, we *could* update F every step, but that would require a divide in interrupt context which should be avoided if at all possible
|
||||
current_position.F = dda->endpoint.F;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ typedef struct {
|
|||
uint8_t live :1;
|
||||
uint8_t accel :1;
|
||||
|
||||
// wait for temperature to stabilise flag
|
||||
uint8_t waitfor_temp :1;
|
||||
|
||||
// directions
|
||||
uint8_t x_direction :1;
|
||||
uint8_t y_direction :1;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
uint8_t mb_head = 0;
|
||||
uint8_t mb_tail = 0;
|
||||
DDA movebuffer[MOVEBUFFER_SIZE];
|
||||
DDA movebuffer[MOVEBUFFER_SIZE] __attribute__ ((__section__ (".bss")));
|
||||
|
||||
uint8_t queue_full() {
|
||||
return (((mb_tail - mb_head - 1) & (MOVEBUFFER_SIZE - 1)) == 0)?255:0;
|
||||
|
|
@ -42,13 +42,43 @@ void enqueue(TARGET *t) {
|
|||
enableTimerInterrupt();
|
||||
}
|
||||
|
||||
void enqueue_temp_wait() {
|
||||
// don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target
|
||||
while (queue_full())
|
||||
delay(WAITING_DELAY);
|
||||
|
||||
uint8_t h = mb_head;
|
||||
h++;
|
||||
if (h == MOVEBUFFER_SIZE)
|
||||
h = 0;
|
||||
|
||||
// wait for temp flag
|
||||
movebuffer[h].waitfor_temp = 1;
|
||||
movebuffer[h].nullmove = 0;
|
||||
#if (F_CPU & 0xFF000000) == 0
|
||||
// set "step" timeout to 1 second
|
||||
movebuffer[h].c = F_CPU << 8;
|
||||
#else
|
||||
// set "step" timeout to maximum
|
||||
movebuffer[h].c = 0xFFFFFF00;
|
||||
#endif
|
||||
|
||||
mb_head = h;
|
||||
|
||||
#ifdef XONXOFF
|
||||
// if queue is full, stop transmition
|
||||
if (queue_full())
|
||||
xoff();
|
||||
#endif
|
||||
|
||||
// fire up in case we're not running yet
|
||||
enableTimerInterrupt();
|
||||
}
|
||||
|
||||
void next_move() {
|
||||
if (queue_empty()) {
|
||||
#if STEP_INTERRUPT_INTERRUPTIBLE
|
||||
#else
|
||||
disableTimerInterrupt();
|
||||
#endif
|
||||
memcpy(&startpoint, ¤t_position, sizeof(TARGET));
|
||||
// memcpy(&startpoint, ¤t_position, sizeof(TARGET));
|
||||
startpoint.E = current_position.E = 0;
|
||||
}
|
||||
else {
|
||||
// next item
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ uint8_t queue_empty(void);
|
|||
// add a new target to the queue
|
||||
void enqueue(TARGET *t);
|
||||
|
||||
// add a wait for target temp to the queue
|
||||
void enqueue_temp_wait(void);
|
||||
|
||||
// called from step timer when current move is complete
|
||||
void next_move(void) __attribute__ ((hot));
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
#include "debug.h"
|
||||
|
||||
volatile uint8_t debug_flags;
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _DEBUG_H
|
||||
#define _DEBUG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_PID 1
|
||||
#define DEBUG_DDA 2
|
||||
#define DEBUG_POSITION 4
|
||||
#else
|
||||
// by setting these to zero, the compiler should optimise the relevant code out
|
||||
#define DEBUG_PID 0
|
||||
#define DEBUG_DDA 0
|
||||
#define DEBUG_POSITION 0
|
||||
#endif
|
||||
|
||||
#define DEBUG_ECHO 128
|
||||
|
||||
extern volatile uint8_t debug_flags;
|
||||
|
||||
#endif /* _DEBUG_H */
|
||||
|
|
@ -92,10 +92,16 @@ mendel_setup() {
|
|||
stty 115200 raw ignbrk -hup -echo ixon ixoff < /dev/arduino
|
||||
}
|
||||
|
||||
mendel_reset() {
|
||||
stty hup < /dev/arduino
|
||||
stty hup < /dev/arduino
|
||||
mendel_setup
|
||||
}
|
||||
|
||||
mendel_cmd() {
|
||||
(
|
||||
IFS=$' \t\n'
|
||||
LN=0
|
||||
RSC=0
|
||||
cmd="$*"
|
||||
echo "$cmd" >&3;
|
||||
while [ "$REPLY" != "OK" ]
|
||||
|
|
@ -105,6 +111,17 @@ mendel_cmd() {
|
|||
then
|
||||
echo "$REPLY"
|
||||
fi
|
||||
if [[ "$REPLY" =~ ^RESEND ]]
|
||||
then
|
||||
if [ "$RSC" -le 3 ]
|
||||
then
|
||||
echo "$cmd" >&3
|
||||
RSC=$(( $RSC + 1 ))
|
||||
else
|
||||
REPLY="OK"
|
||||
echo "Too many retries: aborting" >&2
|
||||
fi
|
||||
fi
|
||||
LN=$(( $LN + 1 ))
|
||||
done
|
||||
) 3<>/dev/arduino;
|
||||
|
|
@ -113,15 +130,26 @@ mendel_cmd() {
|
|||
mendel_cmd_hr() {
|
||||
(
|
||||
IFS=$' \t\n'
|
||||
LN=0
|
||||
cmd="$*"
|
||||
echo "$cmd" >&3;
|
||||
RSC=0
|
||||
echo "$cmd" >&3
|
||||
echo "> $cmd"
|
||||
while [ "$REPLY" != "OK" ]
|
||||
do
|
||||
read -u 3
|
||||
echo "< $REPLY"
|
||||
LN=$(( $LN + 1 ))
|
||||
if [[ "$REPLY" =~ ^RESEND ]]
|
||||
then
|
||||
if [ "$RSC" -le 3 ]
|
||||
then
|
||||
echo "$cmd" >&3
|
||||
echo "> $cmd"
|
||||
RSC=$(( $RSC + 1))
|
||||
else
|
||||
REPLY="OK"
|
||||
echo "Too many retries: aborting" >&2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
) 3<>/dev/arduino;
|
||||
}
|
||||
|
|
|
|||
153
mendel/gcode.c
153
mendel/gcode.c
|
|
@ -11,17 +11,15 @@
|
|||
#include "dda.h"
|
||||
#include "clock.h"
|
||||
#include "watchdog.h"
|
||||
#include "debug.h"
|
||||
|
||||
uint8_t option_bitfield;
|
||||
#define OPTION_COMMENT 128
|
||||
#define OPTION_CHECKSUM 64
|
||||
#define OPTION_ECHO 32
|
||||
|
||||
decfloat read_digit;
|
||||
uint8_t last_field = 0;
|
||||
|
||||
const char alphabet[] = "GMXYZEFSPN*";
|
||||
|
||||
GCODE_COMMAND next_target = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 };
|
||||
decfloat read_digit __attribute__ ((__section__ (".bss")));
|
||||
|
||||
GCODE_COMMAND next_target __attribute__ ((__section__ (".bss")));
|
||||
|
||||
/*
|
||||
utility functions
|
||||
|
|
@ -105,11 +103,9 @@ void SpecialMoveE(int32_t e, uint32_t f) {
|
|||
****************************************************************************/
|
||||
|
||||
void scan_char(uint8_t c) {
|
||||
static uint8_t last_field = 0;
|
||||
|
||||
// move this below switch(c) if the asterisk isn't included in the checksum
|
||||
#define crc(a, b) (a ^ b)
|
||||
if ((option_bitfield & OPTION_CHECKSUM) == 0)
|
||||
if (next_target.seen_checksum == 0)
|
||||
next_target.checksum_calculated = crc(next_target.checksum_calculated, c);
|
||||
|
||||
// uppercase
|
||||
|
|
@ -123,14 +119,12 @@ void scan_char(uint8_t c) {
|
|||
switch (last_field) {
|
||||
case 'G':
|
||||
next_target.G = read_digit.mantissa;
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint8(next_target.G);
|
||||
break;
|
||||
case 'M':
|
||||
next_target.M = read_digit.mantissa;
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint8(next_target.M);
|
||||
break;
|
||||
case 'X':
|
||||
|
|
@ -138,8 +132,7 @@ void scan_char(uint8_t c) {
|
|||
next_target.target.X = decfloat_to_int(&read_digit, STEPS_PER_IN_X, 1);
|
||||
else
|
||||
next_target.target.X = decfloat_to_int(&read_digit, STEPS_PER_MM_X, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_int32(next_target.target.X);
|
||||
break;
|
||||
case 'Y':
|
||||
|
|
@ -147,8 +140,7 @@ void scan_char(uint8_t c) {
|
|||
next_target.target.Y = decfloat_to_int(&read_digit, STEPS_PER_IN_Y, 1);
|
||||
else
|
||||
next_target.target.Y = decfloat_to_int(&read_digit, STEPS_PER_MM_Y, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_int32(next_target.target.Y);
|
||||
break;
|
||||
case 'Z':
|
||||
|
|
@ -156,8 +148,7 @@ void scan_char(uint8_t c) {
|
|||
next_target.target.Z = decfloat_to_int(&read_digit, STEPS_PER_IN_Z, 1);
|
||||
else
|
||||
next_target.target.Z = decfloat_to_int(&read_digit, STEPS_PER_MM_Z, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_int32(next_target.target.Z);
|
||||
break;
|
||||
case 'E':
|
||||
|
|
@ -165,8 +156,7 @@ void scan_char(uint8_t c) {
|
|||
next_target.target.E = decfloat_to_int(&read_digit, STEPS_PER_IN_E, 1);
|
||||
else
|
||||
next_target.target.E = decfloat_to_int(&read_digit, STEPS_PER_MM_E, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint32(next_target.target.E);
|
||||
break;
|
||||
case 'F':
|
||||
|
|
@ -175,23 +165,21 @@ void scan_char(uint8_t c) {
|
|||
next_target.target.F = decfloat_to_int(&read_digit, 254, 10);
|
||||
else
|
||||
next_target.target.F = decfloat_to_int(&read_digit, 1, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint32(next_target.target.F);
|
||||
break;
|
||||
case 'S':
|
||||
// if this is temperature, multiply by 4 to convert to quarter-degree units
|
||||
// cosmetically this should be done in the temperature section,
|
||||
// but it takes less code, less memory and loses no precision if we do it here instead
|
||||
if (next_target.M == 104)
|
||||
if ((next_target.M == 104) || (next_target.M == 109))
|
||||
next_target.S = decfloat_to_int(&read_digit, 4, 1);
|
||||
// if this is heater PID stuff, multiply by PID_SCALE because we divide by PID_SCALE later on
|
||||
else if ((next_target.M >= 130) && (next_target.M <= 132))
|
||||
next_target.S = decfloat_to_int(&read_digit, PID_SCALE, 1);
|
||||
else
|
||||
next_target.S = decfloat_to_int(&read_digit, 1, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint16(next_target.S);
|
||||
break;
|
||||
case 'P':
|
||||
|
|
@ -200,18 +188,17 @@ void scan_char(uint8_t c) {
|
|||
next_target.P = decfloat_to_int(&read_digit, 1000, 1);
|
||||
else
|
||||
next_target.P = decfloat_to_int(&read_digit, 1, 1);
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint16(next_target.P);
|
||||
break;
|
||||
case 'N':
|
||||
next_target.N = decfloat_to_int(&read_digit, 1, 1);
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint32(next_target.N);
|
||||
break;
|
||||
case '*':
|
||||
next_target.checksum_read = decfloat_to_int(&read_digit, 1, 1);
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serwrite_uint8(next_target.checksum_read);
|
||||
break;
|
||||
}
|
||||
|
|
@ -224,12 +211,11 @@ void scan_char(uint8_t c) {
|
|||
}
|
||||
|
||||
// skip comments
|
||||
if ((option_bitfield & OPTION_COMMENT) == 0) {
|
||||
if (next_target.seen_comment == 0) {
|
||||
// new field?
|
||||
if (indexof(c, alphabet) >= 0) {
|
||||
last_field = c;
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serial_writechar(c);
|
||||
}
|
||||
|
||||
|
|
@ -272,12 +258,13 @@ void scan_char(uint8_t c) {
|
|||
break;
|
||||
case '*':
|
||||
next_target.seen_checksum = 1;
|
||||
option_bitfield |= OPTION_CHECKSUM;
|
||||
// option_bitfield |= OPTION_CHECKSUM;
|
||||
break;
|
||||
|
||||
// comments
|
||||
case ';':
|
||||
option_bitfield |= OPTION_COMMENT;
|
||||
next_target.seen_comment = 1;
|
||||
// option_bitfield |= OPTION_COMMENT;
|
||||
break;
|
||||
|
||||
// now for some numeracy
|
||||
|
|
@ -305,8 +292,7 @@ void scan_char(uint8_t c) {
|
|||
|
||||
// end of line
|
||||
if ((c == 10) || (c == 13)) {
|
||||
// if (DEBUG)
|
||||
if (option_bitfield & OPTION_ECHO)
|
||||
if (debug_flags & DEBUG_ECHO)
|
||||
serial_writechar(c);
|
||||
// process
|
||||
if (next_target.seen_G || next_target.seen_M) {
|
||||
|
|
@ -332,18 +318,20 @@ void scan_char(uint8_t c) {
|
|||
next_target.N_expected++;
|
||||
}
|
||||
else {
|
||||
serial_writestr_P(PSTR("RESEND: BAD CHECKSUM\n"));
|
||||
serial_writestr_P(PSTR("RESEND: BAD CHECKSUM: EXPECTED "));
|
||||
serwrite_uint8(next_target.checksum_calculated);
|
||||
serial_writestr_P(PSTR("\n"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
serial_writestr_P(PSTR("RESEND: BAD LINE NUMBER\n"));
|
||||
serial_writestr_P(PSTR("RESEND: BAD LINE NUMBER: EXPECTED "));
|
||||
serwrite_uint32(next_target.N_expected);
|
||||
serial_writestr_P(PSTR("\n"));
|
||||
}
|
||||
}
|
||||
// reset 'seen comment' and 'receiving checksum'
|
||||
option_bitfield &= (OPTION_COMMENT | OPTION_CHECKSUM);
|
||||
|
||||
// reset variables
|
||||
next_target.seen_X = next_target.seen_Y = next_target.seen_Z = next_target.seen_E = next_target.seen_F = next_target.seen_S = next_target.seen_P = next_target.N = next_target.checksum_read = next_target.checksum_calculated = 0;
|
||||
next_target.seen_X = next_target.seen_Y = next_target.seen_Z = next_target.seen_E = next_target.seen_F = next_target.seen_S = next_target.seen_P = next_target.seen_N = next_target.seen_checksum = next_target.seen_comment = next_target.checksum_read = next_target.checksum_calculated = 0;
|
||||
last_field = 0;
|
||||
read_digit.sign = 0;
|
||||
read_digit.mantissa = 0;
|
||||
|
|
@ -363,10 +351,14 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
gcmd->target.X += startpoint.X;
|
||||
gcmd->target.Y += startpoint.Y;
|
||||
gcmd->target.Z += startpoint.Z;
|
||||
gcmd->target.E += startpoint.E;
|
||||
}
|
||||
// E ALWAYS relative, otherwise we overflow our registers after only a few layers
|
||||
// gcmd->target.E += startpoint.E;
|
||||
// easier way to do this
|
||||
// startpoint.E = 0;
|
||||
// moved to dda.c, end of dda_create() and dda_queue.c, next_move()
|
||||
|
||||
// explicitly make unseen values equal to startpoint, otherwise relative position mode is a clusterfuck
|
||||
// explicitly make unseen values equal to startpoint, otherwise relative position mode gets messy
|
||||
if (gcmd->seen_X == 0)
|
||||
gcmd->target.X = startpoint.X;
|
||||
if (gcmd->seen_Y == 0)
|
||||
|
|
@ -511,18 +503,21 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
serial_writechar('\n');
|
||||
}
|
||||
}
|
||||
if (gcmd->seen_M) {
|
||||
else if (gcmd->seen_M) {
|
||||
switch (gcmd->M) {
|
||||
// M101- extruder on
|
||||
case 101:
|
||||
serial_writestr_P(PSTR("Waiting for extruder to reach target temperature\n"));
|
||||
// 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();
|
||||
}
|
||||
if (temp_achieved() == 0) {
|
||||
// serial_writestr_P(PSTR("Waiting for extruder to reach target temperature\n"));
|
||||
// // here we wait until target temperature is reached, and emulate main loop so the temperature can actually be updated
|
||||
// while (temp_achieved() == 0) {
|
||||
// ifclock(CLOCK_FLAG_250MS) {
|
||||
// // this is cosmetically nasty, but exactly what needs to happen
|
||||
// void clock_250ms(void);
|
||||
// clock_250ms();
|
||||
// }
|
||||
// }
|
||||
enqueue_temp_wait();
|
||||
}
|
||||
do {
|
||||
// backup feedrate, move E very quickly then restore feedrate
|
||||
|
|
@ -566,14 +561,52 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
// M106- fan on
|
||||
#ifdef FAN_PIN
|
||||
case 106:
|
||||
WRITE(FAN_PIN, 1);
|
||||
enable_fan();
|
||||
break;
|
||||
// M107- fan off
|
||||
case 107:
|
||||
WRITE(FAN_PIN, 0);
|
||||
disable_fan();
|
||||
break;
|
||||
#endif
|
||||
|
||||
// M109- set temp and wait
|
||||
case 109:
|
||||
temp_set(gcmd->S);
|
||||
if (gcmd->S) {
|
||||
enable_heater();
|
||||
power_on();
|
||||
}
|
||||
else {
|
||||
disable_heater();
|
||||
}
|
||||
enqueue_temp_wait();
|
||||
// while (!temp_achieved()) {
|
||||
// ifclock(CLOCK_FLAG_250MS) {
|
||||
// // this is cosmetically nasty, but exactly what needs to happen
|
||||
// void clock_250ms(void);
|
||||
// clock_250ms();
|
||||
// }
|
||||
// }
|
||||
break;
|
||||
|
||||
// M110- set line number
|
||||
case 110:
|
||||
gcmd->N_expected = gcmd->S - 1;
|
||||
break;
|
||||
// M111- set debug level
|
||||
#ifdef DEBUG
|
||||
case 111:
|
||||
debug_flags = gcmd->S;
|
||||
break;
|
||||
#endif
|
||||
// M112- immediate stop
|
||||
case 112:
|
||||
disableTimerInterrupt();
|
||||
power_off();
|
||||
break;
|
||||
// M113- extruder PWM
|
||||
// M114- report XYZEF to host
|
||||
|
||||
// M130- heater P factor
|
||||
case 130:
|
||||
if (gcmd->seen_S)
|
||||
|
|
@ -599,20 +632,22 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
temp_save_settings();
|
||||
break;
|
||||
|
||||
#ifdef DEBUG
|
||||
// M140- echo off
|
||||
case 140:
|
||||
option_bitfield &= ~OPTION_ECHO;
|
||||
debug_flags &= ~DEBUG_ECHO;
|
||||
serial_writestr_P(PSTR("Echo off\n"));
|
||||
break;
|
||||
// M141- echo on
|
||||
case 141:
|
||||
option_bitfield |= OPTION_ECHO;
|
||||
debug_flags |= DEBUG_ECHO;
|
||||
serial_writestr_P(PSTR("Echo on\n"));
|
||||
break;
|
||||
#endif
|
||||
|
||||
// DEBUG: return current position
|
||||
case 250:
|
||||
serial_writestr_P(PSTR("\n{X:"));
|
||||
serial_writestr_P(PSTR("{X:"));
|
||||
serwrite_int32(current_position.X);
|
||||
serial_writestr_P(PSTR(",Y:"));
|
||||
serwrite_int32(current_position.Y);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ typedef struct {
|
|||
uint8_t seen_P :1;
|
||||
uint8_t seen_N :1;
|
||||
uint8_t seen_checksum :1;
|
||||
uint8_t seen_comment :1;
|
||||
|
||||
uint8_t option_relative :1;
|
||||
uint8_t option_inches :1;
|
||||
|
|
|
|||
|
|
@ -62,13 +62,15 @@
|
|||
// http://blog.arcol.hu/?p=157 may help with this next one
|
||||
// I haven't tuned this at all- it's just a placeholder until I read the above carefully enough
|
||||
// does this refer to filament or extrudate? extrudate depends on XY distance vs E distance.. hm lets go with filament
|
||||
#define STEPS_PER_MM_E ((uint32_t) ((E_STEPS_PER_REV / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER)) + 0.5))
|
||||
// #define STEPS_PER_MM_E ((uint32_t) ((E_STEPS_PER_REV / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER / EXTRUDER_NOZZLE_DIAMETER)) + 0.5))
|
||||
|
||||
#define STEPS_PER_MM_E ((uint32_t) ((E_STEPS_PER_REV * EXTRUDER_NOZZLE_DIAMETER / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER)) + 0.5))
|
||||
|
||||
// same as above with 25.4 scale factor
|
||||
#define STEPS_PER_IN_X ((uint32_t) ((25.4 * X_STEPS_PER_REV / X_COG_CIRCUMFERENCE) + 0.5))
|
||||
#define STEPS_PER_IN_Y ((uint32_t) ((25.4 * Y_STEPS_PER_REV / Y_COG_CIRCUMFERENCE) + 0.5))
|
||||
#define STEPS_PER_IN_Z ((uint32_t) ((25.4 * Z_STEPS_PER_REV * Z_GEAR_RATIO) + 0.5))
|
||||
#define STEPS_PER_IN_E ((uint32_t) ((25.4 * E_STEPS_PER_REV / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER)) + 0.5))
|
||||
#define STEPS_PER_IN_E ((uint32_t) ((25.4 * E_STEPS_PER_REV * EXTRUDER_NOZZLE_DIAMETER / (EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER)) + 0.5))
|
||||
|
||||
// inverse, used in distance calculation during DDA setup
|
||||
#define UM_PER_STEP_X ((uint32_t) ((1000.0 / STEPS_PER_MM_X) + 0.5))
|
||||
|
|
|
|||
|
|
@ -16,10 +16,8 @@
|
|||
#include "temp.h"
|
||||
#include "sermsg.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
#include "debug.h"
|
||||
#include "sersendf.h"
|
||||
|
||||
void io_init(void) {
|
||||
// disable modules we don't use
|
||||
|
|
@ -44,17 +42,19 @@ void io_init(void) {
|
|||
|
||||
#ifdef HEATER_PIN
|
||||
WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN);
|
||||
#ifdef HEATER_PWM
|
||||
// setup PWM timer: fast PWM, no prescaler
|
||||
TCCR0A = MASK(WGM01) | MASK(WGM00);
|
||||
TCCR0B = MASK(CS00);
|
||||
TIMSK0 = 0;
|
||||
OCR0A = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FAN_PIN
|
||||
disable_fan();
|
||||
WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN);
|
||||
#endif
|
||||
|
||||
#if defined(HEATER_PWM) || defined(FAN_PWM)
|
||||
// setup PWM timer: fast PWM, no prescaler
|
||||
TCCR0A = MASK(WGM01) | MASK(WGM00);
|
||||
TCCR0B = MASK(CS00);
|
||||
TIMSK0 = 0;
|
||||
OCR0A = 0;
|
||||
OCR0B = 255;
|
||||
#endif
|
||||
|
||||
#ifdef STEPPER_ENABLE_PIN
|
||||
|
|
@ -115,32 +115,34 @@ void clock_250ms(void) {
|
|||
steptimeout++;
|
||||
|
||||
ifclock(CLOCK_FLAG_1S) {
|
||||
if (DEBUG) {
|
||||
if (debug_flags & DEBUG_POSITION) {
|
||||
// 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');
|
||||
// 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');
|
||||
sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F);
|
||||
|
||||
// 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');
|
||||
// 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');
|
||||
sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"), movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F);
|
||||
|
||||
// Queue
|
||||
print_queue();
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
#define HEATER_PWM OCR0A
|
||||
|
||||
#define FAN_PIN DIO5
|
||||
// #define FAN_PIN_PWM OC0B
|
||||
#define FAN_PWM OCR0B
|
||||
|
||||
/*
|
||||
X Stepper
|
||||
|
|
@ -124,8 +124,13 @@
|
|||
*/
|
||||
|
||||
#ifdef FAN_PIN
|
||||
#define enable_fan() WRITE(FAN_PIN, 1)
|
||||
#define disable_fan() do { WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN); } while (0)
|
||||
#ifdef FAN_PWM
|
||||
#define enable_fan() do { TCCR0A |= MASK(COM0B1); } while (0)
|
||||
#define disable_fan() do { TCCR0A &= ~MASK(COM0B1); } while (0)
|
||||
#else
|
||||
#define enable_fan() WRITE(FAN_PIN, 1)
|
||||
#define disable_fan() WRITE(FAN_PIN, 0);
|
||||
#endif
|
||||
#else
|
||||
#define enable_fan() if (0) {}
|
||||
#define disable_fan() if (0) {}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,14 @@ void serial_writeblock(void *data, int datalen)
|
|||
serial_writechar(((uint8_t *) data)[i]);
|
||||
}
|
||||
|
||||
void serial_writestr(uint8_t *data)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
// yes, this is *supposed* to be assignment rather than comparison, so we break when r is assigned zero
|
||||
for (uint8_t r; (r = data[i]); i++)
|
||||
serial_writechar(r);
|
||||
}
|
||||
|
||||
/*
|
||||
Write from FLASH
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ void serial_writechar(uint8_t data);
|
|||
// uint8_t serial_recvblock(uint8_t *block, int blocksize);
|
||||
void serial_writeblock(void *data, int datalen);
|
||||
|
||||
void serial_writestr(uint8_t *data);
|
||||
|
||||
// write from flash
|
||||
void serial_writechar_P(PGM_P data);
|
||||
void serial_writeblock_P(PGM_P data, int datalen);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
#include "sersendf.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "serial.h"
|
||||
#include "sermsg.h"
|
||||
|
||||
PGM_P str_ox = "0x";
|
||||
|
||||
void sersendf(char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
uint16_t i = 0;
|
||||
uint8_t c = 1, j = 0;
|
||||
for (; c != 0; i++) {
|
||||
c = format[i];
|
||||
if (j) {
|
||||
switch(c) {
|
||||
case 'l':
|
||||
j = 4;
|
||||
case 'u':
|
||||
if (j == 4)
|
||||
serwrite_uint32(va_arg(args, uint32_t));
|
||||
else
|
||||
serwrite_uint16(va_arg(args, uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'd':
|
||||
if (j == 4)
|
||||
serwrite_int32(va_arg(args, int32_t));
|
||||
else
|
||||
serwrite_int16(va_arg(args, int16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'p':
|
||||
case 'x':
|
||||
serial_writestr_P(str_ox);
|
||||
if (j == 4)
|
||||
serwrite_hex32(va_arg(args, uint32_t));
|
||||
else
|
||||
serwrite_hex16(va_arg(args, uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'c':
|
||||
serial_writechar(va_arg(args, uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 's':
|
||||
serial_writestr(va_arg(args, uint8_t *));
|
||||
j = 0;
|
||||
break;
|
||||
default:
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c == '%') {
|
||||
j = 2;
|
||||
}
|
||||
else {
|
||||
serial_writechar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void sersendf_P(PGM_P format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
uint16_t i = 0;
|
||||
uint8_t c = 1, j = 0;
|
||||
for (; c != 0; i++) {
|
||||
c = pgm_read_byte(&format[i]);
|
||||
if (j) {
|
||||
switch(c) {
|
||||
case 's':
|
||||
j = 1;
|
||||
break;
|
||||
case 'l':
|
||||
j = 4;
|
||||
break;
|
||||
case 'u':
|
||||
if (j == 4)
|
||||
serwrite_uint32(va_arg(args, uint32_t));
|
||||
else
|
||||
serwrite_uint16(va_arg(args, uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'd':
|
||||
if (j == 4)
|
||||
serwrite_int32(va_arg(args, int32_t));
|
||||
else
|
||||
serwrite_int16(va_arg(args, int16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'x':
|
||||
if (j == 4)
|
||||
serwrite_hex32(va_arg(args, uint32_t));
|
||||
else if (j == 1)
|
||||
serwrite_hex8(va_arg(args, uint16_t));
|
||||
else
|
||||
serwrite_hex16(va_arg(args, uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'c':
|
||||
serial_writechar(va_arg(args, uint16_t));
|
||||
case 'p':
|
||||
serwrite_hex16(va_arg(args, uint16_t));
|
||||
default:
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c == '%') {
|
||||
j = 2;
|
||||
}
|
||||
else {
|
||||
serial_writechar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _SERSENDF_H
|
||||
#define _SERSENDF_H
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
void sersendf(char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void sersendf_P(PGM_P format, ...);
|
||||
|
||||
#endif /* _SERSENDF_H */
|
||||
166
mendel/temp.c
166
mendel/temp.c
|
|
@ -27,6 +27,8 @@
|
|||
#include "sermsg.h"
|
||||
#include "timer.h"
|
||||
#include "dda.h"
|
||||
#include "sersendf.h"
|
||||
#include "debug.h"
|
||||
|
||||
uint16_t current_temp = 0;
|
||||
uint16_t target_temp = 0;
|
||||
|
|
@ -36,9 +38,9 @@ int16_t heater_i = 0;
|
|||
int16_t heater_d = 0;
|
||||
|
||||
#define DEFAULT_P 4096
|
||||
#define DEFAULT_I 64
|
||||
#define DEFAULT_D -12288
|
||||
#define DEFAULT_I_LIMIT 3072
|
||||
#define DEFAULT_I 256
|
||||
#define DEFAULT_D -14336
|
||||
#define DEFAULT_I_LIMIT 768
|
||||
int32_t p_factor = 0;
|
||||
int32_t i_factor = 0;
|
||||
int32_t d_factor = 0;
|
||||
|
|
@ -123,9 +125,6 @@ uint16_t temp_read() {
|
|||
}
|
||||
}
|
||||
|
||||
// if (DEBUG)
|
||||
// serial_writechar(']');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -152,39 +151,59 @@ uint8_t temp_achieved() {
|
|||
}
|
||||
|
||||
void temp_print() {
|
||||
serial_writestr_P(PSTR("T: "));
|
||||
// serial_writestr_P(PSTR("T: "));
|
||||
if (temp_flags & TEMP_FLAG_TCOPEN) {
|
||||
serial_writestr_P(PSTR("no thermocouple!"));
|
||||
serial_writestr_P(PSTR("T: no thermocouple!\n"));
|
||||
}
|
||||
else {
|
||||
serwrite_uint16(current_temp >> 2);
|
||||
serial_writechar('.');
|
||||
if (current_temp & 3) {
|
||||
if ((current_temp & 3) == 3)
|
||||
serial_writechar('7');
|
||||
else if ((current_temp & 3) == 1)
|
||||
serial_writechar('2');
|
||||
serial_writechar('5');
|
||||
}
|
||||
else {
|
||||
serial_writechar('0');
|
||||
}
|
||||
// serial_writestr_P(PSTR("°C"));
|
||||
serial_writechar('/');
|
||||
serwrite_uint16(target_temp >> 2);
|
||||
serial_writechar('.');
|
||||
if (target_temp & 3) {
|
||||
if ((target_temp & 3) == 3)
|
||||
serial_writechar('7');
|
||||
else if ((target_temp & 3) == 1)
|
||||
serial_writechar('2');
|
||||
serial_writechar('5');
|
||||
}
|
||||
else {
|
||||
serial_writechar('0');
|
||||
}
|
||||
// serwrite_uint16(current_temp >> 2);
|
||||
// serial_writechar('.');
|
||||
// if (current_temp & 3) {
|
||||
// if ((current_temp & 3) == 3)
|
||||
// serial_writechar('7');
|
||||
// else if ((current_temp & 3) == 1)
|
||||
// serial_writechar('2');
|
||||
// serial_writechar('5');
|
||||
// }
|
||||
// else {
|
||||
// serial_writechar('0');
|
||||
// }
|
||||
// // serial_writestr_P(PSTR("°C"));
|
||||
// serial_writechar('/');
|
||||
// serwrite_uint16(target_temp >> 2);
|
||||
// serial_writechar('.');
|
||||
// if (target_temp & 3) {
|
||||
// if ((target_temp & 3) == 3)
|
||||
// serial_writechar('7');
|
||||
// else if ((target_temp & 3) == 1)
|
||||
// serial_writechar('2');
|
||||
// serial_writechar('5');
|
||||
// }
|
||||
// else {
|
||||
// serial_writechar('0');
|
||||
// }
|
||||
//
|
||||
// serial_writestr_P(PSTR(" :"));
|
||||
// serwrite_uint8(temp_residency);
|
||||
uint8_t c = 0, t = 0;
|
||||
|
||||
if (current_temp & 3)
|
||||
c = 5;
|
||||
if ((current_temp & 3) == 1)
|
||||
c += 20;
|
||||
else if ((current_temp & 3) == 3)
|
||||
c += 70;
|
||||
|
||||
if (target_temp & 3)
|
||||
t = 5;
|
||||
if ((target_temp & 3) == 1)
|
||||
t += 20;
|
||||
else if ((target_temp & 3) == 3)
|
||||
t += 70;
|
||||
|
||||
sersendf_P(PSTR("%u.%u/%u.%u :%u\n"), current_temp >> 2, c, target_temp >> 2, t, temp_residency);
|
||||
}
|
||||
serial_writechar('\n');
|
||||
// serial_writechar('\n');
|
||||
}
|
||||
|
||||
void temp_tick() {
|
||||
|
|
@ -202,15 +221,15 @@ void temp_tick() {
|
|||
else if (temp_residency < TEMP_RESIDENCY_TIME)
|
||||
temp_residency++;
|
||||
|
||||
// if (DEBUG)
|
||||
serial_writestr_P(PSTR("T{"));
|
||||
// if (debug_flags & DEBUG_PID)
|
||||
// serial_writestr_P(PSTR("T{"));
|
||||
|
||||
int16_t t_error = target_temp - current_temp;
|
||||
|
||||
// if (DEBUG) {
|
||||
serial_writestr_P(PSTR("E:"));
|
||||
serwrite_int16(t_error);
|
||||
// }
|
||||
// if (debug_flags & DEBUG_PID) {
|
||||
// serial_writestr_P(PSTR("E:"));
|
||||
// serwrite_int16(t_error);
|
||||
// }
|
||||
|
||||
// PID stuff
|
||||
// proportional
|
||||
|
|
@ -229,24 +248,26 @@ void temp_tick() {
|
|||
// heater_d = (current_temp - last_temp);
|
||||
heater_d = current_temp - temp_history[th_p];
|
||||
|
||||
serial_writestr_P(PSTR(", P:"));
|
||||
serwrite_int16(heater_p);
|
||||
serial_writestr_P(PSTR(" * "));
|
||||
serwrite_int32(p_factor);
|
||||
serial_writestr_P(PSTR(" = "));
|
||||
serwrite_int32((int32_t) heater_p * p_factor / PID_SCALE);
|
||||
serial_writestr_P(PSTR(" / I:"));
|
||||
serwrite_int16(heater_i);
|
||||
serial_writestr_P(PSTR(" * "));
|
||||
serwrite_int32(i_factor);
|
||||
serial_writestr_P(PSTR(" = "));
|
||||
serwrite_int32((int32_t) heater_i * i_factor / PID_SCALE);
|
||||
serial_writestr_P(PSTR(" / D:"));
|
||||
serwrite_int16(heater_d);
|
||||
serial_writestr_P(PSTR(" * "));
|
||||
serwrite_int32(d_factor);
|
||||
serial_writestr_P(PSTR(" = "));
|
||||
serwrite_int32((int32_t) heater_d * d_factor / PID_SCALE);
|
||||
// if (debug_flags & DEBUG_PID) {
|
||||
// serial_writestr_P(PSTR(", P:"));
|
||||
// serwrite_int16(heater_p);
|
||||
// serial_writestr_P(PSTR(" * "));
|
||||
// serwrite_int32(p_factor);
|
||||
// serial_writestr_P(PSTR(" = "));
|
||||
// serwrite_int32((int32_t) heater_p * p_factor / PID_SCALE);
|
||||
// serial_writestr_P(PSTR(" / I:"));
|
||||
// serwrite_int16(heater_i);
|
||||
// serial_writestr_P(PSTR(" * "));
|
||||
// serwrite_int32(i_factor);
|
||||
// serial_writestr_P(PSTR(" = "));
|
||||
// serwrite_int32((int32_t) heater_i * i_factor / PID_SCALE);
|
||||
// serial_writestr_P(PSTR(" / D:"));
|
||||
// serwrite_int16(heater_d);
|
||||
// serial_writestr_P(PSTR(" * "));
|
||||
// serwrite_int32(d_factor);
|
||||
// serial_writestr_P(PSTR(" = "));
|
||||
// serwrite_int32((int32_t) heater_d * d_factor / PID_SCALE);
|
||||
// }
|
||||
|
||||
// combine factors
|
||||
int32_t pid_output_intermed = (
|
||||
|
|
@ -257,17 +278,13 @@ void temp_tick() {
|
|||
) / PID_SCALE
|
||||
);
|
||||
|
||||
serial_writestr_P(PSTR(" # O: "));
|
||||
serwrite_int32(pid_output_intermed);
|
||||
// if (debug_flags & DEBUG_PID) {
|
||||
// serial_writestr_P(PSTR(" # O: "));
|
||||
// serwrite_int32(pid_output_intermed);
|
||||
// }
|
||||
|
||||
// rebase and limit factors
|
||||
uint8_t pid_output;
|
||||
// if (pid_output_intermed > 127)
|
||||
// pid_output = 255;
|
||||
// else if (pid_output_intermed < -128)
|
||||
// pid_output = 0;
|
||||
// else
|
||||
// pid_output = (pid_output_intermed + 128);
|
||||
if (pid_output_intermed > 255)
|
||||
pid_output = 255;
|
||||
else if (pid_output_intermed < 0)
|
||||
|
|
@ -275,10 +292,13 @@ void temp_tick() {
|
|||
else
|
||||
pid_output = pid_output_intermed & 0xFF;
|
||||
|
||||
// if (DEBUG) {
|
||||
serial_writestr_P(PSTR(" = "));
|
||||
serwrite_uint8(pid_output);
|
||||
// }
|
||||
// if (debug_flags & DEBUG_PID) {
|
||||
// serial_writestr_P(PSTR(" = "));
|
||||
// serwrite_uint8(pid_output);
|
||||
// }
|
||||
|
||||
if (debug_flags & DEBUG_PID)
|
||||
sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heater_p, p_factor, (int32_t) heater_p * p_factor / PID_SCALE, heater_i, i_factor, (int32_t) heater_i * i_factor / PID_SCALE, heater_d, d_factor, (int32_t) heater_d * d_factor / PID_SCALE, pid_output_intermed, pid_output);
|
||||
|
||||
#ifdef HEATER_PWM
|
||||
HEATER_PWM = pid_output;
|
||||
|
|
@ -289,7 +309,7 @@ void temp_tick() {
|
|||
disable_heater();
|
||||
#endif
|
||||
|
||||
// if (DEBUG)
|
||||
serial_writestr_P(PSTR("}\n"));
|
||||
// if (debug_flags & DEBUG_PID)
|
||||
// serial_writestr_P(PSTR("}\n"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,35 @@
|
|||
#include "dda_queue.h"
|
||||
#include "dda.h"
|
||||
#include "watchdog.h"
|
||||
#include "temp.h"
|
||||
#include "serial.h"
|
||||
|
||||
ISR(TIMER1_COMPA_vect) {
|
||||
WRITE(SCK, 1);
|
||||
|
||||
disableTimerInterrupt();
|
||||
|
||||
// do our next step
|
||||
// NOTE: dda_step makes this interrupt interruptible after steps have been sent but before new speed is calculated.
|
||||
if (movebuffer[mb_tail].live)
|
||||
dda_step(&(movebuffer[mb_tail]));
|
||||
if (movebuffer[mb_tail].live) {
|
||||
if (movebuffer[mb_tail].waitfor_temp) {
|
||||
#if STEP_INTERRUPT_INTERRUPTIBLE
|
||||
// this interrupt can now be interruptible
|
||||
// disableTimerInterrupt();
|
||||
sei();
|
||||
#endif
|
||||
|
||||
#if STEP_INTERRUPT_INTERRUPTIBLE
|
||||
// this interrupt can now be interruptible
|
||||
disableTimerInterrupt();
|
||||
sei();
|
||||
#endif
|
||||
if (temp_achieved()) {
|
||||
movebuffer[mb_tail].live = 0;
|
||||
serial_writestr_P(PSTR("Temp achieved, next move\n"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
dda_step(&(movebuffer[mb_tail]));
|
||||
}
|
||||
}
|
||||
|
||||
// serial_writechar('!');
|
||||
|
||||
// fall directly into dda_start instead of waiting for another step
|
||||
if (movebuffer[mb_tail].live == 0)
|
||||
|
|
@ -27,10 +43,10 @@ ISR(TIMER1_COMPA_vect) {
|
|||
#if STEP_INTERRUPT_INTERRUPTIBLE
|
||||
// return from interrupt in a way that prevents this interrupt nesting with itself at high step rates
|
||||
cli();
|
||||
// check queue, if empty we don't need to interrupt again until re-enabled in dda_create
|
||||
if (queue_empty() == 0)
|
||||
enableTimerInterrupt();
|
||||
#endif
|
||||
// check queue, if empty we don't need to interrupt again until re-enabled in dda_create
|
||||
if (queue_empty() == 0)
|
||||
enableTimerInterrupt();
|
||||
WRITE(SCK, 0);
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +60,7 @@ void setupTimerInterrupt()
|
|||
TIMSK1 = 0;
|
||||
|
||||
//start off with a slow frequency.
|
||||
setTimer(10000);
|
||||
setTimer(F_CPU / 100);
|
||||
}
|
||||
|
||||
// the following are all from reprap project 5D firmware
|
||||
|
|
|
|||
Loading…
Reference in New Issue