Temco PLC as Modbus Master

We are faced with the task of monitoring the state of two heat pumps and controlling them via Modbus RTU.
For this purpose, we purchased your two T3-LB-WIFI-1kPT controllers.

It’s assumed that the T3-LB controller will be the Modbus Master and will be connected to two heat pumps with Modbus addresses 11 and 12 via the RS-485 network.
The control logic for the two heat pumps is programmed in the T3-LB controller, which controls the pumps by writing the required values to the MODBUS HOLDING REGISTERS of the heat pumps.

I spent several days studying your forum and help for the T3000 program and here is what I managed:

  1. to emulate the heat pump, I used the “Modbus Slave” program on my PC and entered the test data in HOLDING REGISTERS 40001-40005:

  2. next I set up the connection in T3000:

  3. and wrote a small program for reading and writing Modbus values:

  4. and here is what I got in the T3000 variables:

Thus, the program reads MODBUS HOLDING REGISTERS but for some reason does not write, see HR40005.
QUESTION 1: WHY? What did I do wrong?
QUESTION 2: In heat pumps, besides MODBUS HOLDING REGISTERS (register numbers 40001-49999, r/w), MODBUS INPUT REGISTERS (register numbers 30001-39999, r) are present. How can they be read by the controller?
I ask you to respond promptly, the task is urgent.


I made a check which requests are sent and answers come from the “Modbus Poll” program and the T3 controller, see the table:

The table shows that the command to write the value 10 to register 40001 from the T3 controller (08 18 FF) does not correspond to the same command from the Modbus Poll program (06 00 00 00 0A 09 67)

I did same test as your, the result is ok. I wirte program code like this :
10 117.11.MB_REG0 = 10
117 is main panel, 11 is modbus id of sub device.
send out “0B 06 00 00 00 0A 09 67”, it is correct.

Chelsea, thank you for the answer!
The command to write the register in my program is correct and everything worked, but after I connected the wires to the RS485 SUB connector, not to the terminals marked with “+” and “-”, but to the terminals “+” and “EARTH”, see screenshot. Is this a mistake in marking the terminal?

I have a new question, see the program:

When I try to work with a variable, see “90 IF HR40001 <> 1 THEN 100 ELSE 120”, nothing happens. But if I change the line to “90 IF 1.11.MB_REG0 <> 1 THEN 100 ELSE 120” everything is OK.
The question is why? After all, I assigned the value of a variable earlier in line 20? Why do I need to re-read the Modbus registers for each operation?

It’s a pity that I did not find this in the instructions, this would speed up the development process :slight_smile:

Colleagues, another question: I’m trying to read MODBUS INPUT REGISTERS using a command from Chelsea, but to no avail. The MB_IN_REG command is not perceived as correct and is displayed in gray, see screenshot:

Sorry, keywords are fixed agian. We should add it to document soon.
MB_COIL -> 01/05
MB_REG -> 03/06

Hi Chelsea,
Now I was able to read the value of INPUT REGISTER, thanks for your help. I’ll understand further.
But my question on reading the assigned values of the Modbus variables remained unanswered, see the post above.

Colleagues, I have a question: the program that I use to emulate several Modbus Slave devices generates errors when receiving packets from the T3 controller: “Invalid function code 0” and “Invalid CRC”. I guess that is not maintained interval of silence, at least 3.5 characters at the beginning of the message and 3.5 characters at the end. Please check their availability and reply to this message. Thank.

unfortunately, I still have not received answers from you to my questions.
And since my T3 controller polls Modbus variables with errors that I wrote above, I decided to try to query one variable and introduce a 10 second delay between polls.
What came of this, look at the video: https://youtu.be/yBKmrRPqymk
The question is, why is this happening? Why are requests executed without delay?

One more question, please tell me, can we use a maximum of 128 variables in the T3-LB controller or more? I mean the number of variables that will be visible in BACnet.

I am not at my desk just now but I believe you are correct, 128 is the maximum for now.

Maurice Duteau

The polling is added to a pool of network points which automatically get refreshed by the network points task. there is no manual control over the polling rate. Yet.

I see that this could be useful and we’ll be looking at letting you control the polling rate by program control soon.

Maurice Duteau

I have a new question: I get Modbus temperature value with a sign. When the temperature is greater than zero, the controller displays it correctly, but when the temperature is negative, the controller displays it in the form “65526”. I guess this is a conversion problem. Please tell me, how I can write in the program that the value of the Modbus variable should be signed?

Default value is unsigned, so have to ask customer conver it if the value is negative.
10 VAR1 = 65526
20 IF VAR1 > 32768 THEN VAR1 = VAR1 - 65536

Hi @chelsea, thanks for the answer, I succeeded.

Unfortunately, you did not answer my question about pauses in Modbus requests. I see that polling by the controller is unstable and this is bad. You probably don’t suspect this, because usually Modbus Slave devices do not display read errors. I see these errors in the emulator program, see video: https://youtu.be/H3B0p6gX5Pw
I don’t see your code in which the controller generates a request, but I believe that in the controller’s request the pauses equal to 3.5 characters required by the Modbus standard are not met.
See below for an example of Python code in which these pauses are implemented:

    # Sleep to make sure 3.5 character times have passed
    minimum_silent_period = _calculate_minimum_silent_period(self.serial.baudrate)
    time_since_read = _now() - _latest_read_times.get(self.serial.port, 0)

    if time_since_read < minimum_silent_period:
        sleep_time = minimum_silent_period - time_since_read

        if self.debug:
            template = (
                "Sleeping {:.2f} ms before sending. "
                + "Minimum silent period: {:.2f} ms, time since read: {:.2f} ms."
            text = template.format(
                sleep_time * _SECONDS_TO_MILLISECONDS,
                minimum_silent_period * _SECONDS_TO_MILLISECONDS,
                time_since_read * _SECONDS_TO_MILLISECONDS,


    def _calculate_minimum_silent_period(baudrate):
        """Calculate the silent period length between messages.
        It should correspond to the time to send 3.5 characters.
            baudrate (numerical): The baudrate for the serial port
            The number of seconds (float) that should pass between each message on the bus.
            ValueError, TypeError.
        # Avoid division by zero
        _check_numerical(baudrate, minvalue=1, description="baudrate")

        MINIMUM_SILENT_TIME_SECONDS = 0.00175  # See Modbus standard

        bittime = 1 / float(baudrate)
        return max(

I await your reply!

@chelsea, @maurice, I’m sorry, but I’m used to that when asking questions they have to answer.
Please tell me, do not you think so? Or do you intentionally ignore my question and believe that the problem does not exist?
I got a few more questions on less significant issues than stability on Modbus, but I can’t ask you them until I get an answer from you to an already asked question.

Hi @maurice,
I wrote all in detail in the message:
and added in the message:

Probably the reason for the unstable operation of Modbus is not so much in the pause between requests, but in the structure of the requests themselves. Watch the video: https://youtu.be/QyNOQh2kYRg
I made the same request to the Modbus register from the “Modbus Poll” program and from the T3-LB controller. Requests from the Temco controller come in torn form, unlike requests from Modbus Poll. Do you see this problem? Please tell me, can it be solved programmatically or is it a hardware problem?

There is a modbus delay parameter in some of our products, please check around in the T3000 user interface for it, advanced parameters tab. If its not in there for the T3-LB we can add it. I have asked one of the team to check on this as well.

@maurice , there is no such parameter in the settings.