PLC가 연결하지 않고 PC만으로 자체적으로 PLC와 연결 테스트 하는 방법을 공유하고자 이 문서를 작성.

 

1) 하단의 웹 페이지에 접속 (공식 웹 페이지에서는 회원가입이 필요하다.)

http://www.servo-tech.co.kr/

 

2) GX-Works 2 다운로드

 

3) GX-Works2 압축을 풀고 설치 파일 실행.

    (SW1DNC-GXW2-E1 폴더 내에 있는 setup파일 실행, Serial 번호 있어야 함.)

 

 

 

1) GX Works2 실행. (Melsoft Application\GX Works2)

 

2) 새 프로젝트 생성. (PLC Series 및 Type은 본인 임의로 입력)

 

3) Simulation 실행

 

 

1) Communication Setup Utility 실행. (Melsoft\Communication Setup Utility)

 

2) PC 프로그램에서 연결 할 PLC Station Number를 입력.

 

3) PC측에서 연결 할 PLC 정보를 설정한다.

 

4) Comment는 사용자 임의로 입력하고 Finish 버튼 클릭

 

5) Finish 클릭 하면 다음과 같은 페이지가 나타난다.

 

6) Connection test 탭으로 이동하여 Test 버튼을 클릭 (연결 성공 이미지) 

 

7) Simulation 프로그램 종료 시 연결 이미지 (연결 실패 이미지) 

Posted by 람뫼
:

2-1에서 빌드를 정상적으로 마쳤다면 아래와 같은 파일이 생성 되었을 것이다.

 

Client는 메인 프로그램인 x64 (64bit) 프로그램을 말한다. (이 문서는 MFC 환경을 기준으로 작성)

개발 환경은 Visual Studio 2019를 사용하였고 Visual Studio 2013부터 동일한 방법으로 사용 중이다.

 

1)프로젝트 생성 방법.

1. 새 프로젝트 생성 : 그림 1과 같이 프로젝트 템플릿 항목에 MFC검색 후 선택 (Visual C++ -> MFC 프로젝트. )

2. 그림 2와 같이 프로젝트 이름을 작성하고 만들기 버튼 클릭 . (프로젝트 명 : MFCApplication1)

2) Server 프로젝트에서 생성한 tlb 파일 적용.

1. 프로젝트의 소스 파일과 헤더 파일이 있는 폴더와 동일한 위치에 tlb 파일을 복사. (본인 파일명 Server1.tlb)

2. 헤더 파일에 ‘#import “server1.tlb” no_namespace’ 작성. (본인 파일명 Server1.tlb.)

위 과정 진행 후 빌드가 안된다면 tlb파일이 다른 위치에 있을 확률이 매우 높다. (주로 debug폴더에..)

빌드 성공 시 debug폴더에 tlb파일명과 동일한 명칭의 tlh, tli형식의 파일이 생성된다. (e.g. Server1.tlh, Server1.tli)

 

3. 헤더 파일에 Com 인스턴스 생성.

4. Cpp파일에서 아래와 같이 테스트.

5. Return 값 확인하여 정상 동작 확인.

 

끝. 

 

Posted by 람뫼
:

MX Component를 64bit 프로그램에서 조금 더 편리하게 사용하는 방법을 공유하는 차에 문서를 작성하였다.

(MX Component는 64bit 환경에서 직접 연결 지원 안됨.)

 

서버는 MX Component와 직접적으로 연결하는 x86 (32bit) 프로그램을 말한다.

개발 환경은 Visual Studio 2019를 사용하였고 Visual Studio 2013부터 동일한 방법으로 사용 중이다.

 

1) 프로젝트 생성 방법.

1. Visual Studio를 관리자 모드로 실행한다.

2. 새 프로젝트 생성 : 프로젝트 템플릿 항목에 ATL 검색 후 선택 (타 버전 : Visual C++ -> ATL 프로젝트)

 

3. 프로젝트 이름을 작성하고 어플리케이션 종류를 exe로 선택한다. (본인 프로젝트 명 : Server1)

 

2) ATL 클래스 추가

1. 프로젝트 생성을 마치면 하나의 솔루션에 두 개의 프로젝트가 생성된다.

2. 본인이 만든 프로젝트 명을 선택하여 우 클릭 후 새 항목을 추가한다. (본인 프로젝트 명 : Server1)

3. C++ -> ATL항목에서 ATL 단순 개체 선택 후 이름 작성 (본인 클래스 명 : PLCManager)

4. ProgID를 제외하고 자동 입력이 되어 있을 것이다.

   ProgID는 레지스트리 (HKEY_CLASS_ROOT\WOW6432Node\CLSID)에 저장되는 ID로

   보통 '프로젝트명.클래스명'의 형태로 입력한다.

   나머지는 기본 설정으로 두고 마침 버튼을 클릭.

5. CLSID는 .idl 파일에서 library의 uuid에 해당된다. 프로젝트 빌드 후 확인해 볼 수 있다.

 

3) Method 생성.

1. 클래스 뷰에서 클래스 선택 후 우측 마우스 클릭하여 Method를 추가한다.

   (열쇠아이콘 더블클릭하여 idl파일이 열리는 항목에서 진행.)

 

2. 다음과 같이 Method 및 매개 변수를 추가한다.

3. MX Component 를 사용하기 위하여 추가 포함 디렉터리에 Melsec\Act\include 경로를 추가한다.

   (사용자 본인 PC의 Melsec 설치 경로 확인)

4. 추가 후 헤더 파일에 #include "ActUtlType_i.h" 구문을 추가한다.

5. 생성 내용 확인 및 Cpp파일에서 필요한 기능을 구현한다. (두 번째로 생성한 Method여서 id는 2번으로 부여 됨.)

- idl (Interface Definition Language) 파일.

- 헤더 파일.

- cpp 파일.

 

4) 정상적인 빌드 후 결과 파일 확인

1. 솔루션 경로의 폴더 내용은 다음과 같다.

2. 솔루션의 Debug 폴더

3. 솔루션\Server1의 Debug 폴더

   (tlb파일은 dll과 유사하게 사용 됨.)

4. Server에서 작성한 내용이 Client에서 정상적으로 작동하려면 아래와 같이 활성화 되어야 한다.

위와 같이 활성화 시키는 방법은

- Visual Studio를 관리자 모드로 하여 Server 실행 후, Client에서 Server에 작성한 Method 실행 시 자동 생성

- 수동으로 등록하는 방법은 솔루션\Debug 폴더 내에서 Server1.exe /Regserver 입력.

- 수동 실행시키는 방법은 Server1.exe 파일 실행.

 

Posted by 람뫼
:

프로젝트 항목에서 추가 포함 디렉터리 및 링크 설정하는 방법이 아닌 더 편한 방법이 있다.

 

VIsual Studio의 Nuget을 이용한 방법인데 Nuget이란 Visual Studio에서 오픈소스를 추가 및 관리하기 쉽게

만들어 놓은 것이다.

 

아래는 임의로 콘솔 프로그램을 만들어 Opencv를 추가한 화면이다.

 

우측 마우스 클릭하여 Nuget 패키지 관리 클릭
온라인 항목에서 Opencv 검색
OpenCV 3.1설치 및 OpenCV 3.1 Symbol 설치. (OpenCV 3.1을 설치하면 OpenCV 3.1 Redist는 자동으로 설치 됨.)
헤더에 #include <opencv2/opencv.hpp> 추가 후 OpenCV 사용하면 된다.

 

Nuget 추가 후 빌드 시 packages 폴더 및 OpenCV 관련 파일들이 다운로드된다. (지우면 빌드 시 재설치됨, 인터넷 연결 되어있어야 함.)

다만 OpenCV는 3버전 이후 부터는 opencv_world310d.dll과 같이 하나로 합쳐져 있는데 하나로 합쳐져 있는 dll을

사용하면 Memory leak 현상이 있어서 이 dll을 분리해서 사용하길 권함. (이 내용은 추후에 포스팅할 계획.)

