IoT Platform 사용방법


본 강좌에서는 enuSpace for mars를 이용하여 IoT 디바이스의 센서값을 취득 및 데이터 로직을 구성하는 방법에 대하여 설명합니다.

enuSpace 학생용 버젼 다운로드 : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


준비물

Raspberry PI, Arduino, sensor


프로그램 설치


1. Raspberry PI Installation (software)


enuSpace for mars와 연동하기 위하여 Raspberry PI에 windows 10 iot core 운영체제를 설치후 다운로드 링크에서 응용 프로그램을 설치합니다.


windows 10 iot core 설치 

설치 가이드 : https://developer.microsoft.com/ko-kr/windows/iot/GetStarted

마이크로소프트사에서 제공하는 설치 가이드를 기반으로 단계별로 설치 절차를 진행합니다.

윈도우 Edge 또는 웹브라우져를 이용하여 Window 10 iot core가 설치된 Raspberry PI에 접속을 수행합니다.



Windows 10 IoT Core의 기본 App의 IoTCoreDefaultApp 실행 화면입니다.



아래 그림과 같이 Raspberry PI와 Arduino 디바이스간에 USB Serial을 통하여 연결을 수행하고 아두이노에 센서 2종을 연결한 화면입니다.



Windows 10 IoT Core가 설치된 Raspberry PI에 아래 링크의 응용프로그램을 설치합니다. 


download link : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017

Windows 10 Core App : enuSpace_IoT (enuSpace_IoT_1.0.3.0_x86_x64_arm.appxbundle)



설정해상도는 1920 *1080으로 설정하여야 정상적인 디스플레이가 가능합니다.



App package 에서 다운로드한 파일을 선택합니다.




Go 버튼을 클릭하여 설치를 수행합니다.



설치를 완료 합니다.


Arduino Installation (software) 


아두이노 디바이스에 아두이노 IDE에서 제공하는 StandardFirmata 프로그램을 설치합니다. 

아두이노 IDE : https://www.arduino.cc/en/Main/Software

라즈베리 파이(Raspberry PI)와 아두이노(Arduino)간에는 StandardFirmata를 이용하여 통신을 수행합니다.


프로그램 기동


Raspberry PI와 Arduino에 프로그램을 설치 마무를 하였다면, 서버 프로그램을 기동합니다. enuSpace 프로그램을 기동하여 새로운 프로젝트를 생성합니다. 

enuSpace의 웹서버를 기동합니다. 웹 서버를 기동하기 전에 리본메뉴 Data/Communication->System Configuration 버튼을 클릭하여 웹서버 사용 유무 및 ip와 포트를 설정합니다.


리본메뉴 Data/Communication->Web Server의 Start 버튼을 클릭하여 서버를 기동합니다. 




서버 사이드 준비사항은 여기까지 입니다. 

라즈베리 파이 응용프로그램을 기동하여 enuSpace 프로그램에 디바이스 등록과정을 통하여 센서의 데이터 및 입출력 핀 제어를 수행합니다.


Raspberry PI -> enuSpace iot 응용프로그램 기동 


라즈베리 파이에 설치한 enuSpace iot 응용프로그램을 실행합니다. 상단의 Server URL의 정보를 enuSpace서버의 ip주소와 포트 정보를 입력합니다.


enuSpace 서버사이드에 본 디바이스를 접속하고자 하는 경우 서버 사이드에 사용자 등록되어 로그인을 수행하여야 합니다. 신규 프로젝트를 생성시에는 사용자 등록 버튼을 클릭하여 사용자 등록을 수행합니다. 


로그인 페이지는 자동 로그인 체크박스, 로그인 버튼, 아이디 찾기/비밀번호 찾기, 사용자 등록 버튼으로 구성, 자동 로그인 체크를 수행후 로그인을 실행하면, 다음 프로그램 재 기동시에는 자동 로그인이 수행됩니다. 

로그인 페이지에서 사용자 등록버튼을 클릭하면, 아래 그림과 같이 사용자 등록을 수행하는 페이지로 전환되면, 사용자 등록 버튼을 클릭을 수행하면, 설정된 서버 주소(enuSpace 서버 사이드)에 사용자 등록 요청을 수행합니다.



