Looping problem for modbus

Hi all
I would like to increment the addresses but I can't.

[
    {
        "id": "f4b3eb2c38e0f0f1",
        "type": "inject",
        "z": "cde86a8aacec4fc2",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "1",
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 110,
        "y": 900,
        "wires": [
            [
                "880181626008d60b"
            ]
        ]
    },
    {
        "id": "880181626008d60b",
        "type": "function",
        "z": "cde86a8aacec4fc2",
        "name": "",
        "func": "for (var add = 1; add < 265; add++)\n{\n\n    msg.payload={\n       value:msg.payload,\n        'fc':03,\n        'unitid':2,\n        'address':add,\n        'quantity':68\n    }\n    return msg\n}\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 270,
        "y": 900,
        "wires": [
            [
                "753a1011362dbd2b"
            ]
        ]
    },
    {
        "id": "753a1011362dbd2b",
        "type": "debug",
        "z": "cde86a8aacec4fc2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 430,
        "y": 900,
        "wires": []
    }
]

image

with the code

for (var add = 1; add < 265; add++)
{

    msg.payload={
       value:msg.payload,
        'fc':03,
        'unitid':2,
        'address':add,
        'quantity':68
    }
    return msg
}

Thank you

Use node.send(msg) instead of return msg because with return you exit the itiration on the first loop

Use 'fc': 3 instead of 03 .. 03 is not valid

265 messages ? each requesting 68 registers ? is this necessary ? isnt the first request covering registers from the second ? review this

Hi, but there is a problem with this configuration...before change a message...you must receive a response from your unit id 2. After this you send next modbus message.

I believe the Modbus read nodes (node-red-contrib-modbus) will queue the commands if the option is set
and handle the request/reply sequentially.

image

but you are right .. this is something @patfrench has to keep in mind .. not to flood the device with to many msgs and give it time to reply.

The Modbus Queue Info node comes in handy for monitoring the amount queued commands.

image

Hello,

Thank you for your help.
"node.send(msg)" works perfectly

I had already enabled
image

My device has 264 addresses but we can only connect 32 sensors (sensor configuration = 68 registers)
I can't know in advance on which address the sensors are.

So I ask the 264 addresses.

I take the opportunity to ask another question:
I would like that at the end of my interrogation (or during) to be able to eliminate the empty addresses. And to have a table with the found addresses.

I try to progress alone but I still have trouble with the functions : I don't know how to get "modbusRequest.address".

in python I would have done something like this :

#if all registrer are empty => pass
#if if at least one register contains data => print address

if my_array.count(0) =! 68:
    print("address found =", modbusRequest.address)

Thank you

The Javascript equivalent would be the function Array.some( ... function that returns true/false ...), so you can try something like this:

let hasData = my_array.some(v => v > 0);
if (hasData) {
... save it ...
}

Alternately, you could just use Math.sum(my_array) === 0 as a test to see if there are any non-zero values in your array (which is only valid if you know that all value are non-negative).

so each sensor writes its value to 2 registers. 32bit value ? its a float ?

you dont have any documentation of your device to know to which addresses it writes for each sensor?

Maybe a Modbus Master utility can help to more easily identify what register addresses are written.
Link to QModMaster

and then use Node-red to read just the ones you need

Thank you for your answers.

I know the PLC (8 modbus lines) but I can't know the address where the customer put the sensors (32 sensor max).

I started by reading all the addresses in python with "minimalmodbus". I created a dictionary with :
key = address found
value = 68 registers

I need to read this once.

Then I can read the sensor measurement (on 2 registers) continuously because I know its address.

today I did this :

type ovar nombre_de_zero;
var adresse_trouve;
var mise_en_forme;
var numero_ligne;

const countOccurrences = (arr, val) => arr. reduce((a, v) => (v === val ? a + 1 : a), 0);
nombre_de_zero = countOccurrences(msg.payload, 0); 

if (nombre_de_zero != 68)
{   
    adresse_trouve = msg.modbusRequest.address;
   
    if (adresse_trouve >=1 & adresse_trouve<=32)
    {
        numero_ligne = "ligne 1";	
    }
    if (adresse_trouve >=33 & adresse_trouve<=64)
    {
        numero_ligne = "ligne 2";	
    }
    if (adresse_trouve >=65 & adresse_trouve<=96)
    {
        numero_ligne = "ligne 3";	
    }
    if (adresse_trouve >=97 & adresse_trouve<=128)
    {
        numero_ligne = "ligne 4";	
    }
    if (adresse_trouve >=129 & adresse_trouve<=160)
    {
        numero_ligne = "ligne 5";	
    }
    if (adresse_trouve >=161 & adresse_trouve<=192)
    {
        numero_ligne = "ligne 6";	
    }
    if (adresse_trouve >=193 & adresse_trouve<=224)
    {
        numero_ligne = "ligne 7";	
    }
    if (adresse_trouve >=225 & adresse_trouve<=256)
    {
        numero_ligne = "ligne 8";	
    }
       
    
    var d =
    [
        {
            "addr":adresse_trouve,
            "register": numero_ligne
        }
    ]
    msg.payload = d;
    return msg;

}r paste code here

