LS PLC로 Modbus 통신 프로그램을 만들다 보니까 한 가지 문제가 발생하였다.
Modbus 통신을 사용하면 PLC에 모드버스 Bit영역과 Word영역을 설정해야 하고 PC에서 설정한 영역의 Bit영역에 Read, Write 요청을 보내야 하는데 문제는 PLC는 일반적인 16진수 체계와 다르다는 것이다.
10진수 | 16진수 | PLC |
159 | 9f | 9f |
160 | a0 | 100 |
161 | a1 | 101 |
위 표처럼 주소가 있게 되는데 한마디로 PLC는 일의 자리 범위만 0~F이고 나머지 자릿수들은 0~9까지 사용한다.
예시로 M8206의 주소에 접근하고 싶다면 아래의 표처럼 변환을 해야한다.
자릿수 | 일반적인 16진수 변환 | PLC 주소 변환 코드 |
6 | 6 * 1 = 6 | 6 * 1 = 6 |
0 | 0 * 16 = 0 | 0 * 16 = 0 |
2 | 2 * 256 = 512 | 2 * 160 = 320 |
8 | 8 * 4096 = 32768 | 8 * 1600 = 12800 |
8206 변환 | 33286 | 13126 |
// PLC 주소를 변환하는 함수
function plcAddressToDecimal(address) {
let result = 0;
let base = 1;
for (let i = address.length - 1; i >= 0; i--) {
let char = address[i];
let value;
if (char >= "0" && char <= "9") {
value = char.charCodeAt(0) - "0".charCodeAt(0);
} else if (char >= "A" && char <= "F") {
value = char.charCodeAt(0) - "A".charCodeAt(0) + 10;
} else {
throw new Error(`Invalid character ${char} in address`);
}
result += value * base;
if (base === 16) {
base = 160; // 10진수 100의 위치를 16진수 160으로 처리
} else if (base === 160) {
base = 1600; // 16진수 1000의 위치
} else {
base *= 16;
}
}
return result;
}
코드는 이렇게 만들었다.
PLC의 M8206 주소에 접근하고 싶다면 이 함수를 통해 아래와 같은 과정을 거친다.
1. "8206" 문자열을 인자로 받는다.
2. 주소 문자열을 역순으로 처리한다.
for (let i = address.length - 1; i >= 0; i--)
주소 문자열을 뒤에서부터 하나씩 처리한다.
문자열 "8206"을 역순으로 읽는다. '6', '0', '2', '8'
3. 문자 값을 변환한다.
if (char >= "0" && char <= "9") {
value = char.charCodeAt(0) - "0".charCodeAt(0);
} else if (char >= "A" && char <= "F") {
value = char.charCodeAt(0) - "A".charCodeAt(0) + 10;
} else {
throw new Error(`Invalid character ${char} in address`);
}
문자가 숫자일 경우 문자를 숫자로 변환한다.
문자가 A~F 범위인 경우 문자를 16진수 값으로 변환한다.
각 문자를 10진수 값으로 변환한다.
'6' -> 6
'0' -> 0
'2' -> 2
'8' -> 8
4. 결과를 계산한다.
result += value * base;
현재 문자 값을 해당 자릿수의 가중치를 곱해서 결과에 더한다.
6 * 1 = 6
0 * 16 = 0
2 * 160 = 320
8 * 1600 = 12800
6 + 0 + 320 + 12800 = 13126
5. 가중치를 업데이트한다.
if (base === 16) {
base = 160; // 10진수 100의 위치를 16진수 160으로 처리
} else if (base === 160) {
base = 1600; // 16진수 1000의 위치
} else {
base *= 16;
}
자릿수별 다른 가중치를 곱하기 위해 가중치를 업데이트한다.
첫째 자리 : 기본 base인 1
둘째 자리 : 가중치 업데이트를 통해 16
셋째 자리 : 가중치 업데이트를 통해 160
넷째 자리 : 가중치 업데이트를 통해 1600
따라서 아래의 표처럼 주소가 변환이 된다.
자릿수 | PLC 주소 변환 코드 |
6 | 6 * 1 = 6 |
0 | 0 * 16 = 0 |
2 | 2 * 160 = 320 |
8 | 8 * 1600 = 12800 |
8206 변환 결과 | 13126 |
정리하자면 PLC의 주소체계는 일의 자리만 16진수를 사용하고 나머지 자릿수들은 10진수이다.
따라서 Modbus 통신으로 Bit 데이터를 송수신할 때는 주소를 위의 과정처럼 16진수 변환이 아니라 별도의 로직이 필요하다.