Search code examples
c#modbusmodbus-rtu-over-tcp

How to correctly convert the values ​received through modbus?


I am getting data in my console program on C# with library Nmodbus4 from a device via modbus rtu. Format: 32 bit floating point.I am request the device by registers 0x0D – 0x0F. My response is 5132, 3595, 8458 .And this answer should match 2020 12 14 11:33:~35. i.e data format are [year][month][day][hour][minute][seconds]. Below my code:

using Modbus.Device;
using Modbus.Utility;
using System;
using System.Collections;
using System.Globalization;
using System.IO.Ports;

namespace Elemer19
{ 
    class Program
    {
        static void Main(string[] args)
        {  
            string[] pathFolder = ReadDirectory.readDir();
            Console.WriteLine("OPENING COM PORT - {0}", pathFolder[0]);

            byte slaveID = 4;
            ushort startAddress = 0x0D;
            ushort numOfPoints = 3;

            SerialPort _serialPort = new SerialPort(pathFolder[0],
                             9600,
                             Parity.None,
                             8,
                             StopBits.One);  
            try
            { 
                _serialPort.Open();

                ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(
                    _serialPort);
                master.Transport.ReadTimeout = 300;
 
                ushort[] date = master.ReadHoldingRegisters(slaveID, startAddress, numOfPoints); 
                    
                foreach (int item in date)
                {
                    Console.Write("\r\n{0}", item);  //5132, 3595, 8458
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now.ToString() + ":Connect process " + ex.StackTrace +
               "==>" + ex.Message);
            }
 
            Console.ReadLine();
 
        }
    }}

Date format in the device: date and time in the combined bit field of the two registers (starting with the least significant bit of the least significant byte):

seconds - (bits 0 ... 5 - values ​​0 ... 59)
minutes - (bits 6 ... 11 - values ​​0 ... 59)
hours - (bits 12 ... 16, values ​​0 ... 23)
number - (bits 17 ... 21, values ​​0 ... 30) - days 1 ... 31
month - (bits 22 ... 25, values ​​0 ... 11) - months January ... December
year - (bits 26 ... 31, values ​​0 ... 63) - years 2000 ... 2063

How to get the date value correctly?


Solution

  • Your bit-decoding information seems to be wrong.

    If you write the three numbers as individual bytes (20, 12, 14, 11, 33, 10), you will see that your expected value can be directly extracted from these bytes:

    DateTime ConvertToDateTime(ushort[] data)
    {
        var year = (int)(data[0] >> 8);
        var month = (int)(data[0] & 0xFF);
        var day = (int)(data[1] >> 8);
        var hour = (int)(data[1] & 0xFF);
        var minute = (int)(data[2] >> 8);
        var second = (int)(data[2] & 0xFF);
        
        return new DateTime(2000 + year, month, day, hour, minute, second);
    }
    

    yields: 2020-12-14 11:33:10