a ton of work on the heater PID loop, it's working great now
This commit is contained in:
parent
2182d7b77a
commit
06cdfaa251
|
|
@ -7,21 +7,21 @@
|
|||
#
|
||||
# and then used like this:
|
||||
#
|
||||
# $ arduincmd G1 X100
|
||||
# $ arduinocmd M250
|
||||
# $ mendel_cmd G1 X100
|
||||
# $ mendel_cmd M250
|
||||
#
|
||||
# {X:4200,Y:0,Z:0,E:0,F:300,c:19334400}
|
||||
# {X:4200,Y:0,Z:0,E:0,F:300,c:0}
|
||||
# Q1/1E
|
||||
# $ readsym_uint8 mb_head
|
||||
# $ mendel_readsym_uint8 mb_head
|
||||
# 1
|
||||
# $ readsym_target startpoint
|
||||
# $ mendel_readsym_target startpoint
|
||||
# X: 2100
|
||||
# Y: 0
|
||||
# Z: 0
|
||||
# E: 0
|
||||
# F: 300
|
||||
# $ readsym_mb
|
||||
# $ mendel_readsym_mb
|
||||
# [0] {
|
||||
# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0
|
||||
# flags: 0
|
||||
|
|
@ -101,13 +101,10 @@ mendel_cmd() {
|
|||
while [ "$REPLY" != "OK" ]
|
||||
do
|
||||
read -u 3
|
||||
# if [ "$LN" -ne 0 ]
|
||||
# then
|
||||
if [ "$REPLY" != "OK" ]
|
||||
then
|
||||
echo "$REPLY"
|
||||
fi
|
||||
# fi
|
||||
if [ "$REPLY" != "OK" ]
|
||||
then
|
||||
echo "$REPLY"
|
||||
fi
|
||||
LN=$(( $LN + 1 ))
|
||||
done
|
||||
) 3<>/dev/arduino;
|
||||
|
|
@ -123,19 +120,17 @@ mendel_cmd_hr() {
|
|||
while [ "$REPLY" != "OK" ]
|
||||
do
|
||||
read -u 3
|
||||
# if [ "$LN" -ne 0 ]
|
||||
# then
|
||||
echo "< $REPLY"
|
||||
# fi
|
||||
echo "< $REPLY"
|
||||
LN=$(( $LN + 1 ))
|
||||
done
|
||||
) 3<>/dev/arduino;
|
||||
}
|
||||
|
||||
mendel_print() {
|
||||
( IFS=$'\n'
|
||||
(
|
||||
for F in "$@"
|
||||
do
|
||||
IFS=$'\n'
|
||||
for L in $(< $F)
|
||||
do
|
||||
mendel_cmd_hr "$L"
|
||||
|
|
@ -150,14 +145,25 @@ mendel_readsym() {
|
|||
sym=$1
|
||||
if [ -n "$sym" ]
|
||||
then
|
||||
make mendel.sym &>/dev/null
|
||||
if egrep -q '\b'$sym'\b' mendel.sym
|
||||
if [[ "$sym" =~ ^(0?x?[0-9A-Fa-f]+)(:([0-9]+))?$ ]]
|
||||
then
|
||||
ADDR=$(( $(egrep '\b'$sym'\b' mendel.sym | cut -d\ -f1) ))
|
||||
SIZE=$(egrep '\b'$sym'\b' mendel.sym | cut -d+ -f2)
|
||||
ADDR=$(( ${BASH_REMATCH[1]} ))
|
||||
SIZE=$(( ${BASH_REMATCH[3]} ))
|
||||
if [ "$SIZE" -le 1 ]
|
||||
then
|
||||
SIZE=1
|
||||
fi
|
||||
mendel_cmd "M253 S$ADDR P$SIZE"
|
||||
else
|
||||
echo "unknown symbol: $sym"
|
||||
make mendel.sym &>/dev/null
|
||||
if egrep -q '\b'$sym'\b' mendel.sym
|
||||
then
|
||||
ADDR=$(( $(egrep '\b'$sym'\b' mendel.sym | cut -d\ -f1) ))
|
||||
SIZE=$(egrep '\b'$sym'\b' mendel.sym | cut -d+ -f2)
|
||||
mendel_cmd "M253 S$ADDR P$SIZE"
|
||||
else
|
||||
echo "unknown symbol: $sym"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "what symbol?" > /dev/fd/2
|
||||
|
|
@ -243,3 +249,24 @@ mendel_readsym_mb() {
|
|||
printf "\n}\n";
|
||||
ENDPERL
|
||||
}
|
||||
|
||||
mendel_heater_pid() {
|
||||
P=$(mendel_readsym_int16 heater_p)
|
||||
I=$(mendel_readsym_int16 heater_i)
|
||||
D=$(mendel_readsym_int16 heater_d)
|
||||
|
||||
PF=$(mendel_readsym_int32 p_factor)
|
||||
IF=$(mendel_readsym_int32 i_factor)
|
||||
DF=$(mendel_readsym_int32 d_factor)
|
||||
|
||||
O=$(mendel_readsym_uint8 0x27)
|
||||
T=$(mendel_cmd M105 | cut -d\ -f2 | cut -d/ -f1)
|
||||
|
||||
echo "P=$P pf=$PF r="$(($P * $PF))
|
||||
echo "I=$I if=$IF r="$(($I * $IF))
|
||||
echo "D=$D df=$DF r="$(($D * $DF))
|
||||
echo "R="$(( $(($P * $PF)) + $(($I * $IF)) + $(($D * $DF)) )) / 1024
|
||||
echo "R="$(( $(( $(($P * $PF)) + $(($I * $IF)) + $(($D * $DF)) )) / 1024 ))
|
||||
echo "R="$(( $(( $(( $(($P * $PF)) + $(($I * $IF)) + $(($D * $DF)) )) / 1024 )) + 128 ))
|
||||
echo "O=$O T=$T"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
// backup feedrate, move E very quickly then restore feedrate
|
||||
uint32_t f = startpoint.F;
|
||||
startpoint.F = FEEDRATE_FAST_E;
|
||||
SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
|
||||
SpecialMoveE(startpoint.E + E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
|
||||
startpoint.F = f;
|
||||
} while (0);
|
||||
break;
|
||||
|
|
@ -541,7 +541,7 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
// backup feedrate, move E very quickly then restore feedrate
|
||||
uint32_t f = startpoint.F;
|
||||
startpoint.F = FEEDRATE_FAST_E;
|
||||
SpecialMoveE(-E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
|
||||
SpecialMoveE(startpoint.E - E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
|
||||
startpoint.F = f;
|
||||
} while (0);
|
||||
break;
|
||||
|
|
@ -594,6 +594,10 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
if (gcmd->seen_S)
|
||||
i_limit = gcmd->S;
|
||||
break;
|
||||
// M134- save PID settings to eeprom
|
||||
case 134:
|
||||
temp_save_settings();
|
||||
break;
|
||||
|
||||
// M140- echo off
|
||||
case 140:
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
// extruder settings
|
||||
#define TEMP_HYSTERESIS 20
|
||||
#define TEMP_RESIDENCY_TIME 60
|
||||
|
||||
/*
|
||||
calculated values - you shouldn't need to touch these
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ void init(void) {
|
|||
// set up clock
|
||||
clock_setup();
|
||||
|
||||
// read PID settings from EEPROM
|
||||
temp_init();
|
||||
|
||||
// set up default feedrate
|
||||
current_position.F = startpoint.F = next_target.target.F = FEEDRATE_SLOW_Z;
|
||||
|
||||
|
|
@ -108,7 +111,7 @@ void clock_250ms(void) {
|
|||
if (steptimeout > (30 * 4)) {
|
||||
power_off();
|
||||
}
|
||||
else if (temp_get_target() == 0)
|
||||
else
|
||||
steptimeout++;
|
||||
|
||||
ifclock(CLOCK_FLAG_1S) {
|
||||
|
|
|
|||
130
mendel/temp.c
130
mendel/temp.c
|
|
@ -18,12 +18,15 @@
|
|||
|
||||
#include "temp.h"
|
||||
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
#include "machine.h"
|
||||
#include "pinout.h"
|
||||
#include "clock.h"
|
||||
#include "serial.h"
|
||||
#include "sermsg.h"
|
||||
#include "timer.h"
|
||||
#include "dda.h"
|
||||
|
||||
uint16_t current_temp = 0;
|
||||
uint16_t target_temp = 0;
|
||||
|
|
@ -32,15 +35,55 @@ int16_t heater_p = 0;
|
|||
int16_t heater_i = 0;
|
||||
int16_t heater_d = 0;
|
||||
|
||||
int32_t p_factor = 680;
|
||||
int32_t i_factor = 18;
|
||||
int32_t d_factor = 200;
|
||||
int16_t i_limit = 500;
|
||||
#define DEFAULT_P 4096
|
||||
#define DEFAULT_I 64
|
||||
#define DEFAULT_D -12288
|
||||
#define DEFAULT_I_LIMIT 3072
|
||||
int32_t p_factor = 0;
|
||||
int32_t i_factor = 0;
|
||||
int32_t d_factor = 0;
|
||||
int16_t i_limit = 0;
|
||||
|
||||
int32_t EEMEM EE_p_factor;
|
||||
int32_t EEMEM EE_i_factor;
|
||||
int32_t EEMEM EE_d_factor;
|
||||
int16_t EEMEM EE_i_limit;
|
||||
|
||||
uint8_t temp_flags = 0;
|
||||
#define TEMP_FLAG_PRESENT 1
|
||||
#define TEMP_FLAG_TCOPEN 2
|
||||
|
||||
uint8_t temp_residency = 0;
|
||||
|
||||
#define TH_COUNT 8
|
||||
uint16_t temp_history[TH_COUNT] __attribute__ ((__section__ (".bss")));
|
||||
uint8_t th_p = 0;
|
||||
|
||||
#ifndef ABSDELTA
|
||||
#define ABSDELTA(a, b) (((a) >= (b))?((a) - (b)):((b) - (a)))
|
||||
#endif
|
||||
|
||||
void temp_init() {
|
||||
p_factor = eeprom_read_dword((uint32_t *) &EE_p_factor);
|
||||
i_factor = eeprom_read_dword((uint32_t *) &EE_i_factor);
|
||||
d_factor = eeprom_read_dword((uint32_t *) &EE_d_factor);
|
||||
i_limit = eeprom_read_word((uint16_t *) &EE_i_limit);
|
||||
|
||||
if ((p_factor == 0) && (i_factor == 0) && (d_factor == 0) && (i_limit == 0)) {
|
||||
p_factor = DEFAULT_P;
|
||||
i_factor = DEFAULT_I;
|
||||
d_factor = DEFAULT_D;
|
||||
i_limit = DEFAULT_I_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
void temp_save_settings() {
|
||||
eeprom_write_dword((uint32_t *) &EE_p_factor, p_factor);
|
||||
eeprom_write_dword((uint32_t *) &EE_i_factor, i_factor);
|
||||
eeprom_write_dword((uint32_t *) &EE_d_factor, d_factor);
|
||||
eeprom_write_word((uint16_t *) &EE_i_limit, i_limit);
|
||||
}
|
||||
|
||||
uint16_t temp_read() {
|
||||
uint16_t temp;
|
||||
|
||||
|
|
@ -87,6 +130,10 @@ uint16_t temp_read() {
|
|||
}
|
||||
|
||||
void temp_set(uint16_t t) {
|
||||
if (t) {
|
||||
steptimeout = 0;
|
||||
power_on();
|
||||
}
|
||||
target_temp = t;
|
||||
}
|
||||
|
||||
|
|
@ -99,12 +146,8 @@ uint16_t temp_get_target() {
|
|||
}
|
||||
|
||||
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;
|
||||
if (temp_residency >= TEMP_RESIDENCY_TIME)
|
||||
return 255;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -146,17 +189,27 @@ void temp_print() {
|
|||
|
||||
void temp_tick() {
|
||||
if (target_temp) {
|
||||
uint16_t last_temp = current_temp;
|
||||
steptimeout = 0;
|
||||
|
||||
// uint16_t last_temp = current_temp;
|
||||
temp_read();
|
||||
|
||||
temp_history[th_p++] = current_temp;
|
||||
th_p &= (TH_COUNT - 1);
|
||||
|
||||
if (ABSDELTA(current_temp, target_temp) > TEMP_HYSTERESIS)
|
||||
temp_residency = 0;
|
||||
else if (temp_residency < TEMP_RESIDENCY_TIME)
|
||||
temp_residency++;
|
||||
|
||||
// if (DEBUG)
|
||||
// serial_writestr_P(PSTR("T{"));
|
||||
serial_writestr_P(PSTR("T{"));
|
||||
|
||||
int16_t t_error = target_temp - current_temp;
|
||||
|
||||
// if (DEBUG) {
|
||||
// serial_writestr_P(PSTR("E:"));
|
||||
// serwrite_int16(t_error);
|
||||
serial_writestr_P(PSTR("E:"));
|
||||
serwrite_int16(t_error);
|
||||
// }
|
||||
|
||||
// PID stuff
|
||||
|
|
@ -173,7 +226,27 @@ void temp_tick() {
|
|||
|
||||
// derivative
|
||||
// note: D follows temp rather than error so there's no large derivative when the target changes
|
||||
heater_d = (current_temp - last_temp);
|
||||
// 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);
|
||||
|
||||
// combine factors
|
||||
int32_t pid_output_intermed = (
|
||||
|
|
@ -184,32 +257,39 @@ void temp_tick() {
|
|||
) / PID_SCALE
|
||||
);
|
||||
|
||||
serial_writestr_P(PSTR(" # O: "));
|
||||
serwrite_int32(pid_output_intermed);
|
||||
|
||||
// rebase and limit factors
|
||||
uint8_t pid_output;
|
||||
if (pid_output_intermed > 127)
|
||||
// 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 < -128)
|
||||
else if (pid_output_intermed < 0)
|
||||
pid_output = 0;
|
||||
else
|
||||
pid_output = (pid_output_intermed + 128);
|
||||
pid_output = pid_output_intermed & 0xFF;
|
||||
|
||||
// if (DEBUG) {
|
||||
// serial_writestr_P(PSTR(",O:"));
|
||||
// serwrite_uint8(pid_output);
|
||||
serial_writestr_P(PSTR(" = "));
|
||||
serwrite_uint8(pid_output);
|
||||
// }
|
||||
|
||||
#ifdef HEATER_PWM
|
||||
HEATER_PWM = pid_output;
|
||||
#else
|
||||
if (pid_output >= 128) {
|
||||
if (pid_output >= 8)
|
||||
enable_heater();
|
||||
}
|
||||
else {
|
||||
else
|
||||
disable_heater();
|
||||
}
|
||||
#endif
|
||||
|
||||
// if (DEBUG)
|
||||
// serial_writechar('}');
|
||||
serial_writestr_P(PSTR("}\n"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ typedef union {
|
|||
} interpret;
|
||||
} max6675_data_format;
|
||||
|
||||
// setup temperature system
|
||||
void temp_init(void);
|
||||
|
||||
// save PID factors to EEPROM
|
||||
void temp_save_settings(void);
|
||||
|
||||
// read temperature from sensor
|
||||
uint16_t temp_read(void);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue