merge multi_temp stuff
This commit is contained in:
parent
c5e544b1fe
commit
d93dcff378
|
|
@ -71,6 +71,63 @@
|
||||||
#define TEMP_THERMISTOR
|
#define TEMP_THERMISTOR
|
||||||
// #define TEMP_AD595
|
// #define TEMP_AD595
|
||||||
|
|
||||||
|
#define NUM_TEMP_SENSORS 1
|
||||||
|
#ifdef TEMP_C
|
||||||
|
/***************************************************************************\
|
||||||
|
* *
|
||||||
|
* Fill in the following struct according to your hardware *
|
||||||
|
* *
|
||||||
|
* If your temperature sensor has no associated heater, enter '255' as the *
|
||||||
|
* heater index. *
|
||||||
|
* *
|
||||||
|
\***************************************************************************/
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t temp_type;
|
||||||
|
uint8_t temp_pin;
|
||||||
|
|
||||||
|
uint8_t heater_index;
|
||||||
|
} temp_sensors[NUM_TEMP_SENSORS] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TT_MAX6675,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUM_HEATERS 1
|
||||||
|
#ifdef HEATER_C
|
||||||
|
/***************************************************************************\
|
||||||
|
* *
|
||||||
|
* Fill in the following struct according to your hardware *
|
||||||
|
* *
|
||||||
|
* For the atmega168/328, timer/pin mappings are as follows *
|
||||||
|
* *
|
||||||
|
* OCR0A - PD6 *
|
||||||
|
* OCR0B - PD5 *
|
||||||
|
* OCR2A - PB3 *
|
||||||
|
* OCR2B - PD3 *
|
||||||
|
* *
|
||||||
|
\***************************************************************************/
|
||||||
|
struct {
|
||||||
|
volatile uint8_t *heater_port;
|
||||||
|
uint8_t heater_pin;
|
||||||
|
volatile uint8_t *heater_pwm;
|
||||||
|
} heaters[NUM_HEATERS] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
&PORTD,
|
||||||
|
PIND0,
|
||||||
|
&OCR0A
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// temperature history count. higher values make PID derivative term more stable at the expense of reaction time
|
||||||
|
#define TH_COUNT 8
|
||||||
|
|
||||||
// if you selected thermistor or AD595, what pin is it on?
|
// if you selected thermistor or AD595, what pin is it on?
|
||||||
#define TEMP_PIN_CHANNEL AIO0_PIN
|
#define TEMP_PIN_CHANNEL AIO0_PIN
|
||||||
#define ANALOG_MASK MASK(TEMP_PIN_CHANNEL)
|
#define ANALOG_MASK MASK(TEMP_PIN_CHANNEL)
|
||||||
|
|
@ -224,6 +281,8 @@
|
||||||
#define FAN_PIN DIO5
|
#define FAN_PIN DIO5
|
||||||
#define FAN_PWM OCR0B
|
#define FAN_PWM OCR0B
|
||||||
|
|
||||||
|
#define PID_SCALE 1024L
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// you shouldn't need to edit anything below this line
|
// you shouldn't need to edit anything below this line
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ void process_gcode_command() {
|
||||||
|
|
||||||
// M104- set temperature
|
// M104- set temperature
|
||||||
case 104:
|
case 104:
|
||||||
temp_set(next_target.S);
|
temp_set(next_target.P, next_target.S);
|
||||||
if (next_target.S) {
|
if (next_target.S) {
|
||||||
enable_heater();
|
enable_heater();
|
||||||
power_on();
|
power_on();
|
||||||
|
|
@ -209,7 +209,7 @@ void process_gcode_command() {
|
||||||
|
|
||||||
// M105- get temperature
|
// M105- get temperature
|
||||||
case 105:
|
case 105:
|
||||||
temp_print();
|
temp_print(next_target.P);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// M106- fan on
|
// M106- fan on
|
||||||
|
|
@ -225,7 +225,7 @@ void process_gcode_command() {
|
||||||
|
|
||||||
// M109- set temp and wait
|
// M109- set temp and wait
|
||||||
case 109:
|
case 109:
|
||||||
temp_set(next_target.S);
|
temp_set(next_target.P, next_target.S);
|
||||||
if (next_target.S) {
|
if (next_target.S) {
|
||||||
enable_heater();
|
enable_heater();
|
||||||
power_on();
|
power_on();
|
||||||
|
|
@ -266,22 +266,26 @@ void process_gcode_command() {
|
||||||
// M130- heater P factor
|
// M130- heater P factor
|
||||||
case 130:
|
case 130:
|
||||||
if (next_target.seen_S)
|
if (next_target.seen_S)
|
||||||
p_factor = next_target.S;
|
// p_factor = next_target.S;
|
||||||
|
pid_set_p(next_target.P, next_target.S);
|
||||||
break;
|
break;
|
||||||
// M131- heater I factor
|
// M131- heater I factor
|
||||||
case 131:
|
case 131:
|
||||||
if (next_target.seen_S)
|
if (next_target.seen_S)
|
||||||
i_factor = next_target.S;
|
// i_factor = next_target.S;
|
||||||
|
pid_set_i(next_target.P, next_target.S);
|
||||||
break;
|
break;
|
||||||
// M132- heater D factor
|
// M132- heater D factor
|
||||||
case 132:
|
case 132:
|
||||||
if (next_target.seen_S)
|
if (next_target.seen_S)
|
||||||
d_factor = next_target.S;
|
// d_factor = next_target.S;
|
||||||
|
pid_set_d(next_target.P, next_target.S);
|
||||||
break;
|
break;
|
||||||
// M133- heater I limit
|
// M133- heater I limit
|
||||||
case 133:
|
case 133:
|
||||||
if (next_target.seen_S)
|
if (next_target.seen_S)
|
||||||
i_limit = next_target.S;
|
// i_limit = next_target.S;
|
||||||
|
pid_set_i_limit(next_target.P, next_target.S);
|
||||||
break;
|
break;
|
||||||
// M134- save PID settings to eeprom
|
// M134- save PID settings to eeprom
|
||||||
case 134:
|
case 134:
|
||||||
|
|
|
||||||
162
heater.c
162
heater.c
|
|
@ -1,107 +1,149 @@
|
||||||
#include "heater.h"
|
#include "heater.h"
|
||||||
|
|
||||||
#ifdef HEATER_PIN
|
|
||||||
|
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
#include "sersendf.h"
|
#include "arduino.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "sersendf.h"
|
||||||
|
|
||||||
int16_t heater_p = 0;
|
#define HEATER_C
|
||||||
int16_t heater_i = 0;
|
#include "config.h"
|
||||||
int16_t heater_d = 0;
|
|
||||||
|
// this struct holds the heater PID factors that are stored in the EEPROM during poweroff
|
||||||
|
struct {
|
||||||
|
int32_t p_factor;
|
||||||
|
int32_t i_factor;
|
||||||
|
int32_t d_factor;
|
||||||
|
int16_t i_limit;
|
||||||
|
} heaters_pid[NUM_HEATERS];
|
||||||
|
|
||||||
|
// this struct holds the runtime heater data- PID counters and such
|
||||||
|
struct {
|
||||||
|
int16_t heater_p;
|
||||||
|
int16_t heater_i;
|
||||||
|
int16_t heater_d;
|
||||||
|
|
||||||
|
uint8_t pid_output;
|
||||||
|
|
||||||
|
uint16_t temp_history[TH_COUNT];
|
||||||
|
uint8_t temp_history_pointer;
|
||||||
|
} heaters_runtime[NUM_HEATERS];
|
||||||
|
|
||||||
#define DEFAULT_P 8192
|
#define DEFAULT_P 8192
|
||||||
#define DEFAULT_I 512
|
#define DEFAULT_I 512
|
||||||
#define DEFAULT_D -24576
|
#define DEFAULT_D -24576
|
||||||
#define DEFAULT_I_LIMIT 384
|
#define DEFAULT_I_LIMIT 384
|
||||||
|
|
||||||
int32_t p_factor = 0;
|
// this lives in the eeprom so we can save our PID settings for each heater
|
||||||
int32_t i_factor = 0;
|
typedef struct {
|
||||||
int32_t d_factor = 0;
|
int32_t EE_p_factor;
|
||||||
int16_t i_limit = 0;
|
int32_t EE_i_factor;
|
||||||
|
int32_t EE_d_factor;
|
||||||
|
int16_t EE_i_limit;
|
||||||
|
} EE_factor;
|
||||||
|
|
||||||
int32_t EEMEM EE_p_factor;
|
EE_factor EEMEM EE_factors[NUM_HEATERS];
|
||||||
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;
|
|
||||||
|
|
||||||
void heater_init() {
|
void heater_init() {
|
||||||
p_factor = eeprom_read_dword((uint32_t *) &EE_p_factor);
|
// read factors from eeprom
|
||||||
i_factor = eeprom_read_dword((uint32_t *) &EE_i_factor);
|
uint8_t i;
|
||||||
d_factor = eeprom_read_dword((uint32_t *) &EE_d_factor);
|
for (i = 0; i < NUM_HEATERS; i++) {
|
||||||
i_limit = eeprom_read_word((uint16_t *) &EE_i_limit);
|
heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor);
|
||||||
|
heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor);
|
||||||
|
heaters_pid[i].d_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_d_factor);
|
||||||
|
heaters_pid[i].i_limit = eeprom_read_word((uint16_t *) &EE_factors[i].EE_i_limit);
|
||||||
|
|
||||||
if ((p_factor == 0) && (i_factor == 0) && (d_factor == 0) && (i_limit == 0)) {
|
if ((heaters_pid[i].p_factor == 0) && (heaters_pid[i].i_factor == 0) && (heaters_pid[i].d_factor == 0) && (heaters_pid[i].i_limit == 0)) {
|
||||||
p_factor = DEFAULT_P;
|
heaters_pid[i].p_factor = DEFAULT_P;
|
||||||
i_factor = DEFAULT_I;
|
heaters_pid[i].i_factor = DEFAULT_I;
|
||||||
d_factor = DEFAULT_D;
|
heaters_pid[i].d_factor = DEFAULT_D;
|
||||||
i_limit = DEFAULT_I_LIMIT;
|
heaters_pid[i].i_limit = DEFAULT_I_LIMIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void heater_save_settings() {
|
void heater_save_settings() {
|
||||||
eeprom_write_dword((uint32_t *) &EE_p_factor, p_factor);
|
uint8_t i;
|
||||||
eeprom_write_dword((uint32_t *) &EE_i_factor, i_factor);
|
for (i = 0; i < NUM_HEATERS; i++) {
|
||||||
eeprom_write_dword((uint32_t *) &EE_d_factor, d_factor);
|
eeprom_write_dword((uint32_t *) &EE_factors[i].EE_p_factor, heaters_pid[i].p_factor);
|
||||||
eeprom_write_word((uint16_t *) &EE_i_limit, i_limit);
|
eeprom_write_dword((uint32_t *) &EE_factors[i].EE_i_factor, heaters_pid[i].i_factor);
|
||||||
|
eeprom_write_dword((uint32_t *) &EE_factors[i].EE_d_factor, heaters_pid[i].d_factor);
|
||||||
|
eeprom_write_word((uint16_t *) &EE_factors[i].EE_i_limit, heaters_pid[i].i_limit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void heater_tick(int16_t current_temp, int16_t target_temp) {
|
void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) {
|
||||||
|
// now for heater stuff
|
||||||
int16_t t_error = target_temp - current_temp;
|
int16_t t_error = target_temp - current_temp;
|
||||||
|
|
||||||
temp_history[th_p++] = current_temp;
|
heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer++] = current_temp;
|
||||||
th_p &= (TH_COUNT - 1);
|
heaters_runtime[h].temp_history_pointer &= (TH_COUNT - 1);
|
||||||
|
|
||||||
// PID stuff
|
// PID stuff
|
||||||
// proportional
|
// proportional
|
||||||
heater_p = t_error;
|
heaters_runtime[h].heater_p = t_error;
|
||||||
|
|
||||||
// integral
|
// integral
|
||||||
heater_i += t_error;
|
heaters_runtime[h].heater_i += t_error;
|
||||||
// prevent integrator wind-up
|
// prevent integrator wind-up
|
||||||
if (heater_i > i_limit)
|
if (heaters_runtime[h].heater_i > heaters_pid[h].i_limit)
|
||||||
heater_i = i_limit;
|
heaters_runtime[h].heater_i = heaters_pid[h].i_limit;
|
||||||
else if (heater_i < -i_limit)
|
else if (heaters_runtime[h].heater_i < -heaters_pid[h].i_limit)
|
||||||
heater_i = -i_limit;
|
heaters_runtime[h].heater_i = -heaters_pid[h].i_limit;
|
||||||
|
|
||||||
// derivative
|
// derivative
|
||||||
// note: D follows temp rather than error so there's no large derivative when the target changes
|
// 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];
|
heaters_runtime[h].heater_d = current_temp - heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer];
|
||||||
|
|
||||||
// combine factors
|
// combine factors
|
||||||
int32_t pid_output_intermed = (
|
int32_t pid_output_intermed = (
|
||||||
(
|
(
|
||||||
(((int32_t) heater_p) * p_factor) +
|
(((int32_t) heaters_runtime[h].heater_p) * heaters_pid[h].p_factor) +
|
||||||
(((int32_t) heater_i) * i_factor) +
|
(((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) +
|
||||||
(((int32_t) heater_d) * d_factor)
|
(((int32_t) heaters_runtime[h].heater_d) * heaters_pid[h].d_factor)
|
||||||
) / PID_SCALE
|
) / PID_SCALE
|
||||||
);
|
);
|
||||||
|
|
||||||
// rebase and limit factors
|
// rebase and limit factors
|
||||||
uint8_t pid_output;
|
|
||||||
if (pid_output_intermed > 255)
|
if (pid_output_intermed > 255)
|
||||||
pid_output = 255;
|
heaters_runtime[h].pid_output = 255;
|
||||||
else if (pid_output_intermed < 0)
|
else if (pid_output_intermed < 0)
|
||||||
pid_output = 0;
|
heaters_runtime[h].pid_output = 0;
|
||||||
else
|
else
|
||||||
pid_output = pid_output_intermed & 0xFF;
|
heaters_runtime[h].pid_output = pid_output_intermed & 0xFF;
|
||||||
|
|
||||||
if (debug_flags & DEBUG_PID)
|
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);
|
sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heaters_runtime[h].heater_p, heaters_pid[h].p_factor, (int32_t) heaters_runtime[h].heater_p * heaters_pid[h].p_factor / PID_SCALE, heaters_runtime[h].heater_i, heaters_pid[h].i_factor, (int32_t) heaters_runtime[h].heater_i * heaters_pid[h].i_factor / PID_SCALE, heaters_runtime[h].heater_d, heaters_pid[h].d_factor, (int32_t) heaters_runtime[h].heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, heaters_runtime[h].pid_output);
|
||||||
|
|
||||||
#ifdef HEATER_PWM
|
heater_set(h, heaters_runtime[h].pid_output);
|
||||||
HEATER_PWM = pid_output;
|
|
||||||
#else
|
|
||||||
if (pid_output >= 8)
|
|
||||||
enable_heater();
|
|
||||||
else
|
|
||||||
disable_heater();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HEATER_PIN */
|
void heater_set(uint8_t index, uint8_t value) {
|
||||||
|
if (heaters[index].heater_pwm) {
|
||||||
|
*heaters[index].heater_pwm = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (value >= 8)
|
||||||
|
*heaters[index].heater_port |= MASK(heaters[index].heater_pin);
|
||||||
|
else
|
||||||
|
*heaters[index].heater_port &= ~MASK(heaters[index].heater_pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_set_p(uint8_t index, int32_t p) {
|
||||||
|
heaters_pid[index].p_factor = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_set_i(uint8_t index, int32_t i) {
|
||||||
|
heaters_pid[index].i_factor = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_set_d(uint8_t index, int32_t d) {
|
||||||
|
heaters_pid[index].d_factor = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_set_i_limit(uint8_t index, int32_t i_limit) {
|
||||||
|
heaters_pid[index].i_limit = i_limit;
|
||||||
|
}
|
||||||
|
|
|
||||||
38
heater.h
38
heater.h
|
|
@ -1,40 +1,20 @@
|
||||||
#ifndef _HEATER_H
|
#ifndef _HEATER_H
|
||||||
#define _HEATER_H
|
#define _HEATER_H
|
||||||
|
|
||||||
#include "config.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef HEATER_PIN
|
#define enable_heater() heater_set(0, 64)
|
||||||
|
#define disable_heater() heater_set(0, 0)
|
||||||
#ifdef HEATER_PWM
|
|
||||||
#define enable_heater() do { TCCR0A |= MASK(COM0A1); } while (0)
|
|
||||||
#define disable_heater() do { TCCR0A &= ~MASK(COM0A1); } while (0)
|
|
||||||
#else
|
|
||||||
#define enable_heater() WRITE(HEATER_PIN, 1)
|
|
||||||
#define disable_heater() WRITE(HEATER_PIN, 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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_init(void);
|
||||||
void heater_save_settings(void);
|
void heater_save_settings(void);
|
||||||
void heater_tick(int16_t current_temp, int16_t target_temp);
|
|
||||||
|
|
||||||
#else /* HEATER_PIN */
|
void heater_set(uint8_t index, uint8_t value);
|
||||||
|
void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp);
|
||||||
|
|
||||||
// if there is no heater pin, there is no heater
|
void pid_set_p(uint8_t index, int32_t p);
|
||||||
#define enable_heater() /* empty */
|
void pid_set_i(uint8_t index, int32_t i);
|
||||||
#define disable_heater() /* empty */
|
void pid_set_d(uint8_t index, int32_t d);
|
||||||
#define heater_init() /* empty */
|
void pid_set_i_limit(uint8_t index, int32_t i_limit);
|
||||||
#define heater_save_settings() /* empty */
|
|
||||||
#define heater_tick(p1, p2) /* empty */
|
|
||||||
|
|
||||||
#endif /* HEATER_PIN */
|
|
||||||
#endif /* _HEATER_H */
|
#endif /* _HEATER_H */
|
||||||
|
|
|
||||||
6
mendel.c
6
mendel.c
|
|
@ -62,6 +62,12 @@ void io_init(void) {
|
||||||
TIMSK0 = 0;
|
TIMSK0 = 0;
|
||||||
OCR0A = 0;
|
OCR0A = 0;
|
||||||
OCR0B = 255;
|
OCR0B = 255;
|
||||||
|
|
||||||
|
TCCR2A = MASK(WGM21) | MASK(WGM20);
|
||||||
|
TCCR2B = MASK(CS20);
|
||||||
|
TIMSK2 = 0;
|
||||||
|
OCR2A = 0;
|
||||||
|
OCR2B = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STEPPER_ENABLE_PIN
|
#ifdef STEPPER_ENABLE_PIN
|
||||||
|
|
|
||||||
333
temp.c
333
temp.c
|
|
@ -1,34 +1,41 @@
|
||||||
/*
|
#include "temp.h"
|
||||||
temp.c
|
|
||||||
|
|
||||||
This file currently reads temp from a MAX6675 on the SPI bus.
|
|
||||||
|
|
||||||
temp fields are 14.2 fixed point, so temp_set(500) will set the temperature to 125 celsius, and temp_get() = 600 is reporting a temperature of 150 celsius.
|
|
||||||
|
|
||||||
the conversion to/from this unit is done in gcode.c, near:
|
|
||||||
if (next_target.M == 104)
|
|
||||||
next_target.S = decfloat_to_int(&read_digit, 4, 1);
|
|
||||||
and
|
|
||||||
// M105- get temperature
|
|
||||||
case 105:
|
|
||||||
uint16_t t = temp_get();
|
|
||||||
|
|
||||||
note that the MAX6675 can't do more than approx 5 conversions per second- we go for 4 so the timing isn't too tight
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "temp.h"
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "arduino.h"
|
||||||
#include "serial.h"
|
|
||||||
#include "sermsg.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "dda.h"
|
|
||||||
#include "sersendf.h"
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "sersendf.h"
|
||||||
#include "heater.h"
|
#include "heater.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TT_THERMISTOR,
|
||||||
|
TT_MAX6675,
|
||||||
|
TT_AD595
|
||||||
|
} temp_types;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PRESENT,
|
||||||
|
TCOPEN
|
||||||
|
} temp_flags_enum;
|
||||||
|
|
||||||
|
#define TEMP_C
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
// this struct holds the runtime sensor data- read temperatures, targets, etc
|
||||||
|
struct {
|
||||||
|
temp_flags_enum temp_flags;
|
||||||
|
|
||||||
|
uint16_t last_read_temp;
|
||||||
|
uint16_t target_temp;
|
||||||
|
|
||||||
|
uint8_t temp_residency;
|
||||||
|
|
||||||
|
uint16_t next_read_time;
|
||||||
|
} temp_sensors_runtime[NUM_TEMP_SENSORS];
|
||||||
|
|
||||||
#ifdef TEMP_MAX6675
|
#ifdef TEMP_MAX6675
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -64,157 +71,143 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = {
|
||||||
#include "analog.h"
|
#include "analog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TEMP_MAX6675
|
void temp_sensor_tick() {
|
||||||
#ifndef TEMP_THERMISTOR
|
uint8_t i = 0, all_within_range = 1;
|
||||||
#ifndef TEMP_AD595
|
for (; i < NUM_TEMP_SENSORS; i++) {
|
||||||
#error none of TEMP_MAX6675, TEMP_THERMISTOR or TEMP_AD595 are defined! What type of temp sensor are you using?
|
if (temp_sensors_runtime[i].next_read_time) {
|
||||||
#endif
|
temp_sensors_runtime[i].next_read_time--;
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t current_temp = 0;
|
|
||||||
uint16_t target_temp = 0;
|
|
||||||
|
|
||||||
uint8_t temp_flags = 0;
|
|
||||||
uint8_t temp_residency = 0;
|
|
||||||
|
|
||||||
#ifndef ABSDELTA
|
|
||||||
#define ABSDELTA(a, b) (((a) >= (b))?((a) - (b)):((b) - (a)))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t temp_read() {
|
|
||||||
uint16_t temp;
|
|
||||||
|
|
||||||
#ifdef TEMP_MAX6675
|
|
||||||
#ifdef PRR
|
|
||||||
PRR &= ~MASK(PRSPI);
|
|
||||||
#elif defined PRR0
|
|
||||||
PRR0 &= ~MASK(PRSPI);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);
|
|
||||||
|
|
||||||
// enable MAX6675
|
|
||||||
WRITE(SS, 0);
|
|
||||||
|
|
||||||
// ensure 100ns delay - a bit extra is fine
|
|
||||||
delay(1);
|
|
||||||
|
|
||||||
// read MSB
|
|
||||||
SPDR = 0;
|
|
||||||
for (;(SPSR & MASK(SPIF)) == 0;);
|
|
||||||
temp = SPDR;
|
|
||||||
temp <<= 8;
|
|
||||||
|
|
||||||
// read LSB
|
|
||||||
SPDR = 0;
|
|
||||||
for (;(SPSR & MASK(SPIF)) == 0;);
|
|
||||||
temp |= SPDR;
|
|
||||||
|
|
||||||
// disable MAX6675
|
|
||||||
WRITE(SS, 1);
|
|
||||||
|
|
||||||
temp_flags = 0;
|
|
||||||
if ((temp & 0x8002) == 0) {
|
|
||||||
// got "device id"
|
|
||||||
temp_flags |= TEMP_FLAG_PRESENT;
|
|
||||||
if (temp & 4) {
|
|
||||||
// thermocouple open
|
|
||||||
temp_flags |= TEMP_FLAG_TCOPEN;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
current_temp = temp >> 3;
|
uint16_t temp = 0;
|
||||||
return current_temp;
|
#ifdef TEMP_THERMISTOR
|
||||||
|
uint8_t j;
|
||||||
|
#endif
|
||||||
|
//time to deal with this temp sensor
|
||||||
|
switch(temp_sensors[i].temp_type) {
|
||||||
|
#ifdef TEMP_MAX6675
|
||||||
|
case TT_MAX6675:
|
||||||
|
#ifdef PRR
|
||||||
|
PRR &= ~MASK(PRSPI);
|
||||||
|
#elif defined PRR0
|
||||||
|
PRR0 &= ~MASK(PRSPI);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);
|
||||||
|
|
||||||
|
// enable TT_MAX6675
|
||||||
|
WRITE(SS, 0);
|
||||||
|
|
||||||
|
// ensure 100ns delay - a bit extra is fine
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
// read MSB
|
||||||
|
SPDR = 0;
|
||||||
|
for (;(SPSR & MASK(SPIF)) == 0;);
|
||||||
|
temp = SPDR;
|
||||||
|
temp <<= 8;
|
||||||
|
|
||||||
|
// read LSB
|
||||||
|
SPDR = 0;
|
||||||
|
for (;(SPSR & MASK(SPIF)) == 0;);
|
||||||
|
temp |= SPDR;
|
||||||
|
|
||||||
|
// disable TT_MAX6675
|
||||||
|
WRITE(SS, 1);
|
||||||
|
|
||||||
|
temp_sensors_runtime[i].temp_flags = 0;
|
||||||
|
if ((temp & 0x8002) == 0) {
|
||||||
|
// got "device id"
|
||||||
|
temp_sensors_runtime[i].temp_flags |= PRESENT;
|
||||||
|
if (temp & 4) {
|
||||||
|
// thermocouple open
|
||||||
|
temp_sensors_runtime[i].temp_flags |= TCOPEN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp = temp >> 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: placeholder number
|
||||||
|
temp_sensors_runtime[i].next_read_time = 25;
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif /* TEMP_MAX6675 */
|
||||||
|
|
||||||
|
#ifdef TEMP_THERMISTOR
|
||||||
|
case TT_THERMISTOR:
|
||||||
|
|
||||||
|
//Read current temperature
|
||||||
|
temp = analog_read(temp_sensors[i].temp_pin);
|
||||||
|
|
||||||
|
//Calculate real temperature based on lookup table
|
||||||
|
for (j = 1; j < NUMTEMPS; j++) {
|
||||||
|
if (pgm_read_word(&(temptable[j][0])) > temp) {
|
||||||
|
// multiply by 4 because internal temp is stored as 14.2 fixed point
|
||||||
|
temp = pgm_read_word(&(temptable[j][1])) + (pgm_read_word(&(temptable[j][0])) - temp) * 4 * (pgm_read_word(&(temptable[j-1][1])) - pgm_read_word(&(temptable[j][1]))) / (pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0])));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clamp for overflows
|
||||||
|
if (j == NUMTEMPS)
|
||||||
|
temp = temptable[NUMTEMPS-1][1];
|
||||||
|
|
||||||
|
// FIXME: placeholder number
|
||||||
|
temp_sensors_runtime[i].next_read_time = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif /* TEMP_THERMISTOR */
|
||||||
|
|
||||||
|
#ifdef TEMP_AD595
|
||||||
|
case TT_AD595:
|
||||||
|
temp = analog_read(temp_pin);
|
||||||
|
|
||||||
|
// convert
|
||||||
|
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
|
||||||
|
temp = (temp * 500L) >> 8;
|
||||||
|
|
||||||
|
// FIXME: placeholder number
|
||||||
|
temp_sensors[i].next_read_time = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif /* TEMP_AD595 */
|
||||||
|
}
|
||||||
|
temp_sensors_runtime[i].last_read_temp = temp;
|
||||||
|
|
||||||
|
if (labs(temp - temp_sensors_runtime[i].target_temp) < TEMP_HYSTERESIS) {
|
||||||
|
if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME)
|
||||||
|
temp_sensors_runtime[i].temp_residency++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp_sensors_runtime[i].temp_residency = 0;
|
||||||
|
all_within_range = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp_sensors[i].heater_index != 255) {
|
||||||
|
heater_tick(temp_sensors[i].heater_index, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* TEMP_MAX6675 */
|
|
||||||
|
|
||||||
#ifdef TEMP_THERMISTOR
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
//Read current temperature
|
|
||||||
temp = analog_read(TEMP_PIN_CHANNEL);
|
|
||||||
|
|
||||||
//Calculate real temperature based on lookup table
|
|
||||||
for (i = 1; i < NUMTEMPS; i++) {
|
|
||||||
if (pgm_read_word(&(temptable[i][0])) > temp) {
|
|
||||||
// multiply by 4 because internal temp is stored as 14.2 fixed point
|
|
||||||
temp = pgm_read_word(&(temptable[i][1])) + (pgm_read_word(&(temptable[i][0])) - temp) * 4 * (pgm_read_word(&(temptable[i-1][1])) - pgm_read_word(&(temptable[i][1]))) / (pgm_read_word(&(temptable[i][0])) - pgm_read_word(&(temptable[i-1][0])));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clamp for overflows
|
|
||||||
if (i == NUMTEMPS)
|
|
||||||
temp = temptable[NUMTEMPS-1][1];
|
|
||||||
|
|
||||||
return temp;
|
|
||||||
|
|
||||||
#endif /* TEMP_THERMISTOR */
|
|
||||||
|
|
||||||
#ifdef TEMP_AD595
|
|
||||||
temp = analog_read(TEMP_PIN_CHANNEL);
|
|
||||||
|
|
||||||
// convert
|
|
||||||
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
|
|
||||||
temp = (temp * 500L) >> 8;
|
|
||||||
|
|
||||||
return temp;
|
|
||||||
#endif /* TEMP_AD595 */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void temp_set(uint16_t t) {
|
|
||||||
if (t) {
|
|
||||||
steptimeout = 0;
|
|
||||||
power_on();
|
|
||||||
}
|
|
||||||
target_temp = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t temp_get() {
|
|
||||||
return current_temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t temp_get_target() {
|
|
||||||
return target_temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void temp_print() {
|
|
||||||
if (temp_flags & TEMP_FLAG_TCOPEN) {
|
|
||||||
serial_writestr_P(PSTR("T: no thermocouple!\n"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
uint8_t c = 0, t = 0;
|
|
||||||
|
|
||||||
c = (current_temp & 3) * 25;
|
|
||||||
t = (target_temp & 3) * 25;
|
|
||||||
#ifdef REPRAP_HOST_COMPATIBILITY
|
|
||||||
sersendf_P(PSTR(" T: %u.%u\n"), current_temp >> 2, c);
|
|
||||||
#else
|
|
||||||
sersendf_P(PSTR("T: %u.%u/%u.%u :%u\n"), current_temp >> 2, c, target_temp >> 2, t, temp_residency);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void temp_tick() {
|
|
||||||
if (target_temp) {
|
|
||||||
steptimeout = 0;
|
|
||||||
|
|
||||||
temp_read();
|
|
||||||
|
|
||||||
heater_tick(current_temp, target_temp);
|
|
||||||
|
|
||||||
if (ABSDELTA(current_temp, target_temp) > TEMP_HYSTERESIS)
|
|
||||||
temp_residency = 0;
|
|
||||||
else if (temp_residency < TEMP_RESIDENCY_TIME)
|
|
||||||
temp_residency++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t temp_achieved() {
|
uint8_t temp_achieved() {
|
||||||
if (temp_residency >= TEMP_RESIDENCY_TIME)
|
uint8_t i, all_ok = 255;
|
||||||
return 255;
|
for (i = 0; i < NUM_TEMP_SENSORS; i++) {
|
||||||
return 0;
|
if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME)
|
||||||
|
all_ok = 0;
|
||||||
|
}
|
||||||
|
return all_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void temp_set(uint8_t index, uint16_t temperature) {
|
||||||
|
temp_sensors_runtime[index].target_temp = temperature;
|
||||||
|
temp_sensors_runtime[index].temp_residency = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void temp_print(uint8_t index) {
|
||||||
|
uint8_t c = 0;
|
||||||
|
|
||||||
|
c = (temp_sensors_runtime[index].last_read_temp & 3) * 25;
|
||||||
|
|
||||||
|
sersendf_P(PSTR("T: %u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
temp.h
56
temp.h
|
|
@ -3,59 +3,23 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "config.h"
|
/*
|
||||||
|
NOTES
|
||||||
|
|
||||||
#define TEMP_FLAG_PRESENT 1
|
no point in specifying a port- all the different temp sensors we have must be on a particular port. The MAX6675 must be on the SPI, and the thermistor and AD595 must be on an analog port.
|
||||||
#define TEMP_FLAG_TCOPEN 2
|
|
||||||
|
|
||||||
#ifdef TEMP_MAX6675
|
we still need to specify which analog pins we use in machine.h for the analog sensors however, otherwise the analog subsystem won't read them.
|
||||||
typedef union {
|
*/
|
||||||
struct {
|
|
||||||
uint8_t high;
|
|
||||||
uint8_t low;
|
|
||||||
} buf;
|
|
||||||
struct {
|
|
||||||
uint16_t dummy :1;
|
|
||||||
uint16_t reading :12;
|
|
||||||
uint16_t tc_open :1;
|
|
||||||
uint16_t device_id :1;
|
|
||||||
uint16_t tristate :1;
|
|
||||||
} interpret;
|
|
||||||
} max6675_data_format;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TEMP_THERMISTOR
|
#define temp_tick temp_sensor_tick
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TEMP_AD595
|
void temp_sensor_tick(void);
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// set target temperature
|
|
||||||
void temp_set(uint16_t t);
|
|
||||||
|
|
||||||
// return last read temperature
|
|
||||||
uint16_t temp_get(void);
|
|
||||||
|
|
||||||
// return target temperature
|
|
||||||
uint16_t temp_get_target(void);
|
|
||||||
|
|
||||||
// true if last read temp is close to target temp, false otherwise
|
|
||||||
uint8_t temp_achieved(void);
|
uint8_t temp_achieved(void);
|
||||||
|
|
||||||
// send current temperature to host
|
void temp_set(uint8_t index, uint16_t temperature);
|
||||||
void temp_print(void);
|
void temp_print(uint8_t index);
|
||||||
|
|
||||||
// periodically read temperature and update heater with PID
|
uint16_t temp_read(uint8_t index);
|
||||||
void temp_tick(void);
|
|
||||||
|
|
||||||
#endif /* _TIMER_H */
|
#endif /* _TIMER_H */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue