Solving XOR with a Neural Network in enuSpace-TensorFlow


모델 비교 동영상

Model 1



Cost 계산 Algorithm


Sigmoid 출력값

Cost 출력 값



Model 2



Cost 계산 Algorithm


Sigmoid 값


Cost 값

SoftmaxCrossEntropyWidthLogits - Batch Size 10개, Train 20회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 87.72%




SoftmaxCrossEntropyWidthLogits - Batch Size 100개, Train 20회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 87.73%



Weight 3차원 결과값 (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 100개, Train 100회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 83.25%



Weight 3차원 결과값 (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 1000개, Train 20회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 89.04%




Weight 3차원 결과값  (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 1000개, Train 100회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 88.03%




Weight 3차원 결과값  (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 10000개, Train 20회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 90.63%




Weight 3차원 결과값 (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 10000개, Train 100회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 90.69%




Weight 3차원 결과값 (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 55000개, Train 20회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.001 

정확도 : 80.57%




Weight 3차원 결과값 (Range -1 ~ 1)




SoftmaxCrossEntropyWidthLogits - Batch Size 55000개, Train 100회 결과 (DataSet : 55000,개 TestSet : 10000개)  learning rate = 0.001 

정확도 : 84.06%




Weight 3차원 결과값 (Range -1 ~ 1)



SoftmaxCrossEntropyWidthLogits - Batch Size 55000개, Train 1000회 결과 (DataSet : 55000,개 TestSet : 10000개) learning rate = 0.000001 

정확도 : 90.20%



cost value : 0.75




Weight 3차원 결과값 (Range -1 ~ 1)



Weight 3차원 결과값 (Range -0.2 ~ 0.2)



SoftmaxCrossEntropyWidthLogits - Batch Size 10000개, Train 500회 결과 (DataSet : 50000,개 TestSet : 10000개) learning rate = 0.0001 

정확도 : 91.60%




Weight 3차원 결과값 (Range -1 ~ 1)






MNIST linear regression


MNIST dataset을 이용하여 linear regression 알고리즘을 enuSpace-Tensorflow를 이용한 사용 방법을 설명합니다.



Python를 이용한 구현

참고 : http://www.xiaoliangbai.com/2017/02/01/tensorflow-applying-linear-regression-on-mnist-dataset

import sys
import time
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data
%matplotlib inline

%load_ext autoreload
%autoreload 2

MNIST = input_data.read_data_sets("MNIST_data", one_hot=True)

# Define parameters for linear model
learning_rate = 0.01
batch_size = 128
n_epochs = 25

# Create placeholders
X = tf.placeholder(tf.float32, [batch_size, 784], name="image")
Y = tf.placeholder(tf.float32, [batch_size, 10], name="label")

# Create weights and bias
w = tf.Variable(tf.random_normal(shape=[784, 10], stddev=0.01), name="weights")
b = tf.Variable(tf.zeros([1,10]), name='bias')

# calculate scores
logits = tf.matmul(X, w) + b

# Entropy cost function and loss
entropy = tf.nn.softmax_cross_entropy_with_logits(logits, Y)
loss = tf.reduce_mean(entropy)

# Define optimizer
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(loss)

# Run optimization and test
loss_history = []
acc_history = []
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    n_batches = int(MNIST.train.num_examples/batch_size)
    for i in range(n_epochs):
        for _ in range(n_batches):
            X_batch, Y_batch = MNIST.train.next_batch(batch_size)
            _, loss_value = sess.run([optimizer, loss], feed_dict={X: X_batch, Y:Y_batch})
        loss_history.append(loss_value)

        # Check validation accuracy    
        n_v_batches = int(MNIST.validation.num_examples/batch_size)
        total_correct_preds = 0
        for j in range(n_v_batches):
            X_batch, Y_batch = MNIST.validation.next_batch(batch_size)
            _, loss_batch, logits_batch = sess.run([optimizer, loss, logits], feed_dict={X: X_batch, Y:Y_batch})
            preds = tf.nn.softmax(logits_batch)
            correct_preds = tf.equal(tf.argmax(preds, 1), tf.argmax(Y_batch, 1))
            accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32))
            total_correct_preds += sess.run(accuracy)
        validation_accuracy = total_correct_preds/MNIST.validation.num_examples
        acc_history.append(validation_accuracy)


    # Test the model
    n_batches = int(MNIST.test.num_examples/batch_size)
    total_correct_preds = 0
    for i in range(n_batches):
        X_batch, Y_batch = MNIST.test.next_batch(batch_size)
        logits_batch = sess.run(logits, feed_dict={X: X_batch, Y:Y_batch})
        preds = tf.nn.softmax(logits_batch)
        correct_preds = tf.equal(tf.argmax(preds, 1), tf.argmax(Y_batch, 1))
        accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32))
        total_correct_preds += sess.run(accuracy)

    print "Test accuracy is {0}".format(total_correct_preds/MNIST.test.num_examples)

enuSpace-Tensorflow를 이용한 구현

Training model 1 (SoftmaxCrossEntropyWidthLogits)

아래 그리픽 모델은 SoftmaxCrossEntropyWidthLogits 객체를 이용하여 그래픽 블럭을 이용하여 각 객체의 핀정보에 대하여 연결선을 수행한 화면이다.

Training model (Subtract)

아래 그래픽 모델은 Subtract객체를 이용하여 그래픽 블럭을 이용하여 각 객체의 핀정보에 대하여 연결선을 수행한 화면이다.

각 블럭별 기능 설명

데이터 셋 불러오기

각 블럭중 데이터셋을 불러와 전달을 수행하기 위한 FIFOQueue , FIFOEnqueue를 활용한다. 한번에 불러올 이미지의 배치 사이즈를 설정한다. 본 모델은 100개를 적용하였다.

Cost값 Gradient

불러온 이미지 데이터 셋을 이용하여 Weight변수와 Bias변수를 생성하여 Training 수행


Traing 결과 저장

Training을 특정 개수에 도달하면, Weight와 Bias의 텐서값을 저장하기 위하여 아래그림과 같이 구성하였다.

Evaluation Model

앞에서 저장된 Weight, Bias의 값을 이용하여 평가를 수행하는 모델이다.

평가용 dataset 가져오기

평가를 수행하기 위해서 평가용 데이터셋의 파일 위치를 지정하여 매 실행마다 불러오기를 수행한다.

Train 결과값 불러오기

앞 Training Model에서 저장한 Weight, Bias 텐서값을 불러오는 불럭이다.

평가하기

평가용 데이터셋과 Weight, bias값을 불러왔다면 평가를 수행한다.

평가 결과 출력하기

평가 결과를 출력하기 위하여 Counter와 판정결과값을 확인하기 블럭을 구성하였다.

3차원 Weight값 실시간 디스플레이

Training 과정을 확인하기 위해서 Weight값을 3차원으로 확인하기 위한 픽쳐를 생성하여 실시간 변화정보에 대하여 확인한다.

SoftmaxCrossEntropyWidthLogits 이용한 모델 결과

Subtract 이용한 모델 결과.




Gradient Descent


Gradient Descent 알고리즘을 enuSpace-Tensorflow를 이용하여 실행 결과입니다.


enuSpace-Tensorflow는 C++ 기반의 API를 이용하여 그래픽 블럭으로 구성되었습니다. Tensorflow의 C++ API를 이용하여 구현하시는 분은 아래링크를 참고하세요.

API 가이드 : https://expnuni.gitbooks.io/enuspacetensorflow/content/


참고 : https://hunkim.github.io/ml/ (모두를 위한 머신러닝/딥러닝 강의)

참고 : https://medium.com/@peteryun/ml-%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-tensorflow-3-gradient-descent-algorithm-%EA%B8%B0%EB%B3%B8-c0688208fc59

Python를 이용한 구현

import tensorflow as tf

x_data = [1., 2., 3.]
y_data = [1., 2., 3.]

W = tf.Variable(tf.random_uniform([1],-10.0, 10.0))

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

hyphothesis = W * X

cost = tf.reduce_mean(tf.square(hyphothesis - Y))

descent = W - tf.mul( 0.1, tf.reduce_mean(tf.mul( (tf.mul(W,X)-Y), X ) ))

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

for step in range(20):
    sess.run(W.assign(descent), feed_dict={X:x_data, Y:y_data})
    print( step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W))

enuSpace-Tensorflow를 이용한 구현

Tensorflow의 그래픽 컴포넌트를 이용하여 위와 동일한 코드를 그래픽 컴포넌트를 이용하여 로직을 구성하여 실행한 결과는 아래 그림과 같다. 

X의 초기값에 {1.0f, 2.0f, 3.0f} 입력시 출력 Y {1.0f, 2.0f, 3.0f}에 해당하는 W값을 구현하는 로직이다.

자세한 알고리즘에 대한 설명은 https://hunkim.github.io/ml/ (모두를 위한 머신러닝/딥러닝 강의)를 참고하시기 바랍니다.

ApplyGradientDescent 블럭을 이용한 구현 예시

ApplyGradientDescent Equation (var = var - alpha*delta)


Multi Variable Linear regression 구현 예시

아래의 테이블의 값을 이용하여 W, b의 찾기 위한 그래픽 블럭을 구성하여 예상된 가중치와 바이어스값을 확인.

X1X2X3Y
152179
151222110
351323135
44524171
51553199
6447120
121727132
62028135

미리계산된 W, Bias 값 (W1 = 1, W2 = 2, W3= 3, Bias = 5)

Hypothesis Using matrix

H(x1, x2, x3) = x1w1 + x2w2 + x3w3

Multi variable Python 코드 구현예시

x_data = [[1., 5., 21.], [15., 12., 22.],
         [35., 13., 23.], [4., 45., 24.], [5., 15., 53.],
         [6., 44., 7.], [12., 17., 27.], [6., 20., 28.]]
y_data = [[79.], [110.], [135.], [171.], [199.], [120.], [132.], [135.]]


# placeholders for a tensor that will be always fed.
X = tf.placeholder(tf.float32, shape=[None, 3])
Y = tf.placeholder(tf.float32, shape=[None, 1])

W = tf.Variable(tf.random_normal([3, 1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')

# Hypothesis
hypothesis = tf.matmul(X, W) + b

그랙픽 블럭 구성 및 실행 결과


W1, W2, W3의 값이 1, 2, 3의 값으로 수렴, Bias 값 5로 수렴

초기값 설정

X = {{1,5,21},{15,12,22},{35,13,23},{4,45,24},{5,15,53},{6,44,7},{12,17,27},{6,20,28}}

Y = {{79 },{110},{135},{171},{199},{120},{132},{135}}

W 초기값 = {{1.5,3.5,0.5}}

b 초기값 = {{0.5}}

ApplyGradientDescent alpha 값 = 0.001



enuSpace for jupiter 개발 이야기

  • enuSpace for jupiter deep learning(tensorflow) plugin project 오픈소스 생성


tensorflow 버젼 : r1.2

enuSpace for jupiter 버젼에서는 외부 모듈과 연동하기 위한 plugin 기능이 추가됩니다.

Deep learning 오픈 플랫폼 tensorflow와 연동하기 위한 공개 소프트웨어 저장소를 생성하였습니다.

Project 주소(github) : https://github.com/EXPNUNI/enuSpaceTensorflow


Tensorflow C++ API Guide

#include "tensorflow/cc/client/client_session.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include "tensorflow/core/framework/tensor.h"

int main() 
{
  using namespace tensorflow;
  using namespace tensorflow::ops;
  Scope root = Scope::NewRootScope();

  // Matrix A = [3 2; -1 0]
  auto A = Const(root, { {3.f, 2.f}, {-1.f, 0.f}});
  
  // Vector b = [3 5]
  auto b = Const(root, { {3.f, 5.f}});
  
  // v = Ab^T
  auto v = MatMul(root.WithOpName("v"), A, b, MatMul::TransposeB(true));
  std::vector outputs;
  ClientSession session(root);
  
  // Run and fetch v
  TF_CHECK_OK(session.Run({v}, &outputs));
  
  // Expect outputs[0] == [19; -3]
  LOG(INFO) << outputs[0].matrix();
  return 0;
}

위와 같이 C++를 이용하여 Tensorflow 코드를 짜야 했던 내용을 enuSpace에서 아래 그림과 같이 로직 블럭을 drag & drop으로 구성하고 연결선을 이용하여 코드를 제작합니다. 

위 프로그램은 실제 Const 입력값에 따라서 MatMul 블럭의 Operation을 수행하여 연산 결과를 출력하는 동작 화면입니다. 

현재단계는 Tensorflow와 메모리 연동에 대한 소프트웨어 설계 및 기초 구현이 되었습니다. 

enuSpace for jupiter 버젼의 진화과정을 github에서 확인하실 수 있습니다. 많은 관심 부탁드립니다.

https://github.com/EXPNUNI/enuSpaceTensorflow


-이엔유 주식회사 developer team - 


Trend(차트) 객체와 히스토리 Popup Trend(팝업 차트) 사용방법


본 강좌에서는 Trend(이하 차트)객체의 속성 및 사용방법에 대하여 설명합니다. 주의사항은 사용방법에 대해 설명하면서 알려드리고 본문 마지막에 표로 정리해 놓겠습니다.

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


Lesson6 project sample: lesson6.zip


enuspace for mars에서 차트의 사용법은 크게 3가지가 있습니다. 본 튜토리얼에서는 3가지와 팝업 차트까지 설명하도록 하겠습니다. 

1. 정적 데이터를 이용한 차트 객체 표현

2. 동적 데이터를 이용한 차트 객체 표현

3. 차트 객체를 Logic객체로 만들어서 사용하기

enuspace for mars에서 차트는 기본적으로 실시간 차트입니다. 이를 라인 차트로 변경하려면 몇가지 설정을 해줘야 합니다.

설정법은 정적 차트 설명 하는 부분에서 알려드리도록 하겠습니다.


우선 차트를 그리기 위한 프로젝트를 하나 생성합니다.

프로젝트 생성은 프로젝트 만들기 튜토리얼을 참조하시길 바랍니다.

프로젝트 생성이 완료 되었다면 Project Explorer에서 Picture폴더에 trend라는 svg파일을 하나 생성합니다.


그리고 리본메뉴에서 차트(Home->Chart)를 선택하고 에디트화면에 생성합니다.


위 화면이 차트를 처음 생성했을 때 나타나는 화면입니다.

여기까지 하셨으면 차트를 사용하기 위한 기본작업이 완료되었습니다.

차트와 차트의 컴포넌트 속성은 다음과 같습니다.


1. 정적으로 차트 사용하기

정적 차트(라인 차트)로 사용하기 위해서 몇가지 속성을 변경해야 합니다. 우선 위에서 생성한 차트를 선택하고 오른쪽에 속성창을 살펴봅니다.

클릭하시면 원본크기로 볼 수 있습니다.

위의 속성창에서 아래 세가지 속성을 변경해줍니다.

trend-flow = off

xview-max = 300

auto-scale = off

속성을 변경 했다면 아래와 같은 그림이 나옵니다.

이제 마우스로 차트를 선택 합니다. 선택하면 상단에 리본메뉴가 아래와 같이 바뀌어 있는것을 볼 수 있습니다. 

리본메뉴에 대해 잠깐 설명 하자면 Add Chart Element는 차트안에 있는 컴포넌트들(범례, 제목, 그래프, x축, y축)의 visible 속성을 뜻합니다.
Drawing 카테고리에 있는 메뉴들은 모두 차트 배경에 관한 속성입니다. 
Add Data항목은 차트의 series를 설정 하는 곳으로 series를 추가, 삭제, 속성 변경 등을 할 수 있습니다.

우리는 series를 추가해야 하니  Add Data를 선택 합니다.

Add Data항목을 선택 했을 때 나오는 창입니다.

위 창에서 Add 버튼을 클릭하여 series를 하나 추가합니다. 그리고 추가된 series를 선택하여 오른쪽에 series에 대한 속성을 띄웁니다.

series에 관한 속성은 다음과 같습니다.


정적 데이터의 데이터 포맷은 x,y x,y 입니다. 예) 50,300 100,250 150,400 200,150 250,500

위의 예를 series2의 data속성에 넣으면 다음과 같은 화면이 나옵니다.

현재 정적 차트에서 사용할 수 있는 타입은 line(선)과 scatter(점) 차트입니다. 그리고 두가지 타입은 하나의 차트에 나타낼 수 있습니다.

2. 동적 차트 사용하기

동적 차트를 사용하기 위해서 우선 값이 변하는 지역변수를 만들어 보겠습니다.

Project Explorer에서 picture폴더에 파일을 하나 더 생성합니다.

생성된 picture파일 화면에서 배경을 클릭하시고 오른쪽 속성창을 확인합니다. 속성창의 윗 부분에 4개의 아이콘이 있는 것을 확인할 수 있습니다. 이 중에서 V모양의 아이콘을 클릭합니다.

그러면 아래와 같은 창이 나옵니다.

여기서 picture파일의 지역변수를 생성할 수 있습니다. 생성 방법은 다음과 같습니다.

1) New라고 표시된 속성에서 드롭다운 메뉴의 <Add Variable>항목을 선택한다.

2) 변수 생성창에서 변수의 타입(필수), 이름(필수), 시작 값(필수), 설명(선택)을 입력하고 Accept버튼을 클릭합니다.


생성 완료된 화면

변수가 생성 되었다면 변수 값을 속성창의 4개 아이콘중 번개 모양의 아이콘을 선택하여 아래와 같은 창을 띄웁니다.

 위의 창에서 Script Type의 type속성을 text/javascript로 변경하고, ontaskview항목을 추가해줍니다.

스크립트 편집 창이 뜨면 다음과 같이 입력합니다.

(생성했던 변수이름) = Math.floor(Math.random() * 500);

입력을 완료하고 Compile 버튼이나 Accept버튼을 클릭하여 스크립트를 등록 하여 줍니다.

여기까지 완료하셨으면 값이 변화 하는지 확인해봅니다.

이제 picture화면에 차트를 새로 생성합니다. 차트가 생성되면 상단 리본메뉴의 Add Data항목을 열어 줍니다.

series1의 속성에서 variable 속성에 위에서 생성한 변수의 이름을 넣어 줍니다. (※주의 : 변수의 이름이 틀리면 값이 들어오지 않거나 원하는 변수의 값이 들어오지 않을 수 있습니다.)

여기까지 완료하면 상단 리본메뉴에서 Home->Run을 클릭하여 스크립트를 실행하여 줍니다. 차트의 그래프가 그려지는지 확인합니다.

그래프가 너무 촘촘히 나온다면 차트의 duration값을 60 또는 120으로 설정하시면 됩니다.

3. 차트 객체를 Logic객체로 만들어서 사용하기

Logic 파일 생성과 Logic객체 이용방법은 LOGIC 프로그래밍, HMI라이브러리 인터페이스 방법에서 확인 하시기 바랍니다.

우선 Project Explorer에서 Logic라이브러리 파일을 생성하고, Logic Node를 생성합니다.

시작과정을 모두 완료한 상태

먼저 리본메뉴의 Home->Connection Pin을 생성합니다. Pin의 속성을 다음과 같이 설정합니다.

name = input
var-type = double

설정이 완료되면 차트를 생성하여 속성을 변경해 줍니다.

title-visible = hidden
legend-visible = hidden
xaxis-visible = hidden
yaxis-visible = hidden
fill-opacity = 0
duration = 30
auto-scale = off

위와 같이 모두 변경 하였다면 차트의 크기를 줄여줍니다(줄이지 않으셔도 무방합니다.). 대략 밑의 그림 정도로 줄여 주시면 됩니다.

이제 차트를 선택클릭하고 리본메뉴의 Add Data항목을 클릭하여 series속성변경 창을 열고 속성을 다음과같이 변경합니다.

variable = pin의 이름(name속성)

위 과정을 모두 완료 한뒤 라이브러리를 저장해 줍니다.

2번에서 만들었던 picture를 열어줍니다.

여기에 방금 만든 Logic차트를 생성하여 줍니다.

생성이 완료되면 Logic차트에 ID값을 입력하여 줍니다. 입력이 완료 되면 배경을 클릭하고 스크립트를 편집합니다.

위 과정이 모두 완료 되면 리본 메뉴의 Run을 눌러 동작하는지 확인합니다.


■ 팝업 차트 사용하기

팝업 차트를 사용하기 위해서는 두가지 방법이 있습니다.

1. DB에 등록된 변수를 이용하여 팝업 차트로 보기

2. 현재 생성되어 있는 Logic객체의 데이터를 이용하여 팝업차트 이용하기

3. Logic객체의 데이터를 모아서 팝업차트 만들기

주의 할 점은 2번 방법의 경우 Logic객체에 Pin객체나 지역변수가 생성되어 있어야 합니다.

3번 방법은 여러개의 데이터를 한데 묶어서 볼 수 있다는 장점이 있습니다.


1. DB에 등록된 변수를 이용하기

우선 DB에 변수를 등록 해야합니다. 위에서 우리가 만들어놓은 지역변수를 등록하여 팝업차트를 만들어 봅시다.

먼저 리본메뉴의 Data/Communcation탭으로 이동합니다. 그리고 DB Show라는 버튼을 클릭합니다.

DB TABLE 다이얼로그가 나타나면 상단의 DB그림에 G가 써져있는 버튼을 클릭합니다. 그 뒤 나타나는 창의 내용은
"해당 버튼을 누르고 계속 진행하면 기존에 생성되어 있던 데이터들이 모두 지워집니다. 그리고 글로벌 변수와 로직 객체의 변수들을 데이터 베이스에 재생성합니다. 계속하시겠습니까?" 라는 내용입니다.


여러분은 처음 생성하는 것일테니 아마도 전부 비어있을 겁니다. 그러므로 걱정하지 마시고 예를 눌러주시면 됩니다.

지금까지 제대로 따라오셨다면 아래와 같은 화면이 나타납니다. DB TABLE창을 닫지 않고, 리본메뉴에서 Run버튼을 눌러 변수의 값을 변화 시켜 줍니다.

DB TABLE창에서 팝업차트에서 보고 싶은 변수를 오른쪽 클릭하거나 'Ctrl+클릭' 또는 'Shift+클릭' 또는 '드래그'로 다중선택 하여 오른쪽위의 버튼을 클릭합니다.

생성된 팝업 차트를 확인합니다.


2. 현재 생성되어 있는 Logic객체의 데이터를 이용하여 팝업차트 이용하기

다시 picture 화면으로 돌아가서 Logic차트를 더블 클릭합니다.


아래와 같은 창이 나타나면 


팝업 차트로 보고싶은 변수를 마우스 오른클릭하여 팝업 차트를 실행합니다.

3. Logic객체의 데이터를 모아서 팝업차트 만들기

데이터를 한데 모아 사용하기 위해서 테이블 기능을 이용합니다. 리본메뉴의 Presentation->New Table버튼을 클릭합니다.

위와 같은 창이 나오면 Logic차트를 더블 클릭하여 아래와 같은 창을 다시 엽니다.

Table 창과 Logic변수 창이 모두 띄워져 있으면 Logic변수 창의 변수를 마우스 오른쪽 클릭하여 Add Monitor Paramiter를 선택합니다.

그리고 Table 창에 해당 변수가 추가되었는지 확인합니다.
※변수는 하나의 객체에서 여러 개를 추가할 수 있고, 다른 Logic객체에서도 추가할 수 있습니다.

여기서 팝업 차트를 띄우기 위해서 변수의 왼쪽에 체크박스를 체크 해줍니다.
※선택해야할 변수가 여러개라면 모두 체크해줍니다.

이후 Show Trend 버튼을 클릭합니다. (그리고 Run상태가 아닐경우 Run버튼을 클릭해줍니다.)

팝업 차트가 정상적으로 돌아가는지 확인합니다.


Web 연동 및 사용방법


본 강좌에서는 enuSpace를 이용하여 웹 브라우져에 화면 디스플레이 및 데이터 인터페이스를 구성하는 방법에 대하여 설명합니다.

enuSpace for mars 다운로드 : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


enuSpace는 javascript와 lua script를 제공합니다. 웹 브라우져에서 동적인 현시를 위해서 javascript로 제작합니다.

enuSpace의 내부 구조와 웹 브라우져 랜더러간의 인터페이스 구조는 아래그림과 같습니다.



enuSpace에서 task scheduler는 lua 스크립트로 구현된 ontask()함수를 설정된 주기에 맞추어 호출되어 연산을 수행합니다. 또한, 뷰어가 드로잉시에 호출되는 ontaskview()함수는 루아스크립트와 자바스크립트 모두 이용할 수 있습니다. 웹 브라우져에서 랜더러의 함수 호출시에는 자바스크립트로 적용된 ontaskview()함수만 적용됩니다. 


웹 브라우져는 첫 기동시 서버측에 그래픽 리소스 svg 파일을 요청하며 관련 데이터를 연동합니다. 웹 브라우져는 내부 랜더러에서 서버 사이드에서 가져온 데이터와 ontaskview()함수를 호출하여 자신의 화면을 갱신합니다. 특정값을 제어하기 위해서 SetTagValue() 함수를 호출하여 서버사이드의 값을 제어합니다.  


enuSpace introduce의 설명


enuSpace for mars의 최신 버젼을 다운로드 하시면, 샘플 프로젝트 introduce를 오픈합니다. 


리본메뉴 Data/Communication->Web Browser 버튼을 클릭하여 브라우져를 실행합니다.  

웹 브라우져 창에 사용자 로그인창이 나타나고, 사용자 리스트에 추가된 로그인 정보를 이용하여 로그인을 수행합니다. 



여기에서 살펴볼 내용은 서버 사이드의 로직 변수, 전역변수 그리고 데이터베이스 tag 변수들에 대한 내용과 연동되는 부분과 enuSpace와 웹 랜더러간의 독립된 표현에 대한 부분이다. 

enuSpace 편집기에서 태양주의를 돌고 있는 별을 하나 선택하여 ontaskview() 함수를 확인하여 보면 다음과 같이 구현되어 있다. 



function _ontaskview()

{

rotate = rotate - 0.3;

if (rotate<0)

rotate = 360;

fill = GetValueColor( rotate/5 );

}

선택한 path객체(star)는 자신의 회전값을 0.3씩 줄이는 코드이며 0이하로 떨어진경우에는 초기값 360도로 설정하는 코드이다. 본 코드의 내용으로는 enuSpace의 서버와 웹 브라우져간의 동일한 현시를 수행하는 코드의 처리방식이 아니다.

만약 객체의 서버사이드의 회전값과 동일한 디스플레이를 수행하고자 하는 경우에는 다음과 같이 코드를 수정하여 보자.


main.svg를 선택하고 최상단에 전역변수를 하나 설정한다. 변수명은 g_rotate_star으로 하고 double 형으로 생성한다. 




생성된 g_rotate_star변수의 값을 갱신하는 코드를 추가하여야 한다. 이미 Main features 글자 객체 왼쪽에 원객체가 추가 되어 있다. 원 객체를 선택하고 Properties 윈도우의 Event 속성을 보면 Script Type에 text/lua 설정되어 있으며, ontask()함수를 수정한다. 



다음과 같이 추가 코드를 작성한다.

     g_rotate_star = g_rotate_star - 0.3 

if (g_rotate_star<0) then 

g_rotate_star = 360 

end


다음으로 그래픽 path 객체(star)의 ontaskview()함수를 다음과 같이 수정하자.

수정 전)

