Manage heaters. More...
#include "heater.h"
#include <stdlib.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include "arduino.h"
#include <avr/io.h>
#include <stdint.h>
#include "temp.h"
#include "crc.h"
#include "sersendf.h"
Data Structures | |
struct | heater_definition_t |
simply holds pinout data- port, pin, pwm channel if used More... | |
struct | EE_factor |
this lives in the eeprom so we can save our PID settings for each heater More... | |
Defines | |
#define | DEFINE_HEATER(name, pin) { &(pin ## _WPORT), pin ## _PIN, (pin ## _PWM) }, |
helper macro to fill heater definition struct from config.h | |
#define | HOST |
#define | STEPS_PER_M_X 333333 |
#define | STEPS_PER_M_Y 333333 |
#define | STEPS_PER_M_Z 333333 |
#define | MAXIMUM_FEEDRATE_X 2000 |
#define | MAXIMUM_FEEDRATE_Y 2000 |
#define | MAXIMUM_FEEDRATE_Z 2000 |
#define | SEARCH_FEEDRATE_X 60 |
#define | SEARCH_FEEDRATE_Y 60 |
#define | SEARCH_FEEDRATE_Z 60 |
#define | X_MIN 0.0 |
#define | X_MAX 720.0 |
#define | Y_MIN 0.0 |
#define | Y_MAX 420.0 |
#define | Z_MIN 0.0 |
#define | Z_MAX 110.0 |
#define | ACCELERATION_RAMPING |
#define | ACCELERATION 50. |
#define | MASK(PIN) (1 << PIN) |
#define | _READ(IO) (IO ## _RPORT & MASK(IO ## _PIN)) |
#define | _WRITE(IO, v) do { if (v) { IO ## _WPORT |= MASK(IO ## _PIN); } else { IO ## _WPORT &= ~MASK(IO ## _PIN); }; } while (0) |
#define | _TOGGLE(IO) do { IO ## _RPORT = MASK(IO ## _PIN); } while (0) |
#define | _SET_INPUT(IO) do { IO ## _DDR &= ~MASK(IO ## _PIN); } while (0) |
#define | _SET_OUTPUT(IO) do { IO ## _DDR |= MASK(IO ## _PIN); } while (0) |
#define | _GET_INPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) == 0) |
#define | _GET_OUTPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) != 0) |
#define | READ(IO) _READ(IO) |
#define | WRITE(IO, v) _WRITE(IO, v) |
#define | TOGGLE(IO) _TOGGLE(IO) |
#define | SET_INPUT(IO) _SET_INPUT(IO) |
#define | SET_OUTPUT(IO) _SET_OUTPUT(IO) |
#define | GET_INPUT(IO) _GET_INPUT(IO) |
#define | GET_OUTPUT(IO) _GET_OUTPUT(IO) |
#define | X_STEP_PIN AIO0 |
#define | X_DIR_PIN AIO1 |
#define | X_MIN_PIN AIO2 |
#define | X_INVERT_DIR 1 |
#define | X_INVERT_MIN 1 |
#define | Y_STEP_PIN AIO3 |
#define | Y_DIR_PIN AIO4 |
#define | Y_MIN_PIN AIO5 |
#define | Y_INVERT_MIN 1 |
#define | Z_STEP_PIN DIO2 |
#define | Z_DIR_PIN DIO4 |
#define | Z_MIN_PIN DIO7 |
#define | Z_INVERT_MIN 1 |
#define | CHARGEPUMP_PIN DIO3 |
#define | ESTOP_IN_PIN DIO8 |
#define | ESTOP_INVERT_IN 1 |
#define | BAUD 115200 |
#define | XONXOFF |
#define | MOVEBUFFER_SIZE 8 |
#define | USE_WATCHDOG |
#define | STEP_INTERRUPT_INTERRUPTIBLE 0 |
#define | ENDSTOP_STEPS 4 |
#define | DEFAULT_P 8192 |
default scaled P factor, equivalent to 8.0 | |
#define | DEFAULT_I 512 |
default scaled I factor, equivalent to 0.5 | |
#define | DEFAULT_D 24576 |
default scaled D factor, equivalent to 24 | |
#define | DEFAULT_I_LIMIT 384 |
default scaled I limit | |
Functions | |
void | heater_init () |
initialise heater subsystem Set directions, initialise PWM timers, read PID factors from eeprom, etc | |
void | heater_save_settings () |
Write PID factors to eeprom. | |
void | heater_tick (heater_t h, temp_sensor_t t, uint16_t current_temp, uint16_t target_temp) |
run heater PID algorithm | |
void | heater_set (heater_t index, uint8_t value) |
manually set PWM output | |
uint8_t | heaters_all_off () |
turn off all heaters | |
void | pid_set_p (heater_t index, int32_t p) |
set heater P factor | |
void | pid_set_i (heater_t index, int32_t i) |
set heater I factor | |
void | pid_set_d (heater_t index, int32_t d) |
set heater D factor | |
void | pid_set_i_limit (heater_t index, int32_t i_limit) |
set heater I limit | |
void | heater_print (uint16_t i) |
send heater debug info to host | |
Variables | |
struct { | |
int32_t p_factor | |
scaled P factor | |
int32_t i_factor | |
scaled I factor | |
int32_t d_factor | |
scaled D factor | |
int16_t i_limit | |
scaled I limit, such that ![]() | |
} | heaters_pid [NUM_HEATERS] |
this struct holds the heater PID factors | |
struct { | |
int16_t heater_i | |
integrator, ![]() | |
uint16_t temp_history [TH_COUNT] | |
store last TH_COUNT readings in a ring, so we can smooth out our differentiator | |
uint8_t temp_history_pointer | |
pointer to last entry in ring | |
uint8_t heater_output | |
this is the PID value we eventually send to the heater | |
} | heaters_runtime [NUM_HEATERS] |
this struct holds the runtime heater data- PID integrator history, temperature history, sanity checker | |
EE_factor EEMEM | EE_factors [NUM_HEATERS] |
Manage heaters.
void heater_print | ( | uint16_t | i | ) |
send heater debug info to host
i | index of heater to send info for |
void heater_set | ( | heater_t | index, | |
uint8_t | value | |||
) |
manually set PWM output
index | the heater we're setting the output for | |
value | the PWM value to write |
anything done by this function is overwritten by heater_tick above if the heater has an associated temp sensor
Referenced by heater_tick().
void heater_tick | ( | heater_t | h, | |
temp_sensor_t | t, | |||
uint16_t | current_temp, | |||
uint16_t | target_temp | |||
) |
run heater PID algorithm
h | which heater we're running the loop for | |
t | which temp sensor this heater is attached to | |
current_temp | the temperature that the associated temp sensor is reporting | |
target_temp | the temperature we're trying to achieve |
Referenced by temp_sensor_tick().
uint8_t heaters_all_off | ( | void | ) |
turn off all heaters
for emergency stop
void pid_set_d | ( | heater_t | index, | |
int32_t | d | |||
) |
set heater D factor
index | heater to change D factor for | |
d | scaled D factor |
void pid_set_i | ( | heater_t | index, | |
int32_t | i | |||
) |
set heater I factor
index | heater to change I factor for | |
i | scaled I factor |
void pid_set_i_limit | ( | heater_t | index, | |
int32_t | i_limit | |||
) |
set heater I limit
index | heater to set I limit for | |
i_limit | scaled I limit |
void pid_set_p | ( | heater_t | index, | |
int32_t | p | |||
) |
set heater P factor
index | heater to change factor for | |
p | scaled P factor |
this struct holds the heater PID factors
PID is a fascinating way to control any closed loop control, combining the error (P), cumulative error (I) and rate at which we're approacing the setpoint (D) in such a way that when correctly tuned, the system will achieve target temperature quickly and with little to no overshoot
At every sample, we calculate where S is setpoint and T is temperature.
The three factors kP, kI, kD are chosen to give the desired behaviour given the dynamics of the system.
See http://www.eetimes.com/design/embedded/4211211/PID-without-a-PhD for the full story
Referenced by heater_init(), heater_print(), heater_save_settings(), heater_tick(), pid_set_d(), pid_set_i(), pid_set_i_limit(), and pid_set_p().