示例#1
0
        private void ConfigureSync01(IList <SlaveInfo> slaveInfoSet)
        {
            // SYNC0 / SYNC1
            foreach (SlaveInfo slaveInfo in slaveInfoSet)
            {
                ushort slaveIndex;
                DistributedClocksSettings distributedClocksSettings;

                slaveIndex = (ushort)(Convert.ToUInt16(slaveInfoSet.ToList().IndexOf(slaveInfo)) + 1);
                distributedClocksSettings = slaveInfo.SlaveExtensionSet.OfType <DistributedClocksSettings>().ToList().FirstOrDefault();

                if (distributedClocksSettings != null)
                {
                    DistributedClocksParameters parameters;
                    byte[] assignActivate;

                    if (!slaveInfo.SlaveEsi.Dc.TimeLoopControlOnly)
                    {
                        assignActivate = null;
                        parameters     = distributedClocksSettings.CalculateDcParameters(ref assignActivate, _settings.CycleFrequency);
                        EcUtilities.CheckErrorCode(this.Context, EcHL.ConfigureSync01(this.Context, slaveIndex, ref assignActivate, assignActivate.Count(), parameters.CycleTime0, parameters.CycleTime1, parameters.ShiftTime0));
                    }
                }
            }
        }
示例#2
0
        private void ConfigureSlaves(IList <SlaveInfo> slaves)
        {
            var callbacks = new List <EcHL.PO2SOCallback>();

            foreach (var slave in slaves)
            {
                // SDO / PDO config / PDO assign
                var currentSlaveIndex = (ushort)(Convert.ToUInt16(slaves.ToList().IndexOf(slave)) + 1);
                var extensions        = slave.Extensions;

                var sdoWriteRequests = slave.GetConfiguration(extensions).ToList();

                EcHL.PO2SOCallback callback = slaveIndex =>
                {
                    sdoWriteRequests.ToList().ForEach(sdoWriteRequest =>
                    {
                        EcUtilities.CheckErrorCode(this.Context, EcUtilities.SdoWrite(this.Context, slaveIndex, sdoWriteRequest.Index, sdoWriteRequest.SubIndex, sdoWriteRequest.Dataset), nameof(EcHL.SdoWrite));
                    });

                    return(0);
                };

                EcHL.RegisterCallback(this.Context, currentSlaveIndex, callback);
                callbacks.Add(callback);
            }

            callbacks.ForEach(callback =>
            {
                GC.KeepAlive(callback);
            });
        }
示例#3
0
        public static SlaveInfo RescanDevices(EcSettings settings, SlaveInfo referenceRootSlave)
        {
            var referenceSlaves = default(IEnumerable <SlaveInfo>);

            if (referenceRootSlave != null)
            {
                referenceSlaves = referenceRootSlave.Descendants().ToList();
            }

            var newRootSlave = EcUtilities.ScanDevices(settings.InterfaceName, referenceRootSlave);

            newRootSlave.Descendants().ToList().ForEach(slave =>
            {
                var referenceSlave = slave.Csa == slave.OldCsa
                    ? referenceSlaves?.FirstOrDefault(x => x.Csa == slave.Csa)
                    : null;

                if (referenceSlave != null)
                {
                    slave.Extensions = referenceSlave.Extensions;
                }

                EcUtilities.CreateDynamicData(settings.EsiDirectoryPath, slave);
            });

            return(newRootSlave);
        }
示例#4
0
        /// <summary>
        /// Initializes EtherCAT and returns found slaves.
        /// </summary>
        /// <param name="interfaceName">The name of the network adapter.</param>
        /// <returns>Returns found slave.</returns>
        public static SlaveInfo ScanDevices(IntPtr context, string interfaceName, SlaveInfo referenceSlave = null)
        {
            ec_slave_info_t[] refSlaveIdentifications = null;

            if (referenceSlave != null)
            {
                refSlaveIdentifications = EcUtilities.ToSlaveIdentifications(referenceSlave);
            }
            else
            {
                refSlaveIdentifications = new ec_slave_info_t[] { }
            };

            // scan devices
            var networkInterface = NetworkInterface
                                   .GetAllNetworkInterfaces()
                                   .Where(nic => nic.Name == interfaceName)
                                   .FirstOrDefault();

            if (networkInterface == null)
            {
                throw new Exception($"{ ErrorMessage.SoemWrapper_NetworkInterfaceNotFound } Interface name: '{ interfaceName }'.");
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                interfaceName = $@"rpcap://\Device\NPF_{networkInterface.Id}";
            }

            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
                     RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                interfaceName = $"{interfaceName}";
            }

            else
            {
                throw new PlatformNotSupportedException();
            }

            EcUtilities.CheckErrorCode(context, EcHL.ScanDevices(context, interfaceName, out var slaveIdentifications, out var slaveCount));

            // create slaveInfo from received data
            var offset = 0;
            var newSlaveIdentifications = new ec_slave_info_t[slaveCount + 1]; // correct because EC master = slaveIdentifications[0]

            for (int i = 0; i <= newSlaveIdentifications.Count() - 1; i++)
            {
                newSlaveIdentifications[i] = Marshal.PtrToStructure <ec_slave_info_t>(IntPtr.Add(slaveIdentifications, offset));
                offset += Marshal.SizeOf(typeof(ec_slave_info_t));
            }

            // validate CSA
            while (EcUtilities.EnsureValidCsa(context, newSlaveIdentifications, refSlaveIdentifications))
            {
                //
            }

            return(EcUtilities.ToSlaveInfo(newSlaveIdentifications));
        }