정상적으로 사용자 등록과 로그인 페이지가 완료되면, 디바이스 등록 페이지가 나타납니다.



디바이스의 타입은 현재 연결된 아두이노의 타입을 설정합니다. 디바이스 키는 통합 저작 도구 IOT 서버에 등록될 디바이스 키 정보이며, 라즈베리 파이의 시스템 이름을 활용합니다.

신규 디바이스를 등록하는 경우에는 관련 디바이스의 정보와 변수 정보를 enuSpace에 등록하는 과정입니다. 디바이스 등록 버튼을 클릭합니다.



아두이노와 연결된 시리얼 포트 리스트에서 아두이노와 연계된 시리얼 포트를 선택후 연결 버튼을 클릭하여 연결 수행합니다. 연결이 정상적으로 수행이 되면, 아두이노의 센서 데이터값이 현시되며, enuSpace에 등록된 서버에 전송을 수행하여 서버 사이드에서 데이터베이스화 되어 저장됩니다. enuSpace 서버 응용 프로그램에서 리본메뉴 Device List와 DB Show 버튼을 클릭하여 등록된 내용을 확인할 수 있습니다.


enuSpace 서버 사이드에서 프로그램 설치시 사용된 라이브러리를 불러와 화면 작도를 수행합니다. 아두이노 디바이스 심볼 객체의 속성 interface 설정값을 true로 설정하고, interface-id 항목에 #+디바이스 이름을 입력합니다. 이 작업은 디바이스와 디바이스의 tag db의 값이 그래픽적인 라이브러리에 인터페이스 됨을 의미합니다.


사용자 정의 device 심볼을 구성하고자 하는 경우에는 아래와 같은 절차를 따라서 생성합니다.

Project Explorer 하위 Libarary의 Logic에 라이브러리 파일을 생성하고, 디바이스 라이브러리 노드 이름을 입력하고 노드를 생성합니다. 로직의 핀을 추가하고 추가된 핀의 name 속성값을 device의 variable이름으로 설정합니다. 



다음 강좌에서는 클라이언트 웹 브라우져에서 랜더링을 위한 enuSpace 서버 사이드에서의 화면 구현 및 javascript 코드 구현 방법에 대하여 알아보겠습니다. 

-이엔유 주식회사-

enuSpace 시뮬레이션 기능 및 Data Visualization 사용방법


본 강좌에서는 enuSpace for mars를 이용하여 시뮬레이션을 수행하는 방법에 대하여 설명합니다. 

enuSpace 학생용 버젼 다운로드 : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


enuSpace for mars에서 시뮬레이션 또는 task를 개발함에 있어 2가지 형태의 모델로 구성될 수 있습니다. enuSpace for mars의 ontask함수를 활용한 방법과 외부의 task의 모듈을 연동하는 방법입니다.


Lesson5 sample : lesson5.zip


1. 로직 라이브러리를 이용한 flowbased programming 방법.

2. 외부 모델을 이용한 연동 방법.


동영상 미리보기


New Project


새로운 프로젝트를 생성하기 위해서 Home->New->New Project메뉴를 이용하여 새로운 프로젝트를 생성합니다.



Simulation Time Setup


새로운 프로젝트 생성을 완료하였다면, 리본메뉴 Data/Communication->System Configuration메뉴를 선택하여 System Configuration 대화창의 속성을 설정합니다. 시뮬레이션용으로 설정하기 위해서는 Time의 속성중 Simulation Time을 설정합니다. Simulation Time을 설정하게 되면 enuSpace에서 기동되는 시작시간의 정보는 0초부터 동작을 수행합니다. 

System Time옵션에서 Simulation Time옵션으로 변경 수행시 프로젝트에 기존에 누적된 히스토리 데이터베이스가 모두 제거되어 초기화 됩니다. 프로젝트 로드시에도 기존의 히스토리 데이터베이스를 초기화 합니다.

참고로 System Time의 설정은 현재시간(UTC)을 기준으로 모든 데이터가 생성되고  히스토레 데이터에 누적됩니다.  



Simulation Scheduling