image

it works but I can't do "addrow" in my ui-table so the values get overwritten.
I must admit that trying to do everything with node-red increases the difficulty

Thank you very much

sorry but i dont undestand why 68 has to be checked

you have 68 registers (32 sensors) BUT with each modbus request message the quantity has to be 2 and not the overal register quantity.

Try this flow that uses Context (you can read more about Context here)
and after each modbus reply, uses @shrickus suggestion to check the reply with some() and only then push() the valid reply ( > 0) to Context and produce an array of objects

[{"id":"5f5b68cda4f88116","type":"inject","z":"5847b7aa62131d37","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":1180,"wires":[["9c613f8cd08766e0"]]},{"id":"9c613f8cd08766e0","type":"function","z":"5847b7aa62131d37","name":"mod requests","func":"// initialize context to empty array\nflow.set(\"modbus\", []);\n\n\nfor (var add = 1; add < 265; add += 2) {\n\n    msg.payload = {\n        value: msg.payload,\n        'fc': 3,\n        'unitid': 1,\n        'address': add,\n        'quantity': 2\n    }\n    node.send(msg)\n\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":1180,"wires":[["3b03844a0c96b8b3"]]},{"id":"c987a5c623906e36","type":"debug","z":"5847b7aa62131d37","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":910,"y":1160,"wires":[]},{"id":"3b03844a0c96b8b3","type":"modbus-flex-getter","z":"5847b7aa62131d37","name":"","showStatusActivities":true,"showErrors":true,"logIOActivities":false,"server":"ebeab3422d31a778","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":580,"y":1180,"wires":[["cec6e78d7bfd1da3"],[]]},{"id":"cec6e78d7bfd1da3","type":"function","z":"5847b7aa62131d37","name":"filter","func":"// get context\nlet modbus = flow.get(\"modbus\");\n\n\n// if any of the 2 registers is > 0\nif (msg.payload.some(r => r > 0)) {\n    modbus.push({\n        unitId: msg.unitId,\n        address: msg.modbusRequest.address,\n        quantity: msg.modbusRequest.quantity\n    })\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":1160,"wires":[["c987a5c623906e36"]]},{"id":"77f18c710d15e562","type":"modbus-queue-info","z":"5847b7aa62131d37","name":"","topic":"","unitid":1,"queueReadIntervalTime":1000,"lowLowLevel":25,"lowLevel":75,"highLevel":150,"highHighLevel":300,"server":"ebeab3422d31a778","errorOnHighLevel":false,"showStatusActivities":true,"updateOnAllQueueChanges":false,"updateOnAllUnitQueues":false,"x":940,"y":1240,"wires":[[]]},{"id":"ebeab3422d31a778","type":"modbus-client","name":"","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"192.168.0.66","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":0,"commandDelay":50,"clientTimeout":500,"reconnectOnTimeout":false,"reconnectTimeout":2000,"parallelUnitIdsAllowed":false}]

image

ps. i didnt implement creating a table .. but that can be easily done by reading the modbus Context

I'm sorry i'm not clear.

this is an example :

configuration of sensor 1 : 'fc':03, 'unitid':2, 'address':1, 'quantity':68 [name_sensor,status,unit,decimal,threshold alarm1,threshold alarm2, …….] 68 registers

configuration of sensor 2 : 'fc':03, 'unitid':2, 'address':2, 'quantity':68
configuration of sensor 3 : 'fc':03, 'unitid':2, 'address':3, 'quantity':68
configuration of sensor 4 : 'fc':03, 'unitid':2, 'address':129, 'quantity':68
configuration of sensor 5 : 'fc':03, 'unitid':2, 'address':160, 'quantity':68

read value/measure dynamic sensor 1 : 'fc':03, 'unitid':2, 'address':2001, 'quantity':1
read value/measure dynamic sensor 2 : 'fc':03, 'unitid':2, 'address':2002, 'quantity':1
read value/measure dynamic sensor 3 : 'fc':03, 'unitid':2, 'address':2003, 'quantity':1
read value/measure dynamic sensor 4 : 'fc':03, 'unitid':2, 'address':2129, 'quantity':1
read value/measure dynamic sensor 5 : 'fc':03, 'unitid':2, 'address':2160, 'quantity':1

I'm querying a transfer table.
do you understand ?

Thank you

so the Sensors are Modbus devices themselves ?

Yes, they are modbus