Shift 연산에 대해 들어보셨나요?

프로그래머용 계산기를 열어보면 <<, >> 라고 표기된 부분이 shift 연산 입니다.

그리 자주 사용하지는 않지만 알쓸신잡 같은 연산도구 입니다.

이걸 사용하는 이유는 통신 데이터 parsing 때문인데요.

제가 과거에 많이 사용하였던 Q4X 라는 레이저 센서의 IO-Link 통신 맵 입니다.

4차 산업이니 뭐니 해서 IO-Link 에 대한 사용이 점점 많아지는 추세인데요.

데이터를 보시면 16개 bit 1개의 워드로 되어 있습니다.

이 중 0번 bit는 센서에 거리에 따라 감지가 on/off 되는 것을 bit로 나타내고요.

1번 bit는 센서에 2번째 설정 거리에 따라 감지가 on/off 되는 것을 bit로 나타냅니다.

2번 bit는 현재 감지가 일정하게 되는 중인지 혹은 되다 한되다 출렁거리는 불안정한 상태인지를 나타내고요.

3번 부터 15번 까지는 거리값을 표현해 줍니다.

15번에서 3번 까지 데이터를 2진수로 기재하면

0001101110011 이죠?

계산기로 표현하면 10진수 부분에 883, 88.3mm를 이와같이 표현한 것을 알 수 있습니다.

그런데 워드 단위 (16bit) 그대로 해석하면 어떻게 되나요? 0b0001101110011101 이런 데이터 상태에서 10진수로 전환하면 7069 라는 데이터로 표현됩니다. 참고로 0b 로 표현하면 binary(2진수) 0x 로 표현하면 hexa(16진수) 를 의미합니다.

7069 에서 88.3mm 를 다시 따로 뽑아내야 하는데 어려움이 있는데요. 이럴 때 사용되는게 바로 shift 연산 입니다.

shift 는 변화 라는 의미도 있지만 옮기다 라는 뜻도 있습니다. 즉 데이터를 옮기거나 이동시키는 연산 입니다.

shift 연산은 위와 같은 규칙으로 동작합니다.

눈치 빠른 분들은 짐작 하시겠지만 필요없는 bit를 제거하는 기능을 하게되죠.

'제가 쓰는 언어에는 shift 연산이 없는데요?' 하시는 분들을 위해 tip 을 드리자면 사실은

N x 2^(shift 연산 수), N / 2^(shift 연산 수) 입니다.

예를 들어 숫자 13을 shift 연산으로 오른쪽으로 3칸 옮기는 연산의 경우 

0b1101 즉 2^3 x 1 +  2^2 x 1 +  2^1 x 0 +  2^0 x 1 에서

0b1 이 되는데요. 이는

(2^3 x 1 +  2^2 x 1 +  2^1 x 0 +  2^0 x 1) / 2^3 이 되면서 

2^(3-3) x 1 +  2^(2-3) x 1 +  2^(1-3) x 0 +  2^(0-3) x 1 이 되고, 소수 이하는 버리게 되면서

2^0 x 1 즉 0b1 이 되게 됩니다.

따라서 우리가 얻은 데이터 0b0001101110011101, 7069 를 우측 쉬프트 연산 3으로 3개 비트를 제거하면 원하는 0b001101110011 즉 883 이라는 데이터로 나오게 되며, 7069를 2^3, 8로 나눠줬을 때 몫도 같은 결과가 나오게 됩니다.

bit 데이터에 대한 parsing 에 위 내용을 기억하시면 아주 유용하게 사용할 수 있습니다.

shift 연산 없이 사칙연산으로 해석이 가능한데 굳이 shift 연산을 만든 이유는 프로그램 코드 가독성 때문인 것 같습니다.

아무 이유없이 / 8 하는 것 보다 3칸 이동했다 라는 해석이 가독성이 더 좋기 때문이죠.

 

여기서 한가지 더, 하위 bit 만 추출하고 싶을때는 어떻게 해야 될까요?

예를들어 Stability State 데이터만 추출하고 싶은 경우 가장 편한 방법은 논리연산 AND를 취하는 것입니다.

0b0001 1011 1001 1101

0b0000 0000 0000 0100

위 둘을 AND 연산을 하게되면

위와 같이 나오게 되죠, 3번 bit에 위치한 데이터 여서 결과값에 / 2^(3-1) 해주면 0,1 로 나오게 됩니다.

혹시라도 논리 연산이 없을 경우...나머지 값을 구하는 mod 함수를 이용하면 원하는 값을 추출할 수 있습니다.

 

PLC에서 Ladder 프로그램 작성하시는 분들이 간혹 위와같은 데이터 추출 방법을 몰라서 어려워 하시는 분들이 있습니다. 특히 시퀀스 위주로 작성하시다 보니 데이터 가공에 대해 어려워 하시는데 위 내용 참고하시어 원하는 데이터 추출을 편하게 하시기 바랍니다.

 

 

위에 나온 프로그래머용 계산기 관련해서 달력과 관련된 재미있는 내용 하나 공유드립니다.

2, 8, 10, 16 진수는 프로그램 하시면서 많이 접하게 되는데요. 2는 binary 에 약자 BIN, 8은 octal 의 약자 OCT, 10은 decimal 의 약자 DEC 16진수는 hexadecimal 의 약자로 HEX 로 사용합니다. 프로그램 하시는 분들은 익숙하실 텐데요. 특히 OCT 관련된 단어들은 8을 뜻하는 것들이 많습니다. 다리가 8개인 문어도 octopus 라는 이름을 가지고 있고요, 달력에서도 October 가 있죠...

 

엥? October는 8월이 아니라 10월인데요??!!

 

이상하죠? ^^

10진수를 뜻하는 Decimal 도 달력에서는 12월이 됩니다. ㅎㅎ 왜그럴까요?

 

저도 정확한 기원은 잘 모르지만 로마에서 초기에 달력이 만들어 지면서 계산 오류가 있었고, 이 때문에 2개 달을 추가하게 됩니다. 여기서 갑자기 들어온 추가된 달이 July, August 입니다. 이는 당시 로마에서 유명했던 율리우스 카이사르 ( Julius Caesar ) 와 아우구스투스 (Augustus) 황제의 이름이 들어간 것입니다.

 

달력에 들어간 사람 이름에 대한 내용은 나중에 재미있는 알쓸신잡 처럼 알아두시면 좋겠습니다.

shift 연산에 대해 내용은 간단한데 너무 장황하게 늘어놓았네요. ( 재미있게 쉬어가도록 하려다가 머리만 더 복잡하게 해드린 것 같습니다. ) 대충 저런게 있다 정도로 넘기시다가 나중에 필요하실 때 다시 찾아보시면 좋을 것 같습니다. 

 

 

 

 

 

 

 

 

 

ASCII code 현업에서 종사하는 사람들이라면 들어는 봤는 그리고 실제로 사용도 많이 하는 코드 입니다.

