Honeywell HC900을 Modbus TCP로 직접 폴링 → gRPC → C# 크롤러 → PostgreSQL. 기존 Experion OPC UA 데이터 경로를 HC900 직접 통신으로 대체. - industrial-comm/cpp: C++ Modbus 게이트웨이 (gRPC 서버) - src: C# .NET 8 ASP.NET Core 크롤러 + 웹 UI (3-Layer) - mcp-server: Python FastMCP (RAG/NL2SQL/P&ID) - 다중 컨트롤러(N-Controller) 지원 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.4 KiB
HC900 직접 통신 아키텍처 브레인스토밍
참고: 51-52-25-111-HC900-Process-Controller-Communications-manual.pdf (Rev 13, April 2017)
HC900 Modbus 통신 요약 (매뉴얼 기반)
기본 프로토콜
- Modbus TCP (Ethernet) + Modbus RTU (RS232/RS485)
- IP 기본값: 192.168.1.254
- 최대 동시 연결: C30/C50=5, C70/C70R=10
- Unit ID: Modbus TCP에서는 사용 안 함 (00)
- Double Register Format: HC900 기본값은 FP B (Big Endian) — 4,3,2,1 byte 순서
- Experion/Honeywell PlantScape는 FP B 사용
- Modicon/Wonderware 표준은 FP LB (Little Endian Byte-Swapped) — 2,1,4,3
지원 Function Code
| Code | 기능 | HC900 사용 |
|---|---|---|
| 03 | Read Holding Registers | 주력 — float/int holding register 읽기 |
| 04 | Read Input Registers | Analog Input 전용 (v4.0+에서 03 대체) |
| 06 | Preset Single Register | Integer 단일 레지스터 쓰기 |
| 16 (10h) | Preset Multiple Registers | Float 다중 레지스터 쓰기 |
| 01/02 | Read Digital Output/Input | DI/DO 전용 |
| 05 | Force Single Coil | DO 제어 |
Fixed Map 개요 (Table 6-1)
| 시작 주소 | 끝 주소 | 내용 | 비고 |
|---|---|---|---|
| 0000 | 003F | 시스템 파라미터 | Instrument Mode, Load Recipe 등 |
| 0040 | 00FF | Loop #1 (PID) | 192bytes: PV, SP, OP, alarms, mode 등 |
| 0140 | 01FF | Loop #2 | Loop마다 256(0x100) offset |
| ... | ... | Loop #3~#24 | |
| 1800 | 187F | Analog Input #1~#64 | FC03 전용, Rack#1 첫 8슬롯만 (v4.0+ 불가) |
| 18C0 | 1D6F | Variable #1~#600 | R/W 가능 |
| 2000 | 27CF | Signal Tag #1~#1000 | Legacy, Read-only |
| 3B60 | 5A9F | Signal Tag #1~#4000 | HC900 범위, Read-only |
| B000 | B3E7 | User Defined | R/W (signal=read-only, variable=R/W) |
| 7840 | 7FFF | Loop #25~#32 | 확장 루프 |
Loop 파라미터 (Table 6-3, Loop #1 기준)
| Offset | 파라미터 | Type | Access |
|---|---|---|---|
| +00 | PV | float | R |
| +02 | Remote SP (SP2) | float | R/W |
| +04 | Working SP | float | R/W |
| +06 | Output (OP) | float | R/W |
| +0C | PV (중복) | float | R |
| +0E | PV (다른 타입) | float | R |
| +2A | LSP #1 | float | R/W |
| +5A | Auto/Manual State | bit | R/W |
| +5E | Loop Status | bit | R |
| +BA | Enable/Disable Fuzzy | bit | R/W |
| +BB | Demand Tune Request | bit | R/W |
| +BD | SP State (SP1/SP2 선택) | bit | R/W |
| +BE | Remote/Local SP State | bit | R/W |
| +BF | Tune Set State | bit | R/W |
루프마다 192개(0xC0) 레지스터 사용. Loop #N 시작주소 = 0x40 + (N-1) * 0x100
Signal Tags (Table 6-11)
- Legacy: 2000
27CF (#1#1000), HC900: 3B605A9F (#1#4000) - 각 태그는 float 2-register 사용 (even address)
- Tag 번호와 실제 태그명의 매핑은 HC Designer의 "Tag Information" 리포트에서 확인
- Read-only
Variables (Table 6-5)
- 18C0
1D6F (#1#600) - 각 2-register float
- R/W 가능
Float 포맷 (매뉴얼 3장)
HC900 컨트롤러는 Double Register Format을 설정 가능:
- FP B (기본): Big Endian — Byte4,3,2,1 → Reg N(High)=Byte4,3 / Reg N+1(Low)=Byte2,1
- FP LB: Little Endian Byte-Swapped — Byte2,1,4,3 → Reg N(High)=Byte2,1 / Reg N+1(Low)=Byte4,3
HC900_FLOAT 포맷 (= FP B): BigEndian byte order + LowFirst (word swap)??
현재 구성 요소
| 구성 요소 | 플랫폼 | 통신 방식 | 용도 |
|---|---|---|---|
| ExperionCrawler | Ubuntu (C# .NET 8) | OPC UA → Experion HS R530 | OPC UA 데이터 수집/저장/API |
| industrial-comm | Ubuntu (C++17) | Modbus TCP → HC900 | HC900 Modbus TCP 라이브러리 (libcomm_core.so) |
| NKOpcTunnel | Windows (C++) | OPC Classic 터널링 (TCP/IP) | DCOM 없는 OPC Classic 통신 (본 프로젝트와 무관) |
목표
ExperionCrawler의 OPC UA → Experion 경로를 Modbus TCP → HC900 경로로 대체한 변형 버전 제작.
Experion을 거치지 않고 HC900과 직접 통신.
제안 아키텍처
HC900 Controller
│ Modbus TCP (port 502)
▼
industrial-comm (C++ gateway, standalone process)
│ gRPC
▼
HC900Crawler (C# .NET 8, ExperionCrawler 변형)
│ EF Core
▼
PostgreSQL (iiot_platform)
필요한 작업
Phase 1: C++ 게이트웨이 완성
- main.cpp 에 gRPC 서버 추가
- gRPC proto 정의 (ReadTag, WriteTag, ReadMultiple, BrowseRegisterMap)
- watchdog 스레드 실제 구현 확인
- cmake에 modbus_tcp.cpp, app_init.cpp 포함
Phase 2: C# 변형 앱
ExperionCrawler에서 OPC UA 계층을 gRPC Client로 교체:
| 기존 (OPC UA) | 변경 (Modbus TCP via gRPC) |
|---|---|
| IExperionOpcClient | IModbusTcpClient (gRPC 호출) |
| ExperionRealtimeService (Subscription) | Hc900RealtimeService (폴링 기반) |
| IExperionOpcWriteClient | IModbusWriteClient (gRPC write) |
| BrowseNodesAsync | Hc900RegisterMapLoader (설정 파일 기반) |
Phase 3: 레지스터-태그 매핑
HC900은 OPC UA의 NodeId 개념이 없음 → 레지스터 주소-태그 매핑 필요
{
"registers": [
{ "address": 100, "tag": "TI-6101", "type": "float", "format": "HC900_FLOAT" },
{ "address": 102, "tag": "PIC-6102.SP", "type": "float", "format": "HC900_FLOAT" },
{ "address": 200, "tag": "XV-6201", "type": "uint16" }
]
}
유지되는 ExperionCrawler 기능
- DB 스키마 (realtime_table, history_table, event_history_table, tag_metadata)
- Background Service 패턴
- Web API / Controllers
- PostgreSQL + TimeScaleDB
- P&ID 관련 기능 (옵션)
- Feedforward Advisory (옵션)
HC900 Modbus Mapping: Fixed vs Custom
HC900은 두 가지 Modbus 레지스터 매핑 방식을 지원함 (매뉴얼 §1.1).
실무적 결론
- 대부분 Fixed Map을 기본 사용 — PID loop 32개 초과 같은 특별한 경우에만 Custom Map으로 전환
- Custom Map으로 전환해도 Fixed Map의 주소 체계가 그대로 Custom Map으로 전달됨 (기존 주소 유지)
- 따라서 매뉴얼의 Fixed Map (Table 6-1)이 실질적인 표준 주소 맵
Fixed Map (고정 맵)
| 특징 | 내용 |
|---|---|
| 제한된 파라미터, 제한된 수량 | 최대 32 loops, SP Programmer 4~8개 등 |
| 그룹화된 주소 범위 | Loop는 0x40~0xFF 범위 고정 |
| 모든 파라미터가 항상 매핑 | PID loop 40여개 파라미터 모두 |
| 편집 제한 | 주소 범위 내에서 이동만 가능 |
| Firmware 무관 | 모든 HC900 버전에서 사용 가능 |
Custom Map (사용자 정의 맵)
| 특징 | 내용 |
|---|---|
| 많은 파라미터 선택 가능 | 주소 범위만 허용하면 무제한에 가까움 |
| 선택적 매핑 | 필요한 파라미터만 골라서 할당 (예: PV, SP, OP만) |
| 유연한 주소 지정 | 어느 주소에나 할당 가능 |
| 추가 블록 지원 | Push Button, AGA, Calendar Event, XYR5000, UDC Loop 등 |
| v4.0 이상만 가능 |
핵심 차이점
Fixed Map: PID Loop #1 → 항상 주소 0x40~0xFF (PV/SP/OP/Alarm/... 전부)
Custom Map: PID Loop #1 → 사용자가 지정한 주소 (PV만 별도 주소에 할당 가능)
→ Custom Map을 사용하면 매뉴얼의 Fixed 주소 테이블이 적용되지 않음 → Custom Map의 주소는 HC Designer에서 "Block Modbus Address" 리포트로만 확인 가능
확인 필요: 대상 HC900 컨트롤러들이 Fixed Map을 쓰는지, Custom Map을 쓰는지?
HC900 레지스터 맵 확보 방안
HC900 Controller Designer Software에서 통신레지스터 주소와 태그명을 추출 가능.
CDE 파일은 binary export 포맷이라 직접 파싱은 복잡했으나, Designer 프로그램 자체에서 다음 리포트를 CSV/텍스트로 export 가능 (매뉴얼 §1.1):
- Tag Information Report — Variables와 Signal Tags를 번호순 + Modbus 주소와 함께 리스트
- Block Modbus Address Report — 모든 주요 블록의 시작 주소
설계 소프트웨어에서 추출해야 할 핵심 정보:
- 각 블록(AI/PID/AO)의 Modbus holding register 시작 주소
- 블록별 파라미터의 register offset map (PV, SP, OP, MODE 등)
- 블록 태그명 (예: "TI-6101", "PIC-6102")
- 데이터 타입 (float 2-register, uint16 1-register 등)
오픈 이슈
- C++ 게이트웨이 통신 방식: gRPC vs Unix Socket vs Raw TCP?
- 레지스터 맵 확보: CDE 파싱 재도전? JSON 수동 정의? 스캔 툴?
- ExperionCrawler를 fork? 아니면 같은 솔루션에 확장?
- HC900 float format 외에 다른 데이터 타입도 HC900 특화 포맷이 있는가?
- 프로젝트명: HC900Crawler? ModbusCrawler?