본문 바로가기
PLC 프로그래밍/MELSEC PLC

시리얼 통신 하기[5]

by lemy 2019. 3. 8.
반응형



시리얼 통신 하기[5]


출처: melsec PLC 동호회(http://cafe.daum.net/melsec)의 회색늑대 (grizlupo)님의 초보 통신 이야기 연재글 입니다. 

회색늑대 (grizlupo)님의 초보 통신 이야기중 시리얼 통신에 관련하여 전반적으로 이해 할 수 있는 좋은 글입니다. 총 7회 분량의 글 입니다.


QJ71C24N 모듈 다루기

특수 모듈을 다룬다는 것은 모듈에 할당된 I/O와 모듈의 버퍼 메모리를 다루는 것에 다름 아니라고 말씀 드렸습니다. 


① 정해진 버퍼 메모리에 필요한 값을 기록한다.

② 기능을 수행하도록 하는 I/O 출력을 살린다.

③ 기능이 수행되고, 그 결과가 (모듈의) 메모리에 기록된다.

④ 기능이 완료되었음을 알리는 I/O 입력이 산다.

⑤ 정해진 버퍼 메모리에서 결과를 읽어 들인다.


특수 모듈을 다루는 것은 대충 이런 형태의 과정을 거치는 작업입니다. 그래서 Q 시리즈 이전의 모델에서 특수 모듈을 다루는 프로그램은 버퍼 메모리에 필요한 값을 쓰기 위한 TO와 버퍼 메모리에서 결과를 얻기 위한 FROM 명령으로 아주 도배가 되어 있었습니다. 하지만 이런 형태의 프로그램은 버퍼 메모리의 용도를 나열해 놓은 표가 없이는 직관적으로 파악한다는 것이 힘듭니다. 그래서 Q 시리즈가 되면서는 몇 가지 개선이 이루어졌습니다.


1. 특수 다이렉트 디바이스

이름도 거창한 이 디바이스는 사실은 버퍼 메모리입니다. 즉 버퍼 메모리를 디바이스처럼 다룰 수 있도록 해 주는 것입니다.

버퍼 메모리를 CPU가 가진 디바이스와 같은 방법으로 다룰 수 있도록 해 주는 것이기 때문에 이전 시리즈에서처럼 FROM, TO라는 특별한 명령이 아닌 그냥 MOV를 사용해서 버퍼 메모리를 읽고 쓸 수 있습니다. 두 형태를 비교해 보십시요.


FROM H2 K100 D100 K1

MOV U2\G100 D100


두 명령은 모두 할당된 시작 I/O가 H20인 모듈의 버퍼 메모리 100번지 한 워드를 D100으로 옮기는 것입니다. 여기서 아래의 MOV 명령에 사용된 U2\G100이라고 되어 있는 것이 바로 특수 다이렉트 디바이스 입니다. U2는 이것이 결국에는 모듈에 작용하는 것이기 때문에 어느 모듈에 작용하는지를 구별하기 위한 것입니다. 그리고 G100은 그렇게 지정한 모듈의 버퍼 메모리중 100번지를 가리키는 것입니다.

여기서 왜? U와 G라고 표시하느냐고 묻지는 마십시요. 그건 이 기능을 만든 사람이 틀림없이 자기 마음대로 결정한 것일 테니까요. MOV 말고도 DMOV, BMOV, FMOV를 비롯한 이동 명령은 물론 이거니와 다른 모든 명령에서도 일반적인 디바이스와 차이없이 사용이 가능합니다.


2. 전용 명령

특수 다이렉트 디바이스 뿐이라면 FROM, TO 명령이 MOV 명령으로 바꾸는 것일 뿐, 프로그램을 작성하는데 있어 별다른 차이는 없을 것입니다. 그래서 만들어진 것이 전용명령이라는 것입니다. 전용이라는 말처럼 해당하는 모듈에만 적용되는 명령입니다. 반대로 말하면 이 명령은 반드시 명령을 수행할 모듈이 있어야 한다는 것입니다. 그래서 모든 전용 명령은 FROM이나 TO 명령에서처럼 명령이 수행할 모듈의 시작 I/O를 필요로 합니다. 그리고 다음으로 기존 같으면 버퍼 메모리에 옮겨 놓았을 명령을 수행하는데 필요한 데이터들을 담고 있는 디바이스를 지정해 줍니다.


시리얼 통신 모듈 설명서에는 ‘제9장 전용 명령’ 부분에서 7가지 전용명령을 설명하고 있습니다. 하지만 여기서 무수순을 다루어야 하는 우리에게 필요한 것은 INPUT과 OUTPUT 두 가지 뿐입니다. INPUT은 수신을 하고 싶을 때 OUTPUT은 송신을 하고 싶을 때 사용합니다. 이런 전용명령은 구체적인 버퍼 메모리에 대한 언급이 없습니다. 그냥 일반 디바이스 메모리에 필요한 데이터를 기록한 후에 그 디바이스를 전용명령에 알려 주는 형태로 동작을 하게 됩니다. 물론 이 과정에서 전용명령에 알려 주어야 하는 데이터가 엄청 많기 때문에 이것이 그냥 버퍼 메모리에 그 값을 직접 채우는 것과 무슨 차이가 있을까 싶을 수도 있습니다. 하지만 몇 가지 점에서 유리합니다.


일반적으로 기능을 수행하는데 필요한 버퍼 메모리들이 연속적으로 일목요연하게 모여 있는 경우는 많지 않습니다. 대부분은 여기 저기 흩어져 있는 버퍼 메모리를 표를 통해 하나씩 확인하면서 프로그램을 하게 됩니다. 하지만 전용명령은 필요한 데이터들을 정리해서 한꺼번에 연속적으로 기록할 수 있도록 해 줍니다. 버퍼 메모리를 설명하는 엄청난 양의 표에서 필요한 데이터를 하나씩 확인하지 않아도 된다는 것은 그것만으로도 충분히 유용한 것입니다.


기존 방법에서는 기능의 시작과 종료를 할당된 I/O를 통해 하는 경우가 많습니다. 하지만 전용명령에서는 기능의 시작은 전송명령이 실행되는 순간이고, 기능이 종료되면 지정한 디바이스가 살도록 되어 있기 때문에 굳이 모듈의 I/O 할당을 일일이 확인하지 않아도 됩니다.


물론 정말이지 사소해 보이는 것들이지만 전용명령이 만들어진 것이 이른 사소한 편리함을 추구하기 위한 것입니다. 이런 별 것 아닌 것 같은 사소한 편리성이 알게 모르게 몸에 익어지게 되면 참으로 이상스럽게도 옛날 형태의 프로그램 방식이 엄청 짜증스러운 것이 되어 버리는 경험을 하게 되실 겁니다. 하지만 전용명령은 몇 되지 않습니다. 자주 사용되는 몇 가지 기능만을 전용명령이라는 형태로 만들어 조금의 편리성을 추구하는 것입니다. 따라서 모듈의 아주 세밀한 특성까지를 다루어야 하는 문제가 발생하면 여전히 버퍼 메모리와 I/O를 직접적으로 다루지 않을 수 없습니다. 때로는 전용명령이 오히려 더 불편하게 만들어진 경우도 왕왕 있기 때문에 전용 명령만으로 모든 것이 가능할 것이라고 낙관하지는 말았으면 합니다.


3. 송신하기

참으로 길게 돌아 온 것 같습니다. 이제 실제로 문자을 송신해 보겠습니다. 송신할 문자열은 “LON” + <CR>이고, D1000에 저장이 되어 있다고 가정하겠습니다.


송신이나 수신을 논하는 것은 어디까지나 무수순일 경우입니다. MC 프로토콜을 사용하는 것으로 설정을 하고서는 직접 송/수신을 하겠다고 전용명령인 INPUT이나 OUTPUT을 사용하려고 하는 이상한 짓은 절대로 하지 마십시요. 십중팔구 바보 취급을 받을 것입니다. 어쩌면 가끔은 유머 감각이 엄청나게 뛰어난 사람으로 대우받을 수 있을지도 모르겠습니만....


그럼 쌍방향은 어떨까? 하는 고민을 하시는 분이 혹 있을지도 모르겠습니다. 쌍방향이라는 것을 소개하면서 수신 여부를 상대방에게 자동으로 알려준다는 상당히 구미가 당기는 기능에 대한 얘기를 기억하시는 분이라면 그런 생각을 혹 하실지도 모르겠습니다. 더군다나 쌍방향은 무수순과 비슷하다는 말도 함께 했었으니까요. 하지만 잊어 버리십시요. 쌍방향이라는 것 자체를 잊어 버리십시요. 쌍방향의 사용을 고려해야 하는 경우는 아마도 평생을 두고 없을 것 같습니다. 


쌍방향을 전화에 비유하면서 상대편 전화기가 “삐”하는 소리로 수신 여부를 알려 준다고 했을 것을 기억하십니까? 이것은 쌍방향이 되기 위해서는 음성이 수신될 때 “삐” 소리를 낼 수 있는 전화기가 있어야 한다는 것에 다름 아닙니다. 발신자 표시 전화기가 없이는 상대방의 전화번호를 확인할 수 없는 것처럼 쌍방향에 대한 지원이 되지 않은 전화기로는 쌍방향을 할 수 없습니다. 하지만 이 쌍방향에 대한 것도 MC 프로토콜처럼 미쯔비시에서 정한 규칙입니다. 어떤 국제적인 표준이 있는 것이 아니기 때문에 아무 장비하고나 쌍방향이 이루어지는 것이 아닙니다.


장비를 개발하는 입장에 있는 사람들이라면 차라리 MC 프로토콜을 지원해 버리지 이도 저도 아닌 어중간한 쌍방향을 지원하지는 않을 것입니다. 따라서 우리가 실제 현장에게 만나게 되는 것은 MC 프로토콜을 지원하는가? 아니면 무수순으로 프로그램을 해야 하는가? 둘 중 하나입니다. 그리고 아주 특별하게 쌍방향을 지원하는 장비가 있다고 하더라도 프로그래머가 바라 보는 관점에서는 무수순과 전혀 다를 바가 없습니다. 문자열을 만들어서 송신하고, 수신된 문자열을 열나게 분석하게 해야 하는 것은 전혀 다르지 않습니다. 그러니 이제 쌍방향이라는 것은 잊어 버리십시요.


4. OUTPUT 명령어

문자열을 송신하기 위해서는 OUTPUT 이라는 전용명령을 사용합니다. 물론 자세한 설명은 사용 설명서로 미루겠습니다. 


MOV K1 D2000

MOV K0 D2001

MOV K2 D2002

G.OUTPUT H2 D2000 D1000 M1000


G혹은 GP은 전송명령 앞에 항상 붙습니다. G로 시작하는 전용명령은 모듈에 작용하는 전송명령입니다. 따라서 반드시 첫번째 인수로 모듈의 시작 I/O가 주어집니다. 이 밖에도 S.나 SP., Z.나 ZP. 혹은 J.나 JP. 등으로 시작하는 전용명령등도 있습니다만 저도 궁금하기는 하지만 이들 간의 차이점을 정확하게 알지는 못합니다. 단지 G는 주어진 시작 I/O를 가지는 모듈에 작용하는 것 같고, J는 MELSEC-NET 모듈처럼 네트워크를 구성하는 모듈인 경우 그 주어진 국번의 모듈에 작용하는 것으로 짐작만 하고 있습니다. S는 주로 CPU 모듈에 작용합니다. 결국에 CPU도 하나의 모듈이기 때문에 몇 가지 특별한 기능은 이런 전용명령 형태로 동작을 하는 것으로 파악하고 있습니다. 하지만 이 Z는 여러 곳에 나타나는데 정확한 의미를 알 수가 없습니다. 위치결정 모듈의 경우 전용명령들이 모두 Z.나 ZP.로 시작하고 일부 CPU에 작용하는 것으로 보이는 명령 중에도 Z.로 시작하는 것이 있습니다. 


아무튼 G.OUTPUT H2라고 하면 시작 I/O가 H20인 모듈에게 송신을 하라는 명령이 됩니다. GP.OUTPUT이라고 할 수도 있습니다. 이 경우에는 동일한 상승펄스에서 한번만 실행되게 됩니다. 실제로는 이렇게 펄스형태로 한번에 실행되도록 하는 것이 맞습니다. 하지만 저 같은 경우에는 G.OUTPUT을 사용하고 실행 조건이 펄스 형태가 될 수 있도록 조정하는 형태를 더 좋아합니다.


왜냐하면 GP.OUTPUT로 하는 경우에는 명령이 실패한 경우에 다시 명령을 수행하고 싶을 때 실행 조건을 반드시 OFF시켰다가 다시 ON 되도록 해야 하는데, 통신은 실패할 확률이 높습니다. 따라서 통신 프로그램은 실패할 수도 있다는 것을 항상 염두에 두고 항상 재시도가 가능한 형태로 프로그램을 해야 합니다. 그러다 보니 GP.OUTPUT으로 해서 재시도할 때 실행조건을 OFF시켰다가 ON시키는 것이나 애초부터 실행조건에 제 진입이 되지 않도로 해두는 것이나 별반 차이가 없습니다. 그래서 저는 G.OUTPUT을 더 선호합니다.


G.OUTPUT으로 송신을 하려면 세가지가 필요합니다. D2000에 주어진 것이 컨트롤 데이터라고 하는 것으로 세가지 값이 필요합니다. 첫번째는 하나의 모듈에 있는 두 채널 중에서 어느 채널을 이용해서 송신을 할 것인지를 지시하는 값입니다. D2000에 1을 기록함으로써 채널 1을 사용한다는 의미가 됩니다. 2를 쓰면 채널 2를 사용하게 됩니다. G.OUTPUT 명령 전에 MOV K1 D2000이라고 되어 있는 것이 바로 이런 지시를 하기 위한 것입니다. 다음으로 MOV K0 D2001이라고 되어 있는 부분은 사용자가 값을 주는 것이 아니고, 명령이 완료되었을 때 에러 코드가 기록되는 곳입니다. 명령을 수행하기 전에 단지 0으로 지워두기 위해서 MOV K0 D2001을 했을 뿐입니다. 굳이 값을 지우지 않아도 상관없습니다. 명령이 완료된 후에 정상적으로 송신이 이루어졌으면 0이 기록되고, 아니면 문제를 표시하는 에러 코드가 기록됩니다. 마지막 세번째 워드 D2002는 몇 워드를 전송할 것인가 하는 것입니다. 우리는 2워드를 전송할 것이기 때문에 MOV K2 D2002라고 했습니다. 


다음으로 필요한 것이 실제로 전송될 문자가 들어 있는 것입니다. 우리의 경우에는 D1000입니다. 이 때 D1000이 굳이 널종료 문자열일 필요는 없습니다. G.OUTPUT 명령은 문자열을 받아들인다기 보다는 컨트롤 데이터에 지정된 길이만큼을 무조건 송신하도록 되어 있기 때문에 실제로 널 종료 문자열에서는 다룰 수 없는 값이 0인 <NUL>문자도 G.OUTPUT은 송신할 수 있습니다. 물론 당연히 <NUL>도 송신할 수 있어야 맞는 것이구요.


마지막의 M1000은 명령이 완료되었을 때 한 스캔 동안만 ON되는 접점입니다. M1000과 함께 M1001도 사용되는데 M1001은 에러가 있는 경우에 ON됩니다. 즉, 에러가 없이 송신이 이루어지면 M1000은 ON M1001은 OFF가 되지만 에러에 의해 송신이 되지 않은 채 명령이 종료되면 M1000도 ON이고 M1001도 ON됩니다. 그리고 D2001에 발새한 문제에 대한 에러코드가 기록됩니다. 여기서 M1000과 M1001은 한 스캔만 ON된다는 것을 명심해야 합니다. 한 스캔만 ON 한다는 것은 말하자면 펄스입니다.


송신 끝! 이것이 전부입니다. 물론 제대로 된 프로그램을 작성하려면 결과 비트를 검사해서 이상이 있는 경우에 3번까지 재시도를 할 수 있도록 한다거나 하는 따위의 것들이 추가되면서 이것보다는 더 많이 복잡해지겠지만 기본적으로 송신에 필요한 것은 앞서 설명한 것이 전부입니다. 송신할 문자을 만드는 프로그램에 대해서 이미 다루었고, 이제 그렇게 만들어진 문자열을 송신하는 달랑 4줄의 프로그램을 알게 되었습니다. 이제 우리는 시리얼 통신 모듈로 우리가 원하는 것이라면 무엇이라도 송신할 수 있게 된 것입니다. 좀 허탈한 사람이 있을지도 모르겠습니다만 앞서 말씀드린 것처럼 통신은 통신 모듈이 알아서 잘 해 줍니다. 그냥 우리는 그 녀석에게 송신하도록 지시만 하면됩니다. 그러니 어려울 것이 전혀 없는 것입니다. 단지 어떻게 지시 하는지만을 알면 되는 것입니다.

반응형

'PLC 프로그래밍 > MELSEC PLC ' 카테고리의 다른 글

시리얼 통신 하기[7]  (0) 2019.03.09
시리얼 통신 하기[6]  (0) 2019.03.08
시리얼 통신 하기[4]  (0) 2019.03.07
시리얼 통신 하기[3]  (0) 2019.03.07
시리얼 통신 하기[2]  (0) 2019.03.06

댓글