Posted by 람뫼
:

CString -> const char *

 

1
2
3
CString aa = _T("123");
CStringA bb = (CStringA)aa;
Const char* dd = bb.GetBuffer();
 

 

const char * -> CString

 

1
2
3
const char* dd = "123";
CString aa;
aa = (CString)dd;
 

'C++ > 형변환' 카테고리의 다른 글

CString <-> LPWSTR  (0) 2018.10.10
CString <-> short * (Unicode, Multibyte), PLC ASCII  (0) 2018.06.08
CString <-> BSTR (Unicode , Multibyte)  (0) 2018.06.07
CString <-> LPCTSTR  (0) 2018.05.29
Posted by 람뫼
:

아래 사진들은 개인적인 공부를 위해 작성했던 PPT 사진임..

 

UMAC 매뉴얼을 참고하고 직접 사용한 경험을 바탕으로 짧게 간추림.

 

터미널 실행 시 화면. (Pewin32Pro에서 실행화면.. PMAC Suite도 동일함.)

아래의 구문들은 위의 터미널 창에 입력하면 된다. (xx는 축 번호)

 

Reference.

 

[1]. http://www.deltatau.co.kr/xe/ 

'UMAC' 카테고리의 다른 글

UMAC 개요  (0) 2018.03.02
Posted by 람뫼
:

귀가

퇴사 기념으로 구매한 게이밍 전용 Asus GL704GW 인데 조금 비싸긴 해도 속도도 빠르고 좋다. (RAM Full.)

LED 키패드, 하단 LED 및 asdw 키 구분 

 

국방무늬 키보드.
겉도 이쁨

 

Posted by 람뫼
:

가끔 프로그래밍을 하면서 의도치 않게 실수를 하곤 한다.


사람인지라 어쩔 수 없지만 그래도 했던 실수를 반복하지 않는게 중요하니.. 글을 남겨야지 ㅜ





이 메시지는 Debug 상태에서만 발생하는 Assert Message로 CString을 잘못 사용하였을 때에 나온다. 


1
2
CString strTemp = _T("abcd");
strTemp.Format(_T("%s.jpg"), strTemp);
cs


.위와 같이 strTemp 변수에 값을 할당하고 Format을 이용하여 strTemp에 문자열을 할당하려고 할 때 발생하는 문제이다.



원인


strTemp를 변경하기 위해 strTemp를 인자 값으로 사용할 경우 복사가 아닌 직접 참조가 되어 인자 값 자체가 


기존 "abcd"에서 다른 값으로 변경이 될 수 있다.



해결 방법


1
2
3
4
CString strTotal;
Cstring strTemp = _T("abcd");
 
strTotal.Format(_T("%s.jpg"), strTemp);
cs


위와 같은 방법으로 변수를 하나 더 선언하여 사용하는 방법을 추천.



Posted by 람뫼
:

CString <-> LPWSTR

C++/형변환 2018. 10. 10. 10:07 |

Unicode 환경에서의 형변환.


CString -> LPWSTR


첫 번째 방법.


1
2
3
4
LPWSTR szAA;
CString strBB;
 
szAA = (LPWSTR)(LPCWSTR)strBB;
cs

 

CString을 LPCWSTR로 변환한 후 LPWSTR로 변환.


두 번째 방법


1
2
CString aa = _T("123");
LPWSTR dd = aa.GetBuffer();
cs



LPWSTR -> CString 

 

1
2
3
4
LPWSTR szAA;
CString strBB;
 
strBB.Format(_T("%s"), szAA);
cs

 

CString의 Format함수를 사용하여 변환.

'C++ > 형변환' 카테고리의 다른 글

CString <-> Const char *  (0) 2020.01.09
CString <-> short * (Unicode, Multibyte), PLC ASCII  (0) 2018.06.08
CString <-> BSTR (Unicode , Multibyte)  (0) 2018.06.07
CString <-> LPCTSTR  (0) 2018.05.29
Posted by 람뫼
:

MFC ListControl Column Check

C++/팁 2018. 10. 8. 13:47 |