enuSpace for mars의 task()함수를 사용하는 경우에는 flowbased programming을 통하여 동작을 수행합니다. 내부 task()함수는 스케쥴링 속성값에 따라서 주기적인 연산을 호출하도록 구성되어 있습니다. 속성 설정하기 위해서 Project Explorer창 Task하위 logic_svg 아이템을 선택합니다. logic_svg 속성창 중 Cycle (Hz) 속성은 1초에 1, 2, 3, 4, 6, 8, 12, 24회 호출 주기에 대한 설정입니다. Task In/Out의 속성은 선택한 Task에 대하여 연산을 수행할 것인지, 제외할것인지를 설정합니다. 



시뮬레이션 모델을 제작하다보면 task()함수에서 delta T값을 이용하는 경우가 있습니다. 전역변수 dt값을 이용하여 코드를 구현합니다.


function _ontask()

--TODO Add your lua script code here

local deltaT = dt

--bla bla ~~

end


외부 모델 연계 API

시뮬레이션 모델 개발시 기존의 코드를 재활용하거나 외부의 모델과의 인터페이스가 필요한 경우가 있습니다. enuSpace는 외부 모델과 연동하기 위한 인터페이스 모듈을 제공합니다. 외부 모델과 연계시 dynamic link library(dll)을 이용합니다.

외부 연동 인터페이스 모듈의 dll의 주요 함수는 아래와 같습니다.


extern "C" __declspec(dllexport) bool OnInit();

extern "C" __declspec(dllexport) bool OnLoad();

extern "C" __declspec(dllexport) bool OnUnload();

extern "C" __declspec(dllexport) bool OnTask();


각 함수는 아래와 같은 조건에서 호출됩니다.

OnInit() : 첫 기동시 호출되는 초기화 함수

OnLoad() : dll 로드수행시 호출되는 함수

OnUnload() : dll 언로드 수행시 호출되는 함수

OnTask() : 스케쥴링 주기에 따라서 호출되는 함수


OnTask()함수 구현부에는 시뮬레이션을 수행하고자 하는 알고리즘을 추가합니다. 작성된 코드와 enuSpace와 연동하기 위해서 인터페이스용 콜백함수 4개를 제공합니다. 


extern "C" __declspec(dllexport) void SetCallBack_SetValue(void fcbSetValue(wchar_t*, double));

extern "C" __declspec(dllexport) void SetCallBack_GetValue(DBDataStruct* fcbGetValue(wchar_t*));

extern "C" __declspec(dllexport) void SetCallBack_SetArrayValue(void fcbSetArrayValue(wchar_t*, void*, int, int));

extern "C" __declspec(dllexport) void SetCallBack_GetArrayValue(DBDataStruct* fcbGetArrayValue(wchar_t*));


특정 데이터베이스의 Tag값을 읽고 쓰기 위한 함수 포인터입니다. 본 함수는 dll로드 수행시 함수의 포인터로 전달됩니다. 전달된 함수 포인터 이용하여 값을 읽거나 쓰기를 수행합니다. 


구현부를 보시면 아래와 같습니다.


void (*g_fcbSetValue)(wchar_t*, double) = NULL;

DBDataStruct* (*g_fcbGetValue)(wchar_t*) = NULL;

void(*g_fcbSetArrayValue)(wchar_t*, void*, int, int) = NULL;

DBDataStruct* (*g_fcbGetArrayValue)(wchar_t*) = NULL;


extern "C" __declspec(dllexport) void SetCallBack_SetValue(void fcbSetValue(wchar_t*, double)) g_fcbSetValue = fcbSetValue; }

extern "C" __declspec(dllexport) void SetCallBack_GetValue(DBDataStruct* fcbGetValue(wchar_t*)) g_fcbGetValue = fcbGetValue; }

extern "C" __declspec(dllexport) void SetCallBack_SetArrayValue(void fcbSetArrayValue(wchar_t*, void*, int, int)) g_fcbSetArrayValue = fcbSetArrayValue; }

extern "C" __declspec(dllexport) void SetCallBack_GetArrayValue(DBDataStruct* fcbGetArrayValue(wchar_t*)) g_fcbGetArrayValue = fcbGetArrayValue; }