대표적인 예로 키보드와 컴퓨터간에 ASCII code를 사용하고 있죠.

ASCII (American Standard Code for Information Interchange, 미국 정보 교환 표준 부호) 입니다.

 

제가 여기서 언급하고 싶은건 A,a 그리고 숫자에 대한 코드 입니다. 왜 A는 65 a는 97 0은 48로 했을까?

여러분들은 어떻게 생각하시나요?

이 숫자를 단순히 10진수로 보면 의미를 받아들이기 힘듭니다. 하지만 2진수나 16진수로 보게되면 해석이 달라지죠.

대문자 A를 의미하는 65는 2진수로 볼 때 64를 나타내는 7번째 비트를 살리고 첫번째 알파벳 이라는 의미로 볼 수 있습니다.

또한 16진수로는 첫번째가 4로 시작하는 숫자 중 첫번째가 대문자 알파벳의 첫번째 인 거죠. 아무 의미 없어보이는 65가 실제로는 저런 의미를 가지고 65번째가 된 것입니다. 그럼 소문자 a 97은 어떨까요?

7번째 비트가 살아 있고 (알파벳인거 같네?), 6번째 비트가 살아있는 상태(아 소문자구나)에서 첫번째 단어(a)네 이렇게 된 것으로 보입니다.

 

16진수를 표현할 때 0x를 앞에 붙여 사용합니다. 그럼 A는 0x41 a는 0x61 이 되죠.

0x51은? 아...알파벳이 26개라서 큰 의미 없는 거고...그럼 0x31은 뭐가 있나?

코드표를 보면 아시겠지만 1은 0x31 0은 0x30 입니다. 16과 32의 합성으로 48이 된거죠. 0x3? 이면 '아 숫자구나?' 하면서 알 수 있는 겁니다.

 

'알파벳이 26개니까 64를 의미하는 7번 비트 on/off로 가독성이 좋게 합시다.', '소문자인지 한개의 비트로만 확인할 수 있도록 배치하려면 65번 97번이 좋지 않겠습니까?', '기왕이면 숫자도 자주 쓰는데 0x3 으로 시작하고 0~9까지 배열합시다.' 라는 대화가 오갔을 것 같습니다. 당시 제작자들이 얼마나 세심하게 배열했는지 다시금 감사하게 생각게 되더라구요. 현업에서 일하다가 혼자 저걸 깨달았을 때 어찌나 기분이 좋던지 세상의 비밀 하나를 알게된 느낌이랄까요? ^^ 

 

다음으로 설명드릴 내용은 Enter 입니다.

여러분은 Enter가 ASCII Code 2개의 합성으로 이루어 진 것을 알고 계시나요?

현업에서 시리얼 통신(Serial communication RS-232, RS-485 등)을 하다보면 데이터 전송 후 마지막에 데이터 끝을 알리는 의미로 <CR>,<LF>를 자주 사용합니다. Enter키를 치면 ASCII로 13,10 16진수로 0x0d,0x0a 입니다.

CR은 Carriage Return  LF는 Line Feed 의 약자 이죠. 이 말들은 무슨 뜻이고, 어디서 비롯된 것 일까요?

출처 pixabay : https://pixabay.com/ko/photos/%ED%83%80%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B4%ED%84%B0-%EA%B8%B0%EA%B3%84%EC%A0%81-%ED%83%80%EC%9E%90-6638277/

바로 키보드의 전 버전인 타자기에서 시작되었습니다.

여기서 Carriage는 타자를 칠 때 종이를 고정하여 움직이는 부분의 명칭입니다.

타자를 다 치고나면 "띵" 소리를 내면서 종이 가장 앞에서 글자를 다시 쓰도록 하기 위해 Carriage가 Return 하는데서 유래가 된 표현입니다.

Line Feed 는 한줄 밑으로 내려가는 동작을 표현하는거고요. 

현재는 거의 찾아볼 수 없는 타자기의 내용이 아직까지 우리생활에 숨어서 가장 많이 사용되는 것을 보면 너무 신기하기만 합니다.

 

codesys 소개가 너무 딱딱하다 보니 현업에서 일하다가 알게된 말랑말랑한 재미있는 지식을 전달 드리고자 부록을 준비해 보았습니다. ^^ 재미있게 읽어주셨다면 좋을 것 같습니다. ㅎㅎ

여기서는

조건문 if, case

반복문 for, while

 

포인터 까지 하고 싶었지만 내용이 많을 것 같아 포인터는 다음장에서 소개하겠습니다. ^^

 

조건문

조건문은 if 와 case 가 있습니다.

사용 용도는 아래와 같습니다.

if       : 특정 조건에서만 if 와 enf_if 사이 혹은 if 와 else 사이의 명령을 수행한다.

case : 특정 조건에 맞는 사례의 명령문만 실행한다.

 

if 문을 먼저 살펴 봅시다.

조건문 IF

영어 원문 설명이 필요하신 분들을 위해 링크 남겨드립니다.

https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_st_instruction_if.html

 

CODESYS Group

The IF statement is used for checking a condition and, depending on this condition, for executing the subsequent statements.A condition is coded as an expression that returns a Boolean value. If the expression returns TRUE, then the condition is fulfilled

content.helpme-codesys.com

 

codesys에서 일반적으로 변수에 데이터를 대입할 경우 xSwitch1:=true; 라고 표기하며
논리연산 and or 비교 등을 하여 참 거짓을 표현하는 경우 : 을 빼고 xSwitch1=true 이렇게 표현 합니다.

부등호 같은 경우 <,>,<=,>= 로 표현하며, =<,=> 는 사용하지 않습니다.

크거나 같다 작거나 같다 라고 하지 같거나 크다, 같거나 작지 하지 않잖아요. ^^

다른 논리 연산도 동일하게 사용 됩니다.

(A and B), (A or B), (A xor B), not(A)

보통 제가 해석이 애매할까봐 괄호를 하는데 안해도 무방하긴 합니다.

 

if 와 then 사이를 보면 xSwitch1= true 라고 되어 있습니다. 위 코딩에 대한 해석을 저는 다음과 같이 합니다.

'만약 스위치가 참 이라는 상태가 참이면 장비의 상태는 on 으로 한다.'

참이라는 상태가 참이면 이라는 해석이 이상하죠?

가독성을 위해 위와 같이 표현하기도 하지만 사실 아래와 같이 조금 더 간결하게 표기하기도 합니다.

if xSwitch1 then 에 대한 해석을 저는 '만약 xSwitch1이 참이면' 이라고 해석합니다.

if 문 내부 상태가 참이냐 거짓이냐에 따라 조건문이 동작하기 때문에 굳이 :=true 라고 할 필요는 없는거죠. bool 변수 자체가 논리연산의 결과가 되기 때문에 그렇습니다.

 

위와 같이 설정 후 실행하면 xSwitch1 이 true가 되면 xMachine_state 가 true가 됩니다.

반대로 xSwitch1 가 false 가 되도 xMachine_state 상태는 계속 true 입니다.

false 명령이 따로 없죠. false 명령도 추가해 보겠습니다.

이제 xSwitch1 이 상태에 따라 xMachine_state 가 true,false가 됩니다.

그런데 줄 수도 많고 시안성도 좋지가 않네요.

반대 상태도 같이 묶어서 표기하면 좋을 것 같습니다. 이럴 때를 위해 사용하는 명령어가 else 입니다.

위와 같이 실행하면 조건문 내부의 조건이 참일 때 (xSwitch1 이 참일 때) if 문 아래를 수행하고, 조건이 거짓 일 경우 else 아래를 수행합니다. 어떤 것을 사용해도 동작은 동일하지만 코드 수, 시안성을 두고 봤을 때 마지막 코딩이 더 가독성이 좋습니다.

이게 제일 가독성이 좋긴 하지만 if 문 설명을 위해서 작성해 보았습니다. ^^

 

if 문에서는 조건을 여러개 둘 수도 있고, 조건도 여러개 사용할 수 있습니다. 또한 if 내부에서 if 문을 사용하는 것도 가능합니다.

예를 들어 생산 제품(iProduct)에 모델 번호가 있고, 이를 1,2,3으로 표현하며, 0은 선정이 안된 상태 그리고 선정이 안된 상태에서 가동 할 경우 에러(xError)를 표현한다고 가정합시다.

실제로 위와 같이 작성하진 않겠지만 조건문을 2중이상 사용할 수 있고, elsif 라고 거짓인 경우 추가 조건을 확인할 수도 있습니다.

설명을 위해 조금 억지스럽게 만들기는 했지만 저런 식으로 규칙에 벗어나지 않으면 다양하게 응용할 수 있다는 점을 보여드리고 싶었습니다.

조건문 CASE

case에 대한 영어 원문 설명 링크 입니다.

https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_st_instruction_case.html

 

CODESYS Group

The CASE statement is a conditional control structure which causes a statement or a section of a statement to be executed only under a specific condition. The section which is executed is determined by comparing the condition and label.Syntax:CASE OF : : :

content.helpme-codesys.com

 

case는 true/false 로 나눠지는 경우보다 한개의 변수를 두고 데이터의 상황에 따라 명령을 실행하는 경우에 적합합니다.

앞서 iProduct가 0,1,2,3 인 경우에 따라 xMachine_state 를 변화 시켰죠?

이 사례를 들고 case문을 만들어 보겠습니다.

iProduct에 대해 눈으로 따라가기가 용이하기 때문에 가독이 편리합니다.

여기서 상황을 추가해 볼께요.

4,5번 제품도 2번 라인에서 생산하며, 10~20번 제품은 1,2,3 장비를 모두 가동해야 되는 경우라고 합시다.

if 문으로 처리하려면 줄 수가 많아졌겠지만 case 문으로 작성하면 훨씬 깔끔하게 작성되는 것을 확인할 수 있습니다.

case문 내부에서도 if 문 등을 사용할 수 있으며, 자유롭게 응용 가능합니다.

반복문 for, while

영어 원문 설명이 필요하신 분들을 위해 아래 링크 공유 드립니다.

https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_st_instruction_for.html

 

CODESYS Group

The FOR loop is used to execute statements with a certain number of repetitions.Syntax:FOR := TO {BY } DO END_FOR;The section inside the curly parentheses {} is optional.CODESYS executes the as long as the is not greater than – or in the case of negative

content.helpme-codesys.com

프로그램에 익숙하신 분들은 그냥 '아 반복문 형식이 이렇구나' 하는 정도로 보시고 넘어가셔도 될 것 같습니다.

참고로 반복문은 ST에서만 사용 가능합니다.

 

반복문은 for, 와 while 로 크게 나눠집니다. (Repeat 도 있습니다. 잘 사용 안합니다. ^^) 사용 용도는 다음과 같습니다.

 

for        : 특정 횟수만큼 반복할 경우 필요

while    : 특정 조건이 충족된 경우에만 반복할 경우 필요

Repeat : 무조건 1회 진행하며, 특정조건에서만 반복문을 빠져나갑니다.

다음은 반복문의 예시 입니다.

for 문은 i가 1에서 5까지 변하며, 1씩 증가합니다. 그 동안 a에 1씩 값을 더합니다.

동작을 실행하면 순서는 다음과 같이 진행 됩니다.

 

2번줄 i=1, a=0

3번줄 i=1, a=1

4번줄 i=1, a=1 2번줄로 돌아감

2번줄 i=2, a=1

3번줄 i=2, a=2

4번줄 i=2, a=2 2번줄로 돌아감

2번줄 i=3, a=2

3번줄 i=3, a=3

4번줄 i=3, a=3 2번줄로 돌아감

2번줄 i=4, a=3

3번줄 i=4, a=4

4번줄 i=4, a=4 2번줄로 돌아감

2번줄 i=5, a=4

3번줄 i=5, a=5

4번줄 i=5, a=5 2번줄로 돌아감

2번줄 i=6, a=5 조건이 맞지 않음으로 5번줄로 감


while 문도 for 문과 동작이 동일합니다. 그런데 왜 나눌까요? 제가 생각하는 이유는 가독력이나 상황이 달라서 그런 것 같습니다.

for 문은 보통 횟수가 정해진 반복이나 배열에 대해 사용을 자주 하는 편인 것 같고,

while 문은 특정 사건 (버튼을 눌렀다던지, 센서에 물체가 감지되었다던지) 에 대한 반복이 필요한 경우에 사용하는 것 같습니다.

 

repeat 문은 위 두 반복문과 다르게 무조건 1회 실행하며, 조건을 마지막에 따지게 됩니다.

뭐...굳이 활용하자면 제품이 도착했을 때 무조건 바코드 스탬프를 한번 찍고 비전 카메라를 읽어서 읽히면 통과 이런 라인에 사용할 수 있겠네요.

 

배열과 변수 선언 팁에 대해 소개하려 했는데 글이 너무 길어서 다음으로 넘길께요. ^^

 

혹시 이해가 안되거나 이상한 점 혹은 문의 있으시면 남겨주시면 감사하겠습니다.

앞서 3-1 에서 변수 타입에 대해 간략히 설명 했습니다.

codesys 프로그램을 시작하기에 변수 설명이 반드시 필요했기 때문에 간단하게만 설명했죠.

이번에 변수 타입과 더불어 조금 더 심도있는 내용을 다루려 합니다. 

먼저 전역변수에 대한 내용을 설명하겠습니다.

전역변수

전역 변수는 prg, fb, fc 등 어디에서도 쓸 수 있는 변수 입니다.

한번만 선언되며, 동시에 2개 이상의 prg, fb, fc 등에서도 접근 가능합니다.

사용자 입장에서 사용하기 편리하지만 무분별한 사용 시 debug가 힘듭니다.

 

전역 변수의 사용 예로는 앞서 설명한 E-Stop 버튼, 장비 Start, Stop 등 프로그램 전체에서 알아야 되는 정보를 사용합니다.

 

사용법은 Application 에서 우클릭하여 Add Object -> Global Variable List 를 클릭합니다.

전역변수를 쓰임에 따라 나누기 위해서 별도의 이름이 필요한 경우 지정해 줍니다.

xStart, xStop , xEstop, xMachine, xError 5개의 변수를 전역 변수로 선언하였고, 사용하는 예시문 입니다.

선언 후 사용에는 앞서 선언한 이름.변수명 으로 사용합니다. ex ) GVL.xStart

 

조건문이 나온김에 간략히 소개하자면

IF 조건 THEN

    조건이 참일 때 실행할 명령 여러개 가능

ELSE

    조건이 거짓일 때 실 행할 명령 여러개 가능

END_IF

 

위 형식으로 되어 있습니다.

 

IF gvl.xStart AND NOT (gvl.xEstop) THEN            <-------------- 시작 버튼이 눌려졌고, Estop 버튼이 안눌러져 있다면
    gvl.xMachine:=TRUE;                                        <-------------- 장비를 가동상태로 둔다.
END_IF                                                                  <-------------- 조건문 종료
IF gvl.xStop THEN                                                 <-------------- 정지 버튼이 눌려졌다면
    gvl.xMachine:=FALSE;                                       <-------------- 장비를 정지상태로 둔다.
END_IF                                                                   <-------------- 조건문 종료
IF gvl.xEstop THEN                                                <-------------- 비상정지 버튼이 눌려졌다면
    gvl.xMachine:=FALSE;                                        <-------------- 장비를 정지상태로 둔다.
END_IF                                                                   <-------------- 조건문 종료

IF gvl.xStart AND gvl.xStop THEN                          <-------------- 시작과 정지가 동시에 눌러졌다면
    gvl.xError:=TRUE;                                               <-------------- 에러상태 on
ELSE                                                                       <-------------- 시작과 정지가 동시에 눌러진게 아니라면
    gvl.xError:=FALSE;                                              <-------------- 에러상태 off
END_IF                                                                   <-------------- 조건문 종료


IF gvl.xMachine THEN                                            <-------------- 장비가 가동상태라면
    fbDiv(                                                                   <-------------- fb를 실행
        iDataA:=Var1,
        iDataB:=Var2
    );
    fbDiv.iQuotient;
    fbDiv.iRemainder;

END_IF                                                                   <-------------- 조건문 종료

 

지역변수

지역변수 역시 어디서나 사용 가능하지만 동시에 여러군데서 접근할 수 없습니다.

사용자 입장에서 데이터를 주고 받을 때 까다로울 수 있지만 만들어진 함수 혹은 펑션블록의 에러 가능성을 없애주고 전역변수에 비해 상대적으로 debug가 용이합니다.

 

지역변수는 다시 크게 3가지로 나눠집니다.

내부 지역변수 VAR

입력 지역변수 VAR_INPUT

출력 지역변수 VAR_OUTPUT

입출력 지역변수도 있지만 여기선 생략하도록 하겠습니다.

 

내부 지역변수 VAR

    내부 지역변수의 대표적인 사용 예로 반복문 for 를 예로 들 수 있습니다.

    codesys 반복문 for는 다음과 같이 사용합니다.

 

     i 라는 변수가 1~100까지 1씩 증가하며, for 와 end_for 사이의 명령을 실행합니다.

     위 반복문은 i가 1에서 100까지 변할 때 까지 변화되는 값을 계속 a에 누적시키게 됩니다.

     위와 같은 경우 i 라는 변수는 큰 의미를 가지고 있지 않고, 반복문 for 를 돌리기 위한 수단으로 사용이 됩니다.

     이와 같은 경우 i 를 전역 변수로 사용한다면 다른 프로그램에서 반복 문 사용 시 중복사용 되며, 원하지 않는 결과를 가져올 수 있

     습니다. 따라서 각 프로그램에서 i 같은 변수는 내부 지역변수로 사용합니다.

 

입력 지역변수 VAR_INPUT

     입력 지역변수는 주로 fb, fc 에서 사용됩니다.

     예를 들어 a, b 두개의 데이터를 받아 몫과 나머지값을 반환하는 fb를 작성한다고 가정합시다.

     상위 에서 fb를 call 하면서 데이터 2개를 넘겨주게 됩니다.

     이 때 a, b 데이터를 받는 변수를 입력 지역변수로 처리합니다.

 

출력 지역변수 VAR_OUTPUT

     fb에서 주로 사용하며, 위의 몫과 나머지 예시를 들었을 때 처리된 몫과 나머지를 상위로 넘겨주는 역할을 합니다.

     fc에서는 사용하지 않습니다. fc는 출력이 데이터가 1개일 경우 사용하며, 출력데이터는 return  값으로 반환하기 때문입니다.

위 작성한 프로그램에서 메인 프로그램 PLC_PRG의 지역변수는 VAr1,Var2가 됩니다.

fbDiv 도 지역변수라 불러야 되는지...는 애매하네요. 뭐 자격증 시험 보는거도 아니고 크게 따지지 맙시다. ^^

fbDivide의 지역변수는 iDataA, iDataB, iQuotient, iRemainder 입니다.

이 중 iDataA, iDataB는 입력 변수로 사용되었고, iQuotient, iRemainder 는 출력 변수로 사용되었습니다.

 

대부분의 변수는 지역변수를 사용할 일이 많을 것으로 예상됩니다.

 

잔류 변수 (Remanent variable) : Retain 변수, Persistent 변수

Remanent variable 은 일반적인 프로그램 런타임 이후에도 값을 유지할 수 있습니다.

일반적인 프로그램 런타임 이라는 말은 어렵지요? 쉽게 말해 전원이 꺼져도 값이 유지되는 것 입니다.

 

예를 들어 공장에 오전 9시에 전원을 켜고 오후 6시에 전원을 끄는 장비가 있다고 합시다.

이 때 6시에 전원이 꺼지고 나면 원래 장비는 시간을 기억하지 못하게 되겠죠?

이러한 시간을 기억하는 용도로 쓰일 수 있다고 보면 됩니다.

 

물론 시간과 관련된 장비는 장비 전원이 꺼지더라도 전원이 공급 되게끔 설계 되었을 겁니다.

하지만 공장에 순간 정전이 온 경우라면 어떨까요?

정전 복구 후 값을 유지 못하는 장비들은 사람들이 일일이 돌아다니며 수동으로 시간을 맞춰줘야 할 것입니다.

또한 시간이 맞춰지지 않더라도 동작이 가능한 장비들의 경우 시간과 맞춰 동작하는 장비와 다시금 연결되었을 때 알수 없는 오작동을 일으킬 가능성이 있습니다. (물론 요즘은 인터넷 때문에 자동으로 시간이 맞춰지겠지만)

 

하지만 또 다른 예를 들어 봅시다.

공장에서 20개 한 묶음으로 포장하던 라인에서 갑자기 전원이 꺼진 경우 현재 19개 밖에 담지 못했다가 초기화 되면 어떨까요?

이러한 현상들을 방지하기 위해 Retain Persistent  변수가 생긴 겁니다.

 

Retain, Persistent 변수는 옵션이 나눠져 있지만 정확히 어떤 의미 인지는 잘 이해 못했습니다.

그냥 사용할 때 같이 사용해 주세요. 

선언 및 사용은 위와 같습니다.

uiTest1은 일반적인 unsigned integer를 선언한 것이고,

uiTest2은 일반적인 Retain Persistent Unsigned Integer를 선언한 것입니다.

각각 20 이라는 값을 강제로 써주고 reset warm 했을 때 Retain Persistent 변수의 경우 초기화 되지 않습니다.

reset cold 했을 때도 값은 유지되지만 reset origin 하게되면 값은 초기화 됩니다.

 

reset 이 나온김에 간단히 설명하자면

 

Reset Warm

    지속 변수를 제외한 변수를 재설정하는 동작

Reset Cold

    PLC를 껏다 켜는 동작과 유사

Reset Origin

    PLC 내부 프로그램을 삭제 공장 초기화 상태로 생각하면 좋음

 

PLC 내부 회로에서는 전원 차단 이후에도 내부에 건전지 혹은 커패시터로 인해 일정 시간동안 PLC가 완전 off 되지 않는 상태로 있습니다. 아주 미세 전원으로 동작하기 때문에 감전에 위험이 없는 수준의 전기로요.

건전지 타입 PLC의 경우 건전지를 주기적으로 갈아줘야 하는 단점이 있지만 전원 차단 이후 시간이 더 오래 지속될 수 있는 ( 몇일  이상 ) 장점이 있습니다.

반대로 커패시터 타입의 경우 건전지를 갈아주지 않아도 되는 장점이 있지만 전원 차단 이후 건전지 타입에 비해 오래 지속되지 못하는 단점이 있습니다. 

 

변수에 대해 추가 설명 하려는데 앞서 설명하지 못한 반복문, 조건문 및 reset에 대해 너무 장황하게 나열한 느낌이 있네요.

다음장에 반복문, 조건문 및 배열 그리고 변수 선언 팁에 대해 소개하도록 하겠습니다.

 

Portainer는 현재 설치 된 images, containers 를 시안성 좋게 관리해주는 도구라고 보시면 됩니다.

추가 편의를 도와주는 다양한 도구들이 있지만 저도 아직 거기까진 잘...공부하는 중이라...ㅎ

일단 간략하게 어떤 차이가 있는지 간단히 소개하고 설치 방법을 소개하도록 하겠습니다.

mobaXterm (ssh docker 화면)

 ssh로 docker를 확인하려면 위와 같이 docker images, docker ps, docker ps -a 등 일일이 명령어를 입력하여 원하는 정보를 확인하여야 합니다.

Portainer 화면

Portainer를 설치 후 접속하게 되면 현재 이미지가 몇개 설치되어 있는지, 컨테이너는 어떤게 있는지, 차지하고 있는 용량, 그리고 네트워크 정보등을 확인할 수 있습니다. 또한 명령어 직접 입력방식 보다는 마우스 클릭을 통해 다양한 정보들을 확인할 수 있습니다.

이와 같이 시안성, 편의성으로 인해 설치를 추천하며, 굳이 필요없으신 분들은 pass 하셔도 무관합니다.

설치 명령은 아래와 같습니다.

 

docker run -d --restart always --name portainer -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

 

Protainer 최초 접속 192.168.1.12:9000 접속 시

설치 후 <장치IP>:9000 입력하면 위와 같은 창이 뜹니다. 최초 접속 시 뜨며, Password 설정 입니다.

 

접속 후 local -> Containers 에 들어가면 위와 같은 화면을 볼 수 있습니다.

 

원하는 컨테이너가 몇번 포트로 접속해서 확인해야 되는지 깔끔하게 확인할 수 있습니다.

또한 현재 run 상태인지 stop 상태인지도 확인할 수 있습니다.

컨테이너 시작, 정지, 삭제 등 동작 관련해서도 간단한 클릭으로 해결할 수 있습니다.

 

name 을 클릭해서 들어가면 아래로 쭉 내렸을 때 Volumes 위에 Restart Policies 를 확인할 수 있습니다.

 

Restart Policies 는 컨테이너를 언제 재시작 할 건지 설정합니다.

원래 변경하려면 컨테이너를 정지하고 변경한 뒤 다시 run 해야 되는데 여기서는 간단한 클릭으로 변경할 수 있습니다.

 

더 다양한 기능이 있겠지만 주로 사용 확인 된 기능만 소개하였으며, 추가 필요한 기능 소개는 차차 다른 과정들을 진행하면서 소개하겠습니다.

 

 

 

 

 

Docker

막상 Docker 설치 라고 글을 시작 했지만 아직도 Docker가 뭔지 설명 하라고 하면 저도 애매합니다.

사용한지 얼마 되진 않았으니까요.

도커에 대한 공식적인 이미지는 위와 같지만 저는 이해를 돕고자 아래와 같은 이미지를 만들어 봤습니다.

제가 처음 Docker를 다뤄보면서 착각했던 가장 큰 부분은 도커는 컨테이너화 된 프로그램들을 실행시키고 정지시키는 도구(프로그램 일 수도 있고) 라는 것 입니다. 명령어도 docker ps, docker run 이런식으로 해서 헷갈립니다. 부디 docker 다루시는 분들은 저와같은 착각을 하지 않았으면 좋겠습니다.

docker 시작하시는 어떤 분들은 위와 같은 질문을 할 수도 있습니다.

docker랑 VM이랑 차이가 뭔가요?

저도 정확한 차이는 명료하게 설명할 순 없지만 VM은 가상의 PC를 돌리는 느낌이라 보시면 될 것 같습니다.

가상의 PC여서 OS 도 필요할 것이고요. 그러다 보니 자연스럽게 더 무거워 질 수 밖에 없습니다.

docker는 container 하나 하나를 개별 관리하기 때문에 하나가 다운된다고 다른 컨테이너에 영향을 줄 수 없습니다. 그리고 재시작도 용이하고요. 정확한 설명은 직접 찾아보시기 바랍니다.

 

아무튼 초보자가 이해하기 쉽게 설명하자면 아래와 같습니다.

  1. docker는 PC에 설치하는 container 관리 프로그램 정도로 이해해 주세요. 
  2. 우리가 실행하는 명령은 docker 라도 실제로는 container 일 수 있습니다. 헷갈리지 말아주세요.
  3. container는 프로그램이라고 보셔도 됩니다.
  4. container를 만들기 위해서 image가 필요합니다.
  5. 1개의 image로 여러개의 container 를 만들 수 있습니다.
  6. 인터넷이 연결된 상태라면 image 파일을 받아올 수 있습니다.

Docker Install

SSH로 접속한 뒤 아래와 같이 입력합니다.
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker ${USER}
groups ${USER}
sudo reboot
 
여기서 ${USER}는 유저 이름을 입력합니다.
잘 모르겠으면 whoami 라고 입력하면 알려줍니다.
설치된 docker 의 버전을 알고싶다면 docker version 입력합니다.

docker 설치 시 권한(permission) 문제가 생기면 sudo chmod 777 /var/run/docker.sock 입력 합니다.
chmod 는 권한 변경 명령으로 자세한 사항은 아래 링크를 참고해 주세요.

 

 

 

이번 글에서는 Pi Connect와 SSH 연결에 대해서 알아보겠습니다.

Pi Connect 는 리눅스 중수, 고수 분들은 그다지 관심 없으실 것 같습니다.

그렇지만 저 같은 초심자나 입문 단계에서는 한번쯤 다뤄보고 가는 것이 좋을 것 같습니다.

 

Pi Connect

과거에 리눅스를 알고계신 분들이나 저 같은 경우에 리눅스는 대부분 명령 프롬프트를 다루는 콘솔 창 같은 느낌이었습니다.

윈도우에 너무 익숙해 진 탓도 있고, Linux 명령어를 그닥 많이 알고있지 못한 탓도 있지만 어렵게 느껴졌죠.

또한 잘못 건드렸을 때 어떻게 원복해야 되는지, OS 싹 밀고 재설치는 용이한 것인지도 한 몫 했던 것 같습니다.

지금은 앞서 올린 글 들을 따라서 1~2시간 투자하면 원복할 수 있기에 쉬워진 것도 있지만 또 하나, UI 창으로 인해 긴장감이 덜해진 것도 있는 것 같습니다.

하지만 책상위에 윈도우용 모니터, 키보드 따로, 라즈베리파이용 모니터, 키보드 따로 두기에는 부담스러운 감이 있습니다.

여기서는 인터넷을 통해 라즈베리 파이를 web browser로 제어하는 Pi Connect에 대해 소개하겠습니다.

Turn On Raspberry Pi Connect 합니다. 그 뒤 Sign In.. 합니다.

계정을 하나 만들고 로그인 합니다. 저는 Google 계정으로 진행했고, google authenticator 앱을 통해서 진행했습니다.

휴대폰으로 QR코드를 스캔하여 연동시킨 뒤 6자리 코드를 입력하게 됩니다.

연동 한 뒤로 window에서 browser 창을 연 뒤 https://connect.raspberrypi.com/devices 접속합니다.

Connect via 를 클릭하신 뒤 Screen sharing 을 클릭하시면 

윈도우 OS PC에서 라즈베리 파이 UI로 접속할 수 있습니다.

 

1. 유용한가?

  100% 만족은 아니지만 나름 쓸만하다고 생각합니다.

2. 100%가 아닌 이유는?

  너무 느리고 버벅거려서 불편합니다.

3. 그럼에도 소개한 이유는?

  모니터, 키보드, 마우스 자리 없애고, 현대의 인터넷 속도에 대한 한계점을 고려할 때 충분히 유용하다고 생각합니다.

4. 많이 쓰일까요?

  많이 쓰이진 않겠죠, 그 이유는 아래 SSH를 통해 알아보겠습니다.

 

SSH

SSH(Secure Shell)는 네트워크를 통해 다른 컴퓨터에 안전하게 접속하고 명령을 실행하며 파일을 전송하는 데 사용되는 프로토콜 및 응용 프로그램 입니다. 포트 22번을 사용합니다.
UI로 보면 더 편리하고 좋은데 왜 SSH 로 사용할까요?

다양한 이유가 있겠지만, 저는 개인적으로 아래와 같은 이유가 작용한다고 생각합니다.

(매우 개인적이기 때문에 틀릴수도 있습니다.)

 

1. 비용

 리눅스 대부분의 프로그램은 open 되어 있으며, 무료로 제공되고 있습니다. 심지어 리눅스 OS자체도 무료로 배포하고 있죠.

 이런한 상황에서 UI에 관련된 frontend 엔지니어까지 달려들어 진행시킬 필요가 있나? 하는 의문이 들게 됩니다.

2. 속도

 UI는 사람이 보기 편안한 상태로 만들어 주지만 반면에 컴퓨터 입장에서는 계속해서 사람에게 보기 편안한 그림으로 표현하는 부담이 되게 됩니다. 유저 입장에서는 보기 힘들고 어렵지만 컴퓨터 입장에서는 최적화 되어 있고, 효율적인 방법이 커멘드 창으로 명령을 주고받는 일 일 수 있습니다. 마치 우리는 10진수가 편하지만 컴퓨터는 2진수가 편한 것 처럼 말입니다.

 

제가 앞으로 다룰 내용들은 유저대 유저의 컴퓨터 활용이 아닌 컴퓨터 대 컴퓨터 의 내용이 될 것 같기에 향후 진행되는 내용들은 SSH로 많이 표현할 것 같습니다.

 

아래에서는 SSH의 가장 기본이 되는 putty 와 제가 사용하는 mobaXterm 에 대해 간단히 소개하고 접속하는 법 까지 알아보겠습니다.

https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

 

Download PuTTY: latest release (0.83)

This page contains download links for the latest released version of PuTTY. Currently this is 0.83, released on 2025-02-08. When new releases come out, this page will update to contain the latest, so this is a good page to bookmark or link to. Alternativel

www.chiark.greenend.org.uk

putty 는 위 링크를 타고 받을 수 있습니다.

설치하여 사용하는 *.msi 파일이 있고, 설치가 필요 없는 .exe 파일이 있습니다. 실행 후 동일 네트워크 대역에서 IP 주소를 치고 들어가면 됩니다.

IP 주소 192.168.1.119 접속 후 login, password 입력을 마친 형태

 

mobaXterm 을 통해 접속하는 방법도 동일합니다.

https://mobaxterm.mobatek.net/download.html

 

MobaXterm free Xserver and tabbed SSH client for Windows

The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!

mobaxterm.mobatek.net

download -> home edition -> download now 하면 putty 와 마찬가지로 설치판과 무설치판이 있습니다.

저는 무설치판을 쓰는데 아직까지 차이를 잘 모르겠습니다.

실행 후 Session -> SSH -> remote host에 IP 주소 입력 후 OK 합니다.

마찬가지로 login, password 입력하면 접속됩니다.

 

  • putty 말고 mobaXterm 을 사용하는 이유가 있나요?
    • 색깔을 통해 시안성을 더 좋게 해 줍니다.
    • 좌측에 windows 탐색기 처럼 위치 관련하여 편의성이 있습니다.
    • 원래 window PC 와 Linux 사이 파일 전송을 위해서 ftp 서버를 별도로 이용해야 되는데 내재되어 있어 편리합니다.

여기까지 SSH 를 통한 Raspberry Pi 접속에 대해 소개하였습니다.

