Community
OpenEnergyMonitor

Community

Modbus and RS-485

The discussion that followed on from this post by @borpin in another thread provides some good general “Modbus and RS-485” information from @Bill.Thomson. I therefore decided to split is out to this thread so both this and the original discussion could continue.

We can ignore my references to a specific mvhr unit and I will start a new thread on that integration when I actually tackle the task.

Care to share the Python script Brian?

I have some Verve (Holtop?) MVHR units to try and talk to soon, or at least listen too. Did you have to use an isolating RS-485 adapter?

Hi @pb66

The adapter I used was this https://www.amazon.co.uk/gp/product/B00HIZMQIO/ I don’t think I had to do anything special to get it to work with the Pi, though my memory may be failing me!

I have uploaded the python file and my interface script to github https://github.com/borpin/heliospy I had forgotten where I picked it up from (see header) and had trouble getting the module installed locally so it would run from anywhere. I quickly reached the end of my knowledge on it so could not get the script to run as a service. At that point I stopped!

I’d love to have the time to learn Python properly!

HTH

Thanks Brian, that gives me a bit of an insight. as you say it is specific to the mvhr unit you have, but the concept would be the same.

Had emonHub development continued on it’s intended course, we could have had a “rs485” interfacer and using that it would be easier to write a “helios” (or other brand/model) interfacer, you would not need to worry about interfacing different softwares, services, requests, MQTT topics etc just on parsing the data for that model.

Changing fan speeds or summer/winter bypass etc would then be as simple as publishing a command to MQTT from your favorite app, emoncms. openHab, openRemote, nodered or home assistant etc etc.

Way down the line we (this particular client and I) are looking at creating a smartphone app that tells a central server (emoncms?) to send control commands out via an MQTT bridge to the remote MQTT brokers to control the mvhr (among other things).

For now I just want to read the data but have very little to go on, Modbus seems to be more of a collection of possibilities rather than an actual standard. As is RS-485 as far as I can tell, the Verve units have a 115v Modbus! Hence the isolating RS-485 adapter.

From https://en.wikipedia.org/wiki/Modbus

Modbus is a serial communications protocol originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs). Simple and robust, it has since become a de facto standard communication protocol and it is now a commonly available means of connecting industrial electronic devices.

So while Modbus isn’t a defined standard, it’s more than just a collection of possibilities.

From https://en.wikipedia.org/wiki/RS-485

TIA-485-A, also known as ANSI/TIA/EIA-485, TIA/EIA-485, EIA-485 or RS-485, is a standard defining the electrical characteristics of drivers and receivers for use in serial communications systems.