위 코드는 기 제공되는 코드의 예시입니다. 


CMap<CString, LPCWSTR, DBDataStruct*, DBDataStruct*> g_DBMapList;

void SetArrayValue(CString strVariable, void* pSrc, int iType, int iSize)

{

if (g_fcbSetArrayValue)

g_fcbSetArrayValue(strVariable.GetBuffer(0), pSrc, iType, iSize);

}

DBDataStruct* GetArrayValue(CString strVariable)

{

if (g_fcbGetArrayValue)

return g_fcbGetArrayValue(strVariable.GetBuffer(0));

return NULL;

}

void SetValue(CString strVariable, double fValue)

{

double fReturn = 0;

DBDataStruct* pData = NULL;

g_DBMapList.Lookup(strVariable, pData);

if (g_fcbSetValue && pData == NULL)

{

pData = g_fcbGetValue(strVariable.GetBuffer(0));

g_DBMapList.SetAt(strVariable, pData);

}

if (pData && pData->pValue)

{

switch (pData->itype)

{

case DEF_INT:

*(int*)pData->pValue = (int)fValue;

break;

case DEF_FLOAT:

*(float*)pData->pValue = (float)fValue;

break;

case DEF_DOUBLE:

*(double*)pData->pValue = fValue;

break;

case DEF_BOOL:

if (fValue == 1)

*(bool*)pData->pValue = true;

else

*(bool*)pData->pValue = false;

break;

case DEF_WCHAR:

break;

default:

break;

}

}

}

double GetValue(CString strVariable)

{

double fReturn = 0;

DBDataStruct* pData = NULL;

g_DBMapList.Lookup(strVariable, pData);

if (g_fcbGetValue && pData == NULL)

{

pData = g_fcbGetValue(strVariable.GetBuffer(0));

if (pData)

g_DBMapList.SetAt(strVariable, pData);

}

if (pData && pData->pValue)

{

switch (pData->itype)

{

case DEF_INT:

fReturn = *(int*)pData->pValue;

break;

case DEF_FLOAT:

fReturn = *(float*)pData->pValue;

break;

case DEF_DOUBLE:

fReturn = *(double*)pData->pValue;

break;

case DEF_BOOL:

if (*(bool*)pData->pValue == TRUE)

fReturn = 1;

else

fReturn = 0;

break;

default:

break;

}

}

return fReturn;

}


실제 인터페이스는 값을 읽기 쓰기위한 코드와 모델 연산로직 코드를 추가함으로서 외부 모델을 연계할 수 있습니다. 


모델 예)

모델의 실행 코드와 인터페이스 코드 예시


double display[16][16];

float initValue = 1.0f;


extern "C" __declspec(dllexport) bool OnTask()

{

initValue = initValue + 0.1;

for (int x = 0; x < 16; x++)

{

for (int y = 0; y < 16; y++)

{

display[x][y] = 1.0 + sin(double((x * 16) + (y * 16)) / 3.141592 / 5 + initValue);

}

}

SetArrayValue(L"@CORE.display[0][0]", display, DEF_DOUBLE, 16 * 16);

return true;

}


sin파를 생성하여 데이터 인터페이스를 수행하는 코드를 작성하였습니다. 위와 같이 코드를 추가하고 컴파일을 수행하여 CoreTask.dll을 생성합니다. 모델 생성이 완료하였다면 데이터베이스와 연동하기 위한 tag id를 enuSpace 프로젝트에 추가를 수행합니다. SetArrayValue()함수는 배열 정보를 enuSpace에서 추가한 tag의(@CORE.display[0][0]) 값에 연산 결과를 전달하는 과정입니다. 


SetArrayValue() 함수의 파라미터 정보를 보면 변수명, 원본 데이터의 메모리 주소, 복사하고자하는 데이터 타입, 사이즈값입니다. 만약 단일 변수에 추가하고자 하는 경우에는 SetValue()함수를 이용합니다. 경우에 따라서 위의 예시에서 제공하는 SetValue()함수 등은 확장 및 변경하여 구현할 수 있습니다.


enuSpace for mars 데이터베이스 TAG 추가


enuSpace의 리본메뉴 Data/Communication->DB Show 버튼을 클릭합니다. 다음과 같이 DB Table의 정보가 나타나고 DB+ 버튼을 클릭하여 모델간의 인터페이스를 위한 TAG 변수를 추가합니다. 추가되는 최종 TAG ID는 @문자가 앞에 추가됩니다. @문자는 데이터베이스 TAG 변수와 전역변수와의 구분자로도 활용됩니다. 데이터베이스 TAG ID를 이용하여 스크립트에서 활용합니다.



정상적으로 데이터베이스 TAG가 추가완료 후 앞에서 제작한 외부 TASK(CoreTask.dll)를 enuSpace 프로젝트에 추가합니다. Project Explorer의 Task항목을 선택하고 팝업메뉴 Add Task를 선택하여 Task Module의 콤보박스에 CoreTask.dll을 선택합니다. 프로젝트 디렉토리 lesson5//Task//CoreTask에 앞에서 생성한 CoreTask.dll 파일이 존재하는 경우 자동으로 콤보박스에서 선택이 가능하도록 제공이 됩니다. 



디렉토리의 구조 및 외부 TASK의 위치는 아래 그림과 같습니다.



TASK가 정상 등록이 되었다면, TASK를 기동하기 위해서 리본메뉴 Home->Script Operation의 Run 버튼을 클릭합니다. 연산이 정상적으로 처리되고 있는지를 확인하기 위해서 리본메뉴의 리본메뉴의 Data/Communication->DB Show메뉴를 선택하여 데이터베이스의 실시간 값을 확인합니다. 



아래 그림과 같이 차트 버튼을 클릭하여 팝업 Trend를 이용하여 데이터값을 확인할 수 있습니다. 차트사용 방법은 별도의 강좌에서 설명하도록 하겠습니다. 



3D data visualization


앞에서 제작한 배열변수의 값을 3차원 디스플레이에 디스플레이 하기 위해서 픽쳐파일 core_display.x3d 파일을 추가합니다. 추가된 x3d 파일을 선택후 Terrain객체를 추가합니다. Terrain 객체의 속성중 subdivision_x, subdivision_y의 값을 데이터베이스 TAG의 배열정보 16, 16으로 설정합니다. subdivision의 값을 설정함에 따라 내부의 double형 데이터 변수 data[16][16]가 생성됩니다.



추가된 Terrain 객체에 javascript 또는 lua script를 이용하여 데이터베이스 tag의 값을 그래픽 객체의 디스플레이 객체에 전달하여 실시간 데이터를 디스플레이 하기 위해서 아래 예시 코드와 같이 memcpy() 함수를 이용합니다. memcpy() 함수를 이용하지 않고 개별적인 인터페이스는 

data[0][0] = @CORE.display[0][0];

data[0][1] = @CORE.display[0][1]; ... 와 같이 코드를 작성할 수 있습니다.


* memcpy함수 사용시 변수의 타입과 변수 사이즈 입력에 주의하여야 한다. 잘못된 인자의 사용으로 인한 메모리 릭 또는 비정상 종료가 발생할 수 있습니다.    


ex) lua script

function _ontaskview()

--TODO Add your lua script code here

memcpy(&data[0][0],&@CORE.display[0][0],16*16)

end

ex) javascript

function _ontaskview()

{

//TODO Add your javascript code here

memcpy(&data[0][0],&@CORE.display[0][0],16*16);

}



2D data visualization


앞 강좌에서 기초객체의 속성값을 이용하여 2D 그래픽에 가시화하는 방법에 소개하였습니다. 간략히 살펴보면 추가된 객체를 선택하고 ontaskview의 함수를 추가합니다. enuSpace는 javascript와 lua script를 지원하며 각각의 예시는 아래와 같습니다.


function _ontaskview()

{

//TODO Add your javascript code here

textContent = @CORE.display[0][0];

}

function _ontaskview()

--TODO Add your lua script code here

text = string.format("%f", @CORE.display[0][0])

end


데이터베이스의 tag 값을 가져오기 위해서는 데이터베이스 tag id를 이용합니다. 데이터베이스 변수는 첫문자에 @문자를 포함합니다. 