다음 장 부터 본격적으로 Docker 를 통해 프로그램들을 설치 하고 다뤄보겠습니다.

 

 요즘 글을 작성하면서 25년 전 리눅스를 처음 들었을 때, 그리고 15년 전 PC에 리눅스를 사용하려고 try 했다가 실패했던 기억이 떠오릅니다. 지금은 Virtual Box, 라즈베리 파이, 클라우드 컴퓨터가 많이 발전하여 예전에 비해 리눅스를 접하기가 많이 쉬워졌습니다.

 뿐만 아니라 리눅스의 파일을 웹상에서 바로 가져올 수 있는 정보들이 많이 open 되어 있는 점 또한 사용자가 리눅스를 편리하게 사용할 수 있는 이유 중 하나겠죠.

 이번 글에서는 웹상에서 이미지를 가져오는 과정 중에 하나인 네트워크 환경 구성에 대해 작성해볼까 합니다.

 더불어 혹여나 라즈베리 파이 자체를 사용하면서 필요한 한글 폰트 설치에 대해서 안내하겠습니다.

 

네트워크 설정

윈도우 네트워크 설정과 유사하게 라즈비안에서도 우측 상단에 네트워크 설정이 있습니다.

처음 설치 후 유선 랜이 연결되면 자동으로 잡히게 되는데 그림에서 보이는 Wired connection 1  을 클릭해서 설정 (아래 톱니바퀴 버튼) 을 눌러서 변경해도 되고, "-" 버튼으로 삭제 후 "+" 로 새로 추가하여 사용하셔도 됩니다.

"+"버튼을 누르게 되면 유선 Ethernet cable 을 연결하는지 혹은 무선 Wi-Fi 를 연결할 것인지 선택할 수 있습니다.

라즈베리파이 3B 모델 부터 Wi-Fi 를 지원하며 그 전 모델은 USB Wi-Fi 모듈을 별매하여 장착하여야 합니다.

Connection name 에는 본인이 원하는 이름으로 설정하셔도 됩니다.

단, 표기된  SSID 에는 Wi-Fi 명칭을 정확히 입력해 주셔야 합니다.

Wireless Security 탭에서 Wi-Fi의 비밀번호를 입력해주시고요. IPv4 Settings 에서 Method 를 DHCP로 설정해 주세요.

DHCP가 IP 자동할당 이신건 다들 알고 있겠죠? 설정이 완료된 후에는 Save 버튼을 눌러 설정을 마칩니다.

라즈베리 파이 콘솔 창을 열어서 ping 8.8.8.8 입력했을 때 ping 이 제대로 되는지 확인합니다.

8.8.8.8은 google dns 입니다. 인터넷 창 열어서 확인해 보셔도 됩니다. 단, 버벅거리고 너무느려서 속터지는건 본인책임

 

다음으로 유선 연결 방법에 대해 소개하겠습니다.

유선은 인터넷 연결이 아닌 내부 망 ( PLC 등 기타 장비 연결용 ) 연결로 사용할 예정이며, 수동 IP로 설정하겠습니다.

무선 연결과 동일하게 구성하시되 Ethernet 선택, 그리고 IPv4 에서 Method 를 Manual 로 선택해 주시면 됩니다.

IP 주소는 원하는 IP 주소를 넣어주시고, Net Mask는 24를 넣습니다. 

Gateway 는 공란으로 둡니다.

 Gateway는 내부 망에서 쓰는 경우 공란으로 두고, 외부 인터넷으로 연결하는 망에 필요한 부분이라 보는 것이 좋습니다. (정확한 의미는 아니지만) 따라서 wifidhcp로 게이트웨이가 잡히고, 내부망 수동 연결 시 게이트웨이는 사용하지 않습니다.

제 경험에 비추어 보아 유선 연결 고정IP에서 설정 했을 때 와이파이가 잡혀도 인터넷이 안되는 증상이 발생한 적이 있었습니다.

 

Net Mask는 255.255.255.0 을 넣으셔도 무관합니다. 

 

Net Mask 24 와 255.255.255.0 은 같은 의미 입니다.

 

10진수로 표현된 255.255.255.0 을 2진수로 표현하면 11111111. 11111111. 11111111.00000000 이 됩니다.

 

여기서 1이 연속해서 24개가 있습니다. Net Mask 24의 의미는 '1이 연속해서 24개가 있다.' 입니다.

 

저도 네트워크에 관련하여 전문가가 아니기 때문에 아래에 참고한 링크 남겨 드립니다. (작성자 허락 요청 중 입니다.)

 

설정 후 최종적으로 사용하지 않는 연결은 삭제해 주시기 바랍니다.

또한 터미널을 통해 update, upgrade 권장 드립니다.

sudo apt update

sudo apt full-upgrade

 

라즈베리 파이 라즈비안 초기에는 비밀번호 설정을 요청할 수도 있습니다.

이 경우 sudo passwd root 한 뒤 비밀번호, 비밀번호 확인 을 통해 비밀번호를 입력합니다.

 

한글 설정

시작 -> preferences -> Raspberry Pi Configuration 으로 들어간다.

Localisation -> Set Locale..

Language -> ko (Korean)

Character Set -> UTF-8

붉은색 테두리 박스가 기존 설정 입니다.

Set Keyboard

Layout -> Korean

Variant -> Korean

붉은색 테두리 박스가 기존 설정 입니다. 설정 ok 후 재부팅을 요청할 수도 있습니다.

재부팅 한 뒤 글자가 깨져있는 모습을 볼 수 있습니다.

당황하지 말고 커멘드 창에서 아래와 같은 명령이 필요합니다.

sudo apt-get install fonts-nanum

설치 후 sudo reboot 가 필요합니다.

 

여기까지 Raspberry Pi Network와 한글 셋팅에 대해 소개했습니다.

다음장에서는 Window PC에서 Raspberry Pi 접속하는 Pi Connect 와 터미널로 접속하는 방법에 대해 소개하겠습니다.

 

 

 

DB 쌓는데 중심이 되는 Raspberry Pi 부터 우선 준비해 보도록 하겠습니다.

저는 회사에 raspberry pi 3b 모델이 있어서 해당 모델로 진행했습니다.

 

준비물

1. Raspberry Pi 3 Model B

2. 모니터 및 HMDI 케이블

3. 유선 키보드, 유선 마우스 (초기에 블루투스 잡기 어려울 수 있음)

4. 랜케이블

5. Raspberry Pi 전원 케이블

6. uSD card

7. uSD card slot usb

 

준비물이 별로 없다고 생각했는데 생각보다 많네요.

막상 시작하려면 사소한 준비물 하나 없어서 도중에 포기한 경험이 많았던 지라 제 글을 보시는 분 들은 하나에서 열까지 사소한 것이라도 꼼꼼하게 기재해 보려 합니다.

 

우선 OS 설치가 필요할 텐데 아래 링크에서 소프트웨어를 받으실 수 있습니다.

