Modbus RTU familiarisation - Page 1
Forum section: electronics / general

author: 741
author_rank: Frequent Contributor
timestamp: December 13, 2022, 10:41:01 am
content: I'm trying to re-familiarise myself with modbus RTU. I came across this site (https://ipc2u.com/articles/knowledge-base/modbus-rtu-made-simple-with-detailed-descriptions-and-examples/) which seems a nicely presented learning resource. However I'm almost immediately unsure of various points from the first example.They sayThe following is an example of a Modbus RTU request for obtaining theAIvalue of the holding registers from registers # 40108 to 40110 with the address of the device 17To me,AImeans/suggests "Analog Input", which is at odds with the 4x addresses.The example request is11 03 006B 0003 7687, and it is shown that006B The address of the first register (40108-40001 = 107 = 6B hex)By "first register" I assume that means "first register in this request". What really bothers me is this, in the response analysis we have lines such as this -AE The value of the upper registerbit(AE hex) Register value Hi (AO0)I don't get the description "upper registerbit" (should that be "byte" ?).Also I fail to see the "Register value Hi (AO0)" part. I can accept that the first holding registeractually implementedmight lie at an offset of 0x6B from 40001. I can believe (but I am not sure) that in this case, offset 0x6B is associated with the first "AO" (Analog out) register. In that case (?) maybe we'd say that logically "AO0" <--> offset 0x6B.However they have only just statedthe first register of AO Holding Register has the number 40001, but its address is 0000a few lines above.

author: peter-h
author_rank: Super Contributor
timestamp: December 15, 2022, 11:35:02 am
content: The reason you aren't getting any responses is because anybody doing Modbus work is getting paid by his employer and is not allowed to post about work stuffI have done a fair bit of Modbus code over the years but not recently, so I can't help you much, but I do know that there are few conventions on data representation using Modbus. You can basically choose what you want and which registers to store it in. Then there are representations for integers, floats, binary or textual data, etc.

author: AndyC_772
author_rank: Super Contributor
timestamp: December 15, 2022, 11:57:08 am
content: I get paid to do Modbus, but there's really no reason I'd touch it otherwise. I dislike it for various reasons, some ideological, others practical.Register addressing is just one of those reasons. The number described as a "register address" in the range 4xxxx (for example) never actually appears on the wire at all, it's a totally unnecessary, confusing misnomer, designed to arbitrarily inflate the amount of time required to implement a Modbus interface by introducing off-by-one errors at every possible opportunity.If you want to read a register in that range, then what you actually do is read from address (n - 40001) using function code 3, which means "read a register in the 4xxxx range". So, for example, to read "register address" 40003, the address on the wire is actually 0002, and the offset of 40001 is simply implied by using the correct function code.

author: Siwastaja
author_rank: Super Contributor
timestamp: December 15, 2022, 12:33:16 pm
content: Modbus is an extremely simple and sensible thing in essence.It's just arbitrarily made a mess by stupid conventions like having TWO different addressing systems which are off-by-one, having shitload of weird legacy message types, and also by all the gazillion devices which do things a bit differently.I have never been able to write anything modbus related by reading standards or documentation. They give you a starting point, but real work is done by having the devices physically and reverse-engineering what they do.That said, in 90% of cases you can't even get documentation, just black boxes with manufacturers refusing to support their shit, so you have to reverse-engineeranyway. Not that it matters, it's probably better that way, less time spent reading crappy documents.It's a pity given there is no rocket science involved and the underlying protocol is fine. Documentation should fit on one page.Just extremely stupid and nasty people, with legacy of toxicly stupid engineering culture.And beware, many devices you wouldexpectto be MODBUS RTU devices - sometimes even incorrectly called MODBUS by manufacturer's marketing team, are actually just any random NIH RS485 protocol. Sometimes much better, sometimes much worse than MODBUS RTU.

author: peter-h
author_rank: Super Contributor
timestamp: December 15, 2022, 02:55:21 pm
content: Modbus is standard because every Scada system has a script language for parsing the registers values and converting them to whatever format you want. People in industrial control are pretty well used to this. They don't need to get involved with the bytes in the packet.It is probably better than a thousand proprietary protocols, some ASCII, some binary...At work we do lots of custom Modbus-whatever converters and we always have to borrow an item of the customer's equipment to test it with because it is normally impossible to write it from a spec. But that's actually true for most protocols... there is usually some ambiguity.

author: Siwastaja
author_rank: Super Contributor
timestamp: December 15, 2022, 04:01:05 pm
content: Quote from: peter-h on December 15, 2022, 02:55:21 pmOf course, but most of the protocol weirdness "leaks" to the higher levels.This is why every automation electrician knows how to configure any automation device to output some test value in different test register address, using different endianness options, so that other automation electrician can check with the other device if communication fails or not. And they still need to configure data types, register addresses, and the same off-by-one confusion exists. They still have to deal with MODBUS return codes when things fail.The bit-level mapping is just a tiny detail and quite obvious.Quote from: peter-h on December 15, 2022, 02:55:21 pmUsually yes, if at all possible. Despite the shortcomings, the benefit of Modbus over custom RS485 communication is simple: multiple devices can live on the same bus and happily ignore each other. It so happens that we are ramping up production on a design which communicates with existing RS485 devices in household and light industrial applications. My example case has four RS485 devices: solar inverter, EV charging station, air-to-water heat pump, heat recovery air ventilator. Only one of them is Modbus RTU (the ventilator), others are all custom NIH RS485, and while they have similar master-slave communication to Modbus RTU, with some kind of addressing and polling, no one knows (or can prove) if they are able to ignore the messages produced by the different devices; they are designed to operate with the manufacturer's own "master box". This is also why I designed this otherwise quite small and low-cost device withtwoRS485 buses, despite the fact that significant % of customers never use either. So blame me for stockpiling all your RS485 transceivers!

author: AndyC_772
author_rank: Super Contributor
timestamp: December 15, 2022, 05:17:46 pm
content: Part of the problem with Modbus is that it doesn't specify nearly enough.The gap between messages must be at least 3.5 character times. This is a well defined, unambiguous feature that all devices on the bus can agree on, even if it's a pain to implement because it requires both a UARTanda timer, and a device driver that coordinates the two in a coherent way. It's OK. Difficult is OK if it means the end product is more reliable and easier to use.But, the spec alsorecommendsthat devices use even parity as a default. WTF? What's wrong with prescribing that every devicemustuse even parity? Why allow the ambiguity?Registers are defined to always be 16 bits wide. That's OK. But how on earth can a specification worthy of the name then NOT prescribe whether it's LSB first or MSB first?It allows for registers to be combined into 32 bit ints or floats... fine. But again, it fails to specify which byte is which, so there's at least 4 different vaguely sensible ways to transfer a simple 32 bit value from one device to another, with probing and random byte swapping being the only real way to make both master and slave agree on one of them. Why?My other major gripe is that replies from a slave have the exact same data format as requests from a master, so it's impossible to tell the difference just by looking at the message. At the very least, couldn't the response have the top bit of the function code set to indicate "this is a response to..."? Why doesn't the master have a unique ID of its own?And who thought it was a good idea for replies not to include any kind of context? The master always has to remember the last request issued, because responses from slave devices are just a string of numbers - there's no way to know what those numbers mean without looking back to see what the last request was. Even a unique sequence number - one byte! - would at least allow the master to confirm that the numbers being sent do actually relate to a specific numbered request. (Imagine a scenario... "M: What's our altitude?" ... <long delay> ... "M: What's our fuel level?" ... "S:<7E 29 00 01>")

author: Siwastaja
author_rank: Super Contributor
timestamp: December 15, 2022, 07:14:45 pm
content: Quote from: AndyC_772 on December 15, 2022, 05:17:46 pmThis causes colossal pain when trying to interface modbus devices through general purpose operating systems and UART adapters.When actually designing a MODBUS device (master or slave), with a microcontroller for example, this is all trivial and IMHO a very good strategy. In 1979, they probably did not think about how bloated all OS abstractions will be 40 years later, and how difficult it will be to do a few even approximately timed IO operations.QuoteIt is indeed hilarious how automation electricians who normally install wiring and so on, have to configure these test registers and probe for the correct byte order without being any kind of computer scientists/engineers at all, I have witnessed this happening. Talk about low level leaking into higher abstractions!QuoteModbus is an ancient protocol, implemented on ancient devices, so the idea was probably: reply is a simple register read and comes immediately after the poll, otherwise master times out, and slave will not reply after a certain time, so mixup can't happen. The problem is, this idea, or timeout value was not specified. When given maximum turn-around time (time until slave activates the RS485 TXEN and sends start bit) like 1 millisecond, no such problem would exist, and then everything would be simple, no need to add the context id and compare it. But as you say, they did not feel like specifying pretty much anything.I can totally see engineers at Schneider or whoever it was trying to write a proper specification and then manager types going like... "no, that is too verbose, remove that, no, don't say that, that doesn't sound cool!"

author: peter-h
author_rank: Super Contributor
timestamp: December 16, 2022, 04:55:39 pm
content: QuoteI am told this is unimplemented (disregarded) in most of today's instruments.Don't know if it is true, but would for sure make Modbus over TCP much easier. Currently, a proper implementation needs to have timeouts to detect the end of data (or parse the protocol) and pack a Modbus packet into one MTU. Or if it doesn't fit, reassemble them at the far end (and there is a spec for that, IIRC).

author: Doctorandus_P
author_rank: Super Contributor
timestamp: December 17, 2022, 12:01:29 am
content: If the mandatory gap between messages is ignored by both nodes, it may still be subject to hardware. For example, in RS485 repeaters it is quite common to create the "Driver Enable" signal from the incoming data and extend it with a simple RC combination with an extra diode over the resistor.See for example the implementation below, which I found somewhere in the internet. That schematic is not for a repeater, but for a uC which does not handle the driver enable signal actively.

author: Wilksey
author_rank: Super Contributor
timestamp: December 17, 2022, 01:46:19 am
content: I wrote some code for MODBUS RTU on a PIC Micro several years ago, I did both ends (Master and Slave) was interesting.... I had been given a large PDF document with protocol information in, included MODBUS TCP which I don't recall being too different to RTU, and a couple of simulators (some professional MODBUS suite written by a German company IIRC), a week of experimenting and then wrote the final code, it was fairly straight forward from what I can remember (not a lot these days!)

author: Perkele
author_rank: Regular Contributor
timestamp: December 17, 2022, 08:18:58 pm
content: Modbus is just a simple master/slave protocol.That tutorial is a bit messy, their example looks like a MODICON device.https://www.modbus.org/docs/PI_MBUS_300.pdfIgnore it and find a better learning resource.Go here:https://en.wikipedia.org/wiki/Modbus#Modbus_object_typesThe part that will probably be of interest to you is:"Under the current standard the address can be 0 - 65535 with the object type identified by the command used to read or write the coil or register."Read the rest of that page from beginning to the end.Then download the official specification and read it thoroughly.https://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdfGo here:https://www.simplymodbus.ca/FAQ.htmOn the left side there are "fc" links. Go through all of them.If you need some kind of tool to quickly communicate with a slave, most of tools on Modbus website are obsolete, limited or non-free.https://modbus.org/tech.phpIgnore them.Download something like QModbus (or any other free tool) and start playing with it.https://github.com/ed-chemnitz/qmodbus/releases/tag/v0.3.0It has a couple of glitches with huge messages because you can't set the timeouts without modifying the source and recompiling the application. But I'm seeing those issues when reading/writing more than 120 registers in one request.Good luck.

author: H.O
author_rank: Frequent Contributor
timestamp: December 20, 2022, 12:08:28 pm
content: Quote from: AndyC_772 on December 15, 2022, 05:17:46 pmIn theMODBUS Application Protocol v1.1dated 2006 one can read:QuoteI don't know if that sentence dates back to the original specification from '79 or if it has been added later but at least it IS there now.What bit me when I implemented MODBUS RTU is that the CRC field, unlike data, is sent low byte first...I have since then used that same code interfacing to devices where I've had to again swap this so I know for a fact that I'm not alone in making that mistake.Standards... :-)

author: Siwastaja
author_rank: Super Contributor
timestamp: December 20, 2022, 12:49:22 pm
content: Quote from: H.O on December 20, 2022, 12:08:28 pmRead more carefully. The quoted part does not specify whetherbitsare sent on the wire MSbit or LSbit first. Both are viable options.But at least they specified half of the 16->8 encoding, so there are onlytwooptions. With multi-register values (like floats, uint32 etc.), this becomesfourdifferent possibilities. Without the text you quoted, that would be 8!

author: H.O
author_rank: Frequent Contributor
timestamp: December 20, 2022, 01:17:05 pm
content: QuoteFair enough.Modbus Serial Line Protocol and Implementation Guide V1.02:Quote

author: T3sl4co1l
author_rank: Super Contributor
timestamp: December 20, 2022, 01:45:39 pm
content: I went through this semi-recently. I used:FreeModbus:https://github.com/T3sl4co1l/freemodbus(this branch runs on AVR-DA and easily adapts to other AVRs; check under /demo/AVR)Local testing: generic isolated RS485 USB adapter (FTDI based); pyModbushttps://pymodbus.readthedocs.io/en/v2.5.3/source/library/modules.htmlClient interface: RTU to TCP gateway e.g.https://www.pusr.com/support/downloads/usr-dr302-user-manualI think there is some confusion about "what's on the wire". The standard is here:https://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdfWhat's transmitted is simply what goes into the packet. What you put into it, and what a device reads that as, is implementation defined -- free to choose as you like.This is most obvious in this source -- a low level implementation which basically returns the packet contents to your callback functions. I mean not that there's a lot to it anyway, it's a very simple protocol.From what I've seen, there are, or have been, implementations, or maybe just traditions, of putting addresses for certain functions in certain ranges. This isn't required by the standard, you can use independent address spaces per function code if you like. Likewise the off-by-one is optional, you either get the address verbatim or add or subtract one (as the case may be) if you like.The addresses match between what's in my code (e.g. 40001) and what's in the .py script (40001), and as far as I know, my client didn't have any problems with it (they didn't mention if there was an off-by-one on their end).If you need better familiarity or certainty, maybe look up some other devices and see how they do it, get a feel for the ecosystem. At worst, call up an industry expert (ask the org?) and get some industrial-grade review/certification done?Tim

author: woody
author_rank: Frequent Contributor
timestamp: December 20, 2022, 02:21:07 pm
content: I found thathttps://www.modbustools.com/modbus.htmlhelped me a lot in understanding Modbus. On this site they sell tools that simulate Modbus master / slave devices.I started out usinghttps://sourceforge.net/projects/qmodmaster/which is free and quite nice, but in the end I also got Modbus Poll which offered features like the ability to load/save workspaces that came in handy.I have no connection to either sw supplier but I had a nice support experience with Witte Software.

author: Siwastaja
author_rank: Super Contributor
timestamp: December 20, 2022, 02:23:47 pm
content: Quote from: H.O on December 20, 2022, 01:17:05 pmWhat the actual ****. Who writes bullshit specifications like this?What an unbelievably convoluted way to call a bog standard 8-bit binary number "containing two 4-bit hexadecimal characters". Characters?This screams some manager having written the spec, instead of engineers; a manager who does not understand the normal binary communication at all, but remembers seeing hexadecimal representation of it on the screen. When a normal sane engineer reads this, no wonder they get confused.But you are right - the order is specified there. Maybe AndyC remembers wrong, or maybe the standard has been modified. I don't know, but I do know that different bit orders are a thing, so if it was in the standard all along, then people implementing it have failed to follow the standard. Possibly because the standard is filled up with nonsense like "hexadecimal characters".

author: AndyC_772
author_rank: Super Contributor
timestamp: December 20, 2022, 02:43:35 pm
content: Quote from: Siwastaja on December 20, 2022, 02:23:47 pmNever!!(Well, almost...)I've been using a development tool (master device emulator) by Simply Modbus, which has buttons in the UI to swap the byte order in various ways. I was rather hoping that the standard itself would have been prescriptive enough to make these buttons unnecessary, and indeed, downright hazardous for someone trying to develop a compliant device.Then again, I often find myself hoping for things that turn out not to happen.

author: gmb42
author_rank: Frequent Contributor
timestamp: December 21, 2022, 11:54:48 am
content: After writing Modbus software for nearly 30 years I'm never surprised at how many ways folks find to ignore the protocol specification (which isn't great to begin with) and use all sorts of byte and bit orders along with many variants of combining registers to handle fixed\floating point or string values.The general approach (from the master side) is to have sufficient parameters to handle whatever comes out of the PLC as its usually seen as easier to modify master code than PLC code.Even more fun when using the more complicated SCADA protocols such as DNP3, IEC 60870-5 and OPC UA and major PLC manufacturers refuse to accept their implementation fails to meet the (voluminous) specifications (MicroLogix ML1400 with DNP3 I'm looking at you) and you havethatdiscussion with the system operator that they need to either replace their PLC's with protocol compliant ones or pay you to modify your code to work around non-compliant devices.