206 lines
9.6 KiB
C#
Raw Normal View History

using Modbus.Device; // NModbus namespace for Modbus communication
using System.IO.Ports; // Namespace for serial port communication
using static System.Console; // Static reference to Console for easier access
internal class Program
{
// Modbus Register Addresses for various parameters
private static class ModbusRegisters
{
public const ushort ReadInput1 = 100; // Register for reading input 1
public const ushort Input1Error = 101; // Register for input 1 error status
public const ushort Alarm1Status = 102; // Register for alarm 1 status
public const ushort Alarm2Status = 106; // Register for alarm 2 status
public const ushort AnalogInput1Decimal = 606; // Register for analog input 1 decimal setting
public const ushort PowerOutput1A = 103; // Register for power output 1A
public const ushort SetPoint1 = 300; // Register for set point 1
public const ushort CurrentDay = 1920; // Register for current day
public const ushort CurrentMonth = 1919; // Register for current month
public const ushort CurrentYear = 1921; // Register for current year
public const ushort CurrentHour = 1916; // Register for current hour
public const ushort CurrentMinute = 1917; // Register for current minute
public const ushort CurrentSecond = 1918; // Register for current second
public const ushort Output1AFunction = 700; // Register for output 1A function
public const ushort Output1ACycleTimeType = 509; // Register for output 1A cycle time type
public const ushort Output1ACycleTime = 506; // Register for output 1A cycle time
public const ushort DigitalInput1Function = 1060; // Register for digital input 1 function
public const ushort DigitalInput1Condition = 1061; // Register for digital input 1 condition
public const ushort DigitalInput1Status = 201; // Register for digital input 1 status
public const ushort PowerOutAction = 1206; // Register for power output action
public const ushort PowerOutTime = 1213; // Register for power output time
public const ushort AnalogInputUnits = 608; // Register for analog input units
public const ushort ControlOutputType = 701; // Register for control output type
public const ushort AnalogInput1SensorType = 601; // Register for analog input 1 sensor type
public const ushort AnalogInput1Sensor = 600; // Register for analog input 1 sensor
public const ushort AnalogInput1SetPointHighLimit = 603; // Register for high limit of analog input 1 set point
public const ushort AnalogInput1SetPointLowLimit = 602; // Register for low limit of analog input 1 set point
public const ushort TempScaleDisplay = 1923; // Register for temperature scale display
public const ushort TempScale = 901; // Register for temperature scale
public const ushort AnalogOutput1AType = 701; // Register for analog output 1A type
public const ushort ProportionalBand = 500; // Register for proportional band
}
// Configuration for Modbus Slave ID
private const byte SlaveID = 1;
private static void Main(string[] args)
{
try
{
using SerialPort serialPort = InitializeSerialPort();
using ModbusSerialMaster master = InitializeModbusMaster(serialPort);
MonitorProcessValues(master);
}
catch (Exception ex)
{
WriteLine($"Initialization error: {ex.Message}");
}
}
private static void MonitorProcessValues(ModbusSerialMaster master)
{
while (true)
{
if (KeyAvailable && ReadKey(true).Key == ConsoleKey.Escape)
{
WriteLine("<ESC> pressed. Exiting...");
break;
}
try
{
if (IsInputError(master))
{
WriteLine("Failure in the temperature input channel; program ends here...\n");
return; // Exit if there's an error
}
DisplayCurrentValues(master);
Thread.Sleep(750); // Wait before the next read
}
catch (Exception ex)
{
WriteLine($"Error: {ex.Message}");
break; // Exit on error
}
}
}
private static bool IsInputError(ModbusSerialMaster master)
{
ushort[] registers = master.ReadInputRegisters(SlaveID, ModbusRegisters.Input1Error, 1);
return registers[0] != 0; // Non-zero indicates an error
}
private static void DisplayCurrentValues(ModbusSerialMaster master)
{
ushort[] temperatureRegisters = master.ReadInputRegisters(SlaveID, ModbusRegisters.ReadInput1, 1);
Write("Temperature is {0:F1}; ", temperatureRegisters[0] / 10.0); // Convert to proper format
ushort[] powerOutputRegisters = master.ReadInputRegisters(SlaveID, ModbusRegisters.PowerOutput1A, 1);
WriteLine("Power output is {0:F2}%", powerOutputRegisters[0] / 100.0); // Convert to percentage
}
private static SerialPort InitializeSerialPort()
{
SerialPort serialPort = new SerialPort
{
PortName = "COM1", // Set the COM port
BaudRate = 19200, // Set the baud rate
DataBits = 8, // Set data bits
Parity = Parity.None, // Set parity
StopBits = StopBits.One, // Set stop bits
ReadTimeout = 1000 // Set read timeout
};
serialPort.Open(); // Open the serial port
return serialPort; // Return the configured serial port
}
private static ModbusSerialMaster InitializeModbusMaster(SerialPort serialPort)
{
ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
ConfigureModbusSettings(master); // Configure Modbus settings
return master; // Return the Modbus master
}
private static void ConfigureModbusSettings(ModbusSerialMaster master)
{
WriteLine("Configuring Modbus settings...");
// Set sensor type and configuration
master.WriteSingleRegister(SlaveID, ModbusRegisters.AnalogInput1Sensor, 1);
master.WriteSingleRegister(SlaveID, ModbusRegisters.AnalogInput1SensorType, 11);
master.WriteSingleRegister(SlaveID, ModbusRegisters.AnalogInput1Decimal, 1);
// Set limits and modes for the Modbus device
SetSetPointLimits(master);
SetOutputFunction(master);
SetAnalogOutput(master);
SetTemperatureScale(master);
SetPowerFailureResponse(master);
SetOutputCycleTime(master);
SetCurrentDateTime(master);
}
private static void SetSetPointLimits(ModbusSerialMaster master)
{
ushort[] lowLimitRegisters = master.ReadInputRegisters(SlaveID, ModbusRegisters.AnalogInput1SetPointLowLimit, 1);
WriteLine("Setpoint low limit is {0}", lowLimitRegisters[0]);
ushort[] highLimitRegisters = master.ReadInputRegisters(SlaveID, ModbusRegisters.AnalogInput1SetPointHighLimit, 1);
WriteLine("Setpoint high limit is {0}", highLimitRegisters[0]);
master.WriteSingleRegister(SlaveID, ModbusRegisters.ProportionalBand, 5);
master.WriteSingleRegister(SlaveID, ModbusRegisters.SetPoint1, 1000);
}
private static void SetOutputFunction(ModbusSerialMaster master)
{
master.WriteSingleRegister(SlaveID, ModbusRegisters.Output1AFunction, 1);
}
private static void SetAnalogOutput(ModbusSerialMaster master)
{
master.WriteSingleRegister(SlaveID, ModbusRegisters.AnalogOutput1AType, 0);
}
private static void SetTemperatureScale(ModbusSerialMaster master)
{
master.WriteSingleRegister(SlaveID, ModbusRegisters.AnalogInputUnits, 0);
master.WriteSingleRegister(SlaveID, ModbusRegisters.TempScaleDisplay, 1);
master.WriteSingleRegister(SlaveID, ModbusRegisters.TempScale, 0);
}
private static void SetPowerFailureResponse(ModbusSerialMaster master)
{
master.WriteSingleRegister(SlaveID, ModbusRegisters.PowerOutAction, 2);
}
private static void SetOutputCycleTime(ModbusSerialMaster master)
{
master.WriteSingleRegister(SlaveID, ModbusRegisters.Output1ACycleTimeType, 0);
ushort[] cycleTimeRegisters = master.ReadInputRegisters(SlaveID, ModbusRegisters.Output1ACycleTime, 1);
WriteLine("Output cycle time is {0}", cycleTimeRegisters[0]); // Display current cycle time
master.WriteSingleRegister(SlaveID, ModbusRegisters.Output1ACycleTime, 500); // Set new cycle time
cycleTimeRegisters = master.ReadInputRegisters(SlaveID, ModbusRegisters.Output1ACycleTime, 1);
WriteLine("Output cycle time is now {0}", cycleTimeRegisters[0]); // Confirm new cycle time
}
private static void SetCurrentDateTime(ModbusSerialMaster master)
{
DateTime currentDateTime = DateTime.Now;
master.WriteSingleRegister(SlaveID, ModbusRegisters.CurrentDay, (ushort)currentDateTime.Day);
master.WriteSingleRegister(SlaveID, ModbusRegisters.CurrentMonth, (ushort)currentDateTime.Month);
master.WriteSingleRegister(SlaveID, ModbusRegisters.CurrentYear, (ushort)currentDateTime.Year);
master.WriteSingleRegister(SlaveID, ModbusRegisters.CurrentHour, (ushort)currentDateTime.Hour);
master.WriteSingleRegister(SlaveID, ModbusRegisters.CurrentMinute, (ushort)currentDateTime.Minute);
master.WriteSingleRegister(SlaveID, ModbusRegisters.CurrentSecond, (ushort)currentDateTime.Second);
WriteLine("Set F4 clock to {0} {1}", currentDateTime.ToLongTimeString(), currentDateTime.ToLongDateString()); // Display confirmation
}
}