From 2dbdf5fbb90a199be51e3bf9affef7cc46d084dd Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Mon, 28 Dec 2020 08:26:13 +0100 Subject: [PATCH] Added class ControllerLogic, Hardcoded Beta for GalaTech "Bohrautomat" --- ln.ethercat.service/EthercatService.cs | 6 +-- .../MainAxFeederControllerLogic.cs | 34 +++++++++++------ ln.ethercat.service/Program.cs | 15 +------- .../api/v1/ControllerApiController.cs | 11 +++++- .../api/v1/ControllerWebSocket.cs | 2 - .../api/v1/EthercatWebSocket.cs | 3 -- .../ln.ethercat.service.csproj | 9 +++-- ln.ethercat.service/www/html/spa.html | 12 ++++-- ln.ethercat.service/www/static/css/spa.css | 30 ++++++++++++++- .../www/static/pages/controller.html | 10 ++--- ln.ethercat/controller/Controller.cs | 38 +++++++++++++++++++ ln.ethercat/controller/ControllerLogic.cs | 10 +++++ .../controller/drives/CIA402Controller.cs | 8 ++-- .../controller/drives/DriveController.cs | 30 ++++++++++++--- ln.ethercat/ln.ethercat.csproj | 4 +- 15 files changed, 164 insertions(+), 58 deletions(-) create mode 100644 ln.ethercat/controller/ControllerLogic.cs diff --git a/ln.ethercat.service/EthercatService.cs b/ln.ethercat.service/EthercatService.cs index 978d689..2c87820 100644 --- a/ln.ethercat.service/EthercatService.cs +++ b/ln.ethercat.service/EthercatService.cs @@ -1,12 +1,10 @@ using System; using System.IO; -using System.Threading; using System.Timers; using ln.application; -using ln.ethercat.controller; -using ln.ethercat.controller.drives; using ln.ethercat.service.api.v1; using ln.http; +using ln.http.api; using ln.http.router; using ln.logging; using ln.type; @@ -15,7 +13,6 @@ namespace ln.ethercat.service { public class EthercatService { - public ECMaster ECMaster { get; private set; } [StaticArgument(Option = 'i', LongOption = "interface")] @@ -92,6 +89,7 @@ namespace ln.ethercat.service try{ EthercatWebSocket.SendProcessData(ECMaster); ControllerWebSocket.SendUpdates(ECMaster.Controller); + JSONEventWebSocketResponse.SendUpdates(); } catch (Exception ex) { Logging.Log(ex); diff --git a/ln.ethercat.service/MainAxFeederControllerLogic.cs b/ln.ethercat.service/MainAxFeederControllerLogic.cs index 7393ebe..036629e 100644 --- a/ln.ethercat.service/MainAxFeederControllerLogic.cs +++ b/ln.ethercat.service/MainAxFeederControllerLogic.cs @@ -8,19 +8,15 @@ using ln.json.mapping; namespace ln.ethercat.service { - public class MainAxFeederControllerLogic + public class CLGalaTechBohrautomat : ControllerLogic { public MyParameters Parameters { get; set; } - ECMaster ECMaster; - SDOValue svRelais; SDOValue svEnable; - public MainAxFeederControllerLogic(ECMaster ecMaster) + public CLGalaTechBohrautomat() { - ECMaster = ecMaster; - Parameters = new MyParameters(); if (File.Exists("mafcl.json")) { @@ -41,22 +37,38 @@ namespace ln.ethercat.service } } - public void Initialize() + public override void Initialize(Controller controller) { if (!( - ECMaster.GetSDOValue(1, 0x2012, 31, out svRelais) && - ECMaster.GetSDOValue(1, 0x2012, 32, out svEnable) + controller.ECMaster.GetSDOValue(1, 0x2012, 31, out svRelais) && + controller.ECMaster.GetSDOValue(1, 0x2012, 32, out svEnable) )) throw new Exception("could not retrieve needed SDOValues"); } - public void ControllerLogic(Controller contreller) + public override void Cycle(Controller controller) { + switch (controller.ControllerState) + { + case ControllerStates.FAULT: + svEnable.SetValue((byte)0x00); + break; + case ControllerStates.NOTREADY: + svEnable.SetValue((byte)0x01); + break; + } + + if (controller.ControllerState == ControllerStates.OPERATIONAL) + { + svRelais.SetValue((byte)0x01); + } else { + svRelais.SetValue((byte)0x00); + } } public class MyParameters { - + } } diff --git a/ln.ethercat.service/Program.cs b/ln.ethercat.service/Program.cs index 2400125..815d285 100644 --- a/ln.ethercat.service/Program.cs +++ b/ln.ethercat.service/Program.cs @@ -34,7 +34,7 @@ namespace ln.ethercat.service ethercatService.Initialize(); ethercatService.ECMaster.OnStateChange += (ECMaster ECMaster, ECSlaveState newState) => { - if (newState == ECSlaveState.OPERATIONAL) + if (newState == ECSlaveState.SAFE_OP) { if (ECMaster.GetSDOValue(1, 0x2012, 32, out SDOValue svEnableDrives)) { @@ -48,21 +48,10 @@ namespace ln.ethercat.service } }; - ethercatService.ECMaster.Controller.OnStateChanged += (controller, state) => { - Logging.Log(LogLevel.DEBUG, "ControllerState=={0}", state); - if (state == ControllerStates.NOTREADY) - { - if (controller.ECMaster.GetSDOValue(1, 0x2012, 32, out SDOValue svEnableDrives)) - { - Logging.Log(LogLevel.DEBUG, "ControllerState=={0} powering up enable signals", state); - svEnableDrives.SetValue((byte)0x01); - } - } - }; + ethercatService.ECMaster.Controller.Add(new CLGalaTechBohrautomat()); ethercatService.Start(); - if (SerialRemotePort != null) { StupidSerialRemote stupidSerialRemote = new StupidSerialRemote(ethercatService.ECMaster.Controller, SerialRemotePort); diff --git a/ln.ethercat.service/api/v1/ControllerApiController.cs b/ln.ethercat.service/api/v1/ControllerApiController.cs index 1e157ea..cd60d4c 100644 --- a/ln.ethercat.service/api/v1/ControllerApiController.cs +++ b/ln.ethercat.service/api/v1/ControllerApiController.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Linq; +using System.Linq.Expressions; using System.Net.Mail; using System.Reflection; using System.Timers; @@ -28,7 +29,15 @@ namespace ln.ethercat.service.api.v1 [GET("/sockets/controller")] - public HttpResponse GetControllerSocket() => new ControllerWebSocket(Controller); + public HttpResponse GetControllerSocket(){ + JSONEventWebSocketResponse webSocket = new JSONEventWebSocketResponse(Controller); + for (int drive = 0; drive < Controller.ECMaster.DriveControllers.Length; drive++) + { + DriveController driveController = Controller.ECMaster.DriveControllers[drive]; + webSocket.AddTarget(String.Format("drives/{0}", drive), driveController, false); + } + return webSocket; + } // [GET("/sockets/controller/drives/:drive")] // public HttpResponse GetDriveControllerSocket(int drive) diff --git a/ln.ethercat.service/api/v1/ControllerWebSocket.cs b/ln.ethercat.service/api/v1/ControllerWebSocket.cs index ec82e7b..9a674fd 100644 --- a/ln.ethercat.service/api/v1/ControllerWebSocket.cs +++ b/ln.ethercat.service/api/v1/ControllerWebSocket.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; using ln.ethercat.controller; @@ -27,7 +26,6 @@ namespace ln.ethercat.service.api.v1 try { - JSONArray jsonDriveControllers = new JSONArray(); foreach (DriveController driveController in controller.ECMaster.DriveControllers) diff --git a/ln.ethercat.service/api/v1/EthercatWebSocket.cs b/ln.ethercat.service/api/v1/EthercatWebSocket.cs index 23218af..2b1a02d 100644 --- a/ln.ethercat.service/api/v1/EthercatWebSocket.cs +++ b/ln.ethercat.service/api/v1/EthercatWebSocket.cs @@ -2,10 +2,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Linq; -using System.Runtime.InteropServices; using ln.http.websocket; using ln.json; using ln.json.mapping; diff --git a/ln.ethercat.service/ln.ethercat.service.csproj b/ln.ethercat.service/ln.ethercat.service.csproj index e5cb91e..1a0686f 100644 --- a/ln.ethercat.service/ln.ethercat.service.csproj +++ b/ln.ethercat.service/ln.ethercat.service.csproj @@ -3,15 +3,16 @@ Exe netcoreapp3.1 - 0.1.0 + 0.1.1 - - - + + + + diff --git a/ln.ethercat.service/www/html/spa.html b/ln.ethercat.service/www/html/spa.html index 2d7debd..e8b3ac5 100644 --- a/ln.ethercat.service/www/html/spa.html +++ b/ln.ethercat.service/www/html/spa.html @@ -94,11 +94,15 @@ LN component: { template: src, data: function(){ - let d = { controller: {}, drive_controller: null }; + let d = { controller: false, drive_controller: null }; d.socket = $ECAPP.connectWebSocket("/api/v1/sockets/controller"); d.socket.onmessage = (evt)=>{ let json = JSON.parse(evt.data); - d.controller = json.value; + d.controller = json.value.Controller; + let drives = [] + for (let n=0;n .wrapper { main, .flex { display: flex; + flex-wrap: wrap; +} + +main { + flex-wrap: nowrap; } main > *, .flex > * { flex-basis: 100%; flex-grow: 1; margin: 0px 8px; + flex-shrink: 1; } main > aside, .flex > .aside{ flex-basis: 25%; flex-grow: 0; + flex-shrink: 0; min-width: 25%; } @@ -67,9 +74,25 @@ fieldset { display: flex; } +fieldset > * { + flex-grow: 1; + flex-shrink: 1; + flex-basis: 10%; +} + +fieldset > label, fieldset > .label { + flex-grow: 1; + flex-shrink: 1; + flex-basis: 5%; + text-align: right; + padding-right: 12px; + padding-left: 12px; +} + +/* fieldset > :first-child { flex-grow: 1; - flex-basis: 50%; + flex-basis: 25%; } fieldset > :nth-child(2) { flex-grow: 1; @@ -80,9 +103,11 @@ fieldset > :last-child { flex-basis: 25%; } fieldset.equal > * { - flex-basis: 50%; + flex-basis: 25%; margin: 4px; + flex-shrink: 1; } +*/ .flex { display: flex; @@ -117,6 +142,7 @@ fieldset.equal > * { margin: 2px 8px; border-radius: 8px;; background-color: #808080; + text-align: center; } .state.large { width: 240px; diff --git a/ln.ethercat.service/www/static/pages/controller.html b/ln.ethercat.service/www/static/pages/controller.html index d4ba47c..99a162c 100644 --- a/ln.ethercat.service/www/static/pages/controller.html +++ b/ln.ethercat.service/www/static/pages/controller.html @@ -1,10 +1,10 @@

Controller

-
+
- {{ controller.State }} + {{ controller.ControllerState }}
@@ -18,20 +18,20 @@
{{ drive.DriveState }} {{ drive.OEMState }}
-
+
{{ drive.DriveMode }}
-
+
diff --git a/ln.ethercat/controller/Controller.cs b/ln.ethercat/controller/Controller.cs index e8baf1e..eeee2cc 100644 --- a/ln.ethercat/controller/Controller.cs +++ b/ln.ethercat/controller/Controller.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Threading; using ln.ethercat.controller.drives; +using ln.http.api; using ln.logging; namespace ln.ethercat.controller @@ -28,26 +29,39 @@ namespace ln.ethercat.controller public ECMaster ECMaster { get; } + [ESProperty] public bool IgnoreRemoteInterface { get; set; } List controlLoops = new List(); public ControlLoop[] ControlLoops => controlLoops.ToArray(); + [ESProperty] public ControllerStates ControllerState { get; private set; } + [ESProperty] public double ControllerLoopInterval { get; set; } = 0.1; + [ESProperty] public double ControllerLoopFrequency { get => 1.0 / ControllerLoopInterval; set => ControllerLoopInterval = 1.0 / value; } + + [ESProperty] public long CycleCounter { get; private set; } Thread threadWatchdog; int wdogCounter; + + [ESProperty] public bool DisableRemoteWatchdog { get; set; } int remoteWatchdogCounter; public int WatchdogReset { get; set; } = 5; + [ESProperty] + public int DriveCount => ECMaster.DriveControllers.Length; + + HashSet controllerLogics = new HashSet(); + public Controller(ECMaster ecMaster) { ECMaster = ecMaster; @@ -56,6 +70,9 @@ namespace ln.ethercat.controller public void Add(ControlLoop controlLoop) => controlLoops.Add(controlLoop); public void Remove(ControlLoop controlLoop) => controlLoops.Remove(controlLoop); + public void Add(ControllerLogic controllerLogic) => controllerLogics.Add(controllerLogic); + public void Remove(ControllerLogic controllerLogic) => controllerLogics.Remove(controllerLogic); + public void Initialize() { CycleCounter = 0; @@ -68,6 +85,9 @@ namespace ln.ethercat.controller foreach (DriveController driveController in ECMaster.DriveControllers) driveController.Initialize(); + + foreach (ControllerLogic controllerLogic in controllerLogics) + controllerLogic.Initialize(this); } void UpdateControllerState() @@ -98,6 +118,12 @@ namespace ln.ethercat.controller if (driveState < nextState) nextState = driveState; } + + if ((ControllerState == ControllerStates.FAULT) && (nextState == ControllerStates.OPERATIONAL)) + { + DisableDrives(); + nextState = ControllerStates.FAULT; + } } ChangeState(nextState); } @@ -107,6 +133,9 @@ namespace ln.ethercat.controller if (newState == ControllerState) return; + if (ControllerState == ControllerStates.FAULT) + return; + OnStateChanging?.Invoke(this, newState); switch (newState) @@ -129,11 +158,13 @@ namespace ln.ethercat.controller OnStateChanged?.Invoke(this, newState); } + [ESMethod] public void DisableDrives() { ChangeState(ControllerStates.DISABLING); } + [ESMethod] public void EnableDrives() { if (ControllerState == ControllerStates.READY) @@ -144,8 +175,12 @@ namespace ln.ethercat.controller } } + [ESMethod] public void ClearFaults() { + if (ControllerState == ControllerStates.FAULT) + ControllerState = ControllerStates.NONE; + foreach (DriveController driveController in ECMaster.DriveControllers) { if (driveController.DriveState == DriveStates.ERROR) @@ -206,6 +241,9 @@ namespace ln.ethercat.controller foreach (ControlLoop controlLoop in controlLoops) controlLoop.Loop(); + foreach (ControllerLogic controllerLogic in controllerLogics) + controllerLogic.Cycle(this); + ControllerLogic?.Invoke(this); foreach (DriveController driveController in ECMaster.DriveControllers) diff --git a/ln.ethercat/controller/ControllerLogic.cs b/ln.ethercat/controller/ControllerLogic.cs new file mode 100644 index 0000000..22c2613 --- /dev/null +++ b/ln.ethercat/controller/ControllerLogic.cs @@ -0,0 +1,10 @@ +using System.Transactions; + +namespace ln.ethercat.controller +{ + public abstract class ControllerLogic + { + public abstract void Initialize(Controller controller); + public abstract void Cycle(Controller contreller); + } +} \ No newline at end of file diff --git a/ln.ethercat/controller/drives/CIA402Controller.cs b/ln.ethercat/controller/drives/CIA402Controller.cs index a635be8..c82e860 100644 --- a/ln.ethercat/controller/drives/CIA402Controller.cs +++ b/ln.ethercat/controller/drives/CIA402Controller.cs @@ -250,14 +250,14 @@ namespace ln.ethercat.controller.drives public override double ActualLoad => (double)(svActualCurrent?.GetValue() ?? 0) / 1000.0; public override double TargetPosition { - get => svTargetPosition.GetValue(); + get => svTargetPosition?.GetValue() ?? 0; set => svTargetPosition.SetValue((int)value); } public override double TargetSpeed { get { if (ModeOfOperation == CIA402ModesOfOperation.CYCLIC_SYNC_VELOCITY) - return (double)svTargetSpeed.GetValue() / (1000.0 * MotorMaxSpeed); + return (double)(svTargetSpeed?.GetValue() ?? 0) / (1000.0 * MotorMaxSpeed); return (double)(svVLTargetVelocity?.GetValue() ?? 0) / MotorMaxSpeed; } set { @@ -267,11 +267,11 @@ namespace ln.ethercat.controller.drives } } public override double TargetTorque { - get => (double)svTargetTorque.GetValue() / 1000.0; + get => (double)(svTargetTorque?.GetValue() ?? 0) / 1000.0; set => svTargetTorque.SetValue((short)(1000 * value)); } - public override int ErrorCode => svErrorCode.GetValue(); + public override int ErrorCode => svErrorCode?.GetValue() ?? 0; public override string ErrorText => ErrorCode.ToString(); diff --git a/ln.ethercat/controller/drives/DriveController.cs b/ln.ethercat/controller/drives/DriveController.cs index 427e8b8..2b41a41 100644 --- a/ln.ethercat/controller/drives/DriveController.cs +++ b/ln.ethercat/controller/drives/DriveController.cs @@ -1,8 +1,5 @@ - - using System; -using System.Net.Http.Headers; -using System.Runtime; +using ln.http.api; namespace ln.ethercat.controller.drives { @@ -26,8 +23,11 @@ namespace ln.ethercat.controller.drives public abstract class DriveController { protected ECMaster ECMaster { get; } + + [ESProperty] public UInt16 Slave { get; } + [ESProperty] public bool IgnoredByController { get; set; } @@ -44,33 +44,53 @@ namespace ln.ethercat.controller.drives /* called by controller after user logic */ public abstract void UpdateDrive(); + [ESProperty] public abstract DriveStates DriveState { get; } + [ESProperty] public abstract string OEMDriveState { get; } + [ESProperty] public abstract Int32 ErrorCode { get; } + [ESProperty] public abstract string ErrorText { get; } + [ESMethod] public abstract void ClearFault(); + [ESProperty] public abstract DriveMode DriveMode { get; set; } + [ESProperty] public abstract string OEMDriveMode { get; } + [ESMethod] public void PowerOn() => Power(true); + [ESMethod] public void PowerOff() => Power(false); + [ESMethod] public abstract void Power(bool poweron); + [ESMethod] public void EnableDrive() => Enable(true); + [ESMethod] public void DisableDrive() => Enable(false); + [ESMethod] public abstract void Enable(bool enabled); + [ESProperty] public abstract double ActualPosition { get; } + [ESProperty] public abstract double ActualSpeed { get; } + [ESProperty] public abstract double ActualTorque { get; } + [ESProperty] public abstract double TargetPosition { get; set; } + [ESProperty] public abstract double TargetSpeed { get; set; } + [ESProperty] public abstract double TargetTorque { get; set; } - + [ESProperty] public abstract double ActualLoad { get; } + [ESProperty] public virtual double TargetValue { get { switch (DriveMode) diff --git a/ln.ethercat/ln.ethercat.csproj b/ln.ethercat/ln.ethercat.csproj index 8fe3848..b971037 100644 --- a/ln.ethercat/ln.ethercat.csproj +++ b/ln.ethercat/ln.ethercat.csproj @@ -19,8 +19,10 @@ - + + +