示例#5
0
        private void ConfigureDc()
        {
            uint systemTimeDifference;

            EcUtilities.CheckErrorCode(this.Context, EcHL.ConfigureDc(this.Context, _settings.FrameCount, _settings.TargetTimeDifference, out systemTimeDifference), nameof(EcHL.ConfigureDc));

            _logger.LogInformation($"DC system time diff. is <= { systemTimeDifference & 0x7FFF } ns");
        }
示例#6
0
        public void Configure(SlaveInfo rootSlaveInfo = null)
        {
            SlaveInfo         actualSlaveInfo;
            IList <SlaveInfo> slaveInfoSet;
            IList <SlaveInfo> actualSlaveInfoSet;
            NetworkInterface  networkInterface;

            networkInterface = NetworkInterface.GetAllNetworkInterfaces().Where(nic => nic.Name == _settings.InterfaceName).FirstOrDefault();

            if (networkInterface?.OperationalStatus != OperationalStatus.Up)
            {
                throw new Exception($"Network interface '{_settings.InterfaceName}' is not linked. Aborting action.");
            }

            #region "PreOp"

            actualSlaveInfo = EcUtilities.ScanDevices(this.Context, _settings.InterfaceName, null);

            if (rootSlaveInfo == null)
            {
                rootSlaveInfo = actualSlaveInfo;

                rootSlaveInfo.Descendants().ToList().ForEach(current =>
                {
                    ExtensibilityHelper.CreateDynamicData(_settings.EsiDirectoryPath, _extensionFactory, current);
                });
            }

            slaveInfoSet       = rootSlaveInfo.Descendants().ToList();
            actualSlaveInfoSet = actualSlaveInfo.Descendants().ToList();

            this.ValidateSlaves(slaveInfoSet, actualSlaveInfoSet);
            this.ConfigureSlaves(slaveInfoSet);
            this.ConfigureIoMap(slaveInfoSet);
            this.ConfigureDc();
            this.ConfigureSync01(slaveInfoSet);

            #endregion

            #region "SafeOp"

            EcUtilities.CheckErrorCode(this.Context, EcHL.CheckSafeOpState(this.Context), nameof(EcHL.CheckSafeOpState));

            #endregion

            #region "Op"

            EcUtilities.CheckErrorCode(this.Context, EcHL.RequestOpState(this.Context), nameof(EcHL.RequestOpState));

            #endregion

            if (_watchdogTask == null)
            {
                _watchdogTask = Task.Run(() => this.WatchdogRoutine(), _cts.Token);
            }
        }
示例#7
0
        public void Configure(SlaveInfo rootSlave = null)
        {
            var networkInterface = NetworkInterface
                                   .GetAllNetworkInterfaces()
                                   .Where(nic => nic.Name == _settings.InterfaceName)
                                   .FirstOrDefault();

            if (networkInterface?.OperationalStatus != OperationalStatus.Up)
            {
                throw new Exception($"Network interface '{_settings.InterfaceName}' is not linked. Aborting action.");
            }

            #region "PreOp"

            var actualSlave = EcUtilities.ScanDevices(this.Context, _settings.InterfaceName, null);

            if (rootSlave == null)
            {
                rootSlave = actualSlave;

                rootSlave.Descendants().ToList().ForEach(current =>
                {
                    EcUtilities.CreateDynamicData(_settings.EsiDirectoryPath, current);
                });
            }

            var slaves       = rootSlave.Descendants().ToList();
            var actualSlaves = actualSlave.Descendants().ToList();

            this.ValidateSlaves(slaves, actualSlaves);
            this.ConfigureSlaves(slaves);
            this.ConfigureIoMap(slaves);
            this.ConfigureDc();
            this.ConfigureSync01(slaves);

            #endregion

            #region "SafeOp"

            EcUtilities.CheckErrorCode(this.Context, EcHL.CheckSafeOpState(this.Context), nameof(EcHL.CheckSafeOpState));

            #endregion

            #region "Op"

            EcUtilities.CheckErrorCode(this.Context, EcHL.RequestCommonState(this.Context, (UInt16)SlaveState.Operational), nameof(EcHL.RequestCommonState));

            #endregion

            if (_watchdogTask == null)
            {
                _watchdogTask = Task.Run(() => this.WatchdogRoutine(), _cts.Token);
            }
        }
示例#8
0
 public static OneDasDataType GetOneDasDataTypeFromEthercatDataType(string value)
 {
     if (value == null)
     {
         return(0);
     }
     else
     {
         return(EcUtilities.GetOneDasDataTypeFromEthercatDataType((EthercatDataType)Enum.Parse(typeof(EthercatDataType), value)));
     }
 }
示例#9
0
        public static SlaveInfo ScanDevices(string interfaceName, SlaveInfo referenceSlaveInfo = null)
        {
            IntPtr    context;
            SlaveInfo slaveInfo;

            context   = EcHL.CreateContext();
            slaveInfo = EcUtilities.ScanDevices(context, interfaceName, referenceSlaveInfo);
            EcHL.FreeContext(context);

            return(slaveInfo);
        }
示例#10
0
        public static SlaveInfo ScanDevices(string interfaceName, SlaveInfo referenceRootSlave = null)
        {
            if (NetworkInterface.GetAllNetworkInterfaces().Where(x => x.Name == interfaceName).FirstOrDefault()?.OperationalStatus != OperationalStatus.Up)
            {
                throw new Exception($"The network interface '{interfaceName}' is not linked. Aborting action.");
            }

            var context   = EcHL.CreateContext();
            var rootSlave = EcUtilities.ScanDevices(context, interfaceName, referenceRootSlave);

            EcHL.FreeContext(context);

            return(rootSlave);
        }
示例#11
0
        private void ConfigureSlaves(IList <SlaveInfo> slaveInfoSet)
        {
            List <EcHL.PO2SOCallback> callbackSet;

            callbackSet = new List <EcHL.PO2SOCallback>();

            foreach (SlaveInfo slaveInfo in slaveInfoSet)
            {
                ushort currentSlaveIndex;
                IEnumerable <SlaveExtensionLogic> extensionSet;
                IEnumerable <SdoWriteRequest>     sdoWriteRequestSet;
                EcHL.PO2SOCallback callback;

                // SDO / PDO config / PDO assign
                currentSlaveIndex = (ushort)(Convert.ToUInt16(slaveInfoSet.ToList().IndexOf(slaveInfo)) + 1);
                extensionSet      = slaveInfo.SlaveExtensionSet.Select(slaveExtension => _extensionFactory.BuildLogic <SlaveExtensionLogic>(slaveExtension)).ToList();

                sdoWriteRequestSet = slaveInfo.GetConfiguration(extensionSet).ToList();

                callback = slaveIndex =>
                {
                    sdoWriteRequestSet.ToList().ForEach(sdoWriteRequest =>
                    {
                        EcUtilities.CheckErrorCode(this.Context, EcUtilities.SdoWrite(this.Context, slaveIndex, sdoWriteRequest.Index, sdoWriteRequest.SubIndex, sdoWriteRequest.Dataset), nameof(EcHL.SdoWrite));
                    });

                    return(0);
                };

                EcHL.RegisterCallback(this.Context, currentSlaveIndex, callback);
                callbackSet.Add(callback);
            }

            callbackSet.ForEach(callback =>
            {
                GC.KeepAlive(callback);
            });
        }
示例#12
0
        private void ConfigureSync01(IList <SlaveInfo> slaves)
        {
            // SYNC0 / SYNC1
            foreach (var slave in slaves)
            {
                var slaveIndex = (ushort)(Convert.ToUInt16(slaves.ToList().IndexOf(slave)) + 1);
                var distributedClocksSettings = slave
                                                .Extensions
                                                .OfType <DistributedClocksExtension>()
                                                .ToList()
                                                .FirstOrDefault();

                if (distributedClocksSettings != null)
                {
                    if (!slave.Esi.Dc.TimeLoopControlOnly)
                    {
                        byte[] assignActivate = null;
                        var    parameters     = distributedClocksSettings.CalculateDcParameters(ref assignActivate, _settings.CycleFrequency);
                        EcUtilities.CheckErrorCode(this.Context, EcHL.ConfigureSync01(this.Context, slaveIndex, ref assignActivate, assignActivate.Count(), parameters.CycleTime0, parameters.CycleTime1, parameters.ShiftTime0));
                    }
                }
            }
        }
