preliminary untested implementation of Markus Amsler's new extruder comms protocol
This commit is contained in:
parent
84457ccc4b
commit
b1a48994dd
|
|
@ -54,8 +54,8 @@ void analog_init() {
|
||||||
adc_counter = 0;
|
adc_counter = 0;
|
||||||
adc_running_mask = 1;
|
adc_running_mask = 1;
|
||||||
|
|
||||||
AIO0_DDR &= ANALOG_MASK;
|
AIO0_DDR &= ~(ANALOG_MASK);
|
||||||
DIDR0 = ANALOG_MASK & 0x3F;
|
DIDR0 = (ANALOG_MASK) & 0x3F;
|
||||||
|
|
||||||
// now we start the first conversion and leave the rest to the interrupt
|
// now we start the first conversion and leave the rest to the interrupt
|
||||||
ADCSRA |= MASK(ADIE) | MASK(ADSC);
|
ADCSRA |= MASK(ADIE) | MASK(ADSC);
|
||||||
|
|
@ -73,7 +73,7 @@ ISR(ADC_vect, ISR_NOBLOCK) {
|
||||||
adc_counter = ANALOG_START;
|
adc_counter = ANALOG_START;
|
||||||
adc_running_mask = ANALOG_START_MASK;
|
adc_running_mask = ANALOG_START_MASK;
|
||||||
}
|
}
|
||||||
} while ((adc_running_mask & ANALOG_MASK) == 0);
|
} while ((adc_running_mask & (ANALOG_MASK)) == 0);
|
||||||
|
|
||||||
// start next conversion
|
// start next conversion
|
||||||
ADMUX = (adc_counter) | REFERENCE;
|
ADMUX = (adc_counter) | REFERENCE;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "arduino.h"
|
#include "arduino.h"
|
||||||
|
|
||||||
|
// controller index- bus is multidrop after all
|
||||||
|
#define THIS_CONTROLLER_NUM 0
|
||||||
|
|
||||||
//RS485 Interface pins
|
//RS485 Interface pins
|
||||||
#define RX_ENABLE_PIN DIO4
|
#define RX_ENABLE_PIN DIO4
|
||||||
#define TX_ENABLE_PIN AIO2
|
#define TX_ENABLE_PIN AIO2
|
||||||
|
|
@ -40,33 +43,13 @@
|
||||||
#define TEMP_HYSTERESIS 20
|
#define TEMP_HYSTERESIS 20
|
||||||
#define TEMP_RESIDENCY_TIME 60
|
#define TEMP_RESIDENCY_TIME 60
|
||||||
|
|
||||||
#define NUM_TEMP_SENSORS 1
|
#ifdef DEFINE_TEMP_SENSOR
|
||||||
#ifdef TEMP_C
|
DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, PINC3)
|
||||||
/***************************************************************************\
|
#endif
|
||||||
* *
|
|
||||||
* Fill in the following struct according to your hardware *
|
|
||||||
* *
|
|
||||||
* If your temperature sensor has no associated heater, enter '255' as the *
|
|
||||||
* heater index. *
|
|
||||||
* *
|
|
||||||
* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to *
|
|
||||||
* 255 *
|
|
||||||
* *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
struct {
|
#ifdef DEFINE_HEATER
|
||||||
uint8_t temp_type;
|
DEFINE_HEATER(extruder, PORTD, DIO6_PIN, OCR0A)
|
||||||
uint8_t temp_pin;
|
DEFINE_HEATER(bed, PORTD, DIO5_PIN, OCR0B)
|
||||||
|
|
||||||
uint8_t heater_index;
|
|
||||||
} temp_sensors[NUM_TEMP_SENSORS] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
TT_THERMISTOR,
|
|
||||||
PINC3,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// list of PWM-able pins and corresponding timers
|
// list of PWM-able pins and corresponding timers
|
||||||
|
|
@ -81,49 +64,6 @@ struct {
|
||||||
#define TH_COUNT 8
|
#define TH_COUNT 8
|
||||||
#define PID_SCALE 1024L
|
#define PID_SCALE 1024L
|
||||||
|
|
||||||
#define NUM_HEATERS 2
|
|
||||||
#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,
|
|
||||||
PIND6,
|
|
||||||
&OCR0A
|
|
||||||
},
|
|
||||||
{
|
|
||||||
&PORTB,
|
|
||||||
PINB4,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// #define HEATER_PIN DIO11
|
|
||||||
// #define HEATER_PWM OCR2A
|
|
||||||
//
|
|
||||||
// #define BED_PIN DIO12
|
|
||||||
|
|
||||||
/*
|
|
||||||
Intercom
|
|
||||||
*/
|
|
||||||
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0)
|
|
||||||
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Motors
|
Motors
|
||||||
|
|
@ -132,16 +72,4 @@ struct {
|
||||||
#define enable_motors() do { TCCR0A |= MASK(COM0A1) | MASK(COM0B1); } while (0)
|
#define enable_motors() do { TCCR0A |= MASK(COM0A1) | MASK(COM0B1); } while (0)
|
||||||
#define disable_motors() do { TCCR0A &= ~MASK(COM0A1) & ~MASK(COM0B1); } while (0)
|
#define disable_motors() do { TCCR0A &= ~MASK(COM0A1) & ~MASK(COM0B1); } while (0)
|
||||||
|
|
||||||
/*
|
|
||||||
Heater
|
|
||||||
*/
|
|
||||||
|
|
||||||
// #ifdef HEATER_PWM
|
|
||||||
// #define enable_heater() do { TCCR2A |= MASK(COM2A1); } while (0)
|
|
||||||
// #define disable_heater() do { TCCR2A &= ~MASK(COM2A1); } while (0)
|
|
||||||
// #else
|
|
||||||
// #define enable_heater() WRITE(HEATER_PIN, 1)
|
|
||||||
// #define disable_heater() WRITE(HEATER_PIN, 0)
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
#endif /* _CONFIG_H */
|
#endif /* _CONFIG_H */
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,12 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
// by setting these to zero, the compiler should optimise the relevant code out
|
||||||
#define DEBUG_PID 1
|
#define DEBUG_PID 0
|
||||||
#define DEBUG_DDA 2
|
#define DEBUG_DDA 0
|
||||||
#define DEBUG_POSITION 4
|
#define DEBUG_POSITION 0
|
||||||
#else
|
|
||||||
// by setting these to zero, the compiler should optimise the relevant code out
|
|
||||||
#define DEBUG_PID 0
|
|
||||||
#define DEBUG_DDA 0
|
|
||||||
#define DEBUG_POSITION 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEBUG_ECHO 128
|
#define DEBUG_ECHO 0
|
||||||
|
|
||||||
extern volatile uint8_t debug_flags;
|
extern volatile uint8_t debug_flags;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ int main (void)
|
||||||
|
|
||||||
temp_sensor_tick();
|
temp_sensor_tick();
|
||||||
|
|
||||||
update_send_cmd(temp_get(0) >> 2);
|
send_temperature(0, temp_get(0));
|
||||||
temp_set(0, get_read_cmd());
|
temp_set(0, read_temperature(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,21 @@
|
||||||
#ifndef EXTRUDER
|
#ifndef EXTRUDER
|
||||||
#include "sersendf.h"
|
#include "sersendf.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "temp.h"
|
||||||
|
|
||||||
#define HEATER_C
|
typedef struct {
|
||||||
#include "config.h"
|
volatile uint8_t *heater_port;
|
||||||
|
uint8_t heater_pin;
|
||||||
|
volatile uint8_t *heater_pwm;
|
||||||
|
} heater_definition_t;
|
||||||
|
|
||||||
|
#undef DEFINE_HEATER
|
||||||
|
#define DEFINE_HEATER(name, port, pin, pwm) { &(port), (pin), &(pwm) },
|
||||||
|
static const heater_definition_t heaters[NUM_HEATERS] =
|
||||||
|
{
|
||||||
|
#include "config.h"
|
||||||
|
};
|
||||||
|
#undef DEFINE_HEATER
|
||||||
|
|
||||||
// this struct holds the heater PID factors that are stored in the EEPROM during poweroff
|
// this struct holds the heater PID factors that are stored in the EEPROM during poweroff
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -32,6 +44,8 @@ struct {
|
||||||
uint16_t sanity_counter;
|
uint16_t sanity_counter;
|
||||||
uint16_t sane_temperature;
|
uint16_t sane_temperature;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint8_t heater_output;
|
||||||
} heaters_runtime[NUM_HEATERS];
|
} heaters_runtime[NUM_HEATERS];
|
||||||
|
|
||||||
#define DEFAULT_P 8192
|
#define DEFAULT_P 8192
|
||||||
|
|
@ -50,8 +64,7 @@ typedef struct {
|
||||||
EE_factor EEMEM EE_factors[NUM_HEATERS];
|
EE_factor EEMEM EE_factors[NUM_HEATERS];
|
||||||
|
|
||||||
void heater_init() {
|
void heater_init() {
|
||||||
#if NUM_HEATERS > 0
|
heater_t i;
|
||||||
uint8_t i;
|
|
||||||
// setup pins
|
// setup pins
|
||||||
for (i = 0; i < NUM_HEATERS; i++) {
|
for (i = 0; i < NUM_HEATERS; i++) {
|
||||||
*(heaters[i].heater_port) &= ~MASK(heaters[i].heater_pin);
|
*(heaters[i].heater_port) &= ~MASK(heaters[i].heater_pin);
|
||||||
|
|
@ -80,82 +93,96 @@ void heater_init() {
|
||||||
// 0 is a "sane" temperature when we're trying to cool down
|
// 0 is a "sane" temperature when we're trying to cool down
|
||||||
heaters_runtime[i].sane_temperature = 0;
|
heaters_runtime[i].sane_temperature = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// read factors from eeprom
|
#ifndef BANG_BANG
|
||||||
heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor);
|
// read factors from eeprom
|
||||||
heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor);
|
heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor);
|
||||||
heaters_pid[i].d_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_d_factor);
|
heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor);
|
||||||
heaters_pid[i].i_limit = eeprom_read_word((uint16_t *) &EE_factors[i].EE_i_limit);
|
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 ((heaters_pid[i].p_factor == 0) && (heaters_pid[i].i_factor == 0) && (heaters_pid[i].d_factor == 0) && (heaters_pid[i].i_limit == 0)) {
|
|
||||||
heaters_pid[i].p_factor = DEFAULT_P;
|
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)) {
|
||||||
heaters_pid[i].i_factor = DEFAULT_I;
|
heaters_pid[i].p_factor = DEFAULT_P;
|
||||||
heaters_pid[i].d_factor = DEFAULT_D;
|
heaters_pid[i].i_factor = DEFAULT_I;
|
||||||
heaters_pid[i].i_limit = DEFAULT_I_LIMIT;
|
heaters_pid[i].d_factor = DEFAULT_D;
|
||||||
}
|
heaters_pid[i].i_limit = DEFAULT_I_LIMIT;
|
||||||
|
}
|
||||||
|
#endif /* BANG_BANG */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void heater_save_settings() {
|
void heater_save_settings() {
|
||||||
uint8_t i;
|
#ifndef BANG_BANG
|
||||||
for (i = 0; i < NUM_HEATERS; i++) {
|
heater_t i;
|
||||||
eeprom_write_dword((uint32_t *) &EE_factors[i].EE_p_factor, heaters_pid[i].p_factor);
|
for (i = 0; i < NUM_HEATERS; i++) {
|
||||||
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_p_factor, heaters_pid[i].p_factor);
|
||||||
eeprom_write_dword((uint32_t *) &EE_factors[i].EE_d_factor, heaters_pid[i].d_factor);
|
eeprom_write_dword((uint32_t *) &EE_factors[i].EE_i_factor, heaters_pid[i].i_factor);
|
||||||
eeprom_write_word((uint16_t *) &EE_factors[i].EE_i_limit, heaters_pid[i].i_limit);
|
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);
|
||||||
|
}
|
||||||
|
#endif /* BANG_BANG */
|
||||||
}
|
}
|
||||||
|
|
||||||
void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) {
|
void heater_tick(heater_t h, temp_sensor_t t, uint16_t current_temp, uint16_t target_temp) {
|
||||||
#if NUM_HEATERS > 0
|
|
||||||
int16_t heater_p;
|
|
||||||
int16_t heater_d;
|
|
||||||
uint8_t pid_output;
|
uint8_t pid_output;
|
||||||
|
|
||||||
int16_t t_error = target_temp - current_temp;
|
|
||||||
|
|
||||||
heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer++] = current_temp;
|
|
||||||
heaters_runtime[h].temp_history_pointer &= (TH_COUNT - 1);
|
|
||||||
|
|
||||||
// PID stuff
|
|
||||||
// proportional
|
|
||||||
heater_p = t_error;
|
|
||||||
|
|
||||||
// integral
|
|
||||||
heaters_runtime[h].heater_i += t_error;
|
|
||||||
// prevent integrator wind-up
|
|
||||||
if (heaters_runtime[h].heater_i > heaters_pid[h].i_limit)
|
|
||||||
heaters_runtime[h].heater_i = heaters_pid[h].i_limit;
|
|
||||||
else if (heaters_runtime[h].heater_i < -heaters_pid[h].i_limit)
|
|
||||||
heaters_runtime[h].heater_i = -heaters_pid[h].i_limit;
|
|
||||||
|
|
||||||
// derivative
|
|
||||||
// note: D follows temp rather than error so there's no large derivative when the target changes
|
|
||||||
heater_d = heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer] - current_temp;
|
|
||||||
|
|
||||||
// combine factors
|
|
||||||
int32_t pid_output_intermed = (
|
|
||||||
(
|
|
||||||
(((int32_t) heater_p) * heaters_pid[h].p_factor) +
|
|
||||||
(((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) +
|
|
||||||
(((int32_t) heater_d) * heaters_pid[h].d_factor)
|
|
||||||
) / PID_SCALE
|
|
||||||
);
|
|
||||||
|
|
||||||
// rebase and limit factors
|
|
||||||
if (pid_output_intermed > 255)
|
|
||||||
pid_output = 255;
|
|
||||||
else if (pid_output_intermed < 0)
|
|
||||||
pid_output = 0;
|
|
||||||
else
|
|
||||||
pid_output = pid_output_intermed & 0xFF;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifndef BANG_BANG
|
||||||
if (debug_flags & DEBUG_PID)
|
int16_t heater_p;
|
||||||
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, heaters_pid[h].p_factor, (int32_t) 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, heater_d, heaters_pid[h].d_factor, (int32_t) heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, pid_output);
|
int16_t heater_d;
|
||||||
|
int16_t t_error = target_temp - current_temp;
|
||||||
|
#endif /* BANG_BANG */
|
||||||
|
|
||||||
|
if (h >= NUM_HEATERS || t >= NUM_TEMP_SENSORS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifndef BANG_BANG
|
||||||
|
heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer++] = current_temp;
|
||||||
|
heaters_runtime[h].temp_history_pointer &= (TH_COUNT - 1);
|
||||||
|
|
||||||
|
// PID stuff
|
||||||
|
// proportional
|
||||||
|
heater_p = t_error;
|
||||||
|
|
||||||
|
// integral
|
||||||
|
heaters_runtime[h].heater_i += t_error;
|
||||||
|
// prevent integrator wind-up
|
||||||
|
if (heaters_runtime[h].heater_i > heaters_pid[h].i_limit)
|
||||||
|
heaters_runtime[h].heater_i = heaters_pid[h].i_limit;
|
||||||
|
else if (heaters_runtime[h].heater_i < -heaters_pid[h].i_limit)
|
||||||
|
heaters_runtime[h].heater_i = -heaters_pid[h].i_limit;
|
||||||
|
|
||||||
|
// derivative
|
||||||
|
// note: D follows temp rather than error so there's no large derivative when the target changes
|
||||||
|
heater_d = heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer] - current_temp;
|
||||||
|
|
||||||
|
// combine factors
|
||||||
|
int32_t pid_output_intermed = (
|
||||||
|
(
|
||||||
|
(((int32_t) heater_p) * heaters_pid[h].p_factor) +
|
||||||
|
(((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) +
|
||||||
|
(((int32_t) heater_d) * heaters_pid[h].d_factor)
|
||||||
|
) / PID_SCALE
|
||||||
|
);
|
||||||
|
|
||||||
|
// rebase and limit factors
|
||||||
|
if (pid_output_intermed > 255)
|
||||||
|
pid_output = 255;
|
||||||
|
else if (pid_output_intermed < 0)
|
||||||
|
pid_output = 0;
|
||||||
|
else
|
||||||
|
pid_output = pid_output_intermed & 0xFF;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
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, heaters_pid[h].p_factor, (int32_t) 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, heater_d, heaters_pid[h].d_factor, (int32_t) heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, pid_output);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if (current_temp >= target_temp)
|
||||||
|
pid_output = BANG_BANG_ON;
|
||||||
|
else
|
||||||
|
pid_output = BANG_BANG_OFF;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HEATER_SANITY_CHECK
|
#ifdef HEATER_SANITY_CHECK
|
||||||
// check heater sanity
|
// check heater sanity
|
||||||
// implementation is a moving window with some slow-down to compensate for thermal mass
|
// implementation is a moving window with some slow-down to compensate for thermal mass
|
||||||
|
|
@ -208,16 +235,19 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) {
|
||||||
if (labs(current_temp - heaters_runtime[h].sane_temperature) > TEMP_HYSTERESIS) {
|
if (labs(current_temp - heaters_runtime[h].sane_temperature) > TEMP_HYSTERESIS) {
|
||||||
// no change, or change in wrong direction for a long time- heater is broken!
|
// no change, or change in wrong direction for a long time- heater is broken!
|
||||||
pid_output = 0;
|
pid_output = 0;
|
||||||
sersendf_P(PSTR("!! heater %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter);
|
sersendf_P(PSTR("!! heater %d or temp sensor %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, t, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter);
|
||||||
}
|
}
|
||||||
#endif /* HEATER_SANITY_CHECK */
|
#endif /* HEATER_SANITY_CHECK */
|
||||||
|
|
||||||
heater_set(h, pid_output);
|
heater_set(h, pid_output);
|
||||||
#endif /* if NUM_HEATERS > 0 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void heater_set(uint8_t index, uint8_t value) {
|
void heater_set(heater_t index, uint8_t value) {
|
||||||
#if NUM_HEATERS > 0
|
if (index >= NUM_HEATERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heaters_runtime[index].heater_output = value;
|
||||||
|
|
||||||
if (heaters[index].heater_pwm) {
|
if (heaters[index].heater_pwm) {
|
||||||
*(heaters[index].heater_pwm) = value;
|
*(heaters[index].heater_pwm) = value;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -231,21 +261,50 @@ void heater_set(uint8_t index, uint8_t value) {
|
||||||
else
|
else
|
||||||
*(heaters[index].heater_port) &= ~MASK(heaters[index].heater_pin);
|
*(heaters[index].heater_port) &= ~MASK(heaters[index].heater_pin);
|
||||||
}
|
}
|
||||||
#endif /* if NUM_HEATERS > 0 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pid_set_p(uint8_t index, int32_t p) {
|
uint8_t heaters_all_off() {
|
||||||
heaters_pid[index].p_factor = p;
|
uint8_t i;
|
||||||
|
for (i = 0; i < NUM_HEATERS; i++) {
|
||||||
|
if (heaters_runtime[i].heater_output > 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pid_set_i(uint8_t index, int32_t i) {
|
void pid_set_p(heater_t index, int32_t p) {
|
||||||
heaters_pid[index].i_factor = i;
|
#ifndef BANG_BANG
|
||||||
|
if (index >= NUM_HEATERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heaters_pid[index].p_factor = p;
|
||||||
|
#endif /* BANG_BANG */
|
||||||
}
|
}
|
||||||
|
|
||||||
void pid_set_d(uint8_t index, int32_t d) {
|
void pid_set_i(heater_t index, int32_t i) {
|
||||||
heaters_pid[index].d_factor = d;
|
#ifndef BANG_BANG
|
||||||
|
if (index >= NUM_HEATERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heaters_pid[index].i_factor = i;
|
||||||
|
#endif /* BANG_BANG */
|
||||||
}
|
}
|
||||||
|
|
||||||
void pid_set_i_limit(uint8_t index, int32_t i_limit) {
|
void pid_set_d(heater_t index, int32_t d) {
|
||||||
heaters_pid[index].i_limit = i_limit;
|
#ifndef BANG_BANG
|
||||||
|
if (index >= NUM_HEATERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heaters_pid[index].d_factor = d;
|
||||||
|
#endif /* BANG_BANG */
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_set_i_limit(heater_t index, int32_t i_limit) {
|
||||||
|
#ifndef BANG_BANG
|
||||||
|
if (index >= NUM_HEATERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heaters_pid[index].i_limit = i_limit;
|
||||||
|
#endif /* BANG_BANG */
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,34 @@
|
||||||
#ifndef _HEATER_H
|
#ifndef _HEATER_H
|
||||||
#define _HEATER_H
|
#define _HEATER_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "temp.h"
|
||||||
|
|
||||||
#define enable_heater() heater_set(0, 64)
|
#define enable_heater() heater_set(0, 64)
|
||||||
#define disable_heater() heater_set(0, 0)
|
#define disable_heater() heater_set(0, 0)
|
||||||
|
|
||||||
|
#undef DEFINE_HEATER
|
||||||
|
#define DEFINE_HEATER(name, port, pin, pwm) HEATER_ ## name,
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
#include "config.h"
|
||||||
|
NUM_HEATERS,
|
||||||
|
HEATER_noheater
|
||||||
|
} heater_t;
|
||||||
|
#undef DEFINE_HEATER
|
||||||
|
|
||||||
void heater_init(void);
|
void heater_init(void);
|
||||||
void heater_save_settings(void);
|
void heater_save_settings(void);
|
||||||
|
|
||||||
void heater_set(uint8_t index, uint8_t value);
|
void heater_set(heater_t index, uint8_t value);
|
||||||
void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp);
|
void heater_tick(heater_t h, temp_sensor_t t, uint16_t current_temp, uint16_t target_temp);
|
||||||
|
|
||||||
void pid_set_p(uint8_t index, int32_t p);
|
uint8_t heaters_all_off(void);
|
||||||
void pid_set_i(uint8_t index, int32_t i);
|
|
||||||
void pid_set_d(uint8_t index, int32_t d);
|
void pid_set_p(heater_t index, int32_t p);
|
||||||
void pid_set_i_limit(uint8_t index, int32_t i_limit);
|
void pid_set_i(heater_t index, int32_t i);
|
||||||
|
void pid_set_d(heater_t index, int32_t d);
|
||||||
|
void pid_set_i_limit(heater_t index, int32_t i_limit);
|
||||||
|
|
||||||
#endif /* _HEATER_H */
|
#endif /* _HEATER_H */
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,53 @@
|
||||||
#include "intercom.h"
|
#include "intercom.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
||||||
#ifdef GEN3
|
#if (defined TEMP_INTERCOM) || (defined EXTRUDER)
|
||||||
#define INTERCOM_BAUD 57600
|
#define INTERCOM_BAUD 57600
|
||||||
|
|
||||||
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0)
|
#define START 0x55
|
||||||
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0)
|
|
||||||
|
|
||||||
/*
|
enum {
|
||||||
Defines a super simple intercom interface using the RS485 modules
|
ERROR_BAD_CRC
|
||||||
|
} err_codes;
|
||||||
|
|
||||||
Host will say: START1 START2 PWM_CMD PWM_CHK
|
typedef struct {
|
||||||
Extruder will reply: START1 START2 TMP_CMD TMP_CHK
|
uint8_t start;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t dio0 :1;
|
||||||
|
uint8_t dio1 :1;
|
||||||
|
uint8_t dio2 :1;
|
||||||
|
uint8_t dio3 :1;
|
||||||
|
uint8_t dio4 :1;
|
||||||
|
uint8_t dio5 :1;
|
||||||
|
uint8_t dio6 :1;
|
||||||
|
uint8_t dio7 :1;
|
||||||
|
};
|
||||||
|
uint8_t dio;
|
||||||
|
};
|
||||||
|
uint8_t controller_num;
|
||||||
|
uint16_t temp[3];
|
||||||
|
uint8_t err;
|
||||||
|
uint8_t crc;
|
||||||
|
} intercom_packet_t;
|
||||||
|
|
||||||
CHK = 255-CMD, if they match do the work, if not, ignore this packet
|
typedef union {
|
||||||
|
intercom_packet_t packet;
|
||||||
|
uint8_t data[sizeof(intercom_packet_t)];
|
||||||
|
} intercom_packet;
|
||||||
|
|
||||||
in a loop
|
intercom_packet tx;
|
||||||
*/
|
intercom_packet rx;
|
||||||
|
|
||||||
|
uint8_t packet_pointer;
|
||||||
|
uint8_t rxcrc;
|
||||||
|
|
||||||
#define START1 0xAA
|
volatile uint8_t intercom_flags;
|
||||||
#define START2 0x55
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SEND_START1,
|
|
||||||
SEND_START2,
|
|
||||||
SEND_CMD,
|
|
||||||
SEND_CHK,
|
|
||||||
SEND_DONE,
|
|
||||||
|
|
||||||
READ_START1,
|
|
||||||
READ_START2,
|
|
||||||
READ_CMD,
|
|
||||||
READ_CHK,
|
|
||||||
} intercom_state_e;
|
|
||||||
|
|
||||||
|
|
||||||
intercom_state_e state = READ_START1;
|
|
||||||
uint8_t cmd, chk, send_cmd, read_cmd;
|
|
||||||
|
|
||||||
void intercom_init(void)
|
void intercom_init(void)
|
||||||
{
|
{
|
||||||
|
|
@ -70,30 +76,60 @@ void intercom_init(void)
|
||||||
|
|
||||||
UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0);
|
UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
intercom_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_send_cmd(uint8_t new_send_cmd) {
|
void send_temperature(uint8_t index, uint16_t temperature) {
|
||||||
send_cmd = new_send_cmd;
|
tx.packet.temp[index] = temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t get_read_cmd(void) {
|
uint16_t read_temperature(uint8_t index) {
|
||||||
return read_cmd;
|
return rx.packet.temp[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_byte(uint8_t val) {
|
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
UDR1 = val;
|
void set_dio(uint8_t index, uint8_t value) {
|
||||||
|
if (value)
|
||||||
|
tx.packet.dio |= (1 << index);
|
||||||
|
else
|
||||||
|
tx.packet.dio &= ~(1 << index);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
UDR0 = val;
|
uint8_t get_dio(uint8_t index) {
|
||||||
|
return rx.packet.dio & (1 << index);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void set_err(uint8_t err) {
|
||||||
|
tx.packet.err = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t get_err() {
|
||||||
|
return rx.packet.err;
|
||||||
|
}
|
||||||
|
|
||||||
void start_send(void) {
|
void start_send(void) {
|
||||||
state = SEND_START1;
|
uint8_t txcrc = 0, i;
|
||||||
|
|
||||||
|
// atomically update flags
|
||||||
|
uint8_t sreg = SREG;
|
||||||
|
cli();
|
||||||
|
intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS;
|
||||||
|
SREG = sreg;
|
||||||
|
|
||||||
|
// calculate CRC for outgoing packet
|
||||||
|
for (i = 0; i < (sizeof(intercom_packet_t) - 1); i++) {
|
||||||
|
txcrc ^= tx.data[i];
|
||||||
|
}
|
||||||
|
tx.packet.crc = txcrc;
|
||||||
|
|
||||||
|
// enable transmit pin
|
||||||
enable_transmit();
|
enable_transmit();
|
||||||
delay_us(15);
|
delay_us(15);
|
||||||
//Enable interrupts so we can send next characters
|
|
||||||
|
// actually start sending the packet
|
||||||
|
packet_pointer = 0;
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
UCSR1B |= MASK(UDRIE1);
|
UCSR1B |= MASK(UDRIE1);
|
||||||
#else
|
#else
|
||||||
|
|
@ -101,119 +137,100 @@ void start_send(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finish_send(void) {
|
|
||||||
state = READ_START1;
|
|
||||||
disable_transmit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Interrupts, UART 0 for mendel
|
Interrupts, UART 0 for mendel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// receive data interrupt- stuff into rx
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
ISR(USART1_RX_vect)
|
ISR(USART1_RX_vect)
|
||||||
#else
|
#else
|
||||||
ISR(USART_RX_vect)
|
ISR(USART_RX_vect)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
// pull character
|
||||||
static uint8_t c;
|
static uint8_t c;
|
||||||
|
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
c = UDR1;
|
c = UDR1;
|
||||||
UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1);
|
UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1);
|
||||||
#else
|
#else
|
||||||
c = UDR0;
|
c = UDR0;
|
||||||
UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0);
|
UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (state >= READ_START1) {
|
// are we waiting for a start byte? is this one?
|
||||||
|
if ((packet_pointer == 0) && (c == START)) {
|
||||||
switch(state) {
|
rxcrc = rx.packet.start = START;
|
||||||
case READ_START1:
|
packet_pointer = 1;
|
||||||
if (c == START1) state = READ_START2;
|
intercom_flags |= FLAG_RX_IN_PROGRESS;
|
||||||
break;
|
|
||||||
case READ_START2:
|
|
||||||
if (c == START2) state = READ_CMD;
|
|
||||||
else state = READ_START1;
|
|
||||||
break;
|
|
||||||
case READ_CMD:
|
|
||||||
cmd = c;
|
|
||||||
state = READ_CHK;
|
|
||||||
break;
|
|
||||||
case READ_CHK:
|
|
||||||
chk = c;
|
|
||||||
|
|
||||||
if (chk == 255 - cmd) {
|
|
||||||
//Values are correct, do something useful
|
|
||||||
WRITE(DEBUG_LED,1);
|
|
||||||
read_cmd = cmd;
|
|
||||||
#ifdef EXTRUDER
|
|
||||||
start_send();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = READ_START1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we're receiving a packet
|
||||||
|
if (packet_pointer > 0) {
|
||||||
|
// calculate CRC (except CRC character!)
|
||||||
|
if (packet_pointer < (sizeof(intercom_packet_t) - 1))
|
||||||
|
rxcrc ^= c;
|
||||||
|
// stuff byte into structure
|
||||||
|
rx.data[packet_pointer++] = c;
|
||||||
|
// last byte?
|
||||||
|
if (packet_pointer >= sizeof(intercom_packet_t)) {
|
||||||
|
// reset pointer
|
||||||
|
packet_pointer = 0;
|
||||||
|
|
||||||
|
intercom_flags = (intercom_flags & ~FLAG_RX_IN_PROGRESS) | FLAG_NEW_RX;
|
||||||
|
#ifndef HOST
|
||||||
|
if (rx.packet.controller_num == THIS_CONTROLLER_NUM) {
|
||||||
|
if (rxcrc != rx.packet.crc)
|
||||||
|
tx.packet.err = ERROR_BAD_CRC;
|
||||||
|
start_send();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finished transmitting interrupt- only enabled at end of packet
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
ISR(USART1_TX_vect)
|
ISR(USART1_TX_vect)
|
||||||
#else
|
#else
|
||||||
ISR(USART_TX_vect)
|
ISR(USART_TX_vect)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (state == SEND_DONE) {
|
if (packet_pointer >= sizeof(intercom_packet_t)) {
|
||||||
finish_send();
|
disable_transmit();
|
||||||
|
packet_pointer = 0;
|
||||||
|
intercom_flags = (intercom_flags & ~FLAG_TX_IN_PROGRESS) | FLAG_TX_FINISHED;
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
UCSR1B &= ~MASK(TXCIE1);
|
UCSR1B &= ~MASK(TXCIE1);
|
||||||
#else
|
#else
|
||||||
UCSR0B &= ~MASK(TXCIE0);
|
UCSR0B &= ~MASK(TXCIE0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tx queue empty interrupt- send next byte
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
ISR(USART1_UDRE_vect)
|
ISR(USART1_UDRE_vect)
|
||||||
#else
|
#else
|
||||||
ISR(USART_UDRE_vect)
|
ISR(USART_UDRE_vect)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
switch(state) {
|
#ifdef HOST
|
||||||
case SEND_START1:
|
UDR1 = tx.data[packet_pointer++];
|
||||||
write_byte(START1);
|
#else
|
||||||
state = SEND_START2;
|
UDR0 = tx.data[packet_pointer++];
|
||||||
break;
|
#endif
|
||||||
case SEND_START2:
|
|
||||||
write_byte(START2);
|
if (packet_pointer >= sizeof(intercom_packet_t)) {
|
||||||
state = SEND_CMD;
|
#ifdef HOST
|
||||||
break;
|
UCSR1B &= ~MASK(UDRIE1);
|
||||||
case SEND_CMD:
|
UCSR1B |= MASK(TXCIE1);
|
||||||
write_byte(send_cmd);
|
#else
|
||||||
state = SEND_CHK;
|
UCSR0B &= ~MASK(UDRIE0);
|
||||||
break;
|
UCSR0B |= MASK(TXCIE0);
|
||||||
case SEND_CHK:
|
#endif
|
||||||
write_byte(255 - send_cmd);
|
|
||||||
state = SEND_DONE;
|
|
||||||
#ifdef HOST
|
|
||||||
UCSR1B &= ~MASK(UDRIE1);
|
|
||||||
UCSR1B |= MASK(TXCIE1);
|
|
||||||
#else
|
|
||||||
UCSR0B &= ~MASK(UDRIE0);
|
|
||||||
UCSR0B |= MASK(TXCIE0);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* GEN3 */
|
#endif /* TEMP_INTERCOM */
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,42 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0)
|
||||||
|
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0)
|
||||||
|
|
||||||
// initialise serial subsystem
|
// initialise serial subsystem
|
||||||
void intercom_init(void);
|
void intercom_init(void);
|
||||||
|
|
||||||
//Update the message we are sending over intercom
|
// if host, send target temperature to extruder
|
||||||
void update_send_cmd(uint8_t new_send_cmd);
|
// if extruder, send actual temperature to host
|
||||||
|
void send_temperature(uint8_t index, uint16_t temperature);
|
||||||
|
|
||||||
|
// if host, read actual temperature from extruder
|
||||||
|
// if extruder, read target temperature from host
|
||||||
|
uint16_t read_temperature(uint8_t index);
|
||||||
|
|
||||||
|
// if host, set DIOs on extruder controller
|
||||||
|
// if extruder, report DIO state
|
||||||
|
void set_dio(uint8_t index, uint8_t value);
|
||||||
|
|
||||||
|
// if host, read extruder DIO inputs
|
||||||
|
// if extruder, set DIO outputs
|
||||||
|
uint8_t get_dio(uint8_t index);
|
||||||
|
|
||||||
|
// set error code to send to other end
|
||||||
|
void set_err(uint8_t err);
|
||||||
|
|
||||||
|
// get error code sent from other end
|
||||||
|
uint8_t get_err(void);
|
||||||
|
|
||||||
|
// if host, send packet to extruder
|
||||||
|
// if extruder, return packet to host
|
||||||
void start_send(void);
|
void start_send(void);
|
||||||
|
|
||||||
//Read the message we are receiving over intercom
|
#define FLAG_RX_IN_PROGRESS 1
|
||||||
uint8_t get_read_cmd(void);
|
#define FLAG_TX_IN_PROGRESS 2
|
||||||
|
#define FLAG_NEW_RX 4
|
||||||
|
#define FLAG_TX_FINISHED 8
|
||||||
|
extern volatile uint8_t intercom_flags;
|
||||||
|
|
||||||
#endif /* _INTERCOM_H */
|
#endif /* _INTERCOM_H */
|
||||||
|
|
|
||||||
178
extruder/temp.c
178
extruder/temp.c
|
|
@ -4,22 +4,6 @@
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TT_THERMISTOR,
|
|
||||||
TT_MAX6675,
|
|
||||||
TT_AD595,
|
|
||||||
TT_PT100,
|
|
||||||
TT_INTERCOM
|
|
||||||
} temp_types;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PRESENT,
|
|
||||||
TCOPEN
|
|
||||||
} temp_flags_enum;
|
|
||||||
|
|
||||||
#define TEMP_C
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "arduino.h"
|
#include "arduino.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
@ -27,10 +11,38 @@ typedef enum {
|
||||||
#include "sersendf.h"
|
#include "sersendf.h"
|
||||||
#endif
|
#endif
|
||||||
#include "heater.h"
|
#include "heater.h"
|
||||||
#ifdef GEN3
|
#ifdef TEMP_INTERCOM
|
||||||
#include "intercom.h"
|
#include "intercom.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TT_THERMISTOR,
|
||||||
|
TT_MAX6675,
|
||||||
|
TT_AD595,
|
||||||
|
TT_PT100,
|
||||||
|
TT_INTERCOM,
|
||||||
|
TT_DUMMY,
|
||||||
|
} temp_types;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PRESENT,
|
||||||
|
TCOPEN
|
||||||
|
} temp_flags_enum;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t temp_type;
|
||||||
|
uint8_t temp_pin;
|
||||||
|
uint8_t heater_index;
|
||||||
|
} temp_sensor_definition_t;
|
||||||
|
|
||||||
|
#undef DEFINE_TEMP_SENSOR
|
||||||
|
#define DEFINE_TEMP_SENSOR(name, type, pin) { (type), (pin), (HEATER_ ## name) },
|
||||||
|
static const temp_sensor_definition_t temp_sensors[NUM_TEMP_SENSORS] =
|
||||||
|
{
|
||||||
|
#include "config.h"
|
||||||
|
};
|
||||||
|
#undef DEFINE_TEMP_SENSOR
|
||||||
|
|
||||||
// this struct holds the runtime sensor data- read temperatures, targets, etc
|
// this struct holds the runtime sensor data- read temperatures, targets, etc
|
||||||
struct {
|
struct {
|
||||||
temp_flags_enum temp_flags;
|
temp_flags_enum temp_flags;
|
||||||
|
|
@ -48,30 +60,7 @@ struct {
|
||||||
|
|
||||||
#ifdef TEMP_THERMISTOR
|
#ifdef TEMP_THERMISTOR
|
||||||
#include "analog.h"
|
#include "analog.h"
|
||||||
|
#include "ThermistorTable.h"
|
||||||
#define NUMTEMPS 20
|
|
||||||
uint16_t temptable[NUMTEMPS][2] PROGMEM = {
|
|
||||||
{1, 841},
|
|
||||||
{54, 255},
|
|
||||||
{107, 209},
|
|
||||||
{160, 184},
|
|
||||||
{213, 166},
|
|
||||||
{266, 153},
|
|
||||||
{319, 142},
|
|
||||||
{372, 132},
|
|
||||||
{425, 124},
|
|
||||||
{478, 116},
|
|
||||||
{531, 108},
|
|
||||||
{584, 101},
|
|
||||||
{637, 93},
|
|
||||||
{690, 86},
|
|
||||||
{743, 78},
|
|
||||||
{796, 70},
|
|
||||||
{849, 61},
|
|
||||||
{902, 50},
|
|
||||||
{955, 34},
|
|
||||||
{1008, 3}
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TEMP_AD595
|
#ifdef TEMP_AD595
|
||||||
|
|
@ -79,7 +68,7 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void temp_init() {
|
void temp_init() {
|
||||||
uint8_t i;
|
temp_sensor_t i;
|
||||||
for (i = 0; i < NUM_TEMP_SENSORS; i++) {
|
for (i = 0; i < NUM_TEMP_SENSORS; i++) {
|
||||||
switch(temp_sensors[i].temp_type) {
|
switch(temp_sensors[i].temp_type) {
|
||||||
#ifdef TEMP_MAX6675
|
#ifdef TEMP_MAX6675
|
||||||
|
|
@ -100,10 +89,10 @@ void temp_init() {
|
||||||
break;*/
|
break;*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GEN3
|
#ifdef TEMP_INTERCOM
|
||||||
case TT_INTERCOM:
|
case TT_INTERCOM:
|
||||||
intercom_init();
|
intercom_init();
|
||||||
update_send_cmd(0);
|
send_temperature(0, 0);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +100,7 @@ void temp_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void temp_sensor_tick() {
|
void temp_sensor_tick() {
|
||||||
uint8_t i = 0;
|
temp_sensor_t i = 0;
|
||||||
for (; i < NUM_TEMP_SENSORS; i++) {
|
for (; i < NUM_TEMP_SENSORS; i++) {
|
||||||
if (temp_sensors_runtime[i].next_read_time) {
|
if (temp_sensors_runtime[i].next_read_time) {
|
||||||
temp_sensors_runtime[i].next_read_time--;
|
temp_sensors_runtime[i].next_read_time--;
|
||||||
|
|
@ -179,15 +168,50 @@ void temp_sensor_tick() {
|
||||||
//Calculate real temperature based on lookup table
|
//Calculate real temperature based on lookup table
|
||||||
for (j = 1; j < NUMTEMPS; j++) {
|
for (j = 1; j < NUMTEMPS; j++) {
|
||||||
if (pgm_read_word(&(temptable[j][0])) > temp) {
|
if (pgm_read_word(&(temptable[j][0])) > temp) {
|
||||||
// multiply by 4 because internal temp is stored as 14.2 fixed point
|
// Thermistor table is already in 14.2 fixed point
|
||||||
temp = pgm_read_word(&(temptable[j][1])) * 4 + (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])));
|
#ifndef EXTRUDER
|
||||||
|
if (debug_flags & DEBUG_PID)
|
||||||
|
sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
|
||||||
|
#endif
|
||||||
|
// Linear interpolating temperature value
|
||||||
|
// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
|
||||||
|
// y = temp
|
||||||
|
// x = ADC reading
|
||||||
|
// x₀= temptable[j-1][0]
|
||||||
|
// x₁= temptable[j][0]
|
||||||
|
// y₀= temptable[j-1][1]
|
||||||
|
// y₁= temptable[j][1]
|
||||||
|
// y =
|
||||||
|
// Wikipedia's example linear interpolation formula.
|
||||||
|
temp = (
|
||||||
|
// ((x - x₀)y₁
|
||||||
|
((uint32_t)temp - pgm_read_word(&(temptable[j-1][0]))) * pgm_read_word(&(temptable[j][1]))
|
||||||
|
// +
|
||||||
|
+
|
||||||
|
// (x₁-x)
|
||||||
|
(pgm_read_word(&(temptable[j][0])) - (uint32_t)temp)
|
||||||
|
// y₀ )
|
||||||
|
* pgm_read_word(&(temptable[j-1][1])))
|
||||||
|
// /
|
||||||
|
/
|
||||||
|
// (x₁ - x₀)
|
||||||
|
(pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0])));
|
||||||
|
#ifndef EXTRUDER
|
||||||
|
if (debug_flags & DEBUG_PID)
|
||||||
|
sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifndef EXTRUDER
|
||||||
|
if (debug_flags & DEBUG_PID)
|
||||||
|
sersendf_P(PSTR(" Sensor:%d\n"),i);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//Clamp for overflows
|
//Clamp for overflows
|
||||||
if (j == NUMTEMPS)
|
if (j == NUMTEMPS)
|
||||||
temp = temptable[NUMTEMPS-1][1] * 4;
|
temp = temptable[NUMTEMPS-1][1];
|
||||||
|
|
||||||
temp_sensors_runtime[i].next_read_time = 0;
|
temp_sensors_runtime[i].next_read_time = 0;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
@ -196,7 +220,7 @@ void temp_sensor_tick() {
|
||||||
|
|
||||||
#ifdef TEMP_AD595
|
#ifdef TEMP_AD595
|
||||||
case TT_AD595:
|
case TT_AD595:
|
||||||
temp = analog_read(temp_pin);
|
temp = analog_read(temp_sensors[i].temp_pin);
|
||||||
|
|
||||||
// convert
|
// convert
|
||||||
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
|
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
|
||||||
|
|
@ -213,16 +237,30 @@ void temp_sensor_tick() {
|
||||||
break
|
break
|
||||||
#endif /* TEMP_PT100 */
|
#endif /* TEMP_PT100 */
|
||||||
|
|
||||||
#ifdef GEN3
|
#ifdef TEMP_INTERCOM
|
||||||
case TT_INTERCOM:
|
case TT_INTERCOM:
|
||||||
temp = get_read_cmd() << 2;
|
temp = read_temperature(temp_sensors[i].temp_pin);
|
||||||
|
|
||||||
start_send();
|
start_send();
|
||||||
|
|
||||||
temp_sensors_runtime[i].next_read_time = 0;
|
temp_sensors_runtime[i].next_read_time = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* GEN3 */
|
#endif /* TEMP_INTERCOM */
|
||||||
|
|
||||||
|
#ifdef TEMP_DUMMY
|
||||||
|
case TT_DUMMY:
|
||||||
|
temp = temp_sensors_runtime[i].last_read_temp;
|
||||||
|
|
||||||
|
if (temp_sensors_runtime[i].target_temp > temp)
|
||||||
|
temp++;
|
||||||
|
else if (temp_sensors_runtime[i].target_temp < temp)
|
||||||
|
temp--;
|
||||||
|
|
||||||
|
temp_sensors_runtime[i].next_read_time = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif /* TEMP_DUMMY */
|
||||||
}
|
}
|
||||||
temp_sensors_runtime[i].last_read_temp = temp;
|
temp_sensors_runtime[i].last_read_temp = temp;
|
||||||
|
|
||||||
|
|
@ -235,14 +273,16 @@ void temp_sensor_tick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temp_sensors[i].heater_index < NUM_HEATERS) {
|
if (temp_sensors[i].heater_index < NUM_HEATERS) {
|
||||||
heater_tick(temp_sensors[i].heater_index, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
|
heater_tick(temp_sensors[i].heater_index, i, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t temp_achieved() {
|
uint8_t temp_achieved() {
|
||||||
uint8_t i, all_ok = 255;
|
temp_sensor_t i;
|
||||||
|
uint8_t all_ok = 255;
|
||||||
|
|
||||||
for (i = 0; i < NUM_TEMP_SENSORS; i++) {
|
for (i = 0; i < NUM_TEMP_SENSORS; i++) {
|
||||||
if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME)
|
if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME)
|
||||||
all_ok = 0;
|
all_ok = 0;
|
||||||
|
|
@ -250,26 +290,42 @@ uint8_t temp_achieved() {
|
||||||
return all_ok;
|
return all_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void temp_set(uint8_t index, uint16_t temperature) {
|
void temp_set(temp_sensor_t index, uint16_t temperature) {
|
||||||
|
if (index >= NUM_TEMP_SENSORS)
|
||||||
|
return;
|
||||||
|
|
||||||
temp_sensors_runtime[index].target_temp = temperature;
|
temp_sensors_runtime[index].target_temp = temperature;
|
||||||
temp_sensors_runtime[index].temp_residency = 0;
|
temp_sensors_runtime[index].temp_residency = 0;
|
||||||
#ifdef GEN3
|
#ifdef TEMP_INTERCOM
|
||||||
if (temp_sensors[index].temp_type == TT_INTERCOM)
|
if (temp_sensors[index].temp_type == TT_INTERCOM)
|
||||||
update_send_cmd(temperature >> 2);
|
send_temperature(temp_sensors[index].temp_pin, temperature);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t temp_get(uint8_t index) {
|
uint16_t temp_get(temp_sensor_t index) {
|
||||||
|
if (index >= NUM_TEMP_SENSORS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return temp_sensors_runtime[index].last_read_temp;
|
return temp_sensors_runtime[index].last_read_temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extruder doesn't have sersendf_P
|
// extruder doesn't have sersendf_P
|
||||||
#ifndef EXTRUDER
|
#ifndef EXTRUDER
|
||||||
void temp_print(uint8_t index) {
|
void temp_print(temp_sensor_t index) {
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
|
|
||||||
|
if (index >= NUM_TEMP_SENSORS)
|
||||||
|
return;
|
||||||
|
|
||||||
c = (temp_sensors_runtime[index].last_read_temp & 3) * 25;
|
c = (temp_sensors_runtime[index].last_read_temp & 3) * 25;
|
||||||
|
|
||||||
|
sersendf_P(PSTR("T:%u.%u"), temp_sensors_runtime[index].last_read_temp >> 2, c);
|
||||||
|
#ifdef HEATER_BED
|
||||||
|
uint8_t b = 0;
|
||||||
|
b = (temp_sensors_runtime[HEATER_BED].last_read_temp & 3) * 25;
|
||||||
|
|
||||||
sersendf_P(PSTR("T: %u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c);
|
sersendf_P(PSTR(" B:%u.%u"), temp_sensors_runtime[HEATER_bed].last_read_temp >> 2 , b);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef _TEMP_H
|
#ifndef _TEMP_H
|
||||||
#define _TEMP_H
|
#define _TEMP_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -11,6 +12,15 @@ no point in specifying a port- all the different temp sensors we have must be on
|
||||||
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.
|
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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#undef DEFINE_TEMP_SENSOR
|
||||||
|
#define DEFINE_TEMP_SENSOR(name, type, pin) TEMP_SENSOR_ ## name,
|
||||||
|
typedef enum {
|
||||||
|
#include "config.h"
|
||||||
|
NUM_TEMP_SENSORS,
|
||||||
|
TEMP_SENSOR_none
|
||||||
|
} temp_sensor_t;
|
||||||
|
#undef DEFINE_TEMP_SENSOR
|
||||||
|
|
||||||
#define temp_tick temp_sensor_tick
|
#define temp_tick temp_sensor_tick
|
||||||
|
|
||||||
void temp_init(void);
|
void temp_init(void);
|
||||||
|
|
@ -19,11 +29,9 @@ void temp_sensor_tick(void);
|
||||||
|
|
||||||
uint8_t temp_achieved(void);
|
uint8_t temp_achieved(void);
|
||||||
|
|
||||||
void temp_set(uint8_t index, uint16_t temperature);
|
void temp_set(temp_sensor_t index, uint16_t temperature);
|
||||||
uint16_t temp_get(uint8_t index);
|
uint16_t temp_get(temp_sensor_t index);
|
||||||
|
|
||||||
void temp_print(uint8_t index);
|
void temp_print(temp_sensor_t index);
|
||||||
|
|
||||||
uint16_t temp_read(uint8_t index);
|
|
||||||
|
|
||||||
#endif /* _TIMER_H */
|
#endif /* _TIMER_H */
|
||||||
|
|
|
||||||
257
intercom.c
257
intercom.c
|
|
@ -1,47 +1,53 @@
|
||||||
#include "intercom.h"
|
#include "intercom.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
||||||
#ifdef TEMP_INTERCOM
|
#if (defined TEMP_INTERCOM) || (defined EXTRUDER)
|
||||||
#define INTERCOM_BAUD 57600
|
#define INTERCOM_BAUD 57600
|
||||||
|
|
||||||
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0)
|
#define START 0x55
|
||||||
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0)
|
|
||||||
|
|
||||||
/*
|
enum {
|
||||||
Defines a super simple intercom interface using the RS485 modules
|
ERROR_BAD_CRC
|
||||||
|
} err_codes;
|
||||||
|
|
||||||
Host will say: START1 START2 PWM_CMD PWM_CHK
|
typedef struct {
|
||||||
Extruder will reply: START1 START2 TMP_CMD TMP_CHK
|
uint8_t start;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t dio0 :1;
|
||||||
|
uint8_t dio1 :1;
|
||||||
|
uint8_t dio2 :1;
|
||||||
|
uint8_t dio3 :1;
|
||||||
|
uint8_t dio4 :1;
|
||||||
|
uint8_t dio5 :1;
|
||||||
|
uint8_t dio6 :1;
|
||||||
|
uint8_t dio7 :1;
|
||||||
|
};
|
||||||
|
uint8_t dio;
|
||||||
|
};
|
||||||
|
uint8_t controller_num;
|
||||||
|
uint16_t temp[3];
|
||||||
|
uint8_t err;
|
||||||
|
uint8_t crc;
|
||||||
|
} intercom_packet_t;
|
||||||
|
|
||||||
CHK = 255-CMD, if they match do the work, if not, ignore this packet
|
typedef union {
|
||||||
|
intercom_packet_t packet;
|
||||||
|
uint8_t data[sizeof(intercom_packet_t)];
|
||||||
|
} intercom_packet;
|
||||||
|
|
||||||
in a loop
|
intercom_packet tx;
|
||||||
*/
|
intercom_packet rx;
|
||||||
|
|
||||||
|
uint8_t packet_pointer;
|
||||||
|
uint8_t rxcrc;
|
||||||
|
|
||||||
#define START1 0xAA
|
volatile uint8_t intercom_flags;
|
||||||
#define START2 0x55
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SEND_START1,
|
|
||||||
SEND_START2,
|
|
||||||
SEND_CMD,
|
|
||||||
SEND_CHK,
|
|
||||||
SEND_DONE,
|
|
||||||
|
|
||||||
READ_START1,
|
|
||||||
READ_START2,
|
|
||||||
READ_CMD,
|
|
||||||
READ_CHK,
|
|
||||||
} intercom_state_e;
|
|
||||||
|
|
||||||
|
|
||||||
intercom_state_e state = READ_START1;
|
|
||||||
uint8_t cmd, chk, send_cmd, read_cmd;
|
|
||||||
|
|
||||||
void intercom_init(void)
|
void intercom_init(void)
|
||||||
{
|
{
|
||||||
|
|
@ -70,30 +76,60 @@ void intercom_init(void)
|
||||||
|
|
||||||
UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0);
|
UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
intercom_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_send_cmd(uint8_t new_send_cmd) {
|
void send_temperature(uint8_t index, uint16_t temperature) {
|
||||||
send_cmd = new_send_cmd;
|
tx.packet.temp[index] = temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t get_read_cmd(void) {
|
uint16_t read_temperature(uint8_t index) {
|
||||||
return read_cmd;
|
return rx.packet.temp[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_byte(uint8_t val) {
|
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
UDR1 = val;
|
void set_dio(uint8_t index, uint8_t value) {
|
||||||
|
if (value)
|
||||||
|
tx.packet.dio |= (1 << index);
|
||||||
|
else
|
||||||
|
tx.packet.dio &= ~(1 << index);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
UDR0 = val;
|
uint8_t get_dio(uint8_t index) {
|
||||||
|
return rx.packet.dio & (1 << index);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void set_err(uint8_t err) {
|
||||||
|
tx.packet.err = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t get_err() {
|
||||||
|
return rx.packet.err;
|
||||||
|
}
|
||||||
|
|
||||||
void start_send(void) {
|
void start_send(void) {
|
||||||
state = SEND_START1;
|
uint8_t txcrc = 0, i;
|
||||||
|
|
||||||
|
// atomically update flags
|
||||||
|
uint8_t sreg = SREG;
|
||||||
|
cli();
|
||||||
|
intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS;
|
||||||
|
SREG = sreg;
|
||||||
|
|
||||||
|
// calculate CRC for outgoing packet
|
||||||
|
for (i = 0; i < (sizeof(intercom_packet_t) - 1); i++) {
|
||||||
|
txcrc ^= tx.data[i];
|
||||||
|
}
|
||||||
|
tx.packet.crc = txcrc;
|
||||||
|
|
||||||
|
// enable transmit pin
|
||||||
enable_transmit();
|
enable_transmit();
|
||||||
delay_us(15);
|
delay_us(15);
|
||||||
//Enable interrupts so we can send next characters
|
|
||||||
|
// actually start sending the packet
|
||||||
|
packet_pointer = 0;
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
UCSR1B |= MASK(UDRIE1);
|
UCSR1B |= MASK(UDRIE1);
|
||||||
#else
|
#else
|
||||||
|
|
@ -101,118 +137,99 @@ void start_send(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finish_send(void) {
|
|
||||||
state = READ_START1;
|
|
||||||
disable_transmit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Interrupts, UART 0 for mendel
|
Interrupts, UART 0 for mendel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// receive data interrupt- stuff into rx
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
ISR(USART1_RX_vect)
|
ISR(USART1_RX_vect)
|
||||||
#else
|
#else
|
||||||
ISR(USART_RX_vect)
|
ISR(USART_RX_vect)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
// pull character
|
||||||
static uint8_t c;
|
static uint8_t c;
|
||||||
|
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
c = UDR1;
|
c = UDR1;
|
||||||
UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1);
|
UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1);
|
||||||
#else
|
#else
|
||||||
c = UDR0;
|
c = UDR0;
|
||||||
UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0);
|
UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (state >= READ_START1) {
|
// are we waiting for a start byte? is this one?
|
||||||
|
if ((packet_pointer == 0) && (c == START)) {
|
||||||
switch(state) {
|
rxcrc = rx.packet.start = START;
|
||||||
case READ_START1:
|
packet_pointer = 1;
|
||||||
if (c == START1) state = READ_START2;
|
intercom_flags |= FLAG_RX_IN_PROGRESS;
|
||||||
break;
|
|
||||||
case READ_START2:
|
|
||||||
if (c == START2) state = READ_CMD;
|
|
||||||
else state = READ_START1;
|
|
||||||
break;
|
|
||||||
case READ_CMD:
|
|
||||||
cmd = c;
|
|
||||||
state = READ_CHK;
|
|
||||||
break;
|
|
||||||
case READ_CHK:
|
|
||||||
chk = c;
|
|
||||||
|
|
||||||
if (chk == 255 - cmd) {
|
|
||||||
//Values are correct, do something useful
|
|
||||||
WRITE(DEBUG_LED,1);
|
|
||||||
read_cmd = cmd;
|
|
||||||
#ifdef EXTRUDER
|
|
||||||
start_send();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = READ_START1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we're receiving a packet
|
||||||
|
if (packet_pointer > 0) {
|
||||||
|
// calculate CRC (except CRC character!)
|
||||||
|
if (packet_pointer < (sizeof(intercom_packet_t) - 1))
|
||||||
|
rxcrc ^= c;
|
||||||
|
// stuff byte into structure
|
||||||
|
rx.data[packet_pointer++] = c;
|
||||||
|
// last byte?
|
||||||
|
if (packet_pointer >= sizeof(intercom_packet_t)) {
|
||||||
|
// reset pointer
|
||||||
|
packet_pointer = 0;
|
||||||
|
|
||||||
|
intercom_flags = (intercom_flags & ~FLAG_RX_IN_PROGRESS) | FLAG_NEW_RX;
|
||||||
|
#ifndef HOST
|
||||||
|
if (rx.packet.controller_num == THIS_CONTROLLER_NUM) {
|
||||||
|
if (rxcrc != rx.packet.crc)
|
||||||
|
tx.packet.err = ERROR_BAD_CRC;
|
||||||
|
start_send();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finished transmitting interrupt- only enabled at end of packet
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
ISR(USART1_TX_vect)
|
ISR(USART1_TX_vect)
|
||||||
#else
|
#else
|
||||||
ISR(USART_TX_vect)
|
ISR(USART_TX_vect)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (state == SEND_DONE) {
|
if (packet_pointer >= sizeof(intercom_packet_t)) {
|
||||||
finish_send();
|
disable_transmit();
|
||||||
|
packet_pointer = 0;
|
||||||
|
intercom_flags = (intercom_flags & ~FLAG_TX_IN_PROGRESS) | FLAG_TX_FINISHED;
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
UCSR1B &= ~MASK(TXCIE1);
|
UCSR1B &= ~MASK(TXCIE1);
|
||||||
#else
|
#else
|
||||||
UCSR0B &= ~MASK(TXCIE0);
|
UCSR0B &= ~MASK(TXCIE0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tx queue empty interrupt- send next byte
|
||||||
#ifdef HOST
|
#ifdef HOST
|
||||||
ISR(USART1_UDRE_vect)
|
ISR(USART1_UDRE_vect)
|
||||||
#else
|
#else
|
||||||
ISR(USART_UDRE_vect)
|
ISR(USART_UDRE_vect)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
switch(state) {
|
#ifdef HOST
|
||||||
case SEND_START1:
|
UDR1 = tx.data[packet_pointer++];
|
||||||
write_byte(START1);
|
#else
|
||||||
state = SEND_START2;
|
UDR0 = tx.data[packet_pointer++];
|
||||||
break;
|
#endif
|
||||||
case SEND_START2:
|
|
||||||
write_byte(START2);
|
if (packet_pointer >= sizeof(intercom_packet_t)) {
|
||||||
state = SEND_CMD;
|
#ifdef HOST
|
||||||
break;
|
UCSR1B &= ~MASK(UDRIE1);
|
||||||
case SEND_CMD:
|
UCSR1B |= MASK(TXCIE1);
|
||||||
write_byte(send_cmd);
|
#else
|
||||||
state = SEND_CHK;
|
UCSR0B &= ~MASK(UDRIE0);
|
||||||
break;
|
UCSR0B |= MASK(TXCIE0);
|
||||||
case SEND_CHK:
|
#endif
|
||||||
write_byte(255 - send_cmd);
|
|
||||||
state = SEND_DONE;
|
|
||||||
#ifdef HOST
|
|
||||||
UCSR1B &= ~MASK(UDRIE1);
|
|
||||||
UCSR1B |= MASK(TXCIE1);
|
|
||||||
#else
|
|
||||||
UCSR0B &= ~MASK(UDRIE0);
|
|
||||||
UCSR0B |= MASK(TXCIE0);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
35
intercom.h
35
intercom.h
|
|
@ -3,15 +3,42 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0)
|
||||||
|
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0)
|
||||||
|
|
||||||
// initialise serial subsystem
|
// initialise serial subsystem
|
||||||
void intercom_init(void);
|
void intercom_init(void);
|
||||||
|
|
||||||
//Update the message we are sending over intercom
|
// if host, send target temperature to extruder
|
||||||
void update_send_cmd(uint8_t new_send_cmd);
|
// if extruder, send actual temperature to host
|
||||||
|
void send_temperature(uint8_t index, uint16_t temperature);
|
||||||
|
|
||||||
|
// if host, read actual temperature from extruder
|
||||||
|
// if extruder, read target temperature from host
|
||||||
|
uint16_t read_temperature(uint8_t index);
|
||||||
|
|
||||||
|
// if host, set DIOs on extruder controller
|
||||||
|
// if extruder, report DIO state
|
||||||
|
void set_dio(uint8_t index, uint8_t value);
|
||||||
|
|
||||||
|
// if host, read extruder DIO inputs
|
||||||
|
// if extruder, set DIO outputs
|
||||||
|
uint8_t get_dio(uint8_t index);
|
||||||
|
|
||||||
|
// set error code to send to other end
|
||||||
|
void set_err(uint8_t err);
|
||||||
|
|
||||||
|
// get error code sent from other end
|
||||||
|
uint8_t get_err(void);
|
||||||
|
|
||||||
|
// if host, send packet to extruder
|
||||||
|
// if extruder, return packet to host
|
||||||
void start_send(void);
|
void start_send(void);
|
||||||
|
|
||||||
//Read the message we are receiving over intercom
|
#define FLAG_RX_IN_PROGRESS 1
|
||||||
uint8_t get_read_cmd(void);
|
#define FLAG_TX_IN_PROGRESS 2
|
||||||
|
#define FLAG_NEW_RX 4
|
||||||
|
#define FLAG_TX_FINISHED 8
|
||||||
|
extern volatile uint8_t intercom_flags;
|
||||||
|
|
||||||
#endif /* _INTERCOM_H */
|
#endif /* _INTERCOM_H */
|
||||||
|
|
|
||||||
14
temp.c
14
temp.c
|
|
@ -92,7 +92,7 @@ void temp_init() {
|
||||||
#ifdef TEMP_INTERCOM
|
#ifdef TEMP_INTERCOM
|
||||||
case TT_INTERCOM:
|
case TT_INTERCOM:
|
||||||
intercom_init();
|
intercom_init();
|
||||||
update_send_cmd(0);
|
send_temperature(0, 0);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -169,8 +169,10 @@ void temp_sensor_tick() {
|
||||||
for (j = 1; j < NUMTEMPS; j++) {
|
for (j = 1; j < NUMTEMPS; j++) {
|
||||||
if (pgm_read_word(&(temptable[j][0])) > temp) {
|
if (pgm_read_word(&(temptable[j][0])) > temp) {
|
||||||
// Thermistor table is already in 14.2 fixed point
|
// Thermistor table is already in 14.2 fixed point
|
||||||
|
#ifndef EXTRUDER
|
||||||
if (debug_flags & DEBUG_PID)
|
if (debug_flags & DEBUG_PID)
|
||||||
sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
|
sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
|
||||||
|
#endif
|
||||||
// Linear interpolating temperature value
|
// Linear interpolating temperature value
|
||||||
// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
|
// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
|
||||||
// y = temp
|
// y = temp
|
||||||
|
|
@ -194,13 +196,17 @@ void temp_sensor_tick() {
|
||||||
/
|
/
|
||||||
// (x₁ - x₀)
|
// (x₁ - x₀)
|
||||||
(pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0])));
|
(pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0])));
|
||||||
|
#ifndef EXTRUDER
|
||||||
if (debug_flags & DEBUG_PID)
|
if (debug_flags & DEBUG_PID)
|
||||||
sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
|
sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifndef EXTRUDER
|
||||||
if (debug_flags & DEBUG_PID)
|
if (debug_flags & DEBUG_PID)
|
||||||
sersendf_P(PSTR(" Sensor:%d\n"),i);
|
sersendf_P(PSTR(" Sensor:%d\n"),i);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//Clamp for overflows
|
//Clamp for overflows
|
||||||
|
|
@ -214,7 +220,7 @@ void temp_sensor_tick() {
|
||||||
|
|
||||||
#ifdef TEMP_AD595
|
#ifdef TEMP_AD595
|
||||||
case TT_AD595:
|
case TT_AD595:
|
||||||
temp = analog_read(temp_pin);
|
temp = analog_read(temp_sensors[i].temp_pin);
|
||||||
|
|
||||||
// convert
|
// convert
|
||||||
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
|
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
|
||||||
|
|
@ -233,7 +239,7 @@ void temp_sensor_tick() {
|
||||||
|
|
||||||
#ifdef TEMP_INTERCOM
|
#ifdef TEMP_INTERCOM
|
||||||
case TT_INTERCOM:
|
case TT_INTERCOM:
|
||||||
temp = get_read_cmd() << 2;
|
temp = read_temperature(temp_sensors[i].temp_pin);
|
||||||
|
|
||||||
start_send();
|
start_send();
|
||||||
|
|
||||||
|
|
@ -292,7 +298,7 @@ void temp_set(temp_sensor_t index, uint16_t temperature) {
|
||||||
temp_sensors_runtime[index].temp_residency = 0;
|
temp_sensors_runtime[index].temp_residency = 0;
|
||||||
#ifdef TEMP_INTERCOM
|
#ifdef TEMP_INTERCOM
|
||||||
if (temp_sensors[index].temp_type == TT_INTERCOM)
|
if (temp_sensors[index].temp_type == TT_INTERCOM)
|
||||||
update_send_cmd(temperature >> 2);
|
send_temperature(temp_sensors[index].temp_pin, temperature);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue