QSerialProt 클래스를 사용하여 Qt와 Arduino에서 직렬 통신

12306 단어 QtArduino

배경



Arduino에서 직렬로 전송 된 데이터를 Qt를 사용하여 처리하려는 경우
어떻게 해야할지 조사했기 때문에 떠납니다.
매번 조사하면 좋지만, 예를 들어 Qt의 정보는 영어뿐입니다.
매번 영어를 읽는 것은 일본어보다 피곤하고 시간이 걸리므로,
잊지 말고 일본어로 남겨 둡니다.

환경



Qt 5.9.1

코드



주로 여기여기 를 참고로 했습니다.
시리얼 통신으로 취득한 문자열을 텍스트 편집 영역에 추가합니다.

mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , _serialPort( new QSerialPort( this ) )
{
    ui->setupUi(this);

    // ここで取得した情報一覧をメニューとかコンボボックスとかに登録できる
    foreach( const QSerialPortInfo info, QSerialPortInfo::availablePorts() )
    {
        qDebug() << "Name        :" << info.portName();
        qDebug() << "Description :" << info.description();
        qDebug() << "Manufacturer:" << info.manufacturer() << "\n";
    }

    // でも今回は直書きする
    // portName: デバイスマネージャで確認する
    _serialPort->setPortName( QString( "COM4" ) );

    // baudRate,dataBits,parity,stopBits:
    // Arduinoのスケッチで指定したものと同じ数値を指定する
    _serialPort->setBaudRate( QSerialPort::Baud115200 );
    // ちなみに以下はArduinoのスケッチでSerial.beginの第2引数を省略した時の値
    _serialPort->setDataBits( QSerialPort::Data8 );
    _serialPort->setParity(   QSerialPort::NoParity );
    _serialPort->setStopBits( QSerialPort::OneStop );

    if ( _serialPort->open( QIODevice::ReadOnly ) )
    {
        connect( _serialPort, &QSerialPort::readyRead,
                 this,        &MainWindow::printData );
    }
    else
    {
        qDebug() << "Couldn't open the port [COM4].";
    }
}

MainWindow::~MainWindow()
{
    _serialPort->close();
    disconnect( _serialPort, &QSerialPort::readyRead,
                this,        &MainWindow::printData );
    delete _serialPort;
    delete ui;
}

void MainWindow::printData()
{
    if ( sender() == _serialPort )
    {
        QString data = QString( _serialPort->readAll() );
        ui->textEdit->append( data );
    }
}


Arduino의 스케치는 여기.
전압을 읽고 출력하기만 하면 됩니다.

voltage.ino
#define GET_VOLTAGE()  analogRead( A0 ) * 5.0 / 1024

float _voltage;

void setup()
{
    _voltage = 0.0;
    Serial.begin( 115200 );
    // Serial.begin( 11520, SERIAL_8N1 );と同じ
    // SERIAL_7E2(データ7ビット,偶数パリティ,ストップビット2ビット)とか
    // SERIAL_8O1(データ8ビット,奇数パリティ,ストップビット1ビット)とかがある。
}

void loop()
{
    _voltage = GET_VOLTAGE();
    Serial.print( "voltage : " );
    Serial.println( _voltage );
    delay( 1000 );
}

놀랐다.





가끔 개행이 잘 되지 않는 부분이 있습니다. 받은 쪽의 데이터 처리가 나쁜 것일까요?
어쨌든, 일단 통신은 할 수 있었습니다.

(2017/09/12 추가)
분명히 슬롯을 처리하는 방법이 나쁜 것 같습니다.
readyRead() 시그널은, 송신측의 1회의 커멘드에 상당하는 것은 아니다고 하고, 1회분의 송신 데이터의 도중까지 밖에 취득할 수 없어도 통지되는 것만 싶습니다.
이것에 대응한 것이 이하.

mainwindow.cpp
void MainWindow::printData()
{
    if ( sender() == _serialPort )
    {
        // とりあえずメンバのバッファにためる
        _buffer.append( _serialPort->readAll() );
        if ( _buffer.contains( "\r\n" ) )
        {

            // ArduinoのSerial.println()は末尾に<CR><LF>が付加される
            // 区切り文字が含まれてたら表示してバッファクリア        
            QString data = QString( _buffer );
            ui->textEdit->append( data );
            _buffer.clear();
        }
    }
}




하지만 이것이라면 문중에 가 있을 때 수정이 필요하게 되는구나.
EOL을 무엇으로 할 것인가를 미리 송신측으로 결정해 두면 좋은 것일까.

기타



readyRead() 시그널을 핸들한다고, QIODevice를 사용할 때의 상구입니다.
QFile 밖에 사용한 적이 없기 때문에 공부가 되었습니다.

전송은 또 이번

(끝)

좋은 웹페이지 즐겨찾기