'Qt Designer'에 해당되는 글 2건

  1. 2018.03.03 UART(Serial) 통신 예제 2
  2. 2017.12.24 Qt 프로그램 소개
Software Programming/Qt2018. 3. 3. 02:38


AVR 시리즈의 칩을 사용하는 Arduino 보드와 STM32F 시리즈 칩을 사용하는 Nucleo 보드의 가장 큰 장점은, UART(Universal asynchronous receiver/transmitter) 통신을 이용하여 PC로부터 프로그래밍(업로드)과 디버깅이 가능하다는 것입니다. 이것이 가능한 이유는 USB를 경유한 UART 통신이 가능하도록 전용 칩을 별도로 보드에 내장하기 때문입니다.


따라서 Arduino와 Nucleo 보드에 작성한 임베디드(embedded) 프로그래밍과 소통하고 서로 데이터를 주고 받기 위해서는 PC 상에 인터페이스 프로그램이 필요하고, 이 간단한 Qt 프로그램은 Arduino나 Nucleo 보드와 UART(serial) 통신을 위한 예제입니다. 아이디어는 다음의 링크에서 참조하였습니다.

http://archive.fabacademy.org/2016/fablabhrw/students/162/week_16.html


mainwindow.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QDebug>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
public slots:
    void serial_connect();
    void serial_rescan();
    void widget_changed();
    void send_test();
    void serial_received();
 
private:
    Ui::MainWindow *ui;
};
 
#endif // MAINWINDOW_H
 
cs


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "mainwindow.h"
#include <QApplication>
#include <qlabel.h>
 
int main(int argc, char* argv[])
{
   QApplication a(argc, argv);
 
   MainWindow w;
//   w.setWindowTitle(QString::fromUtf8("Qt Serial communication"));
//   w.setFixedSize(300, 150);
   w.show();
 
   return a.exec();
}
 
cs


mainwindow.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qserialport.h>
#include <qserialportinfo.h>
#include <stdio.h>
 
QSerialPort *serial;
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
        ui->setupUi(this);
        ui->lcd_temp->setPalette(Qt::red);
        serial = new QSerialPort(this);
        connect(ui->rescan_Button, SIGNAL(clicked()), this, SLOT(serial_rescan()));
        connect(ui->connect_button, SIGNAL(clicked()), this, SLOT (serial_connect()));
        connect(ui->slider1, SIGNAL(valueChanged(int)), this, SLOT(widget_changed()));
        connect(ui->slider2, SIGNAL(valueChanged(int)), this, SLOT(widget_changed()));
        connect(ui->dial, SIGNAL(valueChanged(int)), this, SLOT(widget_changed()));
        connect(serial, SIGNAL(readyRead()), this, SLOT(serial_received()));
        serial_rescan();
}
 
MainWindow::~MainWindow()
{
    delete ui;
    serial->close();
}
 
void MainWindow::serial_connect()
{
        serial->setPortName(ui->port_box->currentText());
        serial->setBaudRate(QSerialPort::Baud115200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
//        serial->write("Hello World!\n");
 
        if(!serial->open(QIODevice::ReadWrite)){
            qDebug() << "Serial port open error";
        }
}
 
void MainWindow::serial_rescan()
{
    ui->port_box->clear();
    foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
        ui->port_box->addItem(serialPortInfo.portName());
    }
}
 
void MainWindow::widget_changed()
{
    QString buffer;
    buffer.sprintf("A%03i;%03i;%03i\n",ui->slider1->value(),ui->slider2->value(),ui->dial->value());
    qDebug() << buffer;
    serial->write( buffer.toStdString().c_str(), buffer.size());
    serial->QSerialPort::waitForBytesWritten(-1);
    ui->lcd_led1->display(ui->slider1->value());
    ui->lcd_led2->display(ui->slider2->value());
    ui->lcd_pwm->display(ui->dial->value());
}
 
