diff --git a/SavvyCAN.pro b/SavvyCAN.pro index 07fc638..705df29 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -49,8 +49,7 @@ SOURCES += main.cpp\ can_structs.cpp \ isotp_interpreterwindow.cpp \ isotp_handler.cpp \ - deltawindow.cpp \ - deltamodel.cpp + motorcontrollerconfigwindow.cpp HEADERS += mainwindow.h \ can_structs.h \ @@ -86,8 +85,7 @@ HEADERS += mainwindow.h \ udsscanwindow.h \ isotp_interpreterwindow.h \ isotp_handler.h \ - deltawindow.h \ - deltamodel.h + motorcontrollerconfigwindow.h FORMS += mainwindow.ui \ graphingwindow.ui \ @@ -110,7 +108,8 @@ FORMS += mainwindow.ui \ fuzzingwindow.ui \ udsscanwindow.ui \ isotp_interpreterwindow.ui \ - deltawindow.ui + deltawindow.ui \ + motorcontrollerconfigwindow.ui DISTFILES += diff --git a/canframemodel.cpp b/canframemodel.cpp index ef08b4f..ae289c2 100644 --- a/canframemodel.cpp +++ b/canframemodel.cpp @@ -188,6 +188,7 @@ void CANFrameModel::recalcOverwrite() QVariant CANFrameModel::data(const QModelIndex &index, int role) const { + int dLen; QString tempString; if (!index.isValid()) return QVariant(); @@ -220,7 +221,10 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const return QString::number(thisFrame.len); break; case 6: //data - for (int i = 0; i < thisFrame.len; i++) + dLen = thisFrame.len; + if (dLen < 0) dLen = 0; + if (dLen > 8) dLen = 8; + for (int i = 0; i < dLen; i++) { tempString.append(Utility::formatNumber(thisFrame.data[i])); tempString.append(" "); diff --git a/config.h b/config.h index 12accfa..de0d42c 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ #ifndef CONFIG #define CONFIG -#define VERSION 156 +#define VERSION 157 //try to keep this in sync. //SavvyCAN will complain if you connect a GVRET board with a revision diff --git a/dbc_classes.h b/dbc_classes.h index 9318791..bde4ead 100644 --- a/dbc_classes.h +++ b/dbc_classes.h @@ -91,10 +91,10 @@ class DBC_MESSAGE public: DBC_MESSAGE(); - int ID; + uint32_t ID; QString name; QString comment; - int len; + unsigned int len; DBC_NODE *sender; QList attributes; DBCSignalHandler *sigHandler; diff --git a/dbchandler.cpp b/dbchandler.cpp index 057ecb1..2142ee3 100644 --- a/dbchandler.cpp +++ b/dbchandler.cpp @@ -289,7 +289,7 @@ void DBCFile::loadFile(QString fileName) if (match.hasMatch()) { DBC_MESSAGE msg; - msg.ID = match.captured(1).toInt(); //the ID is always stored in decimal format + msg.ID = match.captured(1).toULong() & 0x7FFFFFFFul; //the ID is always stored in decimal format msg.name = match.captured(2); msg.len = match.captured(3).toInt(); msg.sender = findNodeByName(match.captured(4)); @@ -310,7 +310,7 @@ void DBCFile::loadFile(QString fileName) sig.isMultiplexor = false; qDebug() << "Found a SG line"; - regex.setPattern("^SG\\_ *(\\w+) *M *: *(\\d+)\\|(\\d+)@(\\d+)([\\+|\\-]) \\(([0-9.+\\-eE]+),([0-9.+\\-eE]+)\\) \\[([0-9.+\\-eE]+)\\|([0-9.+\\-eE]+)\\] \\\"(.*)\\\" (.*)"); + regex.setPattern("^SG\\_ *(\\w+)^ *M *: *(\\d+)\\|(\\d+)@(\\d+)([\\+|\\-]) \\(([0-9.+\\-eE]+),([0-9.+\\-eE]+)\\) \\[([0-9.+\\-eE]+)\\|([0-9.+\\-eE]+)\\] \\\"(.*)\\\" (.*)"); match = regex.match(line); if (match.hasMatch()) @@ -321,7 +321,7 @@ void DBCFile::loadFile(QString fileName) } else { - regex.setPattern("^SG\\_ *(\\w+) *m(\\d+) *: *(\\d+)\\|(\\d+)@(\\d+)([\\+|\\-]) \\(([0-9.+\\-eE]+),([0-9.+\\-eE]+)\\) \\[([0-9.+\\-eE]+)\\|([0-9.+\\-eE]+)\\] \\\"(.*)\\\" (.*)"); + regex.setPattern("^SG\\_ *(\\w+)^ *m(\\d+) *: *(\\d+)\\|(\\d+)@(\\d+)([\\+|\\-]) \\(([0-9.+\\-eE]+),([0-9.+\\-eE]+)\\) \\[([0-9.+\\-eE]+)\\|([0-9.+\\-eE]+)\\] \\\"(.*)\\\" (.*)"); match = regex.match(line); if (match.hasMatch()) { diff --git a/deltamodel.cpp b/deltamodel.cpp deleted file mode 100644 index 4d501d2..0000000 --- a/deltamodel.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "deltamodel.h" - -DeltaModel::DeltaModel(QObject *parent) - : QAbstractTableModel(parent) -{ -} - -QVariant DeltaModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - // FIXME: Implement me! - return QVariant(); -} - -int DeltaModel::rowCount(const QModelIndex &parent) const -{ - if (!parent.isValid()) - return 0; - - return 0; - - // FIXME: Implement me! -} - -int DeltaModel::columnCount(const QModelIndex &parent) const -{ - if (!parent.isValid()) - return 0; - - return 0; - - // FIXME: Implement me! -} - -QVariant DeltaModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - // FIXME: Implement me! - return QVariant(); -} diff --git a/deltamodel.h b/deltamodel.h deleted file mode 100644 index c0444d8..0000000 --- a/deltamodel.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef DELTAMODEL_H -#define DELTAMODEL_H - -#include - -class DeltaModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - explicit DeltaModel(QObject *parent = 0); - - // Header: - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - - // Basic functionality: - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - -private: -}; - -#endif // DELTAMODEL_H \ No newline at end of file diff --git a/deltawindow.cpp b/deltawindow.cpp deleted file mode 100644 index 8a1b3c0..0000000 --- a/deltawindow.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "deltawindow.h" -#include "ui_deltawindow.h" - -DeltaWindow::DeltaWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::DeltaWindow) -{ - ui->setupUi(this); -} - -DeltaWindow::~DeltaWindow() -{ - delete ui; -} diff --git a/deltawindow.h b/deltawindow.h deleted file mode 100644 index e9c30cf..0000000 --- a/deltawindow.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DELTAWINDOW_H -#define DELTAWINDOW_H - -#include - -namespace Ui { -class DeltaWindow; -} - -class DeltaWindow : public QDialog -{ - Q_OBJECT - -public: - explicit DeltaWindow(QWidget *parent = 0); - ~DeltaWindow(); - -private: - Ui::DeltaWindow *ui; -}; - -#endif // DELTAWINDOW_H diff --git a/firmwareuploaderwindow.cpp b/firmwareuploaderwindow.cpp index b9be616..cd032ee 100644 --- a/firmwareuploaderwindow.cpp +++ b/firmwareuploaderwindow.cpp @@ -71,10 +71,11 @@ void FirmwareUploaderWindow::gotTargettedFrame(int frameLoc) const CANFrame &frame = modelFrames->at(frameLoc); if (frame.ID == (baseAddress + 0x10)) { qDebug() << "Start firmware reply"; - if ((frame.data[0] == 0xDE) && (frame.data[1] == 0xAF)) + if ((frame.data[0] == 0xAD) && (frame.data[1] == 0xDE)) { - if ((frame.data[2] == 0xDE) && (frame.data[3] == 0xED)) + if ((frame.data[2] == 0xAF) && (frame.data[3] == 0xDE)) { + qDebug() << "THere's dead beef here"; if ((frame.data[4] == (token & 0xFF)) && (frame.data[5] == ((token >> 8) & 0xFF))) { if ((frame.data[6] == ((token >> 16) & 0xFF)) && (frame.data[7] == ((token >> 24) & 0xFF))) @@ -144,10 +145,10 @@ void FirmwareUploaderWindow::sendFirmwareEnding() output->extended = false; output->len = 4; output->ID = baseAddress + 0x30; - output->data[0] = 0xC0; - output->data[1] = 0xDE; - output->data[2] = 0xFA; - output->data[3] = 0xDE; + output->data[3] = 0xC0; + output->data[2] = 0xDE; + output->data[1] = 0xFA; + output->data[0] = 0xDE; sendCANFrame(output, bus); } @@ -168,10 +169,11 @@ void FirmwareUploaderWindow::handleStartStopTransfer() output->extended = false; output->len = 8; output->ID = baseAddress; - output->data[0] = 0xDE; - output->data[1] = 0xAD; - output->data[2] = 0xBE; - output->data[3] = 0xEF; + + output->data[0] = 0xEF; + output->data[1] = 0xBE; + output->data[2] = 0xAD; + output->data[3] = 0xDE; output->data[4] = token & 0xFF; output->data[5] = (token >> 8) & 0xFF; output->data[6] = (token >> 16) & 0xFF; diff --git a/framefileio.cpp b/framefileio.cpp index 2e96149..c279685 100644 --- a/framefileio.cpp +++ b/framefileio.cpp @@ -126,6 +126,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector* frameCache filters.append(QString(tr("CAN-DO Log (*.avc *.can *.evc *.qcc *.AVC *.CAN *.EVC *.QCC)"))); filters.append(QString(tr("Vehicle Spy (*.csv *.CSV)"))); filters.append(QString(tr("Candump/Kayak (*.log *.LOG)"))); + filters.append(QString(tr("PCAN Viewer (*.txt *.TXT)"))); dialog.setFileMode(QFileDialog::ExistingFile); dialog.setNameFilters(filters); @@ -155,6 +156,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector* frameCache if (dialog.selectedNameFilter() == filters[7]) result = loadCANDOFile(filename, frameCache); if (dialog.selectedNameFilter() == filters[8]) result = loadVehicleSpyFile(filename, frameCache); if (dialog.selectedNameFilter() == filters[9]) result = loadCanDumpFile(filename, frameCache); + if (dialog.selectedNameFilter() == filters[10]) result = loadPCANFile(filename, frameCache); progress.cancel(); @@ -393,6 +395,70 @@ bool FrameFileIO::saveCRTDFile(QString filename, const QVector* frames return true; } + +//; Message Number +//; | Time Offset (ms) +//; | | Type +//; | | | ID (hex) +//; | | | | Data Length Code +//; | | | | | Data Bytes (hex) ... +//; | | | | | | +//;---+-- ----+---- --+-- ----+--- + -+ -- -- -- -- -- -- -- +// 0-6 10-18 21-25 28-35 38 41-? +//Fixed length lines +bool FrameFileIO::loadPCANFile(QString filename, QVector* frames) +{ + QFile *inFile = new QFile(filename); + CANFrame thisFrame; + QByteArray line; + int lineCounter = 0; + bool foundErrors = false; + + if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) + { + delete inFile; + return false; + } + + while (!inFile->atEnd()) { + lineCounter++; + if (lineCounter > 100) + { + qApp->processEvents(); + lineCounter = 0; + } + line = inFile->readLine(); + if (line.startsWith(';')) continue; + if (line.length() > 2) + { + thisFrame.timestamp = line.mid(10, 8).simplified().toFloat() * 1000ull; + thisFrame.ID = line.mid(28, 8).simplified().toUInt(NULL, 16); + if (thisFrame.ID < 0x1FFFFFFF) + { + thisFrame.len = line.mid(38,1).toInt(); + thisFrame.isReceived = true; + thisFrame.bus = 0; + thisFrame.extended = false; + QList tokens = line.mid(41, thisFrame.len * 3).split(' '); + for (int d = 0; d < thisFrame.len; d++) + { + if (tokens[d] != "") + { + thisFrame.data[d] = tokens[d].toInt(NULL, 16); + } + else thisFrame.data[d] = 0; + } + frames->append(thisFrame); + } + } + //else foundErrors = true; + } + inFile->close(); + delete inFile; + return !foundErrors; +} + + //The "native" file format for this program bool FrameFileIO::loadNativeCSVFile(QString filename, QVector* frames) { diff --git a/framefileio.h b/framefileio.h index 44a648f..13f6e59 100644 --- a/framefileio.h +++ b/framefileio.h @@ -43,6 +43,7 @@ public: static bool loadFrameFile(QString &, QVector*); static bool saveFrameFile(QString &, const QVector*); static bool loadCanDumpFile(QString, QVector*); + static bool loadPCANFile(QString, QVector*); private: static QString unQuote(QString); diff --git a/frameinfowindow.cpp b/frameinfowindow.cpp index c06e30d..33c5aa5 100644 --- a/frameinfowindow.cpp +++ b/frameinfowindow.cpp @@ -114,6 +114,9 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) int targettedID; int minLen, maxLen, thisLen; int avgInterval; + int minInterval; + int maxInterval; + int thisInterval; int minData[8]; int maxData[8]; int dataHistogram[256][8]; @@ -195,6 +198,8 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) //clear out all the counters and accumulators minLen = 8; maxLen = 0; + minInterval = 0x7FFFFFFF; + maxInterval = 0; for (int i = 0; i < 8; i++) { minData[i] = 256; @@ -213,7 +218,13 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) //then find all data points for (int j = 0; j < frameCache.count(); j++) { - if (j != 0) avgInterval += (frameCache[j].timestamp - frameCache[j-1].timestamp); + if (j != 0) + { + thisInterval = (frameCache[j].timestamp - frameCache[j-1].timestamp); + if (thisInterval > maxInterval) maxInterval = thisInterval; + if (thisInterval < minInterval) minInterval = thisInterval; + avgInterval += thisInterval; + } thisLen = frameCache.at(j).len; if (thisLen > maxLen) maxLen = thisLen; if (thisLen < minLen) minLen = thisLen; @@ -249,7 +260,16 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) baseNode->addChild(tempItem); tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("Average inter-frame interval: ") + QString::number(avgInterval) + "us"); + tempItem->setText(0, tr("Average inter-frame interval: ") + QString::number(avgInterval / 1000.0f) + "ms"); + baseNode->addChild(tempItem); + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr("Minimum inter-frame interval: ") + QString::number(minInterval / 1000.0f) + "ms"); + baseNode->addChild(tempItem); + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr("Maximum inter-frame interval: ") + QString::number(maxInterval / 1000.0f) + "ms"); + baseNode->addChild(tempItem); + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr("Inter-frame interval variation: ") + QString::number((maxInterval - minInterval) / 1000.0f) + "ms"); baseNode->addChild(tempItem); for (int c = 0; c < maxLen; c++) diff --git a/graphingwindow.cpp b/graphingwindow.cpp index e555f0f..88a2ddf 100644 --- a/graphingwindow.cpp +++ b/graphingwindow.cpp @@ -197,12 +197,16 @@ void GraphingWindow::titleDoubleClick(QMouseEvent* event, QCPPlotTitle* title) Q_UNUSED(event) // Set the plot title by double clicking on it bool ok; + + /* QString newTitle = QInputDialog::getText(this, "SavvyCAN Graphing", "New plot title:", QLineEdit::Normal, title->text(), &ok); if (ok) { title->setText(newTitle); ui->graphingView->replot(); } + */ + editSelectedGraph(); } void GraphingWindow::axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part) @@ -225,7 +229,7 @@ void GraphingWindow::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem // Rename a graph by double clicking on its legend item Q_UNUSED(legend) if (item) // only react if item was clicked (user could have clicked on border padding of legend where there is no item, then item is 0) - { + {/* QCPPlottableLegendItem *plItem = qobject_cast(item); bool ok; QString newName = QInputDialog::getText(this, "SavvyCAN Graphing", "New graph name:", QLineEdit::Normal, plItem->plottable()->name(), &ok); @@ -246,7 +250,8 @@ void GraphingWindow::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem } ui->graphingView->replot(); - } + } */ + editSelectedGraph(); } } diff --git a/mainwindow.cpp b/mainwindow.cpp index 7590f1d..45c7cbc 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -98,6 +98,7 @@ MainWindow::MainWindow(QWidget *parent) : dbcFileWindow = NULL; fuzzingWindow = NULL; udsScanWindow = NULL; + motorctrlConfigWindow = NULL; isoWindow = NULL; dbcHandler = new DBCHandler; bDirty = false; @@ -138,11 +139,12 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->listFilters, &QListWidget::itemChanged, this, &MainWindow::filterListItemChanged); connect(ui->btnFilterAll, &QAbstractButton::clicked, this, &MainWindow::filterSetAll); connect(ui->btnFilterNone, &QAbstractButton::clicked, this, &MainWindow::filterClearAll); - connect(ui->actionFirmware_Uploader, &QAction::triggered, this, &MainWindow::showFirmwareUploaderWindow); + connect(ui->actionFirmware_Update, &QAction::triggered, this, &MainWindow::showFirmwareUploaderWindow); connect(ui->actionDBC_File_Manager, &QAction::triggered, this, &MainWindow::showDBCFileWindow); connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow); connect(ui->actionUDS_Scanner, &QAction::triggered, this, &MainWindow::showUDSScanWindow); connect(ui->actionISO_TP_Decoder, &QAction::triggered, this, &MainWindow::showISOInterpreterWindow); + connect(ui->actionMotorControlConfig, &QAction::triggered, this, &MainWindow::showMCConfigWindow); lbStatusConnected.setText(tr("Not connected")); updateFileStatus(); @@ -978,6 +980,17 @@ void MainWindow::showFuzzingWindow() fuzzingWindow->show(); } +void MainWindow::showMCConfigWindow() +{ + if (!motorctrlConfigWindow) + { + motorctrlConfigWindow = new MotorControllerConfigWindow(model->getListReference()); + connect(motorctrlConfigWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int))); + connect(motorctrlConfigWindow, SIGNAL(sendFrameBatch(const QList*)), worker, SLOT(sendFrameBatch(const QList*))); + } + motorctrlConfigWindow->show(); +} + void MainWindow::showUDSScanWindow() { if (!udsScanWindow) diff --git a/mainwindow.h b/mainwindow.h index fc8115f..d6f1bfd 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -26,6 +26,7 @@ #include "fuzzingwindow.h" #include "udsscanwindow.h" #include "isotp_interpreterwindow.h" +#include "motorcontrollerconfigwindow.h" namespace Ui { class MainWindow; @@ -65,6 +66,7 @@ private slots: void showScriptingWindow(); void showDBCFileWindow(); void showFuzzingWindow(); + void showMCConfigWindow(); void showUDSScanWindow(); void showISOInterpreterWindow(); void exitApp(); @@ -144,6 +146,7 @@ private: FuzzingWindow *fuzzingWindow; UDSScanWindow *udsScanWindow; ISOTP_InterpreterWindow *isoWindow; + MotorControllerConfigWindow *motorctrlConfigWindow; //various private storage QLabel lbStatusConnected; diff --git a/mainwindow.ui b/mainwindow.ui index fafd407..64946bc 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -221,6 +221,8 @@ + + @@ -393,6 +395,16 @@ ISO-TP Decoder + + + Firmware Update + + + + + MotorControlConfig + + diff --git a/motorcontrollerconfigwindow.cpp b/motorcontrollerconfigwindow.cpp new file mode 100644 index 0000000..54bdef3 --- /dev/null +++ b/motorcontrollerconfigwindow.cpp @@ -0,0 +1,406 @@ +#include "motorcontrollerconfigwindow.h" +#include "ui_motorcontrollerconfigwindow.h" + +#include "mainwindow.h" +#include + +MotorControllerConfigWindow::MotorControllerConfigWindow(const QVector *frames, QWidget *parent) : + QDialog(parent), + ui(new Ui::MotorControllerConfigWindow) +{ + ui->setupUi(this); + + modelFrames = frames; + + timer.setInterval(40); + transmitStep = 0; + doingRequest = false; + + connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int))); + connect(ui->btnRefresh, SIGNAL(clicked(bool)), this, SLOT(refreshData())); + connect(ui->btnSave, SIGNAL(clicked(bool)), this, SLOT(saveData())); + connect(&timer, SIGNAL(timeout()), this, SLOT(timerTick())); +} + +MotorControllerConfigWindow::~MotorControllerConfigWindow() +{ + delete ui; +} + +void MotorControllerConfigWindow::updatedFrames(int numFrames) +{ + CANFrame thisFrame; + int id; + int param; + float valu; + uint8_t eightval; + uint16_t sixteenval; + uint32_t thirtytwoval; + if (numFrames == -1) //all frames deleted + { + + } + else if (numFrames == -2) //all new set of frames. Reset + { + + } + else //just got some new frames. See if they are relevant. + { + if (numFrames > modelFrames->count()) return; + for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++) + { + thisFrame = modelFrames->at(i); + id = thisFrame.ID; + + if (id == 0x420) + { + param = thisFrame.data[0]; + eightval = thisFrame.data[1]; + sixteenval = thisFrame.data[1] + (thisFrame.data[2] * 256ul); + thirtytwoval = sixteenval + (thisFrame.data[3] * 65536ul) + (thisFrame.data[4] * 256ul * 65536ul); + + switch (param) + { + case 0: //voltage scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editVoltageScale->setText(QString::number(valu, 'g', 4)); + break; + case 1: //voltage bias + ui->editVoltageOffset->setText(QString::number(sixteenval)); + break; + case 2: //current 1 scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editCurrent1Scale->setText(QString::number(valu, 'g', 4)); + break; + case 3: //current 1 bias + ui->editCurrent1Offset->setText(QString::number(sixteenval)); + break; + case 4: //current 2 scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editCurrent2Scale->setText(QString::number(valu, 'g', 4)); + break; + case 5: //current 2 bias + ui->editCurrent2Offset->setText(QString::number(sixteenval)); + break; + case 6: //Inverter temp 1 scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editInvTemp1Scale->setText(QString::number(valu, 'g', 4)); + break; + case 7: //Inverter temp 1 bias + ui->editInvTemp1Offset->setText(QString::number(sixteenval)); + break; + case 8: //Inverter temp 2 scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editInvTemp2Scale->setText(QString::number(valu, 'g', 4)); + break; + case 9: //Inverter temp 2 bias + ui->editInvTemp2Offset->setText(QString::number(sixteenval)); + break; + case 10: //Motor temp 1 scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editMotorTemp1Scale->setText(QString::number(valu, 'g', 4)); + break; + case 11: //Motor temp 1 bias + ui->editMotorTemp1Offset->setText(QString::number(sixteenval)); + break; + case 12: //Motor temp 2 scale (*65536) + valu = thirtytwoval / 65536.0f; + ui->editMotorTemp2Scale->setText(QString::number(valu, 'g', 4)); + break; + case 13: //Motor temp 2 bias + ui->editMotorTemp2Offset->setText(QString::number(sixteenval)); + break; + case 14: //motor type (inductive, pmac, bldc) + ui->editMotorType->setText(QString::number(eightval)); + break; + case 15: //control type (vhz, foc) + ui->editControlType->setText(QString::number(eightval)); + break; + case 16: //encoder count + ui->editEncoderCount->setText(QString::number(sixteenval)); + break; + case 17: //encoder direction (0 = normal, 1 = reversed) + ui->editEncoderDir->setText(QString::number(eightval)); + break; + case 18: + ui->editPolePairs->setText(QString::number(eightval)); + break; + case 19: //rotor time const (*65536) + valu = thirtytwoval / 65536.0f; + ui->editRotorTime->setText(QString::number(valu, 'g', 4)); + break; + case 20: //Torque KP (*4096) + valu = thirtytwoval / 4096.0f; + ui->editTorqueKP->setText(QString::number(valu, 'g', 4)); + break; + case 21: //Torque KI (*4096) + valu = thirtytwoval / 4096.0f; + ui->editTorqueKI->setText(QString::number(valu, 'g', 4)); + break; + case 22: //Torque KD (*4096) + valu = thirtytwoval / 4096.0f; + ui->editTorqueKD->setText(QString::number(valu, 'g', 4)); + break; + case 23: //Max RPM + ui->editMaxRPM->setText(QString::number(sixteenval)); + break; + case 24: //Max Torque + valu = sixteenval / 10.0f; + ui->editMaxTorque->setText(QString::number(valu, 'g', 4)); + break; + case 25: //Max Amps in Drive + valu = sixteenval / 10.0f; + ui->editMaxAmpsDrive->setText(QString::number(valu, 'g', 4)); + break; + case 26: //Max Amps in Regen + valu = sixteenval / 10.0f; + ui->editMaxAmpsRegen->setText(QString::number(valu, 'g', 4)); + break; + case 27: //VHz Full Speed + ui->editVHZFull->setText(QString::number(sixteenval)); + break; + case 28: //Theta offset + ui->editThetaOffset->setText(QString::number(sixteenval)); + break; + case 29: //Hall AB + ui->editHallAB->setText(QString::number(eightval)); + break; + case 30: //Hall BC + ui->editHallBC->setText(QString::number(eightval)); + break; + case 31: //Hall CA + ui->editHallCA->setText(QString::number(eightval)); + break; + } + } + } + } +} + +void MotorControllerConfigWindow::refreshData() +{ + doingRequest = true; + transmitStep = 0; + timer.start(); +} + +void MotorControllerConfigWindow::saveData() +{ + doingRequest = false; + transmitStep = 0; + timer.start(); +} + +void MotorControllerConfigWindow::timerTick() +{ + float valu; + uint32_t intval32; + uint16_t intval16; + uint8_t intval8; + + if (doingRequest) //send requests for data + { + //qDebug() << "Request: " << QString::number(transmitStep); + send8BitParam(transmitStep, 0); + transmitStep++; + if (transmitStep == 32) + { + timer.stop(); + return; + } + } + else //save current value of all data items + { + //qDebug() << "Transmission: " << QString::number(transmitStep); + switch (transmitStep) + { + case 0: + valu = ui->editVoltageScale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 1: + intval16 = ui->editVoltageOffset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 2: + valu = ui->editCurrent1Scale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 3: + intval16 = ui->editCurrent1Offset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 4: + valu = ui->editCurrent2Scale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 5: + intval16 = ui->editCurrent2Offset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 6: //Inverter temp 1 scale (*65536) + valu = ui->editInvTemp1Scale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 7: //Inverter temp 1 bias + intval16 = ui->editInvTemp1Offset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 8: //Inverter temp 2 scale (*65536) + valu = ui->editInvTemp2Scale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 9: //Inverter temp 2 bias + intval16 = ui->editInvTemp2Offset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 10: //Motor temp 1 scale (*65536) + valu = ui->editMotorTemp1Scale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 11: //Motor temp 1 bias + intval16 = ui->editMotorTemp1Offset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 12: //Motor temp 2 scale (*65536) + valu = ui->editMotorTemp2Scale->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 13: //Motor temp 2 bias + intval16 = ui->editMotorTemp2Offset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 14: //motor type (inductive, pmac, bldc) + intval8 = ui->editMotorType->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 15: //control type (vhz, foc) + intval8 = ui->editControlType->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 16: //encoder count + intval16 = ui->editEncoderCount->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 17: //encoder direction (0 = normal, 1 = reversed) + intval8 = ui->editEncoderDir->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 18: + intval8 = ui->editPolePairs->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 19: //rotor time const (*65536) + valu = ui->editRotorTime->text().toFloat(); + intval32 = valu * 65536; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 20: //Torque KP (*4096) + valu = ui->editTorqueKP->text().toFloat(); + intval32 = valu * 4096; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 21: //Torque KI (*4096) + valu = ui->editTorqueKI->text().toFloat(); + intval32 = valu * 4096; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 22: //Torque KD (*4096) + valu = ui->editTorqueKD->text().toFloat(); + intval32 = valu * 4096; + send32BitParam(0x80 + transmitStep, intval32); + break; + case 23: //Max RPM + intval16 = ui->editMaxRPM->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 24: //Max Torque + valu = ui->editMaxTorque->text().toFloat(); + intval16 = valu * 10; + send16BitParam(0x80 + transmitStep, intval16); + break; + case 25: //Max Amps in Drive + valu = ui->editMaxAmpsDrive->text().toFloat(); + intval16 = valu * 10; + send16BitParam(0x80 + transmitStep, intval16); + break; + case 26: //Max Amps in Regen + valu = ui->editMaxAmpsRegen->text().toFloat(); + intval16 = valu * 10; + send16BitParam(0x80 + transmitStep, intval16); + break; + case 27: //VHz Full Speed + intval16 = ui->editVHZFull->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 28: //Theta offset + intval16 = ui->editThetaOffset->text().toInt(); + send16BitParam(0x80 + transmitStep, intval16); + break; + case 29: //Hall AB + intval8 = ui->editHallAB->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 30: //Hall BC + intval8 = ui->editHallBC->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 31: //Hall CA + intval8 = ui->editHallCA->text().toInt(); + send8BitParam(0x80 + transmitStep, intval8); + break; + case 32: + timer.stop(); + return; + break; + } + transmitStep++; + } +} + +void MotorControllerConfigWindow::send32BitParam(int param, uint32_t valu) +{ + outFrame.ID = 0x230; + outFrame.len = 5; + outFrame.bus = 0; + outFrame.extended = false; + outFrame.data[0] = param & 0xFF; + outFrame.data[1] = valu & 0xFF; + outFrame.data[2] = (valu >> 8) & 0xFF; + outFrame.data[3] = (valu >> 16) & 0xFF; + outFrame.data[4] = (valu >> 24) & 0xFF; + + emit sendCANFrame(&outFrame, 0); +} + +void MotorControllerConfigWindow::send16BitParam(int param, uint16_t valu) +{ + outFrame.ID = 0x230; + outFrame.len = 3; + outFrame.bus = 0; + outFrame.extended = false; + outFrame.data[0] = param & 0xFF; + outFrame.data[1] = valu & 0xFF; + outFrame.data[2] = (valu >> 8) & 0xFF; + + emit sendCANFrame(&outFrame, 0); +} + +void MotorControllerConfigWindow::send8BitParam(int param, uint8_t valu) +{ + outFrame.ID = 0x230; + outFrame.len = 2; + outFrame.bus = 0; + outFrame.extended = false; + outFrame.data[0] = param & 0xFF; + outFrame.data[1] = valu; + + emit sendCANFrame(&outFrame, 0); +} diff --git a/motorcontrollerconfigwindow.h b/motorcontrollerconfigwindow.h new file mode 100644 index 0000000..f973300 --- /dev/null +++ b/motorcontrollerconfigwindow.h @@ -0,0 +1,44 @@ +#ifndef MOTORCONTROLLERCONFIGWINDOW_H +#define MOTORCONTROLLERCONFIGWINDOW_H + +#include +#include +#include "can_structs.h" + +namespace Ui { +class MotorControllerConfigWindow; +} + +class MotorControllerConfigWindow : public QDialog +{ + Q_OBJECT + +public: + explicit MotorControllerConfigWindow(const QVector *frames, QWidget *parent = 0); + ~MotorControllerConfigWindow(); + +signals: + void sendCANFrame(const CANFrame *, int); + void sendFrameBatch(const QList *); + +private slots: + void updatedFrames(int numFrames); + void refreshData(); + void saveData(); + void timerTick(); + +private: + Ui::MotorControllerConfigWindow *ui; + const QVector *modelFrames; + QTimer timer; + CANFrame outFrame; + bool doingRequest; + int transmitStep; + + void send32BitParam(int param, uint32_t valu); + void send16BitParam(int param, uint16_t valu); + void send8BitParam(int param, uint8_t valu); + +}; + +#endif // MOTORCONTROLLERCONFIGWINDOW_H diff --git a/motorcontrollerconfigwindow.ui b/motorcontrollerconfigwindow.ui new file mode 100644 index 0000000..544f07b --- /dev/null +++ b/motorcontrollerconfigwindow.ui @@ -0,0 +1,363 @@ + + + MotorControllerConfigWindow + + + + 0 + 0 + 902 + 328 + + + + Controller Configuration + + + + + + + + + + + Inv Temp 2 Offset + + + + + + + Current 1 Offset + + + + + + + Motor Type + + + + + + + + + + Motor Temp 1 Scale + + + + + + + Inv Temp 1 Scale + + + + + + + Motor Temp 2 Offset + + + + + + + Encoder Count + + + + + + + Pole Pairs + + + + + + + + + + + + + + + + + + + + + + Max Torque + + + + + + + Motor Temp 1 Offset + + + + + + + Encoder Direction + + + + + + + Voltage Scale + + + + + + + Control Type + + + + + + + + + + + + + + + + + + + + + + Torque KP + + + + + + + Motor Temp 2 Scale + + + + + + + Current 1 Scale + + + + + + + Inv Temp 2 Scale + + + + + + + VHz Full RPM + + + + + + + + + + + + + + + + Torque KI + + + + + + + + + + Current 2 Offset + + + + + + + Voltage Offset + + + + + + + Current 2 Scale + + + + + + + Rotor Time Const + + + + + + + Torque KD + + + + + + + Max Amps Drive + + + + + + + Inv Temp 1 Offset + + + + + + + Max Amps Regen + + + + + + + + + + Hall AB + + + + + + + Theta Offset + + + + + + + + + + Hall CA + + + + + + + + + + Max RPM + + + + + + + Hall BC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Refresh + + + + + + + Save + + + + + + + + + +