function _ontaskview()

{

rotate = rotate - 0.3;

if (rotate<0)

rotate = 360;

fill = GetValueColor( rotate/5 );

}

수정 후)

function _ontaskview()

{

rotate = g_rotate_star;

fill = GetValueColor( rotate/5 );

}


수정후 전역변수의 값을 이용하여 회전값을 적용하도록 구성하였다. 


enuSpace의 기동화면 모습과 웹 브라우져에서의 랜더링 출력 위치가 동일한 위치에서 출력되고 있음을 확인할 수 있다. 위 예제는 전역변수를 이용한 인터페이스 방법에 대하여 설명한 내용이다. 전역변수, 로직객체의 pin 변수, 데이터베이스의 tag변수는 동일한 형태로 연계하여 웹 브라우져에 동일한 디스플레이가 가능합니다.  


데이터베이스 TAG 인터페이스


데이터베이스 TAG를 이용하여 인터페이스를 위하여 데이터베이스 TAG 변수 하나를 추가합니다.  

TYPE : double

TAGID : @Presentation.rotate

VARIABLE : rotate


전역변수값을 디스플레이 위한 Text 객체를 추가하고 ontaskview()함수에 디스플레이 코드를 추가합니다.

function _ontaskview()

{

//TODO Add your javascript code here

textContent = GetTagValue("@Presentation.rotate").toString();

}


