2016-04-05 4 views
1

Я написал простую программу для использования Qt (версия 5.5, построенная из исходного кода для Visual Studio 2013, следующего за this guide), чтобы познакомиться с Arduino.Ошибка QSerial, связанная с Arduino

Вот простая прошивка, которая считывается из сериала и через 10 секунд выводит «1» назад:

void setup() { 
    Serial.begin(9600); //Open Serial connection for debugging 
} 

void loop() { 
if (Serial.available()) { 
    char user_input = Serial.read(); 
    if (user_input == '1') { 
     delay(10000); 
     Serial.print('1'); 
    } 
} 

Вот программа Qt, посылающие «1» на последовательный, когда я нажимаю кнопку запуска и продолжает прослушивание сообщений следующего содержания:

main.cpp

#include "mainwindow.h" 
#include <QApplication> 

#pragma comment(lib, "advapi32") 

int main(int argc, char *argv[]) { 
    QApplication a(argc, argv); 
    MainWindow w; 
    w.show(); 
    return a.exec(); 
} 

mainwindow.h

#pragma once 

#include <QMainWindow> 
#include "SerialHandler.h" 

namespace Ui { 
    class MainWindow; 
} 

class MainWindow : public QMainWindow { 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private: 
    Ui::MainWindow* ui; 
    SerialHandler serialHandler; 
public slots: 
    void onStart(); 
}; 

mainwindow.cpp

#include "mainwindow.h" 
#include "ui_mainwindow.h" 

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::MainWindow), serialHandler(QString("COM6")) { 
    ui->setupUi(this); 
    QObject::connect(ui->startButton, SIGNAL(released()), this, SLOT(onStart())); 
} 

MainWindow::~MainWindow() { 
    delete ui; 
} 

void MainWindow::onStart() { 
    serialHandler.moveForward(); 
} 

SerialHandler.h

#pragma once 

#include <QString> 
#include <QtSerialPort> 
#include <QtSerialPort/QSerialPort> 


class SerialHandler { 
public: 
    SerialHandler(QString& serialName); 
    ~SerialHandler(); 
    void moveForward(); 

private: 
    QSerialPort serial; 
    void writeOnSerial(QByteArray& msg); 

private slots: 
    void handleReadyRead(); 
}; 

SerialHandler.cpp

#include "SerialHandler.h" 
#include <QDebug> 
#include <QObject> 


SerialHandler::SerialHandler(QString& serialName){ 
    connect(&serial, SIGNAL(readyRead()), this, SLOT(handleReadyRead())); 

    // Initialize Serial 
    serial.setPortName(serialName); 

    if (!serial.setBaudRate(QSerialPort::Baud9600)) { 
     throw std::runtime_error(QObject::tr("Can't set rate 9600 baud to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.open(QIODevice::ReadWrite)) { 
     throw std::runtime_error(QObject::tr("Can't open %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setDataBits(QSerialPort::Data8)) { 
     throw std::runtime_error(QObject::tr("Can't set 8 data bits to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setParity(QSerialPort::NoParity)) { 
     throw std::runtime_error(QObject::tr("Can't set no patity to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setStopBits(QSerialPort::OneStop)) { 
     throw std::runtime_error(QObject::tr("Can't set 1 stop bit to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { 
     throw std::runtime_error(QObject::tr("Can't set no flow control to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 
} 

SerialHandler::~SerialHandler(){ 
    if (serial.isOpen()) { 
     serial.close(); 
    } 
} 

void SerialHandler::handleReadyRead() { 
    qDebug() << serial.readAll(); 
} 

void SerialHandler::writeOnSerial(QByteArray& msg) { 
    if (serial.isOpen() && serial.isWritable()) { 
     serial.write(msg); 
     serial.flush(); 
    } 
} 

void SerialHandler::moveForward(){ 
    QByteArray msg("1"); 
    writeOnSerial(msg); 
} 

проблема возникает в методе writeOnSerial (SerialHandler.cpp). Вызов serial.write() запускает эту ошибку:

QObject::startTimer: Timers can only be used with threads started with QThread 

«1» записывается на последовательный и читать по Arduino, но компьютер не получает ничего обратно через 10 секунд, сигнал, который readyRead() является никогда не стреляли!

Я видел ту же ошибку в this post, но в моем случае цикл exec существует!

Любые предложения?

+0

Я думаю, что ваша сборка также наполовину сломана: вы не должны включать '', ни является '#pragma комментарий (Пб "advapi32")' необходимо. Просто добавьте '' (* или * '', но не оба!). Если это не сработает, в файле '.pro' отсутствует строка' QT + = serialport' (и/или вы не запустили qmake). –

+1

Обратите внимание, что если вы установите параметры порта перед его открытием, все методы вернут «истину» по дизайну. Настройки будут установлены при открытии порта, и если они не удастся, 'open' завершится с ошибкой и вернет false. Этого вполне достаточно, чтобы обнаруживать сбои, это не имеет значения точно * где * это не удалось - рабочий порт не подведет, возможно, умирающее устройство, но локус неудач будет бесполезным. Это также избавляет от нескольких переводимых строк, так что меньше нагрузки на ваших переводчиков. –

ответ

1

Этот минимальный тестовый кейс работает для меня на Arduino как на Windows, так и на OS X, используя последний Qt 5.5.

Этот вид минимизации является тем, что относится к вашему вопросу. Для демонстрации таких простых сбоев нет необходимости в нескольких файлах (и отсутствующих .ui).

// https://github.com/KubaO/stackoverflown/tree/master/questions/miniserial-36431493 
#include <QtWidgets> 
#include <QtSerialPort> 

int main(int argc, char ** argv) { 
    QApplication app(argc, argv); 
    QWidget w; 
    QFormLayout layout(&w); 
    QPushButton ping("Send"); 
    QTextBrowser output; 
    layout.addRow(&ping); 
    layout.addRow(&output); 
    w.show(); 

    QSerialPort port("COM6"); 
    port.setBaudRate(QSerialPort::Baud9600); // these are guaranteed to return true 
    port.setDataBits(QSerialPort::Data8); 
    port.setParity(QSerialPort::NoParity); 
    port.setStopBits(QSerialPort::OneStop); 
    port.setFlowControl(QSerialPort::NoFlowControl); 
    if (!port.open(QIODevice::ReadWrite)) 
     output.append("! Can't open the port :(<br/>"); 

    QObject::connect(&ping, &QPushButton::clicked, &port, [&]{ 
     if (port.isOpen()) { 
     port.write("1"); 
     output.append("> 1<br/>"); 
     } else 
     output.append("! Write failed :(<br/>"); 
    }); 
    QObject::connect(&port, &QIODevice::readyRead, &output, [&]{ 
     auto data = port.readAll(); 
     output.append(QStringLiteral("< %1<br/>") 
        .arg(QString::fromLatin1(data).toHtmlEscaped())); 
    }); 

    return app.exec(); 
} 
+0

Благодарим за ответ! Завтра утром я проверю это, и я постараюсь выяснить, что я сделал не так! – Jiloc

+0

Как вы сказали в комментариях к моему вопросу, у меня были проблемы со сборкой. Я переключился на qtCreator, и все работало безупречно, спасибо за вашу помощь! – Jiloc