데이터베이스의 값을 가져와 Text 객체의 값으로 할당하는 예시 화면.

사각형의 객체를 가져와 연산 결과를 높이값으로 표현하기 위해서 아래와 같이 코드를 추가합니다.


function _ontaskview()

{

//TODO Add your javascript code here

height = @CORE.display[0][15]*50;

}



시뮬레이션 상태값 저장 및 복원 (Snap, Reset) 기능


enuSpace 시뮬레이션 기능은 현재 설정된 상태값을 저장하고 저장된 상태값에 대한 복원 기능을 제공합니다. 상단의 리본메뉴 Home->Condition의 Snap 버튼과 Reset 버튼을 이용합니다. 


다음 강좌에서는 Trend 객체와 히스토리 팝업 Trend의 기능 및 사용방법에 알아보겠습니다.

-이엔유 주식회사- 

enuSpace를 이용한 LOGIC 라이브러리 생성 및 적용 방법


본 강좌에서는 로직 라이브러리 생성 방법과 생성된 로직을 이용하여 프로그래밍 방법에 대하여 설명합니다.

강좌샘플 : lesson3.zip


동영상 미리보기



New Project

새로운 프로젝트를 생성하기 위해서 Home->New->New Project메뉴를 선택합니다.


New Project (popup window)윈도우가 나타나면, 솔루션 이름과 솔루션을 저장할 디렉토리를 설정후 OK 버튼을 클릭합니다.


New Logic library

Project Explorer->Library->Logic 아이템을 선택후 마우스 오른쪽 버튼을 클릭하여 팝업메뉴를 호출합니다. 팝업메뉴 Add New Hmi Library를 선택하여 라이브러리 이름을 입력합니다.

두개의 입력을 받아서 더하기 연산을 수행하는 ADD 로직 라이브러를 생성하기 위해서, Project Explorer에 추가된 logic_library.svg 파일을 선택, 팝업메뉴 Add Symbol을 선택하여 심볼의 이름을 ADD로 입력하고 New 버튼을 클릭합니다.


추가된 ADD 라이브러리를 선택하고 디자인을 수행합니다. 간단하게 사각형 객체와 Path 객체를 추가후

Ribbon Menu->Home->Connection Pin을 선택후 Graphic 윈도우에 마우스를 클릭하여 Connection Pin 객체를 생성합니다. 두개의 입력과 하나의 출력 핀을 생성하여 배치를 수행합니다.

배치를 모두 마치고나면, 각 핀의 이름을 설정합니다. 설정된 입력핀은 스크립트에서 사용되는 변수명으로 사용됩니다.

입력 핀과 출력 핀의 색상을 바꾸어 직관적 이해가 가능하도록 구성합니다.

위와 같이 입출력핀 구성을 마무리 하였다면, 라이브러리에 로직용 스크립트를 추가합니다. 라이브러리의 멤버함수 ontask() 함수를 추가합니다.

function _ontask()

--TODO Add your lua script code here

output = input1 + input2

end

이로써 더하기 연산을 수행하는 ADD 로직 라이브러리가 완성되었습니다. 추가적인 디자인과 현재값을 현시하는 라벨을 추가하거나 다양한 표현을 추가적으로 구성할 수 있습니다. 


Using Logic Library in picture

앞에서 제작한 로직 라이브러리를 이용하여 로직화면을 구성하도록 하겠습니다.

Project Explorer의 Picture를 선택후 오른쪽 버튼을 클릭하여 New Picture file 다이얼로그를 호출합니다. filename을 sample을 일력하여 새로운 픽쳐파일을 생성합니다.

Logic 라이브러리 창을 클릭후 앞에서 생성한 라이브러리를 선택후 Drag & Drop으로 객체를 생성합니다.

로직을 연산을 수행하기 위해서 Ribbon Menu->Home->Script operation의 Run 버튼을 클릭하여 기동을 수행합니다. 

추가된 객체를 마우스를 이용하여 더블 클릭하면, 로직의 입출력 테이블이 나타납니다. 테이블의 값 부분을 더블 클릭하여 입력값을 수정합니다.

