// Yep, this is actually -*- c++ -*- // Sanguino G-code Interpreter // Arduino v1.0 by Mike Ellery - initial software (mellery@gmail.com) // v1.1 by Zach Hoeken - cleaned up and did lots of tweaks (hoeken@gmail.com) // v1.2 by Chris Meighan - cleanup / G2&G3 support (cmeighan@gmail.com) // v1.3 by Zach Hoeken - added thermocouple support and multi-sample temp readings. (hoeken@gmail.com) // Sanguino v1.4 by Adrian Bowyer - added the Sanguino; extensive mods... (a.bowyer@bath.ac.uk) // Sanguino v1.5 by Adrian Bowyer - implemented 4D Bressenham XYZ+ stepper control... (a.bowyer@bath.ac.uk) // Sanguino v1.6 by Adrian Bowyer - implemented RS485 extruders #ifndef __AVR_ATmega644P__ #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. #endif #include #include //#include #include "WProgram.h" #include "vectors.h" #include "parameters.h" #include "intercom.h" #include "pins.h" #include "extruder.h" #include "cartesian_dda.h" // Maintain a list of extruders... extruder* ex[EXTRUDER_COUNT]; byte extruder_in_use = 0; // Text placed in this (terminated with 0) will be transmitted back to the host // along with the next G Code acknowledgement. char debugstring[20]; #if MOTHERBOARD < 2 // TODO: For some reason, if you declare the following two in the order ex0 ex1 then // ex0 won't drive its stepper. They seem fine this way round though. But that's got // to be a bug. #if EXTRUDER_COUNT == 2 static extruder ex1(EXTRUDER_1_MOTOR_DIR_PIN, EXTRUDER_1_MOTOR_SPEED_PIN , EXTRUDER_1_HEATER_PIN, EXTRUDER_1_FAN_PIN, EXTRUDER_1_TEMPERATURE_PIN, EXTRUDER_1_VALVE_DIR_PIN, EXTRUDER_1_VALVE_ENABLE_PIN, EXTRUDER_1_STEP_ENABLE_PIN); #endif static extruder ex0(EXTRUDER_0_MOTOR_DIR_PIN, EXTRUDER_0_MOTOR_SPEED_PIN , EXTRUDER_0_HEATER_PIN, EXTRUDER_0_FAN_PIN, EXTRUDER_0_TEMPERATURE_PIN, EXTRUDER_0_VALVE_DIR_PIN, EXTRUDER_0_VALVE_ENABLE_PIN, EXTRUDER_0_STEP_ENABLE_PIN); #else #if EXTRUDER_COUNT == 2 static extruder ex1(E1_NAME); #endif static extruder ex0(E0_NAME); intercom talker; #endif // Each entry in the buffer is an instance of cartesian_dda. cartesian_dda* cdda[BUFFER_SIZE]; static cartesian_dda cdda0; static cartesian_dda cdda1; static cartesian_dda cdda2; static cartesian_dda cdda3; volatile byte head; volatile byte tail; unsigned char interruptBlink; // Where the machine is from the point of view of the command stream FloatPoint where_i_am; // Our interrupt function SIGNAL(SIG_OUTPUT_COMPARE1A) { disableTimerInterrupt(); interruptBlink++; if(interruptBlink & 0x80) digitalWrite(DEBUG_PIN, 1); else digitalWrite(DEBUG_PIN, 0); if(cdda[tail]->active()) cdda[tail]->dda_step(); else dQMove(); enableTimerInterrupt(); } void setup() { disableTimerInterrupt(); setupTimerInterrupt(); interruptBlink = 0; pinMode(DEBUG_PIN, OUTPUT); debugstring[0] = 0; ex[0] = &ex0; #if EXTRUDER_COUNT == 2 ex[1] = &ex1; #endif extruder_in_use = 0; head = 0; tail = 0; cdda[0] = &cdda0; cdda[1] = &cdda1; cdda[2] = &cdda2; cdda[3] = &cdda3; //setExtruder(); init_process_string(); where_i_am.x = 0.0; where_i_am.y = 0.0; where_i_am.z = 0.0; where_i_am.e = 0.0; where_i_am.f = SLOW_XY_FEEDRATE; Serial.begin(HOST_BAUD); Serial.println("start"); #if MOTHERBOARD > 1 rs485Interface.begin(RS485_BAUD); #endif setTimer(DEFAULT_TICK); enableTimerInterrupt(); } //long count = 0; //int ct1 = 0; void loop() { manage_all_extruders(); get_and_do_command(); #if MOTHERBOARD > 1 talker.tick(); #endif /* count++; if(count > 1000) { ct1++; ex[0]->step(); if(!ex[0]->ping()) { Serial.print(ct1); Serial.println(debugstring); debugstring[0] = 0; } count = 0; } */ } //****************************************************************************************** // The move buffer inline bool qFull() { if(tail == 0) return head == (BUFFER_SIZE - 1); else return head == (tail - 1); } inline bool qEmpty() { return tail == head && !cdda[tail]->active(); } inline void qMove(const FloatPoint& p) { while(qFull()) delay(WAITING_DELAY); byte h = head; h++; if(h >= BUFFER_SIZE) h = 0; cdda[h]->set_target(p); head = h; } inline void dQMove() { if(qEmpty()) return; byte t = tail; t++; if(t >= BUFFER_SIZE) t = 0; cdda[t]->dda_start(); tail = t; } inline void setUnits(bool u) { for(byte i = 0; i < BUFFER_SIZE; i++) cdda[i]->set_units(u); } inline void setPosition(const FloatPoint& p) { where_i_am = p; } //****************************************************************************************** // Interrupt functions void setupTimerInterrupt() { //clear the registers TCCR1A = 0; TCCR1B = 0; TCCR1C = 0; TIMSK1 = 0; //waveform generation = 0100 = CTC TCCR1B &= ~(1<