mainwindow.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. rmui — an UI for RM (a breaking machine by AMGlatsin <sanddevil@ut.mephi.ru>)
  3. Copyright (C) 2016 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include <QResizeEvent>
  16. #include <QDateTime>
  17. #include <QtSerialPort/QtSerialPort>
  18. #include "mainwindow.h"
  19. #include "ui_mainwindow.h"
  20. MainWindow::MainWindow(QWidget *parent) :
  21. QMainWindow(parent),
  22. ui(new Ui::MainWindow)
  23. {
  24. this->xMax = 60;
  25. this->ui->setupUi(this);
  26. this->setWindowTitle("RM control interface");
  27. this->ui->centralWidget->installEventFilter(this);
  28. this->ui->toolsWidget->installEventFilter(this);
  29. this->ui->ADC1Plot->setAxisScale(QwtPlot::yLeft, 0, 4095);
  30. this->ui->ADC2Plot->setAxisScale(QwtPlot::yLeft, 0, 4095);
  31. this->ui->ADC1Plot->setAxisScale(QwtPlot::xBottom, 0, this->xMax);
  32. this->ui->ADC2Plot->setAxisScale(QwtPlot::xBottom, 0, this->xMax);
  33. this->remote = new QSerialPort(this);
  34. connect(this->remote, SIGNAL(readyRead()), this, SLOT(recvData()));
  35. connect(this->ui->ttyReconnectButton, SIGNAL(released()),this, SLOT(reopenRemote()));
  36. {
  37. memset(&this->curState, 0, sizeof(this->curState));
  38. memset(&this->ADCData, 0xff, sizeof(this->ADCData));
  39. memset(&this->ADCCurPoint, 0, sizeof(this->ADCCurPoint));
  40. int adcId = 0;
  41. while (adcId < ADCS) {
  42. QwtPlot *p = this->getPlotByAdcId(adcId);
  43. p->installEventFilter(this);
  44. int i = 0;
  45. //this->ui->ADC1Plot->setAutoReplot(true);
  46. while (i < 2) {
  47. QwtPlotCurve *c;
  48. c = &this->ADCCurve[adcId][i];
  49. c->setStyle( QwtPlotCurve::Lines );
  50. c->setPen( QColor(0, 0, 0, 255 / ((2-i)*(2-i))) );
  51. c->setRenderHint( QwtPlotItem::RenderAntialiased, true );
  52. c->setPaintAttribute( QwtPlotCurve::ClipPolygons, false );
  53. c->attach(p);
  54. i++;
  55. }
  56. p->show();
  57. adcId++;
  58. }
  59. }
  60. this->showCurState();
  61. this->redrawGraphics();
  62. this->on_stopM0Radio_toggled(true);
  63. this->on_stopM1Radio_toggled(true);
  64. this->openRemote();
  65. }
  66. MainWindow::~MainWindow()
  67. {
  68. this->closeRemote();
  69. delete ui;
  70. }
  71. void MainWindow::openRemote()
  72. {
  73. qDebug("openRemote(): %s", this->ui->ttyPathEdit->toPlainText().toStdString().c_str());
  74. //SettingsDialog::Settings p = settings->settings();
  75. this->remote->setPortName(this->ui->ttyPathEdit->toPlainText());
  76. this->remote->setBaudRate(9600);
  77. this->remote->setDataBits(QSerialPort::Data8);
  78. this->remote->setParity(QSerialPort::NoParity);
  79. this->remote->setStopBits(QSerialPort::OneStop);
  80. this->remote->setFlowControl(QSerialPort::NoFlowControl);
  81. if (remote->open(QIODevice::ReadWrite)) {
  82. this->ui->statusBar->showMessage("Connected");
  83. } else {
  84. this->ui->statusBar->showMessage("Error: cannot connect!");
  85. }
  86. }
  87. void MainWindow::closeRemote()
  88. {
  89. qDebug("closeRemote()");
  90. if (remote->isOpen())
  91. remote->close();
  92. this->ui->statusBar->showMessage("Disconnected");
  93. }
  94. void MainWindow::reopenRemote()
  95. {
  96. this->closeRemote();
  97. this->openRemote();
  98. return;
  99. }
  100. QwtPlot *MainWindow::getPlotByAdcId(int adcId)
  101. {
  102. switch (adcId) {
  103. case 0:
  104. return this->ui->ADC1Plot;
  105. case 1:
  106. return this->ui->ADC2Plot;
  107. default:
  108. qFatal("Invalid adcId == %i", adcId);
  109. }
  110. return NULL;
  111. }
  112. void MainWindow::showCurState()
  113. {
  114. this->ui->ADC1Value->setText("ADC1: "+QString::number(this->curState.adc[0].value));
  115. this->ui->ADC2Value->setText("ADC2: "+QString::number(this->curState.adc[1].value));
  116. this->ui->statusBar->showMessage(QString("Connected: " + QString(this->curState.m[0].direction) +" "+ QString::number(this->curState.m[0].speed) +" "+ QString(this->curState.m[1].direction) +" "+ QString::number(this->curState.m[1].speed) +" "+ QString::number(this->curState.adc[0].value) +" "+ QString::number(this->curState.adc[1].value)));
  117. return;
  118. }
  119. void MainWindow::pushAdcValue(u_int8_t adcId, qint64 ts, u_int16_t value)
  120. {
  121. //static int i = 0;
  122. qint64 ts_local_int = ts;
  123. double ts_local;
  124. ts_local_int %= this->xMax*1000;
  125. ts_local = (double)ts_local_int/1000;
  126. curpoint_t *c = &this->ADCCurPoint[adcId];
  127. //qDebug("pushAdcValue(): %i %lf (%lu) %i", adcId, ts_local, (u_int64_t)ts, value);
  128. if (c->ts != ts_local*POINTSPERSEC) {
  129. point_t *p = &this->ADCData[adcId][c->pointId++];
  130. p->x = ts_local;
  131. p->y = c->avg;
  132. //qDebug("pushAdcValue(): new point: %lu: %f %u", (u_int64_t)c->pointId, p->x, p->y);
  133. if (c->pointId > ADCDATALEN) c->pointId = 0;
  134. c->times = 0;
  135. c->avg = 65535;
  136. c->ts = ts_local*POINTSPERSEC;
  137. }
  138. c->avg = (c->avg * c->times + value) / (c->times+1);
  139. c->times++;
  140. return;
  141. }
  142. int MainWindow::fillPoints(QPolygonF &points, point_t *data, int startPointId, int endPointId, int skipBeforeTs)
  143. {
  144. int i = startPointId;
  145. float skipBeforeTsFloat = (float)skipBeforeTs / POINTSPERSEC;
  146. float oldX = -1;
  147. while (i < endPointId) {
  148. float x = data[i].x;
  149. u_int16_t y = data[i].y;
  150. i++;
  151. if (y > 4096)
  152. continue;
  153. if (x < oldX)
  154. break;
  155. if (x <= skipBeforeTsFloat) {
  156. //qDebug("x <= skipBeforeTsFloat: %f %f", x, skipBeforeTsFloat);
  157. continue;
  158. }
  159. oldX=x;
  160. points << QPointF(x, y);
  161. }
  162. return i;
  163. }
  164. qint64 MainWindow::drawOldCurve(int adcId)
  165. {
  166. QPolygonF points;
  167. int i = this->fillPoints(points, this->ADCData[adcId], (int)this->ADCCurPoint[adcId].pointId, ADCDATALEN, (int)this->ADCCurPoint[adcId].ts);
  168. if (i >= ADCDATALEN)
  169. i = this->fillPoints(points, this->ADCData[adcId], 0, (int)this->ADCCurPoint[adcId].pointId, (int)this->ADCCurPoint[adcId].ts);
  170. if (i != this->ADCCurPoint[adcId].pointId) {
  171. this->ADCCurve[adcId][0].setSamples(points);
  172. this->getPlotByAdcId(adcId)->replot();
  173. } else i = 0;
  174. //qDebug("drawOldCurve(%i): pointId == %lu; i == %i", adcId, (u_int64_t)this->ADCCurPoint[adcId].pointId, i);
  175. return i;
  176. }
  177. void MainWindow::drawNewCurve(int adcId, qint64 startPointId)
  178. {
  179. QPolygonF points;
  180. //qDebug("drawNewCurve(%i, %lu)", adcId, (u_int64_t)startPointId);
  181. if (this->ADCCurPoint[adcId].pointId < startPointId)
  182. this->fillPoints(points, this->ADCData[adcId], startPointId, ADCDATALEN, 0);
  183. this->fillPoints(points, this->ADCData[adcId], startPointId, (int)this->ADCCurPoint[adcId].pointId, 0);
  184. this->ADCCurve[adcId][1].setSamples(points);
  185. this->getPlotByAdcId(adcId)->replot();
  186. }
  187. void MainWindow::redrawGraphics()
  188. {
  189. //qDebug("redrawGraphics()");
  190. int i = 0;
  191. while (i < ADCS) {
  192. this->drawNewCurve(i, this->drawOldCurve(i));
  193. i++;
  194. }
  195. return;
  196. }
  197. void MainWindow::recvData()
  198. {
  199. if (!remote->canReadLine())
  200. return;
  201. QByteArray data = remote->readLine();
  202. QString string = QTextCodec::codecForMib(106)->toUnicode(data);
  203. QRegExp rx("[ ]+");
  204. QStringList arguments = string.split(rx);
  205. qDebug("received data (%i: %s): %s", arguments.size(), arguments.at(0).toStdString().c_str(), string.toStdString().c_str());
  206. if(arguments.size() < 6)
  207. return;
  208. this->curState.m[0].direction = arguments.at(0).at(0).toLatin1();
  209. this->curState.m[0].speed = arguments.at(1).toInt();
  210. this->curState.m[1].direction = arguments.at(2).at(0).toLatin1();
  211. this->curState.m[1].speed = arguments.at(3).toInt();
  212. this->curState.adc[0].value = arguments.at(4).toInt();
  213. this->curState.adc[1].value = arguments.at(5).toInt();
  214. int i = 0;
  215. while (i < MOTORS) {
  216. if (memcmp(&this->curState.m[i], &this->desiredState.m[i], sizeof(this->curState.m[i]))) {
  217. //qDebug("motor %i differs: %c ? %c; %i ? %i", i, this->curState.m[i].direction, this->desiredState.m[i].direction, this->curState.m[i].speed, this->desiredState.m[i].speed);
  218. this->sendDesiredState(i);
  219. }
  220. i++;
  221. }
  222. QDateTime curDateTime = QDateTime::currentDateTime();
  223. qint64 ts = curDateTime.currentMSecsSinceEpoch();
  224. this->pushAdcValue(0, ts, this->curState.adc[0].value);
  225. this->pushAdcValue(1, ts, this->curState.adc[1].value);
  226. this->showCurState();
  227. this->redrawGraphics();
  228. return;
  229. }
  230. void MainWindow::on_resize_centralWidget(QResizeEvent *event) {
  231. qDebug("centralWidget Resized (New Size) - Width: %d Height: %d (was: %d x %d)",
  232. event->size().width(),
  233. event->size().height(),
  234. event->oldSize().width(),
  235. event->oldSize().height()
  236. );
  237. this->ui->graphicsLayout->setGeometry(QRect(0, 0, event->size().width()-105, event->size().height()-20));
  238. this->ui->infoLayout->setGeometry(QRect(event->size().width()-100, 0, 100, event->size().height()-20));
  239. //this->ui->statusBar->setGeometry(0, event->size().height()-20, event->size().width(), 20);
  240. this->redrawGraphics();
  241. return;
  242. }
  243. void MainWindow::on_resize_toolsWidget(QResizeEvent *event) {
  244. qDebug("toolsWidget Resized (New Size) - Width: %d Height: %d (was: %d x %d)",
  245. event->size().width(),
  246. event->size().height(),
  247. event->oldSize().width(),
  248. event->oldSize().height()
  249. );
  250. this->ui->toolsLayout->setGeometry(QRect(0, 0, event->size().width()-40, event->size().height()));
  251. return;
  252. }
  253. void MainWindow::on_resize_plot(QResizeEvent *event, int adcId, QwtPlot *p)
  254. {
  255. QSize centerWidgetSize = this->ui->centralWidget->size();
  256. /*qDebug("plot %i Resized (New Size) - Width: %d Height: %d (was: %d x %d); newY: %u", adcId,
  257. event->size().width(),
  258. event->size().height(),
  259. event->oldSize().width(),
  260. event->oldSize().height(),
  261. (centerWidgetSize.height() * (adcId))/ADCS
  262. );*/
  263. this->ui->graphicsLayout->setGeometry(QRect(0, 0, centerWidgetSize.width()-105, centerWidgetSize.height()-20));
  264. p->setGeometry(0, (centerWidgetSize.height() * (adcId))/ADCS, centerWidgetSize.width()-105, centerWidgetSize.height()/ADCS);
  265. return;
  266. }
  267. bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
  268. if (event->type() == QEvent::Resize) {
  269. Ui::MainWindow *ui = this->ui;
  270. if (obj == ui->centralWidget)
  271. this->on_resize_centralWidget(static_cast<QResizeEvent*>(event));
  272. else
  273. if (obj == ui->toolsWidget)
  274. this->on_resize_toolsWidget (static_cast<QResizeEvent*>(event));
  275. else {
  276. int adcId = 0;
  277. while (adcId < ADCS) {
  278. QwtPlot *p = this->getPlotByAdcId(adcId);
  279. if (obj == p) {
  280. this->on_resize_plot(static_cast<QResizeEvent*>(event), adcId, p);
  281. break;
  282. }
  283. adcId++;
  284. }
  285. }
  286. }
  287. return QWidget::eventFilter(obj, event);
  288. }
  289. void MainWindow::sendDesiredState(int motorId)
  290. {
  291. motor_t *m = &this->desiredState.m[motorId];
  292. QString sendStr = "H"+QString::number(motorId+1)+ m->direction +" "+QString::number(m->speed)+"\r\n";
  293. this->remote->write(sendStr.toUtf8());
  294. //qDebug("sending: %s", sendStr.toStdString().c_str());
  295. }
  296. void MainWindow::on_speedM0Slider_valueChanged(int value)
  297. {
  298. this->desiredState.m[0].speed = sqrt(209-value+0.1);
  299. this->sendDesiredState(0);
  300. }
  301. void MainWindow::on_speedM1Slider_valueChanged(int value)
  302. {
  303. this->desiredState.m[1].speed = sqrt(209-value+0.1);
  304. this->sendDesiredState(0);
  305. }
  306. void MainWindow::on_downM0Radio_toggled(bool checked)
  307. {
  308. if (checked)
  309. this->desiredState.m[0].direction = M_DOWN;
  310. this->sendDesiredState(0);
  311. }
  312. void MainWindow::on_stopM0Radio_toggled(bool checked)
  313. {
  314. if (checked)
  315. this->desiredState.m[0].direction = M_STOP;
  316. this->sendDesiredState(0);
  317. }
  318. void MainWindow::on_upM0Radio_toggled(bool checked)
  319. {
  320. if (checked)
  321. this->desiredState.m[0].direction = M_UP;
  322. this->sendDesiredState(1);
  323. }
  324. void MainWindow::on_downM1Radio_toggled(bool checked)
  325. {
  326. if (checked)
  327. this->desiredState.m[1].direction = M_DOWN;
  328. this->sendDesiredState(1);
  329. }
  330. void MainWindow::on_stopM1Radio_toggled(bool checked)
  331. {
  332. if (checked)
  333. this->desiredState.m[1].direction = M_STOP;
  334. this->sendDesiredState(1);
  335. }
  336. void MainWindow::on_upM1Radio_toggled(bool checked)
  337. {
  338. if (checked)
  339. this->desiredState.m[1].direction = M_UP;
  340. this->sendDesiredState(1);
  341. }