입력값에 따라서 변경되는 것을 확인할 수 있습니다. 

아래 그림과 같이 로직 객체를 추가하여 Ribbon menu의 Home->Transfer 메뉴를 이용하여 객체간에 연결을 수행합니다.

테이블의 입력값을 조정하여 로직을 연산결과를 확인할 수 있습니다.

팝업 테이블의 변수리스트를 다중 선택하여 팝업 TREND로 데이터를 확인할 수 있습니다. 

Trend의 활용법은 별도의 강좌에서 설명하도록 하겠습니다.


다음 강좌에서는 logic객체의 변수값을 hmi객체에 값을 적용하는 응용에 대하여 알아보도록 하겠습니다.

-이엔유 주식회사-


enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법 (2/2)


본 강좌에서는 다이나틱 데이터 디스플레이를 HMI Panel 라이브러리 제작하는 과정을 포함하고 있습니다.

enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법(1/2)


강좌샘플 : lesson2.zip


enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법(1/2)절에 이어서 심볼의 사이즈 조정인자와 심볼의 색상, 라벨의 색상값을 설정할 수 있는 인터페이스를 추가합니다.


Project Explorer에서 LABEL_VALUE를 선택후 Properties창에서 Variable Window를 선택합니다. 다음과 같이 4개의 변수를 추가합니다.

double m_width;                // 라이브러리 폭 조정인자

double m_height;               // 라이브러리 높이 조정인자

wchar m_backcolor;            // 라이브러리 패널 색상 조정인자

wchar m_labelcolor;            // 라이브러리 라벨 색상 조정인자


라이브러리에 추가된 멤버변수는 onload() 함수를 통하여 연계를 수행합니다. onload() 함수는 객체가 초기에 로드시 호출되며, 멤버변수의 속성을 변경 수행시 호출되는 함수입니다.

추가된  코드 내용을 보면 아래와 같습니다.

function _onload()

{

//TODO Add your javascript code here

ID_PANEL.width = ID_PANEL.translate_x + m_width;

ID_PANEL.height = ID_PANEL.translate_y + m_height;

ID_PANEL.fill = m_backcolor;

ID_LABEL.stroke = m_labelcolor;

ID_LABEL.translate_x = ID_PANEL.width/2;

ID_LABEL.translate_y = ID_PANEL.height - ID_PANEL.height/5;

}

ID_PANEL의 폭값은 ID_PANEL의 위치 이동값과 사용자가 업데이트한 또는 초기화된 값의 합으로 설정되며, 높이 또한 동일한 연산을 통하여 ID_PANEL의 사이즈롤 조정합니다. 

또한, 패널의 내부 색상값은 멤버변수 m_backcolor값과 라벨의 폰트 색상은 m_labelcolor의 값을 이용하여 연계됩니다. 

패널의 사이즈 조정시 라벨의 위치값도 조정을 해주어야 합니다. 라벨의 속성중 text_anchor의 값은 middle로 설정되어 있기 때문에 폭의 중간값으로 설정하고 높이는 패널 높이의 4/5위치에 배치시켰다.


코드를 Compile 버튼을 클릭후 이전장에서 추가한 Project Explorer의 Picture의 sample.svg 파일을 오픈한다. 오픈을 수행하면 이전에 생성된 객체의 속성을 유지하고 있기 때문에 재로딩을 수행한다. 단축키 F5 버튼을 누르면 픽쳐페이지를 재로딩을 수행합니다. 수정한 라이브러리의 속성이 나타납니다.


sample.svg 픽쳐에 여러개의 LABEL_VALUE객체를 추가하여 각 객체의 멤버변수의 값을 조정하여 테스트를 합니다. 색상값을 입력할 경우 rgb(20,20,20) 형태로 입력합니다.

라이브러리의 속성값 변경에 따른 디스플레이


LABEL_VALUE 라이브러리에 패널의 외곽선 색상, 폰트의 사이즈에 대한 인터페이스도 추가하여 완성도 높은  라이브러리를 작성해 보세요.


다음 강좌에서는 로직 라이브러리 생성 및 적용방법에 대하여 알아보도록 하겠습니다.

