본문 바로가기
PLC 전기제어 기술자료/샘플 프로그램 & TIP

[MELSEC] 콤마(,)로 나열된 데이터를 분리하는 방법 (INSTR, MIDR명령어)

by 위치결정 2022. 1. 22.
반응형

계측기나 다양한 검사장비들과 데이터를 송수신하다보면 손쉽게 만나는 데이터 형식으로 콤마(,)로 정리된 문자열입니다.

 

이제는 PLC에서도 이렇게 콤마(,)로 구분되어 수신된 데이터를 정리하여 다시 표현 해야하는건 요즘은 너무나도 흔한 일이 되어버린것 같습니다.

이런 경우 사용하면 좋은 명령어 문자열 검색 INSTR()와 문자열 추출 명령어 MIDR() 두가지를 소개합니다.

 

1. 문자열 검색 명령어 : INSTR()

INSTR 명령어의 인수는 [ 검색문자, 기준문자열, 검색문자위치, 검색시작위치 ] 입니다.

 

테스트를 위해 "OK,162.5,165.8,126.1" 이라는 예문을 D0 에 저장하고 콤마(,) 를 찾기위해 D1000에 콤마("," 0x2C) 를 저장하여 INSTR 명령어를 사용하여 D10에 찾은 위치를 리턴받습니다. 검색 시작위치는 상수 K1 로 설정하였기때문에 문자열 제일 처음부터 검색을 시작합니다.

 

처음부터 콤마(,) 을 찾기 시작하여 처음으로 발견한 콤마의 위치는 D10에 3으로 리턴되었네요.

실제로 예문에서도 콤마는 3번째 위치에 있습니다. "OK,162.5,165.8,126.1"

 

그럼 다음 콤마를 찾기 위해 INSTR 명령어를 한번 더 사용해야겠지만 또 시작위치를 1로 설정하면 이전과 똑같이 3번째의 콤마(,) 를 찾아버릴테니, 이번에는 시작위치를 변경해줘야겠네요.

 

마지막으로 찾은 콤마의 위치보다 +1 point 뒤의 문자부터 검색을 시작하면되겠습니다.

방금 찾은 콤마의 위치 D10 에서 1을 더하여 D11에 저장후 INSTR 명령어를 통해 다음 콤마 위치를 D12에 저장합니다.

이번에는 9라는 숫자가 리턴되었네요.

"OK,162.5,165.8,126.1" 아까 예문에서 두번째 콤마도 9번째 자리에 있었습니다.

 

 

2. 문자열 추출 명령어 : MIDR()

MIDR 명령어의 인수는 [ 기준문자열, 추출문자열저장영역, 추출문자열시작점+추출문자캐릭터수(바이트) ] 입니다.

여기서 추출문자열시작점과 추출문자캐릭터수는 연속된 워드어드레스로 자동 할당되니 주의가 필요합니다.

 

먼저 위에서 INSTR 명령어를 통해 콤마의 위치를 알았으니 이제 문자를 추출해볼 차례입니다.

문자열을 추출하기위해 추출할 시작점과 문자의 갯수를 알아내야 합니다.

 

일단 기본적으로 문자의 시작점은 콤마를 기준으로 +1 위치이며,

문자의 갯수는 콤마위치에서 문자의 시작점을 뺀만큼이 문자의 갯수가 될것입니다.

이해가 되지 않으니 예문을 만들어 실제로 테스트를 해보죠.

 

첫번째 문자열인 "OK"를 추출하기 위한 시작점은 문자열의 시작이니까 상수 1을 D20에,

종료점은 다음 콤마위치였던 D10에서 문자의 시작점인 D20을 빼서 D21에 저장합니다.

 

그러면 D20에는 1이 저장되었고, D21는 콤마위치(3) - 문자의 시작위치(1) 이 되어 2가 저장됩니다.

1번째 문자부터 2개의 문자를 추출한다는 의미가 됩니다.

MIDR 명령어를 실행하면 OK가 추출된 것을 확인할수 있습니다.

 

이제 두번째 문자열인 "162.5" 를 추출 하기위해 두번째 문자의 시작위치와 문자갯수를 위의 예문을 이용하여 똑같이 찾아봅니다.

 

두번째 문자열의 시작은 직전에 찾았던 콤마의 위치보다 +1이 될것입니다.

그리고 종료점은 다음 콤마를 찾은 위치에서 시작점만큼 빼주면 그 사이에 있는 문자의 개수가 나오게 되겠죠.

 

그래서 직전콤마위치 D10에서 +1 을 하여 D22에 시작점을 저장하고

다음콤마위치 D12 에서 시작점 D22를 뺀 값을 D23에 저장합니다.

 

 

D22에는 4가 D23에는 5가 저장되었네요.

문자열의 4번째 문자부터 5개의 캐릭터를 D55에 추출할것입니다.

 

 

정확하네요. 이를 반복하면 콤마를 기준으로 정리된 문자열을 내 마음대로 추출 할 수 있습니다!

 

3. 문자열을 추출하는 프로그램 작성

이제 위에서 INSTR명령어와 MIDR명령어를 통해 테스트해본 결과물을 합쳐서 결과물을 만들어봐야겠습니다.

 

이제 실제 프로그램에서는 INSTR 명령어와 MIDR 명령어의 에러를 막기위해 문자열의 총길이를 LEN 명령어로 파악하여 시작포인트가 문자열의 총길이를 넘지 않도록 인터락을 추가합니다.

그리고 MIDR 명령어의 경우 시작포인트는 물론 캐릭터의 갯수도 0보다 큰값일때 명령어가 실행될수 있도록 인터락을 추가해줍니다.

 

이렇게 총 4번에 걸쳐 문자열을 D20, D25, D30, D35로 추출하는 프로그램을 작성하면

예문으로 만들었던 "OK,162.5,165.8,126.1" 문자열이 각각 콤마로 나눠져 있던 문자열로 나눠져서

D20 = "OK"

D25 = "162.5"

D30 = "165.8"

D35 = "126.1" 

로 들어가길 기대해봅니다.

 

어라? 1번째부터 3번째까지 문자열들은 잘 분리가 되었는데 4번째 문자열이 어떤 이유인지 정리가 안되어있군요.

프로그램으로 돌아가서 살펴보겠습니다.

 

아 마지막 문자열에서는 다음 콤마(,)가 없다보니 INSTR명령어에서 반환된 값이 0이였군요. 그러다보니 캐릭터의 갯수 D1021가 정상적으로 계산되지 못한 까닭입니다.

 

그럼 이런 경우에는 종료코드를 이용하여 끝점을 찾는 방법도 있지만 이번 예문에는 종료코드도 없다보니 문자열의 총길이로 끝점을 찾는 방법으로 처리하면 되겠네요.

아까 명령어의 에러방지 인터락을 위해 LEN 명령어를 통해 문자열의 총 길이를 D1002에 바인딩 해두었으니 이를 이용합니다.

 

콤마를 찾지 못한 경우(INSTR명령어 D1022가 0으로 반환) 문자열의 총 길이보다 1을 더한 값을 다음 콤마위치로 써주면 기존에 작성해둔 프로그램 틀이 변하지 않는 선에서 조건이 가능할것 같네요.

 

이제 잘 분리된것을 확인 할수 있습니다.

 

다른 데이터가 수신되어도 당연히 정상 동작 하는것을 확인할수있습니다.

Instr_Midr_1.gxw
0.89MB

편안합니다.

반응형

댓글