206 lines
8.1 KiB
C#

using Modbus.Device; // NModbus namespace
using System.IO.Ports;
using static System.Console;
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;
// Configuration
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;
}
}
// 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;
}
}
}
catch (Exception ex)
{
WriteLine($"Initialization error: {ex.Message}");
}
finally
{
// Shut off the output
master?.WriteSingleRegister(slaveID, SETPOINT1, 0);
// Clean up
master?.Dispose();
serialPort?.Close();
}
static object InitializeModbusSerialPort()
{
SerialPort serialPort;
serialPort = new SerialPort
{
PortName = "COM1",
BaudRate = 19200,
DataBits = 8,
Parity = Parity.None,
StopBits = StopBits.One,
ReadTimeout = 1000
};
serialPort.Open();
return serialPort;
}
static object InitializeModbusMaster(SerialPort serialPort)
{
ushort[] registers;
ushort setPoint = 1000;
ModbusSerialMaster master;
DateTime dateTime;
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;
}
}
}