Results 1 to 13 of 13

Thread: QSerialPort and QThread

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Apr 2017
    Posts
    30
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    9

    Default QSerialPort and QThread

    Hi all!

    I have a small project:

    mainwindow.cpp
    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6.  
    7. ComPort::get().open();
    8.  
    9. thread = new QThread(this);
    10. connect(this, SIGNAL(destroyed(QObject*)), thread, SLOT(quit()));
    11.  
    12. valve = new Valve(7);
    13. connect(valve, SIGNAL(remoteStatus(bool)), this, SLOT(remoteStatus(bool)));
    14.  
    15. valve->moveToThread(thread);
    16.  
    17.  
    18. QTimer *valvesReadTimer = new QTimer(this);
    19. connect(valvesReadTimer, SIGNAL(timeout()), valve, SLOT(getAllStates()));
    20. valvesReadTimer->start(1000);
    21.  
    22. connect(passform, SIGNAL(manualModeEmit(bool)),
    23. this, SLOT(manualMode(bool)));
    24.  
    25.  
    26. emergency = new EmergencyResetOfPressure();
    27. connect(emergency, SIGNAL(openValveSignal(int)), this, SLOT(openValve(int)));
    28. connect(emergency, SIGNAL(closeValveSignal(int)), this, SLOT(closeValve(int)));
    29. //emergency->start();
    30. emergency->moveToThread(emergency);
    31. emergency->start();
    32. thread->start();
    33.  
    34. initActionConnection();
    35.  
    36. }
    37.  
    38. MainWindow::~MainWindow()
    39. {
    40. delete ui;
    41. }
    42.  
    43. void MainWindow::valveSwitch(int id) //переключатель клапанов
    44. {
    45. if (valve->getState(id))
    46. closeValve(id);
    47. else
    48. openValve(id);
    49. }
    50.  
    51. void MainWindow::openValve(int id)
    52. {
    53. QString str = "Клапан №" + QString::number(id+1);
    54. valveButton[id]->setEnabled(false);
    55. if (valve->open(id)) {
    56. if (manualModeState)
    57. valveButton[id]->setEnabled(true);
    58. //valveButton[id]->setPalette(QPalette(Qt::green));
    59. //valveButton[id]->setStyleSheet(VALVE_OPEN_COLOR);
    60. QString style = QString(DEFAULT_STYLE_BUTTON) + QString(DEFAULT_BACKGROUND_BUTTON);
    61. valveButton[id]->setStyleSheet(style);
    62. ui->mainLabel->setText(str + " открыл! :)");
    63. }
    64. else {
    65. if (manualModeState)
    66. valveButton[id]->setEnabled(true);
    67. ui->mainLabel->setText("Не могу открыть " + str);
    68. remoteStatus(0);
    69. }
    70. }
    71. void MainWindow::closeValve(int id)
    72. {
    73. QString str = "Клапан №" + QString::number(id+1);
    74. valveButton[id]->setEnabled(false);
    75. if (valve->close(id)) {
    76. if (manualModeState)
    77. valveButton[id]->setEnabled(true);
    78. //valveButton[id]->setPalette(style()->standardPalette());
    79. valveButton[id]->setStyleSheet("");
    80. ui->mainLabel->setText(str + " закрыл! :)");
    81. }
    82. else {
    83. if (manualModeState)
    84. valveButton[id]->setEnabled(true);
    85. ui->mainLabel->setText("Не могу закрыть " + str);
    86. remoteStatus(0);
    87. }
    88. }
    89.  
    90. void MainWindow::pressureDrop() //Испытание по методу "Спад давления"
    91. {
    92. emergency->begin();
    93.  
    94. ui->mainLabel->setText("Испытание по методу \n Спад давления");
    95. }
    96.  
    97.  
    98. void MainWindow::initActionConnection()
    99. {
    100. //обработка нажатий на кнопки клапанов
    101. QSignalMapper* signalMapper = new QSignalMapper (this); //чтобы можно было обработать ф-ю с аргументом в Слоте
    102. for(int i = 0; i < 7; i++)
    103. signalMapper->setMapping(valveButton[i], i);
    104. for(int i = 0; i < 7; i++)
    105. connect(valveButton[i], SIGNAL(clicked()), signalMapper, SLOT(map()));
    106. connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(valveSwitch(int)));
    107.  
    108.  
    109. connect(ui->pressureTestButton, SIGNAL(clicked(bool)), this, SLOT(pressureDrop())); //опрессовка и испытание на прочность
    110.  
    111. }
    112.  
    113.  
    114. EmergencyResetOfPressure::EmergencyResetOfPressure(QObject *parent) : QThread(parent)
    115. {
    116.  
    117. }
    118.  
    119. EmergencyResetOfPressure::~EmergencyResetOfPressure()
    120. {
    121.  
    122. }
    123.  
    124. void EmergencyResetOfPressure::begin()
    125. {
    126. for (int i = 0; i<7; i++)
    127. {
    128. //sleep(1);
    129. emit openValveSignal(i);
    130. }
    131. for (int i = 0; i<7; i++)
    132. {
    133. //sleep(1);
    134. emit closeValveSignal(i);
    135. }
    136. }
    To copy to clipboard, switch view to plain text mode 

    File for working with valves and port (singleton class)
    Qt Code:
    1. class ComPort : public QObject { //класс синглтон
    2. Q_OBJECT
    3. private:
    4. QString portName;
    5. QSerialPort *serial;
    6. explicit ComPort(QObject *parent = 0);
    7. ~ComPort();
    8.  
    9. //защита от копирования
    10. ComPort(ComPort const&) = delete;
    11. ComPort& operator= (ComPort const&) = delete;
    12.  
    13. int timeoutCount = 0;
    14. int responseCount = 0;
    15.  
    16. public:
    17. QByteArray buffer;
    18. static ComPort& get()
    19. {
    20. static ComPort instance;
    21. return instance;
    22. }
    23.  
    24. void open();
    25. void close();
    26. QByteArray requestResponse(const QByteArray &data);
    27. void write(const QByteArray &data);
    28. bool crcCheck(const QByteArray &data);
    29. private slots:
    30. void readData();
    31. void handleError(QSerialPort::SerialPortError error);
    32. };
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. Valve::Valve(int size, QObject *parent) : QObject(parent) //конструктор
    2. {
    3. valveState.resize(size);
    4. for(int i = 0; i < size; i++)
    5. {
    6. valveState[i] = false;
    7. }
    8. }
    9.  
    10. Valve::~Valve() //деструктор
    11. {
    12.  
    13. }
    14.  
    15. bool Valve::open(int id)
    16. {
    17. arr.resize(7);
    18. arr[0] = 0xAB;
    19. arr[1] = 0x01;
    20. arr[2] = 0x02;
    21. arr[3] = 0x02;
    22. arr[4] = id+1;
    23. arr[5] = 0xFF;
    24. arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
    25.  
    26. QByteArray response = ComPort::get().requestResponse(arr);
    27. if(response[0] == arr[0])
    28. {
    29. qDebug() << "клапан №: " << id+1 << " открыт!";
    30. valveState[id] = true;
    31.  
    32. emit remoteStatus(1);
    33. return 1;
    34. }
    35.  
    36. emit remoteStatus(0);
    37. return 0;
    38. }
    39.  
    40. bool Valve::close(int id)
    41. {
    42. arr.resize(7);
    43. arr[0] = 0xAB;
    44. arr[1] = 0x01;
    45. arr[2] = 0x02;
    46. arr[3] = 0x02;
    47. arr[4] = id+1;
    48. arr[5] = 0x00;
    49. arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
    50.  
    51. QByteArray response = ComPort::get().requestResponse(arr);
    52. if(response[0] == arr[0])
    53. {
    54. qDebug() << "клапан №: " << id+1 << " закрыт!";
    55. valveState[id] = false;
    56.  
    57. emit remoteStatus(1);
    58. return 1;
    59. }
    60.  
    61. emit remoteStatus(0);
    62. return 0;
    63. }
    64.  
    65. /*****************************************
    66.  * Класс для работы с COM портом
    67.  * **************************************/
    68.  
    69. ComPort::ComPort(QObject *parent) : QObject(parent)
    70. {
    71. buffer = "";
    72. serial = new QSerialPort();
    73. connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError)));
    74. }
    75. ComPort::~ComPort()
    76. {
    77.  
    78. }
    79.  
    80. void ComPort::open()
    81. {
    82. if(serial->isOpen())
    83. close();
    84. if(portName != Config::get().getValue("COM/name").toString())
    85. {
    86. qDebug() << "Порт " << portName << "сменился на " << Config::get().getValue("COM/name").toString();
    87. portName = Config::get().getValue("COM/name").toString();
    88. }
    89. serial->setPortName(portName);
    90. if (serial->open(QIODevice::ReadWrite)) {
    91. if (serial->setBaudRate(QSerialPort::Baud115200)
    92. && serial->setFlowControl(QSerialPort::NoFlowControl)) {
    93.  
    94. qDebug() << "Порт открыт";
    95.  
    96. } else {
    97. //QMessageBox::critical(this, "Error", serial->errorString());
    98. qDebug() << QString(serial->errorString());
    99. serial->close();
    100.  
    101. }
    102. } else {
    103. //QMessageBox::critical(this, QObject::tr("Error"), serial->errorString());
    104.  
    105. }
    106. }
    107. QByteArray ComPort::requestResponse(const QByteArray &data)
    108. {
    109. QByteArray readBuf;
    110. qDebug() << "-------------------------";
    111. int attempts = 1;
    112. while (attempts <= REQATTEMPTS) { //3 попытки
    113. if (serial->isWritable())
    114. {
    115. serial->write(data);
    116. qDebug() << "Попытка № " << attempts;
    117. qDebug() << "Запрос: " << data.toHex();
    118. while (serial->waitForReadyRead(WAITFORREADY)) {
    119. readBuf += serial->readAll();
    120. if (crcCheck(readBuf) && data[2] == readBuf[2] ){ //если CRC и команда сошлись -- успех!
    121. qDebug() << "Ответ: " << readBuf.toHex();
    122. responseCount++;
    123. qDebug() << "Кол-во запросов: " << responseCount;
    124. qDebug() << "Кол-во таймаутов: " << timeoutCount;
    125. float percent = timeoutCount * 100;
    126. percent = percent / responseCount;
    127. qDebug() << "Процент косяков: " << QString::number(percent, 'f', 3) << "%";
    128. close();
    129. open();
    130. return readBuf;
    131. }
    132. }
    133. readBuf.clear();
    134. qDebug() << "Таймаут...";
    135. timeoutCount++;
    136. close();
    137. open();
    138. attempts++;
    139. }
    140. else
    141. {
    142. qDebug() << "Порт " << portName << " не пишется!";
    143. return 0;
    144. }
    145.  
    146. }
    147. // close();
    148. // open();
    149. return 0;
    150. }
    151.  
    152. void ComPort::close()
    153. {
    154. serial->close();
    155. qDebug() << "Порт закрыт";
    156. }
    157. void ComPort::write(const QByteArray &data)
    158. {
    159. serial->write(data);
    160. qDebug() << "Запрос: " << data.toHex();
    161. }
    162. void ComPort::readData()
    163. {
    164. buffer = serial->readAll();
    165. if (ComPort::get().crcCheck(buffer))
    166. {
    167. qDebug() << "Ответ: " << buffer.toHex();
    168. qDebug() << "---------------------------";
    169. }
    170. }
    171. void ComPort::handleError(QSerialPort::SerialPortError error)
    172. {
    173. if (error == QSerialPort::ResourceError) {
    174. ComPort::get().close();
    175. qDebug() << "что-то не так!";
    176. }
    177. }
    To copy to clipboard, switch view to plain text mode 

    While working, I get an error:
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QSerialPort(0x197b7f8), parent's thread is QThread(0xc16e50), current thread is QThread(0x197c620)
    How can I get rid of this error?
    I hope for any help. Thanks!
    Last edited by maratk1n; 2nd May 2017 at 14:18.

Similar Threads

  1. QSerialPort
    By fmarques in forum Qt Programming
    Replies: 0
    Last Post: 20th April 2016, 17:04
  2. QserialPort
    By arturs in forum Newbie
    Replies: 0
    Last Post: 13th May 2015, 21:37
  3. Qserialport issue in QT4
    By coss_cat in forum Qt Programming
    Replies: 3
    Last Post: 11th December 2013, 19:11
  4. QSerialport in multithread
    By snow_starzz in forum Newbie
    Replies: 3
    Last Post: 3rd December 2013, 11:18
  5. Replies: 1
    Last Post: 4th October 2012, 15:49

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.