Refactor; moving closer to C# coding style
Signed-off-by: mharb <mharb@noreply.localhost>
This commit is contained in:
parent
ebcb560ef4
commit
534d72f79b
@ -1,206 +1,206 @@
|
||||
using Modbus.Device; // NModbus namespace
|
||||
using System.IO.Ports;
|
||||
using static System.Console;
|
||||
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
|
||||
{
|
||||
// Registers
|
||||
private const ushort READINPUT1 = 100;
|
||||
private const ushort INPUT1ERROR = 101;
|
||||
private const ushort ALARM1STATUS = 102;
|
||||
private const ushort ALARM2STATUS = 106;
|
||||
private const ushort ANALOGINPUT1DECIMAL = 606;
|
||||
private const ushort POWEROUTPUT1A = 103;
|
||||
private const ushort SETPOINT1 = 300;
|
||||
private const ushort CURRENTDAY = 1920;
|
||||
private const ushort CURRENTMONTH = 1919;
|
||||
private const ushort CURRENTYEAR = 1921;
|
||||
private const ushort CURRENTHOUR = 1916;
|
||||
private const ushort CURRENTMINUTE = 1917;
|
||||
private const ushort CURRENTSECOND = 1918;
|
||||
private const ushort OUTPUT1AFUNCTION = 700;
|
||||
private const ushort OUTPUT1ACYCLETIMETYPE = 509;
|
||||
private const ushort OUTPUT1ACYCLETIME = 506;
|
||||
private const ushort DIGITALINPUT1FUNCTION = 1060;
|
||||
private const ushort DIGITALINPUT1CONDITION = 1061;
|
||||
private const ushort DIGITALINPUT1STATUS = 201;
|
||||
private const ushort POWEROUTACTION = 1206;
|
||||
private const ushort POWEROUTTIME = 1213;
|
||||
private const ushort ANALOGINPUTUNITS = 608;
|
||||
private const ushort CONTROLOUTPUTTYPE = 701;
|
||||
private const ushort ANALOGINPUT1SENSORTYPE = 601;
|
||||
private const ushort ANALOGINPUT1SENSOR = 600;
|
||||
private const ushort ANALOGINPUT1SETPOINTHIGHLIMIT = 603;
|
||||
private const ushort ANALOGINPUT1SETPOINTLOWLIMIT = 602;
|
||||
private const ushort TEMPSCALEDISPLAY = 1923;
|
||||
private const ushort TEMPSCALE = 901;
|
||||
private const ushort ANALOGOUTPUT1ATYPE = 701;
|
||||
private const ushort PROPORTIONALBAND = 500;
|
||||
// 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
|
||||
private const byte slaveID = 1;
|
||||
// Configuration for Modbus Slave ID
|
||||
private const byte SlaveID = 1;
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
ushort[] registers;
|
||||
|
||||
// Initialize the F4
|
||||
SerialPort serialPort = (SerialPort)InitializeModbusSerialPort();
|
||||
ModbusSerialMaster master = (ModbusSerialMaster)InitializeModbusMaster(serialPort);
|
||||
|
||||
// Then, run it
|
||||
try
|
||||
{
|
||||
// Monitor continuously
|
||||
while (true)
|
||||
{
|
||||
// Check for escape key press
|
||||
if (KeyAvailable)
|
||||
{
|
||||
ConsoleKeyInfo key = ReadKey(true);
|
||||
if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
WriteLine("<ESC> pressed. Exiting...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
using SerialPort serialPort = InitializeSerialPort();
|
||||
using ModbusSerialMaster master = InitializeModbusMaster(serialPort);
|
||||
|
||||
// Display current process values
|
||||
try
|
||||
{
|
||||
registers = master.ReadInputRegisters(slaveID, INPUT1ERROR, 1);
|
||||
if (registers[0] != 0)
|
||||
{
|
||||
WriteLine("Failure in the temperature input channel; program ends here...\n");
|
||||
return;
|
||||
};
|
||||
registers = master.ReadInputRegisters(slaveID, READINPUT1, 1);
|
||||
Write("temperature is {0:F1}; ", registers[0] / 10.0);
|
||||
registers = master.ReadInputRegisters(slaveID, POWEROUTPUT1A, 1);
|
||||
Write("power output is {0:F2}%\n", registers[0] / 100.0);
|
||||
// Pause before next read
|
||||
Thread.Sleep(750);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteLine($"Error: {ex.Message}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
MonitorProcessValues(master);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteLine($"Initialization error: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
}
|
||||
|
||||
private static void MonitorProcessValues(ModbusSerialMaster master)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Shut off the output
|
||||
master?.WriteSingleRegister(slaveID, SETPOINT1, 0);
|
||||
|
||||
// Clean up
|
||||
master?.Dispose();
|
||||
serialPort?.Close();
|
||||
}
|
||||
|
||||
static object InitializeModbusSerialPort()
|
||||
{
|
||||
SerialPort serialPort;
|
||||
|
||||
serialPort = new SerialPort
|
||||
if (KeyAvailable && ReadKey(true).Key == ConsoleKey.Escape)
|
||||
{
|
||||
PortName = "COM1",
|
||||
BaudRate = 19200,
|
||||
DataBits = 8,
|
||||
Parity = Parity.None,
|
||||
StopBits = StopBits.One,
|
||||
ReadTimeout = 1000
|
||||
};
|
||||
serialPort.Open();
|
||||
return serialPort;
|
||||
}
|
||||
WriteLine("<ESC> pressed. Exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
static object InitializeModbusMaster(SerialPort serialPort)
|
||||
{
|
||||
ushort[] registers;
|
||||
ushort setPoint = 1000;
|
||||
ModbusSerialMaster master;
|
||||
DateTime dateTime;
|
||||
try
|
||||
{
|
||||
if (IsInputError(master))
|
||||
{
|
||||
WriteLine("Failure in the temperature input channel; program ends here...\n");
|
||||
return; // Exit if there's an error
|
||||
}
|
||||
|
||||
master = ModbusSerialMaster.CreateRtu(serialPort);
|
||||
|
||||
// Set sensor type
|
||||
WriteLine("Set sensor type to 100 Ω DIN platinum RTD");
|
||||
master.WriteSingleRegister(slaveID, ANALOGINPUT1SENSOR, 1);
|
||||
master.WriteSingleRegister(slaveID, ANALOGINPUT1SENSORTYPE, 11);
|
||||
|
||||
// Set to one decimal place (this cannot be the first initialization instruction)
|
||||
WriteLine("Set to one decimal place on display");
|
||||
master.WriteSingleRegister(slaveID, ANALOGINPUT1DECIMAL, 1);
|
||||
|
||||
// Display current setpoint high and low limits
|
||||
registers = master.ReadInputRegisters(slaveID, ANALOGINPUT1SETPOINTLOWLIMIT, 1);
|
||||
WriteLine("Setpoint low limit is {0}", registers[0]);
|
||||
registers = master.ReadInputRegisters(slaveID, ANALOGINPUT1SETPOINTHIGHLIMIT, 1);
|
||||
WriteLine("Setpoint high limit is {0}", registers[0]);
|
||||
|
||||
// Set to proportional mode
|
||||
WriteLine("Make proportional band 5°F");
|
||||
master.WriteSingleRegister(slaveID, PROPORTIONALBAND, 5);
|
||||
|
||||
// Set output function to heating
|
||||
WriteLine("Output function is heating");
|
||||
master.WriteSingleRegister(slaveID, OUTPUT1AFUNCTION, 1);
|
||||
|
||||
// Set analog output1 to 4-20 ma
|
||||
WriteLine("Set the analog output to 4-20 MA");
|
||||
master.WriteSingleRegister(slaveID, ANALOGOUTPUT1ATYPE, 0);
|
||||
|
||||
// Set analog input parameter to temperature
|
||||
master.WriteSingleRegister(slaveID, ANALOGINPUTUNITS, 0);
|
||||
|
||||
// Set temperature SCALE to ON
|
||||
master.WriteSingleRegister(slaveID, TEMPSCALEDISPLAY, 1);
|
||||
|
||||
// Set temperature scale type to Fahrenheit
|
||||
master.WriteSingleRegister(slaveID, TEMPSCALE, 0);
|
||||
|
||||
// Set power failure response
|
||||
master.WriteSingleRegister(slaveID, POWEROUTACTION, 2);
|
||||
|
||||
// Set output1 cycle time type to variable burst
|
||||
master.WriteSingleRegister(slaveID, OUTPUT1ACYCLETIMETYPE, 0);
|
||||
|
||||
// Read current output1 cycle time
|
||||
registers = master.ReadInputRegisters(slaveID, OUTPUT1ACYCLETIME, 1);
|
||||
WriteLine("Output cycle time is {0}", registers[0]);
|
||||
|
||||
// Set output1 cycle time to new value
|
||||
master.WriteSingleRegister(slaveID, OUTPUT1ACYCLETIME, 500);
|
||||
|
||||
// Check new value
|
||||
registers = master.ReadInputRegisters(slaveID, OUTPUT1ACYCLETIME, 1);
|
||||
WriteLine("Output cycle time is now {0}", registers[0]);
|
||||
|
||||
// Write setpoint to F4
|
||||
WriteLine("Setting the process variable setpoint");
|
||||
master.WriteSingleRegister(slaveID, SETPOINT1, setPoint);
|
||||
|
||||
// Verify setpoint value
|
||||
WriteLine("Verifying the setpoint value");
|
||||
registers = master.ReadInputRegisters(slaveID, SETPOINT1, 1);
|
||||
WriteLine("Setpoint is {0:F1}", registers[0] / 10.0);
|
||||
|
||||
// Set F4 clock to current date and time
|
||||
dateTime = DateTime.Now;
|
||||
master.WriteSingleRegister(slaveID, CURRENTDAY, (ushort)dateTime.Day);
|
||||
master.WriteSingleRegister(slaveID, CURRENTMONTH, (ushort)dateTime.Month);
|
||||
master.WriteSingleRegister(slaveID, CURRENTYEAR, (ushort)dateTime.Year);
|
||||
master.WriteSingleRegister(slaveID, CURRENTHOUR, (ushort)dateTime.Hour);
|
||||
master.WriteSingleRegister(slaveID, CURRENTMINUTE, (ushort)dateTime.Minute);
|
||||
master.WriteSingleRegister(slaveID, CURRENTSECOND, (ushort)dateTime.Second);
|
||||
WriteLine("Set F4 clock to {0} {1}", dateTime.ToLongTimeString(), dateTime.ToLongDateString());
|
||||
|
||||
return master;
|
||||
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
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user