Skip to content

Instantly share code, notes, and snippets.

@kalkov
Forked from groupsky/noark-ex9em.js
Last active May 20, 2022 12:30
Show Gist options
  • Save kalkov/1bdd30b929681822427a4acea037f756 to your computer and use it in GitHub Desktop.
Save kalkov/1bdd30b929681822427a4acea037f756 to your computer and use it in GitHub Desktop.
ModBus read for Noark Ex9EM 1P 1M 80A MO MT
const data = msg.payload
const voltage = data[0]*0.1
const current = data[1]*0.1
const phase = data[2]*0.1
const power = data[3]
const power_reactive = data[4]
const power_apparent = data[5]
const power_efficiency = data[6]*0.1
const total_power = (data[7] * (1 << 16) + data[8]) / 100
const total_power_reactive = (data[9] * (1 << 16) + data[10]) / 100
const payload = {
voltage: {value: voltage, unit: 'V'},
current: {value: current, unit: 'A'},
phase: { value: phase, unit: 'Hz'},
power: { value: power, unit: 'W'},
power_reactive: { value: power_reactive, unit: 'VAr'},
power_apparent: { value: power_apparent, unit: 'VA'},
power_efficiency: { value: power_efficiency, unit: '%'},
total_usage: { value: total_power, unit: 'kWh'},
total_power_reactive: { value: total_power_reactive, unit: 'kVArh'}
}
return { payload: payload }
#!/usr/bin/env node
/*
* ModBus read for Noark Ex9EM 1P 1M 80A MO MT Electric Meter
* https://www.noark.com.hr/en/products/107281
*/
////////////////
// CONFIGURATION
////////////////
const DEVICE = '/dev/ttyUSB0'
// possible values 1200, 2400, 4800, 9600, default 9600
const BAUD_RATE = 9600
// possible values 'even', 'odd', 'none', default 'even'
const PARITY = 'even'
// possible values 1-247, default 1
const ADDRESS = 2
////////////////////
// END CONFIGURATION
////////////////////
const ModbusRTU = require('modbus-serial')
// create an empty modbus client
const client = new ModbusRTU()
// open connection to a serial port
client.connectRTUBuffered(DEVICE, { baudRate: BAUD_RATE, parity: PARITY })
// set timeout, if slave did not reply back
client.setTimeout(250)
// list of meter's id
const metersIdList = [ADDRESS]
const getMetersValue = async (meters) => {
try{
// get value of all meters
for(let meter of meters) {
await getMeterValue(meter)
// wait 100ms before get another device
await sleep(100)
}
} catch(e){
// if error, handle them here (it should not)
console.log(e)
} finally {
// after get all data from salve repeate it again
setImmediate(() => {
getMetersValue(metersIdList)
})
}
}
const getMeterValue = async (id) => {
try {
// set ID of slave
await client.setID(id);
// read the registers starting at address 0 (first register)
let val = await client.readHoldingRegisters(0x00, 11);
const v = val.data[0]*0.1
const i = val.data[1]*0.1
const phase = val.data[2]*0.1
const p = val.data[3]
const pr = val.data[4]
const pa = val.data[5]
const x = val.data[6]*0.1
const total_p = (val.data[7] * (1 << 16) + val.data[8]) / 100
const total_pr = (val.data[9] * (1 << 16) + val.data[10]) / 100
console.log('====================')
console.log(`Electric Meter ${id}`)
console.log(`V = ${p} V`)
console.log(`I = ${i} A`)
console.log(`phase = ${phase} Hz`)
console.log(`P = ${p} W`)
console.log(`Pr = ${pr} VAr`)
console.log(`Pa = ${pa} VA`)
console.log(`?? = ${x} P`)
console.log(`total a = ${total_p} kWh`)
console.log(`total r = ${total_pr} kVArh`)
console.log(`kpd = ${(1-pr/p)*100}%`)
} catch (e) {
return -1
}
}
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
// start get value
getMetersValue(metersIdList);
{
"name": "test-modbus",
"version": "1.0.0",
"description": "",
"author": "Geno Roupsky",
"license": "ISC",
"dependencies": {
"modbus-serial": "^8.0.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment