diff --git a/src/atcore.cpp b/src/atcore.cpp index b94c3b9..489a5b4 100644 --- a/src/atcore.cpp +++ b/src/atcore.cpp @@ -1,617 +1,626 @@ /* AtCore Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira Lays Rodrigues This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include #include #include #include #include #include #include "atcore.h" #include "atcore_version.h" #include "seriallayer.h" #include "gcodecommands.h" #include "printthread.h" #include "atcore_default_folders.h" Q_LOGGING_CATEGORY(ATCORE_PLUGIN, "org.kde.atelier.core.plugin") Q_LOGGING_CATEGORY(ATCORE_CORE, "org.kde.atelier.core") /** * @brief The AtCorePrivate struct */ struct AtCorePrivate { IFirmware *firmwarePlugin = nullptr;//!< @param firmwarePlugin: pointer to firmware plugin SerialLayer *serial = nullptr; //!< @param serial: pointer to the serial layer QPluginLoader pluginLoader; //!< @param pluginLoader: QPluginLoader QDir pluginsDir; //!< @param pluginsDir: Directory where plugins were found QMap plugins; //!< @param plugins: Map of plugins name / path QByteArray lastMessage; //!< @param lastMessage: lastMessage from the printer int extruderCount = 1; //!< @param extruderCount: extruder count Temperature temperature; //!< @param temperature: Temperature object QStringList commandQueue; //!< @param commandQueue: the list of commands to send to the printer bool ready = false; //!< @param ready: True if printer is ready for a command QTimer *tempTimer = nullptr; //!< @param tempTimer: timer connected to the checkTemperature function float percentage; //!< @param percentage: print job percent QByteArray posString; //!< @param posString: stored string from last M114 return AtCore::STATES printerState; //!< @param printerState: State of the Printer QStringList serialPorts; //!< @param seralPorts: Detected serial Ports QTimer *serialTimer = nullptr; //!< @param serialTimer: Timer connected to locateSerialPorts }; AtCore::AtCore(QObject *parent) : QObject(parent), d(new AtCorePrivate) { qRegisterMetaType("AtCore::STATES"); setState(AtCore::DISCONNECTED); d->tempTimer = new QTimer(this); d->tempTimer->setInterval(5000); d->tempTimer->setSingleShot(false); QStringList pathList = AtCoreDirectories::pluginDir; pathList.append(QLibraryInfo::location(QLibraryInfo::PluginsPath) + QStringLiteral("/AtCore")); for (const auto &path : pathList) { qCDebug(ATCORE_PLUGIN) << "Lookin for plugins in " << path; if (QDir(path).exists()) { d->pluginsDir = QDir(path); qCDebug(ATCORE_PLUGIN) << "Valid path for plugins found !"; break; } } if (!d->pluginsDir.exists()) { qCritical() << "No valid path for plugin !"; } #if defined(Q_OS_WIN) || defined(Q_OS_MAC) d->pluginsDir = qApp->applicationDirPath() + QStringLiteral("/plugins"); #endif qCDebug(ATCORE_PLUGIN) << d->pluginsDir; findFirmwarePlugins(); setState(AtCore::DISCONNECTED); } QString AtCore::version() const { QString versionString = QString::fromLatin1(ATCORE_VERSION_STRING); #if defined GIT_REVISION if (!QStringLiteral(GIT_REVISION).isEmpty()) { versionString.append(QString::fromLatin1("-%1").arg(QStringLiteral(GIT_REVISION))); } #endif return versionString; } SerialLayer *AtCore::serial() const { return d->serial; } IFirmware *AtCore::firmwarePlugin() const { return d->firmwarePlugin; } void AtCore::close() { exit(0); } Temperature &AtCore::temperature() const { return d->temperature; } void AtCore::findFirmware(const QByteArray &message) { if (state() == AtCore::DISCONNECTED) { qWarning() << "Cant find firwmware, serial not connected !"; return; } if (state() == AtCore::CONNECTING) { if (message.contains("start")) { qCDebug(ATCORE_CORE) << "Waiting requestFirmware."; QTimer::singleShot(500, this, &AtCore::requestFirmware); return; } else if (message.contains("Grbl")) { loadFirmwarePlugin(QString::fromLatin1("grbl")); return; } else if (message.contains("Smoothie")) { loadFirmwarePlugin(QString::fromLatin1("smoothie")); return; } } qCDebug(ATCORE_CORE) << "Find Firmware Called" << message; if (!message.contains("FIRMWARE_NAME:")) { qCDebug(ATCORE_CORE) << "No firmware yet."; return; } qCDebug(ATCORE_CORE) << "Found firmware string, Looking for Firmware Name."; QString fwName = QString::fromLocal8Bit(message); fwName = fwName.split(QChar::fromLatin1(':')).at(1); if (fwName.indexOf(QChar::fromLatin1(' ')) == 0) { //remove leading space fwName.remove(0, 1); } if (fwName.contains(QChar::fromLatin1(' '))) { //check there is a space or dont' resize fwName.resize(fwName.indexOf(QChar::fromLatin1(' '))); } fwName = fwName.toLower().simplified(); if (fwName.contains(QChar::fromLatin1('_'))) { fwName.resize(fwName.indexOf(QChar::fromLatin1('_'))); } qCDebug(ATCORE_CORE) << "Firmware Name:" << fwName; if (message.contains("EXTRUDER_COUNT:")) { //this code is broken if more then 9 extruders are detected. since only one char is returned d->extruderCount = message.at(message.indexOf("EXTRUDER_COUNT:") + 15) - '0'; } qCDebug(ATCORE_CORE) << "Extruder Count:" << QString::number(extruderCount()); loadFirmwarePlugin(fwName); } void AtCore::loadFirmwarePlugin(const QString &fwName) { if (d->plugins.contains(fwName)) { d->pluginLoader.setFileName(d->plugins[fwName]); if (!d->pluginLoader.load()) { qCDebug(ATCORE_PLUGIN) << d->pluginLoader.errorString(); } else { qCDebug(ATCORE_PLUGIN) << "Loading plugin."; } d->firmwarePlugin = qobject_cast(d->pluginLoader.instance()); if (!firmwarePluginLoaded()) { qCDebug(ATCORE_PLUGIN) << "No plugin loaded."; qCDebug(ATCORE_PLUGIN) << "Looking plugin in folder:" << d->pluginsDir; setState(AtCore::CONNECTING); } else { qCDebug(ATCORE_PLUGIN) << "Connected to" << firmwarePlugin()->name(); firmwarePlugin()->init(this); disconnect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::newMessage); connect(firmwarePlugin(), &IFirmware::readyForCommand, this, &AtCore::processQueue); d->ready = true; // ready on new firmware load if (firmwarePlugin()->name() != QStringLiteral("Grbl")) { connect(d->tempTimer, &QTimer::timeout, this, &AtCore::checkTemperature); d->tempTimer->start(); } setState(IDLE); } } else { qCDebug(ATCORE_CORE) << "No Firmware Loaded"; } } bool AtCore::initSerial(const QString &port, int baud) { d->serial = new SerialLayer(port, baud); if (serialInitialized()) { setState(AtCore::CONNECTING); connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); return true; } else { qCDebug(ATCORE_CORE) << "Failed to open device."; return false; } } bool AtCore::serialInitialized() const { if (!d->serial) { return false; } return d->serial->isOpen(); } QString AtCore::connectedPort() const { return serial()->portName(); } QStringList AtCore::serialPorts() const { QStringList ports; QList serialPortInfoList = QSerialPortInfo::availablePorts(); if (!serialPortInfoList.isEmpty()) { foreach (const QSerialPortInfo &serialPortInfo, serialPortInfoList) { #ifdef Q_OS_MAC //Mac OS has callout serial ports starting with cu. They can only receive data and it's necessary to filter them out if (!serialPortInfo.portName().startsWith(QStringLiteral("cu."), Qt::CaseInsensitive)) { ports.append(serialPortInfo.portName()); } #else ports.append(serialPortInfo.portName()); #endif } } return ports; } void AtCore::locateSerialPort() { QStringList ports = serialPorts(); if (d->serialPorts != ports) { d->serialPorts = ports; emit portsChanged(d->serialPorts); } } quint16 AtCore::serialTimerInterval() const { if (d->serialTimer != nullptr) { return d->serialTimer->interval(); } return 0; } void AtCore::setSerialTimerInterval(const quint16 &newTime) { if (newTime == 0) { if (d->serialTimer) { disconnect(d->serialTimer, &QTimer::timeout, this, &AtCore::locateSerialPort); delete d->serialTimer; } return; } if (!d->serialTimer) { d->serialTimer = new QTimer(); connect(d->serialTimer, &QTimer::timeout, this, &AtCore::locateSerialPort); } d->serialTimer->start(newTime); } void AtCore::newMessage(const QByteArray &message) { d->lastMessage = message; if (message.startsWith(QString::fromLatin1("X:").toLocal8Bit())) { d->posString = message; d->posString.resize(d->posString.indexOf('E')); d->posString.replace(':', ""); } //Check if have temperature info and decode it if (d->lastMessage.contains("T:") || d->lastMessage.contains("B:")) { temperature().decodeTemp(message); } emit(receivedMessage(d->lastMessage)); } void AtCore::setRelativePosition() { pushCommand(GCode::toCommand(GCode::G91)); } void AtCore::setAbsolutePosition() { pushCommand(GCode::toCommand(GCode::G90)); } float AtCore::percentagePrinted() const { return d->percentage; } void AtCore::print(const QString &fileName) { if (state() == AtCore::CONNECTING) { qCDebug(ATCORE_CORE) << "Load a firmware plugin to print."; return; } //START A THREAD AND CONNECT TO IT setState(AtCore::STARTPRINT); QThread *thread = new QThread(); PrintThread *printThread = new PrintThread(this, fileName); printThread->moveToThread(thread); connect(printThread, &PrintThread::printProgressChanged, this, &AtCore::printProgressChanged, Qt::QueuedConnection); connect(thread, &QThread::started, printThread, &PrintThread::start); connect(printThread, &PrintThread::finished, thread, &QThread::quit); connect(thread, &QThread::finished, printThread, &PrintThread::deleteLater); if (!thread->isRunning()) { thread->start(); } } void AtCore::pushCommand(const QString &comm) { d->commandQueue.append(comm); if (d->ready) { processQueue(); } } void AtCore::closeConnection() { if (serialInitialized()) { if (state() == AtCore::BUSY) { //we have to clean print if printing. setState(AtCore::STOP); } if (firmwarePluginLoaded()) { disconnect(firmwarePlugin(), &IFirmware::readyForCommand, this, &AtCore::processQueue); if (firmwarePlugin()->name() != QStringLiteral("Grbl")) { disconnect(d->tempTimer, &QTimer::timeout, this, &AtCore::checkTemperature); d->tempTimer->stop(); } } serial()->close(); setState(AtCore::DISCONNECTED); } } AtCore::STATES AtCore::state(void) { return d->printerState; } void AtCore::setState(AtCore::STATES state) { if (state != d->printerState) { qCDebug(ATCORE_CORE) << "Atcore state changed from [" \ << d->printerState << "] to [" << state << "]"; d->printerState = state; emit(stateChanged(d->printerState)); } } void AtCore::stop() { setState(AtCore::STOP); d->commandQueue.clear(); setExtruderTemp(0, 0); setBedTemp(0); home(AtCore::X); } void AtCore::emergencyStop() { if (state() == AtCore::BUSY) { setState(AtCore::STOP); } d->commandQueue.clear(); serial()->pushCommand(GCode::toCommand(GCode::M112).toLocal8Bit()); } void AtCore::requestFirmware() { if (serialInitialized()) { qCDebug(ATCORE_CORE) << "Sending " << GCode::toString(GCode::M115); serial()->pushCommand(GCode::toCommand(GCode::M115).toLocal8Bit()); } else { qCDebug(ATCORE_CORE) << "There is no open device to send commands"; } } bool AtCore::firmwarePluginLoaded() const { if (firmwarePlugin()) { return true; } else { return false; } } void AtCore::findFirmwarePlugins() { d->plugins.clear(); qCDebug(ATCORE_PLUGIN) << "plugin dir:" << d->pluginsDir; QStringList files = d->pluginsDir.entryList(QDir::Files); foreach (const QString &f, files) { QString file = f; #if defined(Q_OS_WIN) if (file.endsWith(QStringLiteral(".dll"))) #elif defined(Q_OS_MAC) if (file.endsWith(QStringLiteral(".dylib"))) #else if (file.endsWith(QStringLiteral(".so"))) #endif file = file.split(QChar::fromLatin1('.')).at(0); else { qCDebug(ATCORE_PLUGIN) << "File" << file << "not plugin."; continue; } qCDebug(ATCORE_CORE) << "Found plugin file" << f; if (file.startsWith(QStringLiteral("lib"))) { file = file.remove(QStringLiteral("lib")); } file = file.toLower().simplified(); QString pluginString; pluginString.append(d->pluginsDir.path()); pluginString.append(QChar::fromLatin1('/')); pluginString.append(f); d->plugins[file] = pluginString; qCDebug(ATCORE_CORE) << tr("plugins[%1]=%2").arg(file, pluginString); } } QStringList AtCore::availableFirmwarePlugins() const { return d->plugins.keys(); } void AtCore::detectFirmware() { connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); } void AtCore::pause(const QString &pauseActions) { pushCommand(GCode::toCommand(GCode::M114)); setState(AtCore::PAUSE); if (!pauseActions.isEmpty()) { QStringList temp = pauseActions.split(QChar::fromLatin1(',')); for (int i = 0; i < temp.length(); i++) { pushCommand(temp.at(i)); } } } void AtCore::resume() { pushCommand(GCode::toCommand(GCode::G0, QString::fromLatin1(d->posString))); setState(AtCore::BUSY); } /*~~~~~Control Slots ~~~~~~~~*/ void AtCore::home() { pushCommand(GCode::toCommand(GCode::G28)); } void AtCore::home(uchar axis) { QString args; if (axis & AtCore::X) { args.append(QStringLiteral("X0 ")); } if (axis & AtCore::Y) { args.append(QStringLiteral("Y0 ")); } if (axis & AtCore::Z) { args.append(QStringLiteral("Z0")); } pushCommand(GCode::toCommand(GCode::G28, args)); } void AtCore::setExtruderTemp(uint temp, uint extruder, bool andWait) { if (andWait) { pushCommand(GCode::toCommand(GCode::M109, QString::number(temp), QString::number(extruder))); } else { pushCommand(GCode::toCommand(GCode::M104, QString::number(extruder), QString::number(temp))); } temperature().setExtruderTargetTemperature(temp); } void AtCore::setBedTemp(uint temp, bool andWait) { if (andWait) { pushCommand(GCode::toCommand(GCode::M190, QString::number(temp))); } else { pushCommand(GCode::toCommand(GCode::M140, QString::number(temp))); } temperature().setBedTargetTemperature(temp); } void AtCore::setFanSpeed(uint speed, uint fanNumber) { pushCommand(GCode::toCommand(GCode::M106, QString::number(fanNumber), QString::number(speed))); } void AtCore::setPrinterSpeed(uint speed) { pushCommand(GCode::toCommand(GCode::M220, QString::number(speed))); } void AtCore::setFlowRate(uint speed) { pushCommand(GCode::toCommand(GCode::M221, QString::number(speed))); } void AtCore::move(AtCore::AXES axis, uint arg) { if (axis & AtCore::X) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("X %1").arg(QString::number(arg)))); } else if (axis & AtCore::Y) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("Y %1").arg(QString::number(arg)))); } else if (axis & AtCore::Z) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("Z %1").arg(QString::number(arg)))); } else if (axis & AtCore::E) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("E %1").arg(QString::number(arg)))); } } int AtCore::extruderCount() const { return d->extruderCount; } void AtCore::processQueue() { d->ready = true; if (d->commandQueue.isEmpty()) { return; } if (!serialInitialized()) { qCDebug(ATCORE_PLUGIN) << "Can't process queue ! Serial not initialized."; return; } QString text = d->commandQueue.takeAt(0); if (firmwarePluginLoaded()) { serial()->pushCommand(firmwarePlugin()->translate(text)); } else { serial()->pushCommand(text.toLocal8Bit()); } d->ready = false; } void AtCore::checkTemperature() { if (d->commandQueue.contains(GCode::toCommand(GCode::M105))) { return; } pushCommand(GCode::toCommand(GCode::M105)); } void AtCore::showMessage(const QString &message) { if (!message.isEmpty()) { pushCommand(GCode::toCommand((GCode::M117), message)); } } void AtCore::setUnits(AtCore::UNITS units) { switch (units) { case AtCore::METRIC: pushCommand(GCode::toCommand(GCode::G21)); break; case AtCore::IMPERIAL: pushCommand(GCode::toCommand(GCode::G20)); break; } } QStringList AtCore::portSpeeds() const { return serial()->validBaudRates(); } + +void AtCore::setIdleHold(uint delay) +{ + if (delay != 0) { + pushCommand(GCode::toCommand(GCode::M84, QString::number(delay))); + } else { + pushCommand(GCode::toCommand(GCode::M84)); + } +} diff --git a/src/atcore.h b/src/atcore.h index 6ccabaa..deeb809 100644 --- a/src/atcore.h +++ b/src/atcore.h @@ -1,429 +1,435 @@ /* AtCore Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira Lays Rodrigues This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #pragma once #include #include #include #include "ifirmware.h" #include "temperature.h" #include "atcore_export.h" class SerialLayer; class IFirmware; class QTime; struct AtCorePrivate; /** * @brief The AtCore class * aims to provides a high level interface for serial based gcode devices
* * General Workflow * - Connect to a serial port with initSerial() * - Auto detect the firmware with detectFirmware() * - Send commands to the device (pushCommand(),print(),...) * - AtCore::close() when you are all done. */ class ATCORE_EXPORT AtCore : public QObject { Q_OBJECT Q_PROPERTY(QString version READ version) Q_PROPERTY(QStringList availableFirmwarePlugins READ availableFirmwarePlugins) Q_PROPERTY(quint16 serialTimerInterval READ serialTimerInterval WRITE setSerialTimerInterval) Q_PROPERTY(QStringList serialPorts READ serialPorts NOTIFY portsChanged) Q_PROPERTY(QStringList portSpeeds READ portSpeeds) Q_PROPERTY(QString connectedPort READ connectedPort) Q_PROPERTY(AtCore::STATES state READ state WRITE setState NOTIFY stateChanged) public: /** * @brief STATES enum Possible states the printer can be in */ enum STATES { DISCONNECTED, //!< Not Connected to a printer, initial state CONNECTING, //! * @param port: the port to initialize * @param baud: the baud of the port * @return True is connection was successful * @sa serialPorts(),serial(),closeConnection() */ Q_INVOKABLE bool initSerial(const QString &port, int baud); /** * @brief Returns a list of valid baud speeds */ QStringList portSpeeds() const; /** * @brief Main access to the serialLayer * @return Current serialLayer * @sa initSerial(),serialPorts(),closeConnection() */ SerialLayer *serial() const; /** * @brief Close the current serial connection * @sa initSerial(),serial(),serialPorts(),AtCore::close() */ Q_INVOKABLE void closeConnection(); /** * @brief Main access to the loaded firmware plugin * @return IFirmware * to currently loaded plugin * @sa availableFirmwarePlugins(),loadFirmwarePlugin(),detectFirmware() */ Q_INVOKABLE IFirmware *firmwarePlugin() const; /** * @brief List of available firmware plugins * @sa loadFirmwarePlugin(),firmwarePlugin(),detectFirmware() */ QStringList availableFirmwarePlugins() const; /** * @brief Load A firmware plugin * @param fwName : name of the firmware * @sa firmwarePlugin(),availableFirmwarePlugins(),detectFirmware() */ Q_INVOKABLE void loadFirmwarePlugin(const QString &fwName); /** * @brief Attempt to autodetect the firmware of connect serial device * @sa loadFirmwarePlugin(),availableFirmwarePlugins(),firmwarePlugin() */ Q_INVOKABLE void detectFirmware(); /** * @brief Get Printer state * @return State of the printer * @sa setState(),stateChanged(),AtCore::STATES */ AtCore::STATES state(void); /** * @brief extruderCount * @return The number of detected Extruders Default is 1 */ int extruderCount() const; /** * @brief Return printed percentage * @sa printProgressChanged() */ float percentagePrinted() const; /** * @brief The temperature of the current hotend as told by the Firmware. */ Temperature &temperature() const; /** * @brief Return the amount of miliseconds the serialTimer is set to. 0 = Disabled */ quint16 serialTimerInterval() const; signals: /** * @brief Print job's precentage changed. * @param newProgress : Message * @sa percentagePrinted() */ void printProgressChanged(const float &newProgress); /** * @brief New message was received from the printer * @param message: Message that was received */ void receivedMessage(const QByteArray &message); /** * @brief The Printer's State Changed * @param newState : the new state of the printer * @sa setState(),state(),AtCore::STATES */ void stateChanged(AtCore::STATES newState); /** * @brief Available serialports Changed */ void portsChanged(QStringList); public slots: /** * @brief Set the printers state * @param state : printer state. * @sa state(),stateChanged(),AtCore::STATES */ void setState(AtCore::STATES state); /** * @brief Push a command into the command queue * * @param comm : Command */ void pushCommand(const QString &comm); /** * @brief Public Interface for printing a file * @param fileName: the gcode file to print. */ void print(const QString &fileName); /** * @brief Stop the Printer by empting the queue and aborting the print job (if running) * @sa emergencyStop(),pause(),resume() */ void stop(); /** * @brief stop the printer via the emergency stop Command (M112) * @sa stop(),pause(),resume() */ void emergencyStop(); /** * @brief pause an in process print job * * Sends M114 on pause to store the location where the head stoped. * This is known to cause problems on fake printers * @param pauseActions: Gcode to run after pausing commands are ',' separated * @sa resume(),stop(),emergencyStop() */ void pause(const QString &pauseActions); /** * @brief resume a paused print job. * After returning to location pause was triggered. * @sa pause(),stop(),emergencyStop() */ void resume(); /** * @brief Send home \p axis command * @param axis: the axis(es) to home (use X Y Z or any combo of) * @sa home(), move() */ void home(uchar axis); /** * @brief Send home all command * @sa home(uchar axis), move() */ void home(); /** * @brief Set extruder temperature * @param temp : new temperature * @param extruder : extruder number * @param andWait: True for heat and ignore commands untill temperature is reached */ void setExtruderTemp(uint temp = 0, uint extruder = 0, bool andWait = false); /** * @brief move an axis of the printer * @param axis the axis to move AXES (X Y Z E ) * @param arg the distance to move the axis or the place to move to depending on printer mode * @sa home(), home(uchar axis) */ void move(AtCore::AXES axis, uint arg); /** * @brief Set the bed temperature * @param temp : new temperature * @param andWait: True for heat and ignore commands untill temperature is reached * @sa setExtruderTemp() */ void setBedTemp(uint temp = 0, bool andWait = false); /** * @brief setFanSpeed set the fan speed * @param fanNumber: fan number * @param speed: new speed of the fan 0-100 */ void setFanSpeed(uint speed = 0, uint fanNumber = 0); /** * @brief Set printer to absolute position mode * @sa setRelativePosition() */ void setAbsolutePosition(); /** * @brief Set printer to relative position mode * @sa setAbsolutePosition() */ void setRelativePosition(); + /** + * @brief Disables idle hold of motors after a delay + * @param delay: Seconds until idle hold is released. 0= No delay + */ + void setIdleHold(uint delay = 0); + /** * @brief set the Printers speed * @param speed: speed in % (default is 100); */ void setPrinterSpeed(uint speed = 100); /** * @brief set extruder Flow rate * @param rate: flow rate in % (default is 100) */ void setFlowRate(uint rate = 100); /** * @brief close any open items. * You should call this on close events to force any stuck jobs to close * @sa closeConnection() */ void close(); /** * @brief showMessage push a message to the printers LCD * @param message: message to show on the LCD */ void showMessage(const QString &message); /** * @brief setUnits sets the measurement units do be used * @param units : the measurement units to use(METRIC / IMPERIAL) * @sa AtCore::UNITS */ void setUnits(AtCore::UNITS units); /** * @brief Set the time between checks for new serialPorts (0 is default) * @param newTime: Milliseconds between checks. 0 will Disable Checks. */ void setSerialTimerInterval(const quint16 &newTime); private slots: /** * @brief processQueue send commands from the queue. */ void processQueue(); /** * @brief Send M105 to the printer if one is not in the Queue */ void checkTemperature(); /** * @brief Connect to SerialLayer::receivedCommand * @param message: new message. */ void newMessage(const QByteArray &message); /** * @brief Search for firmware string in message. * A Helper function for detectFirmware() * @param message */ void findFirmware(const QByteArray &message); /** * @brief Search for new serial ports */ void locateSerialPort(); private: /** * @brief True if a firmware plugin is loaded */ bool firmwarePluginLoaded() const; /** * @brief True if a serial port is initialized */ bool serialInitialized() const; /** * @brief send firmware request to the printer */ void requestFirmware(); /** * @brief Search for atcore firmware plugins */ void findFirmwarePlugins(); /** * @brief Hold private data of AtCore. */ AtCorePrivate *d; }; diff --git a/src/gcodecommands.cpp b/src/gcodecommands.cpp index 2d63b64..99d24bd 100644 --- a/src/gcodecommands.cpp +++ b/src/gcodecommands.cpp @@ -1,589 +1,595 @@ /* AtCore Copyright (C) <2016> Authors: Lays Rodrigues Tomaz Canabrava Patrick José Pereira Chris Rizzitello This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "gcodecommands.h" QString GCode::toString(GCommands gcode) { switch (gcode) { case G0://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("G0: Rapid linear move"); case G1://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("G1: Linear move"); case G2://Sprinter - Marlin - Repetier - Smoothie return QObject::tr("G2: Controlled Arc Move clockwise"); case G3://Sprinter - Marlin - Repetier - Smoothie return QObject::tr("G3: Controlled Arc Move counterclockwise"); case G4://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("G4: Dwell"); case G10://Marlin - Repetier > 0.92 - Smoothie return QObject::tr("G10: Retract"); case G11://Marlin - Repetier > 0.92 - Smoothie return QObject::tr("G11: Unretract"); case G20://Teacup - Sprinter - Repetier - Smoothie - RepRap Firmware return QObject::tr("G20: Set units to inches"); case G21://Teacup - Sprinter - Repetier - Smoothie - RepRap Firmware return QObject::tr("G21: Set units to millimeters"); case G28://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("G28: Move to Origin Home"); case G29://Marlin - Repetier 0.91.7 return QObject::tr("G29: Detailed Z-Probe"); case G30:// Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("G30: Single Z-Probe"); case G31://Repetier 0.91.7 - Smoothie - RepRap Firmware - Marlin return QObject::tr("G31: Set or report current probe status / Dock Z Probe sled for Marlin"); case G32://Repetier 0.92.8 - Smoothie - RepRap Firmware - Marlin return QObject::tr("G32: Probe Z and calculate Z plane(Bed Leveling)/ UnDoc Z Probe sled for Marlin"); case G33://Repetier 0.92.8 return QObject::tr("G33: Measure/List/Adjust Distortion Matrix"); case G90://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("G90: Set to absolute positioning"); case G91://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("G91: Set to relative positioning"); case G92://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("G92: Set position"); case G100://Repetier 0.92 return QObject::tr("G100: Calibrate floor or rod radius"); case G130://MakerBot return QObject::tr("G130: Set digital potentiometer value"); case G131://Repetier 0.91 return QObject::tr("G131: Recase Move offset"); case G132://Repetier 0.91 return QObject::tr("G132: Calibrate endstops offsets"); case G133://Repetier 0.91 return QObject::tr("G133: Measure steps to top"); case G161://Teacup - MakerBot return QObject::tr("G161: Home axis to minimum"); case G162://Teacup - MakerBot return QObject::tr("G162: Home axis to maximum"); default: return QObject::tr("GCommand not supported!"); } } QString GCode::toCommand(GCommands gcode, const QString &value1) { switch (gcode) { case G0: { if (value1.isEmpty()) { return QStringLiteral("G0"); } else { return QStringLiteral("G0 %1").arg(value1.toUpper()); } } case G1: { if (value1.isEmpty()) { return QStringLiteral("G1"); } else { return QStringLiteral("G1 %1").arg(value1.toUpper()); } } case G28: { if (value1.isEmpty()) { return QStringLiteral("G28"); } else { return QStringLiteral("G28 %1").arg(value1.toUpper()); } } case G32: return QStringLiteral("G32 S1"); case G90: return QStringLiteral("G90"); case G91: return QStringLiteral("G91"); default: return QObject::tr("Not implemented or not supported!"); } } QString GCode::toString(MCommands gcode) { switch (gcode) { case M0://Marlin - Teacup - RepRap Firmware return QObject::tr("M0: Stop or unconditional stop"); case M1://Marlin - RepRap Firmware return QObject::tr("M1: Sleep or unconditional stop"); case M2://Teacup - Maker Bot return QObject::tr("M2: Program End"); case M6://Teacup return QObject::tr("M6: Tool Change"); case M17://Teacup - Marlin - Smoothie return QObject::tr("M17: Enable/power all steppers motors"); case M18://Teacup - Marlin(M84) - Smoothie -RepRap Firmware return QObject::tr("M18: Disable all steppers motors"); case M20://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M20: List SDCard"); case M21://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M21: Initialize SDCard"); case M22://Teacup - Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M22: Release SDCard"); case M23:////Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M23: Select SD file"); case M24://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M24: Start/resume SD print"); case M25://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M25: Pause SD print"); case M26://Sprinter - Marlin - Repetier - Smoothie(abort) - RepRap Firmware return QObject::tr("M26: Set SD position"); case M27://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M27: Report SD print status"); case M28://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M28: Begin write to SD card"); case M29:// Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M29: Stop writing to SD card"); case M30://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M30: Delete a file on the SD card"); case M31://Marlin return QObject::tr("M31: Output time since last M109 or SD card start to serial"); case M32://Marlin - Smoothie - RepRap Firmware return QObject::tr("M32: Select file and start SD print"); case M33://Marlin return QObject::tr("M33: Get the long name for an SD card file or folder"); case M34://Marlin return QObject::tr("M34: Set SD file sorting options"); case M36://RepRap Firmware return QObject::tr("M36: Return file information"); case M42://Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M42: Switch I/O pin"); case M48://Marlin return QObject::tr("M48: Measure Z-Probe repeatability"); case M70://MakerBot return QObject::tr("M70: Display message"); case M72://MakerBot return QObject::tr("M72: Play a tone or song"); case M73://MakerBot return QObject::tr("M73: Set build percentage"); case M80://Teacup(automatic) - Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M80: ATX Power On"); case M81://Teacup(automatic) - Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M81: ATX Power Off"); case M82://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M82: Set extruder to absolute mode"); case M83://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M83: Set extruder to relative mode"); case M84://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M84: Stop idle hold"); case M85://Sprinter - Marlin - Repetier return QObject::tr("M85: Set Inactivity shutdown timer"); case M92:// Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M92: Set axis steps per unit"); case M93:// Sprinter return QObject::tr("M93: Send axis steps per unit"); case M98: //RepRap Firmware return QObject::tr("M98: Call Macro/Subprogram"); case M99://RepRap Firmware return QObject::tr("M99: Return from Macro/Subprogram"); case M101://Teacup return QObject::tr("M101: Turn extruder 1 on Forward, Undo Retraction"); case M103://Teacup return QObject::tr("M103: Turn all extruders off - Extruder Retraction"); case M104://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("M104: Set Extruder Temperature"); case M105://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("M105: Get Extruder Temperature"); case M106://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M106: Fan On"); case M107:// Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M107: Fan Off"); case M108://Marlin return QObject::tr("M108: Cancel Heating"); case M109:// Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("M109: Set Extruder Temperature and Wait"); case M110:// Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M110: Set Current Line Number"); case M111://Teacup - Marlin - Repetier - RepRap Firmware return QObject::tr("M111: Set Debug Level"); case M112://Teacup - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M112: Emergency Stop"); case M114://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("M114: Get Current Position"); case M115://Teacup - Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M115: Get Firmware Version and Capabilities"); case M116://Teacup - Repetier - RepRap Firmware - MakerBot return QObject::tr("M116: Wait"); case M117:// Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M117: Display Message"); case M119://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M119: Get Endstop Status"); case M120://Marlin - Smoothie - RepRap Firmware return QObject::tr("M120: Push for Smoothie and RepRap Firmware / Enable Endstop detection for Marlin"); case M121://Marlin - Smoothie - RepRap Firmware return QObject::tr("M121: Pop for Smoothie and RepRap Firmware / Disable Endstop detection for Marlin"); case M122://RepRap Firmware return QObject::tr("M122: Diagnose"); case M126://Marlin - MakerBot return QObject::tr("M126: Open valve"); case M127://Marlin - MakerBot return QObject::tr("M127: Close valve"); case M130://Teacup return QObject::tr("M130: Set PID P value"); case M131://Teacup return QObject::tr("M131: Set PID I value"); case M132://Teacup - MakerBot return QObject::tr("M132: Set PID D value"); case M133://Teacup - MakerBot return QObject::tr("M133: Set PID I limit value"); case M134://Teacup - MakerBot return QObject::tr("M134: Write PID values to EEPROM"); case M135://RepRap Firmware - MakerBot return QObject::tr("M135: Set PID sample interval"); case M140://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware - MakerBot return QObject::tr("M140: Set Bed Temperature - Fast"); case M141://RepRap Firmware return QObject::tr("M141: Set Chamber Temperature - Fast"); case M143://RepRap Firmware return QObject::tr("M143: Maximum hot-end temperature"); case M144://RepRap Firmware return QObject::tr("M144: Stand by your bed"); case M150://Marlin return QObject::tr("M150: Set display color"); case M163://Repetier > 0.92 return QObject::tr("M163: Set weight of mixed material"); case M164://Repetier > 0.92 return QObject::tr("M164: Store weights"); case M190://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M190: Wait for bed temperature to reach target temp"); case M200://Marlin - Repetier - Smoothie return QObject::tr("M200: Set filament diameter"); case M201://Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M201: Set max printing acceleration"); case M202://Marlin - Repetier return QObject::tr("M202: Set max travel acceleration"); case M203://Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M203: Set maximum feedrate"); case M204://Sprinter - Marlin - Repetier - Smoothie return QObject::tr("M204: Set default acceleration"); case M205://Sprinter - Marlin - Repetier - Smoothie return QObject::tr("M205: Advanced settings"); case M206://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M206: Offset axes for Sprinter, Marlin, Smoothie, RepRap Firmware / Set eeprom value for Repetier"); case M207://Marlin - Smoothie return QObject::tr("M207: Set retract length"); case M208://Marlin - Smoothie return QObject::tr("M208: Set unretract length"); case M209://Marlin - Repetier return QObject::tr("M209: Enable automatic retract"); case M212://Marlin return QObject::tr("M212: Set Bed Level Sensor Offset"); case M218://Marlin return QObject::tr("M218: Set Hotend Offset"); case M220://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M220: Set speed factor override percentage"); case M221://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M221: Set extrude factor override percentage"); case M226://Marlin - Repetier return QObject::tr("M226: Wait for pin state"); case M231://Repetier return QObject::tr("M231: Set OPS parameter"); case M232://Repetier return QObject::tr("M232: Read and reset max. advance values"); case M240: //Marlin return QObject::tr("M240: Trigger camera"); case M250://Marlin return QObject::tr("M250: Set LCD contrast"); case M251://Repetier return QObject::tr("M251: Measure Z steps from homing stop (Delta printers)"); case M280://Marlin return QObject::tr("M280: Set servo position"); case M300://Marlin - Repetier - RepRap Firmware - MakerBot return QObject::tr("M300: Play beep sound"); case M301://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M301: Set PID parameters"); case M302://Marlin - Repetier > 0.92 - RepRap Firmware return QObject::tr("M302: Allow cold extrudes "); case M303://Sprinter - Marlin - Repetier - Smoothie return QObject::tr("M303: Run PID tuning"); case M304://Marlin - RepRap Firmware return QObject::tr("M304: Set PID parameters - Bed"); case M305:// Smoothie - RepRap Firmware return QObject::tr("M305: Set thermistor and ADC parameters"); case M306:// Smoothie return QObject::tr("M306: set home offset calculated from toolhead position"); case M320://Repeier return QObject::tr("M320: Activate autolevel (Repetier)"); case M321://Repetier return QObject::tr("M321: Deactivate autolevel (Repetier)"); case M322://Repetier return QObject::tr("M322: Reset autolevel matrix (Repetier)"); case M323://Repetier return QObject::tr("M323: Distortion correction on/off (Repetier)"); case M340://Repetier return QObject::tr("M340: Control the servos"); case M350://Marlin - Repetier - RepRap Firmware return QObject::tr("M350: Set microstepping mode"); case M351://Marlin return QObject::tr("M351: Toggle MS1 MS2 pins directly"); case M355://Repetier > 0.92.2 return QObject::tr("M355: Turn case lights on/off"); case M360://Repetier > 9.92.2 return QObject::tr("M360: Report firmware configuration"); case M361://Smoothie return QObject::tr("M361: Move to Theta 90 degree position"); case M362://Smoothie return QObject::tr("M362: Move to Psi 0 degree position"); case M363://Smoothie return QObject::tr("M363: Move to Psi 90 degree position"); case M364://Smoothie return QObject::tr("M364: Move to Psi + Theta 90 degree position"); case M365://Smoothie return QObject::tr("M365: SCARA scaling factor"); case M366://Smoothie return QObject::tr("M366: SCARA convert trim"); case M370://Smoothie return QObject::tr("M370: Morgan manual bed level - clear map"); case M371://Smoothie return QObject::tr("M371: Move to next calibration position"); case M372://Smoothie return QObject::tr("M372: Record calibration value, and move to next position"); case M373://Smoothie return QObject::tr("M373: End bed level calibration mode"); case M374://Smoothie return QObject::tr("M374: Save calibration grid"); case M375://Smoothie return QObject::tr("M375: Display matrix / Load Matrix"); case M380://Marlin return QObject::tr("M380: Activate solenoid"); case M381://Marlin return QObject::tr("M381: Disable all solenoids"); case M400://Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M400: Wait for current moves to finish"); case M401://Marlin return QObject::tr("M401: Lower z-probe"); case M402://Marlin return QObject::tr("M402: Raise z-probe"); case M404://Marlin - RepRap Firmware return QObject::tr("M404: Filament width and nozzle diameter"); case M405://Marlin return QObject::tr("M405: Filament Sensor on"); case M406://Marlin return QObject::tr("M406: Filament Sensor off"); case M407://Marlin - RepRap Firmware return QObject::tr("M407: Display filament diameter"); case M408://RepRap Firmware return QObject::tr("M408: Report JSON-style response"); case M420: return QObject::tr("M420: Enable/Disable Mesh Leveling (Marlin)"); case M450://Repetier return QObject::tr("M450: Report Printer Mode"); case M451://Repetier return QObject::tr("M451: Select FFF Printer Mode"); case M452://Repetier return QObject::tr("M452: Select Laser Printer Mode"); case M453://Repetier return QObject::tr("M453: Select CNC Printer Mode"); case M460://Repetier return QObject::tr("M460: Define temperature range for thermistor controlled fan"); case M500://Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M500: Store parameters in EEPROM"); case M501://Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M501: Read parameters from EEPROM"); case M502://Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M502: Revert to the default 'factory settings'."); case M503://Sprinter - Marlin - RepRap Firmware return QObject::tr("M503: Print settings "); case M540://Marlin return QObject::tr("M540: Enable/Disable 'Stop SD Print on Endstop Hit'"); case M550://RepRap Firmware return QObject::tr("M550: Set Name"); case M551://RepRap Firmware return QObject::tr("M551: Set Password"); case M552://RepRap Firmware return QObject::tr("M552: Set IP address"); case M553://RepRap Firmware return QObject::tr("M553: Set Netmask"); case M554://RepRap Firmware return QObject::tr("M554: Set Gateway"); case M555://RepRap Firmware return QObject::tr("M555: Set compatibility"); case M556://RepRap Firmware return QObject::tr("M556: Axis compensation"); case M557://Smoothie - RepRap Firmware return QObject::tr("M557: Set Z probe point"); case M558://RepRap Firmware return QObject::tr("M558: Set Z probe type"); case M559://RepRap Firmware return QObject::tr("M559: Upload configuration file"); case M560://RepRap Firmware return QObject::tr("M560: Upload web page file"); case M561://Smoothie - RepRap Firmware return QObject::tr("M561: Set Identity Transform"); case M562://RepRap Firmware return QObject::tr("M562: Reset temperature fault"); case M563://RepRap Firmware return QObject::tr("M563: Define or remove a tool"); case M564://RepRap Firmware return QObject::tr("M564: Limit axes"); case M565://Smoothie return QObject::tr("M565: Set Z probe offset"); case M566://RepRap Firmware return QObject::tr("M566: Set allowable instantaneous speed change"); case M567://RepRap Firmware return QObject::tr("M567: Set tool mix ratio"); case M568://RepRap Firmware return QObject::tr("M568: Turn off/on tool mix ratio"); case M569://RepRap Firmware return QObject::tr("M569: Set axis direction and enable values"); case M570://RepRap Firmware return QObject::tr("M570: Set heater timeout"); case M571://RepRap Firmware return QObject::tr("M571: Set output on extrude"); case M573://RepRap Firmware return QObject::tr("M573: Report heater PWM"); case M574://RepRap Firmware return QObject::tr("M574: Set endstop configuration"); case M575://RepRap Firmware return QObject::tr("M575: Set serial comms parameters"); case M577://RepRap Firmware return QObject::tr("M577: Wait until endstop is triggered"); case M578://RepRap Firmware return QObject::tr("M578: Fire inkjet bits"); case M579://RepRap Firmware return QObject::tr("M579: Scale Cartesian axes"); case M580://RepRap Firmware return QObject::tr("M580: Select Roland"); case M600://Marlin return QObject::tr("M600: Filament change pause"); case M605://Marlin return QObject::tr("M605: Set dual x-carriage movement mode"); case M665://Marlin - Smoothie - RepRap Firmware return QObject::tr("M665: Set delta configuration"); case M666://Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M666: Set delta endstop adjustment"); case M667://RepRap Firmware return QObject::tr("M667: Select CoreXY mode"); case M851://Marlin return QObject::tr("M851: Set Z-Probe Offset"); case M906://RepRap Firmware return QObject::tr("M906: Set motor currents"); case M907://Marlin - Repetier - Smoothie return QObject::tr("M907: Set digital trimpot motor"); case M908://Marlin - Repetier > 0.92 return QObject::tr("M908: Control digital trimpot directly"); case M911://RepRap Firmware return QObject::tr("M911: Set power monitor threshold voltages"); case M912://RepRap Firmware return QObject::tr("M912: Set electronics temperature monitor adjustment"); case M913://RepRap Firmware return QObject::tr("M913: Set motor percentage of normal current"); case M928://Marlin return QObject::tr("M928: Start SD logging"); case M997://RepRap Firmware return QObject::tr("M997: Perform in-application firmware update"); case M998://RepRap Firmware return QObject::tr("M998: Request resend of line"); case M999://Marlin - Smoothie - RepRap Firmware return QObject::tr("M999: Restart after being stopped by error"); default: return QObject::tr("Not implemented or not supported!"); } } QString GCode::toCommand(MCommands gcode, const QString &value1, const QString &value2) { switch (gcode) { + case M84: { + if (!value1.isEmpty()) { + return QStringLiteral("M84 S%1").arg(value1); + } + return QStringLiteral("M84"); + } case M104: { if (!value2.isEmpty()) { return QStringLiteral("M104 P%1 S%2").arg(value1).arg(value2); } else if (!value1.isEmpty()) { return QStringLiteral("M104 S%1").arg(value1); } else { return QObject::tr("ERROR! M104: It's obligatory to have an argument"); } } case M105: return QStringLiteral("M105"); case M106: { if (!value2.isEmpty()) { return QStringLiteral("M106 P%1 S%2").arg(value1).arg(value2); } else if (!value1.isEmpty()) { return QStringLiteral("M106 S%1").arg(value1); } else { return QStringLiteral("M106"); } } case M107: return QStringLiteral("M107"); case M109: if (!value1.isEmpty()) { return QStringLiteral("M109 S%1").arg(value1); } else { return QObject::tr("ERROR! M109: It's obligatory to have an argument"); } case M112: return QStringLiteral("M112"); case M114: return QStringLiteral("M114"); case M115: return QStringLiteral("M115"); case M116: return QStringLiteral("M116"); case M117: { if (!value1.isEmpty()) { return QStringLiteral("M117 %1").arg(value1); } else { return QObject::tr("ERROR! M117: It's obligatory to have an argument"); } } case M119: return QStringLiteral("M119"); case M140: { if (!value1.isEmpty()) { return QStringLiteral("M140 S%1").arg(value1); } else { return QObject::tr("ERROR! M140: It's obligatory to have an argument"); } } case M190: { if (!value1.isEmpty()) { return QStringLiteral("M190 S%1").arg(value1); } else { return QObject::tr("ERROR! M190: It's obligatory to have an argument"); } } case M220: { if (!value1.isEmpty()) { return QStringLiteral("M220 S%1").arg(value1); } else { return QObject::tr("ERROR! M220: It's obligatory to have an argument"); } } case M221: { if (!value1.isEmpty()) { return QStringLiteral("M221 S%1").arg(value1); } else { return QObject::tr("ERROR! M221: It's obligatory to have an argument"); } } default: return QObject::tr("Not supported or implemented!"); } } diff --git a/testclient/mainwindow.cpp b/testclient/mainwindow.cpp index 20f1a2e..9b31136 100644 --- a/testclient/mainwindow.cpp +++ b/testclient/mainwindow.cpp @@ -1,574 +1,580 @@ /* AtCore Test Client Copyright (C) <2016> Authors: Patrick José Pereira Lays Rodrigues Chris Rizzitello Tomaz Canabrava 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 3 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, see . */ #include #include #include #include #include #include #include "mainwindow.h" #include "seriallayer.h" #include "gcodecommands.h" #include "widgets/axiscontrol.h" #include "widgets/about.h" Q_LOGGING_CATEGORY(TESTCLIENT_MAINWINDOW, "org.kde.atelier.core") int MainWindow::fanCount = 4; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), core(new AtCore(this)), logFile(new QTemporaryFile(QDir::tempPath() + QStringLiteral("/AtCore_"))) { ui->setupUi(this); setWindowIcon(QIcon(QStringLiteral(":/icon/windowIcon"))); QCoreApplication::setApplicationVersion(core->version()); ui->serialPortCB->setEditable(true); QValidator *validator = new QIntValidator(); ui->baudRateLE->setValidator(validator); ui->baudRateLE->addItems(core->portSpeeds()); ui->baudRateLE->setCurrentIndex(9); ui->pluginCB->addItem(tr("Autodetect")); ui->pluginCB->addItems(core->availableFirmwarePlugins()); AxisControl *axisControl = new AxisControl; ui->moveDockContents->layout()->addWidget(axisControl); addLog(tr("Attempting to locate Serial Ports")); core->setSerialTimerInterval(1000); populateCBs(); //Icon for actionQuit #ifndef Q_OS_MAC ui->actionQuit->setIcon(QIcon::fromTheme(QStringLiteral("application-exit"))); #endif //hide the printing progress bar. ui->printLayout->setVisible(false); ui->statusBar->addWidget(ui->statusBarWidget); printTime = new QTime(); printTimer = new QTimer(); printTimer->setInterval(1000); printTimer->setSingleShot(false); connect(printTimer, &QTimer::timeout, this, &MainWindow::updatePrintTime); connect(ui->connectPB, &QPushButton::clicked, this, &MainWindow::connectPBClicked); connect(ui->saveLogPB, &QPushButton::clicked, this, &MainWindow::saveLogPBClicked); connect(ui->sendPB, &QPushButton::clicked, this, &MainWindow::sendPBClicked); connect(ui->commandLE, &QLineEdit::returnPressed, this, &MainWindow::sendPBClicked); connect(ui->homeAllPB, &QPushButton::clicked, this, &MainWindow::homeAllPBClicked); connect(ui->homeXPB, &QPushButton::clicked, this, &MainWindow::homeXPBClicked); connect(ui->homeYPB, &QPushButton::clicked, this, &MainWindow::homeYPBClicked); connect(ui->homeZPB, &QPushButton::clicked, this, &MainWindow::homeZPBClicked); connect(ui->bedTempPB, &QPushButton::clicked, this, &MainWindow::bedTempPBClicked); connect(ui->extTempPB, &QPushButton::clicked, this, &MainWindow::extTempPBClicked); connect(ui->mvAxisPB, &QPushButton::clicked, this, &MainWindow::mvAxisPBClicked); connect(ui->fanSpeedPB, &QPushButton::clicked, this, &MainWindow::fanSpeedPBClicked); connect(ui->printPB, &QPushButton::clicked, this, &MainWindow::printPBClicked); connect(ui->printerSpeedPB, &QPushButton::clicked, this, &MainWindow::printerSpeedPBClicked); connect(ui->flowRatePB, &QPushButton::clicked, this, &MainWindow::flowRatePBClicked); connect(ui->showMessagePB, &QPushButton::clicked, this, &MainWindow::showMessage); connect(ui->pluginCB, &QComboBox::currentTextChanged, this, &MainWindow::pluginCBChanged); + connect(ui->disableMotorsPB, &QPushButton::clicked, this, &MainWindow::disableMotorsPBClicked); connect(core, &AtCore::stateChanged, this, &MainWindow::printerStateChanged); connect(this, &MainWindow::printFile, core, &AtCore::print); connect(ui->stopPB, &QPushButton::clicked, core, &AtCore::stop); connect(ui->emergencyStopPB, &QPushButton::clicked, core, &AtCore::emergencyStop); connect(axisControl, &AxisControl::clicked, this, &MainWindow::axisControlClicked); connect(core, &AtCore::portsChanged, this, &MainWindow::locateSerialPort); connect(core, &AtCore::printProgressChanged, this, &MainWindow::printProgressChanged); connect(&core->temperature(), &Temperature::bedTemperatureChanged, [ = ](float temp) { checkTemperature(0x00, 0, temp); ui->plotWidget->appendPoint(tr("Actual Bed"), temp); ui->plotWidget->update(); }); connect(&core->temperature(), &Temperature::bedTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x01, 0, temp); ui->plotWidget->appendPoint(tr("Target Bed"), temp); ui->plotWidget->update(); }); connect(&core->temperature(), &Temperature::extruderTemperatureChanged, [ = ](float temp) { checkTemperature(0x02, 0, temp); ui->plotWidget->appendPoint(tr("Actual Ext.1"), temp); ui->plotWidget->update(); }); connect(&core->temperature(), &Temperature::extruderTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x03, 0, temp); ui->plotWidget->appendPoint(tr("Target Ext.1"), temp); ui->plotWidget->update(); }); connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close); connect(ui->actionShowDockTitles, &QAction::toggled, this, &MainWindow::toggleDockTitles); connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::about); ui->menuView->insertAction(nullptr, ui->connectDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->tempControlsDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->commandDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->printDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->moveDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->tempTimelineDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->logDock->toggleViewAction()); //more dock stuff. setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North); tabifyDockWidget(ui->moveDock, ui->tempControlsDock); ui->moveDock->raise(); tabifyDockWidget(ui->connectDock, ui->printDock); tabifyDockWidget(ui->connectDock, ui->commandDock); ui->connectDock->raise(); setCentralWidget(nullptr); } void MainWindow::closeEvent(QCloseEvent *event) { core->close(); event->accept(); } MainWindow::~MainWindow() { delete logFile; delete ui; } QString MainWindow::getTime() { return QTime::currentTime().toString(QStringLiteral("hh:mm:ss:zzz")); } QString MainWindow::logHeader() { return QStringLiteral("[%1] ").arg(getTime()); } QString MainWindow::rLogHeader() { return QStringLiteral("[%1]< ").arg(getTime()); } QString MainWindow::sLogHeader() { return QStringLiteral("[%1]> ").arg(getTime()); } void MainWindow::writeTempFile(QString text) { /* A QTemporaryFile will always be opened in QIODevice::ReadWrite mode, this allows easy access to the data in the file. This function will return true upon success and will set the fileName() to the unique filename used. */ logFile->open(); logFile->seek(logFile->size()); logFile->write(text.toLatin1()); logFile->putChar('\n'); logFile->close(); } void MainWindow::addLog(QString msg) { QString message(logHeader() + msg); ui->logTE->appendPlainText(message); writeTempFile(message); } void MainWindow::addRLog(QString msg) { QString message(rLogHeader() + msg); ui->logTE->appendPlainText(message); writeTempFile(message); } void MainWindow::addSLog(QString msg) { QString message(sLogHeader() + msg); ui->logTE->appendPlainText(message); writeTempFile(message); } void MainWindow::checkReceivedCommand(const QByteArray &message) { addRLog(QString::fromUtf8(message)); } void MainWindow::checkPushedCommands(QByteArray bmsg) { QString msg = QString::fromUtf8(bmsg); QRegExp _newLine(QChar::fromLatin1('\n')); QRegExp _return(QChar::fromLatin1('\r')); msg.replace(_newLine, QStringLiteral("\\n")); msg.replace(_return, QStringLiteral("\\r")); addSLog(msg); } void MainWindow::checkTemperature(uint sensorType, uint number, uint temp) { QString msg; switch (sensorType) { case 0x00: // bed msg = QString::fromLatin1("Bed Temperature "); break; case 0x01: // bed target msg = QString::fromLatin1("Bed Target Temperature "); break; case 0x02: // extruder msg = QString::fromLatin1("Extruder Temperature "); break; case 0x03: // extruder target msg = QString::fromLatin1("Extruder Target Temperature "); break; case 0x04: // enclosure msg = QString::fromLatin1("Enclosure Temperature "); break; case 0x05: // enclosure target msg = QString::fromLatin1("Enclosure Target Temperature "); break; } msg.append(QString::fromLatin1("[%1] : %2")); msg = msg.arg(QString::number(number)) .arg(QString::number(temp)); addRLog(msg); } /** * @brief MainWindow::locateSerialPort * Locate all active serial ports on the computer and add to the list * of serial ports */ void MainWindow::locateSerialPort(const QStringList &ports) { ui->serialPortCB->clear(); if (!ports.isEmpty()) { ui->serialPortCB->addItems(ports); addLog(tr("Found %1 Ports").arg(QString::number(ports.count()))); } else { QString portError(tr("No available ports! Please connect a serial device to continue!")); if (! ui->logTE->toPlainText().endsWith(portError)) { addLog(portError); } } } void MainWindow::connectPBClicked() { if (core->state() == AtCore::DISCONNECTED) { core->initSerial(ui->serialPortCB->currentText(), ui->baudRateLE->currentText().toInt()); connect(core, &AtCore::receivedMessage, this, &MainWindow::checkReceivedCommand); connect(core->serial(), &SerialLayer::pushedCommand, this, &MainWindow::checkPushedCommands); addLog(tr("Serial connected")); ui->connectPB->setText(tr("Disconnect")); if (core->state() == AtCore::CONNECTING) { if (ui->pluginCB->currentText().contains(tr("Autodetect"))) { addLog(tr("No plugin loaded !")); addLog(tr("Requesting Firmware...")); core->detectFirmware(); } else { core->loadFirmwarePlugin(ui->pluginCB->currentText()); } } } else { core->closeConnection(); core->setState(AtCore::DISCONNECTED); addLog(tr("Disconnected")); ui->connectPB->setText(tr("Connect")); } } void MainWindow::sendPBClicked() { QString comm = ui->commandLE->text().toUpper(); core->pushCommand(comm); ui->commandLE->clear(); } void MainWindow::homeAllPBClicked() { addSLog(tr("Home All")); core->home(); } void MainWindow::homeXPBClicked() { addSLog(tr("Home X")); core->home(AtCore::X); } void MainWindow::homeYPBClicked() { addSLog(tr("Home Y")); core->home(AtCore::Y); } void MainWindow::homeZPBClicked() { addSLog(tr("Home Z")); core->home(AtCore::Z); } void MainWindow::bedTempPBClicked() { if (ui->cb_andWait->isChecked()) { addSLog(GCode::toString(GCode::M190)); } else { addSLog(GCode::toString(GCode::M140)); } core->setBedTemp(ui->bedTempSB->value(), ui->cb_andWait->isChecked()); } void MainWindow::extTempPBClicked() { if (ui->cb_andWait->isChecked()) { addSLog(GCode::toString(GCode::M109)); } else { addSLog(GCode::toString(GCode::M104)); } core->setExtruderTemp(ui->extTempSB->value(), ui->extTempSelCB->currentIndex(), ui->cb_andWait->isChecked()); } void MainWindow::mvAxisPBClicked() { addSLog(GCode::toString(GCode::G1)); if (ui->mvAxisCB->currentIndex() == 0) { core->move(AtCore::X, ui->mvAxisSB->value()); } else if (ui->mvAxisCB->currentIndex() == 1) { core->move(AtCore::Y, ui->mvAxisSB->value()); } else if (ui->mvAxisCB->currentIndex() == 2) { core->move(AtCore::Z, ui->mvAxisSB->value()); } } void MainWindow::fanSpeedPBClicked() { addSLog(GCode::toString(GCode::M106)); core->setFanSpeed(ui->fanSpeedSB->value(), ui->fanSpeedSelCB->currentIndex()); } void MainWindow::printPBClicked() { QString fileName; switch (core->state()) { case AtCore::DISCONNECTED: QMessageBox::information(this, tr("Error"), tr("Not Connected To a Printer")); break; case AtCore::CONNECTING: QMessageBox::information(this, tr("Error"), tr(" A Firmware Plugin was not loaded!\n Please send the command M115 and let us know what your firmware returns, so we can improve our firmware detection. We have loaded the most common plugin \"repetier\" for you. You may try to print again after this message")); ui->pluginCB->setCurrentText(QStringLiteral("repetier")); break; case AtCore::IDLE: fileName = QFileDialog::getOpenFileName(this, tr("Select a file to print"), QDir::homePath(), QStringLiteral("*.gcode")); if (fileName.isNull()) { addLog(tr("No File Selected")); } else { addLog(tr("Print: %1").arg(fileName)); emit(printFile(fileName)); } break; case AtCore::BUSY: core->pause(ui->postPauseLE->text()); break; case AtCore::PAUSE: core->resume(); break; default: qCDebug(TESTCLIENT_MAINWINDOW) << "ERROR / STOP unhandled."; } } void MainWindow::saveLogPBClicked() { // Note that if a file with the name newName already exists, copy() returns false (i.e. QFile will not overwrite it). QString fileName = QDir::homePath() + QChar::fromLatin1('/') + QFileInfo(logFile->fileName()).fileName() + QStringLiteral(".txt"); QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save Log to file"), fileName); QFile::copy(logFile->fileName(), saveFileName); logFile->close(); } void MainWindow::pluginCBChanged(QString currentText) { if (core->state() != AtCore::DISCONNECTED) { if (!currentText.contains(tr("Autodetect"))) { core->loadFirmwarePlugin(currentText); } else { core->detectFirmware(); } } } void MainWindow::flowRatePBClicked() { core->setFlowRate(ui->flowRateSB->value()); } void MainWindow::printerSpeedPBClicked() { core->setPrinterSpeed(ui->printerSpeedSB->value()); } void MainWindow::printerStateChanged(AtCore::STATES state) { QString stateString; switch (state) { case AtCore::IDLE: ui->printPB->setText(tr("Print File")); stateString = QStringLiteral("Connected to ") + core->connectedPort(); break; case AtCore::STARTPRINT: stateString = QStringLiteral("START PRINT"); ui->printPB->setText(tr("Pause Print")); ui->printLayout->setVisible(true); printTime->start(); printTimer->start(); break; case AtCore::FINISHEDPRINT: stateString = QStringLiteral("Finished Print"); ui->printPB->setText(tr("Print File")); ui->printLayout->setVisible(false); printTimer->stop(); break; case AtCore::PAUSE: stateString = QStringLiteral("Paused"); ui->printPB->setText(tr("Resume Print")); break; case AtCore::BUSY: stateString = QStringLiteral("Printing"); ui->printPB->setText(tr("Pause Print")); break; case AtCore::DISCONNECTED: stateString = QStringLiteral("Not Connected"); ui->commandDock->setDisabled(true); ui->moveDock->setDisabled(true); ui->tempControlsDock->setDisabled(true); ui->printDock->setDisabled(true); break; case AtCore::CONNECTING: stateString = QStringLiteral("Connecting"); ui->commandDock->setDisabled(false); ui->moveDock->setDisabled(false); ui->tempControlsDock->setDisabled(false); ui->printDock->setDisabled(false); break; case AtCore::STOP: stateString = QStringLiteral("Stoping Print"); break; case AtCore::ERRORSTATE: stateString = QStringLiteral("Command ERROR"); break; } ui->lblState->setText(stateString); } void MainWindow::populateCBs() { // Extruders for (int count = 0; count < core->extruderCount(); count++) { ui->extTempSelCB->insertItem(count, tr("Extruder %1").arg(count)); } // Fan for (int count = 0; count < fanCount; count++) { ui->fanSpeedSelCB->insertItem(count, tr("Fan %1 speed").arg(count)); } } void MainWindow::showMessage() { core->showMessage(ui->messageLE->text()); } void MainWindow::updatePrintTime() { QTime temp(0, 0, 0); ui->time->setText(temp.addMSecs(printTime->elapsed()).toString(QStringLiteral("hh:mm:ss"))); } void MainWindow::printProgressChanged(int progress) { ui->printingProgress->setValue(progress); if (progress > 0) { QTime temp(0, 0, 0); ui->timeLeft->setText(temp.addMSecs((100 - progress) * (printTime->elapsed() / progress)).toString(QStringLiteral("hh:mm:ss"))); } else { ui->timeLeft->setText(QStringLiteral("??:??:??")); } } void MainWindow::toggleDockTitles() { if (ui->actionShowDockTitles->isChecked()) { delete ui->connectDock->titleBarWidget(); delete ui->logDock->titleBarWidget(); delete ui->tempTimelineDock->titleBarWidget(); delete ui->commandDock->titleBarWidget(); delete ui->moveDock->titleBarWidget(); delete ui->tempControlsDock->titleBarWidget(); delete ui->printDock->titleBarWidget(); } else { ui->connectDock->setTitleBarWidget(new QWidget()); ui->logDock->setTitleBarWidget(new QWidget()); ui->tempTimelineDock->setTitleBarWidget(new QWidget()); ui->commandDock->setTitleBarWidget(new QWidget()); ui->moveDock->setTitleBarWidget(new QWidget()); ui->tempControlsDock->setTitleBarWidget(new QWidget()); ui->printDock->setTitleBarWidget(new QWidget()); } } void MainWindow::about() { About *aboutDialog = new About(this); aboutDialog->exec(); } void MainWindow::axisControlClicked(QChar axis, int value) { core->setRelativePosition(); core->pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("%1%2").arg(axis, QString::number(value)))); core->setAbsolutePosition(); } + +void MainWindow::disableMotorsPBClicked() +{ + core->setIdleHold(0); +} diff --git a/testclient/mainwindow.h b/testclient/mainwindow.h index 9b95b84..7b808aa 100644 --- a/testclient/mainwindow.h +++ b/testclient/mainwindow.h @@ -1,267 +1,272 @@ /* AtCore Test Client Copyright (C) <2016> Authors: Patrick José Pereira Lays Rodrigues Chris Rizzitello Tomaz Canabrava 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 3 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, see . */ #pragma once #include #include #include #include "ui_mainwindow.h" #include "atcore.h" class SerialLayer; class MainWindow: public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; public slots: /** * @brief Check received messages * */ void checkReceivedCommand(const QByteArray &message); /** * @brief Check pushed message * * @param bmsg : Message */ void checkPushedCommands(QByteArray); /** * @brief Check temperature * * @param sensorType : type of sensor * @param number : index of sensor * @param temp : temperature */ void checkTemperature(uint sensorType, uint number, uint temp); private slots: //ButtonEvents /** * @brief axisControlClicked Used to catch the axis control. * @param axis The Axis clicked on (X |Y |Z) * @param value Distance Value */ void axisControlClicked(QChar axis, int value); /** * @brief the printing progress has changed * @param progress: the new progress */ void printProgressChanged(int progress); /** * @brief Connect Button Clicked will connect or disconnect based on printer state */ void connectPBClicked(); /** * @brief Send Command Clicked */ void sendPBClicked(); /** * @brief Home All Clicked */ void homeAllPBClicked(); /** * @brief Home X Axis Clicked */ void homeXPBClicked(); /** * @brief Home Y Axis Clicked */ void homeYPBClicked(); /** * @brief Home Z Axis Clicked */ void homeZPBClicked(); /** * @brief Set Bed Temp Clicked */ void bedTempPBClicked(); /** * @brief Set Extruder Temp Clicked */ void extTempPBClicked(); /** * @brief Move Axis Clicked */ void mvAxisPBClicked(); /** * @brief Set Fan Speed Clicked */ void fanSpeedPBClicked(); /** * @brief Print Button Clicked, can also pause /resue print based on printer state */ void printPBClicked(); /** * @brief Save the log file. */ void saveLogPBClicked(); /** * @brief set printer speed clicked */ void printerSpeedPBClicked(); /** * @brief lowRatePB has been clicked */ void flowRatePBClicked(); + /** + * @brief disableMotorsPB has been clicked + */ + void disableMotorsPBClicked(); + /** * @brief printerStateChanged Catch and proccess printer state commands * @param state: new printer state */ void printerStateChanged(AtCore::STATES state); /** * @brief showMessage show a message on the printers LCD */ void showMessage(); /** * @brief Update the print Time */ void updatePrintTime(); /** * @brief show/hide dock titlebars */ void toggleDockTitles(); /** * @brief Show the about dialog */ void about(); signals: /** * @brief printFile emit ready to print a file to atcore * @param fileName : the file to print */ void printFile(const QString &fileName); private: Ui::MainWindow *ui; AtCore *core; QTemporaryFile *logFile; QTime *printTime; QTimer *printTimer; // Define max number of fans static int fanCount; void closeEvent(QCloseEvent *event) override; /** * @brief Locate serial port * */ void locateSerialPort(const QStringList &ports); /** * @brief Return string with actual time * * @return QString */ QString getTime(); /** * @brief Append text in temporary file * * @param text */ void writeTempFile(QString text); /** * @brief Normal header * * @return QString */ QString logHeader(); /** * @brief Header of type received * * @return QString */ QString rLogHeader(); /** * @brief Header of type send * * @return QString */ QString sLogHeader(); /** * @brief Add in logger normal type message * * @param msg: Message */ void addLog(QString msg); /** * @brief Add in logger received type message * * @param msg: Message */ void addRLog(QString msg); /** * @brief Add in logger send type message * * @param msg: Message */ void addSLog(QString msg); /** * @brief pluginCB index changed */ void pluginCBChanged(QString currentText); /** * @brief setupActions for KXMLGui */ void setupActions(); /** * @brief Populate comboboxes */ void populateCBs(); }; diff --git a/testclient/mainwindow.ui b/testclient/mainwindow.ui index 8219979..088698f 100644 --- a/testclient/mainwindow.ui +++ b/testclient/mainwindow.ui @@ -1,962 +1,969 @@ MainWindow 0 0 0 0 AtCore - Test Client 6 418 801 46 100 0 0 0 0 0 AtCoreState: Not Connected Qt::Horizontal QSizePolicy::Expanding 40 20 0 0 QFrame::StyledPanel QFrame::Raised 0 0 0 0 true 0 Stop Print Job .. <html><head/><body><p>Elapsed Time</p></body></html> 00:00:00 Qt::AlignCenter / <html><head/><body><p>Remaining Time</p></body></html> 00:00:00 Qt::AlignCenter false 10 0 473 243 0 0 &Print Print File 0 0 Emergency Stop On Pause: G91,G0 Z1,G90,G1 X0 Y195 0 0 Printer Speed % 300 100 0 0 Set 0 0 Flow Rate % 300 100 0 0 Set false 0 240 485 146 0 0 Comma&nds Send Command Send Show Message Send 0 0 Temperat&ure Timeline 2 0 0 0 0 0 0 &Connection Settings 1 0 0 0 0 0 0 0 0 Port: 0 0 Baud Rate: true Use Plugin 0 0 0 0 Connect 0 0 Session &Log 2 0 0 0 0 0 0 true 0 0 true 1000 Save Session Log .. Qt::NoContextMenu false false 0 0 &Movement 1 Home All Home X Home Y Home Z 0 0 0 0 Move X Axis to Move Y Axis to Move Z Axis to 0 0 0 0 Qt::AlignCenter 0 200.000000000000000 0 0 Go + + + + Disable Motors + + + false 0 0 &Temperatures 1 Wait Untill Temperature Stablizes 0 0 Bed Temp Qt::AlignCenter °C 0 100.000000000000000 Set 0 0 Qt::AlignCenter °C 0 275.000000000000000 Set 0 0 Qt::AlignCenter % 100 0 0 Set 0 0 767 37 File &View Help &Quit true true &Show Dock Titles About F1 PlotWidget QWidget
plotwidget.h
1
diff --git a/unittests/gcodetests.cpp b/unittests/gcodetests.cpp index 1abbd49..3cc0594 100644 --- a/unittests/gcodetests.cpp +++ b/unittests/gcodetests.cpp @@ -1,1210 +1,1216 @@ /* This file is part of the KDE project Copyright (C) 2017 Chris Rizzitello 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 3 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, see . */ #include #include "gcodetests.h" void GCodeTests::command_G0() { QVERIFY(GCode::toCommand(GCode::G0) == QStringLiteral("G0")); QVERIFY(GCode::toCommand(GCode::G0, QStringLiteral("50")) == QStringLiteral("G0 50")); } void GCodeTests::command_G1() { QVERIFY(GCode::toCommand(GCode::G1) == QStringLiteral("G1")); QVERIFY(GCode::toCommand(GCode::G1, QStringLiteral("50")) == QStringLiteral("G1 50")); } void GCodeTests::command_G28() { QVERIFY(GCode::toCommand(GCode::G28) == QStringLiteral("G28")); QVERIFY(GCode::toCommand(GCode::G28, QStringLiteral("Y")) == QStringLiteral("G28 Y")); } void GCodeTests::command_G32() { QVERIFY(GCode::toCommand(GCode::G32) == QStringLiteral("G32 S1")); } void GCodeTests::command_G90() { QVERIFY(GCode::toCommand(GCode::G90) == QStringLiteral("G90")); } void GCodeTests::command_G91() { QVERIFY(GCode::toCommand(GCode::G91) == QStringLiteral("G91")); } void GCodeTests::command_unsupportedG() { QVERIFY(GCode::toCommand(GCode::G2) == QObject::tr("Not implemented or not supported!")); } void GCodeTests::string_G0() { QVERIFY(GCode::toString(GCode::G0) == QObject::tr("G0: Rapid linear move")); } void GCodeTests::string_G1() { QVERIFY(GCode::toString(GCode::G1) == QObject::tr("G1: Linear move")); } void GCodeTests::string_G2() { QVERIFY(GCode::toString(GCode::G2) == QObject::tr("G2: Controlled Arc Move clockwise")); } void GCodeTests::string_G3() { QVERIFY(GCode::toString(GCode::G3) == QObject::tr("G3: Controlled Arc Move counterclockwise")); } void GCodeTests::string_G4() { QVERIFY(GCode::toString(GCode::G4) == QObject::tr("G4: Dwell")); } void GCodeTests::string_G10() { QVERIFY(GCode::toString(GCode::G10) == QObject::tr("G10: Retract")); } void GCodeTests::string_G11() { QVERIFY(GCode::toString(GCode::G11) == QObject::tr("G11: Unretract")); } void GCodeTests::string_G20() { QVERIFY(GCode::toString(GCode::G20) == QObject::tr("G20: Set units to inches")); } void GCodeTests::string_G21() { QVERIFY(GCode::toString(GCode::G21) == QObject::tr("G21: Set units to millimeters")); } void GCodeTests::string_G28() { QVERIFY(GCode::toString(GCode::G28) == QObject::tr("G28: Move to Origin Home")); } void GCodeTests::string_G29() { QVERIFY(GCode::toString(GCode::G29) == QObject::tr("G29: Detailed Z-Probe")); } void GCodeTests::string_G30() { QVERIFY(GCode::toString(GCode::G30) == QObject::tr("G30: Single Z-Probe")); } void GCodeTests::string_G31() { QVERIFY(GCode::toString(GCode::G31) == QObject::tr("G31: Set or report current probe status / Dock Z Probe sled for Marlin")); } void GCodeTests::string_G32() { QVERIFY(GCode::toString(GCode::G32) == QObject::tr("G32: Probe Z and calculate Z plane(Bed Leveling)/ UnDoc Z Probe sled for Marlin")); } void GCodeTests::string_G33() { QVERIFY(GCode::toString(GCode::G33) == QObject::tr("G33: Measure/List/Adjust Distortion Matrix")); } void GCodeTests::string_G90() { QVERIFY(GCode::toString(GCode::G90) == QObject::tr("G90: Set to absolute positioning")); } void GCodeTests::string_G91() { QVERIFY(GCode::toString(GCode::G91) == QObject::tr("G91: Set to relative positioning")); } void GCodeTests::string_G92() { QVERIFY(GCode::toString(GCode::G92) == QObject::tr("G92: Set position")); } void GCodeTests::string_G100() { QVERIFY(GCode::toString(GCode::G100) == QObject::tr("G100: Calibrate floor or rod radius")); } void GCodeTests::string_G130() { QVERIFY(GCode::toString(GCode::G130) == QObject::tr("G130: Set digital potentiometer value")); } void GCodeTests::string_G131() { QVERIFY(GCode::toString(GCode::G131) == QObject::tr("G131: Recase Move offset")); } void GCodeTests::string_G132() { QVERIFY(GCode::toString(GCode::G132) == QObject::tr("G132: Calibrate endstops offsets")); } void GCodeTests::string_G133() { QVERIFY(GCode::toString(GCode::G133) == QObject::tr("G133: Measure steps to top")); } void GCodeTests::string_G161() { QVERIFY(GCode::toString(GCode::G161) == QObject::tr("G161: Home axis to minimum")); } void GCodeTests::string_G162() { QVERIFY(GCode::toString(GCode::G162) == QObject::tr("G162: Home axis to maximum")); } +void GCodeTests::command_M84() +{ + QVERIFY(GCode::toCommand(GCode::M84) == QStringLiteral("M84")); + QVERIFY(GCode::toCommand(GCode::M84, QStringLiteral("10")) == QStringLiteral("M84 S10")); +} + void GCodeTests::command_M104() { QVERIFY(GCode::toCommand(GCode::M104) == QStringLiteral("ERROR! M104: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M104, QStringLiteral("100")) == QStringLiteral("M104 S100")); QVERIFY(GCode::toCommand(GCode::M104, QStringLiteral("3"), QStringLiteral("100")) == QStringLiteral("M104 P3 S100")); } void GCodeTests::command_M105() { QVERIFY(GCode::toCommand(GCode::M105) == QStringLiteral("M105")); } void GCodeTests::command_M106() { QVERIFY(GCode::toCommand(GCode::M106) == QStringLiteral("M106")); QVERIFY(GCode::toCommand(GCode::M106, QStringLiteral("100")) == QStringLiteral("M106 S100")); QVERIFY(GCode::toCommand(GCode::M106, QStringLiteral("3"), QStringLiteral("100")) == QStringLiteral("M106 P3 S100")); } void GCodeTests::command_M107() { QVERIFY(GCode::toCommand(GCode::M107) == QStringLiteral("M107")); } void GCodeTests::command_M109() { QVERIFY(GCode::toCommand(GCode::M109) == QStringLiteral("ERROR! M109: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M109, QStringLiteral("100")) == QStringLiteral("M109 S100")); } void GCodeTests::command_M112() { QVERIFY(GCode::toCommand(GCode::M112) == QStringLiteral("M112")); } void GCodeTests::command_M114() { QVERIFY(GCode::toCommand(GCode::M114) == QStringLiteral("M114")); } void GCodeTests::command_M115() { QVERIFY(GCode::toCommand(GCode::M115) == QStringLiteral("M115")); } void GCodeTests::command_M116() { QVERIFY(GCode::toCommand(GCode::M116) == QStringLiteral("M116")); } void GCodeTests::command_M117() { QVERIFY(GCode::toCommand(GCode::M117) == QStringLiteral("ERROR! M117: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M117, QStringLiteral("100")) == QStringLiteral("M117 100")); } void GCodeTests::command_M119() { QVERIFY(GCode::toCommand(GCode::M119) == QStringLiteral("M119")); } void GCodeTests::command_M140() { QVERIFY(GCode::toCommand(GCode::M140) == QStringLiteral("ERROR! M140: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M140, QStringLiteral("100")) == QStringLiteral("M140 S100")); } void GCodeTests::command_M190() { QVERIFY(GCode::toCommand(GCode::M190) == QStringLiteral("ERROR! M190: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M190, QStringLiteral("100")) == QStringLiteral("M190 S100")); } void GCodeTests::command_M220() { QVERIFY(GCode::toCommand(GCode::M220) == QStringLiteral("ERROR! M220: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M220, QStringLiteral("100")) == QStringLiteral("M220 S100")); } void GCodeTests::command_M221() { QVERIFY(GCode::toCommand(GCode::M221) == QStringLiteral("ERROR! M221: It's obligatory to have an argument")); QVERIFY(GCode::toCommand(GCode::M221, QStringLiteral("100")) == QStringLiteral("M221 S100")); } void GCodeTests::command_unsupportedM() { QVERIFY(GCode::toCommand(GCode::M999) == QObject::tr("Not supported or implemented!")); } void GCodeTests::string_M0() { QVERIFY(GCode::toString(GCode::M0) == QObject::tr("M0: Stop or unconditional stop")); } void GCodeTests::string_M1() { QVERIFY(GCode::toString(GCode::M1) == QObject::tr("M1: Sleep or unconditional stop")); } void GCodeTests::string_M2() { QVERIFY(GCode::toString(GCode::M2) == QObject::tr("M2: Program End")); } void GCodeTests::string_M6() { QVERIFY(GCode::toString(GCode::M6) == QObject::tr("M6: Tool Change")); } void GCodeTests::string_M17() { QVERIFY(GCode::toString(GCode::M17) == QObject::tr("M17: Enable/power all steppers motors")); } void GCodeTests::string_M18() { QVERIFY(GCode::toString(GCode::M18) == QObject::tr("M18: Disable all steppers motors")); } void GCodeTests::string_M20() { QVERIFY(GCode::toString(GCode::M20) == QObject::tr("M20: List SDCard")); } void GCodeTests::string_M21() { QVERIFY(GCode::toString(GCode::M21) == QObject::tr("M21: Initialize SDCard")); } void GCodeTests::string_M22() { QVERIFY(GCode::toString(GCode::M22) == QObject::tr("M22: Release SDCard")); } void GCodeTests::string_M23() { QVERIFY(GCode::toString(GCode::M23) == QObject::tr("M23: Select SD file")); } void GCodeTests::string_M24() { QVERIFY(GCode::toString(GCode::M24) == QObject::tr("M24: Start/resume SD print")); } void GCodeTests::string_M25() { QVERIFY(GCode::toString(GCode::M25) == QObject::tr("M25: Pause SD print")); } void GCodeTests::string_M26() { QVERIFY(GCode::toString(GCode::M26) == QObject::tr("M26: Set SD position")); } void GCodeTests::string_M27() { QVERIFY(GCode::toString(GCode::M27) == QObject::tr("M27: Report SD print status")); } void GCodeTests::string_M28() { QVERIFY(GCode::toString(GCode::M28) == QObject::tr("M28: Begin write to SD card")); } void GCodeTests::string_M29() { QVERIFY(GCode::toString(GCode::M29) == QObject::tr("M29: Stop writing to SD card")); } void GCodeTests::string_M30() { QVERIFY(GCode::toString(GCode::M30) == QObject::tr("M30: Delete a file on the SD card")); } void GCodeTests::string_M31() { QVERIFY(GCode::toString(GCode::M31) == QObject::tr("M31: Output time since last M109 or SD card start to serial")); } void GCodeTests::string_M32() { QVERIFY(GCode::toString(GCode::M32) == QObject::tr("M32: Select file and start SD print")); } void GCodeTests::string_M33() { QVERIFY(GCode::toString(GCode::M33) == QObject::tr("M33: Get the long name for an SD card file or folder")); } void GCodeTests::string_M34() { QVERIFY(GCode::toString(GCode::M34) == QObject::tr("M34: Set SD file sorting options")); } void GCodeTests::string_M36() { QVERIFY(GCode::toString(GCode::M36) == QObject::tr("M36: Return file information")); } void GCodeTests::string_M42() { QVERIFY(GCode::toString(GCode::M42) == QObject::tr("M42: Switch I/O pin")); } void GCodeTests::string_M48() { QVERIFY(GCode::toString(GCode::M48) == QObject::tr("M48: Measure Z-Probe repeatability")); } void GCodeTests::string_M70() { QVERIFY(GCode::toString(GCode::M70) == QObject::tr("M70: Display message")); } void GCodeTests::string_M72() { QVERIFY(GCode::toString(GCode::M72) == QObject::tr("M72: Play a tone or song")); } void GCodeTests::string_M73() { QVERIFY(GCode::toString(GCode::M73) == QObject::tr("M73: Set build percentage")); } void GCodeTests::string_M80() { QVERIFY(GCode::toString(GCode::M80) == QObject::tr("M80: ATX Power On")); } void GCodeTests::string_M81() { QVERIFY(GCode::toString(GCode::M81) == QObject::tr("M81: ATX Power Off")); } void GCodeTests::string_M82() { QVERIFY(GCode::toString(GCode::M82) == QObject::tr("M82: Set extruder to absolute mode")); } void GCodeTests::string_M83() { QVERIFY(GCode::toString(GCode::M83) == QObject::tr("M83: Set extruder to relative mode")); } void GCodeTests::string_M84() { QVERIFY(GCode::toString(GCode::M84) == QObject::tr("M84: Stop idle hold")); } void GCodeTests::string_M85() { QVERIFY(GCode::toString(GCode::M85) == QObject::tr("M85: Set Inactivity shutdown timer")); } void GCodeTests::string_M92() { QVERIFY(GCode::toString(GCode::M92) == QObject::tr("M92: Set axis steps per unit")); } void GCodeTests::string_M93() { QVERIFY(GCode::toString(GCode::M93) == QObject::tr("M93: Send axis steps per unit")); } void GCodeTests::string_M98() { QVERIFY(GCode::toString(GCode::M98) == QObject::tr("M98: Call Macro/Subprogram")); } void GCodeTests::string_M99() { QVERIFY(GCode::toString(GCode::M99) == QObject::tr("M99: Return from Macro/Subprogram")); } void GCodeTests::string_M101() { QVERIFY(GCode::toString(GCode::M101) == QObject::tr("M101: Turn extruder 1 on Forward, Undo Retraction")); } void GCodeTests::string_M103() { QVERIFY(GCode::toString(GCode::M103) == QObject::tr("M103: Turn all extruders off - Extruder Retraction")); } void GCodeTests::string_M104() { QVERIFY(GCode::toString(GCode::M104) == QObject::tr("M104: Set Extruder Temperature")); } void GCodeTests::string_M105() { QVERIFY(GCode::toString(GCode::M105) == QObject::tr("M105: Get Extruder Temperature")); } void GCodeTests::string_M106() { QVERIFY(GCode::toString(GCode::M106) == QObject::tr("M106: Fan On")); } void GCodeTests::string_M107() { QVERIFY(GCode::toString(GCode::M107) == QObject::tr("M107: Fan Off")); } void GCodeTests::string_M108() { QVERIFY(GCode::toString(GCode::M108) == QObject::tr("M108: Cancel Heating")); } void GCodeTests::string_M109() { QVERIFY(GCode::toString(GCode::M109) == QObject::tr("M109: Set Extruder Temperature and Wait")); } void GCodeTests::string_M110() { QVERIFY(GCode::toString(GCode::M110) == QObject::tr("M110: Set Current Line Number")); } void GCodeTests::string_M111() { QVERIFY(GCode::toString(GCode::M111) == QObject::tr("M111: Set Debug Level")); } void GCodeTests::string_M112() { QVERIFY(GCode::toString(GCode::M112) == QObject::tr("M112: Emergency Stop")); } void GCodeTests::string_M114() { QVERIFY(GCode::toString(GCode::M114) == QObject::tr("M114: Get Current Position")); } void GCodeTests::string_M115() { QVERIFY(GCode::toString(GCode::M115) == QObject::tr("M115: Get Firmware Version and Capabilities")); } void GCodeTests::string_M116() { QVERIFY(GCode::toString(GCode::M116) == QObject::tr("M116: Wait")); } void GCodeTests::string_M117() { QVERIFY(GCode::toString(GCode::M117) == QObject::tr("M117: Display Message")); } void GCodeTests::string_M119() { QVERIFY(GCode::toString(GCode::M119) == QObject::tr("M119: Get Endstop Status")); } void GCodeTests::string_M120() { QVERIFY(GCode::toString(GCode::M120) == QObject::tr("M120: Push for Smoothie and RepRap Firmware / Enable Endstop detection for Marlin")); } void GCodeTests::string_M121() { QVERIFY(GCode::toString(GCode::M121) == QObject::tr("M121: Pop for Smoothie and RepRap Firmware / Disable Endstop detection for Marlin")); } void GCodeTests::string_M122() { QVERIFY(GCode::toString(GCode::M122) == QObject::tr("M122: Diagnose")); } void GCodeTests::string_M126() { QVERIFY(GCode::toString(GCode::M126) == QObject::tr("M126: Open valve")); } void GCodeTests::string_M127() { QVERIFY(GCode::toString(GCode::M127) == QObject::tr("M127: Close valve")); } void GCodeTests::string_M130() { QVERIFY(GCode::toString(GCode::M130) == QObject::tr("M130: Set PID P value")); } void GCodeTests::string_M131() { QVERIFY(GCode::toString(GCode::M131) == QObject::tr("M131: Set PID I value")); } void GCodeTests::string_M132() { QVERIFY(GCode::toString(GCode::M132) == QObject::tr("M132: Set PID D value")); } void GCodeTests::string_M133() { QVERIFY(GCode::toString(GCode::M133) == QObject::tr("M133: Set PID I limit value")); } void GCodeTests::string_M134() { QVERIFY(GCode::toString(GCode::M134) == QObject::tr("M134: Write PID values to EEPROM")); } void GCodeTests::string_M135() { QVERIFY(GCode::toString(GCode::M135) == QObject::tr("M135: Set PID sample interval")); } void GCodeTests::string_M140() { QVERIFY(GCode::toString(GCode::M140) == QObject::tr("M140: Set Bed Temperature - Fast")); } void GCodeTests::string_M141() { QVERIFY(GCode::toString(GCode::M141) == QObject::tr("M141: Set Chamber Temperature - Fast")); } void GCodeTests::string_M143() { QVERIFY(GCode::toString(GCode::M143) == QObject::tr("M143: Maximum hot-end temperature")); } void GCodeTests::string_M144() { QVERIFY(GCode::toString(GCode::M144) == QObject::tr("M144: Stand by your bed")); } void GCodeTests::string_M150() { QVERIFY(GCode::toString(GCode::M150) == QObject::tr("M150: Set display color")); } void GCodeTests::string_M163() { QVERIFY(GCode::toString(GCode::M163) == QObject::tr("M163: Set weight of mixed material")); } void GCodeTests::string_M164() { QVERIFY(GCode::toString(GCode::M164) == QObject::tr("M164: Store weights")); } void GCodeTests::string_M190() { QVERIFY(GCode::toString(GCode::M190) == QObject::tr("M190: Wait for bed temperature to reach target temp")); } void GCodeTests::string_M200() { QVERIFY(GCode::toString(GCode::M200) == QObject::tr("M200: Set filament diameter")); } void GCodeTests::string_M201() { QVERIFY(GCode::toString(GCode::M201) == QObject::tr("M201: Set max printing acceleration")); } void GCodeTests::string_M202() { QVERIFY(GCode::toString(GCode::M202) == QObject::tr("M202: Set max travel acceleration")); } void GCodeTests::string_M203() { QVERIFY(GCode::toString(GCode::M203) == QObject::tr("M203: Set maximum feedrate")); } void GCodeTests::string_M204() { QVERIFY(GCode::toString(GCode::M204) == QObject::tr("M204: Set default acceleration")); } void GCodeTests::string_M205() { QVERIFY(GCode::toString(GCode::M205) == QObject::tr("M205: Advanced settings")); } void GCodeTests::string_M206() { QVERIFY(GCode::toString(GCode::M206) == QObject::tr("M206: Offset axes for Sprinter, Marlin, Smoothie, RepRap Firmware / Set eeprom value for Repetier")); } void GCodeTests::string_M207() { QVERIFY(GCode::toString(GCode::M207) == QObject::tr("M207: Set retract length")); } void GCodeTests::string_M208() { QVERIFY(GCode::toString(GCode::M208) == QObject::tr("M208: Set unretract length")); } void GCodeTests::string_M209() { QVERIFY(GCode::toString(GCode::M209) == QObject::tr("M209: Enable automatic retract")); } void GCodeTests::string_M212() { QVERIFY(GCode::toString(GCode::M212) == QObject::tr("M212: Set Bed Level Sensor Offset")); } void GCodeTests::string_M218() { QVERIFY(GCode::toString(GCode::M218) == QObject::tr("M218: Set Hotend Offset")); } void GCodeTests::string_M220() { QVERIFY(GCode::toString(GCode::M220) == QObject::tr("M220: Set speed factor override percentage")); } void GCodeTests::string_M221() { QVERIFY(GCode::toString(GCode::M221) == QObject::tr("M221: Set extrude factor override percentage")); } void GCodeTests::string_M226() { QVERIFY(GCode::toString(GCode::M226) == QObject::tr("M226: Wait for pin state")); } void GCodeTests::string_M231() { QVERIFY(GCode::toString(GCode::M231) == QObject::tr("M231: Set OPS parameter")); } void GCodeTests::string_M232() { QVERIFY(GCode::toString(GCode::M232) == QObject::tr("M232: Read and reset max. advance values")); } void GCodeTests::string_M240() { QVERIFY(GCode::toString(GCode::M240) == QObject::tr("M240: Trigger camera")); } void GCodeTests::string_M250() { QVERIFY(GCode::toString(GCode::M250) == QObject::tr("M250: Set LCD contrast")); } void GCodeTests::string_M251() { QVERIFY(GCode::toString(GCode::M251) == QObject::tr("M251: Measure Z steps from homing stop (Delta printers)")); } void GCodeTests::string_M280() { QVERIFY(GCode::toString(GCode::M280) == QObject::tr("M280: Set servo position")); } void GCodeTests::string_M300() { QVERIFY(GCode::toString(GCode::M300) == QObject::tr("M300: Play beep sound")); } void GCodeTests::string_M301() { QVERIFY(GCode::toString(GCode::M301) == QObject::tr("M301: Set PID parameters")); } void GCodeTests::string_M302() { QVERIFY(GCode::toString(GCode::M302) == QObject::tr("M302: Allow cold extrudes ")); } void GCodeTests::string_M303() { QVERIFY(GCode::toString(GCode::M303) == QObject::tr("M303: Run PID tuning")); } void GCodeTests::string_M304() { QVERIFY(GCode::toString(GCode::M304) == QObject::tr("M304: Set PID parameters - Bed")); } void GCodeTests::string_M305() { QVERIFY(GCode::toString(GCode::M305) == QObject::tr("M305: Set thermistor and ADC parameters")); } void GCodeTests::string_M306() { QVERIFY(GCode::toString(GCode::M306) == QObject::tr("M306: set home offset calculated from toolhead position")); } void GCodeTests::string_M320() { QVERIFY(GCode::toString(GCode::M320) == QObject::tr("M320: Activate autolevel (Repetier)")); } void GCodeTests::string_M321() { QVERIFY(GCode::toString(GCode::M321) == QObject::tr("M321: Deactivate autolevel (Repetier)")); } void GCodeTests::string_M322() { QVERIFY(GCode::toString(GCode::M322) == QObject::tr("M322: Reset autolevel matrix (Repetier)")); } void GCodeTests::string_M323() { QVERIFY(GCode::toString(GCode::M323) == QObject::tr("M323: Distortion correction on/off (Repetier)")); } void GCodeTests::string_M340() { QVERIFY(GCode::toString(GCode::M340) == QObject::tr("M340: Control the servos")); } void GCodeTests::string_M350() { QVERIFY(GCode::toString(GCode::M350) == QObject::tr("M350: Set microstepping mode")); } void GCodeTests::string_M351() { QVERIFY(GCode::toString(GCode::M351) == QObject::tr("M351: Toggle MS1 MS2 pins directly")); } void GCodeTests::string_M355() { QVERIFY(GCode::toString(GCode::M355) == QObject::tr("M355: Turn case lights on/off")); } void GCodeTests::string_M360() { QVERIFY(GCode::toString(GCode::M360) == QObject::tr("M360: Report firmware configuration")); } void GCodeTests::string_M361() { QVERIFY(GCode::toString(GCode::M361) == QObject::tr("M361: Move to Theta 90 degree position")); } void GCodeTests::string_M362() { QVERIFY(GCode::toString(GCode::M362) == QObject::tr("M362: Move to Psi 0 degree position")); } void GCodeTests::string_M363() { QVERIFY(GCode::toString(GCode::M363) == QObject::tr("M363: Move to Psi 90 degree position")); } void GCodeTests::string_M364() { QVERIFY(GCode::toString(GCode::M364) == QObject::tr("M364: Move to Psi + Theta 90 degree position")); } void GCodeTests::string_M365() { QVERIFY(GCode::toString(GCode::M365) == QObject::tr("M365: SCARA scaling factor")); } void GCodeTests::string_M366() { QVERIFY(GCode::toString(GCode::M366) == QObject::tr("M366: SCARA convert trim")); } void GCodeTests::string_M370() { QVERIFY(GCode::toString(GCode::M370) == QObject::tr("M370: Morgan manual bed level - clear map")); } void GCodeTests::string_M371() { QVERIFY(GCode::toString(GCode::M371) == QObject::tr("M371: Move to next calibration position")); } void GCodeTests::string_M372() { QVERIFY(GCode::toString(GCode::M372) == QObject::tr("M372: Record calibration value, and move to next position")); } void GCodeTests::string_M373() { QVERIFY(GCode::toString(GCode::M373) == QObject::tr("M373: End bed level calibration mode")); } void GCodeTests::string_M374() { QVERIFY(GCode::toString(GCode::M374) == QObject::tr("M374: Save calibration grid")); } void GCodeTests::string_M375() { QVERIFY(GCode::toString(GCode::M375) == QObject::tr("M375: Display matrix / Load Matrix")); } void GCodeTests::string_M380() { QVERIFY(GCode::toString(GCode::M380) == QObject::tr("M380: Activate solenoid")); } void GCodeTests::string_M381() { QVERIFY(GCode::toString(GCode::M381) == QObject::tr("M381: Disable all solenoids")); } void GCodeTests::string_M400() { QVERIFY(GCode::toString(GCode::M400) == QObject::tr("M400: Wait for current moves to finish")); } void GCodeTests::string_M401() { QVERIFY(GCode::toString(GCode::M401) == QObject::tr("M401: Lower z-probe")); } void GCodeTests::string_M402() { QVERIFY(GCode::toString(GCode::M402) == QObject::tr("M402: Raise z-probe")); } void GCodeTests::string_M404() { QVERIFY(GCode::toString(GCode::M404) == QObject::tr("M404: Filament width and nozzle diameter")); } void GCodeTests::string_M405() { QVERIFY(GCode::toString(GCode::M405) == QObject::tr("M405: Filament Sensor on")); } void GCodeTests::string_M406() { QVERIFY(GCode::toString(GCode::M406) == QObject::tr("M406: Filament Sensor off")); } void GCodeTests::string_M407() { QVERIFY(GCode::toString(GCode::M407) == QObject::tr("M407: Display filament diameter")); } void GCodeTests::string_M408() { QVERIFY(GCode::toString(GCode::M408) == QObject::tr("M408: Report JSON-style response")); } void GCodeTests::string_M420() { QVERIFY(GCode::toString(GCode::M420) == QObject::tr("M420: Enable/Disable Mesh Leveling (Marlin)")); } void GCodeTests::string_M450() { QVERIFY(GCode::toString(GCode::M450) == QObject::tr("M450: Report Printer Mode")); } void GCodeTests::string_M451() { QVERIFY(GCode::toString(GCode::M451) == QObject::tr("M451: Select FFF Printer Mode")); } void GCodeTests::string_M452() { QVERIFY(GCode::toString(GCode::M452) == QObject::tr("M452: Select Laser Printer Mode")); } void GCodeTests::string_M453() { QVERIFY(GCode::toString(GCode::M453) == QObject::tr("M453: Select CNC Printer Mode")); } void GCodeTests::string_M460() { QVERIFY(GCode::toString(GCode::M460) == QObject::tr("M460: Define temperature range for thermistor controlled fan")); } void GCodeTests::string_M500() { QVERIFY(GCode::toString(GCode::M500) == QObject::tr("M500: Store parameters in EEPROM")); } void GCodeTests::string_M501() { QVERIFY(GCode::toString(GCode::M501) == QObject::tr("M501: Read parameters from EEPROM")); } void GCodeTests::string_M502() { QVERIFY(GCode::toString(GCode::M502) == QObject::tr("M502: Revert to the default 'factory settings'.")); } void GCodeTests::string_M503() { QVERIFY(GCode::toString(GCode::M503) == QObject::tr("M503: Print settings ")); } void GCodeTests::string_M540() { QVERIFY(GCode::toString(GCode::M540) == QObject::tr("M540: Enable/Disable 'Stop SD Print on Endstop Hit'")); } void GCodeTests::string_M550() { QVERIFY(GCode::toString(GCode::M550) == QObject::tr("M550: Set Name")); } void GCodeTests::string_M551() { QVERIFY(GCode::toString(GCode::M551) == QObject::tr("M551: Set Password")); } void GCodeTests::string_M552() { QVERIFY(GCode::toString(GCode::M552) == QObject::tr("M552: Set IP address")); } void GCodeTests::string_M553() { QVERIFY(GCode::toString(GCode::M553) == QObject::tr("M553: Set Netmask")); } void GCodeTests::string_M554() { QVERIFY(GCode::toString(GCode::M554) == QObject::tr("M554: Set Gateway")); } void GCodeTests::string_M555() { QVERIFY(GCode::toString(GCode::M555) == QObject::tr("M555: Set compatibility")); } void GCodeTests::string_M556() { QVERIFY(GCode::toString(GCode::M556) == QObject::tr("M556: Axis compensation")); } void GCodeTests::string_M557() { QVERIFY(GCode::toString(GCode::M557) == QObject::tr("M557: Set Z probe point")); } void GCodeTests::string_M558() { QVERIFY(GCode::toString(GCode::M558) == QObject::tr("M558: Set Z probe type")); } void GCodeTests::string_M559() { QVERIFY(GCode::toString(GCode::M559) == QObject::tr("M559: Upload configuration file")); } void GCodeTests::string_M560() { QVERIFY(GCode::toString(GCode::M560) == QObject::tr("M560: Upload web page file")); } void GCodeTests::string_M561() { QVERIFY(GCode::toString(GCode::M561) == QObject::tr("M561: Set Identity Transform")); } void GCodeTests::string_M562() { QVERIFY(GCode::toString(GCode::M562) == QObject::tr("M562: Reset temperature fault")); } void GCodeTests::string_M563() { QVERIFY(GCode::toString(GCode::M563) == QObject::tr("M563: Define or remove a tool")); } void GCodeTests::string_M564() { QVERIFY(GCode::toString(GCode::M564) == QObject::tr("M564: Limit axes")); } void GCodeTests::string_M565() { QVERIFY(GCode::toString(GCode::M565) == QObject::tr("M565: Set Z probe offset")); } void GCodeTests::string_M566() { QVERIFY(GCode::toString(GCode::M566) == QObject::tr("M566: Set allowable instantaneous speed change")); } void GCodeTests::string_M567() { QVERIFY(GCode::toString(GCode::M567) == QObject::tr("M567: Set tool mix ratio")); } void GCodeTests::string_M568() { QVERIFY(GCode::toString(GCode::M568) == QObject::tr("M568: Turn off/on tool mix ratio")); } void GCodeTests::string_M569() { QVERIFY(GCode::toString(GCode::M569) == QObject::tr("M569: Set axis direction and enable values")); } void GCodeTests::string_M570() { QVERIFY(GCode::toString(GCode::M570) == QObject::tr("M570: Set heater timeout")); } void GCodeTests::string_M571() { QVERIFY(GCode::toString(GCode::M571) == QObject::tr("M571: Set output on extrude")); } void GCodeTests::string_M573() { QVERIFY(GCode::toString(GCode::M573) == QObject::tr("M573: Report heater PWM")); } void GCodeTests::string_M574() { QVERIFY(GCode::toString(GCode::M574) == QObject::tr("M574: Set endstop configuration")); } void GCodeTests::string_M575() { QVERIFY(GCode::toString(GCode::M575) == QObject::tr("M575: Set serial comms parameters")); } void GCodeTests::string_M577() { QVERIFY(GCode::toString(GCode::M577) == QObject::tr("M577: Wait until endstop is triggered")); } void GCodeTests::string_M578() { QVERIFY(GCode::toString(GCode::M578) == QObject::tr("M578: Fire inkjet bits")); } void GCodeTests::string_M579() { QVERIFY(GCode::toString(GCode::M579) == QObject::tr("M579: Scale Cartesian axes")); } void GCodeTests::string_M580() { QVERIFY(GCode::toString(GCode::M580) == QObject::tr("M580: Select Roland")); } void GCodeTests::string_M600() { QVERIFY(GCode::toString(GCode::M600) == QObject::tr("M600: Filament change pause")); } void GCodeTests::string_M605() { QVERIFY(GCode::toString(GCode::M605) == QObject::tr("M605: Set dual x-carriage movement mode")); } void GCodeTests::string_M665() { QVERIFY(GCode::toString(GCode::M665) == QObject::tr("M665: Set delta configuration")); } void GCodeTests::string_M666() { QVERIFY(GCode::toString(GCode::M666) == QObject::tr("M666: Set delta endstop adjustment")); } void GCodeTests::string_M667() { QVERIFY(GCode::toString(GCode::M667) == QObject::tr("M667: Select CoreXY mode")); } void GCodeTests::string_M851() { QVERIFY(GCode::toString(GCode::M851) == QObject::tr("M851: Set Z-Probe Offset")); } void GCodeTests::string_M906() { QVERIFY(GCode::toString(GCode::M906) == QObject::tr("M906: Set motor currents")); } void GCodeTests::string_M907() { QVERIFY(GCode::toString(GCode::M907) == QObject::tr("M907: Set digital trimpot motor")); } void GCodeTests::string_M908() { QVERIFY(GCode::toString(GCode::M908) == QObject::tr("M908: Control digital trimpot directly")); } void GCodeTests::string_M911() { QVERIFY(GCode::toString(GCode::M911) == QObject::tr("M911: Set power monitor threshold voltages")); } void GCodeTests::string_M912() { QVERIFY(GCode::toString(GCode::M912) == QObject::tr("M912: Set electronics temperature monitor adjustment")); } void GCodeTests::string_M913() { QVERIFY(GCode::toString(GCode::M913) == QObject::tr("M913: Set motor percentage of normal current")); } void GCodeTests::string_M928() { QVERIFY(GCode::toString(GCode::M928) == QObject::tr("M928: Start SD logging")); } void GCodeTests::string_M997() { QVERIFY(GCode::toString(GCode::M997) == QObject::tr("M997: Perform in-application firmware update")); } void GCodeTests::string_M998() { QVERIFY(GCode::toString(GCode::M998) == QObject::tr("M998: Request resend of line")); } void GCodeTests::string_M999() { QVERIFY(GCode::toString(GCode::M999) == QObject::tr("M999: Restart after being stopped by error")); } QTEST_MAIN(GCodeTests) diff --git a/unittests/gcodetests.h b/unittests/gcodetests.h index d829e77..6c10456 100644 --- a/unittests/gcodetests.h +++ b/unittests/gcodetests.h @@ -1,266 +1,267 @@ /* This file is part of the KDE project Copyright (C) 2017 Chris Rizzitello 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 3 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, see . */ #include #include #include "../src/gcodecommands.h" class GCodeTests: public QObject { Q_OBJECT private slots: void command_G0(); void command_G1(); void command_G28(); void command_G32(); void command_G90(); void command_G91(); void command_unsupportedG(); void string_G0(); void string_G1(); void string_G2(); void string_G3(); void string_G4(); void string_G10(); void string_G11(); void string_G20(); void string_G21(); void string_G28(); void string_G29(); void string_G30(); void string_G31(); void string_G32(); void string_G33(); void string_G90(); void string_G91(); void string_G92(); void string_G100(); void string_G130(); void string_G131(); void string_G132(); void string_G133(); void string_G161(); void string_G162(); + void command_M84(); void command_M104(); void command_M105(); void command_M106(); void command_M107(); void command_M109(); void command_M112(); void command_M114(); void command_M115(); void command_M116(); void command_M117(); void command_M119(); void command_M140(); void command_M190(); void command_M220(); void command_M221(); void command_unsupportedM(); void string_M0(); void string_M1(); void string_M2(); void string_M6(); void string_M17(); void string_M18(); void string_M20(); void string_M21(); void string_M22(); void string_M23(); void string_M24(); void string_M25(); void string_M26(); void string_M27(); void string_M28(); void string_M29(); void string_M30(); void string_M31(); void string_M32(); void string_M33(); void string_M34(); void string_M36(); void string_M42(); void string_M48(); void string_M70(); void string_M72(); void string_M73(); void string_M80(); void string_M81(); void string_M82(); void string_M83(); void string_M84(); void string_M85(); void string_M92(); void string_M93(); void string_M98(); void string_M99(); void string_M101(); void string_M103(); void string_M104(); void string_M105(); void string_M106(); void string_M107(); void string_M108(); void string_M109(); void string_M110(); void string_M111(); void string_M112(); void string_M114(); void string_M115(); void string_M116(); void string_M117(); void string_M119(); void string_M120(); void string_M121(); void string_M122(); void string_M126(); void string_M127(); void string_M130(); void string_M131(); void string_M132(); void string_M133(); void string_M134(); void string_M135(); void string_M140(); void string_M141(); void string_M143(); void string_M144(); void string_M150(); void string_M163(); void string_M164(); void string_M190(); void string_M200(); void string_M201(); void string_M202(); void string_M203(); void string_M204(); void string_M205(); void string_M206(); void string_M207(); void string_M208(); void string_M209(); void string_M212(); void string_M218(); void string_M220(); void string_M221(); void string_M226(); void string_M231(); void string_M232(); void string_M240(); void string_M250(); void string_M251(); void string_M280(); void string_M300(); void string_M301(); void string_M302(); void string_M303(); void string_M304(); void string_M305(); void string_M306(); void string_M320(); void string_M321(); void string_M322(); void string_M323(); void string_M340(); void string_M350(); void string_M351(); void string_M355(); void string_M360(); void string_M361(); void string_M362(); void string_M363(); void string_M364(); void string_M365(); void string_M366(); void string_M370(); void string_M371(); void string_M372(); void string_M373(); void string_M374(); void string_M375(); void string_M380(); void string_M381(); void string_M400(); void string_M401(); void string_M402(); void string_M404(); void string_M405(); void string_M406(); void string_M407(); void string_M408(); void string_M420(); void string_M450(); void string_M451(); void string_M452(); void string_M453(); void string_M460(); void string_M500(); void string_M501(); void string_M502(); void string_M503(); void string_M540(); void string_M550(); void string_M551(); void string_M552(); void string_M553(); void string_M554(); void string_M555(); void string_M556(); void string_M557(); void string_M558(); void string_M559(); void string_M560(); void string_M561(); void string_M562(); void string_M563(); void string_M564(); void string_M565(); void string_M566(); void string_M567(); void string_M568(); void string_M569(); void string_M570(); void string_M571(); void string_M573(); void string_M574(); void string_M575(); void string_M577(); void string_M578(); void string_M579(); void string_M580(); void string_M600(); void string_M605(); void string_M665(); void string_M666(); void string_M667(); void string_M851(); void string_M906(); void string_M907(); void string_M908(); void string_M911(); void string_M912(); void string_M913(); void string_M928(); void string_M997(); void string_M998(); void string_M999(); };