time to save again, preliminary PID/PWM support for extruder barrel heater
This commit is contained in:
parent
411ada4d82
commit
496d58f357
|
|
@ -3,6 +3,31 @@
|
|||
|
||||
#include <avr/io.h>
|
||||
|
||||
/*
|
||||
utility functions
|
||||
*/
|
||||
|
||||
#ifndef MASK
|
||||
#define MASK(PIN) (1 << PIN)
|
||||
#endif
|
||||
|
||||
#define _READ(IO) (RPORT_ ## IO & MASK(PIN_ ## IO))
|
||||
#define _WRITE(IO, v) if (v) { WPORT_ ## IO |= MASK(PIN_ ## IO); } else { WPORT_ ## IO &= ~MASK(PIN_ ## IO); }
|
||||
|
||||
#define _SET_INPUT(IO) (DDR_ ## IO |= MASK(PIN_ ## IO))
|
||||
#define _SET_OUTPUT(IO) (DDR_ ## IO &= ~MASK(PIN_ ## IO))
|
||||
|
||||
// why double up on macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
|
||||
#define READ(IO) _READ(IO)
|
||||
#define WRITE(IO, v) _WRITE(IO, v)
|
||||
#define SET_INPUT(IO) _SET_INPUT(IO)
|
||||
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
|
||||
|
||||
/*
|
||||
pins
|
||||
*/
|
||||
|
||||
#define PIN_DIO0 PD0
|
||||
#define RPORT_DIO0 PIND
|
||||
#define WPORT_DIO0 PORTD
|
||||
|
|
|
|||
20
mendel/dda.c
20
mendel/dda.c
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "pinout.h"
|
||||
#include "timer.h"
|
||||
|
||||
extern struct {
|
||||
|
|
@ -128,7 +129,8 @@ uint32_t approx_distance_3( int32_t dx, int32_t dy, int32_t dz )
|
|||
*/
|
||||
|
||||
void dda_create(TARGET *target, DDA *dda) {
|
||||
static TARGET startpoint = { 0, 0, 0, 0, 0 };
|
||||
static TARGET startpoint = { 0, 0, 0, 0, 0 };
|
||||
uint32_t distance;
|
||||
|
||||
// we start at the previous endpoint
|
||||
// memcpy(&dda->currentpoint, &startpoint, sizeof(TARGET));
|
||||
|
|
@ -145,16 +147,16 @@ void dda_create(TARGET *target, DDA *dda) {
|
|||
|
||||
// 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.
|
||||
if (dda->z_delta == 0)
|
||||
dda->distance = approx_distance(dda->x_delta, dda->y_delta);
|
||||
distance = approx_distance(dda->x_delta, dda->y_delta);
|
||||
else if (dda->x_delta == 0 && dda->y_delta == 0)
|
||||
dda->distance = dda->z_delta;
|
||||
distance = dda->z_delta;
|
||||
else
|
||||
dda->distance = approx_distance_3(dda->x_delta, dda->y_delta, dda->z_delta);
|
||||
distance = approx_distance_3(dda->x_delta, dda->y_delta, dda->z_delta);
|
||||
|
||||
if (dda->distance < 2)
|
||||
dda->distance = dda->e_delta;
|
||||
if (dda->distance < 2)
|
||||
dda->distance = dda->f_delta;
|
||||
if (distance < 2)
|
||||
distance = dda->e_delta;
|
||||
if (distance < 2)
|
||||
distance = dda->f_delta;
|
||||
|
||||
dda->total_steps = dda->x_delta;
|
||||
if (dda->y_delta > dda->total_steps)
|
||||
|
|
@ -194,7 +196,7 @@ void dda_create(TARGET *target, DDA *dda) {
|
|||
// mm (distance) * 60000000 us/min / step (total_steps) = mm.us per step.min
|
||||
// so in the interrupt we must simply calculate
|
||||
// mm.us per step.min / mm per min (F) = us per step
|
||||
dda->move_duration = dda->distance * 60000000 / dda->total_steps;
|
||||
dda->move_duration = distance * 60000000 / dda->total_steps;
|
||||
|
||||
// next dda starts where we finish
|
||||
memcpy(&startpoint, &dda->endpoint, sizeof(TARGET));
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ typedef struct {
|
|||
uint32_t total_steps;
|
||||
|
||||
uint16_t f_scale;
|
||||
uint32_t distance;
|
||||
uint32_t move_duration;
|
||||
} DDA;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "machine.h"
|
||||
#include "dda.h"
|
||||
#include "serial.h"
|
||||
|
||||
extern uint8_t option_bitfield;
|
||||
|
||||
|
|
@ -76,13 +77,8 @@ void scan_char(uint8_t c) {
|
|||
next_target.target.E = manexp_to_float(mantissa, exp) * STEPS_PER_MM_E;
|
||||
break;
|
||||
case 'F':
|
||||
// TODO: calculate end speed in microseconds per step from millimeters per minute
|
||||
// MM = sqrt(X^2 + Y^2)
|
||||
// STEPS = max(X * STEPS_PER_MM_X, Y * STEPS_PER_MM_Y)
|
||||
// DURATION = MM / MM_PER_MIN * 60 SEC_PER_MIN * 1000000 US_PER_SEC
|
||||
// US/STEP = DURATION / STEPS
|
||||
// intF = sqrt(X^2 + Y^2) / max(X * STEPS_PER_MM_X, Y * STEPS_PER_MM_Y)
|
||||
next_target.target.F = manexp_to_float(mantissa, exp) * STEPS_PER_MM_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 = mantissa;
|
||||
break;
|
||||
}
|
||||
mantissa = 0;
|
||||
|
|
@ -122,6 +118,8 @@ void scan_char(uint8_t c) {
|
|||
last_field = 0;
|
||||
memset(&next_target, 0, sizeof(GCODE_COMMAND));
|
||||
next_target.option = option_bitfield;
|
||||
|
||||
serial_writeblock((uint8_t *) "OK\n", 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
/*
|
||||
machine variables
|
||||
*/
|
||||
|
||||
#define MOVEBUFFER_SIZE 8
|
||||
|
||||
/*
|
||||
axis calculations, adjust as necessary
|
||||
*/
|
||||
|
|
@ -17,27 +19,18 @@
|
|||
#define EXTRUDER_INLET_DIAMETER 3
|
||||
#define EXTRUDER_NOZZLE_DIAMETER 0.8
|
||||
|
||||
|
||||
#define STEPS_PER_MM_X (XY_STEPS_PER_REV * XY_COG_CIRCUMFERENCE)
|
||||
#define STEPS_PER_MM_Y (XY_STEPS_PER_REV * XY_COG_CIRCUMFERENCE)
|
||||
#define STEPS_PER_MM_Z (3200)
|
||||
#define STEPS_PER_MM_E (EXTRUDER_STEPS_PER_REV * EXTRUDER_SHAFT_RADIUS * PI * EXTRUDER_INLET_DIAMETER / EXTRUDER_NOZZLE_DIAMETER)
|
||||
|
||||
#define STEPS_PER_MM_PER_S_F (3200)
|
||||
|
||||
#define STEPS_PER_MM_F STEPS_PER_MM_PER_S_F
|
||||
|
||||
/*
|
||||
F is sent in units of millimeters per second
|
||||
and implemented as microseconds per step
|
||||
|
||||
MM/S * steps/mm * 1000000us/s = steps per microsecond
|
||||
heater PID variables
|
||||
used as int16_t * FACTOR so don't put brackets around them
|
||||
*/
|
||||
|
||||
|
||||
#define FAST_MM_PER_SEC 40
|
||||
#define SLOW_MM_PER_SEC 20
|
||||
#define ACCEL 10
|
||||
|
||||
#define P_FACTOR 133 / 1024
|
||||
#define I_FACTOR 17 / 1024
|
||||
#define D_FACTOR 180 / 1024
|
||||
|
||||
#endif /* _MACHINE_H */
|
||||
|
|
|
|||
130
mendel/pinout.h
130
mendel/pinout.h
|
|
@ -3,58 +3,118 @@
|
|||
|
||||
#include "arduino.h"
|
||||
|
||||
#ifndef MASK
|
||||
#define MASK(PIN) (1 << PIN)
|
||||
#endif
|
||||
/*
|
||||
Machine Pin Definitions
|
||||
*/
|
||||
|
||||
#define READ(IO) (RPORT_ ## IO & MASK(PIN_ ## IO))
|
||||
#define WRITE(IO, v) if (v) { WPORT_ ## IO |= MASK(PIN_ ## IO); } else { WPORT_ ## IO &= ~MASK(PIN_ ## IO); }
|
||||
// RXD DIO0
|
||||
// TXD DIO1
|
||||
|
||||
#define SET_INPUT(IO) (DDR_ ## IO |= MASK(PIN_ ## IO))
|
||||
#define SET_OUTPUT(IO) (DDR_ ## IO &= ~MASK(PIN ## IO))
|
||||
#define X_STEP_PIN AIO0
|
||||
#define X_DIR_PIN AIO1
|
||||
#define X_MIN_PIN AIO2
|
||||
|
||||
#define _x_step(st) WRITE(AIO0, st)
|
||||
#define Y_STEP_PIN AIO3
|
||||
#define Y_DIR_PIN AIO4
|
||||
#define Y_MIN_PIN AIO5
|
||||
|
||||
#define Z_STEP_PIN DIO5
|
||||
#define Z_DIR_PIN DIO6
|
||||
#define Z_MIN_PIN DIO7
|
||||
|
||||
#define E_STEP_PIN DIO2
|
||||
#define E_DIR_PIN DIO3
|
||||
|
||||
// list of PWM-able pins
|
||||
// OC0A DIO6
|
||||
// OC0B DIO5
|
||||
// OC1A DIO9
|
||||
// OC1B DIO10
|
||||
// OC2A DIO11
|
||||
// OC2B DIO3
|
||||
|
||||
#define HEATER_PIN DIO6
|
||||
#define HEATER_PIN_PWM OC0A
|
||||
|
||||
#define SCK DIO13
|
||||
#define MISO DIO12
|
||||
#define MOSI DIO11
|
||||
#define SS DIO10
|
||||
|
||||
/*
|
||||
X Stepper
|
||||
*/
|
||||
|
||||
#define _x_step(st) WRITE(X_STEP_PIN, st)
|
||||
#define x_step() _x_step(1);
|
||||
#define x_direction(dir) WRITE(AIO1, dir)
|
||||
#define x_min() READ(AIO2)
|
||||
#ifdef MAX_ENDSTOPS
|
||||
#define x_max() READ(AIO3)
|
||||
#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)
|
||||
#else
|
||||
#define x_max() (0)
|
||||
#define x_max() (0)
|
||||
#endif
|
||||
|
||||
#define _y_step(st) WRITE(DIO2, st)
|
||||
/*
|
||||
Y Stepper
|
||||
*/
|
||||
|
||||
#define _y_step(st) WRITE(Y_STEP_PIN, st)
|
||||
#define y_step() _y_step(1);
|
||||
#define y_direction(dir) WRITE(DIO3, dir)
|
||||
#define y_min() READ(DIO4)
|
||||
#ifdef MAX_ENDSTOPS
|
||||
#define y_max() READ(DIO5)
|
||||
#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)
|
||||
#else
|
||||
#define y_max() (0)
|
||||
#define y_max() (0)
|
||||
#endif
|
||||
|
||||
#define _z_step(st) WRITE(DIO6, st)
|
||||
/*
|
||||
Z Stepper
|
||||
*/
|
||||
|
||||
#define _z_step(st) WRITE(Z_STEP_PIN, st)
|
||||
#define z_step() _z_step(1);
|
||||
#define z_direction(dir) WRITE(DIO7, dir)
|
||||
#define z_min() READ(DIO8)
|
||||
#ifdef MAX_ENDSTOPS
|
||||
#define z_max() READ(DIO9)
|
||||
#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)
|
||||
#else
|
||||
#define z_max() (0)
|
||||
#define z_max() (0)
|
||||
#endif
|
||||
|
||||
#define _e_step(st) WRITE(AIO4, st)
|
||||
/*
|
||||
Extruder
|
||||
*/
|
||||
|
||||
#define _e_step(st) WRITE(E_STEP_PIN, st)
|
||||
#define e_step() _e_step(1);
|
||||
#define e_direction(dir) WRITE(AIO5, dir)
|
||||
#define e_direction(dir) WRITE(E_DIR_PIN, dir)
|
||||
|
||||
#define enable_steppers() WRITE(DIO10, 1)
|
||||
#define disable_steppers() WRITE(DIO10, 0)
|
||||
/*
|
||||
Heater
|
||||
*/
|
||||
|
||||
inline void unstep(void) {
|
||||
_x_step(0);
|
||||
_y_step(0);
|
||||
_z_step(0);
|
||||
_e_step(0);
|
||||
}
|
||||
#define enable_heater() WRITE(HEATER_PIN, 1)
|
||||
#define disable_heater() WRITE(HEATER_PIN, 0)
|
||||
|
||||
/*
|
||||
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)
|
||||
#else
|
||||
#define enable_steppers() if (0) {}
|
||||
#define disable_steppers() if (0) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
End Step - All Steppers
|
||||
(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)
|
||||
|
||||
#endif /* _PINOUT_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
#include "temp.h"
|
||||
|
||||
#include "machine.h"
|
||||
#include "pinout.h"
|
||||
|
||||
uint16_t current_temp;
|
||||
uint16_t target_temp;
|
||||
|
||||
int16_t heater_p;
|
||||
int16_t heater_i;
|
||||
int16_t heater_d;
|
||||
|
||||
void temp_setup() {
|
||||
SET_OUTPUT(SCK);
|
||||
SET_INPUT(MISO);
|
||||
SET_OUTPUT(SS);
|
||||
|
||||
WRITE(SS, 0);
|
||||
WRITE(SCK, 0);
|
||||
}
|
||||
|
||||
uint16_t temp_read() {
|
||||
uint16_t temp;
|
||||
SPCR = MASK(MSTR) | MASK(SPE);
|
||||
|
||||
SPDR = 0;
|
||||
for (;(SPSR & MASK(SPIF)) == 0;);
|
||||
temp = SPDR << 8;
|
||||
|
||||
SPDR = 0;
|
||||
for (;(SPSR & MASK(SPIF)) == 0;);
|
||||
temp |= SPDR;
|
||||
|
||||
if ((temp & 0x8002) == 0) {
|
||||
// got "device id"
|
||||
if (temp & 4) {
|
||||
// thermocouple open
|
||||
}
|
||||
else {
|
||||
current_temp = temp >> 3;
|
||||
return current_temp;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void temp_set(uint16_t t) {
|
||||
target_temp = t;
|
||||
}
|
||||
|
||||
void temp_tick() {
|
||||
uint16_t last_temp = current_temp;
|
||||
temp_read();
|
||||
|
||||
int16_t t_delta = target_temp - current_temp;
|
||||
|
||||
// PID stuff
|
||||
heater_p = t_delta;
|
||||
heater_i += t_delta;
|
||||
// note: D follows temp rather than error so there's no large derivative when the target temperature changes
|
||||
heater_d = (current_temp - last_temp);
|
||||
|
||||
int16_t pid_output = (heater_p * P_FACTOR) + (heater_i * I_FACTOR) + (heater_d * D_FACTOR);
|
||||
|
||||
#ifdef HEATER_PIN_PWMABLE
|
||||
HEATER_PIN_PWMABLE = pid_output
|
||||
#else
|
||||
if (pid_output > 0) {
|
||||
enable_heater();
|
||||
}
|
||||
else {
|
||||
disable_heater();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _TEMP_H
|
||||
#define _TEMP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void temp_setup(void);
|
||||
uint16_t temp_read(void);
|
||||
void temp_set(uint16_t t);
|
||||
void temp_tick(void);
|
||||
|
||||
#endif /* _TIMER_H */
|
||||
|
|
@ -31,9 +31,6 @@ inline void disableTimerInterrupt(void)
|
|||
TIMSK1 &= ~(1<<OCIE1A);
|
||||
}
|
||||
|
||||
inline void setTimerCeiling(uint16_t c)
|
||||
{
|
||||
OCR1A = c;
|
||||
}
|
||||
#define setTimerCeiling(c) OCR1A = c
|
||||
|
||||
#endif /* _TIMER_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue