merge gen3 stuff

This commit is contained in:
Michael Moon 2010-10-26 01:01:46 +11:00
parent c7ac215c59
commit 4bdb97c3b7
26 changed files with 843 additions and 69 deletions

View File

@ -31,7 +31,7 @@
PROGRAM = mendel
SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c
SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c
##############################################################################
# #
@ -68,10 +68,12 @@ OBJCOPY = $(ARCH)objcopy
# enables reprap-style acceleration #
# ACCELERATION_RAMPING #
# enables start/stop ramping #
# GEN3 #
# build for standard reprap electronics instead of your custom rig #
# #
##############################################################################
DEFS = -DF_CPU=$(F_CPU)
DEFS = -DF_CPU=$(F_CPU) -DHOST -DGEN3
# DEFS += "-DDEBUG=1"
OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once
@ -115,9 +117,9 @@ clean:
size: $(PROGRAM).elf
@echo " SIZE Atmega168 Atmega328p Atmega644"
@$(OBJDUMP) -h $^ | perl -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (14 * 1024), 14, $$a * 100 / (30 * 1024), 30, $$a * 100 / (63 * 1024), 63 }'
@$(OBJDUMP) -h $^ | perl -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (4 * 1024), 4 }'
@$(OBJDUMP) -h $^ | perl -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (2 * 1024), 2 }'
@$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (14 * 1024)), 14, ceil($$a * 100 / (30 * 1024)), 30, ceil($$a * 100 / (63 * 1024)), 63 }'
@$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (4 * 1024)), 4 }'
@$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (2 * 1024)), 2 }'
config.h: config.h.dist
@echo "Please review config.h, as config.h.dist is more recent."

View File

@ -46,14 +46,14 @@
Each movement starts at the speed of the previous command and accelerates or decelerates linearly to reach target speed at the end of the movement.
Can also be set in Makefile
*/
#define ACCELERATION_REPRAP
// #define ACCELERATION_REPRAP
/*
acceleration and deceleration ramping.
Each movement starts at (almost) no speed, linearly accelerates to target speed and decelerates just in time to smoothly stop at the target. alternative to ACCELERATION_REPRAP
Can also be set in Makefile
*/
//#define ACCELERATION_RAMPING
#define ACCELERATION_RAMPING
// how fast to accelerate when using ACCELERATION_RAMPING
// smaller values give quicker acceleration
@ -68,7 +68,7 @@
// which temperature sensor are you using?
// #define TEMP_MAX6675
#define TEMP_THERMISTOR
// #define TEMP_THERMISTOR
// #define TEMP_AD595
#define NUM_TEMP_SENSORS 1
@ -80,6 +80,9 @@
* If your temperature sensor has no associated heater, enter '255' as the *
* heater index. *
* *
* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to *
* 255 *
* *
\***************************************************************************/
struct {
@ -90,14 +93,14 @@ struct {
} temp_sensors[NUM_TEMP_SENSORS] =
{
{
TT_MAX6675,
TT_INTERCOM,
0,
0
}
};
#endif
#define NUM_HEATERS 1
#define NUM_HEATERS 0
#ifdef HEATER_C
/***************************************************************************\
* *
@ -119,7 +122,7 @@ struct {
{
{
&PORTD,
PIND0,
PIND6,
&OCR0A
}
};
@ -238,6 +241,12 @@ struct {
#define STEPPER_ENABLE_PIN DIO9
#ifdef GEN3
#define TX_ENABLE_PIN AIO2
#define RX_ENABLE_PIN DIO4
#define DEBUG_LED DIO13
#endif
/**
* list of PWM-able pins and corresponding timers
* timer1 is used for step timing so don't use OC1A/OC1B
@ -273,14 +282,7 @@ struct {
*
*/
// comment out the ones you don't have
#define HEATER_PIN DIO6
#define HEATER_PWM OCR0A
#define FAN_PIN DIO5
#define FAN_PWM OCR0B
// this is the scaling of internally stored PID values. 1024L is a good value
#define PID_SCALE 1024L
// --------------------------------------------------------------------------

142
extruder/Makefile Normal file
View File

@ -0,0 +1,142 @@
##############################################################################
# #
# FiveD on Arduino - alternative firmware for repraps #
# #
# by Triffid Hunter, Traumflug, jakepoz #
# #
# #
# This firmware is Copyright (C) 2009-2010 Michael Moon aka Triffid_Hunter #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #
# #
##############################################################################
##############################################################################
# #
# Change these to suit your application #
# #
##############################################################################
PROGRAM = extruder
SOURCES = $(PROGRAM).c intercom.c delay.c analog.c watchdog.c
##############################################################################
# #
# Change these to suit your hardware #
# #
##############################################################################
MCU_TARGET = atmega168
F_CPU = 16000000L
##############################################################################
# #
# These defaults should be ok, change if you need to #
# #
##############################################################################
ARCH = avr-
CC = $(ARCH)gcc
OBJDUMP = $(ARCH)objdump
OBJCOPY = $(ARCH)objcopy
##############################################################################
# #
# Available Defines: #
# #
# DEBUG #
# enables tons of debugging output. may cause host-side talkers to choke #
# XONXOFF #
# enables XON/XOFF flow control for stupid or crude talkers #
# ACCELERATION_REPRAP #
# enables reprap-style acceleration #
# ACCELERATION_RAMPING #
# enables start/stop ramping #
# #
##############################################################################
DEFS = -DF_CPU=$(F_CPU) -DEXTRUDER -DGEN3
# DEFS += "-DDEBUG=1"
OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once
# OPTIMIZE = -O0
CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps
LDFLAGS = -Wl,--as-needed -Wl,--gc-sections
AVRDUDE = avrdude
AVRDUDECONF = /etc/avrdude.conf
##############################################################################
# #
# udev rule for /dev/arduino (insert into /etc/udev/rules.d/99-local.rules) #
# SUBSYSTEMS=="usb", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", #
# NAME="%k", SYMLINK+="arduino", SYMLINK+="arduino_$attr{serial}", #
# MODE="0660" #
# #
##############################################################################
PROGPORT = /dev/arduino
PROGBAUD = 57600
OBJ = $(patsubst %.c,%.o,${SOURCES})
.PHONY: all program clean size
.PRECIOUS: %.o %.elf
all: config.h $(PROGRAM).hex $(PROGRAM).lst $(PROGRAM).sym size
program: $(PROGRAM).hex config.h
stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT)
@sleep 0.1
@stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT)
$(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C$(AVRDUDECONF) -U flash:w:$^
stty 115200 raw ignbrk -hup -echo ixoff < $(PROGPORT)
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~
size: $(PROGRAM).elf
@echo " SIZE Atmega168 Atmega328p Atmega644"
@$(OBJDUMP) -h $^ | perl -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (14 * 1024), 14, $$a * 100 / (30 * 1024), 30, $$a * 100 / (63 * 1024), 63 }'
@$(OBJDUMP) -h $^ | perl -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (4 * 1024), 4 }'
@$(OBJDUMP) -h $^ | perl -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (2 * 1024), 2 }'
config.h: config.h.dist
@echo "Please review config.h, as config.h.dist is more recent."
@false
%.o: %.c config.h
@echo " CC $@"
@$(CC) -c $(CFLAGS) -Wa,-adhlns=$(<:.c=.al) -o $@ $(subst .o,.c,$@)
%.elf: $(OBJ)
@echo " LINK $@"
@$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
%.lst: %.elf
@echo " OBJDUMP $@"
@$(OBJDUMP) -h -S $< > $@
%.hex: %.elf
@echo " OBJCOPY $@"
@$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.bin: %.elf
@echo " OBJCOPY $@"
@$(OBJCOPY) -j .text -j .data -O binary $< $@
%.sym: %.elf
@echo " SYM $@"
@$(OBJDUMP) -t $< | perl -ne 'BEGIN { printf " ADDR NAME SIZE\n"; } /([0-9a-f]+)\s+(\w+)\s+O\s+\.(bss|data)\s+([0-9a-f]+)\s+(\w+)/ && printf "0x%04x %-20s +%d\n", eval("0x$$1") & 0xFFFF, $$5, eval("0x$$4")' | sort -k1 > $@

2
extruder/README Normal file
View File

@ -0,0 +1,2 @@
Reprap Gen3 extruder controller support for Triffid_Hunter's FiveD_on_Arduino firmware
by jakepoz

1
extruder/analog.c Symbolic link
View File

@ -0,0 +1 @@
../analog.c

1
extruder/analog.h Symbolic link
View File

@ -0,0 +1 @@
../analog.h

1
extruder/arduino.h Symbolic link
View File

@ -0,0 +1 @@
../arduino.h

1
extruder/arduino_168_328p.h Symbolic link
View File

@ -0,0 +1 @@
../arduino_168_328p.h

79
extruder/config.h.dist Normal file
View File

@ -0,0 +1,79 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#include "arduino.h"
//RS485 Interface pins
#define RX_ENABLE_PIN DIO4
#define TX_ENABLE_PIN AIO2
// Control pins for the A3949 chips
#define H1D DIO7
#define H1E DIO5
#define H2D DIO8
#define H2E DIO6
// PWM versions of the enable_pins
#define H1E_PWM OCR0B
#define H2E_PWM OCR0A
//Step/Dir Pins from motherboard to extruder
//IMPORTANT: Assumes that the step pin is on PCIE0
#define E_STEP_PIN DIO10
#define E_DIR_PIN DIO9
//Trimpot is on AIO0, pin 23
#define TRIM_POT AIO0
#define TRIM_POT_CHANNEL 0
//Debug LED will blink on RS485 transmission
#define DEBUG_LED DIO13
//Read analog voltage from thermistor
#define TEMP_PIN AIO3
#define TEMP_PIN_CHANNEL 3
#define REFERENCE REFERENCE_AVCC
// list of PWM-able pins and corresponding timers
// timer1 is used for step timing so don't use OC1A/OC1B (DIO9/DIO10)
// OC0A DIO6
// OC0B DIO5
// OC1A DIO9
// OC1B DIO10
// OC2A DIO11
// OC2B DIO3
#define HEATER_PIN DIO11
#define HEATER_PWM OCR2A
#define BED_PIN DIO12
#define ANALOG_MASK (MASK(TRIM_POT_CHANNEL) | MASK(TEMP_PIN_CHANNEL))
/*
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
*/
#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 */

1
extruder/delay.c Symbolic link
View File

@ -0,0 +1 @@
../delay.c

1
extruder/delay.h Symbolic link
View File

@ -0,0 +1 @@
../delay.h

229
extruder/extruder.c Normal file
View File

@ -0,0 +1,229 @@
#include <stdint.h>
#include <string.h>
#include <avr/interrupt.h>
#include "intercom.h"
#include "analog.h"
#include "config.h"
#include "watchdog.h"
static uint8_t motor_pwm;
#define NUMTEMPS 20
short temptable[NUMTEMPS][2] = {
{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}
};
void io_init(void) {
// setup I/O pins
WRITE(DEBUG_LED, 0); SET_OUTPUT(DEBUG_LED);
WRITE(H1D,0); SET_OUTPUT(H1D);
WRITE(H1E,0); SET_OUTPUT(H1E);
WRITE(H2D,0); SET_OUTPUT(H2D);
WRITE(H2E,0); SET_OUTPUT(H2E);
SET_INPUT(TRIM_POT);
SET_INPUT(TEMP_PIN);
SET_INPUT(E_STEP_PIN);
SET_INPUT(E_DIR_PIN);
//Enable the RS485 transceiver
SET_OUTPUT(RX_ENABLE_PIN);
SET_OUTPUT(TX_ENABLE_PIN);
disable_transmit();
#ifdef HEATER_PIN
WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN);
#endif
#ifdef BED_PIN
WRITE(BED_PIN, 0); SET_OUTPUT(BED_PIN);
#endif
#if defined(HEATER_PWM) || defined(FAN_PWM) || defined(BED_PWM)
// setup PWM timer: fast PWM, no prescaler
TCCR2A = MASK(WGM21) | MASK(WGM20);
TCCR2B = MASK(CS22);
TIMSK2 = 0;
OCR2A = 0;
OCR2B = 0;
#endif
#if defined(H1E_PWM) && defined(H2E_PWM)
TCCR0A = MASK(WGM01) | MASK(WGM00);
TCCR0B = MASK(CS20);
TIMSK0 = 0;
OCR0A = 0;
OCR0B = 0;
#endif
}
void motor_init(void) {
//Enable an interrupt to be triggered when the step pin changes
//This will be PCIE0
PCICR = MASK(PCIE0);
PCMSK0 = MASK(PCINT2);
}
ISR(PCINT0_vect) {
static uint8_t coil_pos, pwm, flag;
if (flag == 1) flag = 0;
else flag = 1;
//if the step pin is high, we advance the motor
if (flag) {
//Turn on motors only on first tick to save power I guess
enable_motors();
//Advance the coil position
if (READ(E_DIR_PIN))
coil_pos++;
else
coil_pos--;
coil_pos &= 31;
//Grab the latest motor power to use
pwm = motor_pwm;
switch(coil_pos >> 2) {
case 0:
WRITE(H1D, 0);
WRITE(H2D, 0);
H1E_PWM = 0;
H2E_PWM = pwm;
break;
case 1:
WRITE(H1D, 1);
WRITE(H2D, 0);
H1E_PWM = pwm;
H2E_PWM = pwm;
break;
case 2:
WRITE(H1D, 1);
WRITE(H2D, 0);
H1E_PWM = pwm;
H2E_PWM = 0;
break;
case 3:
WRITE(H1D, 1);
WRITE(H2D, 1);
H1E_PWM = pwm;
H2E_PWM = pwm;
break;
case 4:
WRITE(H1D, 1);
WRITE(H2D, 1);
H1E_PWM = 0;
H2E_PWM = pwm;
break;
case 5:
WRITE(H1D, 0);
WRITE(H2D, 1);
H1E_PWM = pwm;
H2E_PWM = pwm;
break;
case 6:
WRITE(H1D, 0);
WRITE(H2D, 1);
H1E_PWM = pwm;
H2E_PWM = 0;
break;
case 7:
WRITE(H1D, 0);
WRITE(H2D, 0);
H1E_PWM = pwm;
H2E_PWM = pwm;
break;
}
}
}
void init(void) {
// set up watchdog
wd_init();
// setup analog reading
analog_init();
// set up serial
intercom_init();
// set up inputs and outputs
io_init();
// set up extruder motor driver
motor_init();
// enable interrupts
sei();
// reset watchdog
wd_reset();
}
int main (void)
{
static uint8_t i;
static uint16_t raw_temp;
init();
enable_heater();
start_send();
// main loop
for (;;)
{
wd_reset();
//Read motor PWM
motor_pwm = analog_read(TRIM_POT_CHANNEL) >> 2;
//Read current temperature
raw_temp = analog_read(TEMP_PIN_CHANNEL);
//Calculate real temperature based on lookup table
for (i = 1; i < NUMTEMPS; i++) {
if (temptable[i][0] > raw_temp) {
raw_temp = temptable[i][1] +
(temptable[i][0] - raw_temp) * (temptable[i-1][1] - temptable[i][1]) / (temptable[i][0] - temptable[i-1][0]);
break;
}
}
//Clamp for overflows
if (i == NUMTEMPS) raw_temp = temptable[NUMTEMPS-1][1];
if (raw_temp > 255) raw_temp = 255;
//Update the intercom values
update_send_cmd(raw_temp);
HEATER_PWM = get_read_cmd();
}
}

220
extruder/intercom.c Normal file
View File

@ -0,0 +1,220 @@
#ifdef GEN3
#include "intercom.h"
#include <avr/interrupt.h>
#include "config.h"
#include "delay.h"
#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)
/*
Defines a super simple intercom interface using the RS485 modules
Host will say: START1 START2 PWM_CMD PWM_CHK
Extruder will reply: START1 START2 TMP_CMD TMP_CHK
CHK = 255-CMD, if they match do the work, if not, ignore this packet
in a loop
*/
#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;
void intercom_init(void)
{
#ifdef HOST
#if INTERCOM_BAUD > 38401
UCSR1A = MASK(U2X1);
UBRR1 = (((F_CPU / 8) / INTERCOM_BAUD) - 0.5);
#else
UCSR1A = 0;
UBRR1 = (((F_CPU / 16) / INTERCOM_BAUD) - 0.5);
#endif
UCSR1B = MASK(RXEN1) | MASK(TXEN1);
UCSR1C = MASK(UCSZ11) | MASK(UCSZ10);
UCSR1B |= MASK(RXCIE1) | MASK(TXCIE1);
#else
#if INTERCOM_BAUD > 38401
UCSR0A = MASK(U2X0);
UBRR0 = (((F_CPU / 8) / INTERCOM_BAUD) - 0.5);
#else
UCSR0A = 0;
UBRR0 = (((F_CPU / 16) / INTERCOM_BAUD) - 0.5);
#endif
UCSR0B = MASK(RXEN0) | MASK(TXEN0);
UCSR0C = MASK(UCSZ01) | MASK(UCSZ00);
UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0);
#endif
}
void update_send_cmd(uint8_t new_send_cmd) {
send_cmd = new_send_cmd;
}
uint8_t get_read_cmd(void) {
return read_cmd;
}
static void write_byte(uint8_t val) {
#ifdef HOST
UDR1 = val;
#else
UDR0 = val;
#endif
}
void start_send(void) {
state = SEND_START1;
enable_transmit();
delay_us(15);
//Enable interrupts so we can send next characters
#ifdef HOST
UCSR1B |= MASK(UDRIE1);
#else
UCSR0B |= MASK(UDRIE0);
#endif
}
static void finish_send(void) {
state = READ_START1;
disable_transmit();
}
/*
Interrupts, UART 0 for mendel
*/
#ifdef HOST
ISR(USART1_RX_vect)
#else
ISR(USART_RX_vect)
#endif
{
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
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
}
}
#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;
}
}
#endif /* GEN3 */

17
extruder/intercom.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef _INTERCOM_H
#define _INTERCOM_H
#include <stdint.h>
// initialise serial subsystem
void intercom_init(void);
//Update the message we are sending over intercom
void update_send_cmd(uint8_t new_send_cmd);
void start_send(void);
//Read the message we are receiving over intercom
uint8_t get_read_cmd(void);
#endif /* _INTERCOM_H */

1
extruder/watchdog.c Symbolic link
View File

@ -0,0 +1 @@
../watchdog.c

1
extruder/watchdog.h Symbolic link
View File

@ -0,0 +1 @@
../watchdog.h

View File

@ -192,11 +192,9 @@ void gcode_parse_char(uint8_t c) {
// 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))
next_target.S = decfloat_to_int(&read_digit, 4, 1);
#ifdef HEATER_PIN
// 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))
next_target.S = decfloat_to_int(&read_digit, PID_SCALE, 1);
#endif
else
next_target.S = decfloat_to_int(&read_digit, 1, 1);
if (debug_flags & DEBUG_ECHO)

View File

@ -199,7 +199,6 @@ void process_gcode_command() {
case 104:
temp_set(next_target.P, next_target.S);
if (next_target.S) {
enable_heater();
power_on();
}
else {
@ -213,15 +212,15 @@ void process_gcode_command() {
break;
// M106- fan on
#ifdef FAN_PIN
#if NUM_HEATERS > 1
case 106:
enable_fan();
heater_set(1, 255);
break;
// M107- fan off
case 107:
disable_fan();
heater_set(1, 0);
break;
#endif
#endif
// M109- set temp and wait
case 109:
@ -262,7 +261,7 @@ void process_gcode_command() {
serial_writestr_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 HEATER_COUNT:1\n"));
break;
#ifdef HEATER_PIN
#if NUM_HEATERS > 0
// M130- heater P factor
case 130:
if (next_target.seen_S)
@ -291,7 +290,7 @@ void process_gcode_command() {
case 134:
heater_save_settings();
break;
#endif /* HEATER_PIN */
#endif /* NUM_HEATERS > 0 */
// M190- power on
case 190:

View File

@ -47,8 +47,18 @@ typedef struct {
EE_factor EEMEM EE_factors[NUM_HEATERS];
void heater_init() {
// read factors from eeprom
#if NUM_HEATERS > 0
uint8_t i;
// setup pins
for (i = 0; i < NUM_HEATERS; i++) {
*(heaters[i].heater_port) &= ~heaters[i].heater_pin;
// DDR is always 1 address below PORT. ugly code but saves ram and an extra field in heaters[] which will never be used anywhere but here
*((volatile uint8_t *) (heaters[i].heater_port - 1)) |= heaters[i].heater_pin;
if (heaters[i].heater_pwm)
*heaters[i].heater_pwm = 0;
}
// read factors from eeprom
for (i = 0; i < NUM_HEATERS; i++) {
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);
@ -62,6 +72,7 @@ void heater_init() {
heaters_pid[i].i_limit = DEFAULT_I_LIMIT;
}
}
#endif
}
void heater_save_settings() {
@ -121,6 +132,7 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) {
}
void heater_set(uint8_t index, uint8_t value) {
#if NUM_HEATERS > 0
if (heaters[index].heater_pwm) {
*heaters[index].heater_pwm = value;
}
@ -130,6 +142,7 @@ void heater_set(uint8_t index, uint8_t value) {
else
*heaters[index].heater_port &= ~MASK(heaters[index].heater_pin);
}
#endif
}
void pid_set_p(uint8_t index, int32_t p) {

1
intercom.c Symbolic link
View File

@ -0,0 +1 @@
extruder/intercom.c

1
intercom.h Symbolic link
View File

@ -0,0 +1 @@
extruder/intercom.h

View File

@ -46,28 +46,18 @@ void io_init(void) {
WRITE(E_STEP_PIN, 0); SET_OUTPUT(E_STEP_PIN);
WRITE(E_DIR_PIN, 0); SET_OUTPUT(E_DIR_PIN);
#ifdef HEATER_PIN
WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN);
#endif
// setup PWM timer: fast PWM, no prescaler
TCCR0A = MASK(WGM01) | MASK(WGM00);
TCCR0B = MASK(CS00);
TIMSK0 = 0;
OCR0A = 0;
OCR0B = 255;
#ifdef FAN_PIN
WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN);
#endif
#if defined(HEATER_PWM) || defined(FAN_PWM)
// setup PWM timer: fast PWM, no prescaler
TCCR0A = MASK(WGM01) | MASK(WGM00);
TCCR0B = MASK(CS00);
TIMSK0 = 0;
OCR0A = 0;
OCR0B = 255;
TCCR2A = MASK(WGM21) | MASK(WGM20);
TCCR2B = MASK(CS20);
TIMSK2 = 0;
OCR2A = 0;
OCR2B = 0;
#endif
TCCR2A = MASK(WGM21) | MASK(WGM20);
TCCR2B = MASK(CS20);
TIMSK2 = 0;
OCR2A = 0;
OCR2B = 0;
#ifdef STEPPER_ENABLE_PIN
power_off();
@ -102,7 +92,10 @@ void init(void) {
// start up analog read interrupt loop, if anything uses analog as determined by ANALOG_MASK in your config.h
analog_init();
// set up temperature inputs
temp_init();
// enable interrupts
sei();
@ -114,12 +107,14 @@ void init(void) {
}
void clock_250ms(void) {
void clock_10ms(void) {
// reset watchdog
wd_reset();
temp_tick();
}
void clock_250ms(void) {
if (steptimeout > (30 * 4)) {
power_off();
}
@ -156,6 +151,10 @@ int main (void)
gcode_parse_char(c);
}
ifclock(CLOCK_FLAG_10MS) {
clock_10ms();
}
ifclock(CLOCK_FLAG_250MS) {
clock_250ms();
}

63
temp.c
View File

@ -9,11 +9,17 @@
#include "debug.h"
#include "sersendf.h"
#include "heater.h"
#ifdef GEN3
#include "intercom.h"
#endif
typedef enum {
TT_THERMISTOR,
TT_MAX6675,
TT_AD595
#ifdef GEN3
, TT_INTERCOM
#endif
} temp_types;
typedef enum {
@ -71,6 +77,38 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = {
#include "analog.h"
#endif
void temp_init() {
uint8_t i;
for (i = 0; i < NUM_TEMP_SENSORS; i++) {
switch(temp_sensors[i].temp_type) {
#ifdef TEMP_MAX6675
// initialised when read
/* case TT_MAX6675:
break;*/
#endif
#ifdef TEMP_THERMISTOR
// handled by analog_init()
/* case TT_THERMISTOR:
break;*/
#endif
#ifdef TEMP_AD595
// handled by analog_init()
/* case TT_AD595:
break;*/
#endif
#ifdef GEN3
case TT_INTERCOM:
intercom_init();
update_send_cmd(0);
break;
#endif
}
}
}
void temp_sensor_tick() {
uint8_t i = 0, all_within_range = 1;
for (; i < NUM_TEMP_SENSORS; i++) {
@ -87,9 +125,9 @@ void temp_sensor_tick() {
#ifdef TEMP_MAX6675
case TT_MAX6675:
#ifdef PRR
PRR &= ~MASK(PRSPI);
PRR &= ~MASK(PRSPI);
#elif defined PRR0
PRR0 &= ~MASK(PRSPI);
PRR0 &= ~MASK(PRSPI);
#endif
SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);
@ -127,7 +165,7 @@ void temp_sensor_tick() {
}
}
// FIXME: placeholder number
// this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms
temp_sensors_runtime[i].next_read_time = 25;
break;
@ -152,7 +190,6 @@ void temp_sensor_tick() {
if (j == NUMTEMPS)
temp = temptable[NUMTEMPS-1][1];
// FIXME: placeholder number
temp_sensors_runtime[i].next_read_time = 0;
break;
@ -166,11 +203,21 @@ void temp_sensor_tick() {
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
temp = (temp * 500L) >> 8;
// FIXME: placeholder number
temp_sensors[i].next_read_time = 0;
temp_sensors_runtime[i].next_read_time = 0;
break;
#endif /* TEMP_AD595 */
#ifdef GEN3
case TT_INTERCOM:
temp = get_read_cmd() << 2;
start_send();
temp_sensors_runtime[i].next_read_time = 0;
break;
#endif /* GEN3 */
}
temp_sensors_runtime[i].last_read_temp = temp;
@ -202,6 +249,10 @@ uint8_t temp_achieved() {
void temp_set(uint8_t index, uint16_t temperature) {
temp_sensors_runtime[index].target_temp = temperature;
temp_sensors_runtime[index].temp_residency = 0;
#ifdef GEN3
if (temp_sensors[index].temp_type == TT_INTERCOM)
update_send_cmd(temperature >> 2);
#endif
}
void temp_print(uint8_t index) {

2
temp.h
View File

@ -13,6 +13,8 @@ we still need to specify which analog pins we use in machine.h for the analog se
#define temp_tick temp_sensor_tick
void temp_init(void);
void temp_sensor_tick(void);
uint8_t temp_achieved(void);

24
timer.c
View File

@ -6,6 +6,7 @@
volatile uint32_t next_step_time;
uint8_t clock_counter_10ms = 0;
uint8_t clock_counter_250ms = 0;
uint8_t clock_counter_1s = 0;
volatile uint8_t clock_flag = 0;
@ -30,14 +31,21 @@ ISR(TIMER1_CAPT_vect) {
/*
clock stuff
*/
clock_counter_250ms += (TICK_TIME / (F_CPU / 1000));
if (clock_counter_250ms >= 250) {
clock_counter_250ms -= 250;
clock_flag |= CLOCK_FLAG_250MS;
clock_counter_1s += 1;
if (clock_counter_1s >= 4) {
clock_counter_1s -= 4;
clock_flag |= CLOCK_FLAG_1S;
clock_counter_10ms += (TICK_TIME / (F_CPU / 1000));
if (clock_counter_10ms >= 10) {
clock_counter_10ms -= 10;
clock_flag |= CLOCK_FLAG_10MS;
clock_counter_250ms += 10;
if (clock_counter_250ms >= 250) {
clock_counter_250ms -= 250;
clock_flag |= CLOCK_FLAG_250MS;
clock_counter_1s += 1;
if (clock_counter_1s >= 4) {
clock_counter_1s -= 4;
clock_flag |= CLOCK_FLAG_1S;
}
}
}
}

View File

@ -13,8 +13,9 @@ clock stuff
*/
extern volatile uint8_t clock_flag;
#define CLOCK_FLAG_250MS 1
#define CLOCK_FLAG_1S 2
#define CLOCK_FLAG_10MS 1
#define CLOCK_FLAG_250MS 2
#define CLOCK_FLAG_1S 4
#define ifclock(F) for (;clock_flag & (F);clock_flag &= ~(F))
/*