사각형 객체 2개를 추가하고, 각각 데이터베이스 TAG의 값을 변경하는 코드를 추가합니다.

function _onmousedown()

{

//TODO Add your javascript code here

SetTagValue("@Presentation.rotate", 90);

}


function _onmousedown()

{

//TODO Add your javascript code here

SetTagValue("@Presentation.rotate", 45);

}



enuSpace의 RunTime에서 사각형 객체를 클릭하여 Tag값이 변경됨을 확인할 수 있으며, 클라이언트 웹 브라우져에서 사각형 객체를 클릭하여 tag값이 변경되어 디스플레이 됨을 확인할 수 있습니다.




전역변수 및 로직객체 PIN 변수의 인터페이스


enuSpace에서는 전역변수와 로직객체의 PIN 변수의 인터페이스를 위하여 SetValue(), GetValue() 함수를 제공합니다.


SetValue 함수의 사용 예)

function _onmousedown()

{

//TODO Add your javascript code here

SetValue("ID_ARD.A0", 99);

}


GetValue 함수의 사용 예)

function _ontaskview()

{

//TODO Add your javascript code here

textContent = GetValue("ID_ARD.A0").toString();

}


* GetValue의 함수는 클라이언트 웹에서 특정 이벤트에 의해서 서버의 값을 가져와 처리하는 경우에 사용하며, 일반적으로 다음과 같이 코드를 사용하기를 권고합니다. (빠른 응답 속도)

