plc와 pc 연동을 C#, python으로 구현해보고, npm에 modbus-serial 모듈이 있는 것을 알고 난 후 nodejs를 활용하여 plc와의 연동을 테스트해보았다.

 

예제 코드도 가지고 있었던 터라 아무 문제 없이 해결할 수 있을 줄 알았지만 예상치 못한 문제가 발생하였다.

 

Issue

콜백 함수의 향연으로 Thread를 신경쓰지 않아도 되는 nodejs 특성상 어떤 놈이 먼저 실행이 될 지 알 수가 없다...ㅋ

그러다 보니 serial 통신을 이용해서 하나의 데이터만 가져오는 것은 아무 상관이 없었는데, read를 두 번 이상 하니 이 함수 놈이 요청하고, serial통신 버퍼에 있는 데이터를 몽땅 가져오는 바람에 뒤에 실행되는 read함수에서 데이터가 없다며 에러를 토해내는 것이 아닌가..

 

그렇다면 내가 할 수 있는 최선은 이 중구난방으로 실행되는 비동기 함수들을 순차적으로 실행시켜주면 되는 일..

 

그래서 Async.series를 사용해서 문제를 해결하였다.

 

p.s. series는 단순 순차 실행, waterfall은 순차 실행인데 결과를 다음 콜백 함수에 전달 할 수 있다고 한다더라.

 

해결

개발 환경 : Ubuntu 64bit 16.04

IDE : vscode

nodejs version : v13.11.0

npm package : modbus-serial, async

 

더보기

코드

const ModbusRTU = require("modbus-serial")
var async = require("async");

var client = new ModbusRTU();
var timeoutConnectRef = null

function connect(){
    console.log("Connecting..!!");
    clearTimeout(timeoutConnectRef);

    if(client.isOpen){
        console.log('Already connected!!');
        run();
    }

    client.connectRTUBuffered("/dev/ttyUSB0", {dataBits: 8, stopBits: 1, baudRate: 115200})
    .then(setClient)
    .then(function() {console.log("Connected");})
}

function setClient(){
    console.log("Set client ID..!!");
    client.setID(1);
    client.setTimeout(3000);

    run();
}

var task = [
    function(callback) {
        client.readDiscreteInputs(1,4, function(err, res_read){
            console.log("L1: " ,res_read.data[0], res_read.data[1], res_read.data[2], res_read.data[3])
            callback()
        })
    },
    function(callback){
        client.readHoldingRegisters(1,4, function(err, res_read){
            console.log("L1Q: " ,res_read.data[0], res_read.data[1], res_read.data[2], res_read.data[3])
            callback()
        })
    }
]

function run(){
    var setLoop = setInterval(function(){
        async.series(task, function(err, results){
            console.log("done")
        })
    }, 1000)
}

connect()

 

출력 결과

ㅣ1은 bit를, L1Q는 word를 읽는 것.

github : https://github.com/Mistive/-js-modbusRTU.git

 

task 변수를 생성하여 순차적으로 동작시킬 task를 설정해주고, 1초에 한번씩 위의 동작을 반복하여 내가 필요한 값을 읽어들이는 작업을 수행하였다.

 

처음에 callback()을 function(callback){} 안에 넣지 않고 밖에 넣었더니 순차적으로 진행이 되지 않는 실수를..ㅎ;;

1번의 콜백 함수가 호출이 된 후, 콜백 함수가 수행이 되고, 1의 결과를 출력하고 그 다음 콜백 함수를 수행하는 형식으로 동작한다.

 

이거야 함수가 2개밖에 안되서 콜백에 콜백을 써도 되겠지만..... 한 3~4개만 되도 보는 사람 빡치게 만들기 충분한 코드가 될 것이라고 확답할 수 있다..ㅎㅎ

 

python으로 구현할 때는 thread timer를 이용하여 일정 주기로 Read&Write를 수행했는데, 흠.... js가 좀 더 깔끔한거 같기도 하고...ㅎㅎ

 

무튼 재밌다 코딩 ㅋㅋ

'PLC' 카테고리의 다른 글

[PLC, Python]PLC를 통한 PC 동영상 제어  (9) 2020.02.28

+ Recent posts