From b1a48994ddca970d6cd03c0ccb93696bef905daf Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 12 Feb 2011 23:59:19 +1100 Subject: [PATCH 01/19] preliminary untested implementation of Markus Amsler's new extruder comms protocol --- extruder/analog.c | 6 +- extruder/config.h.dist | 90 ++------------ extruder/debug.h | 16 +-- extruder/extruder.c | 4 +- extruder/heater.c | 227 +++++++++++++++++++++++------------- extruder/heater.h | 26 ++++- extruder/intercom.c | 259 ++++++++++++++++++++++------------------- extruder/intercom.h | 35 +++++- extruder/temp.c | 178 ++++++++++++++++++---------- extruder/temp.h | 18 ++- intercom.c | 257 +++++++++++++++++++++------------------- intercom.h | 35 +++++- temp.c | 14 ++- 13 files changed, 659 insertions(+), 506 deletions(-) diff --git a/extruder/analog.c b/extruder/analog.c index e4aebbb..d3e36de 100644 --- a/extruder/analog.c +++ b/extruder/analog.c @@ -54,8 +54,8 @@ void analog_init() { adc_counter = 0; adc_running_mask = 1; - AIO0_DDR &= ANALOG_MASK; - DIDR0 = ANALOG_MASK & 0x3F; + AIO0_DDR &= ~(ANALOG_MASK); + DIDR0 = (ANALOG_MASK) & 0x3F; // now we start the first conversion and leave the rest to the interrupt ADCSRA |= MASK(ADIE) | MASK(ADSC); @@ -73,7 +73,7 @@ ISR(ADC_vect, ISR_NOBLOCK) { adc_counter = ANALOG_START; adc_running_mask = ANALOG_START_MASK; } - } while ((adc_running_mask & ANALOG_MASK) == 0); + } while ((adc_running_mask & (ANALOG_MASK)) == 0); // start next conversion ADMUX = (adc_counter) | REFERENCE; diff --git a/extruder/config.h.dist b/extruder/config.h.dist index cd6d41a..e4345b4 100644 --- a/extruder/config.h.dist +++ b/extruder/config.h.dist @@ -3,6 +3,9 @@ #include "arduino.h" +// controller index- bus is multidrop after all +#define THIS_CONTROLLER_NUM 0 + //RS485 Interface pins #define RX_ENABLE_PIN DIO4 #define TX_ENABLE_PIN AIO2 @@ -40,33 +43,13 @@ #define TEMP_HYSTERESIS 20 #define TEMP_RESIDENCY_TIME 60 -#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. * -* * -* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * -* 255 * -* * -\***************************************************************************/ +#ifdef DEFINE_TEMP_SENSOR +DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, PINC3) +#endif -struct { - uint8_t temp_type; - uint8_t temp_pin; - - uint8_t heater_index; -} temp_sensors[NUM_TEMP_SENSORS] = -{ - { - TT_THERMISTOR, - PINC3, - 0 - } -}; +#ifdef DEFINE_HEATER +DEFINE_HEATER(extruder, PORTD, DIO6_PIN, OCR0A) +DEFINE_HEATER(bed, PORTD, DIO5_PIN, OCR0B) #endif // list of PWM-able pins and corresponding timers @@ -81,49 +64,6 @@ struct { #define TH_COUNT 8 #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 @@ -132,16 +72,4 @@ struct { #define enable_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 */ diff --git a/extruder/debug.h b/extruder/debug.h index e96e268..08f0321 100644 --- a/extruder/debug.h +++ b/extruder/debug.h @@ -3,18 +3,12 @@ #include -#ifdef DEBUG - #define DEBUG_PID 1 - #define DEBUG_DDA 2 - #define DEBUG_POSITION 4 -#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 +// 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 -#define DEBUG_ECHO 128 +#define DEBUG_ECHO 0 extern volatile uint8_t debug_flags; diff --git a/extruder/extruder.c b/extruder/extruder.c index cc4bbb0..e67c539 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -187,7 +187,7 @@ int main (void) temp_sensor_tick(); - update_send_cmd(temp_get(0) >> 2); - temp_set(0, get_read_cmd()); + send_temperature(0, temp_get(0)); + temp_set(0, read_temperature(0)); } } diff --git a/extruder/heater.c b/extruder/heater.c index 7d0d759..8779dc1 100644 --- a/extruder/heater.c +++ b/extruder/heater.c @@ -9,9 +9,21 @@ #ifndef EXTRUDER #include "sersendf.h" #endif +#include "temp.h" -#define HEATER_C -#include "config.h" +typedef struct { + 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 struct { @@ -32,6 +44,8 @@ struct { uint16_t sanity_counter; uint16_t sane_temperature; #endif + + uint8_t heater_output; } heaters_runtime[NUM_HEATERS]; #define DEFAULT_P 8192 @@ -50,8 +64,7 @@ typedef struct { EE_factor EEMEM EE_factors[NUM_HEATERS]; void heater_init() { - #if NUM_HEATERS > 0 - uint8_t i; + heater_t i; // setup pins for (i = 0; i < NUM_HEATERS; i++) { *(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 heaters_runtime[i].sane_temperature = 0; #endif - - // read factors from eeprom - 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 ((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; - heaters_pid[i].i_factor = DEFAULT_I; - heaters_pid[i].d_factor = DEFAULT_D; - heaters_pid[i].i_limit = DEFAULT_I_LIMIT; - } + + #ifndef BANG_BANG + // read factors from eeprom + 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 ((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; + heaters_pid[i].i_factor = DEFAULT_I; + heaters_pid[i].d_factor = DEFAULT_D; + heaters_pid[i].i_limit = DEFAULT_I_LIMIT; + } + #endif /* BANG_BANG */ } - #endif } void heater_save_settings() { - uint8_t i; - for (i = 0; i < NUM_HEATERS; i++) { - 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_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); - } + #ifndef BANG_BANG + heater_t i; + for (i = 0; i < NUM_HEATERS; i++) { + 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_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); + } + #endif /* BANG_BANG */ } -void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { - #if NUM_HEATERS > 0 - int16_t heater_p; - int16_t heater_d; +void heater_tick(heater_t h, temp_sensor_t t, uint16_t current_temp, uint16_t target_temp) { 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 - 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); + #ifndef BANG_BANG + int16_t heater_p; + 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 - + #ifdef HEATER_SANITY_CHECK // check heater sanity // 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) { // no change, or change in wrong direction for a long time- heater is broken! 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 */ heater_set(h, pid_output); - #endif /* if NUM_HEATERS > 0 */ } -void heater_set(uint8_t index, uint8_t value) { - #if NUM_HEATERS > 0 +void heater_set(heater_t index, uint8_t value) { + if (index >= NUM_HEATERS) + return; + + heaters_runtime[index].heater_output = value; + if (heaters[index].heater_pwm) { *(heaters[index].heater_pwm) = value; #ifdef DEBUG @@ -231,21 +261,50 @@ void heater_set(uint8_t index, uint8_t value) { else *(heaters[index].heater_port) &= ~MASK(heaters[index].heater_pin); } - #endif /* if NUM_HEATERS > 0 */ } -void pid_set_p(uint8_t index, int32_t p) { - heaters_pid[index].p_factor = p; +uint8_t heaters_all_off() { + 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) { - heaters_pid[index].i_factor = i; +void pid_set_p(heater_t index, int32_t p) { + #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) { - heaters_pid[index].d_factor = d; +void pid_set_i(heater_t index, int32_t i) { + #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) { - heaters_pid[index].i_limit = i_limit; +void pid_set_d(heater_t index, int32_t d) { + #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 */ } diff --git a/extruder/heater.h b/extruder/heater.h index fdc9dc9..edd3d23 100644 --- a/extruder/heater.h +++ b/extruder/heater.h @@ -1,20 +1,34 @@ #ifndef _HEATER_H #define _HEATER_H +#include "config.h" #include +#include "temp.h" #define enable_heater() heater_set(0, 64) #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_save_settings(void); -void heater_set(uint8_t index, uint8_t value); -void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp); +void heater_set(heater_t index, uint8_t value); +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); -void pid_set_i(uint8_t index, int32_t i); -void pid_set_d(uint8_t index, int32_t d); -void pid_set_i_limit(uint8_t index, int32_t i_limit); +uint8_t heaters_all_off(void); + +void pid_set_p(heater_t index, int32_t p); +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 */ diff --git a/extruder/intercom.c b/extruder/intercom.c index 7cab163..8da6e62 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -1,47 +1,53 @@ #include "intercom.h" +#include #include #include "config.h" #include "delay.h" -#ifdef GEN3 +#if (defined TEMP_INTERCOM) || (defined EXTRUDER) #define INTERCOM_BAUD 57600 -#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) +#define START 0x55 -/* - Defines a super simple intercom interface using the RS485 modules +enum { + ERROR_BAD_CRC +} err_codes; - Host will say: START1 START2 PWM_CMD PWM_CHK - Extruder will reply: START1 START2 TMP_CMD TMP_CHK +typedef struct { + 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 -#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; +volatile uint8_t intercom_flags; void intercom_init(void) { @@ -70,30 +76,60 @@ void intercom_init(void) UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0); #endif + + intercom_flags = 0; } -void update_send_cmd(uint8_t new_send_cmd) { - send_cmd = new_send_cmd; +void send_temperature(uint8_t index, uint16_t temperature) { + tx.packet.temp[index] = temperature; } -uint8_t get_read_cmd(void) { - return read_cmd; +uint16_t read_temperature(uint8_t index) { + return rx.packet.temp[index]; } -static void write_byte(uint8_t val) { #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 - UDR0 = val; +uint8_t get_dio(uint8_t index) { + return rx.packet.dio & (1 << index); +} #endif + +void set_err(uint8_t err) { + tx.packet.err = err; } +uint8_t get_err() { + return rx.packet.err; +} 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(); delay_us(15); - //Enable interrupts so we can send next characters + + // actually start sending the packet + packet_pointer = 0; #ifdef HOST UCSR1B |= MASK(UDRIE1); #else @@ -101,119 +137,100 @@ void start_send(void) { #endif } -static void finish_send(void) { - state = READ_START1; - disable_transmit(); -} - - /* Interrupts, UART 0 for mendel */ + +// receive data interrupt- stuff into rx #ifdef HOST ISR(USART1_RX_vect) #else ISR(USART_RX_vect) #endif { + // pull character static uint8_t c; -#ifdef HOST - c = UDR1; - UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1); -#else - c = UDR0; - UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0); -#endif - - if (state >= READ_START1) { - - switch(state) { - case READ_START1: - if (c == START1) state = READ_START2; - 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; - } + #ifdef HOST + c = UDR1; + UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1); + #else + c = UDR0; + UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0); + #endif + + // are we waiting for a start byte? is this one? + if ((packet_pointer == 0) && (c == START)) { + rxcrc = rx.packet.start = START; + packet_pointer = 1; + intercom_flags |= FLAG_RX_IN_PROGRESS; } + // 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 ISR(USART1_TX_vect) #else ISR(USART_TX_vect) #endif { - if (state == SEND_DONE) { - finish_send(); - - -#ifdef HOST - UCSR1B &= ~MASK(TXCIE1); -#else - UCSR0B &= ~MASK(TXCIE0); -#endif + if (packet_pointer >= sizeof(intercom_packet_t)) { + disable_transmit(); + packet_pointer = 0; + intercom_flags = (intercom_flags & ~FLAG_TX_IN_PROGRESS) | FLAG_TX_FINISHED; + #ifdef HOST + UCSR1B &= ~MASK(TXCIE1); + #else + UCSR0B &= ~MASK(TXCIE0); + #endif } } +// tx queue empty interrupt- send next byte #ifdef HOST ISR(USART1_UDRE_vect) #else ISR(USART_UDRE_vect) #endif { - switch(state) { - case SEND_START1: - write_byte(START1); - state = SEND_START2; - break; - case SEND_START2: - write_byte(START2); - state = SEND_CMD; - break; - case SEND_CMD: - write_byte(send_cmd); - state = SEND_CHK; - break; - case SEND_CHK: - 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; + #ifdef HOST + UDR1 = tx.data[packet_pointer++]; + #else + UDR0 = tx.data[packet_pointer++]; + #endif + + if (packet_pointer >= sizeof(intercom_packet_t)) { + #ifdef HOST + UCSR1B &= ~MASK(UDRIE1); + UCSR1B |= MASK(TXCIE1); + #else + UCSR0B &= ~MASK(UDRIE0); + UCSR0B |= MASK(TXCIE0); + #endif } } -#endif /* GEN3 */ +#endif /* TEMP_INTERCOM */ diff --git a/extruder/intercom.h b/extruder/intercom.h index 5a6ab8e..f8bc666 100644 --- a/extruder/intercom.h +++ b/extruder/intercom.h @@ -3,15 +3,42 @@ #include +#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 void intercom_init(void); -//Update the message we are sending over intercom -void update_send_cmd(uint8_t new_send_cmd); +// if host, send target temperature to extruder +// 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); -//Read the message we are receiving over intercom -uint8_t get_read_cmd(void); +#define FLAG_RX_IN_PROGRESS 1 +#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 */ diff --git a/extruder/temp.c b/extruder/temp.c index 4809218..e1d13a5 100644 --- a/extruder/temp.c +++ b/extruder/temp.c @@ -4,22 +4,6 @@ #include #include -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 "delay.h" #include "debug.h" @@ -27,10 +11,38 @@ typedef enum { #include "sersendf.h" #endif #include "heater.h" -#ifdef GEN3 +#ifdef TEMP_INTERCOM #include "intercom.h" #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 struct { temp_flags_enum temp_flags; @@ -48,30 +60,7 @@ struct { #ifdef TEMP_THERMISTOR #include "analog.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} -}; +#include "ThermistorTable.h" #endif #ifdef TEMP_AD595 @@ -79,7 +68,7 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = { #endif void temp_init() { - uint8_t i; + temp_sensor_t i; for (i = 0; i < NUM_TEMP_SENSORS; i++) { switch(temp_sensors[i].temp_type) { #ifdef TEMP_MAX6675 @@ -100,10 +89,10 @@ void temp_init() { break;*/ #endif - #ifdef GEN3 + #ifdef TEMP_INTERCOM case TT_INTERCOM: intercom_init(); - update_send_cmd(0); + send_temperature(0, 0); break; #endif } @@ -111,7 +100,7 @@ void temp_init() { } void temp_sensor_tick() { - uint8_t i = 0; + temp_sensor_t i = 0; for (; i < NUM_TEMP_SENSORS; i++) { if (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 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])) * 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]))); + // Thermistor table is already in 14.2 fixed point + #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; } } + #ifndef EXTRUDER + if (debug_flags & DEBUG_PID) + sersendf_P(PSTR(" Sensor:%d\n"),i); + #endif + //Clamp for overflows if (j == NUMTEMPS) - temp = temptable[NUMTEMPS-1][1] * 4; + temp = temptable[NUMTEMPS-1][1]; temp_sensors_runtime[i].next_read_time = 0; } while (0); @@ -196,7 +220,7 @@ void temp_sensor_tick() { #ifdef TEMP_AD595 case TT_AD595: - temp = analog_read(temp_pin); + temp = analog_read(temp_sensors[i].temp_pin); // convert // >>8 instead of >>10 because internal temp is stored as 14.2 fixed point @@ -213,16 +237,30 @@ void temp_sensor_tick() { break #endif /* TEMP_PT100 */ - #ifdef GEN3 + #ifdef TEMP_INTERCOM case TT_INTERCOM: - temp = get_read_cmd() << 2; + temp = read_temperature(temp_sensors[i].temp_pin); start_send(); temp_sensors_runtime[i].next_read_time = 0; 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; @@ -235,14 +273,16 @@ void temp_sensor_tick() { } 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 i, all_ok = 255; + temp_sensor_t i; + uint8_t all_ok = 255; + for (i = 0; i < NUM_TEMP_SENSORS; i++) { if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME) all_ok = 0; @@ -250,26 +290,42 @@ uint8_t temp_achieved() { 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].temp_residency = 0; -#ifdef GEN3 +#ifdef TEMP_INTERCOM if (temp_sensors[index].temp_type == TT_INTERCOM) - update_send_cmd(temperature >> 2); + send_temperature(temp_sensors[index].temp_pin, temperature); #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; } // extruder doesn't have sersendf_P #ifndef EXTRUDER -void temp_print(uint8_t index) { +void temp_print(temp_sensor_t index) { uint8_t c = 0; - + + if (index >= NUM_TEMP_SENSORS) + return; + 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 diff --git a/extruder/temp.h b/extruder/temp.h index b00ee95..1815c4c 100644 --- a/extruder/temp.h +++ b/extruder/temp.h @@ -1,6 +1,7 @@ #ifndef _TEMP_H #define _TEMP_H +#include "config.h" #include /* @@ -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. */ +#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 void temp_init(void); @@ -19,11 +29,9 @@ void temp_sensor_tick(void); uint8_t temp_achieved(void); -void temp_set(uint8_t index, uint16_t temperature); -uint16_t temp_get(uint8_t index); +void temp_set(temp_sensor_t index, uint16_t temperature); +uint16_t temp_get(temp_sensor_t index); -void temp_print(uint8_t index); - -uint16_t temp_read(uint8_t index); +void temp_print(temp_sensor_t index); #endif /* _TIMER_H */ diff --git a/intercom.c b/intercom.c index c523d6e..8da6e62 100644 --- a/intercom.c +++ b/intercom.c @@ -1,47 +1,53 @@ #include "intercom.h" +#include #include #include "config.h" #include "delay.h" -#ifdef TEMP_INTERCOM +#if (defined TEMP_INTERCOM) || (defined EXTRUDER) #define INTERCOM_BAUD 57600 -#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) +#define START 0x55 -/* - Defines a super simple intercom interface using the RS485 modules +enum { + ERROR_BAD_CRC +} err_codes; - Host will say: START1 START2 PWM_CMD PWM_CHK - Extruder will reply: START1 START2 TMP_CMD TMP_CHK +typedef struct { + 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 -#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; +volatile uint8_t intercom_flags; void intercom_init(void) { @@ -70,30 +76,60 @@ void intercom_init(void) UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0); #endif + + intercom_flags = 0; } -void update_send_cmd(uint8_t new_send_cmd) { - send_cmd = new_send_cmd; +void send_temperature(uint8_t index, uint16_t temperature) { + tx.packet.temp[index] = temperature; } -uint8_t get_read_cmd(void) { - return read_cmd; +uint16_t read_temperature(uint8_t index) { + return rx.packet.temp[index]; } -static void write_byte(uint8_t val) { #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 - UDR0 = val; +uint8_t get_dio(uint8_t index) { + return rx.packet.dio & (1 << index); +} #endif + +void set_err(uint8_t err) { + tx.packet.err = err; } +uint8_t get_err() { + return rx.packet.err; +} 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(); delay_us(15); - //Enable interrupts so we can send next characters + + // actually start sending the packet + packet_pointer = 0; #ifdef HOST UCSR1B |= MASK(UDRIE1); #else @@ -101,118 +137,99 @@ void start_send(void) { #endif } -static void finish_send(void) { - state = READ_START1; - disable_transmit(); -} - - /* Interrupts, UART 0 for mendel */ + +// receive data interrupt- stuff into rx #ifdef HOST ISR(USART1_RX_vect) #else ISR(USART_RX_vect) #endif { + // pull character static uint8_t c; -#ifdef HOST - c = UDR1; - UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1); -#else - c = UDR0; - UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0); -#endif - - if (state >= READ_START1) { - - switch(state) { - case READ_START1: - if (c == START1) state = READ_START2; - 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; - } + #ifdef HOST + c = UDR1; + UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1); + #else + c = UDR0; + UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0); + #endif + + // are we waiting for a start byte? is this one? + if ((packet_pointer == 0) && (c == START)) { + rxcrc = rx.packet.start = START; + packet_pointer = 1; + intercom_flags |= FLAG_RX_IN_PROGRESS; } + // 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 ISR(USART1_TX_vect) #else ISR(USART_TX_vect) #endif { - if (state == SEND_DONE) { - finish_send(); - - -#ifdef HOST - UCSR1B &= ~MASK(TXCIE1); -#else - UCSR0B &= ~MASK(TXCIE0); -#endif + if (packet_pointer >= sizeof(intercom_packet_t)) { + disable_transmit(); + packet_pointer = 0; + intercom_flags = (intercom_flags & ~FLAG_TX_IN_PROGRESS) | FLAG_TX_FINISHED; + #ifdef HOST + UCSR1B &= ~MASK(TXCIE1); + #else + UCSR0B &= ~MASK(TXCIE0); + #endif } } +// tx queue empty interrupt- send next byte #ifdef HOST ISR(USART1_UDRE_vect) #else ISR(USART_UDRE_vect) #endif { - switch(state) { - case SEND_START1: - write_byte(START1); - state = SEND_START2; - break; - case SEND_START2: - write_byte(START2); - state = SEND_CMD; - break; - case SEND_CMD: - write_byte(send_cmd); - state = SEND_CHK; - break; - case SEND_CHK: - 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; + #ifdef HOST + UDR1 = tx.data[packet_pointer++]; + #else + UDR0 = tx.data[packet_pointer++]; + #endif + + if (packet_pointer >= sizeof(intercom_packet_t)) { + #ifdef HOST + UCSR1B &= ~MASK(UDRIE1); + UCSR1B |= MASK(TXCIE1); + #else + UCSR0B &= ~MASK(UDRIE0); + UCSR0B |= MASK(TXCIE0); + #endif } } diff --git a/intercom.h b/intercom.h index 5a6ab8e..f8bc666 100644 --- a/intercom.h +++ b/intercom.h @@ -3,15 +3,42 @@ #include +#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 void intercom_init(void); -//Update the message we are sending over intercom -void update_send_cmd(uint8_t new_send_cmd); +// if host, send target temperature to extruder +// 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); -//Read the message we are receiving over intercom -uint8_t get_read_cmd(void); +#define FLAG_RX_IN_PROGRESS 1 +#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 */ diff --git a/temp.c b/temp.c index f5423b2..e1d13a5 100644 --- a/temp.c +++ b/temp.c @@ -92,7 +92,7 @@ void temp_init() { #ifdef TEMP_INTERCOM case TT_INTERCOM: intercom_init(); - update_send_cmd(0); + send_temperature(0, 0); break; #endif } @@ -169,8 +169,10 @@ void temp_sensor_tick() { for (j = 1; j < NUMTEMPS; j++) { if (pgm_read_word(&(temptable[j][0])) > temp) { // Thermistor table is already in 14.2 fixed point + #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 @@ -194,13 +196,17 @@ void temp_sensor_tick() { / // (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; } } + #ifndef EXTRUDER if (debug_flags & DEBUG_PID) sersendf_P(PSTR(" Sensor:%d\n"),i); + #endif //Clamp for overflows @@ -214,7 +220,7 @@ void temp_sensor_tick() { #ifdef TEMP_AD595 case TT_AD595: - temp = analog_read(temp_pin); + temp = analog_read(temp_sensors[i].temp_pin); // convert // >>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 case TT_INTERCOM: - temp = get_read_cmd() << 2; + temp = read_temperature(temp_sensors[i].temp_pin); start_send(); @@ -292,7 +298,7 @@ void temp_set(temp_sensor_t index, uint16_t temperature) { temp_sensors_runtime[index].temp_residency = 0; #ifdef TEMP_INTERCOM if (temp_sensors[index].temp_type == TT_INTERCOM) - update_send_cmd(temperature >> 2); + send_temperature(temp_sensors[index].temp_pin, temperature); #endif } From b7f84a1812886c1aeaae4b5aaf89358ba2091da3 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Sun, 13 Feb 2011 21:22:29 +0100 Subject: [PATCH 02/19] itercom: Enable the RS485 transceiver on the host. --- mendel.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mendel.c b/mendel.c index 8a16100..2068273 100644 --- a/mendel.c +++ b/mendel.c @@ -20,6 +20,7 @@ #include "pinio.h" #include "arduino.h" #include "clock.h" +#include "intercom.h" void io_init(void) { // disable modules we don't use @@ -120,6 +121,13 @@ void io_init(void) { WRITE(MOSI, 1); SET_OUTPUT(MOSI); WRITE(MISO, 1); SET_INPUT(MISO); WRITE(SS, 1); SET_OUTPUT(SS); + + #ifdef TEMP_INTERCOM + // Enable the RS485 transceiver + SET_OUTPUT(RX_ENABLE_PIN); + SET_OUTPUT(TX_ENABLE_PIN); + disable_transmit(); + #endif } void init(void) { From 680b70ad0dba0a29d91b9c2b2ada135b9f84fa13 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Sun, 13 Feb 2011 21:23:36 +0100 Subject: [PATCH 03/19] intercom: Send packet only once. --- temp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/temp.c b/temp.c index e1d13a5..e9bf188 100644 --- a/temp.c +++ b/temp.c @@ -241,8 +241,6 @@ void temp_sensor_tick() { case TT_INTERCOM: temp = read_temperature(temp_sensors[i].temp_pin); - start_send(); - temp_sensors_runtime[i].next_read_time = 0; break; @@ -277,6 +275,9 @@ void temp_sensor_tick() { } } } + #ifdef TEMP_INTERCOM + start_send(); + #endif } uint8_t temp_achieved() { From e6a137d5f1956d98ac60cb99d20ac144fc3af5ce Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Sun, 13 Feb 2011 21:30:50 +0100 Subject: [PATCH 04/19] intercom: Init start byte. --- extruder/intercom.c | 3 +++ intercom.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/extruder/intercom.c b/extruder/intercom.c index 8da6e62..2d44f01 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -118,6 +118,9 @@ void start_send(void) { intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS; SREG = sreg; + // set start byte + tx.packet.start = START; + // calculate CRC for outgoing packet for (i = 0; i < (sizeof(intercom_packet_t) - 1); i++) { txcrc ^= tx.data[i]; diff --git a/intercom.c b/intercom.c index 8da6e62..2d44f01 100644 --- a/intercom.c +++ b/intercom.c @@ -118,6 +118,9 @@ void start_send(void) { intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS; SREG = sreg; + // set start byte + tx.packet.start = START; + // calculate CRC for outgoing packet for (i = 0; i < (sizeof(intercom_packet_t) - 1); i++) { txcrc ^= tx.data[i]; From a3b15296075ce57a66258d5e0875e33116b6e8c9 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Sun, 13 Feb 2011 21:32:32 +0100 Subject: [PATCH 05/19] intercom: don't store start byte twice. --- extruder/intercom.c | 5 ++--- intercom.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/extruder/intercom.c b/extruder/intercom.c index 2d44f01..5258fa3 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -168,9 +168,8 @@ ISR(USART_RX_vect) packet_pointer = 1; intercom_flags |= FLAG_RX_IN_PROGRESS; } - - // we're receiving a packet - if (packet_pointer > 0) { + else if (packet_pointer > 0) { + // we're receiving a packet // calculate CRC (except CRC character!) if (packet_pointer < (sizeof(intercom_packet_t) - 1)) rxcrc ^= c; diff --git a/intercom.c b/intercom.c index 2d44f01..5258fa3 100644 --- a/intercom.c +++ b/intercom.c @@ -168,9 +168,8 @@ ISR(USART_RX_vect) packet_pointer = 1; intercom_flags |= FLAG_RX_IN_PROGRESS; } - - // we're receiving a packet - if (packet_pointer > 0) { + else if (packet_pointer > 0) { + // we're receiving a packet // calculate CRC (except CRC character!) if (packet_pointer < (sizeof(intercom_packet_t) - 1)) rxcrc ^= c; From 959bae2f4a9e9850aff1bd086a457de8c9aee1f7 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Sun, 13 Feb 2011 21:36:18 +0100 Subject: [PATCH 06/19] intercom: Add delay before slave replies. Without it the first byte gets lost. --- extruder/intercom.c | 2 ++ intercom.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/extruder/intercom.c b/extruder/intercom.c index 5258fa3..e8aaf36 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -185,6 +185,8 @@ ISR(USART_RX_vect) if (rx.packet.controller_num == THIS_CONTROLLER_NUM) { if (rxcrc != rx.packet.crc) tx.packet.err = ERROR_BAD_CRC; + // not sure why exactly this delay is needed, but wihtout it first byte never arrives. + delay_us(150); start_send(); } #endif diff --git a/intercom.c b/intercom.c index 5258fa3..e8aaf36 100644 --- a/intercom.c +++ b/intercom.c @@ -185,6 +185,8 @@ ISR(USART_RX_vect) if (rx.packet.controller_num == THIS_CONTROLLER_NUM) { if (rxcrc != rx.packet.crc) tx.packet.err = ERROR_BAD_CRC; + // not sure why exactly this delay is needed, but wihtout it first byte never arrives. + delay_us(150); start_send(); } #endif From e41e659e66d141a202c78824dc55a0477ebe3f9f Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 14 Feb 2011 11:30:05 +1100 Subject: [PATCH 07/19] intercom: Disable rx while doing tx. Avoids local RS485 half-duplex echo. Signed-off-by: Michael Moon --- extruder/extruder.c | 1 + extruder/intercom.h | 10 ++++++++-- intercom.h | 10 ++++++++-- mendel.c | 1 + 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/extruder/extruder.c b/extruder/extruder.c index e67c539..be1c11a 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -28,6 +28,7 @@ void io_init(void) { //Enable the RS485 transceiver SET_OUTPUT(RX_ENABLE_PIN); SET_OUTPUT(TX_ENABLE_PIN); + WRITE(RX_ENABLE_PIN,0); disable_transmit(); #ifdef HEATER_PIN diff --git a/extruder/intercom.h b/extruder/intercom.h index f8bc666..1120a05 100644 --- a/extruder/intercom.h +++ b/extruder/intercom.h @@ -2,9 +2,15 @@ #define _INTERCOM_H #include +#include "config.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) +#ifdef HOST + #define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); UCSR1B &= ~MASK(RXEN1); } while(0) + #define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); UCSR1B |= MASK(RXEN1); } while(0) +#else + #define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); UCSR0B &= ~MASK(RXEN0); } while(0) + #define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); UCSR0B |= MASK(RXEN0); } while(0) +#endif // initialise serial subsystem void intercom_init(void); diff --git a/intercom.h b/intercom.h index f8bc666..1120a05 100644 --- a/intercom.h +++ b/intercom.h @@ -2,9 +2,15 @@ #define _INTERCOM_H #include +#include "config.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) +#ifdef HOST + #define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); UCSR1B &= ~MASK(RXEN1); } while(0) + #define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); UCSR1B |= MASK(RXEN1); } while(0) +#else + #define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); UCSR0B &= ~MASK(RXEN0); } while(0) + #define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); UCSR0B |= MASK(RXEN0); } while(0) +#endif // initialise serial subsystem void intercom_init(void); diff --git a/mendel.c b/mendel.c index 2068273..c708481 100644 --- a/mendel.c +++ b/mendel.c @@ -126,6 +126,7 @@ void io_init(void) { // Enable the RS485 transceiver SET_OUTPUT(RX_ENABLE_PIN); SET_OUTPUT(TX_ENABLE_PIN); + WRITE(RX_ENABLE_PIN,0); disable_transmit(); #endif } From b0d1ba0e60782322a9963eb6d97bc51a17872383 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 14 Feb 2011 18:32:00 +0100 Subject: [PATCH 08/19] Fix analog reading of channel 0 if another channel is active. --- analog.c | 7 +++++-- extruder/analog.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/analog.c b/analog.c index d3e36de..ff5b03d 100644 --- a/analog.c +++ b/analog.c @@ -9,7 +9,10 @@ uint8_t adc_running_mask, adc_counter; -#if ANALOG_MASK & 2 +#if ANALOG_MASK & 1 + #define ANALOG_START 0 + #define ANALOG_START_MASK 1 +#elif ANALOG_MASK & 2 #define ANALOG_START 1 #define ANALOG_START_MASK 2 #elif ANALOG_MASK & 4 @@ -31,7 +34,7 @@ uint8_t adc_running_mask, adc_counter; #define ANALOG_START 7 #define ANALOG_START_MASK 128 #else - // ANALOG_MASK == 1 or 0, either way defines are the same except they're not used if ANALOG_MASK == 0 + // ANALOG_MASK == 0 #define ANALOG_START 0 #define ANALOG_START_MASK 1 #endif diff --git a/extruder/analog.c b/extruder/analog.c index d3e36de..ff5b03d 100644 --- a/extruder/analog.c +++ b/extruder/analog.c @@ -9,7 +9,10 @@ uint8_t adc_running_mask, adc_counter; -#if ANALOG_MASK & 2 +#if ANALOG_MASK & 1 + #define ANALOG_START 0 + #define ANALOG_START_MASK 1 +#elif ANALOG_MASK & 2 #define ANALOG_START 1 #define ANALOG_START_MASK 2 #elif ANALOG_MASK & 4 @@ -31,7 +34,7 @@ uint8_t adc_running_mask, adc_counter; #define ANALOG_START 7 #define ANALOG_START_MASK 128 #else - // ANALOG_MASK == 1 or 0, either way defines are the same except they're not used if ANALOG_MASK == 0 + // ANALOG_MASK == 0 #define ANALOG_START 0 #define ANALOG_START_MASK 1 #endif From afe58621a2a4754096ba16f7936d6f529277a656 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 14 Feb 2011 18:33:33 +0100 Subject: [PATCH 09/19] M140: S value is a temperature --- gcode_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcode_parse.c b/gcode_parse.c index 4eb05e1..9fb078b 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -155,7 +155,7 @@ void gcode_parse_char(uint8_t c) { // if this is temperature, multiply by 4 to convert to quarter-degree units // cosmetically this should be done in the temperature section, // but it takes less code, less memory and loses no precision if we do it here instead - if ((next_target.M == 104) || (next_target.M == 109)) + if ((next_target.M == 104) || (next_target.M == 109) || (next_target.M == 140)) next_target.S = decfloat_to_int(&read_digit, 4, 1); // if this is heater PID stuff, multiply by PID_SCALE because we divide by PID_SCALE later on else if ((next_target.M >= 130) && (next_target.M <= 132)) From 7aff5623ef37da67ca47d839dc3272eae2b2c48b Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:14 +1100 Subject: [PATCH 10/19] home: delay is in micro seconds --- home.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/home.c b/home.c index 4832fb9..883671e 100644 --- a/home.c +++ b/home.c @@ -44,7 +44,7 @@ void home() { delay(5); unstep(); // wait until next step time - delay((uint32_t) (60.0 * ((float) F_CPU) / STEPS_PER_MM_X / ((float) MAXIMUM_FEEDRATE_X))); + delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_MM_X / ((float) MAXIMUM_FEEDRATE_X))); } denoise_count = 0; @@ -61,7 +61,7 @@ void home() { delay(5); unstep(); // wait until next step time - delay((uint32_t) (60.0 * ((float) F_CPU) / STEPS_PER_MM_X / ((float) SEARCH_FEEDRATE_X))); + delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_MM_X / ((float) SEARCH_FEEDRATE_X))); } // set X home @@ -91,7 +91,7 @@ void home() { delay(5); unstep(); // wait until neyt step time - delay((uint32_t) (60.0 * ((float) F_CPU) / STEPS_PER_MM_Y / ((float) MAXIMUM_FEEDRATE_Y))); + delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_MM_Y / ((float) MAXIMUM_FEEDRATE_Y))); } denoise_count = 0; @@ -108,7 +108,7 @@ void home() { delay(5); unstep(); // wait until next step time - delay((uint32_t) (60.0 * ((float) F_CPU) / STEPS_PER_MM_Y / ((float) SEARCH_FEEDRATE_Y))); + delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_MM_Y / ((float) SEARCH_FEEDRATE_Y))); } // set Y home @@ -138,7 +138,7 @@ void home() { delay(5); unstep(); // wait until next step time - delay((uint32_t) (60.0 * ((float) F_CPU) / STEPS_PER_MM_Z / ((float) MAXIMUM_FEEDRATE_Z))); + delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_MM_Z / ((float) MAXIMUM_FEEDRATE_Z))); } denoise_count = 0; @@ -155,7 +155,7 @@ void home() { delay(5); unstep(); // wait until next step time - delay((uint32_t) (60.0 * ((float) F_CPU) / STEPS_PER_MM_Z / ((float) SEARCH_FEEDRATE_Z))); + delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_MM_Z / ((float) SEARCH_FEEDRATE_Z))); } // set Z home From 5cf550733d08ae08678c64a7e1efea00e7cf0cc3 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:14 +1100 Subject: [PATCH 11/19] arduino_168: define AIO6/7 --- arduino_168_328p.h | 10 ++++++++++ extruder/arduino_168_328p.h | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/arduino_168_328p.h b/arduino_168_328p.h index 9bc289b..ed970fe 100644 --- a/arduino_168_328p.h +++ b/arduino_168_328p.h @@ -126,6 +126,16 @@ pins #define AIO5_WPORT PORTC #define AIO5_DDR DDRC +#define AIO6_PIN PINC6 +#define AIO6_RPORT PINC +#define AIO6_WPORT PORTC +#define AIO6_DDR DDRC + +#define AIO7_PIN PINC7 +#define AIO7_RPORT PINC +#define AIO7_WPORT PORTC +#define AIO7_DDR DDRC + #define PB0_PIN PINB0 #define PB0_RPORT PINB #define PB0_WPORT PORTB diff --git a/extruder/arduino_168_328p.h b/extruder/arduino_168_328p.h index 9bc289b..ed970fe 100644 --- a/extruder/arduino_168_328p.h +++ b/extruder/arduino_168_328p.h @@ -126,6 +126,16 @@ pins #define AIO5_WPORT PORTC #define AIO5_DDR DDRC +#define AIO6_PIN PINC6 +#define AIO6_RPORT PINC +#define AIO6_WPORT PORTC +#define AIO6_DDR DDRC + +#define AIO7_PIN PINC7 +#define AIO7_RPORT PINC +#define AIO7_WPORT PORTC +#define AIO7_DDR DDRC + #define PB0_PIN PINB0 #define PB0_RPORT PINB #define PB0_WPORT PORTB From e3672da1cf7557087cf9ebebbc7bdc06b861be92 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:15 +1100 Subject: [PATCH 12/19] extruder: Check the step pin directly. Flag could get out of sync, with undefined results. --- extruder/extruder.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/extruder/extruder.c b/extruder/extruder.c index be1c11a..4f227d0 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -65,13 +65,10 @@ void motor_init(void) { } ISR(PCINT0_vect) { - static uint8_t coil_pos, pwm, flag; + static uint8_t coil_pos, pwm; - if (flag == 1) flag = 0; - else flag = 1; - //if the step pin is high, we advance the motor - if (flag) { + if (READ(E_STEP_PIN)) { //Turn on motors only on first tick to save power I guess enable_motors(); From d0cbe86a2decbaebb6172eb2afca577cfbd33d2e Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:15 +1100 Subject: [PATCH 13/19] extruder: Half-step on every step signal. No idea why only every 4th step signal would actually step, but this generates a lot of noise for nothing. --- extruder/extruder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extruder/extruder.c b/extruder/extruder.c index 4f227d0..3882564 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -79,12 +79,12 @@ ISR(PCINT0_vect) { else coil_pos--; - coil_pos &= 31; + coil_pos &= 7; //Grab the latest motor power to use pwm = motor_pwm; - switch(coil_pos >> 2) { + switch(coil_pos) { case 0: WRITE(H1D, 0); WRITE(H2D, 0); From e032cf5dab55e1ab6fd6453b7527c1053d5c9461 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:15 +1100 Subject: [PATCH 14/19] extruder: Use pull up resistors for step/dir pin to avoid noise. --- extruder/extruder.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extruder/extruder.c b/extruder/extruder.c index 3882564..e0169f3 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -25,6 +25,10 @@ void io_init(void) { SET_INPUT(E_STEP_PIN); SET_INPUT(E_DIR_PIN); + // use pull up resistors to avoid noise + WRITE(E_STEP_PIN, 1); + WRITE(E_DIR_PIN, 1); + //Enable the RS485 transceiver SET_OUTPUT(RX_ENABLE_PIN); SET_OUTPUT(TX_ENABLE_PIN); From 6d83bdb067b23f74685437f2ebbb7b9b091b996d Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:15 +1100 Subject: [PATCH 15/19] extruder: add fan definitions --- extruder/config.h.dist | 10 +++++++--- extruder/extruder.c | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/extruder/config.h.dist b/extruder/config.h.dist index e4345b4..f92d93d 100644 --- a/extruder/config.h.dist +++ b/extruder/config.h.dist @@ -39,6 +39,10 @@ #define TEMP_THERMISTOR +#define HEATER_PIN DIO11 +#define BED_PIN AIO1 +#define FAN_PIN DIO12 + // extruder settings #define TEMP_HYSTERESIS 20 #define TEMP_RESIDENCY_TIME 60 @@ -48,8 +52,8 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, PINC3) #endif #ifdef DEFINE_HEATER -DEFINE_HEATER(extruder, PORTD, DIO6_PIN, OCR0A) -DEFINE_HEATER(bed, PORTD, DIO5_PIN, OCR0B) +DEFINE_HEATER(extruder, PORTD, HEATER_PIN, OCR0A) +DEFINE_HEATER(bed, PORTD, BED_PIN, OCR0B) #endif // list of PWM-able pins and corresponding timers @@ -57,7 +61,7 @@ DEFINE_HEATER(bed, PORTD, DIO5_PIN, OCR0B) // OC0A DIO6 // OC0B DIO5 // OC1A DIO9 -// OC1B DIO10 +// OC1B DIO10 // OC2A DIO11 // OC2B DIO3 diff --git a/extruder/extruder.c b/extruder/extruder.c index e0169f3..93b195c 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -43,6 +43,10 @@ void io_init(void) { WRITE(BED_PIN, 0); SET_OUTPUT(BED_PIN); #endif + #ifdef FAN_PIN + WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN); + #endif + // #if defined(HEATER_PWM) || defined(FAN_PWM) || defined(BED_PWM) // setup PWM timer: fast PWM, no prescaler TCCR2A = MASK(WGM21) | MASK(WGM20); From 5e56784ac104316c0fc73bab4b7f4a1bd4a19f8f Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:16 +1100 Subject: [PATCH 16/19] extruder: Set/get bed temperature. --- extruder/config.h.dist | 10 ++++++++-- extruder/extruder.c | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/extruder/config.h.dist b/extruder/config.h.dist index f92d93d..d1851e1 100644 --- a/extruder/config.h.dist +++ b/extruder/config.h.dist @@ -33,9 +33,14 @@ #define TEMP_PIN AIO3 #define TEMP_PIN_CHANNEL 3 +//Read analog voltage from thermistor +#define TEMP_BED_PIN AIO6 +#define TEMP_BED_PIN_CHANNEL 6 + + #define REFERENCE REFERENCE_AVCC -#define ANALOG_MASK (MASK(TRIM_POT_CHANNEL) | MASK(TEMP_PIN_CHANNEL)) +#define ANALOG_MASK (MASK(TRIM_POT_CHANNEL) | MASK(TEMP_PIN_CHANNEL) | MASK(TEMP_BED_PIN_CHANNEL)) #define TEMP_THERMISTOR @@ -48,7 +53,8 @@ #define TEMP_RESIDENCY_TIME 60 #ifdef DEFINE_TEMP_SENSOR -DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, PINC3) +DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, TEMP_PIN_CHANNEL) +DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, TEMP_BED_PIN_CHANNEL) #endif #ifdef DEFINE_HEATER diff --git a/extruder/extruder.c b/extruder/extruder.c index 93b195c..79d1eff 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -22,6 +22,7 @@ void io_init(void) { SET_INPUT(TRIM_POT); SET_INPUT(TEMP_PIN); + SET_INPUT(TEMP_BED_PIN); SET_INPUT(E_STEP_PIN); SET_INPUT(E_DIR_PIN); @@ -194,6 +195,8 @@ int main (void) temp_sensor_tick(); send_temperature(0, temp_get(0)); + send_temperature(1, temp_get(1)); temp_set(0, read_temperature(0)); + temp_set(1, read_temperature(1)); } } From fa2a4389fc89ddad351f921c2428a51ddce6c38e Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:16 +1100 Subject: [PATCH 17/19] intercom: Transmit/receive from/to temporary packets. Fixes that the packet could be changed during transmit. And only values from packets with correct checksum are used. --- extruder/intercom.c | 38 +++++++++++++++++++++++++++++--------- intercom.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/extruder/intercom.c b/extruder/intercom.c index e8aaf36..780dc07 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -41,8 +41,10 @@ typedef union { uint8_t data[sizeof(intercom_packet_t)]; } intercom_packet; -intercom_packet tx; -intercom_packet rx; +intercom_packet tx; // this packet will be send +intercom_packet rx; // the last received packet with correct checksum +intercom_packet _tx; // current packet in transmission +intercom_packet _rx; // receiving packet uint8_t packet_pointer; uint8_t rxcrc; @@ -116,7 +118,6 @@ void start_send(void) { uint8_t sreg = SREG; cli(); intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS; - SREG = sreg; // set start byte tx.packet.start = START; @@ -127,6 +128,12 @@ void start_send(void) { } tx.packet.crc = txcrc; + for (i = 0; i < (sizeof(intercom_packet_t) ); i++) { + _tx.data[i] = tx.data[i]; + } + + SREG = sreg; + // enable transmit pin enable_transmit(); delay_us(15); @@ -164,7 +171,7 @@ ISR(USART_RX_vect) // are we waiting for a start byte? is this one? if ((packet_pointer == 0) && (c == START)) { - rxcrc = rx.packet.start = START; + rxcrc = _rx.packet.start = START; packet_pointer = 1; intercom_flags |= FLAG_RX_IN_PROGRESS; } @@ -174,16 +181,29 @@ ISR(USART_RX_vect) if (packet_pointer < (sizeof(intercom_packet_t) - 1)) rxcrc ^= c; // stuff byte into structure - rx.data[packet_pointer++] = c; + _rx.data[packet_pointer++] = c; // last byte? if (packet_pointer >= sizeof(intercom_packet_t)) { // reset pointer packet_pointer = 0; + #ifndef HOST + if (rxcrc == _rx.packet.crc && + _rx.packet.controller_num == THIS_CONTROLLER_NUM){ + #else + if (rxcrc == _rx.packet.crc){ + #endif + // correct crc copy packet + static uint8_t i; + for (i = 0; i < (sizeof(intercom_packet_t) ); i++) { + rx.data[i] = _rx.data[i]; + } + } + 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) + if (_rx.packet.controller_num == THIS_CONTROLLER_NUM) { + if (rxcrc != _rx.packet.crc) tx.packet.err = ERROR_BAD_CRC; // not sure why exactly this delay is needed, but wihtout it first byte never arrives. delay_us(150); @@ -221,9 +241,9 @@ ISR(USART_UDRE_vect) #endif { #ifdef HOST - UDR1 = tx.data[packet_pointer++]; + UDR1 = _tx.data[packet_pointer++]; #else - UDR0 = tx.data[packet_pointer++]; + UDR0 = _tx.data[packet_pointer++]; #endif if (packet_pointer >= sizeof(intercom_packet_t)) { diff --git a/intercom.c b/intercom.c index e8aaf36..780dc07 100644 --- a/intercom.c +++ b/intercom.c @@ -41,8 +41,10 @@ typedef union { uint8_t data[sizeof(intercom_packet_t)]; } intercom_packet; -intercom_packet tx; -intercom_packet rx; +intercom_packet tx; // this packet will be send +intercom_packet rx; // the last received packet with correct checksum +intercom_packet _tx; // current packet in transmission +intercom_packet _rx; // receiving packet uint8_t packet_pointer; uint8_t rxcrc; @@ -116,7 +118,6 @@ void start_send(void) { uint8_t sreg = SREG; cli(); intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS; - SREG = sreg; // set start byte tx.packet.start = START; @@ -127,6 +128,12 @@ void start_send(void) { } tx.packet.crc = txcrc; + for (i = 0; i < (sizeof(intercom_packet_t) ); i++) { + _tx.data[i] = tx.data[i]; + } + + SREG = sreg; + // enable transmit pin enable_transmit(); delay_us(15); @@ -164,7 +171,7 @@ ISR(USART_RX_vect) // are we waiting for a start byte? is this one? if ((packet_pointer == 0) && (c == START)) { - rxcrc = rx.packet.start = START; + rxcrc = _rx.packet.start = START; packet_pointer = 1; intercom_flags |= FLAG_RX_IN_PROGRESS; } @@ -174,16 +181,29 @@ ISR(USART_RX_vect) if (packet_pointer < (sizeof(intercom_packet_t) - 1)) rxcrc ^= c; // stuff byte into structure - rx.data[packet_pointer++] = c; + _rx.data[packet_pointer++] = c; // last byte? if (packet_pointer >= sizeof(intercom_packet_t)) { // reset pointer packet_pointer = 0; + #ifndef HOST + if (rxcrc == _rx.packet.crc && + _rx.packet.controller_num == THIS_CONTROLLER_NUM){ + #else + if (rxcrc == _rx.packet.crc){ + #endif + // correct crc copy packet + static uint8_t i; + for (i = 0; i < (sizeof(intercom_packet_t) ); i++) { + rx.data[i] = _rx.data[i]; + } + } + 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) + if (_rx.packet.controller_num == THIS_CONTROLLER_NUM) { + if (rxcrc != _rx.packet.crc) tx.packet.err = ERROR_BAD_CRC; // not sure why exactly this delay is needed, but wihtout it first byte never arrives. delay_us(150); @@ -221,9 +241,9 @@ ISR(USART_UDRE_vect) #endif { #ifdef HOST - UDR1 = tx.data[packet_pointer++]; + UDR1 = _tx.data[packet_pointer++]; #else - UDR0 = tx.data[packet_pointer++]; + UDR0 = _tx.data[packet_pointer++]; #endif if (packet_pointer >= sizeof(intercom_packet_t)) { From 52c27889977ea0b1cb2fbae6a6a67d16c6291112 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:17 +1100 Subject: [PATCH 18/19] intercom: updating the extruder in 250ms intervals should be fast enough. --- clock.c | 3 +++ temp.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clock.c b/clock.c index 6d035d2..4c8ce34 100644 --- a/clock.c +++ b/clock.c @@ -31,6 +31,9 @@ void clock_250ms() { /* if (temp_get_target()) temp_print();*/ } + #ifdef TEMP_INTERCOM + start_send(); + #endif } void clock_10ms() { diff --git a/temp.c b/temp.c index e9bf188..c944eaa 100644 --- a/temp.c +++ b/temp.c @@ -275,9 +275,6 @@ void temp_sensor_tick() { } } } - #ifdef TEMP_INTERCOM - start_send(); - #endif } uint8_t temp_achieved() { From bfae6ff97f7b6cfbccd690bd64c74f6e715f2ba7 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Mon, 21 Feb 2011 15:52:17 +1100 Subject: [PATCH 19/19] intercom: Reduce sections with disabled interrupts. --- extruder/intercom.c | 3 +-- intercom.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/extruder/intercom.c b/extruder/intercom.c index 780dc07..06cfa36 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -118,6 +118,7 @@ void start_send(void) { uint8_t sreg = SREG; cli(); intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS; + SREG = sreg; // set start byte tx.packet.start = START; @@ -132,8 +133,6 @@ void start_send(void) { _tx.data[i] = tx.data[i]; } - SREG = sreg; - // enable transmit pin enable_transmit(); delay_us(15); diff --git a/intercom.c b/intercom.c index 780dc07..06cfa36 100644 --- a/intercom.c +++ b/intercom.c @@ -118,6 +118,7 @@ void start_send(void) { uint8_t sreg = SREG; cli(); intercom_flags = (intercom_flags & ~FLAG_TX_FINISHED) | FLAG_TX_IN_PROGRESS; + SREG = sreg; // set start byte tx.packet.start = START; @@ -132,8 +133,6 @@ void start_send(void) { _tx.data[i] = tx.data[i]; } - SREG = sreg; - // enable transmit pin enable_transmit(); delay_us(15);