이 문서는 Visual Studio 2013 환경에서 제작 되었습니다.

 

ListControl를 가공해서 사용할 경우 기존 코드와는 조금 다른 방식으로 사용해야 한다.

 

 

 

기본 방식

 

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
void CTest::Init()
{
    CListCtrl m_ctrList_MESStatus; //리소스 뷰에서 리스트 컨트롤 변수 생성하면 생성 됨. 

 

    //ListControl 스타일 설정

    m_ctrList_MESStatus.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES 

   | LVS_EX_DOUBLEBUFFER);  

    

    //Column 생성    

    m_ctrList_MESStatus.InsertColumn(0, _T("CELL ID"), LVCFMT_CENTER, 230-1);

    m_ctrList_MESStatus.InsertColumn(1, _T("MES SEND"), LVCFMT_CENTER, 100-1);
    m_ctrList_MESStatus.InsertColumn(2, _T("MES RECIVE"), LVCFMT_CENTER, 100-1);
 
 
    int nCnt = 0;
    CString strIdx;
    nCnt = m_ctrList_MESStatus.GetItemCount();
    strIdx.Format(_T("%d"), nCnt + 1);
    
 
    //Row 생성 (실제 데이터)
    m_ctrList_MESStatus.InsertItem(nCnt, strIdx);
    m_ctrList_MESStatus.SetItem(nCnt, 1, LVIF_TEXT, _T("MES Send OK"), NULLNULLNULLNULL);
    m_ctrList_MESStatus.SetItem(nCnt++, 2, LVIF_TEXT, _T("MES Recive OK"), NULLNULLNULLNULL);
 
    m_ctrList_MESStatus.InsertItem(nCnt, strIdx);
    m_ctrList_MESStatus.SetItem(nCnt, 1, LVIF_TEXT, _T("MES Send zz"), NULLNULLNULLNULL);
    m_ctrList_MESStatus.SetItem(nCnt, 2, LVIF_TEXT, _T("MES Recive zx"), NULLNULLNULLNULL);
}
 
cs

 

 

위의 방식으로 스타일에서 체크박스를 적용할 경우 체크박스는 각 항목의 맨 오른쪽에 나타나게 된다.

 

이 체크박스를 하나하나 누르기 힘들기 때문에 컬럼 부분에 체크박스를 추가해서 전체 체크를 하려면 

 

아래와 같이 사용하면 된다.

 

가공 방식

 

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
void CTest::Init()
{

    CWnd *m_CwndList; //변수 구분을 위해 여기에 표기. (헤더에 두고 사용 추천)

    m_CwndList = GetDlgItem(IDC_LIST_MES_NG_STATUS);
    ListView_SetExtendedListViewStyle(m_CwndList->m_hWnd, LVS_EX_DOUBLEBUFFER | 

    LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);

 
    // Add some columns to the list view control
    LVCOLUMN lvc = { 0 };
    ListView_InsertColumn(m_CwndList->m_hWnd, 0&lvc);
    lvc.mask = LVCF_TEXT;
    lvc.iSubItem++;
    lvc.pszText = _T("Cell ID");
    ListView_InsertColumn(m_CwndList->m_hWnd, 1&lvc);
    lvc.iSubItem++;
    lvc.pszText = _T("MES Send");
    ListView_InsertColumn(m_CwndList->m_hWnd, 2&lvc);
    lvc.iSubItem++;
    lvc.pszText = _T("MES Receive");
    ListView_InsertColumn(m_CwndList->m_hWnd, 3&lvc);
 
    // Set column widths
    ListView_SetColumnWidth(m_CwndList->m_hWnd, 0, LVSCW_AUTOSIZE_USEHEADER);
    ListView_SetColumnWidth(m_CwndList->m_hWnd, 1, LVSCW_AUTOSIZE_USEHEADER); //Cell ID
    ListView_SetColumnWidth(m_CwndList->m_hWnd, 2, LVSCW_AUTOSIZE_USEHEADER); //MES Send
    ListView_SetColumnWidth(m_CwndList->m_hWnd, 3, LVSCW_AUTOSIZE_USEHEADER); //MES Receive
    
    
    HWND header = ListView_GetHeader(m_ctrList_MESStatus);
    DWORD dwHeaderStyle = ::GetWindowLong(header, GWL_STYLE);
    dwHeaderStyle |= HDS_CHECKBOXES;
    ::SetWindowLong(header, GWL_STYLE, dwHeaderStyle);
 
    m_nListSelectIdx = ::GetDlgCtrlID(header);
 
    HDITEM hdi = { 0 };
    hdi.mask = HDI_FORMAT;
    Header_GetItem(header, 0&hdi);
    hdi.fmt |= HDF_CHECKBOX/* | HDF_FIXEDWIDTH*/;
    Header_SetItem(header, 0&hdi);}
}
 
