Exemplo n.º 1
0
        public static SlaveInfo ReloadHardware(string esiDirectoryPath, IExtensionFactory extensionFactory, string interfaceName, SlaveInfo referenceRootSlaveInfo)
        {
            IntPtr    context;
            SlaveInfo newRootSlaveInfo;
            SlaveInfo referenceSlaveInfo;
            IEnumerable <SlaveInfo> referenceSlaveInfoSet;

            referenceSlaveInfo    = null;
            referenceSlaveInfoSet = null;

            if (NetworkInterface.GetAllNetworkInterfaces().Where(x => x.GetPhysicalAddress().ToString() == interfaceName).FirstOrDefault()?.OperationalStatus != OperationalStatus.Up)
            {
                throw new Exception($"The network interface '{interfaceName}' is not linked. Aborting action.");
            }

            context          = EcHL.CreateContext();
            newRootSlaveInfo = EcUtilities.ScanDevices(context, interfaceName, referenceRootSlaveInfo);
            EcHL.FreeContext(context);

            if (referenceRootSlaveInfo != null)
            {
                referenceSlaveInfoSet = referenceRootSlaveInfo.Descendants().ToList();
            }

            newRootSlaveInfo.Descendants().ToList().ForEach(slaveInfo =>
            {
                referenceSlaveInfo = slaveInfo.Csa == slaveInfo.OldCsa ? referenceSlaveInfoSet?.FirstOrDefault(x => x.Csa == slaveInfo.Csa) : null;
                ExtensibilityHelper.GetDynamicSlaveInfoData(esiDirectoryPath, extensionFactory, slaveInfo);
                ExtensibilityHelper.UpdateSlaveExtensions(extensionFactory, slaveInfo, referenceSlaveInfo);
            });

            return(newRootSlaveInfo);
        }
Exemplo n.º 2
0
        public SlaveVariable(SlavePdo parent, string name, ushort index, byte subIndex, DataDirection dataDirection, EthercatDataType dataType, byte bitLength = 0)
        {
            this.Parent        = parent;
            this.Name          = name;
            this.Index         = index;
            this.SubIndex      = subIndex;
            this.DataDirection = dataDirection;
            this.DataType      = dataType;

            if (bitLength == 0)
            {
                this.BitLength = EcUtilities.GetBitLength(dataType);
            }
            else
            {
                this.BitLength = bitLength;
            }
        }
Exemplo n.º 3
0
        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;
            }
        }
