이미지 센서와 PLC를 연결하는 방법: Omron FH×NX 통신 설계 시 주의점
요약
FA(Factory Automation) 분야에서 이미지 센서와 PLC를 연결하는 통신 설계 시 주의사항을 다룬 글입니다. 특히 FH와 NX/NJ 같은 시스템 간의 데이터 전송은 양쪽의 바이트 배열 일관성이 필수적이며, AI에게 코드를 작성하게 하더라도 최종 사양 결정과 경로 선택은 사람이 주도해야 함을 강조합니다.
핵심 포인트
- 통신 설계는 어느 한쪽만 봐서는 안 되며, 양쪽의 바이트 배열 일관성을 사람이 주도해야 합니다.
- EtherCAT, EtherNet/IP 등 통신 경로는 장비 사양에 따라 결정되어야 하며 AI에게 선택하게 해서는 안 됩니다.
- 데이터 전송 시에는 받는 쪽(PLC)의 바이트 구성을 먼저 고정하고, 보내는 쪽(FH)을 그에 맞추어 설계하는 것이 효율적입니다.
- 가장 흔한 오류 중 하나인 엔디언(Endianness) 불일치 등 바이트 순서 문제를 반드시 확인해야 합니다.
이미지 센서로 측정한 값을 PLC에 전달하여 장치를 구동한다. 이는 FA(Factory Automation) 분야에서는 흔한 구성이다. 오므론(Omron)의 경우, FH 시리즈로 측정하고 NX/NJ 시리즈의 PLC가 받아 제어한다. 이 두 시스템을 연결하는 통신 설계에서 AI에게 도움을 받을 때 주의해야 할 점들을 정리해 보았다.
통신은 어느 한쪽만 보고서는 올바르게 구성할 수 없다. FH 측 매크로가 보내는 바이트 배열과 PLC 측 ST(Structured Text)이 받는 바이트 배열이 1바이트 단위로 맞지 않으면 작동하지 않는다. AI는 각 쪽을 개별적으로 작성하는 것은 능숙하지만, 양쪽의 일관성을 스스로 맞춰주지는 못한다. 따라서 이 부분은 사람이 사양(specification)을 주도해야 한다. 코드 예시는 기사용 범용 샘플이며 실제 장비 구성과는 다르다.
(2026-10-18 수정) 최초 공개 버전에서는 FH 매크로의 코드 예시에 타입 식별자가 없는 변수나, 통신 모듈명을 지정하지 않은 SendString을 포함하고 있었다. 구분자(Str$) 앞의 공백, 장면 전환, FH 측 수신에 대한 설명 등에도 매뉴얼에서 확인할 수 없는 내용이 있었다. OMRON의 영문 매뉴얼 Z367(FH Series Vision System Macro Customize Functions Programming Manual)의 기재 내용에 맞춰 수정했다.
먼저 경로를 결정한다. AI에게 선택하게 하지 마라
FH와 PLC 사이에는 여러 통신 경로가 있다. EtherCAT, EtherNet/IP, 무순서 TCP/UDP, PLC 링크 등이 그것이다. 어떤 것을 사용하느냐에 따라 매크로 측의 작성 방식과 PLC 측의 수신 방식이 완전히 달라진다.
EtherCAT을 사용하는 경우, FH는 슬레이브(slave)처럼 동작하며 대응하는 CPU 유닛을 통해 데이터가 흐른다. 매크로는 주로 결과 값의 형태만 담당하는 경우가 많다. EtherNet/IP를 사용하는 경우 태그 데이터 링크(tag data link)로, 변수 간의 대응 관계 설정이 설계의 핵심이 된다. 무순서 TCP/UDP를 사용하는 경우, 바이트 배열의 구성을 직접 정하고 송신과 수신 양쪽에서 조립 및 분해 코드를 작성해야 한다.
여기서 AI에게 '어떤 경로가 좋은지' 선택하게 하는 것은 피하는 것이 좋다. 경로 선택은 장비 구성, CPU 종류, 요구되는 사이클 타임 등 장치에 대한 설계 판단으로 결정된다. 레퍼런스나 과거 실적을 통해 근거를 확인할 수 있을 때만 결정할 수 있다. AI에게 제안받는 것 자체는 괜찮지만, 채택 여부의 판단은 근거를 확인한 후에 사람이 해야 한다. 경로가 결정된 후, 그 경로에 맞춰 코드를 AI에게 작성하게 하는 것이 좋다.
바이트 구성은 받는 쪽(수신 측)에서 정한다
무순서 TCP/UDP로 수치를 보낼 때, 설계 순서가 중요하다. 나는 데이터를 받을 쪽(PLC)의 바이트 구성을 먼저 고정하고, 보내는 쪽(FH)을 그에 맞춘다. 반대로 하면 FH 측 사정에 맞춰 배열한 바이트 배열을 PLC 측에서 억지로 해석해야 하므로 변환이 번거로워진다.
바이트 구성은 표로 만들어 사양서에 기재한다.
| 바이트 | 내용 | 타입 | 순서 |
|---|---|---|---|
| 0~3 | 측정 X | 32비트 정수 (0.001mm 단위) | 상위부터 |
| ... |
이 표를 AI에게 주면, 양쪽의 코드를 이 표에 맞춰 작성해 준다. 표가 없으면 AI는 FH 측과 PLC 측에서 각자 다른 순서를 임의로 정한다. 실수(real number)를 그대로 보내기보다 단위를 정해서 정수화하여 보내는 것이 부동 소수점 표현 차이 때문에 고민할 필요가 없어 나도 정수화를 기본으로 한다.
엔디언(Endianness) 불일치가 전형적인 오류다
수치를 보낼 때 가장 흔한 것이 바이트 순서의 불일치이다. 보내는 쪽과 받는 쪽에서 상위 바이트부터 배열할지 하위 바이트부터 배열할지가 일치하지 않으면 완전히 다른 숫자가 된다.
PLC 측에서 32비트 정수를 조립할 때, 상위 바이트부터 배열하는 코드는 다음과 같다.
dwTemp := DINT_TO_DWORD(diValue);
abBuf[0] := DWORD_TO_BYTE(SHR(dwTemp, 24));
abBuf[1] := DWORD_TO_BYTE(SHR(dwTemp, 16) AND DWORD#16#FF);
...
받는 쪽에서 분해할 때는 이의 역순을 수행한다. 바이트를 DWORD로 되돌리고 왼쪽으로 시프트하면서 더한 다음, 마지막에 DINT로 변환한다. 조립과 분해는 쌍이므로, 한쪽을 AI에게 작성하게 했다면 다른 쪽은 '이것의 역순을 써달라'고 요청하는 것이 일관성을 유지하기 쉽다.
FH 측 매크로에서 이 바이트 구성을 바이너리로 보낼 경우, SendData를 사용하여 통신 모듈명, 정수 배열, 바이트 수를 지정한다. 정수 배열이 어떤 바이트 순서로 나오는지는 Z367에 기재되어 있지 않으므로 실제 장비에서 확인해야 한다. 순서를 맞추는 것은 설계자의 일이며, AI에게 맡기면 어느 한쪽의 편의대로 배열해 버린다. 나는 받는 쪽의 바이트 구성을 먼저 고정하고, 그것을 사양으로 삼아 AI에게 전달하는 방식을 사용한다.
문자열로 보낼 경우 개행 코드를 맞춘다
수치를 문자열로 보내는 간단한 방식도 있다. 바이트 배열을 구성할 필요가 없고 디버깅 시에도 읽기 쉬우므로, 속도 요구사항이 느슨하다면 이쪽이 더 편하다. 이때 구분자 개행 코드가 주의해야 할 부분이다. FH의 비동기 TCP(TcpNormal)에서는 구분이 CR(Chr$(13))로 고정되어 있어 변경할 수 없다. 비동기 UDP에서는 구분이 필요 없다. CR, LF, CR+LF 중에서 선택할 수 있는 것은 시리얼(SerialNormal) 설정이다. TCP로 보낼 것이라면 PLC 측을 CR 구분자에 맞추는 것이 좋다. 맞추지 않으면 구분자를 인식하지 못하고 수신이 멈춘다.
' FH 측: 비동기 TCP(TcpNormal)로 보내는 예시. TCP의 구분자는 CR 고정
MSG$ = "X=" + Str$(RESULTX#) + ",Y=" + Str$(RESULTY#)
SendString "TcpNormal", MSG$
AI는 개행 코드를 깊이 생각하지 않고 붙이기 때문에, 여기서는 사양으로 명시하여 전달해야 한다. SendString은 첫 번째 인수에 통신 모듈 이름이 필요하다. FH 매크로 변수에는 타입 식별자(&, #, $, !)가 필요하며 생략할 수 없다. SendString이 CR을 자동으로 붙이는지는 Z367에 명시되어 있지 않다. Z367의 예시는 Chr$(13)을 붙이지 않고 보내고 있지만, CR이 붙는지는 실기에서 확인해야 한다. 자릿수를 맞추고 싶다면 Str2$로 정수 자릿수와 소수 자릿수를 지정한다. PLC 측에서는 수신한 문자열을 구분자 문자로 분해하여 숫자로 되돌린다. ST의 문자열 함수로는 FIND나 MID 등이 사용할 수 있으므로, 그것으로 잘라내어 변환한다. 문자열 방식은 읽기 쉬워 디버깅이 편하지만, 구분자나 자릿수 처리에서 예상외로 재작업이 발생할 수 있다.
핸드셰이크 설계하기
계속 보내기만 하면 PLC 측이 받았는지 알 수 없다. 특히 계측 결과로 장치를 구동하는 경우, 오래된 결과로 작동하는 사고를 막기 위해 간단한 핸드셰이크를 넣는다.
내가 자주 사용하는 것은 PLC 측이 '계측 요구'를 보내고, FH 측이 계측하여 결과를 반환하고, PLC 측이 '수령'을 반환하는 3단계이다. FH 측은 수령이 올 때까지 다음 계측 결과를 보내지 않는다. PLC 측은 수령을 반환할 때까지 결과를 사용하지 않는다. 이 왕복 과정을 사양에 작성하고 양쪽 코드에 구현한다.
AI에게 이 절차를 쓰게 할 때는 상태 전이(state transition)로 전달해야 한다. '요구 대기 → 계측 → 결과 전송 → 수령 대기 → 요구 대기'와 같은 상태를 명시하면, 양쪽 코드가 짝을 이루어 나온다. 상태를 명시하지 않고
반대로 말하면, 맞물림 사양(噛み合わせの仕様)만 저희가 확보해 놓으면 구현의 수고는 상당히 줄일 수 있습니다. 설계와 구현의 분담을 명확히 하는 것이 통신을 AI와 결합할 때의 요령이라고 생각합니다.
혹시 본인의 현장에서 이 경로로 연결하고 있다는 이야기가 있다면 댓글로 알려주세요.
연재 '터미널도 Git도 없는 FA 개발 환경에서의 AI 코딩'
- 터미널 없이 AI 코딩 — PLC 엔지니어가 Claude Code가 아닌 Claude Desktop을 선택한 이유
- Claude에게 PLC 전문 지식을 상주시키기 — '스킬'로 허가 명령 목록과 함정 포인트 모음집을 갖게 하는 방법
- AI가 작성한 ST 코드가 Sysmac Studio에서 통하지 않는 전형적인 패턴 — 타입 지정 리터럴, 배열 INDEX, Execute 타입 FB
- FH 매크로를 AI에게 작성하게 하기 어려운 이유 — VBA처럼 보이지만 VBA는 아니다
- AI의 코드를 공장에서 사용하기 전 검증 프로토콜 — 사양 추적(仕様トレース), 책상 위 추적(机上トレース), 독립 리뷰
- 세션을 넘나들며 지식을 쌓기 — Claude Desktop의 메모리와 폴더 연결을 FA 개발에 활용
- 코드보다 문서가 많은 경우 — FA 업무의 비코드 공정을 AI에게 맡기기
- 이미지 센서와 PLC를 연결하기 — 오므론 FH×NX 통신을 AI와 설계할 때의 함정 (이 글)
토론(Discussion)

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기