-이엔유 주식회사-

SVG와 JavaScript를 이용한 다이나믹 심볼 제작 (온도 Gauge)


라이브러리 생성

엔유스페이스를 실행하고 Project Explorer에서 Library하위에서 Logic선택후 Add New logic Library를 선택합니다. 라이브러리 파일이름을 입력후 Create를 수행하면, 새로운 로직파일이 생성됩니다.

생성된 파일을 선택후 팝업메뉴를 이용하여 Add Node를 통하여 새로운 심볼을 생성합니다. 생성된 심볼을 디자인합니다. 디자인 객체를 이용하여 아래 그림과 같이 디자인을 수행합니다. 

각각의 객체의 속성에 id를 위 그림과 같이 설정합니다. 핀객체에 대해서는 name의 속성값을 설정합니다. 핀객체는 로직블럭과 로직블럭간의 연결선을 이용하여 연결이 가능합니다. 연결선을 이용하여 핀객체 연결시 데이터 전송 역할을 수행합니다.


심볼의 자체에 이벤트 함수를 등록합니다. _ontask()함수에 아래의 코드를 추가합니다. 입력핀의 객체 변수값을 출력핀의 객체 변수값으로 할당하는 코드입니다.

function _ontask()

--TODO Add your lua script code here

output = input

end

심볼에 입력데이터의 min, max를 정의하는 변수를 추가합니다. 

float min = 0

float max = 100

다음으로 ID_GAGUE객체를 선택하고 이벤트함수 _ontaskview()함수를 추가합니다. 이때 추가할 스크립트는 JavaScript를 이용하여 추가합니다. JavaScript를 이용하는 경우에는 웹 현시에 있어 동일한 스크립트가 동작되어 수행됩니다.

function _ontaskview()

{

//TODO Add your javascript code here

var datagap = max-min;


var data = output;

if (data < min)

data = min;

else if (data >max)

data = max;


var h = (43 * (data-min)) / (max - min);

ID_GAUGE.height = h;


ID_LABEL_VALUE.textContent = output.toString();

ID_LABEL_MIN.textContent = min.toString();

ID_LABEL_MAX.textContent = max.toString();

}

위 코드를 간단하게 보면, 출력 데이터의 값이 심볼변수를 설정한 min, max의 범위안에서 처리가 되도록 조건을 걸어줍니다. 다음으로 ID_GAUGE의 초기 Height값 43을 기준으로 출력 데이터의 실제 게이지의 높이값을 계산하여, ID_GAUGE객체의 높이값으로 치환합니다.

ID_LABEL_VALUE, ID_LABEL_MIN, ID_LABEL_MAX의 값 현시를 위한 코드를 추가합니다. 이와같은 방법으로 SVG 그래픽 과 JavaScript 코드를 이용하여 다양한 그래픽 심볼 라이브러리를 생성할 수 있습니다. 


화면 드로잉

생성된 라이브러리를 이용하여 픽쳐페이지에 적용합니다. Project Explorer에서 Picture를 선택후 Add New Picture Item 메뉴를 선택하여 픽쳐페이지를 생성합니다.

생성된 픽쳐페이지에 생성한 라이브러리를 마우스를 이용하여 드래그 & 드랍으로 객체를 생성합니다. 선택객체를 더블클릭하여 Value Table의 입력값을 조정하여 정상적으로 라이브러리가 생성되었는지 확인합니다.

입력값을 50으로 설정시 게이지바의 위치가 50의 위치하였음을 확인할 수 있습니다.

리본 메뉴의 Data/Communication에서 웹서버 기동 메뉴를 클릭하여, 웹서버를 기동한 후 웹브라우져를 통하여 제작한 픽쳐페이지가 정상적으로 현시되는지 확인합니다. 


다양한 형태의 게이지를 생성하여, 아래 그림과 같이 적용 및 활용할 수 있습니다.

enuSpace for Mars(2017)은 HMI/SCADA/DCS/IoT분야에 강력한 기능을 활용하여 적용할 수 있습니다. 


본 기술개발의 일부는 중소기업청의 창업기술개발사업의 일환으로 수행된 결과입니다.


+ Recent posts