Page MenuHomec4science

mainwindow.cpp
No OneTemporary

File Metadata

Created
Sun, Jul 6, 13:55

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <climits>
#include <QMessageBox>
#include <QDebug>
#include <QInputDialog>
#include <QSerialPortInfo>
#include <QList>
#include "../Firmware/src/definitions.h"
const int SYNCVAR_LIST_ITEM_SIZE = SYNCVAR_NAME_SIZE + 3;
const double ENCODER_STEPS_TO_UM = 0.050;
const double GRAPH_TIME_SPAN = 10.0; // [s].
const int UPDATE_PERIOD = 50; // [ms].
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//
ui->setupUi(this);
//
encoderVarIndex = -1;
lastEncoderValue = 0.0;
encoderOffset = 0.0;
// Setup the graph widget.
ui->grapher->addGraph();
ui->grapher->xAxis->setTickLabelType(QCPAxis::ltDateTime);
ui->grapher->xAxis->setDateTimeFormat("hh:mm:ss");
ui->grapher->xAxis->setLabel("Time [s]");
ui->grapher->yAxis->setRange(-10000.0, 10000.0);
ui->grapher->yAxis->setLabel("Position [um]");
// Connect the signals to the slots.
connect(ui->zeroButton, SIGNAL(clicked(bool)), this, SLOT(zero()));
connect(ui->clearButton, SIGNAL(clicked(bool)), this, SLOT(clearDisplay()));
// Ask for the COM port.
QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
QString comPortName;
for(int i=ports.size()-1; i >= 0; i--)
{
// Remove from the list all the serial COM ports that are not the CP210x
// USB-to-serial chip.
if(!ports[i].description().contains("CP210x"))
ports.removeAt(i);
}
if(ports.size() == 0)
{
QMessageBox::critical(this, "HRI2_PC_Controller", "No COM port.");
exit(0);
}
else if(ports.size() == 1)
comPortName = ports[0].portName();
else
{
QStringList portsDescriptions;
bool ok;
for(int i=0; i<ports.size(); i++)
portsDescriptions.append(ports[i].portName() + " - " + ports[i].description());
QString portChoice = QInputDialog::getItem(this, "HRI2_PC_Controller", "Serial port:", portsDescriptions, 0, false, &ok);
int portIndex = portsDescriptions.indexOf(portChoice);
if(portIndex == -1 || !ok)
exit(0);
comPortName = ports[portIndex].portName();
}
// Setup the serial port.
serial.setPortName(comPortName);
serial.setBaudRate(UART_BAUDRATE);
serial.setDataBits(QSerialPort::Data8);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.setParity(QSerialPort::NoParity);
connect(&serial, SIGNAL(readyRead()), this, SLOT(onReceivedData()));
qDebug() << "Opening the serial COM port...";
if(serial.open(QIODevice::ReadWrite))
qDebug() << "COM port opened successfully.";
else
{
QMessageBox::critical(this, "Error", "Can't open the COM port.");
exit(0);
}
// Setup the display update timer.
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateDisplay()));
updateTimer.setSingleShot(false);
updateTimer.start(UPDATE_PERIOD);
// Request the variables list.
sendPacket(PC_MESSAGE_GET_VARS_LIST);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::sendPacket(quint8 messageType, QByteArray dataBytes)
{
QByteArray txBuffer;
txBuffer.append((1<<7) + messageType);
for(int i=0; i<dataBytes.size(); i++)
{
txBuffer.append(((quint8)dataBytes[i]) >> 4); // MSB.
txBuffer.append(((quint8)dataBytes[i]) & 0xf); // LSB.
}
serial.write(txBuffer);
serial.waitForBytesWritten(-1);
}
void MainWindow::onReceivedData()
{
QByteArray rxData = serial.readAll();
//qDebug() << "RX:" << byteBufferToBinaryString(rxData);
for(int i=0; i<rxData.size(); i++)
{
quint8 rxByte = rxData[i];
if(rxByte & (1<<7)) // The start byte has the most significant bit high.
{
rxCurrentMessageType = (rxByte & ~(1<<7)); // Remove the start bit.
rxBytesCount = 0;
}
else // The data bytes have the most significant byte low.
{
rxBytesCount++;
if(rxBytesCount % 2 == 1) // First half of the data byte has been received.
firstHalfByte = rxByte; // Store it until the second half arrives.
else // Second half of the data byte has been received.
{
int dataBytesReady = rxBytesCount/2;
rxDataBytesBuffer[dataBytesReady-1] = (firstHalfByte<<4) + (rxByte & 0xf);
switch(rxCurrentMessageType)
{
case STM_MESSAGE_VARS_LIST:
if(dataBytesReady >= 1)
{
quint8 nVars = rxDataBytesBuffer[0];
if(dataBytesReady == 1 + nVars * SYNCVAR_LIST_ITEM_SIZE)
{
for(int i=0; i<nVars; i++)
{
QString varName((char*)&rxDataBytesBuffer[1+i*SYNCVAR_LIST_ITEM_SIZE]);
if(varName == "raw_encoder")
{
encoderVarIndex = i;
// Setup the streaming.
QByteArray ba;
ba.append((quint8)1);
ba.append((quint8)1);
ba.append((quint8)encoderVarIndex);
sendPacket(PC_MESSAGE_SET_STREAMED_VAR, ba);
qDebug() << "Variable found.";
break;
}
}
}
}
break;
case STM_MESSAGE_STREAMING_PACKET:
if(dataBytesReady == 1 + 4 + 4)
{
if(rxDataBytesBuffer[0] == 1)
{
// Decode the encoder value.
qint32 rawEncoderValue; // [steps].
memcpy(&rawEncoderValue, &rxDataBytesBuffer[5], 4);
lastEncoderValue = ENCODER_STEPS_TO_UM * (double)rawEncoderValue;
}
}
break;
case STM_MESSAGE_DEBUG_TEXT:
if(dataBytesReady > 0 &&
rxDataBytesBuffer[dataBytesReady-1] == '\0')
{
qDebug() << QString((const char*)rxDataBytesBuffer);
rxCurrentMessageType = 0;
}
break;
default: // Ignore.
break;
}
}
}
}
}
void MainWindow::zero()
{
encoderOffset = lastEncoderValue;
}
void MainWindow::updateDisplay()
{
double offsettedEncoderValue = lastEncoderValue - encoderOffset;
// Get the time.
double time = ((double)QDateTime::currentMSecsSinceEpoch()) / 1000.0;
//time = fmod(time, 60.0);
// Update the label widget.
ui->probeLabel->setText(QString::number(offsettedEncoderValue, 'f', 3) + " um");
// Update the graph widget.
ui->grapher->graph(0)->addData(time,
offsettedEncoderValue);
ui->grapher->graph(0)->removeDataBefore(time - GRAPH_TIME_SPAN);
ui->grapher->xAxis->setRange(time - GRAPH_TIME_SPAN,
time);
double minVal = std::numeric_limits<double>::max();
double maxVal = std::numeric_limits<double>::lowest();
QCPDataMap* graphData = ui->grapher->graph(0)->data();
for(auto it = graphData->begin(); it != graphData->end(); ++it)
{
double val = (*it).value;
if(val > maxVal)
maxVal = val;
if(val < minVal)
minVal = val;
}
ui->grapher->yAxis->setRange(minVal, maxVal);
ui->grapher->replot();
}
void MainWindow::clearDisplay()
{
ui->grapher->graph(0)->clearData();
}

Event Timeline