void MainWindow::send_test()
{
    serial->write("test!\n");
}
 
 
void MainWindow::serial_received()
{
//    usleep(10000);
//    QString received = serial->readAll();
    QString received;
    while (serial->canReadLine()){
        received = serial->readLine();  //reads in data line by line, separated by \n or \r characters
    }
 
    QStringList splitted = received.split(";");
    if (splitted.value(0== "A"){
        ui->lcd_temp->display(splitted.value(1));
    }
}
 
cs


Qt 프로그램의 가장 큰 특징은 signal/slot 시스템입니다. 이는 오브젝트간 통신을 위해 사용되는데 예를 들어, GUI 프로그래밍에서 버튼을 눌렀을 때, 그 이벤트를 받아서 label에 텍스트를 출력한다거나 할 때에 사용됩니다. 이는 굳이 GUI가 없는 console 프로그래밍에서 비동기 호출이 필요한 pipe/socket/serial port 등에서도 유용하게 사용될 수 있습니다. 여기서 signal이란 Win32 프로그래밍에서 message 처리와 같은 개념입니다.


Qt의 signal/slot 시스템은 QObject를 상속받은 모든 class에서 사용할 수 있으며, 사용자에게 일관된 이벤트 인터페이스를 제공합니다. 사실 오브젝트간 통신에서 쓸 수 있는 가장 보편적인 방법으로 callback 또는 인터페이스가 존재하고 있지만, 첫째 함수를 처리할 때 정확한 매개변수 타입으로 호출하게 될 것인지 알 수 없다는 것으로 타입 안정성이 낮고, 둘째로 객체 지향 프로그램(Object Oriented Programming)을 지향하는 언어에서 흔히 쓰이는 인터페이스를 사용하는 방법은 오브젝트간에 강한 커플링으로 상호 참조가 생기거나 래퍼런스 카운팅에 문제가 생길 수 있습니다.


Qt는 이런 방식의 대안으로 타입 안정성을 갖고 있으며 이벤트를 발생시키는 오브젝트와 이벤트를 처리하는 핸들러 오브젝트간에 아무런 연관 관계가 없어, 서로 참조하지 않으면서도 사용이 가능하다는 것입니다.



위 그림에서와 같이 Qt에서 signal과 slot이라는 멤버 함수는 connect() 함수로 서로 연결되며, slot이 처리해야 할 signal을 감시하고 있다가 signal이 발생하면 slot 함수가 실행되게 됩니다. signal과 slot 함수는 1:1 연결 뿐만 아니라 1:N으로도 연결 가능합니다.


이 프로그램에서는 'mainwindow.h' 파일의 13번 라인에서 Q_OBJECT로 상속받았고 'mainwindow.cpp'의 16~21번 라인에서 다음과 같이 5개의 connect() 함수로써 signal과 slot 함수를 연결시켰습니다.


1
2
3
4
5
6
connect(ui->rescan_Button, SIGNAL(clicked()), this, SLOT(serial_rescan()));
connect(ui->connect_button, SIGNAL(clicked()), this, SLOT (serial_connect()));
connect(ui->slider1, SIGNAL(valueChanged(int)), this, SLOT(widget_changed()));
connect(ui->slider2, SIGNAL(valueChanged(int)), this, SLOT(widget_changed()));
connect(ui->dial, SIGNAL(valueChanged(int)), this, SLOT(widget_changed()));
connect(serial, SIGNAL(readyRead()), this, SLOT(serial_received()));
cs


1번 라인의 의미는 'rescan_Button'이 클릭(clicked())되어 signal이 발생하면 'serial_rescan()'이라는 slot 함수를 실행시킴을 의미하고, 3번 라인은 'slider1'이 값이 변동(valueChanged)하였다는 signal이 발생하면 'widget_change()'이라는 slot 함수를 실행시킴을 의미하고, 마지막으로 6번 라인에 'serial' 포트가 준비가 되었다(readyRead())는 signal이 발생하면 'serial_received()'이라는 slot 함수가 실행됨을 의미합니다.


다음은 예를 들어 push button의 경우에 발생할 수 있는 signal을 Qt Designer로 본 것입니다. 다만 모든 signal들이 Qt Designer에서 보여지지는 않으므로 라이브러리를 참고하시길 바랍니다.



serialport.pro

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#-------------------------------------------------
#
# Project created by QtCreator 2016-05-22T13:08:09
#
#-------------------------------------------------
 
QT       += core gui serialport
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
TARGET = serialport
TEMPLATE = app
 
 
SOURCES += main.cpp\
        mainwindow.cpp
 
HEADERS  += mainwindow.h
 
FORMS    += mainwindow.ui
 
cs


Qt Designer의 화면입입니다.


다음은 Qt로 작성한 serialport.exe의 실행화면입니다.


USB를 이용하여 PC와 연결하고자 하는 Nucleo 보드나 기타 보드와 송수신 데이터의 패킷 구성은 사용자가 임의로 정할 수 있습니다. 이 프로그램의 경우에는 송수신 데이터를 'A', ';' 그리고 '\n' 문자를 식별자로 구분하였습니다. 따라서 사용자는 해당 보드의 임베디드 프로그램에서 이와 같은 식별자를 이용하여 합니다.


Serialport.zip



'Software Programming > Qt' 카테고리의 다른 글

Hello world 예제  (0) 2018.03.02
Qt 프로그램 소개  (0) 2017.12.24
Posted by Nature & Life
Software Programming/Qt2017. 12. 24. 16:05


임베디드(Embedded) 시스템을 제어하거나 테스트하기 위한 프로그램 개발에는 여러 프로그램들이 사용되어질 수 있습니다. 예를 들어 Windows 환경에서 API나 MFC를 이용하여 개발한 경우, Linux와 같은 다른 환경에서 사용하기 위해서는 다시 그 환경에 맞는 툴을 사용하여 다시 제작하여야 합니다. 그러나 Qt는 cross platform으로 Unix, Linux 그리고 Windows, MAC OS X 등등 다양한 platform과 iOS나 Android 조차에서도 다시 컴파일하면 하면 된다는 것입니다.


역사적으로 Qt는 1995년 최초 버전이 공식 배포 되었고 이후 20년간 Qt는 산업 흐름에 맞추어 기능이 확장되고 성능이 개선되어 왔으며, 해당 기간 동안 전세계 1백만명이 넘는 개발자들에 의해서 검증된 안정적이고 성숙된 제품이 되었습니다. 현재 Qt 는 GUI 개발과 더불어 응용 프로그램 개발 전반을 커버하는 1,300여개의 풍부한 라이브러리들과 다양한 개발 도구를 갖춘 종합적인 개발 프레임워크 제품으로 완성되었다고 알려집니다.



기존의 개발 환경에서는 '볼륨' 버튼도 직접 제작하거나 별도의 라이브러리를 구입해야 하지만, Qt에서는 고급스러운 GUI 환경을 덕택에 가져다 쓰면 되고 상업적인 목적이 아닌 이상 소스 코드 채 배포되며 무료이면서 어떤 제한도 없다는 것입니다. 예를 들어, Qt만의 전통적이며 강력한 GUI 개발 기능은 Qt Widget으로부터 새롭게 지원되고 있는 Qt 자체의 GUI 개발용 스크립트 언어인 Qt Quick/QML로 이어졌고, QML을 이용하면 기존의 MFC 등의 개발 도구로는 구현이 매우 어려운 에니메이션이나 3D 인터페이스와 같은 자연스러운 그래픽 효과들도 쉽고 빠르게 구현할 수 있다는 것입니다.


뿐만 아니라, 프로그램 개발에 필수적인 멀티 스레드 프로세스 통신, 네트워크, OpenGL의 3D 그래픽, HTML5 지원 통합 웹엔진, XML 데이터베이스 등 C++ 개발자가 개발 중에 필요한 요구 사항도 다양한 라이브러리에 모듈형식으로 기능별로 제공한다는 것입니다. 또한 스마트폰과 태블릿 환경에서 요구되는 기존의 물리적 버튼과 원시적인 액정 스크린이 아닌 스마트폰과 같은 터치 패널 디스플레이 탑재와 고급스럽고 풍부한 표현을 가진 UI/HMI를 총망라 하고 있다는 것입니다.


Qt 에서는 'Qt Creator' 라는 통합 IDE 환경을 이용하여 코드를 작성하게 하며 GUI 화면을 직접 디자인하고 이를 개발코드와 직접 연결시킬 수 있는 'Qt Designer', GUI 개발을 편리하게 해주는 Qt 자체의 스크립트 언어인 'QML'과 UI 개발을 할 수 있는 'Qt Quick(Qt User Interface Creation Kit', Qt로 제작된 GUI 화면의 상세한 리소스 프로파일링이 가능한 'Qt Quick Profiler', Qt 라이브러리에 대한 상세한 도움말 문서인 'Qt Assistant'를 포함합니다. 또한 Visual Stuido나 Eclipse등 친숙한 개발 환경에서도 플러그인 하여 이용할 수도 있다는 것입니다.



Qt는 C++을 기반으로 하여 주로 C++을 사용하지만, 파이썬(Python), 루비(Ruby), C, 펄(Perl), 파스칼(Pascal)과도 연동됩니다. C 보다 C++을 사용할 경우 확장이 용이하다는 장점이 있습니다. 그러므로 클래스(class) 등의 C++의 기본 개념 지식이 먼저 요구됩니다.


https://www.qt.io/



'Software Programming > Qt' 카테고리의 다른 글

UART(Serial) 통신 예제  (2) 2018.03.03
Hello world 예제  (0) 2018.03.02
Posted by Nature & Life