Author Topic: Modbus Data Blocks  (Read 3717 times)

Cube

  • Administrator
  • Contributor
  • *****
  • Posts: 86
    • View Profile
    • The Venturii Adventure
Modbus Data Blocks
« on: May 16, 2018, 08:47:55 AM »
Originally my design was to have RTU devices own DataBlocks. DataBlocks are arrays of bytes which are either read from or written to by modbus commands. Each of these bits or bytes would have a corresponding VINT associated with it, and thus we could apply Venturii nomenclature to Modbus Remote Terminal Unit devices in a fairly sane way. This was all up and running and worked well, however as I've been working on this project my understanding of Modbus has grown and so too my desire to extend the functionality of this plugin even further.

The problem

We are integrating with a Modbus system that at present only accepts a single connection; subsequent connection attempts succeed but are immediately closed. When we disconnect the incumbent system, we can connect Buscom's Modbus plugin and interact with the Modbus devices through the connection, but this cuts off all access to the legacy system.

A Solution In The Works

I was talking to one of my colleagues about this problem, and he suggested we "Y-Connect" the TCP socket. Not a terrible idea, but because Modbus is a query/response system, it's not as simple to just cross-connect the thing like an NCC-1701 warp core. However the suggestion got me thinking, and the more I thought, the more I liked the idea that came to mind. What if, I thought, we open up the data blocks to more than one RTU device. We could even create slave RTU devices in the Buscom plugin, that would simply serve up data from one or more linked data blocks. In this way we could act as an intermediary between the existing Modbus equipment, legacy system, and continue to develop and interact with the hardware ourselves concurrently -- all on this same Modbus connection. In fact, this virtual data block could serve as an information for multiple RTU masters.

Using this topology we could shoe-horn the Buscom/Modbus plugin in between those systems. One RTU Master device would query the existing field hardware, update it's own copy of the registers & coils (stored in data blocks within the Bustom/Modbus plugin) and we would act as a slave to the legacy system which would poll [[us]] for updates. Our slave would serve up the correct coil and register data to the legacy host which would be none the wiser that it was talking to an intermediary now instead of the field hardware directly, and we can ourselves peek and poke at the data in situ.
« Last Edit: May 17, 2018, 07:47:09 AM by Cube »
Venturii - Integrate Everything

Cube

  • Administrator
  • Contributor
  • *****
  • Posts: 86
    • View Profile
    • The Venturii Adventure
Re: Modbus Data Blocks
« Reply #1 on: May 16, 2018, 07:37:17 PM »
The Plot And Problem Both Thicken

The Modbus slave driver (interesting function categorization) utilizes the modbus_mapping_t structure type to contain each of the four types of data it can process: bits, input bits, registers and input registers. Each of these point to a contiguous block of memory allocated of either uint8_t or uint16_t, depending on the bits or bytes parts. The way I have my data blocks set up, they need not necessarily be contiguous nor present necessarily. This creates a problem though, when I try to blend the two systems of storing these data types together.

Thinking It Through

Because I want to be able to have multiple slaves serve data off the same block, we have the conundrum of where that block resides. On the one hand I could create a modbus_mapping_t structure within the RTU structure of each virtual Slave RTU, and could cross-link other RTU masters with that block, along with the DataBlocks to pull the VINT data from them. Maybe a better solution is to create external modbus blocks. If I remove my concept of a datablock (which is really just a subset of the main block of data) and create raw blocks of data as the data blocks instead, we could point VINTs at them using the newly implemented value arrays. Imagine then, we create a datablock of, say, a thousand bits and a thousand bytes for each of the pairs of input and output coils and registers within our virtual RTU slave. Now we can point our modbus_reply() function to this block of data, or we can point multiple RTUs at it. Then, we create new construct - maybe called something like a Section, Tag or Subset - which contains a starting address and a length parameter, referencing one of our main blocks of data. This Section gets a single VINT for it's value, but it will make proper use of the array functionality of VINTs now that this has been implemented. We add a Device Status VINT for the entire section (since one is enough) and we have our access in and out of the global data blocks, satisfying both needs with efficiency!

 The one last piece of the puzzle is data concurrency; race conditions and how to prevent them. Since multiple virtual and/or real RTU devices may be accessing the same block of memory, how can we ensure only one uses it at a time, especially when the reply() function potentially blocks? We might be able to use 0 timeout values, gather up all the sockfd's from each RTU device and run them through our own select() call. For that matter, we might single-thread the entire modbus plugin, which would eliminate the need for the locks at all. Interesting. A little daunting, but very interesting...
Venturii - Integrate Everything

Cube

  • Administrator
  • Contributor
  • *****
  • Posts: 86
    • View Profile
    • The Venturii Adventure
Re: Modbus Data Blocks
« Reply #2 on: December 04, 2018, 08:47:26 PM »
It would appear that I've just somewhat recreated this post (though less eloquently.) Sigh. I guess it's good that I'm finally getting back around to it...
Venturii - Integrate Everything