From 273d63f24238797969961188b02cbc33829dd2b9 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 12 Sep 2010 14:47:49 +1000 Subject: [PATCH] splitting heater stuff out into a separate file --- Makefile | 2 +- gcode.c | 3 +- heater.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ heater.h | 21 ++++++++++ mendel.c | 3 +- temp.c | 56 ++++++++----------------- temp.h | 10 ----- 7 files changed, 164 insertions(+), 53 deletions(-) create mode 100644 heater.c create mode 100644 heater.h diff --git a/Makefile b/Makefile index 5e5f348..b46c2f8 100644 --- a/Makefile +++ b/Makefile @@ -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 debug.c sersendf.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 heater.c ############################################################################## # # diff --git a/gcode.c b/gcode.c index e706675..4e1ce05 100644 --- a/gcode.c +++ b/gcode.c @@ -12,6 +12,7 @@ #include "clock.h" #include "watchdog.h" #include "debug.h" +#include "heater.h" uint8_t last_field = 0; @@ -661,7 +662,7 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { break; // M134- save PID settings to eeprom case 134: - temp_save_settings(); + heater_save_settings(); break; #ifdef DEBUG diff --git a/heater.c b/heater.c new file mode 100644 index 0000000..96c53bf --- /dev/null +++ b/heater.c @@ -0,0 +1,122 @@ +#include "heater.h" + +#include + +#include "sersendf.h" +#include "machine.h" +#include "pinout.h" +#include "debug.h" +#include "arduino.h" + +int16_t heater_p = 0; +int16_t heater_i = 0; +int16_t heater_d = 0; + +#define DEFAULT_P 8192 +#define DEFAULT_I 512 +#define DEFAULT_D -24576 +#define DEFAULT_I_LIMIT 384 +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; + +#define TH_COUNT 8 +uint16_t temp_history[TH_COUNT] __attribute__ ((__section__ (".bss"))); +uint8_t th_p = 0; + +uint8_t temp_residency = 0; + +#ifndef ABSDELTA +#define ABSDELTA(a, b) (((a) >= (b))?((a) - (b)):((b) - (a))) +#endif + +void heater_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 heater_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); +} + +void heater_tick(int16_t current_temp, int16_t target_temp) { + 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++; + + int16_t t_error = target_temp - current_temp; + + // PID stuff + // proportional + heater_p = t_error; + + // integral + heater_i += t_error; + // prevent integrator wind-up + if (heater_i > i_limit) + heater_i = i_limit; + else if (heater_i < -i_limit) + heater_i = -i_limit; + + // derivative + // note: D follows temp rather than error so there's no large derivative when the target changes + heater_d = current_temp - temp_history[th_p]; + + // combine factors + int32_t pid_output_intermed = ( + ( + (((int32_t) heater_p) * p_factor) + + (((int32_t) heater_i) * i_factor) + + (((int32_t) heater_d) * d_factor) + ) / PID_SCALE + ); + + // rebase and limit factors + uint8_t pid_output; + if (pid_output_intermed > 255) + pid_output = 255; + else if (pid_output_intermed < 0) + pid_output = 0; + else + pid_output = pid_output_intermed & 0xFF; + + 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; + #else + if (pid_output >= 8) + enable_heater(); + else + disable_heater(); + #endif +} + +uint8_t temp_achieved() { + if (temp_residency >= TEMP_RESIDENCY_TIME) + return 255; + return 0; +} diff --git a/heater.h b/heater.h new file mode 100644 index 0000000..56e760f --- /dev/null +++ b/heater.h @@ -0,0 +1,21 @@ +#ifndef _HEATER_H +#define _HEATER_H + +#include + +// extruder heater PID factors +// google "PID without a PHD" if you don't understand this PID stuff +extern int32_t p_factor; +extern int32_t i_factor; +extern int32_t d_factor; +extern int16_t i_limit; + +#define PID_SCALE 1024L +#define I_LIMIT 4000 + +void heater_init(void); +void heater_save_settings(void); +void heater_tick(int16_t current_temp, int16_t target_temp); +uint8_t temp_achieved(void); + +#endif /* _HEATER_H */ diff --git a/mendel.c b/mendel.c index 0b59f00..fe45239 100644 --- a/mendel.c +++ b/mendel.c @@ -18,6 +18,7 @@ #include "watchdog.h" #include "debug.h" #include "sersendf.h" +#include "heater.h" void io_init(void) { // disable modules we don't use @@ -92,7 +93,7 @@ void init(void) { clock_setup(); // read PID settings from EEPROM - temp_init(); + heater_init(); // set up default feedrate current_position.F = startpoint.F = next_target.target.F = SEARCH_FEEDRATE_Z; diff --git a/temp.c b/temp.c index c1310b9..72d9d67 100644 --- a/temp.c +++ b/temp.c @@ -29,11 +29,12 @@ #include "dda.h" #include "sersendf.h" #include "debug.h" +#include "heater.h" uint16_t current_temp = 0; uint16_t target_temp = 0; -int16_t heater_p = 0; +/*int16_t heater_p = 0; int16_t heater_i = 0; int16_t heater_d = 0; @@ -45,47 +46,26 @@ 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; +*/ +// 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; +/*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; @@ -144,12 +124,6 @@ uint16_t temp_get_target() { return target_temp; } -uint8_t temp_achieved() { - if (temp_residency >= TEMP_RESIDENCY_TIME) - return 255; - return 0; -} - void temp_print() { if (temp_flags & TEMP_FLAG_TCOPEN) { serial_writestr_P(PSTR("T: no thermocouple!\n")); @@ -173,7 +147,9 @@ void temp_tick() { temp_read(); - temp_history[th_p++] = current_temp; + heater_tick(current_temp, target_temp); + +/* temp_history[th_p++] = current_temp; th_p &= (TH_COUNT - 1); if (ABSDELTA(current_temp, target_temp) > TEMP_HYSTERESIS) @@ -227,6 +203,6 @@ void temp_tick() { enable_heater(); else disable_heater(); - #endif + #endif*/ } } diff --git a/temp.h b/temp.h index 44c3acd..9605f0e 100644 --- a/temp.h +++ b/temp.h @@ -6,16 +6,6 @@ // RepRap host software isn't exactly tolerant on what it ready back. #define REPRAP_HOST_COMPATIBILITY -// extruder heater PID factors -// google "PID without a PHD" if you don't understand this PID stuff -extern int32_t p_factor; -extern int32_t i_factor; -extern int32_t d_factor; -extern int16_t i_limit; - -#define PID_SCALE 1024L -#define I_LIMIT 4000 - typedef union { struct { uint8_t high;