'Software Programming/Qt'에 해당되는 글 3건

  1. 2018.03.03 UART(Serial) 통신 예제 2
  2. 2018.03.02 Hello world 예제
  3. 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/Qt2018. 3. 2. 21:01


Qt Creator를 실행합니다. 그리고 아래의 첫 화면에서 새로운 프로젝트를 생성하기 위해서 'New Project'를 클릭합니다.



그럼 아래의 화면이 나타나고 'Projects > Application'을 선택하고 그 중에서도 'Qt Widgets Application'을 선택하며 이를 적용하기 위해서 우측 하단의 'Choose' 버튼을 클릭합니다.



그럼 다음의 화면이 나타나고 여기서 프로젝트의 이름과 위치를 지정하고 우측 하단의 'Next' 버튼을 클릭합니다.



위 화면에서 (1)번인 'Name' 필드는 프로젝트 이름을 공백없이 기록하며, (2)번인 'Create in' 필드는 이 프로젝트가 저장될 위치를 지정하는 것으로 Qt가 설치된 예하 디렉토리를 설정할 경우, 차후에 Qt를 제거하였을 때 함께 삭제될 수 있으니 유지 관리를 위해서 사용자의 데이터 영역에 저장할 것을 권장합니다.


다음 화면은 'Kit Selection'으로 Helloworld 프로젝트에 사용될 Kit 정보를 보여줍니다. Kit 정보는 어떤 컴파일러를 사용할지 등에 대한 내용입니다. 확인하였으면 우측 하단에 'Next' 버튼을 클릭합니다. 여기서 MingGW 32bit를 볼 수 있는데 MingGW는 'Minimalist GNU for Windows'의 약자로 전통적인 Linux/Unix OS 환경 이외에도 Windows에서도 GNU 컴파일러 사용할 수 있도록 만든 툴입니다.


 

위 화면에서 아래 화면과 같이 'Details' 버튼을 클릭함으로서 추가적으로 세부적인 정보는 확인할 수 있습니다.



다음 화면은 Class 정보로서 생성될 메인 클라스 이름과 파일 이름을 지정하는 단계로서 여기서는 Qt의 네이밍 관례를 그대로 따르기 위해서 우측 하단의 'Next' 버튼을 클릭하여 다음 단계로 넘어갑니다.



다음 화면에서 (1)번 필드는 version control을 위한 것으로 이 예제에서는 사용하지 않으므로 '<None>'으로 설정합니다. (2)번 영역은 최종 생성될 파일들을 나타냅니다. 여기서 '*.pro' 파일은 Qt의 프로젝트 파일입니다. 우측 하단의 'Finsh' 버튼을 클릭하여 완성합니다.



다음 화면은 생성된 프로젝트를 보여줍니다. 메인 윈도우 화면을 변경하기 위해서 좌측 Projects에서 'Forms'를 클릭하여 펼치고 그 안에 'mainwindow.ui' 파일을 더블 클릭합니다. 



그럼 다음 화면과 같이 메인 윈도우 화면을 보여주는 design 모드로 자동 전환되며, 좌측 Filter 메뉴에서 스크롤 업다운하여 Display Widgets의 Text Browser 메뉴를 메인 윈도우 화면 위에 드래그 앤 드롭하여 가져다 놓습니다.



그리고 아래 화면과 같이 가져다 놓은 Text Browser를 더블 클릭하여 'This is a Text Browser!'라고 디폴트 메세지를 입력하고 'File > Save "mainwindow.ui"' 메뉴를 선택하거나 'Ctrl + S'를 쳐 'mainwindow.ui' 파일을 저장합니다.



다음은 맨 좌측에 Edit 메뉴를 클릭하여 Edit 모드로 복귀하고 Projects 내에 'mainwindow.cpp' 파일을 더블 클릭하여 오픈합니다. 그리고 다음의 코드를 다음 화면과 같이 삽입하고 저장합니다.

ui->textBrowser->setText("Hello World !!");

 이 코드는 Text Browser에 보낼 메세지를 설정할 수 있습니다.



코딩이 완료되었으며, 'Build > Run' 메뉴를 선택하거나 'Ctrl + R'를 쳐 실행시키면 다음과 같은 실행화면을 확인할 수 있습니다.



Debug 폴더에서 실행 파일을 직접 클릭하여 실행시킬 수도 있는데 이 경우에는 *.dll 파일이 없다는 오류가 발생하는데 이는 정적(static)으로 빌드하였기 때문으로 배포시에 동적(dynamic) 빌드하면 해결됩니다.



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

UART(Serial) 통신 예제  (2) 2018.03.03
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