Exemplo n.º 4
0
        public static void CreateDynamicData(string esiDirectoryPath, IExtensionFactory extensionFactory, SlaveInfo slaveInfo)
        {
            string          name;
            string          description;
            List <SlavePdo> pdoSet;

            byte[] base64ImageData;

            // find ESI
            if (slaveInfo.Csa != 0)
            {
                (slaveInfo.SlaveEsi, slaveInfo.SlaveEsi_Group) = EsiUtilities.FindEsi(esiDirectoryPath, slaveInfo.Manufacturer, slaveInfo.ProductCode, slaveInfo.Revision);
            }

            //
            pdoSet          = new List <SlavePdo>();
            base64ImageData = new byte[] { };

            name        = slaveInfo.SlaveEsi.Type.Value;
            description = slaveInfo.SlaveEsi.Name.FirstOrDefault()?.Value;

            if (description.StartsWith(name))
            {
                description = description.Substring(name.Length);
            }
            else if (string.IsNullOrWhiteSpace(description))
            {
                description = "no description available";
            }

            // PDOs
            foreach (DataDirection dataDirection in Enum.GetValues(typeof(DataDirection)))
            {
                IEnumerable <PdoType> pdoTypeSet = null;

                switch (dataDirection)
                {
                case DataDirection.Output:
                    pdoTypeSet = slaveInfo.SlaveEsi.RxPdo;
                    break;

                case DataDirection.Input:
                    pdoTypeSet = slaveInfo.SlaveEsi.TxPdo;
                    break;
                }

                foreach (PdoType pdoType in pdoTypeSet)
                {
                    int      syncManager;
                    ushort   pdoIndex;
                    string   pdoName;
                    SlavePdo slavePdo;

                    var osMax = Convert.ToUInt16(pdoType.OSMax);

                    if (osMax == 0)
                    {
                        pdoName     = pdoType.Name.First().Value;
                        pdoIndex    = (ushort)EsiUtilities.ParseHexDecString(pdoType.Index.Value);
                        syncManager = pdoType.SmSpecified ? pdoType.Sm : -1;

                        slavePdo = new SlavePdo(slaveInfo, pdoName, pdoIndex, osMax, pdoType.Fixed, pdoType.Mandatory, syncManager);

                        pdoSet.Add(slavePdo);

                        IList <SlaveVariable> slaveVariableSet = pdoType.Entry.Select(x =>
                        {
                            var variableIndex = (ushort)EsiUtilities.ParseHexDecString(x.Index.Value);
                            var subIndex      = Convert.ToByte(x.SubIndex);
                            //// Improve. What about -1 if SubIndex does not exist?
                            return(new SlaveVariable(slavePdo, x.Name?.FirstOrDefault()?.Value, variableIndex, subIndex, dataDirection, EcUtilities.GetOneDasDataTypeFromEthercatDataType(x.DataType?.Value), (byte)x.BitLen));
                        }).ToList();

                        slavePdo.SetVariableSet(slaveVariableSet);
                    }
                    else
                    {
                        for (ushort indexOffset = 0; indexOffset <= osMax - 1; indexOffset++)
                        {
                            pdoName     = $"{pdoType.Name.First().Value} [{indexOffset}]";
                            pdoIndex    = (ushort)((ushort)EsiUtilities.ParseHexDecString(pdoType.Index.Value) + indexOffset);
                            syncManager = pdoType.SmSpecified ? pdoType.Sm : -1;
                            var indexOffset_Tmp = indexOffset;

                            slavePdo = new SlavePdo(slaveInfo, pdoName, pdoIndex, osMax, pdoType.Fixed, pdoType.Mandatory, syncManager);

                            pdoSet.Add(slavePdo);

                            IList <SlaveVariable> slaveVariableSet = pdoType.Entry.Select(x =>
                            {
                                var variableIndex = (ushort)EsiUtilities.ParseHexDecString(x.Index.Value);
                                var subIndex      = (byte)(byte.Parse(x.SubIndex) + indexOffset_Tmp);
                                //// Improve. What about -1 if SubIndex does not exist?
                                return(new SlaveVariable(slavePdo, x.Name.FirstOrDefault()?.Value, variableIndex, subIndex, dataDirection, EcUtilities.GetOneDasDataTypeFromEthercatDataType(x.DataType?.Value), (byte)x.BitLen));
                            }).ToList();

                            slavePdo.SetVariableSet(slaveVariableSet);
                        }
                    }
                }
            }

            // image data
            if (slaveInfo.SlaveEsi_Group.ItemElementName == ItemChoiceType1.ImageData16x14)
            {
                base64ImageData = (byte[])slaveInfo.SlaveEsi_Group.Item;
            }

            if (slaveInfo.SlaveEsi.ItemElementName.ToString() == nameof(ItemChoiceType1.ImageData16x14))
            {
                base64ImageData = (byte[])slaveInfo.SlaveEsi.Item;
            }

            // attach dynamic data
            slaveInfo.DynamicData = new SlaveInfoDynamicData(name, description, pdoSet, base64ImageData);

            // execute extension logic
            ExtensibilityHelper.UpdateSlaveExtensions(extensionFactory, slaveInfo);

            slaveInfo.SlaveExtensionSet.ToList().ForEach(slaveExtension =>
            {
                slaveExtension.EvaluateSettings();
            });
        }
Exemplo n.º 5
0
        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;
            }
        }
Exemplo n.º 6
0
        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;
            }
        }