merge intercom-protocol into master

This commit is contained in:
Michael Moon 2011-02-21 16:01:27 +11:00
commit 8188ff3593
18 changed files with 805 additions and 576 deletions

View File

@ -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

View File

@ -31,6 +31,9 @@ void clock_250ms() {
/* if (temp_get_target())
temp_print();*/
}
#ifdef TEMP_INTERCOM
start_send();
#endif
}
void clock_10ms() {

View File

@ -1,48 +1,21 @@
#include "analog.h"
#include "temp.h"
#include <avr/interrupt.h>
#ifndef ANALOG_MASK
#warning ANALOG_MASK not defined - analog subsystem disabled
#define ANALOG_MASK 0
#endif
/* OR-combined mask of all channels */
#undef DEFINE_TEMP_SENSOR
#define DEFINE_TEMP_SENSOR(name, type, pin) | (((type == TT_THERMISTOR) || (type == TT_AD595)) ? 1 << (pin) : 0)
static const uint8_t analog_mask = 0
#include "config.h"
;
#undef DEFINE_TEMP_SENSOR
uint8_t adc_running_mask, adc_counter;
#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
#define ANALOG_START 2
#define ANALOG_START_MASK 4
#elif ANALOG_MASK & 8
#define ANALOG_START 3
#define ANALOG_START_MASK 8
#elif ANALOG_MASK & 16
#define ANALOG_START 4
#define ANALOG_START_MASK 16
#elif ANALOG_MASK & 32
#define ANALOG_START 5
#define ANALOG_START_MASK 32
#elif ANALOG_MASK & 64
#define ANALOG_START 6
#define ANALOG_START_MASK 64
#elif ANALOG_MASK & 128
#define ANALOG_START 7
#define ANALOG_START_MASK 128
#else
// ANALOG_MASK == 0
#define ANALOG_START 0
#define ANALOG_START_MASK 1
#endif
volatile uint16_t adc_result[8] __attribute__ ((__section__ (".bss")));
static uint8_t adc_counter;
static volatile uint16_t adc_result[8] __attribute__ ((__section__ (".bss")));
void analog_init() {
#if ANALOG_MASK > 0
if (analog_mask > 0) {
#ifdef PRR
PRR &= ~MASK(PRADC);
#elif defined PRR0
@ -55,36 +28,32 @@ void analog_init() {
ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0);
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);
#endif /* ANALOG_MASK > 0 */
} /* analog_mask > 0 */
}
ISR(ADC_vect, ISR_NOBLOCK) {
// emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts
if (analog_mask > 0) {
adc_result[ADMUX & 0x0F] = ADC;
// find next channel
do {
adc_counter++;
adc_running_mask <<= 1;
if (adc_counter == 8) {
adc_counter = ANALOG_START;
adc_running_mask = ANALOG_START_MASK;
}
} while ((adc_running_mask & ANALOG_MASK) == 0);
adc_counter &= 0x07;
} while ((analog_mask & (1 << adc_counter)) == 0);
// start next conversion
ADMUX = (adc_counter) | REFERENCE;
ADCSRA |= MASK(ADSC);
}
}
uint16_t analog_read(uint8_t channel) {
#if ANALOG_MASK > 0
if (analog_mask > 0) {
uint16_t r;
uint8_t sreg;
@ -100,7 +69,7 @@ uint16_t analog_read(uint8_t channel) {
SREG = sreg;
return r;
#else
} else {
return 0;
#endif
}
}

View File

@ -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

View File

@ -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
@ -30,43 +33,33 @@
#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
#define HEATER_PIN DIO11
#define BED_PIN AIO1
#define FAN_PIN DIO12
// extruder settings
#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, TEMP_PIN_CHANNEL)
DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, TEMP_BED_PIN_CHANNEL)
#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, HEATER_PIN, OCR0A)
DEFINE_HEATER(bed, PORTD, BED_PIN, OCR0B)
#endif
// list of PWM-able pins and corresponding timers
@ -81,49 +74,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 +82,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 */

View File

@ -3,18 +3,12 @@
#include <stdint.h>
#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
#define DEBUG_ECHO 128
#define DEBUG_ECHO 0
extern volatile uint8_t debug_flags;

View File

@ -22,12 +22,18 @@ 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);
// 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);
WRITE(RX_ENABLE_PIN,0);
disable_transmit();
#ifdef HEATER_PIN
@ -38,6 +44,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);
@ -64,13 +74,10 @@ void motor_init(void) {
}
ISR(PCINT0_vect) {
static uint8_t coil_pos, pwm, flag;
if (flag == 1) flag = 0;
else flag = 1;
static uint8_t coil_pos, pwm;
//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();
@ -81,12 +88,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);
@ -187,7 +194,9 @@ 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));
send_temperature(1, temp_get(1));
temp_set(0, read_temperature(0));
temp_set(1, read_temperature(1));
}
}

View File

@ -9,9 +9,21 @@
#ifndef EXTRUDER
#include "sersendf.h"
#endif
#include "temp.h"
#define HEATER_C
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);
@ -81,6 +94,7 @@ void heater_init() {
heaters_runtime[i].sane_temperature = 0;
#endif
#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);
@ -93,28 +107,35 @@ void heater_init() {
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;
#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;
#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);
@ -155,6 +176,12 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) {
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
@ -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) {
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_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_i(uint8_t index, int32_t i) {
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_d(uint8_t index, int32_t d) {
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(uint8_t index, int32_t i_limit) {
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 */
}

View File

@ -1,20 +1,34 @@
#ifndef _HEATER_H
#define _HEATER_H
#include "config.h"
#include <stdint.h>
#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 */

View File

@ -1,47 +1,55 @@
#include "intercom.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#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; // 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;
#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 +78,67 @@ 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;
// 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];
}
tx.packet.crc = txcrc;
for (i = 0; i < (sizeof(intercom_packet_t) ); i++) {
_tx.data[i] = tx.data[i];
}
// 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,21 +146,18 @@ 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
@ -126,53 +168,62 @@ ISR(USART_RX_vect)
UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0);
#endif
if (state >= READ_START1) {
// 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;
}
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;
// stuff byte into structure
_rx.data[packet_pointer++] = c;
// last byte?
if (packet_pointer >= sizeof(intercom_packet_t)) {
// reset pointer
packet_pointer = 0;
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;
#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];
}
}
if (chk == 255 - cmd) {
//Values are correct, do something useful
WRITE(DEBUG_LED,1);
read_cmd = cmd;
#ifdef EXTRUDER
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;
// not sure why exactly this delay is needed, but wihtout it first byte never arrives.
delay_us(150);
start_send();
}
#endif
}
else
{
state = READ_START1;
}
break;
default:
break;
}
}
}
// 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();
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
@ -181,28 +232,20 @@ ISR(USART_TX_vect)
}
}
// 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
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);
@ -210,10 +253,7 @@ ISR(USART_UDRE_vect)
UCSR0B &= ~MASK(UDRIE0);
UCSR0B |= MASK(TXCIE0);
#endif
break;
default:
break;
}
}
#endif /* GEN3 */
#endif /* TEMP_INTERCOM */

View File

@ -2,16 +2,49 @@
#define _INTERCOM_H
#include <stdint.h>
#include "config.h"
#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);
//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 */

View File

@ -4,22 +4,6 @@
#include <avr/eeprom.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 "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\n"), temp_sensors_runtime[index].last_read_temp >> 2, c);
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(" B:%u.%u"), temp_sensors_runtime[HEATER_bed].last_read_temp >> 2 , b);
#endif
}
#endif

View File

@ -1,6 +1,7 @@
#ifndef _TEMP_H
#define _TEMP_H
#include "config.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.
*/
#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 */

12
home.c
View File

@ -45,7 +45,7 @@ void home_x_negative() {
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;
@ -95,7 +95,7 @@ void home_x_positive() {
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
@ -126,7 +126,7 @@ void home_y_negative() {
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;
@ -176,7 +176,7 @@ void home_y_positive() {
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
@ -207,7 +207,7 @@ void home_z_negative() {
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;
@ -257,7 +257,7 @@ void home_z_positive() {
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

View File

@ -1,47 +1,55 @@
#include "intercom.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#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; // 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;
#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 +78,67 @@ 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;
// 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];
}
tx.packet.crc = txcrc;
for (i = 0; i < (sizeof(intercom_packet_t) ); i++) {
_tx.data[i] = tx.data[i];
}
// 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,21 +146,18 @@ 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
@ -126,53 +168,62 @@ ISR(USART_RX_vect)
UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0);
#endif
if (state >= READ_START1) {
// 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;
}
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;
// stuff byte into structure
_rx.data[packet_pointer++] = c;
// last byte?
if (packet_pointer >= sizeof(intercom_packet_t)) {
// reset pointer
packet_pointer = 0;
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;
#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];
}
}
if (chk == 255 - cmd) {
//Values are correct, do something useful
WRITE(DEBUG_LED,1);
read_cmd = cmd;
#ifdef EXTRUDER
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;
// not sure why exactly this delay is needed, but wihtout it first byte never arrives.
delay_us(150);
start_send();
}
#endif
}
else
{
state = READ_START1;
}
break;
default:
break;
}
}
}
// 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();
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
@ -181,28 +232,20 @@ ISR(USART_TX_vect)
}
}
// 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
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);
@ -210,9 +253,6 @@ ISR(USART_UDRE_vect)
UCSR0B &= ~MASK(UDRIE0);
UCSR0B |= MASK(TXCIE0);
#endif
break;
default:
break;
}
}

View File

@ -2,16 +2,49 @@
#define _INTERCOM_H
#include <stdint.h>
#include "config.h"
#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);
//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 */

View File

@ -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
@ -123,6 +124,14 @@ 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);
WRITE(RX_ENABLE_PIN,0);
disable_transmit();
#endif
}
void init(void) {

14
temp.c
View File

@ -83,7 +83,7 @@ void temp_init() {
#ifdef TEMP_INTERCOM
case TT_INTERCOM:
intercom_init();
update_send_cmd(0);
send_temperature(0, 0);
break;
#endif
@ -163,8 +163,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
@ -188,13 +190,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
@ -227,9 +233,7 @@ void temp_sensor_tick() {
#ifdef TEMP_INTERCOM
case TT_INTERCOM:
temp = get_read_cmd() << 2;
start_send();
temp = read_temperature(temp_sensors[i].temp_pin);
temp_sensors_runtime[i].next_read_time = 0;
@ -289,7 +293,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
}