VHFMill/vhfmill.cpp
2023-03-02 15:13:54 +01:00

629 lines
12 KiB
C++

#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("GB");
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";
}
}