cs

 

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
BEGIN_MESSAGE_MAP(CTest, CDialogEx)
    ON_NOTIFY(HDN_ITEMSTATEICONCLICK, 0&CTest::OnHdnItemStateIconClickListMesNgStatus)
END_MESSAGE_MAP()
 
void CTest::OnHdnItemStateIconClickListMesNgStatus(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    
    LPNMHEADER pnmHeader = (LPNMHEADER)pNMHDR;
 
    if (pnmHeader->pitem->mask & HDI_FORMAT && pnmHeader->pitem->fmt & HDF_CHECKBOX) 
    {
        CheckAllItems(!(pnmHeader->pitem->fmt & HDF_CHECKED));
    }
    
    *pResult = 0;    
}
 
void CTest::CheckAllItems(BOOL bChecked)
{
    for (int nItem = 0; nItem < ListView_GetItemCount(m_CwndList->m_hWnd); nItem++
    {
        ListView_SetCheckState(m_CwndList->m_hWnd, nItem, bChecked);
    }
}
cs

 

HDN_ITEMSTATEICONCLICK 이벤트를 추가한 후 위와 같이 작성하면 컬럼 헤더에서 체크박스 클릭 시 전체 항목 선택

 

및 선택해제가 가능하다.

 

 

그리고 아이템 항목 추가는 아래와 같이 한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void CTest::AddItem(CString strCellID, CString strSend, CString strReceive)
{
    CWnd *m_CwndList; //변수 구분을 위해 여기에 표기. (헤더에 두고 사용 추천)
    m_CwndList = GetDlgItem(IDC_LIST_MES_NG_STATUS);
 
    LVITEM lvi = { 0 };    lvi.iItem = ListView_GetItemCount(m_CwndList->m_hWnd);
    ListView_InsertItem(m_CwndList->m_hWnd, &lvi);
 
    lvi.mask = LVIF_TEXT;
    lvi.iSubItem = 1;
    lvi.pszText = (LPWSTR)(LPCWSTR)strCellID;
    ListView_SetItem(m_CwndList->m_hWnd, &lvi);
 
    lvi.iSubItem++;
    lvi.pszText = (LPWSTR)(LPCWSTR)strSend;
    ListView_SetItem(m_CwndList->m_hWnd, &lvi);
 
    lvi.iSubItem++;
    lvi.pszText = (LPWSTR)(LPCWSTR)strReceive;
    ListView_SetItem(m_CwndList->m_hWnd, &lvi);
}
 
cs

 

항목 삭제는 다음과 같이 한다.

 

1
2
3
4
5
6
7
8
void CTest::DeleteItem()
{
    CWnd *m_CwndList; //변수 구분을 위해 여기에 표기. (헤더에 두고 사용 추천)
    m_CwndList = GetDlgItem(IDC_LIST_MES_NG_STATUS);
    
    ListView_DeleteItem(m_CwndList->m_hWnd, ListView_GetItemCount(m_CwndList->m_hWnd) - 1);
}
 
cs

 

이 체크박스 전체 선택은 속성창에서 자체 해결 불가능하기 때문에 조금 불편하더라도 위와 같은 방식으로 ListControl을

 

가공하여 사용해야 한다.

Posted by 람뫼
: