RS485 connection to thermocouple module with Controllino Maxi

Hello everyone,

I have the task to read data via RS485 from a thermocouple which is connected to a thermocouple module for reading multiple thermocouples. I am using a Controllino Maxi which supports RS485, meaning I am not using any additional elements like a MAX485.

For the thermocouple module, I am using an EX-5019 (manual: https://www.meilhaus.de/cosmoshop/default/articleMedia/ex-5000/de/Manual_Expert_eX-5000_en.pdf)
relevant pages for the modbus: 49-50, 54
I have the module connected to 12V, the DX+ and DX- ports connected directly to the RS485 + and - ports of my Controllino.
The analog inputs AI0+ and AI0- of the module are connected to a K-type thermocouple which I want to gather the data from.

This is my current code which delivers only the value 0 for both adresses that I am trying to adress:

#include <Controllino.h>
#include "ModbusRtu.h"
#include <SoftwareSerial.h>

#define MasterModbusAdd 0
#define SlaveModbusAdd 1
#define RS485Serial 3

Modbus ControllinoModbusMaster(MasterModbusAdd, RS485Serial, 0);

uint16_t ModbusSlaveRegisters[8];

modbus_t ModbusQuery[2];

uint8_t myState;
uint8_t currentQuery;

unsigned long WaitingTime;

void setup() {
 Serial.begin(9600);
 Serial.println("-----------------------------------------");
 Serial.println("CONTROLLINO Modbus RTU Master Test Sketch");
 Serial.println("-----------------------------------------");
 Serial.println("");

 // Define Modbus queries for the register addresses
 ModbusQuery[0].u8id = SlaveModbusAdd;
 ModbusQuery[0].u8fct = 4;
 ModbusQuery[0].u16RegAdd = 30293;
 ModbusQuery[0].u16CoilsNo = 1;
 ModbusQuery[0].au16reg = ModbusSlaveRegisters;

 ModbusQuery[1].u8id = SlaveModbusAdd;
 ModbusQuery[1].u8fct = 4;
 ModbusQuery[1].u16RegAdd = 30294;
 ModbusQuery[1].u16CoilsNo = 1;
 ModbusQuery[1].au16reg = ModbusSlaveRegisters;

 ControllinoModbusMaster.begin(9600, SERIAL_8E1);
 ControllinoModbusMaster.setTimeOut(20000);

 WaitingTime = millis() + 3000;
 myState = 0;
 currentQuery = 0;
}

void loop() {
 switch(myState) {
   case 0:
     if (millis() > WaitingTime) myState++;
     break;
   case 1:
     Serial.print("---- Sending query ");
     Serial.print(currentQuery);
     Serial.println(" -------------");
     ControllinoModbusMaster.query(ModbusQuery[currentQuery]);
     Serial.print("State after query: ");
     Serial.println(ControllinoModbusMaster.getState());
     ControllinoModbusMaster.query(ModbusQuery[currentQuery]);
     myState++;
     currentQuery++;
     if (currentQuery == 2) {
       currentQuery = 0;
     }
     break;
   case 2:
     ControllinoModbusMaster.poll();
     if (ControllinoModbusMaster.getState() == COM_IDLE) {
       myState = 0;
       WaitingTime = millis() + 3000;
       Serial.println("---------- READ RESPONSE RECEIVED ----");
       Serial.print("Slave ");
       Serial.print(SlaveModbusAdd, DEC);
       Serial.print(" Register: 0x");
       Serial.print(ModbusQuery[currentQuery].u16RegAdd, HEX);
       Serial.print(" Value: ");
       Serial.println(ModbusSlaveRegisters[0], HEX);
       Serial.println("-------------------------------------");
       Serial.println("");
       
     }
     break;
 }
}

I am a beginner at all this stuff, especially RS485 communication and I am very thankful for every suggestion!
Frank

Hello,

What is the question? Are you intending to read data from the device's registers or modify them?

When I work with a RS485 device for the first time, I like to work with Modbus Poll first, just in case you want to take a look to it.

Yes, I am trying to read data from the device's registers.
And thanks for the suggestion, I will look into it.

The request and response are explained in the document:

For the request, it says modbus id is always 1. Modbus function should be 0x03 in your case in order to read data from the device. The initial register and number of register are in the tables

imagen

The max quantity of readable registers is normally found in the datasheet, but haven't found it for this one. I guess you will have to test it manually...

I've understood what the request command is containing. I slightly changed my code to use the modbus function 0x03. The adresses, the modbus ID and the number of registers were already correct in my code I think. I just can't figure out how to correctly send it to the module so I receive a response.
What do I need the max quantity of readable registers for exactly?
Here my slightly updated code:

#include <Controllino.h>
#include "ModbusRtu.h"
#include <SoftwareSerial.h>

#define MasterModbusAdd 0
#define SlaveModbusAdd 01
#define RS485Serial 3

Modbus ControllinoModbusMaster(MasterModbusAdd, RS485Serial, 0);

uint16_t ModbusSlaveRegisters[8];

modbus_t ModbusQuery[2];

uint8_t myState;
uint8_t currentQuery;

unsigned long WaitingTime;

void setup() {
 Serial.begin(9600);
 Serial.println("-----------------------------------------");
 Serial.println("CONTROLLINO Modbus RTU Master Test Sketch");
 Serial.println("-----------------------------------------");
 Serial.println("");

 // Define Modbus queries for the register addresses
 ModbusQuery[0].u8id = SlaveModbusAdd;
 ModbusQuery[0].u8fct = 0x03;
 ModbusQuery[0].u16RegAdd = 0x7655;
 ModbusQuery[0].au16reg = ModbusSlaveRegisters;
 ModbusQuery[0].u16CoilsNo = 01;

 ModbusQuery[1].u8id = SlaveModbusAdd;
 ModbusQuery[1].u8fct = 0x03;
 ModbusQuery[1].u16RegAdd = 0x7656;
 ModbusQuery[1].au16reg = ModbusSlaveRegisters;
 ModbusQuery[1].u16CoilsNo = 01;
 

 ControllinoModbusMaster.begin(9600, SERIAL_8E1);
 ControllinoModbusMaster.setTimeOut(20000);

 WaitingTime = millis() + 3000;
 myState = 0;
 currentQuery = 0;
}

void loop() {
 switch(myState) {
   case 0:
     if (millis() > WaitingTime) myState++;
     break;
   case 1:
     Serial.print("---- Sending query ");
     Serial.print(currentQuery);
     Serial.println(" -------------");
     ControllinoModbusMaster.query(ModbusQuery[currentQuery]);
     Serial.print("State after query: ");
     Serial.println(ControllinoModbusMaster.getState());
     ControllinoModbusMaster.query(ModbusQuery[currentQuery]);
     myState++;
     currentQuery++;
     if (currentQuery == 2) {
       currentQuery = 0;
     }
     break;
   case 2:
     ControllinoModbusMaster.poll();
     if (ControllinoModbusMaster.getState() == COM_IDLE) {
       myState = 0;
       WaitingTime = millis() + 3000;
       Serial.println("---------- READ RESPONSE RECEIVED ----");
       Serial.print("Slave ");
       Serial.print(SlaveModbusAdd, DEC);
       Serial.print(" Register: 0x");
       Serial.print(ModbusQuery[currentQuery].u16RegAdd, HEX);
       Serial.print(" Value: ");
       Serial.println(ModbusSlaveRegisters[0], HEX);
       Serial.println("-------------------------------------");
       Serial.println("");
       
     }
     break;
 }
}

Can you give the Arduino output?

Anyway, I don't know if it is possible to set

ModbusQuery[0].u16CoilsNo = 01;

Also check out the documentation in order to see in how many registers the value is in. Normally, at least the devices I work with, it is either 2 or 4.

Have you done the connection yourself? Is it ok?

The output:

CONTROLLINO Modbus RTU Master Test Sketch


---- Sending query 0 -------------

State after query: 1

---------- READ RESPONSE RECEIVED ----

Slave 1 Register: 0x7656 Value: 0


---- Sending query 1 -------------

State after query: 1

---------- READ RESPONSE RECEIVED ----

Slave 1 Register: 0x7655 Value: 0

I'm assuming the value is in only one 16 bit register as I couldn't find anything opposing in the documentation.

I've done the connection myself, I'm pretty confident that it is ok. I think the issue must be in the code somewhere.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.