Given the TIA ans ANSI are both US entities, the following bears mentioning:
(from https://en.wikipedia.org/wiki/Telecommunications_Industry_Association)
To ensure that these standards become incorporated globally, TIA is also engaged in the International Telecommunication Union (ITU), the International Organization for Standardization (ISO), and the International Electrotechnical Commission (IEC)

From www.edaboard.com/thread180181.html
RS485 is hardware serial-interface standard that defines the hardware for carrying a message.
Modbus is a messaging protocol that defines the content of that message.

@Bill.Thomson, I certainly meant no offence nor was I putting down the use of modbus or rs-485, my point is the terms “Modbus” and “RS-485” cover a lot of possibilities, it doesn’t even come close to defining anything too specific or helpful. Many other questions need to be answered, type of Modbus, voltage of RS-485 lines, baud, info about master/slave or polled /broadcast, that’s just to open the comm lines and get a lump of data that then needs to be extracted/translated/parsed etc.

As far as standards go, both are pretty flexible, combine them and you have even more possibilities, so whilst I agree with your points i don’t think my comment was that far from the truth, perhaps I should of said “Modbus seems to be more like of a family of protocols than one specific standard” or something similar, I didn’t expect to be taken quite so literally.

No worries, Paul. None taken. In fact, I have three Elkor WattsOn power transducers that have an RS-485 interface which I use to read the data from the meter. Personally, I like the RS-485 / Modbus combo.

Just wanted to point out that Modbus is actually fairly well defined, and has been known as an industry de facto standard for quite some time.
e.g. www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf

RS-485 is well defined too. Unlike RS-232 which defines things as detailed as which pin on a conector gets used for what function, RS-485 describes line drivers, voltages and network topology.
e.g. https://www.lammertbies.nl/comm/info/RS-485.html

Since the RS-485 definition lacks the detail RS-232 has, implementations of it, as you’ve said, vary widely.

With Modbus, whether it be Modbus RTU, ASCII or TCP, reading the registers from an instrument is much the same across all of the variants. Not quite a standard, as per the definition of same, but close.

I actually got quite a shock when I discovered these mvhr units have a 115v RS-485 connection, although no where near as much of a shock as I could of got had I not discovered that before hooking it up some cheap low voltage USB adapter, I guess!!

THAT would have definitely lit your Christmas Tree!

Maybe this will be of some help.

“Type” of Modbus depends on the instrument. e.g. an instrument could have a RTU interface, a TCP interface. or it might use a RTU-to-TCP converter…

Typical Modbus RTU data rate is 9600 bps.
The specification maximum is much higher. Usable max depends on cable length.
Modbus is a request / response protocol. i.e. no broadcast.
The RS-485 line “specs” are here. (Near the bottom of the page)
Here’s another page with info that may be helpful. And another.

One point that might appear to be counterintuitive:
Modbus RTU slaves are servers (instruments)
Modbus RTU masters are clients (controllers)

Reading data from a Modbus instrument typically consists of reading “Registers.”
The registers may be read one at a time, or in groups. Typical register contents are 16-bit integer data.
Some instruments have registers that contain 32-bit floating point data. Some use two 16-bit registers to hold large integer values.

Single bits may also be read. Single bits are known as “Coils.” Analogous to a relay coil, Coils are used to activate / deactivate a two-state device, or as status indicators.

Configuring a Modbus instrument consists of writing to “User Configuration” registers.

I chose to use the Python module minimalmodbus vice PyModbus as it provides Modbus RTU suport, without the stuff I didn’t need i.e. Modbus TCP.

The minimalmodbus API returns the data directly. i.e. when a register is read, the retreived data is a decimal integer or float value represening kW, kVa, Volts, Hz, etc.

1 Like

@Bill.Thomson - This is some great info you are sharing here, I was not aware we had a “Modbus and RS-485” guru on hand :slight_smile:

Some bits of this I have picked up along the way, but it is good to have it summarized in one place.

I had come to the conclusion (rightly or wrongly) that most Modbus were of the RTU variety but was not confident enough to believe that unless told otherwise, a Modbus is probably RTU, would you say that was a good assumption or is it essential to find out the detail?

I will take a closer look at minimalmodbus, at first glance it looks very capable and well documented, cheers for the link.

Thanks for the good words. 'preciate that.

The details, most assuredly. Modbus has been around since the 70s, and the RTU variant is the most common. So it’s likely a lot of RTU devices are still in service. But, newer instrumentation could include a TCP interface, or use TCP exclusively. IOW, the device has no RTU interface. The nice thing about Modbus TCP is that it works the same as Modbus RTU. The only difference is the transmission medium.

I use PERL and it’s Modbus modules to read out a Siemens S7 PLC which is doing our Water Treatment of our town.
Works like a charm and is ultra robust. So if one doesn’t like Python, which i also use to read other small PLC’s, PERL is also a good lightweight alternative.

In addition what Bill Thomson said the Siemens is doing it with reversed registers which is odd to know.

I see the Mod TCP is really easy to use and I personally would prefer a TCP Modbus device over a RTU. In my case I use 2-wire DSL modems to do a p2p connection between two water reservoirs 1.8km distance. On the main reservoir I connect from the Workstation via these DSL modems to the siemens over normal ethernet TCP connection and it’s stable and did not have any failures for over a year. The smaller RTU PLCs, like the SDM630 power meter do have some oddities with the USB RS485 adapter.

Here’s the PERL script to connect to a Modbus TCP device:

#!/usr/bin/perl

use Device::Modbus::Client;
use Device::Modbus::TCP::Client;
use strict;
use warnings;
use v5.10;
use LWP::Simple;
use DBI;

my $port = "503";
my $remote = IO::Socket::INET->new(
Proto    => "tcp",
PeerAddr => "192.168.1.5",
PeerPort => $port,
Timeout  => 2,
);

my $client = Device::Modbus::TCP::Client->new(
    host => '192.168.1.5',
	port => 503,
);		

my @req = (
    # Word oriented
    $client->read_holding_registers(
        address  => 0,
        quantity => 50
    )
);

$client->send_request($req[0]) || die "Send error: $!";
$response = $client->receive_response;
@values = @{ $response->values };

and here is the part to actually reverse the floating point values of the registers. In this case, I wanted to get the height of the water level in the reservoir. Siemens stores these values in reverse order:

$NiveauReservoir = unpack 'f', pack 'v2', $values[22], $values[21];
say sprintf "Niveau_Reservoir_Meter:%f", $NiveauReservoir;

The unpack was the key to get the data back into the correct order :slight_smile:

I’m posting this because it took me a few days to find this information, and maybe others will benefit from this knowledge :slight_smile: