inital commit
This commit is contained in:
commit
f91c9f1a6f
43
CMakeLists.txt
Normal file
43
CMakeLists.txt
Normal file
@ -0,0 +1,43 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(VHFMill VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets SerialPort Network 3DCore 3DRender 3DInput 3DExtras)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
vhfmill.cpp
|
||||
vhfmill.h
|
||||
led.cpp
|
||||
led.h
|
||||
gcodetovhf.cpp
|
||||
gcodetovhf.h
|
||||
mainwindow.h
|
||||
mainwindow.ui
|
||||
backplotwidget.cpp
|
||||
backplotwidget.h
|
||||
orbitcameracontroller.cpp
|
||||
orbitcameracontroller.h
|
||||
vhfmillthread.cpp
|
||||
vhfmillthread.h
|
||||
mainobject.cpp
|
||||
mainobject.h
|
||||
)
|
||||
|
||||
qt_add_executable(VHFMill MANUAL_FINALIZATION ${PROJECT_SOURCES})
|
||||
|
||||
target_link_libraries(VHFMill PRIVATE Qt6::Widgets Qt6::SerialPort Qt6::Network Qt6::3DCore Qt6::3DRender Qt6::3DExtras)
|
||||
target_include_directories(VHFMill PRIVATE .)
|
||||
|
||||
install(TARGETS VHFMill BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
qt_finalize_executable(VHFMill)
|
337
backplotwidget.cpp
Normal file
337
backplotwidget.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
#include "backplotwidget.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QCamera>
|
||||
#include <QCameraLens>
|
||||
#include <QMaterial>
|
||||
#include <QGeometry>
|
||||
#include <Qt3DExtras/QCylinderMesh>
|
||||
#include <Qt3DExtras/QPlaneMesh>
|
||||
#include <Qt3DRender/qpointlight.h>
|
||||
#include <QRenderSettings>
|
||||
|
||||
BackPlotWidget::BackPlotWidget(QWidget *parent, double xLimit, double yLimit, double zLimit)
|
||||
: limits(xLimit, yLimit, zLimit),
|
||||
QWidget(parent)
|
||||
{
|
||||
|
||||
containerWdiget = QWidget::createWindowContainer(&view);
|
||||
hLayout.addWidget(containerWdiget);
|
||||
containerWdiget->setParent(this);
|
||||
setLayout(&hLayout);
|
||||
view.defaultFrameGraph()->setClearColor("Black");
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void BackPlotWidget::reset()
|
||||
{
|
||||
view.setRootEntity(nullptr);
|
||||
|
||||
if(rootEntity)
|
||||
delete rootEntity;
|
||||
rootEntity = new Qt3DCore::QEntity();
|
||||
view.setRootEntity(rootEntity);
|
||||
view.renderSettings()->setRenderPolicy(Qt3DRender::QRenderSettings::OnDemand);
|
||||
|
||||
camController = new OrbitCameraController(QVector2D(100, 100), rootEntity);
|
||||
camController->setLinearSpeed(200.0f);
|
||||
camController->setLookSpeed(360.0f);
|
||||
camController->setCamera(view.camera());
|
||||
|
||||
axisMaterial = new Qt3DExtras::QPhongMaterial(rootEntity);
|
||||
rapidMaterial= new Qt3DExtras::QPhongMaterial(rootEntity);
|
||||
pathMaterial = new Qt3DExtras::QPhongMaterial(rootEntity);
|
||||
axisMaterial->setAmbient(QColorConstants::Red);
|
||||
rapidMaterial->setAmbient(QColorConstants::Gray);
|
||||
pathMaterial->setAmbient(QColorConstants::White);
|
||||
|
||||
view.camera()->setPosition(QVector3D(limits.x()/2, limits.y()/2, limits.z()*4));
|
||||
view.camera()->setUpVector(QVector3D(0, 1, 0));
|
||||
view.camera()->setViewCenter(QVector3D(limits.x()/2, limits.y()/2, 0));
|
||||
|
||||
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity);
|
||||
light->setColor(QColorConstants::White);
|
||||
light->setIntensity(0.2);
|
||||
lightEntity->addComponent(light);
|
||||
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
|
||||
lightTransform->setTranslation(QVector3D(0-limits.x()/2, 0-limits.y()/2, 1000.0f));
|
||||
lightEntity->addComponent(lightTransform);
|
||||
|
||||
Qt3DCore::QEntity* xAxisEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DCore::QEntity* yAxisEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DCore::QEntity* zAxisEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DExtras::QPhongMaterial* xAxisMaterial = new Qt3DExtras::QPhongMaterial(xAxisEntity);
|
||||
Qt3DExtras::QPhongMaterial* yAxisMaterial = new Qt3DExtras::QPhongMaterial(yAxisEntity);
|
||||
Qt3DExtras::QPhongMaterial* zAxisMaterial = new Qt3DExtras::QPhongMaterial(zAxisEntity);
|
||||
xAxisMaterial->setAmbient(QColorConstants::Green);
|
||||
yAxisMaterial->setAmbient(QColorConstants::Red);
|
||||
zAxisMaterial->setAmbient(QColor(18,128,255));
|
||||
touchoffTransform = new Qt3DCore::QTransform(rootEntity);
|
||||
touchoffTransform->setTranslation(limits);
|
||||
xAxisEntity->addComponent(touchoffTransform);
|
||||
yAxisEntity->addComponent(touchoffTransform);
|
||||
zAxisEntity->addComponent(touchoffTransform);
|
||||
drawLine(QVector3D(0,0,0), QVector3D(-15,0,0), xAxisMaterial, xAxisEntity);
|
||||
drawLine(QVector3D(0,0,0), QVector3D(0,-15,0), yAxisMaterial, yAxisEntity);
|
||||
drawLine(QVector3D(0,0,0), QVector3D(0,0,15), zAxisMaterial, zAxisEntity);
|
||||
|
||||
drawBox(QVector3D(0, 0, 0), limits, axisMaterial, new Qt3DCore::QEntity(rootEntity));
|
||||
|
||||
Qt3DCore::QEntity* planeEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DExtras::QPlaneMesh* plane = new Qt3DExtras::QPlaneMesh(planeEntity);
|
||||
Qt3DCore::QTransform *planeTransform = new Qt3DCore::QTransform(planeEntity);
|
||||
Qt3DExtras::QPhongMaterial* planeMaterial = new Qt3DExtras::QPhongMaterial(planeEntity);
|
||||
planeMaterial->setDiffuse(QColorConstants::DarkGray);
|
||||
planeTransform->setTranslation(QVector3D(limits.x()/2, limits.y()/2, -1));
|
||||
planeTransform->setRotationX(90);
|
||||
plane->setHeight(limits.y()*2);
|
||||
plane->setWidth(limits.x()*2);
|
||||
planeEntity->addComponent(plane);
|
||||
planeEntity->addComponent(planeMaterial);
|
||||
planeEntity->addComponent(planeTransform);
|
||||
|
||||
Qt3DCore::QEntity* planeRevEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DExtras::QPlaneMesh* planeRev = new Qt3DExtras::QPlaneMesh(planeRevEntity);
|
||||
Qt3DCore::QTransform *planeRevTransform = new Qt3DCore::QTransform(planeRevEntity);
|
||||
planeRevTransform->setTranslation(QVector3D(limits.x()/2, limits.y()/2, -1));
|
||||
planeRevTransform->setRotationX(-90);
|
||||
planeRev->setHeight(limits.y()*2);
|
||||
planeRev->setWidth(limits.x()*2);
|
||||
planeRevEntity->addComponent(planeRev);
|
||||
planeRevEntity->addComponent(planeMaterial);
|
||||
planeRevEntity->addComponent(planeRevTransform);
|
||||
|
||||
toolEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DExtras::QCylinderMesh* toolMesh = new Qt3DExtras::QCylinderMesh(toolEntity);
|
||||
Qt3DExtras::QPhongMaterial* toolMaterial = new Qt3DExtras::QPhongMaterial(toolEntity);
|
||||
toolTransform = new Qt3DCore::QTransform(toolEntity);
|
||||
toolTransform->setTranslation(limits + QVector3D(0,0,5));
|
||||
toolTransform->setRotationX(90);
|
||||
toolMaterial->setDiffuse(QColorConstants::White);
|
||||
toolMaterial->setAmbient(QColor(64,64,64));
|
||||
toolMesh->setRadius(1);
|
||||
toolMesh->setLength(10);
|
||||
toolEntity->addComponent(toolMesh);
|
||||
toolEntity->addComponent(toolMaterial);
|
||||
toolEntity->addComponent(toolTransform);
|
||||
}
|
||||
|
||||
void BackPlotWidget::showView(ViewPos viewPos)
|
||||
{
|
||||
if(viewPos == VIEW_TOP)
|
||||
{
|
||||
view.camera()->setPosition(QVector3D(limits.x()/2, limits.y()/2, limits.z()*4));
|
||||
view.camera()->setUpVector(QVector3D(0, 1, 0));
|
||||
}
|
||||
else if(viewPos == VIEW_FRONT)
|
||||
{
|
||||
view.camera()->setPosition(QVector3D(limits.x()/2, 0-limits.y()*4, limits.z()/2));
|
||||
view.camera()->setUpVector(QVector3D(0, 0, 1));
|
||||
}
|
||||
else if(viewPos == VIEW_LEFT)
|
||||
{
|
||||
view.camera()->setPosition(QVector3D(0-limits.x()*4, limits.y()/2, limits.z()/2));
|
||||
view.camera()->setUpVector(QVector3D(0, 0, 1));
|
||||
}
|
||||
else if(viewPos == VIEW_RIGHT)
|
||||
{
|
||||
view.camera()->setPosition(QVector3D(limits.x()*4, limits.y()/2, limits.z()/2));
|
||||
view.camera()->setUpVector(QVector3D(0, 0, 1));
|
||||
}
|
||||
|
||||
if(viewPos == VIEW_TOP)
|
||||
view.camera()->setViewCenter(QVector3D(limits.x()/2, limits.y()/2, 0));
|
||||
else
|
||||
view.camera()->setViewCenter(QVector3D(limits.x()/2, limits.y()/2, limits.z()/2));
|
||||
camController->setZoomFactor(1);
|
||||
}
|
||||
|
||||
void BackPlotWidget::positionUpdate(std::vector<int> position)
|
||||
{
|
||||
assert(position.size() >= 3);
|
||||
toolTransform->setTranslation(limits - QVector3D(position[0]/1000.0, position[1]/1000.0, (position[2]/1000.0)-5));
|
||||
}
|
||||
|
||||
void BackPlotWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
double aspectRatio = static_cast<double>(geometry().width())/geometry().height();
|
||||
double screenWidth;
|
||||
double screenHeight;
|
||||
if(aspectRatio > 1.0)
|
||||
{
|
||||
screenWidth = 500.0;
|
||||
screenHeight = screenWidth/aspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
screenHeight = 500;
|
||||
screenWidth = aspectRatio*screenHeight;
|
||||
}
|
||||
camController->setOrthoSize(QVector2D(screenWidth, screenHeight));
|
||||
}
|
||||
|
||||
void BackPlotWidget::drawBox(const QVector3D& a, const QVector3D& b, Qt3DRender::QMaterial* material, Qt3DCore::QEntity* parent)
|
||||
{
|
||||
drawLine(QVector3D(a.x(), a.y(), a.z()), QVector3D(b.x(), a.y(), a.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), a.y(), a.z()), QVector3D(a.x(), b.y(), a.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), a.y(), a.z()), QVector3D(a.x(), a.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(b.x(), a.y(), a.z()), QVector3D(b.x(), b.y(), a.z()), material, parent);
|
||||
drawLine(QVector3D(b.x(), a.y(), a.z()), QVector3D(b.x(), a.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), b.y(), a.z()), QVector3D(b.x(), b.y(), a.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), b.y(), a.z()), QVector3D(a.x(), b.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), a.y(), b.z()), QVector3D(b.x(), a.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), a.y(), b.z()), QVector3D(a.x(), b.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(b.x(), b.y(), a.z()), QVector3D(b.x(), b.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(a.x(), b.y(), b.z()), QVector3D(b.x(), b.y(), b.z()), material, parent);
|
||||
drawLine(QVector3D(b.x(), a.y(), b.z()), QVector3D(b.x(), b.y(), b.z()), material, parent);
|
||||
}
|
||||
|
||||
QByteArray BackPlotWidget::removeComments(const QByteArray& program)
|
||||
{
|
||||
int commentCounter = 0;
|
||||
QByteArray out;
|
||||
for(char ch : program)
|
||||
{
|
||||
if(ch == '/')
|
||||
++commentCounter;
|
||||
else if(ch == '\\' && commentCounter > 0)
|
||||
--commentCounter;
|
||||
else if(commentCounter == 0)
|
||||
out.push_back(ch);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QList<int> BackPlotWidget::getFields(QByteArray command)
|
||||
{
|
||||
command.remove(0, 2);
|
||||
QList<QByteArray> fieldsText = command.split(',');
|
||||
QList<int> fields;
|
||||
for(const QByteArray& field : fieldsText)
|
||||
{
|
||||
if(field.size() == 0)
|
||||
fields.push_back(NO_FIELD);
|
||||
else
|
||||
fields.push_back(field.toInt());
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
void BackPlotWidget::programChanged(QByteArray program)
|
||||
{
|
||||
for(Qt3DCore::QEntity* entitiy : pathEntitys)
|
||||
delete entitiy;
|
||||
pathEntitys.clear();
|
||||
|
||||
program = removeComments(program);
|
||||
QList<QByteArray> commands = program.split(';');
|
||||
|
||||
QVector3D lastPos = touchoffPosition;
|
||||
|
||||
qDebug()<<__func__;
|
||||
|
||||
for(QByteArray& command : commands)
|
||||
{
|
||||
command = command.trimmed().toUpper();
|
||||
if(command.size() < 2)
|
||||
continue;
|
||||
if(command[0] == 'P' || command[0] == 'G')
|
||||
{
|
||||
QList<int> fields = getFields(command);
|
||||
QVector3D pos;
|
||||
|
||||
if(fields.size() <= 2 || fields[2] == NO_FIELD)
|
||||
pos.setZ(command[1] != 'R' ? lastPos.z()-touchoffPosition.z() : 0);
|
||||
else if(fields.size() > 2)
|
||||
pos.setZ(fields[2]/1000.0);
|
||||
|
||||
if(fields.size() <= 1 || fields[1] == NO_FIELD)
|
||||
pos.setY(command[1] != 'R' ? lastPos.y()-touchoffPosition.y() : 0);
|
||||
else if(fields.size() > 1)
|
||||
pos.setY(fields[1]/1000.0);
|
||||
|
||||
if(fields.size() <= 0 || fields[0] == NO_FIELD)
|
||||
pos.setX(command[1] != 'R' ? lastPos.x()-touchoffPosition.x() : 0);
|
||||
else if(fields.size() > 0)
|
||||
pos.setX(fields[0]/1000.0);
|
||||
|
||||
if(command[1] == 'A')
|
||||
pos = pos+touchoffPosition;
|
||||
else if(command[1] == 'R')
|
||||
pos = pos+lastPos;
|
||||
|
||||
pathEntitys.push_back(new Qt3DCore::QEntity(rootEntity));
|
||||
drawLine(limits-lastPos, limits-pos, command[0] == 'G' ? rapidMaterial : pathMaterial, pathEntitys.back());
|
||||
|
||||
lastPos = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BackPlotWidget::touchoffUpdate(std::vector<int> position)
|
||||
{
|
||||
assert(position.size() >= 3);
|
||||
touchoffPosition.setX(position[0]/1000.0);
|
||||
touchoffPosition.setY(position[1]/1000.0);
|
||||
touchoffPosition.setZ(position[2]/1000.0);
|
||||
touchoffTransform->setTranslation(limits-touchoffPosition);
|
||||
}
|
||||
|
||||
void BackPlotWidget::drawLine(const QVector3D& start, const QVector3D& end, Qt3DRender::QMaterial* material, Qt3DCore::QEntity* parent)
|
||||
{
|
||||
Qt3DCore::QGeometry* geometry = new Qt3DCore::QGeometry(parent);
|
||||
|
||||
// position vertices (start and end)
|
||||
QByteArray bufferBytes;
|
||||
bufferBytes.resize(3 * 2 * sizeof(float)); // start.x, start.y, start.end, end.x, end.y, end.z
|
||||
float* positions = reinterpret_cast<float*>(bufferBytes.data());
|
||||
*positions++ = start.x();
|
||||
*positions++ = start.y();
|
||||
*positions++ = start.z();
|
||||
*positions++ = end.x();
|
||||
*positions++ = end.y();
|
||||
*positions++ = end.z();
|
||||
|
||||
Qt3DCore::QBuffer* buf = new Qt3DCore::QBuffer(geometry);
|
||||
buf->setData(bufferBytes);
|
||||
|
||||
auto *positionAttribute = new Qt3DCore::QAttribute(geometry);
|
||||
positionAttribute->setName(Qt3DCore::QAttribute::defaultPositionAttributeName());
|
||||
positionAttribute->setVertexBaseType(Qt3DCore::QAttribute::Float);
|
||||
positionAttribute->setVertexSize(3);
|
||||
positionAttribute->setAttributeType(Qt3DCore::QAttribute::VertexAttribute);
|
||||
positionAttribute->setBuffer(buf);
|
||||
positionAttribute->setByteStride(3 * sizeof(float));
|
||||
positionAttribute->setCount(2);
|
||||
geometry->addAttribute(positionAttribute); // We add the vertices in the geometry
|
||||
|
||||
// connectivity between vertices
|
||||
QByteArray indexBytes;
|
||||
indexBytes.resize(2 * sizeof(unsigned int)); // start to end
|
||||
unsigned int *indices = reinterpret_cast<unsigned int*>(indexBytes.data());
|
||||
*indices++ = 0;
|
||||
*indices++ = 1;
|
||||
|
||||
Qt3DCore::QBuffer* indexBuffer = new Qt3DCore::QBuffer(geometry);
|
||||
indexBuffer->setData(indexBytes);
|
||||
|
||||
Qt3DCore::QAttribute *indexAttribute = new Qt3DCore::QAttribute(geometry);
|
||||
indexAttribute->setVertexBaseType(Qt3DCore::QAttribute::UnsignedInt);
|
||||
indexAttribute->setAttributeType(Qt3DCore::QAttribute::IndexAttribute);
|
||||
indexAttribute->setBuffer(indexBuffer);
|
||||
indexAttribute->setCount(2);
|
||||
geometry->addAttribute(indexAttribute); // We add the indices linking the points in the geometry
|
||||
|
||||
// mesh
|
||||
auto *line = new Qt3DRender::QGeometryRenderer(parent);
|
||||
line->setGeometry(geometry);
|
||||
line->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
|
||||
|
||||
// entity
|
||||
auto *lineEntity = new Qt3DCore::QEntity(parent);
|
||||
lineEntity->addComponent(line);
|
||||
lineEntity->addComponent(material);
|
||||
}
|
86
backplotwidget.h
Normal file
86
backplotwidget.h
Normal file
@ -0,0 +1,86 @@
|
||||
#ifndef BACKPLOTWIDGET_H
|
||||
#define BACKPLOTWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <Qt3DExtras/qtorusmesh.h>
|
||||
#include <Qt3DRender/qmesh.h>
|
||||
#include <Qt3DRender/qtechnique.h>
|
||||
#include <Qt3DRender/qmaterial.h>
|
||||
#include <Qt3DRender/qeffect.h>
|
||||
#include <Qt3DRender/qtexture.h>
|
||||
#include <Qt3DRender/qrenderpass.h>
|
||||
#include <Qt3DRender/qsceneloader.h>
|
||||
|
||||
#include <Qt3DCore/qtransform.h>
|
||||
#include <Qt3DCore/qaspectengine.h>
|
||||
|
||||
#include <Qt3DRender/qrenderaspect.h>
|
||||
#include <Qt3DExtras/qforwardrenderer.h>
|
||||
|
||||
#include <Qt3DExtras/qt3dwindow.h>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPhongMaterial>
|
||||
|
||||
#include "orbitcameracontroller.h"
|
||||
|
||||
class BackPlotWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Qt3DExtras::Qt3DWindow view;
|
||||
OrbitCameraController *camController;
|
||||
Qt3DCore::QEntity* rootEntity = nullptr;
|
||||
Qt3DExtras::QPhongMaterial* axisMaterial;
|
||||
Qt3DExtras::QPhongMaterial* rapidMaterial;
|
||||
Qt3DExtras::QPhongMaterial* pathMaterial;
|
||||
QWidget *containerWdiget;
|
||||
|
||||
Qt3DCore::QEntity* toolEntity;
|
||||
Qt3DCore::QTransform *toolTransform;
|
||||
std::vector<Qt3DCore::QEntity*> pathEntitys;
|
||||
|
||||
Qt3DCore::QTransform *touchoffTransform;
|
||||
|
||||
QVector3D limits;
|
||||
QVector3D touchoffPosition;
|
||||
|
||||
QHBoxLayout hLayout;
|
||||
|
||||
static constexpr int NO_FIELD = std::numeric_limits<int>::min();
|
||||
|
||||
public:
|
||||
|
||||
typedef int ViewPos;
|
||||
static constexpr ViewPos VIEW_TOP = 0;
|
||||
static constexpr ViewPos VIEW_FRONT = 1;
|
||||
static constexpr ViewPos VIEW_LEFT = 2;
|
||||
static constexpr ViewPos VIEW_RIGHT = 3;
|
||||
|
||||
private:
|
||||
|
||||
static void drawBox(const QVector3D& bottomCloseLeft, const QVector3D& topFarRight, Qt3DRender::QMaterial* material, Qt3DCore::QEntity* parent);
|
||||
static void drawLine(const QVector3D& start, const QVector3D& end, Qt3DRender::QMaterial* material, Qt3DCore::QEntity* parent);
|
||||
static QList<int> getFields(QByteArray command);
|
||||
QByteArray removeComments(const QByteArray& program);
|
||||
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void positionUpdate(std::vector<int> position);
|
||||
void touchoffUpdate(std::vector<int> position);
|
||||
void programChanged(const QByteArray program);
|
||||
void showView(ViewPos view);
|
||||
|
||||
public:
|
||||
explicit BackPlotWidget(QWidget *parent = nullptr, double xLimits = 190, double yLimits = 92, double zLimits = 85);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // BACKPLOTWIDGET_H
|
||||
|
544
gcodetovhf.cpp
Normal file
544
gcodetovhf.cpp
Normal file
@ -0,0 +1,544 @@
|
||||
#include "gcodetovhf.h"
|
||||
|
||||
#include <QList>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QDebug>
|
||||
|
||||
static constexpr double TOLLERANCE = 0.005;
|
||||
|
||||
QByteArray removeComments(const QByteArray& gcodeCommand)
|
||||
{
|
||||
size_t comment = 0;
|
||||
QByteArray output;
|
||||
for(size_t i = 0; i < gcodeCommand.size(); ++i)
|
||||
{
|
||||
if(gcodeCommand[i] == '(')
|
||||
++comment;
|
||||
else if(gcodeCommand[i] == ')' && comment > 0)
|
||||
--comment;
|
||||
|
||||
if(comment == 0)
|
||||
output.push_back(gcodeCommand[i]);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
class Gmove
|
||||
{
|
||||
public:
|
||||
int gmode = 0;
|
||||
int coordmode = 54;
|
||||
bool relative = false;
|
||||
double xStart = 0;
|
||||
double yStart = 0;
|
||||
double zStart = 0;
|
||||
double aStart = 0;
|
||||
|
||||
bool x = false;
|
||||
bool y = false;
|
||||
bool z = false;
|
||||
bool a = false;
|
||||
bool i = false;
|
||||
bool j = false;
|
||||
bool p = false;
|
||||
bool r = false;
|
||||
bool l = false;
|
||||
|
||||
double xVal;
|
||||
double yVal;
|
||||
double zVal;
|
||||
double aVal;
|
||||
double iVal;
|
||||
double jVal;
|
||||
double pVal;
|
||||
double rVal;
|
||||
double lVal;
|
||||
|
||||
void fill()
|
||||
{
|
||||
if(!x)
|
||||
xVal = relative ? 0 : xStart;
|
||||
if(!y)
|
||||
yVal = relative ? 0 : yStart;
|
||||
if(!z)
|
||||
zVal = relative ? 0 : zStart;
|
||||
if(!a)
|
||||
aVal = relative ? 0 : aStart;
|
||||
|
||||
x = true;
|
||||
y = true;
|
||||
z = true;
|
||||
}
|
||||
void makeAbsolute()
|
||||
{
|
||||
if(!relative)
|
||||
return;
|
||||
if(x)
|
||||
xVal = xVal+xStart;
|
||||
if(y)
|
||||
yVal = yVal+yStart;
|
||||
if(z)
|
||||
zVal = zVal+zStart;
|
||||
if(a)
|
||||
aVal = aVal+aStart;
|
||||
relative = false;
|
||||
}
|
||||
};
|
||||
|
||||
static QString checkMove(Gmove gmove)
|
||||
{
|
||||
if(gmove.gmode == 0 || gmove.gmode == 1)
|
||||
{
|
||||
if(!gmove.x && !gmove.y && !gmove.z)
|
||||
return "At least one coordinate is required for linear move.";
|
||||
else if(gmove.i || gmove.j || gmove.p || gmove.r)
|
||||
return "Invalid parameter in linear move.";
|
||||
}
|
||||
else if(gmove.gmode == 2 || gmove.gmode == 3)
|
||||
{
|
||||
if(!gmove.x && !gmove.y && !gmove.z)
|
||||
return "At least one coordinate is required for arc move.";
|
||||
else if(!gmove.i && !gmove.j && !gmove.r)
|
||||
return "No arc center or radius defined.";
|
||||
else if((gmove.i || gmove.j) && gmove.r)
|
||||
return "More than one arc center defined.";
|
||||
|
||||
gmove.fill();
|
||||
gmove.makeAbsolute();
|
||||
QVector2D xyVect(gmove.xVal, gmove.yVal);
|
||||
QVector2D startVect(gmove.xStart, gmove.yStart);
|
||||
|
||||
if(gmove.r)
|
||||
{
|
||||
if(gmove.rVal < TOLLERANCE)
|
||||
return "Arc radius must be larger than zero.";
|
||||
if((xyVect-startVect).length()/2 > gmove.rVal+TOLLERANCE)
|
||||
return "Arc radius to small to fit to provided sart and end points.";
|
||||
}
|
||||
else
|
||||
{
|
||||
/*QVector2D ijVect(gmove.i ? gmove.iVal : 0, gmove.j ? gmove.jVal : 0);
|
||||
QVector2D center = startVect+ijVect;
|
||||
double r = (center-xyVect).length();
|
||||
double r2 = (center-startVect).length();
|
||||
|
||||
if(abs(r-r2) > TOLLERANCE)
|
||||
return "Arc start and end point radii differ";*/
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
static QByteArray generateLinearCommand(const Gmove& gmove)
|
||||
{
|
||||
assert(gmove.gmode == 0 || gmove.gmode == 1);
|
||||
|
||||
QByteArray output;
|
||||
if(gmove.gmode == 0)
|
||||
{
|
||||
if(gmove.relative)
|
||||
output.append("GR");
|
||||
else if(gmove.coordmode != 53)
|
||||
output.append("GA");
|
||||
else
|
||||
output.append("GB");
|
||||
}
|
||||
else if(gmove.gmode == 1)
|
||||
{
|
||||
if(gmove.relative)
|
||||
output.append("PR");
|
||||
else if(gmove.coordmode != 53)
|
||||
output.append("PA");
|
||||
else
|
||||
output.append("PB");
|
||||
}
|
||||
else
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
if(gmove.x)
|
||||
output.append(QByteArray::number(static_cast<int>(gmove.xVal*1000)));
|
||||
if(gmove.y || gmove.z || gmove.a)
|
||||
output.append(',');
|
||||
if(gmove.y)
|
||||
output.append(QByteArray::number(static_cast<int>(gmove.yVal*1000)));
|
||||
if(gmove.z || gmove.a)
|
||||
output.append(',');
|
||||
if(gmove.z)
|
||||
output.append(QByteArray::number(static_cast<int>(gmove.zVal*-1000)));
|
||||
if(gmove.a)
|
||||
{
|
||||
output.append(',');
|
||||
output.append(QByteArray::number(static_cast<int>(gmove.aVal*1000)));
|
||||
}
|
||||
|
||||
output.append(';');
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static bool findCircleCenter(QVector2D a, QVector2D b, double r, bool leftHanded, QVector2D& result)
|
||||
{ float distance = (a-b).length();
|
||||
if(distance/2 > r+TOLLERANCE)
|
||||
return false;
|
||||
|
||||
QVector2D baseVect = (b-a).normalized();
|
||||
float loftDist = sqrt(pow(r, 2)-pow(distance/2, 2));
|
||||
QVector2D loftVect;
|
||||
if(leftHanded)
|
||||
{
|
||||
loftVect.setX(baseVect.y()*-1);
|
||||
loftVect.setY(baseVect.x());
|
||||
}
|
||||
else
|
||||
{
|
||||
loftVect.setX(baseVect.y());
|
||||
loftVect.setY(baseVect.x()*-1);
|
||||
}
|
||||
loftVect = loftVect*loftDist;
|
||||
baseVect = baseVect*(distance/2);
|
||||
result = a+baseVect+loftVect;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool withinTollerance(double a, double b)
|
||||
{
|
||||
return a+TOLLERANCE > b && a-TOLLERANCE < b;
|
||||
}
|
||||
|
||||
static QByteArray generateArcCommand(Gmove gmove, size_t resolution)
|
||||
{
|
||||
assert(gmove.gmode == 2 || gmove.gmode == 3);
|
||||
gmove.fill();
|
||||
gmove.makeAbsolute();
|
||||
|
||||
QVector2D startMove(gmove.xStart, gmove.yStart);
|
||||
QVector2D endMove(gmove.xVal, gmove.yVal);
|
||||
QVector2D center;
|
||||
double radius;
|
||||
if(gmove.i && gmove.j)
|
||||
{
|
||||
center.setX(gmove.xStart+gmove.iVal);
|
||||
center.setY(gmove.yStart+gmove.jVal);
|
||||
radius = (QVector2D(gmove.xStart, gmove.yStart)-center).length();
|
||||
}
|
||||
else if(gmove.r)
|
||||
{
|
||||
findCircleCenter(QVector2D(gmove.xStart, gmove.yStart), QVector2D(gmove.xVal, gmove.yVal), gmove.rVal, gmove.gmode == 3, center);
|
||||
radius = gmove.rVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical()<<"Can't create arc move";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QVector2D aVector = startMove-center;
|
||||
QVector2D bVector = endMove-center;
|
||||
double startAngle = acos(aVector.x()/(aVector.length()));
|
||||
double endAngle = acos(bVector.x()/(bVector.length()));
|
||||
|
||||
{
|
||||
bool a = false;
|
||||
bool b = false;
|
||||
QVector2D computedEnpoint(cos(endAngle)*radius+center.x(), sin(endAngle)*radius+center.y());
|
||||
if((computedEnpoint-endMove).length() > TOLLERANCE)
|
||||
endAngle = 0 - endAngle;
|
||||
|
||||
QVector2D computedSart(cos(startAngle)*radius+center.x(), sin(startAngle)*radius+center.y());
|
||||
if((computedSart-startMove).length() > TOLLERANCE)
|
||||
startAngle = 0 - startAngle;
|
||||
|
||||
if((startAngle-endAngle) < 0)
|
||||
startAngle = startAngle+2*M_PI;
|
||||
}
|
||||
{
|
||||
/*QVector2D computedEnpoint(cos(endAngle)*radius+center.x(), sin(endAngle)*radius+center.y());
|
||||
assert((computedEnpoint-endMove).length() > TOLLERANCE);
|
||||
|
||||
QVector2D computedSart(cos(startAngle)*radius+center.x(), sin(startAngle)*radius+center.y());
|
||||
assert((computedSart-startMove).length() > TOLLERANCE);*/
|
||||
}
|
||||
|
||||
|
||||
if(gmove.p && gmove.pVal > 1)
|
||||
endAngle = endAngle+std::copysign(1.0, endAngle-startAngle)*2*(gmove.pVal-1)*M_PI;
|
||||
|
||||
size_t steps = (resolution*(fabs(endAngle-startAngle)))/(2*M_PI);
|
||||
|
||||
double angleStep;
|
||||
if(gmove.gmode == 2)
|
||||
angleStep = (endAngle-startAngle)/steps;
|
||||
else
|
||||
angleStep = (2*M_PI-(startAngle-endAngle))/steps;
|
||||
|
||||
QByteArray output;
|
||||
double deltaZ = (gmove.zVal - gmove.zStart)/steps;
|
||||
for(size_t i = 1; i < steps; ++i)
|
||||
{
|
||||
double workAngle = startAngle+angleStep*i;
|
||||
QVector2D point;
|
||||
point.setX(cos(workAngle)*radius);
|
||||
point.setY(sin(workAngle)*radius);
|
||||
point = point+center;
|
||||
QByteArray command("PA");
|
||||
command.append(QByteArray::number(static_cast<int>(point.x()*1000)) + "," +
|
||||
QByteArray::number(static_cast<int>(point.y()*1000)) + "," +
|
||||
QByteArray::number(static_cast<int>((gmove.zStart+deltaZ*i)*-1000)) + ";");
|
||||
output.append(command);
|
||||
}
|
||||
|
||||
QByteArray command("PA");
|
||||
command.append(QByteArray::number(static_cast<int>(gmove.xVal*1000)) +"," +
|
||||
QByteArray::number(static_cast<int>(gmove.yVal*1000)) + "," +
|
||||
QByteArray::number(static_cast<int>(gmove.zVal*-1000)) + ";");
|
||||
output.append(command);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static QByteArray generateDrillingCycle(Gmove gmove)
|
||||
{
|
||||
if(!gmove.r)
|
||||
return QByteArray();
|
||||
if(!gmove.z)
|
||||
return QByteArray();
|
||||
gmove.gmode = 0;
|
||||
if(gmove.relative)
|
||||
gmove.rVal = gmove.rVal+gmove.zVal;
|
||||
gmove.makeAbsolute();
|
||||
|
||||
QByteArray output("GA,,"+QByteArray::number(static_cast<int>(gmove.rVal*-1000))+"; ");
|
||||
if(gmove.x || gmove.y)
|
||||
{
|
||||
gmove.z = false;
|
||||
output.append(generateLinearCommand(gmove));
|
||||
}
|
||||
|
||||
size_t count = gmove.l ? gmove.lVal : 1;
|
||||
|
||||
for(size_t i = 0; i < count; ++i)
|
||||
{
|
||||
output.append("PA,,"+QByteArray::number(static_cast<int>(gmove.zVal*-1000))+"; ");
|
||||
output.append("GA,,"+QByteArray::number(static_cast<int>(gmove.rVal*-1000))+"; ");
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
static QByteArray generateMoveCommand(const Gmove& gmove)
|
||||
{
|
||||
if(gmove.gmode == 0 || gmove.gmode == 1)
|
||||
return generateLinearCommand(gmove);
|
||||
else if(gmove.gmode == 2 || gmove.gmode == 3)
|
||||
return generateArcCommand(gmove, 100);
|
||||
else if(gmove.gmode == 81)
|
||||
return generateDrillingCycle(gmove);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
static Gmove doMove(Gmove gmove)
|
||||
{
|
||||
gmove.fill();
|
||||
gmove.makeAbsolute();
|
||||
|
||||
Gmove out;
|
||||
out.xStart = gmove.xVal;
|
||||
out.yStart = gmove.yVal;
|
||||
out.zStart = gmove.zVal;
|
||||
out.aStart = gmove.aVal;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QByteArray gcodeToVhf(const QByteArray& gcode, bool* ok, QList<QString>* errors)
|
||||
{
|
||||
int gmode = -1;
|
||||
int coordmode = 54;
|
||||
bool relmode = false;
|
||||
double spinspeed = 1000;
|
||||
double feedrate = std::numeric_limits<double>::min();
|
||||
int tool = 0;
|
||||
Gmove move;
|
||||
bool clearMove;
|
||||
|
||||
QByteArray output;
|
||||
|
||||
if(gcode.size()< 2)
|
||||
return output;
|
||||
|
||||
QList<QByteArray> gcodeCommands = gcode.toUpper().split('\n');
|
||||
|
||||
if(ok)
|
||||
*ok = true;
|
||||
|
||||
size_t line = 0;
|
||||
for(QByteArray& command : gcodeCommands)
|
||||
{
|
||||
++line;
|
||||
move.gmode = gmode;
|
||||
move.coordmode = coordmode;
|
||||
move.relative = relmode;
|
||||
bool startSpindle = false;
|
||||
bool toolchange = false;
|
||||
command = removeComments(command);
|
||||
|
||||
QList<QByteArray> subcommands = command.split(' ');
|
||||
for(QByteArray& subcommand : subcommands)
|
||||
{
|
||||
subcommand = subcommand.trimmed();
|
||||
if(subcommand.size() < 1)
|
||||
continue;
|
||||
if(subcommand[0] == 'G')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
int gcodeCode = subcommand.toInt();
|
||||
if(gcodeCode >= 0 && gcodeCode <= 3 || gcodeCode == 81)
|
||||
gmode = gcodeCode;
|
||||
else if(gcodeCode == 80 && gmode == 81)
|
||||
gmode = 0;
|
||||
else if(gcodeCode == 91)
|
||||
relmode = true;
|
||||
else if(gcodeCode == 90)
|
||||
relmode = false;
|
||||
else if(gcodeCode == 53)
|
||||
move.coordmode = 53;
|
||||
else if(gcodeCode > 54 && gcodeCode < 59)
|
||||
move.coordmode = gcodeCode;
|
||||
else if(gcodeCode == 28)
|
||||
output.append("PB0,0,0,0; ");
|
||||
else if(gcodeCode == 64)
|
||||
clearMove = true;
|
||||
|
||||
move.gmode = gmode;
|
||||
if(move.coordmode != 53)
|
||||
move.coordmode = coordmode;
|
||||
move.relative = relmode;
|
||||
}
|
||||
else if(subcommand[0] == 'M')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
int mCode = subcommand.toDouble();
|
||||
switch(mCode)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
output.append("!S; ");
|
||||
break;
|
||||
case 3:
|
||||
startSpindle = true;
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
output.append("RVS0; ");
|
||||
startSpindle = false;
|
||||
break;
|
||||
case 6:
|
||||
toolchange = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(subcommand[0] == 'F')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
double newFeedrate = subcommand.toDouble();
|
||||
if(abs(newFeedrate - feedrate) > TOLLERANCE)
|
||||
{
|
||||
feedrate = newFeedrate;
|
||||
output.append("VS" + QByteArray::number(static_cast<int>(feedrate*(1000.0/60.0))) + "; ");
|
||||
}
|
||||
}
|
||||
else if(subcommand[0] == 'T')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
tool = subcommand.toInt();
|
||||
}
|
||||
else if(subcommand[0] == 'S')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
spinspeed = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'X')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.x = true;
|
||||
move.xVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'Y')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.y = true;
|
||||
move.yVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'Z')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.z = true;
|
||||
move.zVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'P')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.p = true;
|
||||
move.pVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'A')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.a = true;
|
||||
move.aVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'I')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.i = true;
|
||||
move.iVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'J')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.j = true;
|
||||
move.jVal = subcommand.toDouble();
|
||||
}
|
||||
else if(subcommand[0] == 'R')
|
||||
{
|
||||
subcommand.remove(0, 1);
|
||||
move.r = true;
|
||||
move.rVal = subcommand.toDouble();
|
||||
}
|
||||
}
|
||||
|
||||
if(toolchange)
|
||||
output.append("T" + QByteArray::number(static_cast<int>(tool)) + "; ");
|
||||
if(startSpindle)
|
||||
output.append("RVS" + QByteArray::number(static_cast<int>(spinspeed)) + "; ");
|
||||
if(move.x || move.y || move.z || move.a)
|
||||
{
|
||||
QString error = checkMove(move);
|
||||
if(error.isEmpty())
|
||||
{
|
||||
output.append(generateMoveCommand(move));
|
||||
}
|
||||
else
|
||||
{
|
||||
*ok = false;
|
||||
if(errors)
|
||||
errors->push_back("Error on line " + QString::number(line) + ": " + error);
|
||||
qWarning()<<"Error on line"<<line<<error;
|
||||
}
|
||||
move = doMove(move);
|
||||
}
|
||||
else if(clearMove)
|
||||
move = doMove(move);
|
||||
if(output.size() > 0 && output.back() != '\n')
|
||||
output.push_back('\n');
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
7
gcodetovhf.h
Normal file
7
gcodetovhf.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef GCODETOVHF_H
|
||||
#define GCODETOVHF_H
|
||||
#include <QByteArray>
|
||||
|
||||
QByteArray gcodeToVhf(const QByteArray& gcode, bool* ok, QList<QString>* errors = nullptr);
|
||||
|
||||
#endif // GCODETOVHF_H
|
55
led.cpp
Normal file
55
led.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*UVOS*/
|
||||
|
||||
/* This file is part of MAClient copyright © 2021 Carl Philipp Klemm.
|
||||
*
|
||||
* MAClient is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (GPL) version
|
||||
* 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* MAClient 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 MAClient. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "led.h"
|
||||
#include <QPainter>
|
||||
#include <algorithm>
|
||||
|
||||
Led::Led(QWidget* parent): QWidget(parent)
|
||||
{
|
||||
setMinimumSize(QSize(40,40));
|
||||
setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
|
||||
}
|
||||
|
||||
bool Led::lit() const
|
||||
{
|
||||
return lit_;
|
||||
}
|
||||
|
||||
void Led::setLit(bool lit)
|
||||
{
|
||||
if(lit != lit_)
|
||||
{
|
||||
lit_ = lit;
|
||||
stateChanged(lit_);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void Led::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
QPainter ledPainter(this);
|
||||
ledPainter.setRenderHint(QPainter::Antialiasing, true);
|
||||
ledPainter.setPen(Qt::black);
|
||||
if(lit_)
|
||||
ledPainter.setBrush(Qt::green);
|
||||
else
|
||||
ledPainter.setBrush(Qt::red);
|
||||
int size = std::min(rect().width(), rect().height());
|
||||
QRect ellipseRect(rect().x()+(rect().width()-size)/2+1, rect().y()+(rect().height()-size)/2+1, size-2, size-2);
|
||||
ledPainter.drawEllipse(ellipseRect);
|
||||
}
|
45
led.h
Normal file
45
led.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*UVOS*/
|
||||
|
||||
/* This file is part of MAClient copyright © 2021 Carl Philipp Klemm.
|
||||
*
|
||||
* MAClient is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (GPL) version
|
||||
* 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* MAClient 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 MAClient. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LED_H
|
||||
#define LED_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class Led : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
bool lit_ = false;
|
||||
|
||||
public:
|
||||
|
||||
Led(QWidget* parent = nullptr);
|
||||
bool lit() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void setLit(bool lit);
|
||||
|
||||
signals:
|
||||
|
||||
void stateChanged(bool lit);
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
|
||||
};
|
||||
#endif // LED_H
|
64
main.cpp
Normal file
64
main.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSerialPort>
|
||||
#include <QTcpSocket>
|
||||
#include <QMessageBox>
|
||||
#include <QCommandLineParser>
|
||||
#include <QThread>
|
||||
|
||||
#include "vhfmill.h"
|
||||
#include "vhfmillthread.h"
|
||||
#include "mainobject.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
QCoreApplication::setOrganizationName("UVOS");
|
||||
QCoreApplication::setOrganizationDomain("uvos.xyz");
|
||||
QCoreApplication::setApplicationName("VHFMill");
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("VHF mill cnc interface");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption tcpOption(QStringList() << "t" << "tcp", QCoreApplication::translate("main", "Use Tcp connection"));
|
||||
parser.addOption(tcpOption);
|
||||
QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main",
|
||||
"Set server host ip addres"), "adress");
|
||||
parser.addOption(hostOption);
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main",
|
||||
"Set server Port in TCP mode or Serial port in serial mode"), "port");
|
||||
parser.addOption(portOption);
|
||||
QCommandLineOption serialOption(QStringList() << "s" << "serial", QCoreApplication::translate("main",
|
||||
"Use serial connection"));
|
||||
parser.addOption(serialOption);
|
||||
QCommandLineOption settingsPathOption(QStringList() << "c" << "config", QCoreApplication::translate("main",
|
||||
"Set config file"), "configFilePath");
|
||||
parser.addOption(settingsPathOption);
|
||||
QCommandLineOption secondaryOption(QStringList() << "e" << "secondary", QCoreApplication::translate("main",
|
||||
"Set if instance is not main instance"));
|
||||
parser.addOption(secondaryOption);
|
||||
parser.process(a);
|
||||
|
||||
int port = 6856;
|
||||
QString serialPort("ttyUSB0");
|
||||
QString host("127.0.0.1");
|
||||
if(parser.isSet(hostOption))
|
||||
host = parser.value(hostOption);
|
||||
if(parser.isSet(tcpOption) && parser.isSet(portOption))
|
||||
port = parser.value(portOption).toInt();
|
||||
else if(parser.isSet(portOption))
|
||||
serialPort = parser.value(portOption);
|
||||
|
||||
VhfMillThread vhfMillTread(parser.isSet(tcpOption), port, host, serialPort);
|
||||
MainObject mainObject(&a, &vhfMillTread);
|
||||
vhfMillTread.start();
|
||||
|
||||
int ret = a.exec();
|
||||
|
||||
vhfMillTread.exit();
|
||||
return ret;
|
||||
}
|
33
mainobject.cpp
Normal file
33
mainobject.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "mainobject.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
MainObject::MainObject(QApplication* appI, VhfMillThread* millThreadI, QObject *parent):
|
||||
app(appI),
|
||||
millThread(millThreadI),
|
||||
QObject{parent}
|
||||
{
|
||||
connect(millThread, &VhfMillThread::ready, this, &MainObject::activate);
|
||||
}
|
||||
|
||||
void MainObject::activate()
|
||||
{
|
||||
if(millThread->ret != 0)
|
||||
{
|
||||
if(millThread->ret == -2)
|
||||
QMessageBox::critical(nullptr, "Error", "Can not connect to to Server");
|
||||
if(millThread->ret == -3)
|
||||
QMessageBox::critical(nullptr, "Error", "Can not open serial port read write");
|
||||
}
|
||||
else
|
||||
{
|
||||
w = new MainWindow(millThread->mill);
|
||||
app->installEventFilter(w);
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
|
||||
MainObject::~MainObject()
|
||||
{
|
||||
if(w)
|
||||
delete w;
|
||||
}
|
26
mainobject.h
Normal file
26
mainobject.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef MAINOBJECT_H
|
||||
#define MAINOBJECT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "vhfmillthread.h"
|
||||
|
||||
class MainObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
MainWindow* w;
|
||||
QApplication* app;
|
||||
VhfMillThread* millThread;
|
||||
|
||||
public:
|
||||
explicit MainObject(QApplication* appI, VhfMillThread* millThreadI, QObject *parent = nullptr);
|
||||
~MainObject();
|
||||
|
||||
public slots:
|
||||
void activate();
|
||||
};
|
||||
|
||||
#endif // MAINOBJECT_H
|
552
mainwindow.cpp
Normal file
552
mainwindow.cpp
Normal file
@ -0,0 +1,552 @@
|
||||
#include "mainwindow.h"
|
||||
#include "./ui_mainwindow.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "gcodetovhf.h"
|
||||
|
||||
MainWindow::MainWindow(VhfMill* mill, QWidget *parent)
|
||||
: mill_(mill), QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
viewTopAction(QKeySequence(Qt::Key_7), this, 0, 0, Qt::ApplicationShortcut),
|
||||
viewFrontAction(QKeySequence(Qt::Key_1), this, 0, 0, Qt::ApplicationShortcut),
|
||||
viewLeftAction(QKeySequence(Qt::Key_9), this, 0, 0, Qt::ApplicationShortcut),
|
||||
viewRightAction(QKeySequence(Qt::Key_3), this, 0, 0, Qt::ApplicationShortcut)
|
||||
{
|
||||
installEventFilter(this);
|
||||
|
||||
ui->setupUi(this);
|
||||
checkBlocks();
|
||||
|
||||
int splitHight = ui->splitter->size().height();
|
||||
ui->splitter->setSizes({3*splitHight/4, splitHight/4});
|
||||
|
||||
ui->horizontalSlider->setTracking(false);
|
||||
ui->plainTextEdit_compiled->setVisible(false);
|
||||
ui->plainTextEdit_compiled->setWordWrapMode(QTextOption::NoWrap);
|
||||
ui->plainTextEdit->setWordWrapMode(QTextOption::NoWrap);
|
||||
|
||||
connect(mill_, &VhfMill::raiseError, this, &MainWindow::raiseError);
|
||||
connect(mill_, &VhfMill::positionUpdate, this, &MainWindow::positionUpdate);
|
||||
connect(mill_, &VhfMill::gotToolNum, ui->lcd_tool, QOverload<int>::of(&QLCDNumber::display));
|
||||
connect(mill_, &VhfMill::gotOutputs, this, &MainWindow::gotOutputs);
|
||||
connect(mill_, &VhfMill::gotSindleSpeed, this, &MainWindow::gotSpindleSpeed);
|
||||
connect(mill_, &VhfMill::gotProbeState, ui->led_probe, &Led::setLit);
|
||||
connect(mill_, &VhfMill::gotPressureState, this, &MainWindow::gotPressureState);
|
||||
connect(mill_, &VhfMill::initDone, this, &MainWindow::checkBlocks);
|
||||
connect(mill_, &VhfMill::isHomed, this, &MainWindow::isHomed);
|
||||
connect(mill_, &VhfMill::toolChangeDone, this, &MainWindow::toolChangeDone);
|
||||
connect(mill_, &VhfMill::touchoffChanged, this, &MainWindow::touchoffChanged);
|
||||
connect(mill_, &VhfMill::positionUpdate, ui->backPlot, &BackPlotWidget::positionUpdate);
|
||||
|
||||
connect(ui->checkBox_oe1, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 1), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->checkBox_oe2, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 2), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->checkBox_oe3, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 3), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->checkBox_oe4, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 4), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->checkBox_oe5, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 5), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->checkBox_oe6, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 6), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->checkBox_oe7, &QCheckBox::toggled, mill_,
|
||||
[this](bool checked)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 7), Q_ARG(bool, checked));
|
||||
});
|
||||
connect(ui->pushButton_home, &QPushButton::clicked, this, &MainWindow::home);
|
||||
connect(ui->pushButton_homeAll, &QPushButton::clicked, this, [this](){QMetaObject::invokeMethod(mill_, [this]() {mill_->home(VhfMill::AXIS_ALL);}, Qt::QueuedConnection);});
|
||||
connect(ui->pushButton_stopSpindle, &QPushButton::clicked, this, &MainWindow::stopSpindle);
|
||||
connect(ui->horizontalSlider, &QSlider::valueChanged, mill_, &VhfMill::setSpindleSpeed);
|
||||
connect(ui->pushButton_init, &QPushButton::clicked, mill_, &VhfMill::init);
|
||||
connect(ui->pushButton_run, &QPushButton::clicked, this, &MainWindow::run);
|
||||
connect(ui->pushButton_toolUnload, &QPushButton::clicked, this, &MainWindow::toolUnload);
|
||||
connect(ui->pushButton_toolSwitch, &QPushButton::clicked, this, &MainWindow::toolSwitch);
|
||||
connect(ui->pushButton_touchoff, &QPushButton::clicked, this, &MainWindow::touchoff);
|
||||
connect(ui->pushButton_touchoffAll, &QPushButton::clicked, this, &MainWindow::touchoffAll);
|
||||
connect(ui->pushButton_touchoffRst, &QPushButton::clicked, this, &MainWindow::touchoffRst);
|
||||
connect(ui->pushButton_stop, &QPushButton::released, mill_, &VhfMill::stop);
|
||||
connect(ui->actionOpen_Gcode, &QAction::triggered, this, &MainWindow::openGcode);
|
||||
connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openVhfCode);
|
||||
connect(ui->plainTextEdit, &QPlainTextEdit::textChanged, this, &MainWindow::textChanged);
|
||||
connect(ui->radioButton_gcode, &QRadioButton::toggled, ui->plainTextEdit_compiled, &QPlainTextEdit::setVisible);
|
||||
connect(ui->radioButton_gcode, &QRadioButton::toggled, this, &MainWindow::textChanged);
|
||||
connect(ui->comboBox_jogStep, &QComboBox::currentIndexChanged, this, &MainWindow::selectedJogStepChanged);
|
||||
|
||||
connect(ui->pushButton_jogXp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_X, 1);});
|
||||
connect(ui->pushButton_jogXn, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_X, -1);});
|
||||
connect(ui->pushButton_jogYp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Y, -1);});
|
||||
connect(ui->pushButton_jogYn, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Y, 1);});
|
||||
connect(ui->pushButton_jogUp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Z, 1);});
|
||||
connect(ui->pushButton_jogDown, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Z, -1);});
|
||||
connect(ui->pushButton_jogAp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_A, 1);});
|
||||
connect(ui->pushButton_jogAn, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_A, -1);});
|
||||
connect(ui->pushButton_jogXp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_X, 0);});
|
||||
connect(ui->pushButton_jogXn, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_X, 0);});
|
||||
connect(ui->pushButton_jogYp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Y, 0);});
|
||||
connect(ui->pushButton_jogYn, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Y, 0);});
|
||||
connect(ui->pushButton_jogUp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Z, 0);});
|
||||
connect(ui->pushButton_jogDown, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Z, 0);});
|
||||
connect(ui->pushButton_jogAp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_A, 0);});
|
||||
connect(ui->pushButton_jogAn, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_A, 0);});
|
||||
|
||||
BackPlotWidget* backplot = ui->backPlot;
|
||||
connect(&viewTopAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_TOP);});
|
||||
connect(&viewFrontAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_FRONT);});
|
||||
connect(&viewLeftAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_LEFT);});
|
||||
connect(&viewRightAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_RIGHT);});
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::selectedJogStepChanged(int index)
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(-1);}, Qt::QueuedConnection);
|
||||
break;
|
||||
case 1:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(5000);}, Qt::QueuedConnection);
|
||||
break;
|
||||
case 2:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(1000);}, Qt::QueuedConnection);
|
||||
break;
|
||||
case 3:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(250);}, Qt::QueuedConnection);
|
||||
break;
|
||||
case 4:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(100);}, Qt::QueuedConnection);
|
||||
break;
|
||||
case 5:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(50);}, Qt::QueuedConnection);
|
||||
break;
|
||||
default:
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(0);}, Qt::QueuedConnection);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::jog(VhfMill::Axis axis, int jogDirection)
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, [this, axis, jogDirection](){mill_->jog(axis, jogDirection);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
bool MainWindow::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if(jogEnabled)
|
||||
{
|
||||
if(event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
||||
switch(ke->key())
|
||||
{
|
||||
case Qt::Key_Up:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Y, -1);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_Left:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_X, -1);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_Right:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_X, 1);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_Down:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Y, 1);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_PageUp:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Z, 1);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_PageDown:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Z, -1);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
||||
switch(ke->key())
|
||||
{
|
||||
case Qt::Key_Up:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Y, 0);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_Left:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_X, 0);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_Right:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_X, 0);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_Down:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Y, 0);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_PageUp:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Z, 0);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
case Qt::Key_PageDown:
|
||||
if(!ke->isAutoRepeat())
|
||||
jog(VhfMill::AXIS_Z, 0);
|
||||
event->setAccepted(true);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::textChanged()
|
||||
{
|
||||
bool ok = true;
|
||||
QByteArray programm = ui->plainTextEdit->toPlainText().toLatin1();
|
||||
|
||||
if(ui->radioButton_gcode->isChecked())
|
||||
{
|
||||
QList<QString> errors;
|
||||
programm = gcodeToVhf(programm, &ok, &errors);
|
||||
if(!ok)
|
||||
ui->statusbar->showMessage(errors.back());
|
||||
ui->plainTextEdit_compiled->setPlainText(programm);
|
||||
}
|
||||
|
||||
ui->backPlot->programChanged(programm);
|
||||
}
|
||||
|
||||
void MainWindow::home()
|
||||
{
|
||||
VhfMill::Axis axis = comboBoxToAxis(*ui->comboBox_homeAxis);
|
||||
qDebug()<<__func__<<axis;
|
||||
QMetaObject::invokeMethod(mill_, [this, axis](){mill_->home(axis);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::toolUnload()
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setTool(0);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::gotSpindleSpeed(int speed)
|
||||
{
|
||||
ui->lcd_spindle->display(speed);
|
||||
}
|
||||
|
||||
void MainWindow::stopSpindle()
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setSpindleSpeed(0);}, Qt::QueuedConnection);
|
||||
ui->horizontalSlider->setValue(0);
|
||||
}
|
||||
|
||||
void MainWindow::isHomed(VhfMill::Axis axis)
|
||||
{
|
||||
ui->led_homeX->setLit(axis & VhfMill::AXIS_X);
|
||||
ui->led_homeY->setLit(axis & VhfMill::AXIS_Y);
|
||||
ui->led_homeZ->setLit(axis & VhfMill::AXIS_Z);
|
||||
ui->led_homeA->setLit(axis & VhfMill::AXIS_A);
|
||||
checkBlocks();
|
||||
}
|
||||
|
||||
VhfMill::Axis MainWindow::comboBoxToAxis(const QComboBox& box)
|
||||
{
|
||||
switch(box.currentIndex())
|
||||
{
|
||||
case 0:
|
||||
return VhfMill::AXIS_X;
|
||||
case 1:
|
||||
return VhfMill::AXIS_Y;
|
||||
case 2:
|
||||
return VhfMill::AXIS_Z;
|
||||
case 3:
|
||||
return VhfMill::AXIS_A;
|
||||
case 4:
|
||||
return VhfMill::AXIS_B;
|
||||
default:
|
||||
return VhfMill::AXIS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::run()
|
||||
{
|
||||
QByteArray programm = ui->plainTextEdit->toPlainText().toLatin1();
|
||||
if(ui->radioButton_gcode->isChecked())
|
||||
{
|
||||
bool ok;
|
||||
programm = gcodeToVhf(programm, &ok);
|
||||
if(!ok)
|
||||
{
|
||||
QMessageBox::critical(this, "Error", "failed to parse gcode");
|
||||
return;
|
||||
}
|
||||
}
|
||||
QMetaObject::invokeMethod(mill_, [programm, this](){mill_->send(programm);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::toolSwitch()
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->setTool(ui->comboBox_tool->currentIndex()+1);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::touchoff()
|
||||
{
|
||||
bool ok;
|
||||
double offset = QInputDialog::getDouble(this, "Offset", "offset in mm", 0, -1000, 1000, 2, &ok);
|
||||
if(ok)
|
||||
QMetaObject::invokeMethod(mill_, [this, offset](){mill_->touchOff(comboBoxToAxis(*ui->comboBox_TouchoffAxis), offset*1000);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::touchoffAll()
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->touchOff(VhfMill::AXIS_ALL, 0);}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::touchoffRst()
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, [this](){mill_->touchOffAbsolute({0,0,0,0});}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::toolChangeDone()
|
||||
{
|
||||
QMetaObject::invokeMethod(mill_, &VhfMill::reqTool, Qt::QueuedConnection);
|
||||
setToolchangeBlocked(false);
|
||||
}
|
||||
|
||||
void MainWindow::raiseError(int errorNum)
|
||||
{
|
||||
QMessageBox::critical(this, "Error", VhfMill::textForErrno(errorNum));
|
||||
checkBlocks();
|
||||
}
|
||||
|
||||
void MainWindow::positionUpdate(std::vector<int> position)
|
||||
{
|
||||
if(position.size() < 4)
|
||||
return;
|
||||
|
||||
std::vector<int> touchoff;
|
||||
if(ui->radioButton->isChecked())
|
||||
touchoff.assign(position.size(), 0);
|
||||
else
|
||||
touchoff = mill_->getLastTouchoffPosition();
|
||||
|
||||
size_t xIndex = VhfMill::axisToIndex(VhfMill::AXIS_X);
|
||||
size_t yIndex = VhfMill::axisToIndex(VhfMill::AXIS_Y);
|
||||
size_t zIndex = VhfMill::axisToIndex(VhfMill::AXIS_Z);
|
||||
size_t aIndex = VhfMill::axisToIndex(VhfMill::AXIS_A);
|
||||
|
||||
double xDpl = position[xIndex] - touchoff[xIndex];
|
||||
double yDpl = position[yIndex] - touchoff[yIndex];
|
||||
double zDpl = position[zIndex] - touchoff[zIndex];
|
||||
double aDpl = position[aIndex] - touchoff[aIndex];
|
||||
|
||||
ui->lcd_x->display(xDpl/1000.0);
|
||||
ui->lcd_y->display(yDpl/1000.0);
|
||||
ui->lcd_z->display(zDpl/1000.0);
|
||||
ui->lcd_a->display(aDpl/1000.0);
|
||||
}
|
||||
|
||||
void MainWindow::openVhfCode()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "~", "VhfCode (*.vhf)");
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
QFile gcodeFile(fileName);
|
||||
if(!gcodeFile.open(QIODeviceBase::ReadOnly))
|
||||
{
|
||||
QMessageBox::critical(this, "Error", "Could not open " + fileName + " for reading");
|
||||
return;
|
||||
}
|
||||
QByteArray vhfCode = gcodeFile.readAll();
|
||||
|
||||
ui->radioButton_vhfCode->setChecked(true);
|
||||
ui->plainTextEdit->setPlainText(vhfCode);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::openGcode()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "~", "Gcode (*.ngc *.nc)");
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
QFile gcodeFile(fileName);
|
||||
if(!gcodeFile.open(QIODeviceBase::ReadOnly))
|
||||
{
|
||||
QMessageBox::critical(this, "Error", "Could not open " + fileName + " for reading");
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
QByteArray gcode = gcodeFile.readAll();
|
||||
gcodeToVhf(gcode, &ok);
|
||||
if(!ok)
|
||||
{
|
||||
QMessageBox::critical(this, "Error", "failed to parse gcode");
|
||||
return;
|
||||
}
|
||||
|
||||
ui->radioButton_gcode->setChecked(true);
|
||||
ui->radioButton_vhfCode->setChecked(false);
|
||||
ui->plainTextEdit->setPlainText(gcode);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::touchoffChanged(std::vector<int> position)
|
||||
{
|
||||
if(position.size() < 4)
|
||||
return;
|
||||
ui->lcd_touchX->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_X)])/1000.0);
|
||||
ui->lcd_touchY->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_Y)])/1000.0);
|
||||
ui->lcd_touchZ->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_Z)])/1000.0);
|
||||
ui->lcd_touchA->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_A)])/1000.0);
|
||||
positionUpdate(mill_->getLastKnownPosition());
|
||||
ui->backPlot->touchoffUpdate(position);
|
||||
textChanged();
|
||||
}
|
||||
|
||||
void MainWindow::checkBlocks()
|
||||
{
|
||||
setAllBlocked(true);
|
||||
if(mill_->isInitDone())
|
||||
{
|
||||
qDebug()<<__func__<<"unblocking home and spindle";
|
||||
setSpindleBlocked(false);
|
||||
setHomeingBlocked(false);
|
||||
setOutputsBlocked(false);
|
||||
if(mill_->allHomed())
|
||||
{
|
||||
qDebug()<<__func__<<"unblocking jog";
|
||||
setJogBlocked(false);
|
||||
ui->pushButton_run->setEnabled(true);
|
||||
if(mill_->presureReady())
|
||||
{
|
||||
qDebug()<<__func__<<"unblocking tool change";
|
||||
setToolchangeBlocked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::gotOutputs(uint8_t outputs)
|
||||
{
|
||||
ui->checkBox_oe1->setChecked(outputs & 1<<0);
|
||||
ui->checkBox_oe2->setChecked(outputs & 1<<1);
|
||||
ui->checkBox_oe3->setChecked(outputs & 1<<2);
|
||||
ui->checkBox_oe4->setChecked(outputs & 1<<3);
|
||||
ui->checkBox_oe5->setChecked(outputs & 1<<4);
|
||||
ui->checkBox_oe6->setChecked(outputs & 1<<5);
|
||||
ui->checkBox_oe7->setChecked(outputs & 1<<6);
|
||||
}
|
||||
|
||||
void MainWindow::gotPressureState(bool state)
|
||||
{
|
||||
ui->led_pressure->setLit(!state);
|
||||
checkBlocks();
|
||||
}
|
||||
|
||||
void MainWindow::setAllBlocked(bool blocked)
|
||||
{
|
||||
setOutputsBlocked(blocked);
|
||||
setJogBlocked(blocked);
|
||||
setToolchangeBlocked(blocked);
|
||||
setSpindleBlocked(blocked);
|
||||
setHomeingBlocked(blocked);
|
||||
ui->pushButton_run->setEnabled(!blocked);
|
||||
}
|
||||
|
||||
void MainWindow::setOutputsBlocked(bool block)
|
||||
{
|
||||
ui->checkBox_oe1->setEnabled(!block);
|
||||
ui->checkBox_oe2->setEnabled(!block);
|
||||
ui->checkBox_oe3->setEnabled(!block);
|
||||
ui->checkBox_oe4->setEnabled(!block);
|
||||
ui->checkBox_oe5->setEnabled(!block);
|
||||
ui->checkBox_oe6->setEnabled(!block);
|
||||
ui->checkBox_oe7->setEnabled(!block);
|
||||
}
|
||||
|
||||
void MainWindow::setJogBlocked(bool block)
|
||||
{
|
||||
jogEnabled = !block;
|
||||
ui->pushButton_jogDown->setEnabled(!block);
|
||||
ui->pushButton_jogUp->setEnabled(!block);
|
||||
ui->pushButton_jogXp->setEnabled(!block);
|
||||
ui->pushButton_jogXn->setEnabled(!block);
|
||||
ui->pushButton_jogYp->setEnabled(!block);
|
||||
ui->pushButton_jogYn->setEnabled(!block);
|
||||
ui->pushButton_jogAp->setEnabled(!block);
|
||||
ui->pushButton_jogAn->setEnabled(!block);
|
||||
ui->comboBox_jogStep->setEnabled(!block);
|
||||
}
|
||||
|
||||
void MainWindow::setToolchangeBlocked(bool block)
|
||||
{
|
||||
ui->pushButton_toolSwitch->setEnabled(!block);
|
||||
ui->pushButton_toolUnload->setEnabled(!block);
|
||||
ui->comboBox_tool->setEnabled(!block);
|
||||
}
|
||||
|
||||
void MainWindow::setSpindleBlocked(bool block)
|
||||
{
|
||||
ui->pushButton_stopSpindle->setEnabled(!block);
|
||||
ui->horizontalSlider->setEnabled(!block);
|
||||
}
|
||||
|
||||
void MainWindow::setHomeingBlocked(bool block)
|
||||
{
|
||||
ui->pushButton_home->setEnabled(!block);
|
||||
ui->pushButton_homeAll->setEnabled(!block);
|
||||
ui->comboBox_homeAxis->setEnabled(!block);
|
||||
}
|
||||
|
||||
void MainWindow::setTouchoffBlocked(bool block)
|
||||
{
|
||||
ui->comboBox_TouchoffAxis->setEnabled(!block);
|
||||
ui->pushButton_touchoff->setEnabled(!block);
|
||||
ui->pushButton_touchoffAll->setEnabled(!block);
|
||||
}
|
||||
|
70
mainwindow.h
Normal file
70
mainwindow.h
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QComboBox>
|
||||
#include <QShortcut>
|
||||
#include "vhfmill.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class MainWindow; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
VhfMill* mill_;
|
||||
|
||||
QShortcut viewTopAction;
|
||||
QShortcut viewFrontAction;
|
||||
QShortcut viewLeftAction;
|
||||
QShortcut viewRightAction;
|
||||
bool jogEnabled = false;
|
||||
|
||||
private slots:
|
||||
void raiseError(int errorNum);
|
||||
void positionUpdate(std::vector<int> position);
|
||||
void isHomed(VhfMill::Axis axis);
|
||||
void gotOutputs(uint8_t outputs);
|
||||
void gotPressureState(bool state);
|
||||
void checkBlocks();
|
||||
void toolChangeDone();
|
||||
void gotSpindleSpeed(int speed);
|
||||
void touchoffChanged(std::vector<int> position);
|
||||
void textChanged();
|
||||
void selectedJogStepChanged(int index);
|
||||
void jog(VhfMill::Axis axis, int jogDirection);
|
||||
|
||||
void home();
|
||||
void stopSpindle();
|
||||
void run();
|
||||
void toolSwitch();
|
||||
void touchoff();
|
||||
void touchoffAll();
|
||||
void touchoffRst();
|
||||
void toolUnload();
|
||||
void openGcode();
|
||||
void openVhfCode();
|
||||
|
||||
private:
|
||||
void setAllBlocked(bool block);
|
||||
void setOutputsBlocked(bool block);
|
||||
void setJogBlocked(bool block);
|
||||
void setToolchangeBlocked(bool block);
|
||||
void setSpindleBlocked(bool block);
|
||||
void setHomeingBlocked(bool block);
|
||||
void setTouchoffBlocked(bool block);
|
||||
|
||||
static VhfMill::Axis comboBoxToAxis(const QComboBox& box);
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *o, QEvent *e) override;
|
||||
|
||||
public:
|
||||
MainWindow(VhfMill* mill, QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui = nullptr;
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
862
mainwindow.ui
Normal file
862
mainwindow.ui
Normal file
@ -0,0 +1,862 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1048</width>
|
||||
<height>687</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>VHF Mill</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Setup</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QComboBox" name="comboBox_TouchoffAxis">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>y</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>z</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>a</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="pushButton_touchoff">
|
||||
<property name="text">
|
||||
<string>Touchoff Axis</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QComboBox" name="comboBox_homeAxis">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>y</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>z</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>a</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="pushButton_init">
|
||||
<property name="text">
|
||||
<string>init</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pushButton_homeAll">
|
||||
<property name="text">
|
||||
<string>Home All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pushButton_home">
|
||||
<property name="text">
|
||||
<string>Home Axis</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="pushButton_touchoffAll">
|
||||
<property name="text">
|
||||
<string>Touchoff All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="pushButton_touchoffRst">
|
||||
<property name="text">
|
||||
<string>Reset Touchoff</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Jog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="pushButton_jogDown">
|
||||
<property name="text">
|
||||
<string>⤓</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="pushButton_jogAn">
|
||||
<property name="text">
|
||||
<string>⟲</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="pushButton_jogYn">
|
||||
<property name="text">
|
||||
<string>↓</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="pushButton_jogAp">
|
||||
<property name="text">
|
||||
<string>⟳</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="pushButton_jogXn">
|
||||
<property name="text">
|
||||
<string>←</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButton_jogUp">
|
||||
<property name="text">
|
||||
<string>↥</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButton_jogXp">
|
||||
<property name="text">
|
||||
<string>→</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pushButton_jogYp">
|
||||
<property name="text">
|
||||
<string>↑</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBox_jogStep">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Continues</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>5 mm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1 mm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0.25 mm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0.1 mm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0.05 mm</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0">
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabDro">
|
||||
<attribute name="title">
|
||||
<string>DRO</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,1,1" columnstretch="0,1,1,1,1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLCDNumber" name="lcd_touchX">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Z</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Led" name="led_homeX" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Position</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="Led" name="led_homeZ" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Touchoff Position</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="Led" name="led_homeA" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLCDNumber" name="lcd_z">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLCDNumber" name="lcd_y">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Homed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QLCDNumber" name="lcd_a">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>A</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLCDNumber" name="lcd_x">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLCDNumber" name="lcd_touchY">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QLCDNumber" name="lcd_touchA">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLCDNumber" name="lcd_touchZ">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="Led" name="led_homeY" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Pressure</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Probe</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="Led" name="led_pressure" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="Led" name="led_probe" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton">
|
||||
<property name="text">
|
||||
<string>Show Absolute</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_2">
|
||||
<property name="text">
|
||||
<string>Show Relative</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab3d">
|
||||
<attribute name="title">
|
||||
<string>3D</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="BackPlotWidget" name="backPlot" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,1,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Current Tool</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="lcd_tool">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_tool">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>5</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_toolSwitch">
|
||||
<property name="text">
|
||||
<string>Switch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_toolUnload">
|
||||
<property name="text">
|
||||
<string>Unload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Spindle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="lcd_spindle">
|
||||
<property name="segmentStyle">
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>60000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="tracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_stopSpindle">
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe1">
|
||||
<property name="text">
|
||||
<string>Unclamp Tool</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe2">
|
||||
<property name="text">
|
||||
<string>Bearing Air</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe5">
|
||||
<property name="text">
|
||||
<string>Air Assist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe3">
|
||||
<property name="text">
|
||||
<string>Clamp Tools</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe4">
|
||||
<property name="text">
|
||||
<string>Compressor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe6">
|
||||
<property name="text">
|
||||
<string>A Axis Clamp</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_oe7">
|
||||
<property name="text">
|
||||
<string>Fixture Air</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Programm</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit_compiled">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_vhfCode">
|
||||
<property name="text">
|
||||
<string>VHF code</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_gcode">
|
||||
<property name="text">
|
||||
<string>Gcode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_stop">
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_run">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1048</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen_Gcode"/>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionClear"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open VHL</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSerial_Port">
|
||||
<property name="text">
|
||||
<string>Serial Port</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Gcode">
|
||||
<property name="text">
|
||||
<string>Open Gcode</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionQuit">
|
||||
<property name="text">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClear">
|
||||
<property name="text">
|
||||
<string>Save VhfCode</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Led</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">led.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>BackPlotWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">backplotwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
164
orbitcameracontroller.cpp
Normal file
164
orbitcameracontroller.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "orbitcameracontroller.h"
|
||||
|
||||
#include <Qt3DRender/QCamera>
|
||||
|
||||
/*!
|
||||
\class Qt3DExtras::OrbitCameraController
|
||||
\ingroup qt3d-extras-cameracontrollers
|
||||
\brief The OrbitCameraController class allows controlling the scene camera along orbital path.
|
||||
\inmodule Qt3DExtras
|
||||
\since 5.7
|
||||
\inherits Qt3DCore::QEntity
|
||||
|
||||
The controls are:
|
||||
\table
|
||||
\header
|
||||
\li Input
|
||||
\li Action
|
||||
\row
|
||||
\li Left mouse button
|
||||
\li While the left mouse button is pressed, mouse movement along x-axis moves the camera
|
||||
left and right and movement along y-axis moves it up and down.
|
||||
\row
|
||||
\li Right mouse button
|
||||
\li While the right mouse button is pressed, mouse movement along x-axis pans the camera
|
||||
around the camera view center and movement along y-axis tilts it around the camera
|
||||
view center.
|
||||
\row
|
||||
\li Both left and right mouse button
|
||||
\li While both the left and the right mouse button are pressed, mouse movement along y-axis
|
||||
zooms the camera in and out without changing the view center.
|
||||
\row
|
||||
\li Mouse scroll wheel
|
||||
\li Zooms the camera in and out without changing the view center.
|
||||
\row
|
||||
\li Arrow keys
|
||||
\li Move the camera vertically and horizontally relative to camera viewport.
|
||||
\row
|
||||
\li Page up and page down keys
|
||||
\li Move the camera forwards and backwards.
|
||||
\row
|
||||
\li Shift key
|
||||
\li Changes the behavior of the up and down arrow keys to zoom the camera in and out
|
||||
without changing the view center. The other movement keys are disabled.
|
||||
\row
|
||||
\li Alt key
|
||||
\li Changes the behovior of the arrow keys to pan and tilt the camera around the view
|
||||
center. Disables the page up and page down keys.
|
||||
\row
|
||||
\li Escape
|
||||
\li Moves the camera so that entire scene is visible in the camera viewport.
|
||||
\endtable
|
||||
*/
|
||||
|
||||
OrbitCameraController::OrbitCameraController(QVector2D orthoSize, Qt3DCore::QNode *parent)
|
||||
: QAbstractCameraController(parent),
|
||||
m_orthoSize(orthoSize)
|
||||
{
|
||||
}
|
||||
|
||||
OrbitCameraController::~OrbitCameraController()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\property OrbitCameraController::zoomInLimit
|
||||
|
||||
Holds the current zoom-in limit. The zoom-in limit determines how close to the view center
|
||||
the camera can be zoomed.
|
||||
*/
|
||||
float OrbitCameraController::zoomInLimit() const
|
||||
{
|
||||
return m_zoomInLimit;
|
||||
}
|
||||
|
||||
void OrbitCameraController::updateProjection()
|
||||
{
|
||||
camera()->lens()->setOrthographicProjection(0-(m_orthoSize.x()/m_zoomFactor)/2, (m_orthoSize.x()/m_zoomFactor)/2,
|
||||
0-(m_orthoSize.y()/m_zoomFactor)/2, (m_orthoSize.y()/m_zoomFactor)/2, 0.01, 100000);
|
||||
}
|
||||
|
||||
void OrbitCameraController::setZoomInLimit(float zoomInLimit)
|
||||
{
|
||||
if (m_zoomInLimit != zoomInLimit)
|
||||
{
|
||||
m_zoomInLimit = zoomInLimit;
|
||||
emit zoomInLimitChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void OrbitCameraController::setZoomFactor(float factor)
|
||||
{
|
||||
m_zoomFactor = factor;
|
||||
updateProjection();
|
||||
}
|
||||
|
||||
void OrbitCameraController::setOrthoSize(QVector2D orthoSize)
|
||||
{
|
||||
m_orthoSize = orthoSize;
|
||||
updateProjection();
|
||||
}
|
||||
|
||||
inline float clampInputs(float input1, float input2)
|
||||
{
|
||||
float axisValue = input1 + input2;
|
||||
return (axisValue < -1) ? -1 : (axisValue > 1) ? 1 : axisValue;
|
||||
}
|
||||
|
||||
inline float zoomDistance(QVector3D firstPoint, QVector3D secondPoint)
|
||||
{
|
||||
return (secondPoint - firstPoint).lengthSquared();
|
||||
}
|
||||
|
||||
void OrbitCameraController::moveCamera(const QAbstractCameraController::InputState &state, float dt)
|
||||
{
|
||||
Qt3DRender::QCamera *theCamera = camera();
|
||||
|
||||
if (theCamera == nullptr)
|
||||
return;
|
||||
|
||||
const QVector3D upVector(0.0f, 0.0f, 1.0f);
|
||||
|
||||
if(state.tzAxisValue != 0)
|
||||
{
|
||||
m_zoomFactor+=0.1*state.tzAxisValue;
|
||||
if(m_zoomFactor < 1)
|
||||
m_zoomFactor = 1;
|
||||
else if(m_zoomFactor > m_zoomInLimit)
|
||||
m_zoomFactor = m_zoomInLimit;
|
||||
updateProjection();
|
||||
}
|
||||
|
||||
// Mouse input
|
||||
if (state.rightMouseButtonActive)
|
||||
{
|
||||
// Translate
|
||||
theCamera->translate(QVector3D(clampInputs(0-state.rxAxisValue, 0-state.txAxisValue) * linearSpeed(),
|
||||
clampInputs(0-state.ryAxisValue, 0-state.tyAxisValue) * linearSpeed(),
|
||||
0) * dt);
|
||||
}
|
||||
else if (state.leftMouseButtonActive)
|
||||
{
|
||||
// Orbit
|
||||
theCamera->panAboutViewCenter((state.rxAxisValue * -1 * lookSpeed()) * dt, upVector);
|
||||
theCamera->tiltAboutViewCenter((state.ryAxisValue * -1 * lookSpeed()) * dt);
|
||||
}
|
||||
|
||||
// Keyboard Input
|
||||
if (state.altKeyActive)
|
||||
{
|
||||
// Orbit
|
||||
theCamera->panAboutViewCenter((state.txAxisValue * lookSpeed()) * dt, upVector);
|
||||
theCamera->tiltAboutViewCenter((state.tyAxisValue * lookSpeed()) * dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Translate
|
||||
theCamera->translate(QVector3D(clampInputs(state.leftMouseButtonActive ? state.rxAxisValue : 0, state.txAxisValue) * linearSpeed(),
|
||||
clampInputs(state.leftMouseButtonActive ? state.ryAxisValue : 0, state.tyAxisValue) * linearSpeed(),
|
||||
state.tzAxisValue * linearSpeed()) * dt);
|
||||
}
|
||||
}
|
33
orbitcameracontroller.h
Normal file
33
orbitcameracontroller.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#pragma once
|
||||
#include <QAbstractCameraController>
|
||||
#include <QVector2D>
|
||||
|
||||
class OrbitCameraController : public Qt3DExtras::QAbstractCameraController
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
float m_zoomInLimit = 10.0;
|
||||
float m_zoomFactor = 1.0;
|
||||
QVector2D m_orthoSize;
|
||||
|
||||
void updateProjection();
|
||||
|
||||
public:
|
||||
explicit OrbitCameraController(QVector2D orthoSize, Qt3DCore::QNode *parent = nullptr);
|
||||
~OrbitCameraController();
|
||||
|
||||
float zoomInLimit() const;
|
||||
|
||||
void setZoomInLimit(float zoomInLimit);
|
||||
void setZoomFactor(float factor);
|
||||
void setOrthoSize(QVector2D orthoSize);
|
||||
|
||||
signals:
|
||||
void zoomInLimitChanged();
|
||||
|
||||
private:
|
||||
virtual void moveCamera(const Qt3DExtras::QAbstractCameraController::InputState &state, float dt) override;
|
||||
};
|
628
vhfmill.cpp
Normal file
628
vhfmill.cpp
Normal file
@ -0,0 +1,628 @@
|
||||
#include "vhfmill.h"
|
||||
#include <QDebug>
|
||||
|
||||
VhfMill::VhfMill(QIODevice* serial, uint8_t nAxis, QObject *parent)
|
||||
: serial_(serial), nAxis_(nAxis), QObject{parent}
|
||||
{
|
||||
QObject::connect(serial_, &QIODevice::readyRead, this, &VhfMill::serialReadyRead);
|
||||
|
||||
qDebug()<<__func__<<" object created";
|
||||
|
||||
lastKnownPos_.assign(5, 0);
|
||||
touchoffPos_.assign(5, 0);
|
||||
|
||||
initTimer.callOnTimeout(this, &VhfMill::initTimerFn);
|
||||
initTimer.setInterval(3000);
|
||||
|
||||
stateTimer.callOnTimeout(this, &VhfMill::stateTimerFn);
|
||||
stateTimer.setInterval(1000);
|
||||
|
||||
positionTimer.callOnTimeout(this, &VhfMill::reqPosition);
|
||||
positionTimer.setInterval(100);
|
||||
|
||||
limits_ = {190000, 92000, 85000, 100000};
|
||||
}
|
||||
|
||||
void VhfMill::serialReadyRead()
|
||||
{
|
||||
char charBuf;
|
||||
while(serial_->getChar(&charBuf))
|
||||
{
|
||||
lineBuffer_.push_back(charBuf);
|
||||
if(lineBuffer_.endsWith(';') )
|
||||
{
|
||||
lineBuffer_.chop(1);
|
||||
processIncomeingLine();
|
||||
gotLine(lineBuffer_);
|
||||
lineBuffer_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VhfMill::init()
|
||||
{
|
||||
initTimerFn();
|
||||
initTimer.start();
|
||||
}
|
||||
|
||||
void VhfMill::setSpindleSpeed(int speed)
|
||||
{
|
||||
serial_->write("RVS"+QByteArray::number(speed)+";\n");
|
||||
serial_->write("?RV;");
|
||||
}
|
||||
|
||||
void VhfMill::setjogStep(int step)
|
||||
{
|
||||
jogStep_ = step;
|
||||
jogStepChanged(jogStep_);
|
||||
}
|
||||
|
||||
VhfMill::Axis VhfMill::homed() const
|
||||
{
|
||||
return axisHomed_;
|
||||
}
|
||||
|
||||
void VhfMill::jog(VhfMill::Axis axis, int jogDirection)
|
||||
{
|
||||
if(homed() & axis)
|
||||
{
|
||||
if(jogStep_ > 0 && jogDirection != 0 && jogAxis_ == AXIS_NONE)
|
||||
{
|
||||
QByteArray command("GR");
|
||||
if(axis == AXIS_X)
|
||||
command.append(QByteArray::number(jogStep_*jogDirection*-1));
|
||||
else
|
||||
command.push_back('0');
|
||||
command.push_back(',');
|
||||
if(axis == AXIS_Y)
|
||||
command.append(QByteArray::number(jogStep_*jogDirection));
|
||||
else
|
||||
command.push_back('0');
|
||||
command.push_back(',');
|
||||
if(axis == AXIS_Z)
|
||||
command.append(QByteArray::number(jogStep_*jogDirection*-1));
|
||||
else
|
||||
command.push_back('0');
|
||||
command.push_back(',');
|
||||
if(axis == AXIS_A)
|
||||
command.append(QByteArray::number(jogStep_*jogDirection*-1));
|
||||
else
|
||||
command.push_back('0');
|
||||
command.push_back(';');
|
||||
send(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(jogAxis_ == axis && jogDirection == 0)
|
||||
{
|
||||
serial_->write("!M;");
|
||||
jogDirection_ = 0;
|
||||
jogAxis_ = AXIS_NONE;
|
||||
}
|
||||
else if(jogAxis_ == AXIS_NONE && jogDirection != 0)
|
||||
{
|
||||
jogAxis_ = axis;
|
||||
jogDirection_ = jogDirection;
|
||||
jogDirection = jogDirection == -1 ? 1 : 0;
|
||||
QByteArray command("GA");
|
||||
if(axis == AXIS_X)
|
||||
command.append(QByteArray::number(getLimits()[0]*jogDirection));
|
||||
else
|
||||
command.push_back(QByteArray::number(getLastKnownPosition()[0]));
|
||||
command.push_back(',');
|
||||
if(axis == AXIS_Y)
|
||||
command.append(QByteArray::number(getLimits()[1]*jogDirection));
|
||||
else
|
||||
command.push_back(QByteArray::number(getLastKnownPosition()[1]));
|
||||
command.push_back(',');
|
||||
if(axis == AXIS_Z)
|
||||
command.append(QByteArray::number(getLimits()[2]*jogDirection));
|
||||
else
|
||||
command.push_back(QByteArray::number(getLastKnownPosition()[2]));
|
||||
command.push_back(',');
|
||||
if(axis == AXIS_A)
|
||||
command.append(QByteArray::number(getLimits()[3]*jogDirection));
|
||||
else
|
||||
command.push_back(QByteArray::number(getLastKnownPosition()[3]));
|
||||
command.push_back(';');
|
||||
send(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<int>& VhfMill::getLimits() const
|
||||
{
|
||||
return limits_;
|
||||
}
|
||||
|
||||
QByteArray VhfMill::generateCmdForOffset(QByteArray command)
|
||||
{
|
||||
QByteArray output = command.first(2);
|
||||
command.remove(0, 2);
|
||||
QList<QByteArray> values = command.split(',');
|
||||
|
||||
for(size_t i = 0; i < values.size(); ++i)
|
||||
{
|
||||
if(values[i].size() != 0)
|
||||
{
|
||||
bool ok;
|
||||
int value = values[i].toInt(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
raiseError(10);
|
||||
return QByteArray();
|
||||
}
|
||||
output.append(QByteArray::number(value+touchoffPos_[i]));
|
||||
}
|
||||
output.push_back(',');
|
||||
}
|
||||
|
||||
output.back() == ',';
|
||||
output.chop(1);
|
||||
return output;
|
||||
}
|
||||
|
||||
void VhfMill::send(const QByteArray& cmd)
|
||||
{
|
||||
QList<QByteArray> commands = cmd.split(';');
|
||||
|
||||
for(const QByteArray& command : commands)
|
||||
{
|
||||
QByteArray trimmedCmd = command.trimmed().toUpper();
|
||||
if(trimmedCmd.size() < 2)
|
||||
continue;
|
||||
if(trimmedCmd.first(2) == "PA" || trimmedCmd.first(2) == "GA")
|
||||
trimmedCmd = generateCmdForOffset(trimmedCmd);
|
||||
else if(trimmedCmd.first(2) == "PB")
|
||||
trimmedCmd[1] = 'A';
|
||||
else if(trimmedCmd.first(2) == "GB")
|
||||
trimmedCmd[1] = 'A';
|
||||
qDebug()<<"Writeing"<<(trimmedCmd + ";\n");
|
||||
serial_->write(trimmedCmd + ";\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VhfMill::stop()
|
||||
{
|
||||
send("!B;");
|
||||
send("CONT;");
|
||||
}
|
||||
|
||||
void VhfMill::home(VhfMill::Axis axis)
|
||||
{
|
||||
if(mode_ != MODE_NORMAL || homeAxis_ != AXIS_NONE)
|
||||
{
|
||||
raiseError(3);
|
||||
return;
|
||||
}
|
||||
if(axis == AXIS_ALL)
|
||||
serial_->write("RF;\n");
|
||||
else if(axis == AXIS_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int axisNum = axisToMashineNumber(axis);
|
||||
qDebug()<<__func__<<axisNum;
|
||||
if(axisNum == 0)
|
||||
{
|
||||
raiseError(20);
|
||||
return;
|
||||
}
|
||||
serial_->write("RF" + QByteArray::number(axisNum) + ";\n");
|
||||
}
|
||||
homeAxis_ = axis;
|
||||
mode_ = MODE_HOME;
|
||||
axisHomed_ &= ~axis;
|
||||
isHomed(axisHomed_);
|
||||
}
|
||||
|
||||
void VhfMill::stateTimerFn()
|
||||
{
|
||||
reqOutputs();
|
||||
reqSensors();
|
||||
reqSpindleSpeed();
|
||||
}
|
||||
|
||||
void VhfMill::setOutput(int output, bool state)
|
||||
{
|
||||
serial_->write("OA" + QByteArray::number(static_cast<int>(output)) + "," + QByteArray::number(static_cast<int>(state)) + ";\n");
|
||||
reqOutputs();
|
||||
}
|
||||
|
||||
void VhfMill::setTool(int tool)
|
||||
{
|
||||
if(mode_ != MODE_NORMAL)
|
||||
{
|
||||
VhfMill::raiseError(3);
|
||||
return;
|
||||
}
|
||||
mode_ = MODE_TOOLCHANGE;
|
||||
serial_->write("T" + QByteArray::number(tool) + ";\n");
|
||||
reqTool();
|
||||
}
|
||||
|
||||
void VhfMill::reqTool()
|
||||
{
|
||||
serial_->write("?T;\n");
|
||||
}
|
||||
|
||||
void VhfMill::reqOutputs()
|
||||
{
|
||||
serial_->write("?OA;\n");
|
||||
}
|
||||
|
||||
void VhfMill::reqPosition()
|
||||
{
|
||||
serial_->write("?PA;\n");
|
||||
}
|
||||
|
||||
void VhfMill::reqSpindleSpeed()
|
||||
{
|
||||
serial_->write("?RV;\n");
|
||||
}
|
||||
|
||||
void VhfMill::reqSensors()
|
||||
{
|
||||
serial_->write("?IA;\n");
|
||||
}
|
||||
|
||||
void VhfMill::enablePosUpdates(bool enable)
|
||||
{
|
||||
if(enable && !positionTimer.isActive())
|
||||
positionTimer.start();
|
||||
else
|
||||
positionTimer.stop();
|
||||
}
|
||||
|
||||
void VhfMill::enableStateUpdates(bool enable)
|
||||
{
|
||||
if(enable && !stateTimer.isActive())
|
||||
stateTimer.start();
|
||||
else
|
||||
stateTimer.stop();
|
||||
}
|
||||
|
||||
void VhfMill::reinit()
|
||||
{
|
||||
mode_ = MODE_PREINIT;
|
||||
enablePosUpdates(false);
|
||||
enableStateUpdates(false);
|
||||
serial_->write("!N;\n");
|
||||
}
|
||||
|
||||
void VhfMill::initTimerFn()
|
||||
{
|
||||
if(mode_ != MODE_PREINIT)
|
||||
{
|
||||
initTimer.stop();
|
||||
enablePosUpdates(true);
|
||||
enableStateUpdates(true);
|
||||
return;
|
||||
}
|
||||
|
||||
reinit();
|
||||
}
|
||||
|
||||
void VhfMill::processIncomeingLine()
|
||||
{
|
||||
if(lineBuffer_.isEmpty())
|
||||
{
|
||||
if(mode_ == MODE_PREINIT)
|
||||
{
|
||||
qDebug()<<"init done signal";
|
||||
mode_ = MODE_NORMAL;
|
||||
initDone();
|
||||
}
|
||||
else if(mode_ == MODE_TOOLCHANGE)
|
||||
{
|
||||
qDebug()<<"toolchange done signal";
|
||||
mode_ = MODE_NORMAL;
|
||||
toolChangeDone();
|
||||
}
|
||||
else if(mode_ == MODE_HOME)
|
||||
{
|
||||
qDebug()<<"homeing done";
|
||||
axisHomed_ = axisHomed_ | homeAxis_;
|
||||
mode_ = MODE_NORMAL;
|
||||
homeAxis_ = AXIS_NONE;
|
||||
isHomed(axisHomed_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(lineBuffer_.size() == 0)
|
||||
return;
|
||||
|
||||
if(lineBuffer_[0] == 'E')
|
||||
{
|
||||
lineBuffer_.remove(0,1);
|
||||
bool ok;
|
||||
int errorNumber = lineBuffer_.toInt(&ok);
|
||||
if(!ok)
|
||||
errorNumber = 90;
|
||||
VhfMill::raiseError(errorNumber);
|
||||
}
|
||||
else if(lineBuffer_.startsWith("PA="))
|
||||
{
|
||||
lineBuffer_.remove(0,3);
|
||||
QList<QByteArray> list = lineBuffer_.split(',');
|
||||
if(list.size() != nAxis_)
|
||||
{
|
||||
VhfMill::raiseError(22);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> postion(5, 0);
|
||||
for(int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
bool ok;
|
||||
postion[i] = list[i].toInt(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
VhfMill::raiseError(90);
|
||||
return;
|
||||
}
|
||||
lastKnownPos_ = postion;
|
||||
positionUpdate(lastKnownPos_);
|
||||
}
|
||||
}
|
||||
else if(lineBuffer_.startsWith("T="))
|
||||
{
|
||||
lineBuffer_.remove(0,2);
|
||||
bool ok;
|
||||
int toolNumber = lineBuffer_.toInt(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
VhfMill::raiseError(90);
|
||||
return;
|
||||
}
|
||||
gotToolNum(toolNumber);
|
||||
}
|
||||
else if(lineBuffer_.startsWith("O="))
|
||||
{
|
||||
lineBuffer_.remove(0,2);
|
||||
bool ok;
|
||||
int outputs = lineBuffer_.toInt(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
VhfMill::raiseError(90);
|
||||
return;
|
||||
}
|
||||
if(outputs_ != outputs)
|
||||
{
|
||||
outputs_ = outputs;
|
||||
gotOutputs(outputs_);
|
||||
}
|
||||
}
|
||||
else if(lineBuffer_.startsWith("RV="))
|
||||
{
|
||||
lineBuffer_.remove(0,3);
|
||||
bool ok;
|
||||
int speed = lineBuffer_.toInt(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
VhfMill::raiseError(90);
|
||||
return;
|
||||
}
|
||||
if(spindleSpeed_ != speed)
|
||||
{
|
||||
spindleSpeed_ = speed;
|
||||
gotSindleSpeed(spindleSpeed_);
|
||||
}
|
||||
}
|
||||
else if(lineBuffer_.startsWith("I="))
|
||||
{
|
||||
lineBuffer_.remove(0,2);
|
||||
bool ok;
|
||||
unsigned int sensorBits = lineBuffer_.toUInt(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
VhfMill::raiseError(90);
|
||||
return;
|
||||
}
|
||||
if(sensors_ != sensorBits)
|
||||
{
|
||||
sensors_ = sensorBits;
|
||||
gotProbeState(sensors_ & 1U);
|
||||
gotPressureState(sensors_ & 1U<<1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VhfMill::presureReady() const
|
||||
{
|
||||
return !(sensors_ & 1<<1);
|
||||
}
|
||||
|
||||
bool VhfMill::isInitDone() const
|
||||
{
|
||||
return mode_ != MODE_PREINIT;
|
||||
}
|
||||
|
||||
int VhfMill::getLastSpindleSpeed() const
|
||||
{
|
||||
return spindleSpeed_;
|
||||
}
|
||||
|
||||
bool VhfMill::allHomed() const
|
||||
{
|
||||
bool allHomed = !(~axisHomed_ & (AXIS_X | AXIS_Y | AXIS_Z | AXIS_A | (nAxis_ > 4 ? AXIS_B : 0)));
|
||||
qDebug()<<__func__<<allHomed;
|
||||
return allHomed;
|
||||
}
|
||||
|
||||
uint8_t VhfMill::axisCount() const
|
||||
{
|
||||
return nAxis_;
|
||||
}
|
||||
|
||||
void VhfMill::touchOff(VhfMill::Axis axis, int offset)
|
||||
{
|
||||
if(axis == AXIS_ALL)
|
||||
{
|
||||
for(size_t i = 0; i < nAxis_; ++i)
|
||||
touchoffPos_[i] = lastKnownPos_[i] + offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
touchoffPos_[axisToIndex(axis)] = lastKnownPos_[axisToIndex(axis)] + offset;
|
||||
}
|
||||
touchoffChanged(touchoffPos_);
|
||||
}
|
||||
|
||||
void VhfMill::touchOffAbsolute(std::vector<int> touchoffPos)
|
||||
{
|
||||
for(size_t i = 0; i < touchoffPos.size() && i < touchoffPos_.size(); ++i)
|
||||
touchoffPos_[i] = touchoffPos[i];
|
||||
touchoffChanged(touchoffPos_);
|
||||
}
|
||||
|
||||
size_t VhfMill::axisToIndex(Axis axis)
|
||||
{
|
||||
return axisToMashineNumber(axis)-1;
|
||||
}
|
||||
|
||||
std::vector<int> VhfMill::getLastTouchoffPosition() const
|
||||
{
|
||||
return touchoffPos_;
|
||||
}
|
||||
|
||||
std::vector<int> VhfMill::getLastKnownPosition() const
|
||||
{
|
||||
return lastKnownPos_;
|
||||
}
|
||||
|
||||
int VhfMill::axisToMashineNumber(Axis axis)
|
||||
{
|
||||
switch(axis)
|
||||
{
|
||||
case AXIS_X:
|
||||
return 1;
|
||||
case AXIS_Y:
|
||||
return 2;
|
||||
case AXIS_Z:
|
||||
return 3;
|
||||
case AXIS_A:
|
||||
return 4;
|
||||
case AXIS_B:
|
||||
return 5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const QString VhfMill::textForErrno(int errorNumber)
|
||||
{
|
||||
switch(errorNumber)
|
||||
{
|
||||
case 0:
|
||||
return "No error";
|
||||
case 1:
|
||||
return "unsupported command";
|
||||
case 2:
|
||||
return "invalid command";
|
||||
case 3:
|
||||
return "command not allowed in this state";
|
||||
case 4:
|
||||
return "syntax error";
|
||||
case 5:
|
||||
return "invalid feature";
|
||||
case 6:
|
||||
return "stopped by user";
|
||||
case 7:
|
||||
return "unknown error";
|
||||
case 10:
|
||||
return "invalid parameter";
|
||||
case 12:
|
||||
return "missing parameter";
|
||||
case 13:
|
||||
return "parameter is out of range";
|
||||
case 14:
|
||||
return "no customer profile";
|
||||
case 20:
|
||||
return "axis not defined";
|
||||
case 21:
|
||||
return "axis not combinable";
|
||||
case 22:
|
||||
return "axis not referenced";
|
||||
case 23:
|
||||
return "no referenzpoint found";
|
||||
case 24:
|
||||
return "no measurepoint found";
|
||||
case 25:
|
||||
return "axis range ended";
|
||||
case 26:
|
||||
return "tool too long";
|
||||
case 27:
|
||||
return "tool too short";
|
||||
case 30:
|
||||
return "no spindle defined";
|
||||
case 31:
|
||||
return "no spindle response";
|
||||
case 32:
|
||||
return "spindle input active";
|
||||
case 40:
|
||||
return "can not record macro";
|
||||
case 41:
|
||||
return "macro too long";
|
||||
case 42:
|
||||
return "error in last macro";
|
||||
case 43:
|
||||
return "macro not found";
|
||||
case 50:
|
||||
return "initial stop";
|
||||
case 51:
|
||||
return "external stop";
|
||||
case 52:
|
||||
return "power driver stop";
|
||||
case 53:
|
||||
return "external spindle stop";
|
||||
case 54:
|
||||
return "internal spindle stop";
|
||||
case 55:
|
||||
return "hbox stop";
|
||||
case 56:
|
||||
return "powerfail stop";
|
||||
case 57:
|
||||
return "fpga confdone stop";
|
||||
case 58:
|
||||
return "refswitch stop";
|
||||
case 59:
|
||||
return "fpga error stop";
|
||||
case 60:
|
||||
return "overcurrent spindle stop";
|
||||
case 61:
|
||||
return "overload spindle stop";
|
||||
case 62:
|
||||
return "wait for input stop";
|
||||
case 63:
|
||||
return "unexpected input stop";
|
||||
case 70:
|
||||
return "leveloffset too high";
|
||||
case 71:
|
||||
return "internal error";
|
||||
case 72:
|
||||
return "error opening/reading file";
|
||||
case 73:
|
||||
return "no answer from device";
|
||||
case 74:
|
||||
return "error while loading fpga";
|
||||
case 75:
|
||||
return "update not feasible";
|
||||
case 76:
|
||||
return "update failed";
|
||||
case 77:
|
||||
return "wait for input failed";
|
||||
case 90:
|
||||
return "return parse error";
|
||||
default:
|
||||
return "errno not valid";
|
||||
}
|
||||
}
|
125
vhfmill.h
Normal file
125
vhfmill.h
Normal file
@ -0,0 +1,125 @@
|
||||
#ifndef VHFMILL_H
|
||||
#define VHFMILL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <QTimer>
|
||||
|
||||
class VhfMill : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum {
|
||||
AXIS_NONE = 0,
|
||||
AXIS_X = 1,
|
||||
AXIS_Y = 1<<1,
|
||||
AXIS_Z = 1<<2,
|
||||
AXIS_A = 1<<3,
|
||||
AXIS_B = 1<<4,
|
||||
AXIS_ALL = AXIS_X | AXIS_Y | AXIS_Z | AXIS_A | AXIS_B,
|
||||
};
|
||||
typedef int Axis;
|
||||
|
||||
private:
|
||||
|
||||
typedef enum {
|
||||
MODE_PREINIT,
|
||||
MODE_HOME,
|
||||
MODE_NORMAL,
|
||||
MODE_TOOLCHANGE,
|
||||
MODE_JOG,
|
||||
} Mode;
|
||||
|
||||
std::vector<int> limits_;
|
||||
|
||||
QIODevice* serial_;
|
||||
uint8_t nAxis_;
|
||||
|
||||
uint8_t outputs_ = 0;
|
||||
int spindleSpeed_ = 0;
|
||||
uint16_t sensors_;
|
||||
std::vector<int> lastKnownPos_;
|
||||
std::vector<int> touchoffPos_;
|
||||
Mode mode_ = MODE_PREINIT;
|
||||
Axis axisHomed_ = AXIS_NONE;
|
||||
Axis homeAxis_ = AXIS_NONE;
|
||||
|
||||
Axis jogAxis_ = AXIS_NONE;
|
||||
int jogStep_ = -1;
|
||||
int jogDirection_ = 0;
|
||||
|
||||
QTimer positionTimer;
|
||||
QTimer stateTimer;
|
||||
QTimer initTimer;
|
||||
|
||||
QByteArray lineBuffer_;
|
||||
|
||||
void processIncomeingLine();
|
||||
static int axisToMashineNumber(Axis axis);
|
||||
QByteArray generateCmdForOffset(QByteArray command);
|
||||
|
||||
private slots:
|
||||
void serialReadyRead();
|
||||
void initTimerFn();
|
||||
void stateTimerFn();
|
||||
void reinit();
|
||||
|
||||
public:
|
||||
explicit VhfMill(QIODevice* serial, uint8_t nAxis = 4, QObject *parent = nullptr);
|
||||
std::vector<int> getLastKnownPosition() const;
|
||||
Axis homed() const;
|
||||
bool allHomed() const;
|
||||
uint8_t axisCount() const;
|
||||
uint16_t getLastKnownSensors() const;
|
||||
bool presureReady() const;
|
||||
bool isInitDone() const;
|
||||
int getLastSpindleSpeed() const;
|
||||
std::vector<int> getLastTouchoffPosition() const;
|
||||
const std::vector<int>& getLimits() const;
|
||||
|
||||
static const QString textForErrno(int errorNumber);
|
||||
static size_t axisToIndex(Axis axis);
|
||||
|
||||
public slots:
|
||||
void setSpindleSpeed(int speed);
|
||||
void send(const QByteArray& cmd);
|
||||
void stop();
|
||||
void home(VhfMill::Axis axis);
|
||||
void jog(VhfMill::Axis axis, int jogDirection);
|
||||
void setOutput(int output, bool state);
|
||||
void setTool(int tool);
|
||||
void reqTool();
|
||||
void reqOutputs();
|
||||
void reqPosition();
|
||||
void reqSensors();
|
||||
void reqSpindleSpeed();
|
||||
void enablePosUpdates(bool enable);
|
||||
void enableStateUpdates(bool enable);
|
||||
void touchOff(VhfMill::Axis axis, int offset);
|
||||
void touchOffAbsolute(std::vector<int> touchoffPos);
|
||||
void setjogStep(int step);
|
||||
void init();
|
||||
|
||||
signals:
|
||||
void raiseError(int errorNumber);
|
||||
void positionUpdate(std::vector<int> position);
|
||||
void isHomed(VhfMill::Axis axis);
|
||||
void gotLine(QByteArray string);
|
||||
void gotToolNum(int tool);
|
||||
void gotOutputs(uint8_t outputs);
|
||||
void gotSindleSpeed(int speed);
|
||||
void gotProbeState(bool state);
|
||||
void gotPressureState(bool state);
|
||||
void touchOffChanged();
|
||||
void initDone();
|
||||
void toolChangeDone();
|
||||
void touchoffChanged(std::vector<int> touchoffPos);
|
||||
void jogStepChanged(int step);
|
||||
};
|
||||
|
||||
#endif // VHFMILL_H
|
53
vhfmillthread.cpp
Normal file
53
vhfmillthread.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "vhfmillthread.h"
|
||||
|
||||
VhfMillThread::VhfMillThread(bool tcpI, int portI, const QString& hostI, const QString& serialPortI, QObject *parent):
|
||||
tcp(tcpI),
|
||||
port(portI),
|
||||
serialPort(serialPortI),
|
||||
host(hostI),
|
||||
QThread(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void VhfMillThread::run()
|
||||
{
|
||||
if(tcp)
|
||||
{
|
||||
QTcpSocket* microSocket = new QTcpSocket;
|
||||
microSocket->connectToHost(host, port, QIODevice::ReadWrite);
|
||||
if(!microSocket->waitForConnected(1000))
|
||||
{
|
||||
ret = -2;
|
||||
ready();
|
||||
return;
|
||||
}
|
||||
masterIODevice = microSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSerialPort* microPort = new QSerialPort;
|
||||
microPort->setPortName(serialPort);
|
||||
microPort->setBaudRate(115200);
|
||||
|
||||
if(!microPort->open(QIODevice::ReadWrite))
|
||||
{
|
||||
qDebug()<<"could not open serial port "<<serialPort;
|
||||
ret = -3;
|
||||
ready();
|
||||
return;
|
||||
}
|
||||
masterIODevice = microPort;
|
||||
}
|
||||
|
||||
mill = new VhfMill(masterIODevice);
|
||||
ret = 0;
|
||||
ready();
|
||||
exec();
|
||||
delete mill;
|
||||
delete masterIODevice;
|
||||
}
|
||||
|
||||
VhfMillThread::~VhfMillThread()
|
||||
{
|
||||
}
|
||||
|
36
vhfmillthread.h
Normal file
36
vhfmillthread.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef VHFMILLTHREAD_H
|
||||
#define VHFMILLTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QSerialPort>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include "vhfmill.h"
|
||||
|
||||
class VhfMillThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
const bool tcp;
|
||||
const int port;
|
||||
const QString serialPort;
|
||||
const QString host;
|
||||
|
||||
public:
|
||||
VhfMill* mill = nullptr;
|
||||
QIODevice* masterIODevice = nullptr;
|
||||
int ret = -1;
|
||||
|
||||
public:
|
||||
VhfMillThread(bool tcpI, int portI, const QString& hostI, const QString& serialPortI, QObject *parent = nullptr);
|
||||
~VhfMillThread();
|
||||
|
||||
signals:
|
||||
void ready();
|
||||
|
||||
protected:
|
||||
virtual void run() override;
|
||||
};
|
||||
|
||||
|
||||
#endif // VHFMILLTHREAD_H
|
Loading…
x
Reference in New Issue
Block a user