New! Conversion data array boolean to char. Reading module inputs

Hello everyone! I am new and I am learning little by little. I got stuck in a data conversion.
I have a module with 16 digital inputs. This module communicates by modbus. With a command I read an array of 16 booleans.
I would like to split it into two chars (1byte and 1byte).
Could you help me please?

nodered2

This is confusing. Are you reading two bytes or are you reading 16 boolean expressions? Either the input coming out is incorrectly formatted or you're reading the output incorrectly.

That aside, you can easily split this into two groups using the .slice() method.

var msg1.payload = msg.payload.slice(0,8);
var msg2.payload = msg.payload.slice(8,8);

That will give you a split of your array. That being said, I question how you're implementing your MODBUS node. It sounds like your MODBUS device is trying to send two bytes and you're getting it as individual bits instead of it being read as bytes. Or your device is trying to track the condition of 16 digital inputs, which at that point, why split it into two groups of 8 when you can just pull individual array positions to get the data? A little more information on your setup will be very helpful in solving your underlying problem.

1 Like

The modbus node outputs both an integer array and a byte buffer.

Change the debug node to show complete message, enable it and look inside the output of the modbus msg. Something like msg.responseBuffer (I forget)

Failing that, install node-red-contrib-buffer-parser (it is designed for this task)

1 Like

Yes. @Johnn This is why it's important to list what your node configuration is as well as your setup. Once you can post some more details so we understand what your setup is, physically and programmatically, we can help you figure out what you're wanting to know. MODBUS is kinda tricky, purely because you need to know not only HOW your device feeds back data (i.e. integer, float, boolean, etc.), but you need to know how to parse that in Node-Red. The MODBUS node does a great job getting data. But it's not so great at making it human readable when and how you need it.

1 Like

Hello! Thank you very much for your help.

Sorry if it's a bit confusing. I'll try to explain better:

I have a module with 16 digital inputs.
I use the function FC2-Read Input Status.

This is the output of debug2:

The reason I want to split it into a char(0-255) and a char(0-255) is because I want to send it to a controller that splits it automatically.

Attached is the command sheet for the digital input device:

Thank you very much!!!

Interesting. Very interesting indeed. I can't say that I've ever heard of a similar arrangement outside of building an old lights-and-switches computer. There are a few options available to you that you might want to explore.

First, FC2 is capable of getting you information, true. But FC3 is what will read your status register. Have you looked to see if there was a register associated with groups of inputs? You may be able to read your bytes directly from your first module without any need for translation and may be able to avoid all this mess altogether. I've worked with a few MODBUS objects and I've never really found a use for using FC2 vs. FC3 if I had the ability to read a register.

Next, it's not easy to do, but you could do a bitwise shift and push the individual inputs into a variable that would hold them. The problem is, I don't know of a Javascript variable that is a single byte, so you would have to manipulate based on that. Perhaps when you send it out to the controller, the method you use to send it will translate it correctly into a byte. But again, it's not super-straightforward to do bitwise shifting into a variable.

Which brings me to a likely simple answer Javascript does support.

var arr = msg.payload;
var byte1 = (arr[0]*1)+(arr[1]*2)+(arr[2]*4)+(arr[3]*8)+(arr[4]*`6)+(arr[5]*32)+(arr[6]*64)+(arr[7]*`128);
var byte2 = (arr[8]*1)+(arr[9]*2)+(arr[10]*4)+(arr[11]*8)+(arr[12]*`6)+(arr[13]*32)+(arr[14]*64)+(arr[15]*`128);

I just moved the array into a variable that can be more easily typed than msg.payload over and over. But, you can multiply numbers by boolean in Javascript and it's completely normal. This is simply converting binary to decimal as a person would be taught to do it and storing the number in a variable. Multiplying a given spot by the boolean either produces that spots value for a true or a 0 for a false. Added together, you get the binary representation. Those variables can then be sent on to whatever needs them. Obviously you'll need to account for whether you have MSB or LSB first in your array and adjust accordingly.

All that being said, I would still double check with your module to see if you can use FC3 to get a status register and completely bypass all the issues of converting and whatnot. But if not, binary conversion to decimal by math is your simplest answer.

1 Like

Hello again!

Adding two functions with your response, the conversion does it perfectly.

var arr = msg.payload;
var byte1 = (arr[0] * 1) + (arr[1] * 2) + (arr[2] * 4) + (arr[3] * 8) + (arr[4] * 16) + (arr[5] * 32) + (arr[6] * 64) + (arr[7] * 128);
msg.payload = byte1;
return msg;

With input 1 and 3 active, after the function I have an output value of 5. Great!

On the subject of the function, unfortunately I can't use the FC3 function because the input module doesn't support it. This causes me a problem. I have 6 modules with 16 inputs each (96 inputs).
I think the bus saturates using the FC2 function because it has to read a lot of registers very fast. Can I be right?

Captura

Right now I only have one module connected and these errors in no time.
Read every 100ms

I attach my modbus server configuration:

Your responses are being of great help. Thank you very much!

That is a very high speed read rate on those. Does it absolutely need to be that fast? What is your setup trying to do that requires that high of a refresh rate on data inputs? Let's do some math.

Your serial transmission is right now 9600 baud. 9600bps. Bits per second. You have to divide that in half because your serial isn't full duplex, so each direction effectively gets 4800bps. When you have a 100ms window, you get 480 bits each direction to work with. That's 60 bytes. Your simplest MODBUS query looks like this:


(from Modbus Protocol)

That's 8 bytes just to make the query. Another 7 makes up the response that goes to that. If there was no lag in your MODBUS module, that baud rate would be sufficient. But, there is lag. Once you make the query, the module has to form a response and send it before you make the next query. And 100ms is a very short window to have to make that happen for some controllers. You're sending a query to check 16 positions which may add another 15 bytes to your query and response or more. That adds lag to perform each check and build each response. Chances are your bumping against several thresholds in your setup.

But never fear, there are options. If you have the option on your device to increase your baud rate, do so. That will increase your bandwidth and allow for more time to form responses and send them in your 100ms window. That's assuming that your problem is bandwidth and not something else. Your next option is using a flex-getter node and having a function pass in your query parameters and waiting for a response on your flex-getter output before sending the next query. That will make your code respond at the speed of the device instead of having a pre-set window to work in. It may slow down your setup to do that, but you're guaranteed that you won't have any communication issues. Queries sent through the flex-getter will respond at the speed of the bus so each module communicates when the bus is open. Instant traffic regulation.

In short, I would say you really need to evaluate your setup and what you need it to do. It's likely it needs to be adjusted to handle what you're expecting or your expectations need to adjust to accommodate its capabilities. It sounds like you're initially getting what you need and then it just stacks up and dies. Comb through it's capabilities and adjust accordingly, whether it's speeding up the modules or slowing down your responses. You should be fine after that.

1 Like

Hello! Yes, as you say, it is a very fast reading speed.
The idea is to use these digital inputs for pushbuttons. The reading has to be fast enough to be able to add multi-tap functions in the future.

I can try to increase the speed of the bus. I think this will help me somewhat.

I find it very interesting to be able to add "Modbus Flex Getter" and that it be this function that manages the data on the bus. It is important not to have saturation errors.

I have been doing some tests with this function and I get an error:

Request-Input1:

msg.payload = { value: msg.payload,
'fc': 2,
'unitid': 1, 
'address': 0 , 
'quantity': 16 }; 
return msg;

Request-Input3:

msg.payload = { value: msg.payload,
'fc': 2,
'unitid': 3, 
'address': 0 , 
'quantity': 16 }; 
return msg;

Debug:

If I test the functions separately, they work fine. When they are together is when it fails. This is normal?

Thank you very much

So essentially you're polling the buttons every 100ms for state changes? Stuff like that doesn't scale well, especially when you have such tight windows. Do your controllers not have the option of sending data on a state change? That would be much more efficient.

Which now opens up for more possible issues. You have your Node-Red setup using a serial communication connection at 9600 to what would be some kind of USB serial to possibly a RS-485 bridge? My guess is it's communicating with all the controllers in series? Or is it a parallel connection with all six units? Either way, that can introduce more delay I didn't account for previously. But in general, you're most likely running into communication issues still.

Try this just to get an idea of what your setup is capable of right now. Change your inject node to send a single injection automatically and then have the output of the flex-getter feed back to the function nodes. Your function nodes will need to detect which request was last sent and the allow the other request to be sent after. That will be part of the msg object, which should include the query that produced the results. Scrub the msg object of all previous data in your function (the data should be in your debug anyways) and send the next request. Doing this will clock your setup to see how quickly you can poll your MODBUS units successfully as it will restrict itself to response speed. If you have the ability, open it up to all your MODBUS units as a full function timing test. Once you have that info, we can work from there. It may be that if you don't have the option of reactive communications (i.e. send message on button press), you may need to add five more serial communication modules so you can communicate to all the other units in parallel. It may not be a limitation of Node-Red as much as a physical limitation of the setup itself.

1 Like

Hello!

All modules are on the same bus, devices in parallel.

I have applied the changes, one output feeds the next and so on. Is that how you said?

Without changing the bus speed (default 9600), I have managed to read at a speed of 0.3s without errors. I have done another test at 0.25s and I have many errors.

For further experimentation, I have increased the bus speed to 38400.
Reading speed at 0.25s and 0.2s with some errors. Finally at 0.15s I have bus saturations.

I could say that there is no significant improvement with the change of bus speed (rare).

I have a doubt about adding the readings in series, it could be the case that I need to make a reading of a device every 5 minutes and another reading of another device every 1 minute. How could I insert this condition? I have tried a delay but it affects the rest of the series that hangs below.
I don't need this last one right now, it's just to learn.

Once again, thank you so much!

Not quite what I was thinking of, but it sounds like you got some kind of meaningful data from it. This was more the layout I was envisioning for you.


Notice how the output goes right back to the input of the functions. Your timestamp node will only fire once to start the actions and only to the first function. Inside that function is a check to see if it's the function that received the last call (look at your whole object debug info to see unique message identifiers like topic or something). If it sent the last call, it ignores the message. If it wasn't, it scrubs msg (i.e. msg = {}) and sends it's own message to get it's own query.

A better implementation would be to have all the calls in one function.


If the function receives a call from the inject node (remember, use something unique to identify), it spits out the system time and sends the first message. As the function receives a MODBUS response, it fires off the next call. When the result from the last message is received, it spits out the system time and ends. So seven if statements (1-6 and end) and a debug on the single function node. You can also setup the function node to have two outputs and send the system time to output 2 (node.send([null,msg]); to not send on output one and send on output 2). If you temporarily disconnect the debug on the output of the flex-getter, you'll get two debug messages with the start and end system time. That's how long it takes to go through six calls with as little overhead as possible, since printing debugs takes a lot of time and would introduce artificial delays. That would give you the best info on how quick your setup can make six MODBUS calls on the serial bus you have implemented.

Let me know if that doesn't make much sense.

1 Like

Hello!

I understand what you mean but considering that I have been in node-red for a week, I don't know how to implement it. I am sorry.

I have tried the following without success


I put the delay because the program saturated me and I prefer to do the tests with longer times and then adjust them to my needs.

code inside function:
(unsuccessfully)

if (msg.modbusRequest.unitid == 3) {
    msg.payload = {
        value: msg.payload,
        'fc': 2,
        'unitid': 1,
        'address': 0,
        'quantity': 16
    };
    return msg;
} else if (msg.modbusRequest.unitid == 1) {
    msg.payload = {
        value: msg.payload,
        'fc': 3,
        'unitid': 1,
        'address': 0,
        'quantity': 16
    };
    return msg;
}  

This is the output message of a successful read (not using the code above).

How could I implement everything in the same function with an adjustable time according to my needs?
Thanks and sorry for being a newbie :slightly_smiling_face:

Not an issue. Your looking for a setup like this.
image

if(msg.payload == "begin"){
    msg.payload = {
        'fc': 2,
        'unitid': 1,
        'address': 0,
        'quantity': 16
    };
    var nowTime = Date.now();
    return([msg,{"payload":nowTime}]);
} 
else{
    if(msg.modbusRequest.unitid  == 6){
        var nowTime = Date.now();
        return([null,{payload:nowTime}]);
    }
    var count = msg.modbusRequest.unitid + 1;
    msg.payload = {
        'fc': 2,
        'unitid': count,
        'address': 0,
        'quantity': 16
    };
    return([msg,null]);
}

What this does is send a trigger into the function with a payload of "begin". When the function receives that payload, it creates the payload your MODBUS device needs to process a request. Then (more crucially) it gets the system time in milliseconds and sends both messages out. The one message triggers the MODBUS request and the other message hits the debug so you see the system time (will be a really, really big number). That's the first block of the function.

