static async Task Main(string[] args) { /* Set interface name. Edit this to suit your needs. */ var interfaceName = "eth0"; /* Set ESI location. Make sure it contains ESI files! The default path is /home/{user}/.local/share/ESI */ var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var esiDirectoryPath = Path.Combine(localAppDataPath, "ESI"); Directory.CreateDirectory(esiDirectoryPath); /* Copy native file. NOT required in end user scenarios, where EtherCAT.NET package is installed via NuGet! */ var codeBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Directory.EnumerateFiles(Path.Combine(codeBase, "runtimes"), "*soem_wrapper.*", SearchOption.AllDirectories).ToList().ForEach(filePath => { if (filePath.Contains(RuntimeEnvironment.RuntimeArchitecture)) { File.Copy(filePath, Path.Combine(codeBase, Path.GetFileName(filePath)), true); } }); /* create logger */ var loggerFactory = LoggerFactory.Create(loggingBuilder => { loggingBuilder.SetMinimumLevel(LogLevel.Debug); loggingBuilder.AddConsole(); }); var logger = loggerFactory.CreateLogger("EtherCAT Master"); /* create EtherCAT master settings (with 10 Hz cycle frequency) */ var settings = new EcSettings(cycleFrequency: 10U, esiDirectoryPath, interfaceName); /* scan available slaves */ var rootSlave = EcUtilities.ScanDevices(settings.InterfaceName); rootSlave.Descendants().ToList().ForEach(slave => { // If you have special extensions for this slave, add it here: // slave.Extensions.Add(new MyFancyExtension()); /*################ Sample code START ################## * * // Example code to add SDO write request during initialization * // to Beckhoff "EL3021" * if (slave.ProductCode == 0xBCD3052) * { * var dataset = new List<object>(); * dataset.Add((byte)0x01); * * var requests = new List<SdoWriteRequest>() * { * // Index 0x8000 sub index 6: Filter on * new SdoWriteRequest(0x8000, 0x6, dataset) * }; * * slave.Extensions.Add(new InitialSettingsExtension(requests)); * } * ################## Sample code END #################*/ EcUtilities.CreateDynamicData(settings.EsiDirectoryPath, slave); }); /* print list of slaves */ var message = new StringBuilder(); var slaves = rootSlave.Descendants().ToList(); message.AppendLine($"Found {slaves.Count()} slaves:"); foreach (var slave in slaves) { message.AppendLine($"{slave.DynamicData.Name} (PDOs: {slave.DynamicData.Pdos.Count} - CSA: {slave.Csa})"); } logger.LogInformation(message.ToString().TrimEnd()); /* create variable references for later use */ var variables = slaves.SelectMany(child => child.GetVariables()).ToList(); /* create EC Master (short sample) */ using (var master = new EcMaster(settings, logger)) { try { master.Configure(rootSlave); } catch (Exception ex) { logger.LogError(ex.Message); throw; } /* start master */ var random = new Random(); var cts = new CancellationTokenSource(); var task = Task.Run(() => { var sleepTime = 1000 / (int)settings.CycleFrequency; while (!cts.IsCancellationRequested) { master.UpdateIO(DateTime.UtcNow); unsafe { if (variables.Any()) { var myVariableSpan = new Span <int>(variables.First().DataPtr.ToPointer(), 1); myVariableSpan[0] = random.Next(0, 100); } } Thread.Sleep(sleepTime); } }, cts.Token); /* wait for stop signal */ Console.ReadKey(true); cts.Cancel(); await task; } return; /* remove this to run real world sample*/ /* create EC Master (real world sample) */ using (var master = new EcMaster(settings, logger)) { try { master.Configure(rootSlave); } catch (Exception ex) { logger.LogError(ex.Message); throw; } /*################ Sample code START ################## * * // Beckhoff EL2004 (4 channel digital output) * var eL2004 = new DigitalOut(slaves[1]); * * eL2004.SetChannel(1, false); * eL2004.SetChannel(2, true); * eL2004.SetChannel(3, false); * eL2004.SetChannel(4, true); * * // Beckhoff EL1014 (4 channel digital input) * var eL1014 = new DigitalIn(slaves[2]); * * // Beckhoff EL3021 (1 channel analog input - 16bit) * var pdoAnalogIn = slaves[3].DynamicData.Pdos; * var varAnalogIn = pdoAnalogIn[0].Variables.Where(x => x.Name == "Value").First(); * var varUnderrange = pdoAnalogIn[0].Variables.Where(x => x.Name == "Status__Underrange").First(); * var varOverrange = pdoAnalogIn[0].Variables.Where(x => x.Name == "Status__Overrange").First(); * * // Beckhoff EL3021 SDO read (index: 0x8000 sub index: 0x6) * var datasetFilter = new byte[2]; * EcUtilities.SdoRead(master.Context, 4, 0x8000, 6, ref datasetFilter); * var filterOn = BitConverter.ToBoolean(datasetFilter, 0); * logger.LogInformation($"EL3021 filter on: {filterOn}"); * ################## Sample code END #################*/ /* start master */ var random = new Random(); var cts = new CancellationTokenSource(); var task = Task.Run(() => { var sleepTime = 1000 / (int)settings.CycleFrequency; while (!cts.IsCancellationRequested) { master.UpdateIO(DateTime.UtcNow); /*################ Sample code START ################## * * // Beckhoff EL2004 toggle digital output for ch1 and ch3 * eL2004.ToggleChannel(2); * eL2004.ToggleChannel(4); * * // Beckhoff EL1014 read digital input state * logger.LogInformation($"EL1014 channel 1 input: {eL1014.GetChannel(1)}"); * logger.LogInformation($"EL1014 channel 2 input: {eL1014.GetChannel(2)}"); * logger.LogInformation($"EL1014 channel 3 input: {eL1014.GetChannel(3)}"); * logger.LogInformation($"EL1014 channel 4 input: {eL1014.GetChannel(4)}"); * * // Beckhoff EL2004 read digital output state * logger.LogInformation($"EL1014 channel 1 output: {eL2004.GetChannel(1)}"); * logger.LogInformation($"EL1014 channel 2 output: {eL2004.GetChannel(2)}"); * logger.LogInformation($"EL1014 channel 3 output: {eL2004.GetChannel(3)}"); * logger.LogInformation($"EL1014 channel 4 output: {eL2004.GetChannel(4)}"); * * // Beckhoff EL3021 SDO read (index: 0x6000 sub index: 0x2) * // overrange of 12 bit analog input. * var slaveIndex = (ushort)(Convert.ToUInt16(slaves.ToList().IndexOf(slaves[3])) + 1); * var dataset1 = new byte[2]; * EcUtilities.SdoRead(master.Context, slaveIndex, 0x6000, 2, ref dataset1); * bool overrange = BitConverter.ToBoolean(dataset1, 0); * logger.LogInformation($"EL3021 overrange: {overrange}"); * * // Beckhoff EL3021 SDO read (index: 0x6000 sub index: 0x1) * // underrange of 12 bit analog input. * var dataset2 = new byte[2]; * EcUtilities.SdoRead(master.Context, slaveIndex, 0x6000, 1, ref dataset2); * bool underrange = BitConverter.ToBoolean(dataset2, 0); * logger.LogInformation($"EL3021 underrange: {underrange}"); * ################## Sample code END #################*/ unsafe { if (variables.Any()) { /*################ Sample code START ################## * * // Read analog current from EL3021 (16 bit - PDO) * void* data = varAnalogIn.DataPtr.ToPointer(); * int bitmask = (1 << varAnalogIn.BitLength) - 1; * int shift = (*(int*)data >> varAnalogIn.BitOffset) & bitmask; * short analogIn = (short)shift; * logger.LogInformation($"EL3021 analog current in: {analogIn}"); * * // Read analog current underrange status (1 bit - PDO) * void* dataUnder = varUnderrange.DataPtr.ToPointer(); * bitmask = (1 << varUnderrange.BitLength) - 1; * int under = (*(int*)dataUnder >> varUnderrange.BitOffset) & bitmask; * logger.LogInformation($"EL3021 underrange: {under}"); * * // Read analog current overrange status (1 bit - PDO) * void* dataOver = varOverrange.DataPtr.ToPointer(); * bitmask = (1 << varOverrange.BitLength) - 1; * int over = (*(int*)dataOver >> varOverrange.BitOffset) & bitmask; * logger.LogInformation($"EL3021 overrange: {over}"); * ################## Sample code END #################*/ } } Thread.Sleep(sleepTime); } }, cts.Token); /* wait for stop signal */ Console.ReadKey(true); cts.Cancel(); await task; } }
static async Task Main(string[] args) { /* Set interface name. Edit this to suit your needs. */ var interfaceName = "eth0"; /* Set ESI location. Make sure it contains ESI files! The default path is /home/{user}/.local/share/ESI */ var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var esiDirectoryPath = Path.Combine(localAppDataPath, "ESI"); Directory.CreateDirectory(esiDirectoryPath); /* Copy native file. NOT required in end user scenarios, where EtherCAT.NET package is installed via NuGet! */ var codeBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Directory.EnumerateFiles(Path.Combine(codeBase, "runtimes"), "*soem_wrapper.*", SearchOption.AllDirectories).ToList().ForEach(filePath => { if (filePath.Contains(RuntimeEnvironment.RuntimeArchitecture)) { File.Copy(filePath, Path.Combine(codeBase, Path.GetFileName(filePath)), true); } }); /* prepare dependency injection */ var services = new ServiceCollection(); ConfigureServices(services); /* create types */ var provider = services.BuildServiceProvider(); var extensionFactory = provider.GetRequiredService <IExtensionFactory>(); var loggerFactory = provider.GetRequiredService <ILoggerFactory>(); var logger = loggerFactory.CreateLogger("EtherCAT Master"); /* create EtherCAT master settings (with 10 Hz cycle frequency) */ var cycleFrequency = 10U; var settings = new EcSettings(cycleFrequency, esiDirectoryPath, interfaceName); /* create root slave info by scanning available slaves */ var rootSlaveInfo = EcUtilities.ScanDevices(settings.InterfaceName); rootSlaveInfo.Descendants().ToList().ForEach(current => { ExtensibilityHelper.CreateDynamicData(settings.EsiDirectoryPath, extensionFactory, current); }); /* print list of slaves */ var message = new StringBuilder(); var slaves = rootSlaveInfo.Descendants().ToList(); message.AppendLine($"Found {slaves.Count()} slaves:"); slaves.ForEach(current => { message.AppendLine($"{current.DynamicData.Name} (PDOs: {current.DynamicData.PdoSet.Count} - CSA: { current.Csa })"); }); logger.LogInformation(message.ToString().TrimEnd()); /* create variable references for later use */ var variables = slaves.SelectMany(child => child.GetVariableSet()).ToList(); /* create EC Master */ using (var master = new EcMaster(settings, extensionFactory, logger)) { try { master.Configure(rootSlaveInfo); } catch (Exception ex) { logger.LogError(ex.Message); throw; } /* start master */ var random = new Random(); var cts = new CancellationTokenSource(); var task = Task.Run(() => { var sleepTime = 1000 / (int)cycleFrequency; while (!cts.IsCancellationRequested) { master.UpdateIO(DateTime.UtcNow); unsafe { if (variables.Any()) { var myVariableSpan = new Span <int>(variables.First().DataPtr.ToPointer(), 1); myVariableSpan[0] = random.Next(0, 100); } } Thread.Sleep(sleepTime); } }, cts.Token); /* wait for stop signal */ Console.ReadKey(true); cts.Cancel(); await task; } }
static async Task Main(string[] args) { /* Set interface name. Edit this to suit your needs. */ var interfaceName = "Lokal"; /* Set ESI location. Make sure it contains ESI files! The default path is /home/{user}/.local/share/ESI */ var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var esiDirectoryPath = Path.Combine(localAppDataPath, "ESI"); Directory.CreateDirectory(esiDirectoryPath); /* Copy native file. NOT required in end user scenarios, where EtherCAT.NET package is installed via NuGet! */ var codeBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Directory.EnumerateFiles(Path.Combine(codeBase, "runtimes"), "*soem_wrapper.*", SearchOption.AllDirectories).ToList().ForEach(filePath => { if (filePath.Contains(RuntimeEnvironment.RuntimeArchitecture)) { File.Copy(filePath, Path.Combine(codeBase, Path.GetFileName(filePath)), true); } }); /* create logger */ var loggerFactory = LoggerFactory.Create(loggingBuilder => { loggingBuilder.SetMinimumLevel(LogLevel.Debug); loggingBuilder.AddConsole(); }); var logger = loggerFactory.CreateLogger("EtherCAT Master"); /* create EtherCAT master settings (with 10 Hz cycle frequency) */ var settings = new EcSettings(cycleFrequency: 10U, esiDirectoryPath, interfaceName); /* scan available slaves */ var rootSlave = EcUtilities.ScanDevices(settings.InterfaceName); rootSlave.Descendants().ToList().ForEach(slave => { // If you have special extensions for this slave, add it here: // slave.Extensions.Add(new MyFancyExtension()); EcUtilities.CreateDynamicData(settings.EsiDirectoryPath, slave); }); /* print list of slaves */ var message = new StringBuilder(); var slaves = rootSlave.Descendants().ToList(); message.AppendLine($"Found {slaves.Count()} slaves:"); foreach (var slave in slaves) { message.AppendLine($"{slave.DynamicData.Name} (PDOs: {slave.DynamicData.Pdos.Count} - CSA: {slave.Csa})"); } logger.LogInformation(message.ToString().TrimEnd()); /* create variable references for later use */ var variables = slaves.SelectMany(child => child.GetVariables()).ToList(); /* create EC Master */ using (var master = new EcMaster(settings, logger)) { // If you want to change SDO values of a certain slave, register a callback: // // EcHL.RegisterCallback(master.Context, slaveIndex /* 1-based indexing */, slaveIndex => // { // var returnValue = EcUtilities.SdoWrite(master.Context, slaveIndex, ...); // EcUtilities.CheckErrorCode(master.Context, returnValue); // return 0; // }); try { master.Configure(rootSlave); } catch (Exception ex) { logger.LogError(ex.Message); throw; } /* start master */ var random = new Random(); var cts = new CancellationTokenSource(); var task = Task.Run(() => { var sleepTime = 1000 / (int)settings.CycleFrequency; while (!cts.IsCancellationRequested) { master.UpdateIO(DateTime.UtcNow); unsafe { if (variables.Any()) { var myVariableSpan = new Span <int>(variables.First().DataPtr.ToPointer(), 1); myVariableSpan[0] = random.Next(0, 100); } } Thread.Sleep(sleepTime); } }, cts.Token); /* wait for stop signal */ Console.ReadKey(true); cts.Cancel(); await task; } }