// This program connects to a Sealevel type 463E-OEM I/O processor https://www.sealevel.com/seai-o-463e-oem/ // Note: this program cannot be started until at least five seconds after powering up the I/O processor // Note: if the program is interrupted and does not terminate normally, a power reset is required on the 463E using Modbus.Device; using System.Net.Sockets; using static System.Console; namespace ModbusReadRegisters { internal class ModbusProgram { private const string IPaddress = "10.10.10.110"; // Modbus device IP private const int Port = 502; // Default Modbus TCP port private const byte SlaveID = 247; // Modbus slave ID private const ushort RegisterStartAddress = 0; // Starting address to read private const ushort NumRegisters = 9; // Number of registers to read private const ushort CoilStartAddress = 0; // Starting address to write coils private static void Main(string[] args) { WriteLine("ModbusProgram begins here...\n\n"); try { using TcpClient client = new(IPaddress, Port); // Build a client ModbusIpMaster master = ModbusIpMaster.CreateIp(client); WriteLine("CreateIp done\n"); // Read register values ushort[] registers = master.ReadHoldingRegisters(SlaveID, RegisterStartAddress, NumRegisters); WriteLine("ReadHoldingRegisters done\n"); DisplayRegisters(registers, RegisterStartAddress); WriteLine("\nDisplayRegisters done\n"); // Set all channels as outputs master.WriteSingleRegister(SlaveID, 2, 0); WriteLine("WriteSingleRegister done."); // Write to specific outputs WriteIndividualCoils(master, registers, CoilStartAddress); WriteLine("WriteIndividualCoils done\n"); // Write to groups of eight outputs at a time WriteAllOutputs(SlaveID, master); WriteLine("WriteAllOutputs done\n"); ShutDown(SlaveID, master); } catch (Exception ex) { WriteLine("An error occurred:\n\n" + ex.Message); } finally { WriteLine("\nModbusProgram ends here.\n"); _ = ReadKey(true); } } // Print registers we found and their values private static void DisplayRegisters(ushort[] registers, ushort startAddress) { WriteLine($"Read {registers.Length} registers starting at address {startAddress}:"); for (int i = 0; i < registers.Length; i++) { WriteLine($"Register {startAddress + i}: {registers[i]}"); } } // Exercise two racks, eight points at a time private static void WriteAllOutputs(ushort slaveID, ModbusIpMaster master) { bool[] valueArrayON = [true, false, true, false, true, false, true, false]; bool[] valueArrayOFF = [false, true, false, true, false, true, false, true]; WriteLine("Writing to two boards at once:\n"); for (ushort j = 0; j < 4; j++) { for (ushort i = 0; i < 6; i++) { master.WriteMultipleCoils((byte)slaveID, (ushort)(i * 8), valueArrayON); } Thread.Sleep(150); for (ushort i = 0; i < 6; i++) { master.WriteMultipleCoils((byte)slaveID, (ushort)(i * 8), valueArrayOFF); } } } // Execise individual outputs private static void WriteIndividualCoils(ModbusIpMaster master, ushort[] registers, ushort coilStartAddress) { WriteLine("The value of 'coilStartAddress' is {0}", coilStartAddress); for (int i = 0; i < registers.Length; i++) { WriteLine(registers[i]); } DisplayRegisters(registers, RegisterStartAddress); for (ushort j = 0; j < 4; j++) { WriteLine("Turning the outputs ON."); for (ushort i = 0; i < 48; i++) { master.WriteSingleCoil(SlaveID, i, true); } for (ushort i = 0; i < 48; i++) { master.WriteSingleCoil(SlaveID, i, false); } } WriteLine("\nDone writing individual outputs!\n\n"); } // Shut off all outputs private static void ShutDown(ushort slaveID, ModbusIpMaster master) { bool[] valueArrayOFF = [false, false, false, false, false, false, false, false]; for (ushort i = 0; i < 6; i++) { master.WriteMultipleCoils((byte)slaveID, (ushort)(i * 8), valueArrayOFF); } } } }