The second block of the function triggers when the flex-getter returns a message. The payload won't contain "begin" because it will now contain the results of the MODBUS communication. It will also have the unit ID that processed the request. The first thing I do is see if the unit that processed the request is ID 6 (you have 6 units, I'm just assuming their ID is 1-6 accordingly). If unit 6 processed the request, that means it's made it through all your units. The end time is recorded and sent out on debug. Because nothing is going out on the MODBUS channel (the null), nothing will trigger another communication and nothing will trigger another iteration of the function. The loop ends. If, however, the 6th unit did not process the request, the unit ID increments to the next unit and sends out a request. This continues until the 6th unit sends back results and punches the time clock.

That loop (properly adjusted for your specific setup) should give you a start time and end time in your debug window you can use to calculate how long it takes to have six requests processed on your bus system. This will saturate your bus, hopefully, which is what we want. We want the maximum capabilities your system can handle so you know what you have to work with. But it will be a brief saturation to time it.

And like I said, you'll need to adjust your code to accommodate the requirements of your MODBUS. This was just a barebones example to illustrate how it works. Let me know if anything is confusing.

1 Like

Hello madhouse!
I have successfully tested the proposal.
The results are optimistic.

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)msg : Object

object

payload: 2022-10-15T07:13:47.104Z

_msgid: "b12812a412b53e24"

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)93a8f1f404f0e670 : msg : Object

{ _msgid: "b12812a412b53e24", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a5dabf726ad632b11b2ed", modbusRequest: object … }

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)93a8f1f404f0e670 : msg : Object

{ _msgid: "b12812a412b53e24", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a5dabf726ad632b11b2ee", modbusRequest: object … }

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)93a8f1f404f0e670 : msg : Object

{ _msgid: "b12812a412b53e24", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a5dabf726ad632b11b2ef", modbusRequest: object … }

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)93a8f1f404f0e670 : msg : Object

{ _msgid: "b12812a412b53e24", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a5dabf726ad632b11b2f0", modbusRequest: object … }

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)93a8f1f404f0e670 : msg : Object

{ _msgid: "b12812a412b53e24", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a5dabf726ad632b11b2f1", modbusRequest: object … }

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)93a8f1f404f0e670 : msg : Object

{ _msgid: "b12812a412b53e24", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a5dabf726ad632b11b2f2", modbusRequest: object … }

15/10/2022, 9:13:46[node: byte1](http://homeassistant:8123/api/hassio_ingress/W-k-PM7qxZvF06h4xSYghc_cWI3PuyXykyzxGadY6Qc/#)msg : Object

object

payload: 2022-10-15T07:13:47.280Z

_msgid: "b12812a412b53e24"

The first inquiry is sent to at: 07:13:47.104Z

And the last answer to: 07:13:47.280Z

I understand that we are talking about 176ms? This is really fast
If you want I can lower the bus speed to 9600 to test and compare. It costs me nothing.

I have added delay to finish adjusting the desired speed and continue testing.

I have tested the system consistency but it has a problem. I have disconnected input module 4 and it causes that modules 5 and 6 are not read anymore. In addition, it causes an error in "Modbus Flex Getter" that causes it to initialize.

15/10/2022, 9:45:06node: 32e78ebaf8875bfb
msg : Object
{ payload: 1665819906665, _msgid: "da4a34f05c06afe1" }
15/10/2022, 9:45:06node: 3a125fbe24bc2f1b
93a8f1f404f0e670 : msg : Object
{ _msgid: "da4a34f05c06afe1", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a6502f726ad632b11b375", modbusRequest: object … }
15/10/2022, 9:45:06node: 3a125fbe24bc2f1b
93a8f1f404f0e670 : msg : Object
{ _msgid: "da4a34f05c06afe1", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a6502f726ad632b11b376", modbusRequest: object … }
15/10/2022, 9:45:06node: 3a125fbe24bc2f1b
93a8f1f404f0e670 : msg : Object
{ _msgid: "da4a34f05c06afe1", payload: array[16], topic: "93a8f1f404f0e670", messageId: "634a6503f726ad632b11b377", modbusRequest: object … }
15/10/2022, 9:45:07node: Modbus Flex Getter
msg : string[60]
"Modbus Failure On State sending Get More About It By Logging"
15/10/2022, 9:45:07node: Modbus Flex Getter
msg : error
"Error: Timed out"
15/10/2022, 9:45:07node: 3a125fbe24bc2f1b
93a8f1f404f0e670 : msg : Object
{ topic: "93a8f1f404f0e670", messageId: "634a6503f726ad632b11b378", payload: "", queueLengthByUnitId: object, queueUnitId: 4 … }
15/10/2022, 9:45:08node: 22ca57b398372ef1
function : (error)
"TypeError: Cannot read properties of undefined (reading 'unitid')"

How could you adapt your function so that it will loop as long as an eject is not deactivated? Would I have to create a constant? I'm a bit lost on this.

Thanks again sir

Yay! You got it to work! 176ms to transit all six of your modules just goes to show that trying to do it in 100ms was too tight and not going to happen. Essentially the first responses would start rolling in and then the program would start stomping on them and causing traffic collisions. That's been the problem all along is simple traffic collisions.

To accommodate for a module disconnect on your line, simply take what you got in your error response and put something in your function to catch it and respond. It's just a matter of putting in an if statement that looks at something in msg, which looks like it's msg itself and not a subkey. It looks like there is a queue ID you can use to identify the failed module, which you can add one to and continue looping.

I'm curious though. Why the delay? You can leave that looping at full speed without any adverse effects. Adding an artificial delay just slows down a system that already can't perform to your original requirements. Taking it out allows it to run in a manner you've proven works, so long as all your modules are connected (which you can easily take into account). So why the delay?

1 Like

Hello!!!
Ok, let's start with the easy. I implement a delay with the sole purpose of being able to correctly debug the program. When everything is operational, the idea is to eliminate the delay and make it work at full capacity.

I've been trying to implement fault checking, I'm a bit stuck on this although it's not essential for me.
I attach the code that I have been testing:

if (msg.payload == "begin") {
    msg.payload = {
        'fc': 2,
        'unitid': 1,
        'address': 0,
        'quantity': 16
    };
    return msg;
}else{
    var count;
    if (msg.payload == "") {
        count = msg.unitId + 1;
    }else{
        count = msg.modbusRequest.unitid + 1;
    }
    if (count < 7) {
        msg.payload = {
            'fc': 2,
            'unitid': count,
            'address': 0,
            'quantity': 16
        };
    }else{
        msg.payload = {
            'fc': 2,
            'unitid': 1,
            'address': 0,
            'quantity': 16
        };
    }
    return ([msg, null]);
}

When an error is generated in debugging the following is output:


image

For me it is much more important to be able to add a modbus reading from another device in this loop. For example, I have a temperature and humidity sensor with node #11. Do you have any idea how I could add reading from this device? This device would not have to read it as fast (176ms). Maybe every 6s would be fine. For me the difficulty is in timing these 6 seconds and adding it to the next message.
What do you think?

Thank you very much!

We'll go back to my last function example for simplicity and modify it for error catching.

if(!(msg.hasOwnProperty('payload'))){
    return null;
}
var count;
if(msg.payload == ""){
    count = msg.queueUnitId + 1;
}
if(msg.modbusRequest.unitid  < 6){
    count = msg.modbusRequest.unitid + 1;
}
else{
    count = 1;
}
msg.payload = {
    'fc': 2,
    'unitid': count,
    'address': 0,
    'quantity': 16
};
return msg;

Let's go through what changed piece by piece. First of all, there's now a check at the top of the code to see if msg has the object payload in it. If not, it essentially skips the message by returning null. This catches the error messages themselves and keeps them from triggering an erroneous round of attempts that would probably fail anyways.

Next, you'll notice I took out the check to see if you're injecting a start message. You no longer will. What you'll want to do instead is set your inject node to inject the requirements to pretend it's either an error event or a successful payload attempt. An error (like a disconnected module) has a payload of "" while a successful doesn't. An error has a queueUnitId property where a successful event has a modbusRequest.unitid property. You'll want to set your inject node with one of those IDs and a payload that matches. This will make the function "think" that it received feedback from an already in progress query and continue on where it left off. It makes the whole process circular.

Before the rest happens, we setup our count variable to be universally used when we build our query. This keeps it easier and shrinks our code significantly.

In place of the start section, you'll notice the new error check. Since it looks like your error msgs have a payload of "", we set that as an easy check. That would assume an error happened, get the unit ID that errored and move to the next.

If the payload exists and has contents, the error check is skipped and it moves to figure out which module just had a successful return. This value is used and incremented to get the next module's data. All of this is only if it hasn't reached the last module.

If it has reached the last module, the count is reset to 1 and it continues on.

The MODBUS query is then built and sent out to the flex-getter for processing.

Does all of that make sense? The whole concept of error catching is that you look for something unique in the error that identifies it from the rest of the successful data and use it to extract and react to the error. Finding something unique can either be very easy or somewhat difficult, depending on how a node handles them. Sometimes it takes experimenting to find something that works.

As for your question on a temperature/humidity sensor, you have a few options. You could count loops through your MODBUS modules by using a context.set() and context.get() setup to track the iterations. You could setup timed injection node firing into your function or directly into the flex-getter, which would have to be accounted for in your function code (would not be difficult at all, don't overthink it). Or you could setup a separate MODBUS routine to check it, though that's not advised if you have it on the same MODBUS channel as your other units. That's just a few possibilities. There are many, many options. See what happens when you try that now.

1 Like

Hello!
I am testing the code.
I think an if should be added.
What I'm seeing is that I inject a (msg.payload = "") and (msg.queueUnitId = 0) and I get an error that 'unitid' cannot be read. This goes in by checking if it's less than 6.

The code would be like this:

if (!(msg.hasOwnProperty('payload'))) {
    return null;
}
var count;
if (msg.payload == "") {
    count = msg.queueUnitId + 1;
} else {
    if (msg.modbusRequest.unitid < 6) {
        count = msg.modbusRequest.unitid + 1;
    }
    else {
        count = 1;
    }
}
msg.payload = {
    'fc': 2,
    'unitid': count,
    'address': 0,
    'quantity': 16
};
return msg;

If during the test, I disconnect a module. Everything gets a little crazy. The bus saturates and tries to initialize.
I attach a video:
ezgif.com-gif-maker

If during these errors, I connect the previously disconnected module, everything continues in error.
The video starts again and it seems that the error is cleared but not. The error remains and the "modbus flex getter" tries to initialize but fails.

I've been thinking about it better and I think it would be better (before complicating everything), to add a second bus. In this way we would have the first bus that works at maximum speed and another second bus where we read other devices (sensors of temperature, humidity, levels, relay status, ...) at a slower speed.
Now the dilemma is whether to add all this in a function or make a structure similar to this:
image
(This image is not mine. It is an idea found on the internet.)

I will try and post

As always, thanks for your help.

A few things to look at then.

  • Add whatever you need to correct the function flow so it can pick up what you're sending and react appropriately. That's the benefit of knowing your setup better than anyone else. :slightly_smiling_face: The code block I gave you is the simplest I could come up with to show the functionality. If it's not triggering correctly, fix it until it does so your system works.
  • Your messages are calling out an "init" as part of the error. There is potential that your USB to MODBUS module needs a period of time to reinitialize after a timeout error. That will be something you want to research on the module. Or (as a test) pick up the first message that happens after you unplug a module and see what message is your last that is sent. Once you know what the last message is, you can trigger off of that instead of one that might be in the middle. Or maybe use another output of your function that routes through a delay node to delay the normal message and allow the system to recover.
  • Adding a second bus can be some tricky language to work with. Does that mean plugging in a second USB controller or adding another MODBUS node for the controller you have? I would only use a second node if you have a second and physically separate conversion module to connect to it. The flex-getter will do really well at preventing traffic collisions when used properly for the module you have. But it can't regulate what happens in a second node sending to it's same module.
  • I would avoid the left side of the image you sent. You'll want one function, if you have any functions at all. I do have a MODBUS setup where I have several inject nodes feeding into a flex-getter and it works fine. They're all timed to fire at the same time and the flex-getter regulates the flow without issue. But I also have my MODBUS over ethernet with a high-speed controller on the other end. So it can handle the traffic. The function code I gave you ensures there is never a traffic collision because only one message traverses the channel at a time and another won't traverse until the first has returned. You can try having multiple inputs simultaneously and see if your system can handle it. If it works fine, you also know you can time your inputs differently so they all go through the same node. Don't be scared to try new stuff with this. You'll probably find some cool stuff out that makes the setup much better.
  • When you do get your inputs the way you want, your outputs most likely will look like the right side of the graphic you put up. You'll probably have a number of functions, charts, outputs and the like, all responding on their turn to the traffic coming out of the flex-getter. That's what is common and I wouldn't expect to see anything different. You can have a single function with multiple outputs to do that, but it doesn't scale well. So the right side is a definite expect that. The left side, not so much.

In all of this, this is your project and you know it best. Just adjust what you have until it works and optimize until you're happy with it. It sounds like you have a good grasp of what's going on now that you've had some success and know the limits of your setup (modules appear to need an individual window of 29.33ms, or 30ms for a nice even number). So just work within that and you'll make this happen. You got it.

1 Like