2016-10-25 48 views
1

ArduinoとC++ Qt5.7(MinGW)プログラムとの間でデータをやり取りしようとしています。双方向シリアル通信bethween ArduinoとQt 5.7

FRT QT TO ARDUINOから問題なくデータを転送することができます。 Arduinoは完全に点滅します。

一方、ARDUINOからQTに転送されたデータは常に期待されていません(「LED OFF」にする必要がある場合は「LED ON」を送信します)。

QTコード:

#include <QCoreApplication> 
#include <QDebug> 

#include <QSerialPort> 
#include <QSerialPortInfo> 
#include <QThread> 

#include <iostream> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    QSerialPort serial; 
    serial.setPortName("COM6"); 
    serial.setBaudRate(9600); 
    serial.setDataBits(QSerialPort::Data8); 
    serial.setParity(QSerialPort::NoParity); 
    serial.setStopBits(QSerialPort::OneStop); 
    serial.setFlowControl(QSerialPort::NoFlowControl); 

    if(serial.open(QSerialPort::ReadWrite)) 
    { 
     string c; 
     QByteArray s; 
     QByteArray received; 
     while(true) 
     { 
      qDebug("TRUE"); 
      //WRITE 
      cin >> c; 
      cout << endl; 
      s = QByteArray::fromStdString(c); 
      serial.write(s); 
      serial.waitForBytesWritten(-1); 

      //serial.flush(); 

      s = serial.readAll(); 
      serial.waitForReadyRead(-1); 
      cout << s.toStdString() << endl; 

      //serial.flush(); 
     } 
    } 
    else 
    { 
     QString error = serial.errorString(); 
     cout << error.toStdString() << endl; 
     qDebug("FALSE") ; 
    } 


    serial.close(); 

    return a.exec(); 
} 

のArduino CODE:エラーの

void setup() { 
    // initialize digital pin LED_BUILTIN as an output. 
    pinMode(LED_BUILTIN, OUTPUT); 

    Serial.begin(9600); 
} 

// the loop function runs over and over again forever 
void loop() { 
    delay(1000); // wait for a second 
} 

void serialEvent() 
{ 
    char inChar; 
    while (Serial.available()) 
    { 
    // get the new byte: 
    inChar = (char)Serial.read(); 
    if(inChar == 'a') 
    { 
     digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) 
    } 
    else 
    { 
     digitalWrite(LED_BUILTIN, LOW); // turn the LED off (LOW is the voltage level) 
    } 
    } 
    delay(500); 
    if(inChar == 'a') 
    { 
     Serial.write("LED ON"); 
    } 
    else 
    { 
     Serial.write("LED OFF"); 
    } 
} 

ターミナル画像:

TERMINAL WITH ERROR image

助けてください! ありがとう、

+0

はあなたの問題を再現するための完全かつ最小限のコードを提供していただきありがとうございます。スタックオーバーフローへようこそ! –

答えて

1

パケット化は一切ありません。時間の経過を除いて、データの個々のチャンク間に区切り文字はありません。 Arudino側で

  1. 、代わりにwriteの各メッセージは完全なラインになるように、あなたはprintlnを使用する必要があります。

  2. Qt側では、完全な行を処理します。 waitForReadyReadの後にシリアルポートから完全な応答を得ることは保証されません。保証されるのは、少なくとも1バイトが読み込めるということです。それがあなたの問題の原因です。あなたはLEをどうやって入手したのかをご確認の上、D OFFの直後にLED ONが続きます。完全な行が利用可能になるまでデータを待つ必要があります。

することは、物事のQtの側で動作するはずです以下 - また、あなたができるだけ多く含まれる必要はありませんし、あなたが使用するAPIの数を下げるために、代わりのiostreamのQTextStreamを使用できることに注意してください。最後に、ブロックコードを記述するので、app.execは必要ありません。

// https://github.com/KubaO/stackoverflown/tree/master/questions/arduino-read-40246601 
#include <QtSerialPort> 
#include <cstdio> 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a{argc, argv}; 
    QTextStream in{stdin}; 
    QTextStream out{stdout}; 

    QSerialPort port; 
    port.setPortName("COM6"); 
    port.setBaudRate(9600); 
    port.setDataBits(QSerialPort::Data8); 
    port.setParity(QSerialPort::NoParity); 
    port.setStopBits(QSerialPort::OneStop); 
    port.setFlowControl(QSerialPort::NoFlowControl); 

    if (!port.open(QSerialPort::ReadWrite)) { 
     out << "Error opening serial port: " << port.errorString() << endl; 
     return 1; 
    } 

    while(true) 
    { 
     out << "> "; 
     auto cmd = in.readLine().toLatin1(); 
     if (cmd.length() < 1) 
      continue; 

     port.write(cmd); 

     while (!port.canReadLine()) 
      port.waitForReadyRead(-1); 

     while (port.canReadLine()) 
      out << "< " << port.readLine(); // lines are already terminated 
    } 
} 

ご希望の場合は、あなたも簡単にそれはそうするだけの数行ですが、GUIアプリケーションにそれを回すことができます。

#include <QtSerialPort> 
#include <QtWidgets> 

int main(int argc, char *argv[]) 
{ 
    QApplication app{argc, argv}; 
    QWidget ui; 
    QFormLayout layout{&ui}; 
    QLineEdit portName{"COM6"}; 
    QTextBrowser term; 
    QLineEdit command; 
    QPushButton open{"Open"}; 
    layout.addRow("Port", &portName); 
    layout.addRow(&term); 
    layout.addRow("Command:", &command); 
    layout.addRow(&open); 
    ui.show(); 

    QSerialPort port; 
    port.setBaudRate(9600); 
    port.setDataBits(QSerialPort::Data8); 
    port.setParity(QSerialPort::NoParity); 
    port.setStopBits(QSerialPort::OneStop); 
    port.setFlowControl(QSerialPort::NoFlowControl); 

    QObject::connect(&open, &QPushButton::clicked, &port, [&]{ 
     port.setPortName(portName.text()); 
     if (port.open(QSerialPort::ReadWrite)) return; 
     term.append(QStringLiteral("* Error opening serial port: %1").arg(port.errorString())); 
    }); 

    QObject::connect(&command, &QLineEdit::returnPressed, &port, [&]{ 
     term.append(QStringLiteral("> %1").arg(command.text())); 
     port.write(command.text().toLatin1()); 
    }); 

    QObject::connect(&port, &QIODevice::readyRead, &term, [&]{ 
     if (!port.canReadLine()) return; 
     while (port.canReadLine()) 
      term.append(QStringLiteral("< %1").arg(QString::fromLatin1(port.readLine()))); 
    }); 
    return app.exec(); 
} 
0

QTにEOLとCarrigeのリターン文字を使用する必要があると思います。 ArduinoコードでSerial.writeSerial.printlnに置き換えてみてください。

関連する問題