https://www.raspberrypi.com/software/

 

Raspberry Pi software – Raspberry Pi

From our operating system to our GitHub repos, explore the software that powers our technology

www.raspberrypi.com

 

uSD카드는 용량은 크게 무관하지만 속도는 조금 고려하시는 편이 좋습니다.

https://www.sony.co.kr/electronics/support/articles/00252738

해당 이미지는 이해를 위한 참고용이며, 어떠한 상업적 용도나 광고를 위해 기재한 것이 아닙니다.

 

저는 개인적으로 속도가 너무 낮은 uSD 카드 사용 시 Raspberry Pi 자체가 버벅거리는 증상이 있었기에 가급적이면 어느정도는 속도가 되는 카드를 추천드립니다. (단, uSD 카드 속도가 좋아도 Raspberry Pi 자체 cpu 성능으로 인해 버벅거리는 증상은 계속 나올 수 있습니다. )

 

 

혹시 SD adapter 사용하시는 분들은 Lock 풀려있는지 확인 필요합니다.

 

OS 선택 및 설명이 한글로도 잘 나와 있어서 따라 하시기 편리하실 겁니다.

설치 도중 설정 편집하기에서 사용자 이름과 비밀번호, 시간대 설정 하시는 점 잊지 마시기 바랍니다.

저는 회사에서 하는거다 보니 회사 상호인 RaonRPA로 기재했습니다.

나머지 서비스 및 옵션도 따로 설정하진 않았지만 올려둡니다.

공개키만 인증 허용은 필요하신 분들은 따로 공부해서 적용해 보시기 바랍니다. 저는 초보자니까 비밀번호 인증으로 했습니다.

 

저장 한 뒤 위 그림과 같이 선택하면 자동으로 OS 설치가 됩니다. 

 

설치 전 후 위와같이 포멧 여부를 물어보면 취소 하시면 됩니다. (알아서 포멧하고 설치하기 때문에)

완료 후 uSD 카드를 Raspberry Pi 본체에 꽂고 전원을 넣으면 모니터에서 다음과 같은 화면을 확인할 수 있습니다.

전원 넣기 전 모니터 마우스 키보드 다 연결해 두는 것 잊지 마시기 바랍니다.

 

다음 글에서는 네트워크 설정, 키보드 한글 설정 등을 알아보겠습니다.

 앞서 Wago의 PLC 제품군이 ID/PW를 open 하면서 컨트롤러에서 PLC 기능 외에 다양한 기능들을 sub로 구현할 수 있게 됨을 알게 되었습니다. 여기서 소개할 내용은 공장 자동화 및 향후 에너지 솔루션을 위해 Raspberry PI를 통해 DB서버를 구축하고 Grafana를 통해 모니터링 할 수 있는 방법 그리고 휴대폰에서 접속하여 확인할 수 있는 방법까지 소개할 예정입니다.

개략도는 아래와 같습니다.

 

통신 프로토콜 별로 나눠서 설명을 하자면,

1. Wago의 MID 센서와 MODBUS RTU

https://www.wago.com/global/energy-measurement-technology/energy-meter-mid24/p/879-3000#details

MID 센서에 관련된 내용은 상기 링크를 확인해주세요.

 

MID 센서는 AC 단상, 3상 사용중인 전력양에 대한 데이터를 MODBUS RTU 로 상위에 전달해줍니다.

굳이 MID 센서를 사용한 이유는 아래와 같습니다.

  • 차세대 사업에 대해 고도화된 기술만 추구해 오던 과거와 달리 다가올 미래에는 전력 효율, 에너지 효율화에 대한 수요
  • 일반 센서와 달리 모니터링 하기에 실시간으로 다양한 데이터를 불러 올 수 있는 점

2. 허브를 통해 다른 PLC에서 데이터를 가져갈 수 있도록 구성

기존 현장에서 시스템이 꾸려진 경우 일부 데이터를 취득하여 모니터링이 가능하도록 구성했습니다.

Wago PLC는 EtherCAT master, Modbus, EtherNET/IP, CANopen 등 다양한 산업용 통신 프로토콜을 지원하고 있습니다.

https://www.wago.com/global/plcs-%E2%80%93-controllers/compact-controller-100/p/751-9401#details

CC100 컨트롤러에 관련된 상세 내용은 상기 링크를 확인해 주세요.

CC100 컨트롤러는 앞서 다른 글에서 소개한 Codesys 3.5를 탑재한 PLC입니다.

 

다음으로 Raspberry PI 와 CC100 구성입니다.

 

Raspberry PI는  docker를 통해 다음과 같은 Container 들을 설치 할 예정입니다.

 

   1. Node-red : CC100 에서 획득한 데이터를 통신으로 받고 InfluxDB 에 전달하는 용도로 사용됩니다.

   2. Influx DB : 센서 데이터를 축적하는 DB로 사용할 예정입니다.

                       InfluxDB는 시계열 데이터 (시간에 따라 축적해야 되는 데이터) 를 쌓기에 편리한 DB 입니다.

   3. Grafana : InfluxDB 에 쌓인 데이터를 보여주기에 편리한 GUI를 구축하는 용도 입니다.

   4. Portainer : docker 관리를 시각화 할 수 있어서 처음 접하는 유저들에게 쉽게 접근할 수 있도록 해 줍니다.

 

CC100은 Codesys를 통해 Modbus TCP 통신으로 Raspberry PI와 통신이 가능하며, MQTT 도 사용 가능합니다.

또한 CC100 자체적으로 node-red를 설치하여 MID센서와 직접 Modbus RTU 통신을 하며 데이터를 취득하고 전달 할 수도 있습니다. 통신방식은 아직 정하진 않았지만 순차적으로 다 소개하는 편으로 생각하고 있습니다.

 

저는 데이터 쌓는 서버의 용도로 Raspberry PI 를 사용하였지만 사실 현장에 사용하기에 적합하지는 않죠, 다만 테스트 및 구현의 용도로 사용하는 것이니 이 점 참고하시면 좋을 것 같습니다. 더불어 지금 사용하는 Raspberry PI를 Cloud로 바꾸게 되면 sensor 데이터를 Cloud까지 올릴 수 있게 됩니다. ( Cloud로 사용하지 않는 이유는 비용 때문입니다. )

 

다음으로 통신 부분입니다.

Raspberry PI 는 회사 내 ipTime 에 무선으로 연결되어 있고, ipTime 은 다시 무선으로 공유기에 붙어 있습니다.

휴대폰을 통해 공유기 사설 IP에 접속하여 port fowarding을 통해 Raspberry PI에 있는 Grafana에 접속하여 센서 데이터를 모니터링 할 예정입니다.

위와 같은 구성은 보안에 대한 부분은 전혀 고려하지 않고 단순 테스트 목적으로 진행하였습니다.

이 점 참고해 주시면 감사하겠습니다.

 

다음 글에서 구현 방법에 대해 소개하도록 하겠습니다.

 

 

+ Recent posts