diff --git a/Pins.h b/Pins.h new file mode 100644 index 0000000..82441da --- /dev/null +++ b/Pins.h @@ -0,0 +1,17 @@ +#ifndef PINS_H__ +#define PINS_H__ + +// Load Pins_.h + +#if !defined(PLATFORM) +#define PLATFORM duet +#endif + +#define P_EXPAND(x) x +#define P_CONCAT(x,y) P_EXPAND(x)y +#define P_STR(x) #x +#define P_XSTR(x) P_STR(x) +#define P_INCLUDE_FILE P_XSTR(P_CONCAT(Pins_,P_CONCAT(PLATFORM,.h))) +#include P_INCLUDE_FILE + +#endif // PINS_H__ diff --git a/Roland.cpp b/Roland.cpp new file mode 100644 index 0000000..ed787b6 --- /dev/null +++ b/Roland.cpp @@ -0,0 +1,268 @@ +// This class allows the RepRap firmware to transmit commands to a Roland mill +// See: http://www.rolanddg.com/product/3d/3d/mdx-20_15/mdx-20_15.html +// http://altlab.org/d/content/m/pangelo/ideas/rml_command_guide_en_v100.pdf + +#include "RepRapFirmware.h" + +Roland::Roland(Platform* p) +{ + platform = p; +} + + +void Roland::Init() +{ + pinMode(ROLAND_RTS_PIN, OUTPUT); + pinMode(ROLAND_CTS_PIN, INPUT); + digitalWrite(ROLAND_RTS_PIN, HIGH); + Serial1.begin(ROLAND_BAUD); //For serial comms to mill + + sBuffer = new StringRef(buffer, ARRAY_SIZE(buffer)); + sBuffer->Clear(); + + bufferPointer = 0; + Zero(true); + longWait = platform->Time(); + active = false; +} + +void Roland::Spin() +{ + if (!Active()) + { + platform->ClassReport(longWait); + return; + } + + // 'U' is 01010101 in binary (nice for an oscilloscope...) + + //Serial1.write('U'); + //Serial1.flush(); + //return; + + // Are we sending something to the Roland? + + if (Busy()) // Busy means we are sending something + { + if (digitalRead(ROLAND_CTS_PIN)) + { + platform->ClassReport(longWait); + return; + } + + Serial1.write(buffer[bufferPointer]); + Serial1.flush(); + bufferPointer++; + } + else // Not sending. + { + // Finished talking to the Roland + + sBuffer->Clear(); + bufferPointer = 0; + + // Anything new to do? + + EndstopChecks endStopsToCheck; + uint8_t moveType; + FilePosition filePos; + if (reprap.GetGCodes()->ReadMove(move, endStopsToCheck, moveType, filePos)) + { + move[AXES] = move[DRIVES]; // Roland doesn't have extruders etc. + ProcessMove(); + } + } + + platform->ClassReport(longWait); +} + +void Roland::Zero(bool feed) +{ + size_t lim = feed ? AXES + 1 : AXES; + for(size_t axis = 0; axis < lim; axis++) + { + move[axis] = 0.0; + coordinates[axis] = 0.0; + oldCoordinates[axis] = 0.0; + offset[axis] = 0.0; + } + + if (reprap.Debug(moduleGcodes)) + { + platform->Message(HOST_MESSAGE, "Roland zero\n"); + } +} + +bool Roland::Busy() +{ + return buffer[bufferPointer] != 0; +} + +bool Roland::ProcessHome() +{ + if (Busy()) + { + return false; + } + + sBuffer->copy("H;\n"); + Zero(false); + if (reprap.Debug(moduleGcodes)) + { + platform->MessageF(HOST_MESSAGE, "Roland home: %s", buffer); + } + return true; +} + +bool Roland::ProcessDwell(long milliseconds) +{ + if (Busy()) + { + return false; + } + + sBuffer->printf("W%ld;", milliseconds); + sBuffer->catf("Z %.4f,%.4f,%.4f;", oldCoordinates[0], oldCoordinates[1], oldCoordinates[2]); + sBuffer->cat("W0;\n"); + if (reprap.Debug(moduleGcodes)) + { + platform->MessageF(HOST_MESSAGE, "Roland dwell: %s", buffer); + } + return true; +} + +bool Roland::ProcessG92(float v, size_t axis) +{ + if (Busy()) + { + return false; + } + + move[axis] = v; + coordinates[axis] = move[axis]*ROLAND_FACTOR + offset[axis]; + offset[axis] = oldCoordinates[axis]; + oldCoordinates[axis] = coordinates[axis]; + if (reprap.Debug(moduleGcodes)) + { + platform->Message(HOST_MESSAGE, "Roland G92\n"); + } + return true; +} + +bool Roland::ProcessSpindle(float rpm) +{ + if (Busy()) + { + return false; + } + + if (rpm < 0.5) // Stop + { + sBuffer->printf("!MC 0;\n"); + } + else // Go + { + sBuffer->printf("!RC%ld;!MC 1;\n", (long)(rpm + 100.0)); + } + + if (reprap.Debug(moduleGcodes)) + { + platform->MessageF(HOST_MESSAGE, "Roland spindle: %s", buffer); + } + return true; + +} + +void Roland::GetCurrentRolandPosition(float moveBuffer[]) +{ + for(size_t axis = 0; axis < AXES; axis++) + { + moveBuffer[axis] = move[axis]; + } + + for(size_t axis = AXES; axis < DRIVES; axis++) + { + moveBuffer[axis] = 0.0; + } + + moveBuffer[DRIVES] = move[AXES]; +} + +void Roland::ProcessMove() +{ + for(size_t axis = 0; axis < AXES; axis++) + { + coordinates[axis] = move[axis] * ROLAND_FACTOR + offset[axis]; + } + coordinates[AXES] = move[AXES]; + + // Start with feedrate; For some reason the Roland won't accept more than 4 d.p. + + sBuffer->printf("V %.4f;", coordinates[AXES]); + + // Now the move + + sBuffer->catf("Z %.4f,%.4f,%.4f;\n", coordinates[0], coordinates[1], coordinates[2]); + + for(size_t axis = 0; axis <= AXES; axis++) + { + oldCoordinates[axis] = coordinates[axis]; + } + + if (reprap.Debug(moduleGcodes)) + { + platform->MessageF(HOST_MESSAGE, "Roland move: %s", buffer); + } +} + + +bool Roland::RawWrite(const char* s) +{ + if (Busy()) + { + return false; + } + + sBuffer->copy(s); + sBuffer->cat("\n"); + + if (reprap.Debug(moduleGcodes)) + { + platform->MessageF(HOST_MESSAGE, "Roland rawwrite: %s", buffer); + } + return true; +} + +bool Roland::Active() +{ + return active; +} + +void Roland::Activate() +{ + digitalWrite(ROLAND_RTS_PIN, LOW); + active = true; + + if (reprap.Debug(moduleGcodes)) + { + platform->Message(HOST_MESSAGE, "Roland started\n"); + } +} + +bool Roland::Deactivate() +{ + if (Busy()) + { + return false; + } + + digitalWrite(ROLAND_RTS_PIN, HIGH); + active = false; + if (reprap.Debug(moduleGcodes)) + { + platform->Message(HOST_MESSAGE, "Roland stopped\n"); + } + return true; +} + +// vim: ts=4:sw=4 diff --git a/Roland.h b/Roland.h new file mode 100644 index 0000000..62a05e0 --- /dev/null +++ b/Roland.h @@ -0,0 +1,78 @@ +/**************************************************************************************************** + +RepRapFirmware - Roland + +This class can interface with a Roland mill (e.g. Roland MDX-20/15) and allows the underlying hardware +to act as a G-Code proxy, which translates G-Codes to internal Roland commands. + +----------------------------------------------------------------------------------------------------- + +Version 0.1 + +Created on: Oct 14, 2015 + +Adrian Bowyer + +Licence: GPL + +****************************************************************************************************/ + +#ifndef ROLAND_H +#define ROLAND_H + +// This class allows the RepRap firmware to transmit commands to a Roland mill +// See: http://www.rolanddg.com/product/3d/3d/mdx-20_15/mdx-20_15.html +// http://altlab.org/d/content/m/pangelo/ideas/rml_command_guide_en_v100.pdf + +#include "Arduino.h" +#include "Platform.h" + +const float ROLAND_FACTOR = (1.016088061*100.0/2.54); // Roland units are 0.001" +const int8_t ROLAND_RTS_PIN = 75; // Expansion pin 29, SPI0_MOSI +const int8_t ROLAND_CTS_PIN = 76; // Expansion pin 28, SPI0_SPCK +const size_t ROLAND_BUFFER_SIZE = 50; + +// TX and RX +// Expansion pin 11, PA13_TXD1 +// Expansion pin 12, PA12_RXD1 + +const uint16_t ROLAND_BAUD = 9600; + + +class Roland +{ + public: + Roland(Platform* p); + void Init(); + void Spin(); + bool ProcessHome(); + bool ProcessDwell(long milliseconds); + bool ProcessG92(float v, size_t axis); + bool ProcessSpindle(float rpm); + bool RawWrite(const char* s); + void GetCurrentRolandPosition(float moveBuffer[]); + bool Active(); + void Activate(); + bool Deactivate(); + + private: + void ProcessMove(); + void Zero(bool feed); + bool Busy(); + + Platform* platform; + float longWait; + + float move[DRIVES+1]; + float coordinates[AXES+1]; + float oldCoordinates[AXES+1]; + float offset[AXES+1]; + char buffer[ROLAND_BUFFER_SIZE]; + int bufferPointer; + StringRef *sBuffer; + bool active; +}; + +#endif + +// vim: ts=4:sw=4