Java Script

[Node RED] JavaScript 부호 비트 연산

다크엔지니어 2021. 4. 17. 13:17
반응형

라즈베리파이 보드 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

 

반응형