Error while reading with EM6436 energy meter using modbus4j.jar
-
2012-07-19 02:51:44 PDT
We are using EM6436 energy meter connected to a PC via RS232 to RS485 converter .
With my own code using modbus4j open source library,we are able to discover the Energy meter and obtain its ID using Modbus4j.
But when I try to read data address (3901 say) of the device(EM6436) using the following code:
SerialParameters params = new SerialParameters();
params.setCommPortId("COM1");
params.setBaudRate(9600);
params.setDataBits(SerialPort.DATABITS_8);
params.setParity(SerialPort.PARITY_EVEN);
params.setStopBits(SerialPort.STOPBITS_1);
ModbusMaster master = null;
ModbusFactory factory = null;
try
{
factory = new ModbusFactory();
master=factory.createRtuMaster(params, 0);
if (master == null){
return;
}
master.setTimeout(5000);
master.init();
Object obj = null;
NumericLocator locator = null;
try{
locator = new NumericLocator(1, RegisterRange.HOLDING_REGISTER, 3901, DataType.FOUR_BYTE_FLOAT_SWAPPED);
obj = master.getValue(locator);}catch (Exception e) { System.out.println("Exception occured : "+e.getMessage()); } System.out.println("Value read"+"for------"+i+"----------->"+obj); } } finally { master.destroy(); } }
We are getting error as Error Response Exception :Invalid data address or sometimes its giving TimeOut exception.
We increase the timeout from 500 to 20000 but still it giving us the TimeOut Exception.
The same code is working fine with the simulators(Modbus PAL , Modbus PLC).
Even reading the same data address with ModScan32 (with the same connection)is also working but not with the above code. Please suggest. -
We are using Mango 1.13 version to perform the reading of Modbus RTU energy meter device EM6436 register value and we are able to read the register values of energy meter device.
We tried the sample code provided by mango community(RTU example),but we are not getting particular method like- master.getValue(7, RegisterRange.HOLDING_REGISTER, 1000, DataType.FOUR_BYTE_FLOAT_SWAPPED)
- ModbusLocator loc = new ModbusLocator(1, RegisterRange.HOLDING_REGISTER, 0, DataType.TWO_BYTE_INT_UNSIGNED);
Can you suggest some solution for reading register value from Modbus RTU device, since we are using modbus4j.jar for the same and is there any latest seroUtil and modbus jar available which support above mentioned function.
-
Note that Modbus4J uses 0-indexing for registers. I don't recall precisely, but perhaps ModScan uses 1-indexing? So, have you tried reading from register 3900 instead?
-
We tried the sample code provided by mango community(RTU example),but we are not getting particular method like ...
That code looks old. Changes to Modbus4J have occurred since then. From your other code samples, it looks like you've figured out the new ways doing things, so i'm not sure what your question in.
-
Hi mlohbihler,
Thx for the information.
The code we posted is used by use and we also tried the RTU sample code.
The sample code given by mango to read RTU device register there they used one line code to read the value on device i.e
master.getValue(7, RegisterRange.HOLDING_REGISTER, 1000, DataType.FOUR_BYTE_FLOAT_SWAPPED)We tried to use this particular line in our code but we are not getting this method in modbus4j.jar
In your previous post you mentioned about the register indexing i.e 0 used by modbus4j and 1 by ModScan ,we also tried to read register from 3900,1000,2000 etc...but still we are geting error like
- Illegal register address (When register address is 3901)
- TimeOut exception (When register address is 3900)
Similarly we tried to read the register value using ModbusLocater ,this method is also not get imported.
Sample code for ModbusLocater which we tried is like this:// Define the point locator.
ModbusLocator loc = new ModbusLocator(1, RegisterRange.HOLDING_REGISTER, 0, DataType.TWO_BYTE_INT_UNSIGNED);// Set the point value
master.setValue(loc, 1800);// Get the point value
System.out.println(master.getValue(loc));Can you suggest anything on it.
-
Do you have Mango? You could try the discovery tools in there to see what's going on in your device.
Otherwise, it's hard to troubleshoot something that works in some cases but not in others without being able to test it personally. To deal with your issues with code versions, i suggest you download the latest jars (modbus4J and seroUtils) from the SF CVS.
-
Hi mlohbihler,
I got the solution for my problem ,i like to ask one more thing is there any way to convert Modbus response into an float or any way to convert response into an float.
Since our device support floating value ,there is no problem with the integer and real values.Thx..
Solution is like this:
ModbusRequest mreq = new ModbusFactory().createReadRequest(2, 3, 3926, 2); ReadResponse mres = (ReadResponse) master.send(mreq); short[] data = mres.getShortData(); int length = 65536 - 3926; for (int i = 0; i < length; i++) System.out.println("Result: "+Integer.toHexString(data*)+" === "+Integer.toString(data*)+" === "+data*);
-
Note that you are using a different register address than before. Does this explain why it was previously not working?
Conversion from/to float/double is the point behind locators. The following should be equivalent to what you are trying to do:
NumericLocator nl = new NumericLocator(2, RegisterRange.HOLDING_REGISTER, 3926, DataType.FOUR_BYTE_FLOAT); float value = master.getValue(nl).floatValue();
Your data type could also be FOUR_BYTE_FLOAT_SWAPPED. Also, locators are stateless, and so can be created once and reused as required.
-
Previously we are just creating ModbusRequest and getting the ReadHoldingRegistersResponse now instead of that we are creating ModbusRequest and getting ReadResponse .
We tried to convert the values into float with the NumericLocater but it giving us the enumerated output like 5.12345E28
Instead of it we like to get the floating values like 12.234. -
Not sure what you mean by this:
the enumerated output like 5.12345E28
How is your data stored? I.e. what does this print out?
System.out.println("Result: "+Integer.toHexString(data*)+" === "+Integer.toString(data*)+" === "+data*);
If it is not stored as a float, then you need to use another data type.