라즈베리파이 보드 Linux 기반에 NodeRED 플랫폼을 올려 사용 중인 환경이며,
상위 미쯔비시 PLC 와 Melsec Protocol 을 통해 데이터를 읽어 온다.
데이터를 웹 어플리케이션으로 제공하기 위해 JavaScript 와 여러 모듈을 사용한다.
여기서 소개할 내용은 PLC 데이터를 읽어 와서 양수 음수 값을 표현 해주기 이다.~
(다른팀에 개발해서 인수인계 해주었던 프로그램 수정 요청이 들어와 작업을 하게 되었다.)
그럼 그냥 데이터 읽은 데로 표현 해주면 될텐데 왜 신경을 써야하냐 인데...
보통 PLC 에서는 데이터 범위가 BYTE WORD DWORD QWORD 등이 있다.
C / C++ / C# 에서는 이러한 비트 연산 처리가 비교적 자유로운데 JavaScript 에서는 약간의?
제약이 있는것을 확인 했다.
우선 통신하여 읽어올 미쯔비시 PLC 의 데이터 상태를 보자면
- 하나의 address 당 BYTE 8bit
- 표현 해야 하는 데이터는 총 2개의 address 를 사용
- 즉 WORD 데이터로 write 하고 있는 상태
- 내가 읽어올 JavaScript 에서는 var 은 기본 QWORD 이다.
그러다 보니 아무리 시프트 연산자 처리를 통해서 작업을 해도 부호비트에 도달할 일이 있나...
가 원인이었던 것이다.
그럼 원인은 알게되었고 어떻게 수정을 할것이냐.. 나는 간단하게 강제로 부호비트쪽을 고정시키고
melsec 으로 받은 데이터를 에디션 하는 방식으로 수정 하기로 하였다.
if(0x80 & melsecInputData){
curr = 0xffffffffffff0000 | (map6400[21 + add * (buttonStatus-13)] << 8) | map6400[20 + add * (buttonStatus-13)];
}
else{
curr = (map6400[21 + add * (buttonStatus-13)] << 8) | map6400[20 + add * (buttonStatus-13)];
}
수정할 내용은 위와 같다. WORD 데이터 중 부호비트를 변경하려는 값이면
QWORD 부호비트와 실제 표현하려는 데이터를 합쳐서 표현하면, WORD 에서 표현하려는 음수와
데이터가 문제 없이 표현될 수 있다.
var map6000 = global.get('Memorymap6000')||0;
var map6100 = global.get('Memorymap6100')||0;
var map6200 = global.get('Memorymap6200')||0;
var map6300 = global.get('Memorymap6300')||0;
var map6400 = global.get('Memorymap6400')||0;
var map6510 = global.get('Memorymap6510')||0;
if(map6000 === 0 || map6100 === 0 || map6200 === 0 || map6300 === 0 || map6400 === 0 || map6510 === 0)
return null;
var ADDR_AXIS1_CUR_H = 0;
var ADDR_AXIS1_CUR_L = 1;
var ADDR_AXIS1_SPD = 2;
var ADDR_AXIS1_STA = 3;
var ADDR_AXIS1_ERR = 4;
var ADDR_AXIS1_WAR = 5;
var ADDR_AXIS1_POS = 6;
var ADDR_AXIS2_CUR_H = 300;
var ADDR_AXIS2_CUR_L = 301;
var ADDR_AXIS2_SPD = 302;
var ADDR_AXIS2_STA = 303;
var ADDR_AXIS2_ERR = 304;
var ADDR_AXIS2_WAR = 305;
var ADDR_AXIS2_POS = 306;
var ADDR_AXIS3_CUR_H = 0;
var ADDR_AXIS3_CUR_L = 1;
var ADDR_AXIS3_SPD = 2;
var ADDR_AXIS3_STA = 3;
var ADDR_AXIS3_ERR = 4;
var ADDR_AXIS3_WAR = 5;
var ADDR_AXIS3_POS = 6;
var curr;
var speed;
var status;
var error;
var warn;
var pos;
var add = 30;
var buttonStatus = msg.payload;
if(buttonStatus === undefined || buttonStatus === null || buttonStatus === 0)
{
//curr = (map[ADDR_AXIS1_CUR_L] << 8 | map[ADDR_AXIS1_CUR_H]) & 0xffff;
if(map[ADDR_AXIS1_CUR_L] & 0x80){
curr = 0xffffffffffff0000 | (map[ADDR_AXIS1_CUR_L] << 8) | map[ADDR_AXIS1_CUR_H];
}
else{
curr = (map[ADDR_AXIS1_CUR_L] << 8) | map[ADDR_AXIS1_CUR_H];
}
speed = map[ADDR_AXIS1_SPD];
status = map[ADDR_AXIS1_STA];
error = map[ADDR_AXIS1_ERR];
warn = map[ADDR_AXIS1_WAR];
pos = map[ADDR_AXIS1_POS];
}
if ((buttonStatus > 0) && (buttonStatus < 17))
{
if((buttonStatus >= 1) && (buttonStatus <= 4))
{//6000
//curr = (map6000[1 + add * (buttonStatus-1)] << 8 | map6000[0 + add * (buttonStatus-1)]) & 0xffff;
if(map[1 + add * (buttonStatus-1)] & 0x80){
curr = 0xffffffffffff0000 | (map6000[1 + add * (buttonStatus-1)] << 8) | map6000[0 + add * (buttonStatus-1)];
}
else{
curr = (map6000[1 + add * (buttonStatus-1)] << 8) | map6000[0 + add * (buttonStatus-1)];
}
speed = map6000[2 + add * (buttonStatus-1)];
status = map6000[3 + add * (buttonStatus-1)];
error = map6000[4 + add * (buttonStatus-1)];
warn = map6000[5 + add * (buttonStatus-1)];
pos = map6000[6 + add * (buttonStatus-1)];
}
else if((buttonStatus >= 5) && (buttonStatus <= 7))
{//6100
//curr = (map6100[21 + add * (buttonStatus-5)] << 8 | map6100[20 + add * (buttonStatus-5)]) & 0xffff;
if(map[21 + add * (buttonStatus-5)] & 0x80){
curr = 0xffffffffffff0000 | (map6100[21 + add * (buttonStatus-5)] << 8) | map6100[20 + add * (buttonStatus-5)];
}
else{
curr = (map6100[21 + add * (buttonStatus-5)] << 8) | map6100[20 + add * (buttonStatus-5)];
}
speed = map6100[22 + add * (buttonStatus-5)];
status = map6100[23 + add * (buttonStatus-5)];
error = map6100[24 + add * (buttonStatus-5)];
warn = map6100[25 + add * (buttonStatus-5)];
pos = map6100[26 + add * (buttonStatus-5)];
}
else if(buttonStatus === 8)
{//6200
//curr = (map6200[11] << 8 | map6200[10]) & 0xffff;
if(map[11] & 0x80){
curr = 0xffffffffffff0000 | (map6200[11] << 8) | map6200[10];
}
else{
curr = (map6200[11] << 8) | map6200[10];
}
speed = map6200[12];
status = map6200[13];
error = map6200[14];
warn = map6200[15];
pos = map6200[16];
}
else if((buttonStatus >= 9) && (buttonStatus <= 12))
{//6300
//curr = (map6300[1 + add * (buttonStatus-9)] << 8 | map6300[0 + add * (buttonStatus-9)]) & 0xffff;
if(map[1 + add * (buttonStatus-9)] & 0x80){
curr = 0xffffffffffff0000 | (map6300[1 + add * (buttonStatus-9)] << 8) | map6300[0 + add * (buttonStatus-9)];
}
else{
curr = (map6300[1 + add * (buttonStatus-9)] << 8) | map6300[0 + add * (buttonStatus-9)];
}
speed = map6300[2 + add * (buttonStatus-9)];
status = map6300[3 + add * (buttonStatus-9)];
error = map6300[4 + add * (buttonStatus-9)];
warn = map6300[5 + add * (buttonStatus-9)];
pos = map6300[6 + add * (buttonStatus-9)];
}
else if((buttonStatus >= 13) && (buttonStatus <= 15))
{//6400
//curr = (map6400[21 + add * (buttonStatus-13)] << 8 | map6400[20 + add * (buttonStatus-13)]) & 0xffff;
if(map[21 + add * (buttonStatus-13)] & 0x80){
curr = 0xffffffffffff0000 | (map6400[21 + add * (buttonStatus-13)] << 8) | map6400[20 + add * (buttonStatus-13)];
}
else{
curr = (map6400[21 + add * (buttonStatus-13)] << 8) | map6400[20 + add * (buttonStatus-13)];
}
speed = map6400[22 + add * (buttonStatus-13)];
status = map6400[23 + add * (buttonStatus-13)];
error = map6400[24 + add * (buttonStatus-13)];
warn = map6400[25 + add * (buttonStatus-13)];
pos = map6400[26 + add * (buttonStatus-13)];
}
else if(buttonStatus === 16)
{//6510
//curr = (map6510[1] << 8 | map6510[0]) & 0xffff;
if(map[1] & 0x80){
curr = 0xffffffffffff0000 | (map6510[1] << 8) | map6510[0];
}
else{
curr = (map6510[1] << 8) | map6510[0];
}
speed = map6510[2];
status = map6510[3];
error = map6510[4];
warn = map6510[5];
pos = map6510[6];
}
else
{
curr = 0;
speed = 0;
status = 0;
error = 0;
warn = 0;
pos = 0;
}
}
var d = [
{
"t": buttonStatus+"Axis 현재값",
"val1": curr
},
{
"t": buttonStatus+"Axis Speed Override",
"val1": speed
},
{
"t": buttonStatus+"Axis 동작상태",
"val1": status
},
{
"t":buttonStatus+"Axis 에러번호",
"val1": error
},
{
"t": buttonStatus+"Axis 경고번호",
"val1": warn
},
{
"t": buttonStatus+"Axis 실행위치결정No",
"val1": pos
}
]
msg.payload = d;
return msg;
이 노드 함수에 대한 코드 이다.
global 로 melsec protocol 에서 query 해 온 데이터들을 가져오게 된다. 저 부분이 궁금 하다면,
아래 링크를 들어가보면 된다.
2021.04.17 - [JavaScript] - [Node RED] JavaScript Melsec Protocol
[Node RED] JavaScript Melsec Protocol
라즈베리파이 보드 / 리눅스 OS에서 Node RED 플랫폼을 올려 사용중인 환경이다. 이전에는 Modbus TCP Protocol 기반에서 작업을 했지만 이번엔 미쯔비시 사 Melsec Protocol 을 사용해볼 것이다. 읽어올 메모
darkengineer.tistory.com
'Java Script' 카테고리의 다른 글
| [Node RED] Modbus Protocol JavaScript (0) | 2021.04.22 |
|---|---|
| [Node RED] JavaScript Melsec Protocol (2) | 2021.04.17 |
| [Node RED] Node JS 플랫폼 Session Cookie 기반 Login Logout 기능 만들기 (5) | 2021.03.20 |
| CSS, JQuery 를 이용한 웹 어플리케이션 적용 (0) | 2021.02.24 |