inital commit
This commit is contained in:
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
|
Reference in New Issue
Block a user