using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; using Modbus; using Modbus.Device; using Modbus.Utility; namespace PowerMeterDemoCode { /// /// The "Program" Class will teach you that how to read/write power meter's holding registers, read power meter's Input Registers and so on. /// The "ConnectToPowerMeter" function show how to connect to power meter. /// The "DisconnectPowerMeter" function show how to disconnect power meter. /// The "ReadValueFromPowerMeter" function will show how to read input registers from power meter. /// The "WriteDefaultParameterValueToPowerMeter" function show how to write holding registers to power meter. /// class Program { private static int[] BaudRate = { 9600, 19200, 38400 }; private static SerialPort mySerialPort; private static ExampleSetting mySetting; private static IModbusSerialMaster modbusMaster; /// /// "ExampleSetting" Structure contains connection parameters of power meter.The parameters are set by user interface or console inpute. /// In this programm, ExampleSetting member's values are either index or amount of units to set power meter parameters. /// They are not actually the real values of Modbus Holding Registers which specified in hardware manual. /// public struct ExampleSetting { public string PortName; public int BaudRate; public byte Modbus_slave_ID; public int StopBit; public int PT; public int CT; public const int Meter_Ratio = 500; // Truly value: 500 } static void Main(string[] args) { // Get a list of available serial port names,then select a port number to communicate. string[] ports = SerialPort.GetPortNames(); if (ports.Length == 0) { Console.WriteLine("No available COM port."); Console.ReadLine(); return; } string portnums = string.Empty; for (int i = 0; i < ports.Length; i++) { portnums += string.Format("[{0}]: {1}, ",i,ports[i]); if ((i + 1) % 4 == 0 || (i+1) == ports.Length) { portnums += "\n"; } } Console.WriteLine("Available COM port number: \n" + portnums ); Console.Write(string.Format("Selected index ( 0 ~ {0} ): ",ports.Length-1)); // Get port's index which user input int selectedPortIndex = 0; bool isright = false; while (!isright) { int cursorleft = Console.CursorLeft; int cursortop = Console.CursorTop; if (int.TryParse(Console.ReadLine(), out selectedPortIndex)) { if (selectedPortIndex < ports.Length) { isright = true; } } if (!isright) Console.SetCursorPosition(cursorleft, cursortop); } // Connect to power meter. If connecting is successful, then // read or write the data of power meter. if ( ConnectToPowerMeter(ports[selectedPortIndex]) ) { string actionString = @"********************************************************************** Execute: [0] : Programe Exit. [1] : Read value from power meter [2] : Write default parameter value to power meter Input index number: "; // Get index number which user input bool isloop = true; while (isloop) { Console.WriteLine(); Console.Write(actionString); // Get index number which user input int actionIndex = 0; bool isOK= false; while (!isOK) { int cursorleft = Console.CursorLeft; int cursortop = Console.CursorTop; if (int.TryParse(Console.ReadLine(), out actionIndex)) { if (actionIndex < 3) { isOK = true; } } if (!isOK) { Console.SetCursorPosition(cursorleft, cursortop); } } Console.WriteLine(); // Execute function by selected index switch (actionIndex) { case 0: DisconnectPowerMeter(); isloop = false; break; case 1: ReadValueFromPowerMeter(); break; case 2: WriteDefaultParameterValueToPowerMeter(); break; } } } } /// /// This function show how to connect to power meter. /// /// /// private static bool ConnectToPowerMeter(string portName) { // Before connecting, // we should initialize power meter's connection parameters first. // You can change parameter value by yourself. mySetting = new ExampleSetting(); mySetting.PortName = portName; mySetting.Modbus_slave_ID = 1; mySetting.BaudRate = BaudRate[1]; mySetting.StopBit = 1; mySetting.PT = 1; mySetting.CT = 1; Console.WriteLine("Start to connect ICP DAS Power Meter."); // Create a SerialPort instance for COM communication mySerialPort = new SerialPort(); mySerialPort.PortName = mySetting.PortName; mySerialPort.BaudRate = mySetting.BaudRate; mySerialPort.StopBits = (StopBits)mySetting.StopBit; mySerialPort.DataBits = 8; mySerialPort.Parity = Parity.None; mySerialPort.ReadTimeout = 1000; mySerialPort.WriteTimeout = 1000; // Open serialport, and to create an instance for modbus communication. if (!mySerialPort.IsOpen) { try { mySerialPort.Open(); // After COM opened, // to create modbus master instance which is used to communicate a power meter. // Bind modbus master instance to the COM port instance. modbusMaster = ModbusSerialMaster.CreateRtu(mySerialPort); } catch (Exception err) { Console.WriteLine(err.Message); //Console.WriteLine(err.StackTrace); Console.Read(); return false; } } Console.WriteLine("Open ICP DAS Power Meter Success!!"); return true; } /// /// This function show how to disconnect power meter. /// private static void DisconnectPowerMeter() { if (mySerialPort != null) { if (mySerialPort.IsOpen) { mySerialPort.Close(); mySerialPort.Dispose(); modbusMaster.Dispose(); } } } /// /// This function show how to read input registers from power meter. /// private static void ReadValueFromPowerMeter() { // Read Input Registers (Fun04). // Power meter will return 36 Power Parameters (Voltage, Current, Power, Energy...etc) ushort startAddress = 0x1100; // 4352; ushort numRegister = 72; // 36*2 ushort[] PowerParameters = new ushort[72]; if (mySerialPort.IsOpen) { try { // Set parameters of function to get all input register values in power meter. Console.WriteLine("Modbus_slave_ID: {0}, startAddress: {1}, numRegister: {2}", mySetting.Modbus_slave_ID, startAddress, numRegister); PowerParameters = modbusMaster.ReadInputRegisters(mySetting.Modbus_slave_ID, startAddress, numRegister); // Convert two UInt16 values into a IEEE 32 floating point format value. float[] fvalue = new float[36]; for (int i = 0; i < (numRegister / 2); i++) { fvalue[i] = ModbusUtility.GetSingle(PowerParameters[2 * i + 1], PowerParameters[2 * i]); } //Output the result. string titleformate = "{0,13} {1,13} {2,13} {3,13} {4,13}"; string dataformate = "{0,13} {1,13:f3} {2,13:f3} {3,13:f3} {4,13:f3}"; Console.WriteLine(string.Format(titleformate, "", "<>", "<>", "<>", "<>")); Console.WriteLine(string.Format(dataformate, "[Voltage]", fvalue[0], fvalue[9], fvalue[18], fvalue[27])); Console.WriteLine(string.Format(dataformate, "[Current]", fvalue[1], fvalue[10], fvalue[19], fvalue[28])); Console.WriteLine(string.Format(dataformate, "[kW]", fvalue[2], fvalue[11], fvalue[20], fvalue[29])); Console.WriteLine(string.Format(dataformate, "[kVar]", fvalue[3], fvalue[12], fvalue[21], fvalue[30])); Console.WriteLine(string.Format(dataformate, "[kVA]", fvalue[4], fvalue[13], fvalue[22], fvalue[31])); Console.WriteLine(string.Format(dataformate, "[PF]", fvalue[5], fvalue[14], fvalue[23], fvalue[32])); Console.WriteLine(string.Format(dataformate, "[kWh]", fvalue[6], fvalue[15], fvalue[24], fvalue[33])); Console.WriteLine(string.Format(dataformate, "[kvarh]", fvalue[7], fvalue[16], fvalue[25], fvalue[34])); Console.WriteLine(string.Format(dataformate, "[kVah]", fvalue[8], fvalue[17], fvalue[26], fvalue[35])); } catch (Exception err) { Console.WriteLine(err.Message); //Console.WriteLine(err.StackTrace); } } } /// /// This function show how to write and read holding registers /// which store power meter's connection parameters and meter parameters. /// In this function, you will know how to convert modbus holding regester /// values to UI value. /// private static void WriteDefaultParameterValueToPowerMeter() { ushort startAddress = 0x1003; // 4096 ushort numRegister = 2; // only PT, CT ushort[] PowerParameters = new ushort[2]; ushort[] feedbackParams = new ushort[2]; if (mySerialPort.IsOpen) { try { // Default power meter parameters. // User must realize that how to convert the UI value to Modbus register value. // Modbus register value ===> UI value PowerParameters[0] = 1 * 100; // PT ratio: 1 PowerParameters[1] = 1; // CT ratio: 1 // Write data to power meter's holding registers by modbus protocol. modbusMaster.WriteMultipleRegisters(mySetting.Modbus_slave_ID, startAddress, PowerParameters); mySerialPort.Close(); // After write new baudrate data to holding registers, // it must reassign serialport's baudrate value for next connection. mySerialPort.BaudRate = BaudRate[1]; mySerialPort.StopBits = StopBits.One; mySerialPort.Open(); // Read data from power meter's holding registers by modbus protocol. // User must realize how to convert modbus register value to UI value. feedbackParams = modbusMaster.ReadHoldingRegisters(mySetting.Modbus_slave_ID, startAddress, numRegister); Console.WriteLine("The parameter values read back after writing: "); Console.WriteLine(string.Format(" [PT ratio]: {0}", PowerParameters[0] * 0.01 )); Console.WriteLine(string.Format(" [CT ratio]: {0}", PowerParameters[1] )); } catch (Exception err) { Console.WriteLine(err.Message); //Console.WriteLine(err.StackTrace); } } } } }