示例#13
0
        public static void CreateDynamicData(string esiDirectoryPath, SlaveInfo slave)
        {
            // find ESI
            if (slave.Csa != 0)
            {
                (slave.Esi, slave.EsiGroup) = EsiUtilities.FindEsi(esiDirectoryPath, slave.Manufacturer, slave.ProductCode, slave.Revision);
            }

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

            var name        = slave.Esi.Type.Value;
            var description = slave.Esi.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> pdoTypes = null;

                switch (dataDirection)
                {
                case DataDirection.Output:
                    pdoTypes = slave.Esi.RxPdo;
                    break;

                case DataDirection.Input:
                    pdoTypes = slave.Esi.TxPdo;
                    break;
                }

                foreach (var pdoType in pdoTypes)
                {
                    var osMax = Convert.ToUInt16(pdoType.OSMax);

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

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

                        pdos.Add(slavePdo);

                        var slaveVariables = 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.ParseEtherCatDataType(x.DataType?.Value), (byte)x.BitLen));
                        }).ToList();

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

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

                            pdos.Add(slavePdo);

                            var slaveVariables = 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.ParseEtherCatDataType(x.DataType?.Value), (byte)x.BitLen));
                            }).ToList();

                            slavePdo.SetVariables(slaveVariables);
                        }
                    }
                }
            }

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

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

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

            // add DC extension to extensions
            if (slave.Esi.Dc is not null &&
                !slave.Extensions.Any(extension => extension.GetType() == typeof(DistributedClocksExtension)))
            {
                slave.Extensions.Add(new DistributedClocksExtension(slave));
            }

            // execute extension logic
            slave.Extensions.ToList().ForEach(extension =>
            {
                extension.EvaluateSettings();
            });
        }
示例#14
0
        public static SlavePdo[] UploadPdoConfig(IntPtr context, UInt16 slave, UInt16 smIndex)
        {
            int    pdoCount;
            IntPtr ecPdoInfoPtrSet;

            SlavePdo[]      slavePdoSet;
            SyncManagerType syncManagerType;
            DataDirection   dataDirection;

            //
            EcHL.GetSyncManagerType(context, slave, smIndex, out syncManagerType);

            switch (syncManagerType)
            {
            case SyncManagerType.Inputs:
                dataDirection = DataDirection.Input;
                break;

            case SyncManagerType.Outputs:
                dataDirection = DataDirection.Output;
                break;

            default:
                throw new ArgumentException();
            }

            EcHL.UploadPdoConfig(context, slave, smIndex, out ecPdoInfoPtrSet, out pdoCount);

            slavePdoSet = Enumerable.Range(0, pdoCount).Select(index =>
            {
                ec_pdo_info_t ecPdoInfo;
                SlavePdo slavePdo;
                IntPtr ecPdoInfoPtr;

                ecPdoInfoPtr = IntPtr.Add(ecPdoInfoPtrSet, index * Marshal.SizeOf(typeof(ec_pdo_info_t)));
                ecPdoInfo    = Marshal.PtrToStructure <ec_pdo_info_t>(ecPdoInfoPtr);
                slavePdo     = new SlavePdo(null, ecPdoInfo.name, ecPdoInfo.index, 0, true, true, smIndex - 0x1C10);

                slavePdo.SetVariableSet(Enumerable.Range(0, ecPdoInfo.variableCount).Select(index2 =>
                {
                    ec_variable_info_t ecVariableInfo;
                    SlaveVariable slaveVariable;
                    IntPtr ecVariableInfoPtr;

                    ecVariableInfoPtr = IntPtr.Add(ecPdoInfo.variableInfoSet, index2 * Marshal.SizeOf(typeof(ec_variable_info_t)));
                    ecVariableInfo    = Marshal.PtrToStructure <ec_variable_info_t>(ecVariableInfoPtr);
                    slaveVariable     = new SlaveVariable(slavePdo, ecVariableInfo.name, ecVariableInfo.index, ecVariableInfo.subIndex, dataDirection, EcUtilities.GetOneDasDataTypeFromEthercatDataType(ecVariableInfo.dataType));

                    return(slaveVariable);
                }).ToList());

                EcHL.Free(ecPdoInfo.variableInfoSet);

                return(slavePdo);
            }).ToArray();

            EcHL.Free(ecPdoInfoPtrSet);

            return(slavePdoSet);
        }