textContent = GetValue("ID_ARD.A0").toString();  => textContent = ID_ARD.A0.toString();


* SetValue의 함수 또한 클라이언트 웹에서 특정 이벤트에 의하여 서버의 값을 설정하는 경우에 사용하며, 일반적으로 다음과 같이 코드를 사용하기를 권고합니다. (빠른 응답 속도)

SetValue("ID_ARD.A0", 99); => ID_ARD.A0 = 99;


본 강좌에서는 웹 브라우져와 연동시에 사용하는 함수에 대하여 알아보았습니다. 


-이엔유 주식회사-

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의 기능 및 사용방법에 알아보겠습니다.

-이엔유 주식회사- 

LOGIC 프로그램밍, HMI라이브러리 인터페이스 방법


본 강좌에서는 로직 라이브러리를 이용하여 로직 프로그래밍을 수행하고, HMI 화면구성을 통하여 사용자 인터페이스 모니터링 및 제어화면을 구성하여 봅니다.


New Project

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

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

Import Library

기존 제작한 Logic 및 hmi 라이브러리르 가져오기 위해서, Project Explorer의 Library의 팝업메뉴 Add Existing Hmi Library 메뉴를 이용합니다.

예시로 enuSpace for mars 설치시 포함된 presentation 디렉토리의 logic 라이브러리 파일을 선택하여 가져오기를 수행합니다. 기존 라이브러리는 유지하고, 본 프로젝트의 Library 디렉토리에 파일을 복사수행 후 로드를 수행합니다.

Properties 윈도우에서 상단의 콤보박스를 이용하여 해당사하는 라이브러리의 썸네일 이미지를 확인할 수 있습니다.  

불러온 라이브러리를 편집하고자 하는 경우에는, Project Explorer의 Library에서 HMI 또는 Logic의 파일의 하위의 심볼 아이템을 선택하여 Graphic 편집알 통하여 심볼을 편집합니다. 


New Picture

Create New Picture file

2개의 픽쳐화면을 생성합니다. 하나의 화면에는 로직 프로그래밍을 위한 픽쳐 페이지이고, 로직 프로그래밍에서의 입출력 변수 변수값을 사용자에게 제공할  HMI 화면작도를 위한 픽쳐입니다.

- 각종 연산 및 제어를 위한 로직을 구성하기 위해서 logic_picture.svg 파일을 추가합니다. 

- logic_picture.svg 파일에서 구성한 로직을 제어하기 위한 hmi_picture.svg 파일을 추가합니다.

본 강좌에서는 로직변수를 HMI변수에 적용하는 방법에 대하여 설명합니다. 

우선 간단하게 로직 페이지에 임의의 로직 객체를 추가합니다. 아래그림과 같이 로직을 추가하고 각각의 로직 객체의 id값을 고융한 id로 설정합니다.

로직 페이지 구성을 완료하였다면, hmi_picture.svg 파일에 로직의 값을 표현할 HMI 객체를 추가합니다.

Set Attribute

HMI 객체의 Properties 윈도우의 Variable Window를 확인하여 보면, 내부 멤버변수(Attribute)와 할당될 Assing 변수(Set Attribute)할당 부분이 있습니다. HMI 객체 제작시 제작자가 제공하는 인터페이스입니다. 자세한 구현 부분을 보고자 하는 경우에는 라이브러리 편집 모드에서 자세한 코드 구현 부분을 확인하시면 됩니다. 

본 예에서서는 추가된 HMI 객체에 logic_picture.svg파일에서 추가한 객체의 입력값을 인터페이스 합니다. 로직객체 ID_SINE_DOUBLE객체의 output값을 HMI객체에 연결하기 위해서 Set Attribute의 속성에 #+로직변수명을 입력합니다. 

추가한 HMI 라이브러리 gauge_pie의 라이브러리 제작은 아래와 같이 구성되어 있습니다. 인터페이스를 위한 멤버변수 m_value값에 따라서 게이지값을 표현되도록 구현된 라이브러리 입니다. gauge_pie의 라이브러리는 내부 구성을 보면 svg의 path객체가 포함되어 있습니다. path객체의 속성 d값을 변경하여 값에 따라 회전위치 정보를 계산하는 로직입니다. svg의 path정보는 사이트에서 좀더 자세히 확인해 보실수 있습니다.

참고 : https://www.w3schools.com/graphics/svg_path.asp

function _ontaskview()

{

//TODO Add your javascript code here

var datagap = m_max-m_min;

var data = m_value;


if (data < m_min)

data = m_min;

else if (data >m_max)

data = m_max;

var angle = ((360 * (data-m_min)) / (m_max - m_min) - 90);

// M40,40 L35.42,79.76 A40.00,40.00 0 1,0 40.00,0.00 Z

var x1 = 80+Math.cos(angle * 3.141592 / 180)*80;

var y1 = 80+Math.sin(angle * 3.141592 / 180)*80;

var dir = 0;


if (angle+90>180)

dir = 1;


ID_GAUGE.d = "M80,80 L"+x1.toString()+ ","+y1.toString()+" A80.00,80.00 0 "+ dir.toString()+",0 80.00,0.00 Z";

ID_LABEL.textContent = m_value.toString();

ID_GAUGE.fill = m_color;

}

내부 페이지 또는 별도의 페이지에 존재하는 로직 객체의 변수를 HMI 객체에 연동하는 방법에 대하여 알아보았습니다. 


다음 강좌에서는 시뮬레이션 사용방법에 대하여 알아보도록 하겠습니다.

-이엔유 주식회사-




+ Recent posts