Improvements to WebUI
ln.build - build0.waldrennach.l--n.de build job pending
Details
ln.build - build0.waldrennach.l--n.de build job pending
Details
parent
9c054f3865
commit
1283d1c570
|
@ -36,8 +36,6 @@ namespace ln.ethercat.service
|
|||
ethercatService.ECMaster.OnStateChange += (ECMaster ECMaster, ECSlaveState newState) => {
|
||||
if (newState == ECSlaveState.OPERATIONAL)
|
||||
{
|
||||
ECMaster.DriveControllers[1].IgnoredByController = true;
|
||||
|
||||
if (ECMaster.GetSDOValue(1, 0x2012, 32, out SDOValue svEnableDrives))
|
||||
{
|
||||
svEnableDrives.SetValue((byte)0x00);
|
||||
|
@ -52,7 +50,6 @@ 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))
|
||||
|
@ -60,9 +57,6 @@ namespace ln.ethercat.service
|
|||
Logging.Log(LogLevel.DEBUG, "ControllerState=={0} powering up enable signals", state);
|
||||
svEnableDrives.SetValue((byte)0x01);
|
||||
}
|
||||
} else if (state == ControllerStates.READY)
|
||||
{
|
||||
controller.ECMaster.DriveControllers[1].DriveMode = DriveMode.TORQUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using ln.ethercat.controller;
|
||||
using ln.ethercat.controller.drives;
|
||||
using ln.http.websocket;
|
||||
using ln.json;
|
||||
using ln.json.mapping;
|
||||
using ln.logging;
|
||||
using ln.type;
|
||||
|
||||
namespace ln.ethercat.service.api.v1
|
||||
{
|
||||
|
@ -48,6 +51,8 @@ namespace ln.ethercat.service.api.v1
|
|||
.Add("State", controller.ControllerState.ToString())
|
||||
.Add("Drives", jsonDriveControllers)
|
||||
.Add("CycleCounter", controller.CycleCounter)
|
||||
.Add("DisableRemoteWatchdog", controller.DisableRemoteWatchdog)
|
||||
.Add("IgnoreRemoteInterface", controller.IgnoreRemoteInterface)
|
||||
;
|
||||
|
||||
|
||||
|
@ -100,12 +105,40 @@ namespace ln.ethercat.service.api.v1
|
|||
|
||||
public override void Received(string textMessage)
|
||||
{
|
||||
object target;
|
||||
|
||||
base.Received(textMessage);
|
||||
|
||||
JSONValue jsonTextValue = JSONParser.Parse(textMessage);
|
||||
if (jsonTextValue is JSONObject jsonMessage)
|
||||
{
|
||||
string eventName = jsonMessage["event"].ToNative().ToString();
|
||||
JSONObject jsonValue = jsonMessage["value"] as JSONObject;
|
||||
|
||||
switch (eventName)
|
||||
{
|
||||
case "set":
|
||||
string propName = jsonValue["name"].ToNative().ToString();
|
||||
object propValue = jsonValue["value"].ToNative();
|
||||
target = Controller;
|
||||
if (jsonValue.ContainsKey("drive"))
|
||||
target = Controller.ECMaster.DriveControllers[(Int64)jsonValue["drive"].ToNative()];
|
||||
|
||||
PropertyInfo propertyInfo = target.GetType().GetProperty(propName);
|
||||
propertyInfo.SetValue(target, Cast.To(propValue, propertyInfo.PropertyType));
|
||||
break;
|
||||
case "action":
|
||||
string methodName = jsonValue["method"].ToNative().ToString();
|
||||
JSONMapper.DefaultMapper.Deserialize(jsonValue["arguments"], out object[] arguments);
|
||||
target = Controller;
|
||||
if (jsonValue.ContainsKey("drive"))
|
||||
target = Controller.ECMaster.DriveControllers[(Int64)jsonValue["drive"].ToNative()];
|
||||
|
||||
MethodInfo methodInfo = target.GetType().GetMethod(methodName);
|
||||
methodInfo.Invoke(target,new object[0]);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,12 +95,46 @@ LN
|
|||
template: src,
|
||||
data: function(){
|
||||
let d = { controller: {}, drive_controller: null };
|
||||
let socket = $ECAPP.connectWebSocket("/api/v1/sockets/controller");
|
||||
socket.onmessage = (evt)=>{
|
||||
d.socket = $ECAPP.connectWebSocket("/api/v1/sockets/controller");
|
||||
d.socket.onmessage = (evt)=>{
|
||||
let json = JSON.parse(evt.data);
|
||||
d.controller = json;
|
||||
d.controller = json.value;
|
||||
};
|
||||
return d;
|
||||
},
|
||||
methods: {
|
||||
drive_set: function(drive, propName, propValue){
|
||||
let jsonMessage = {
|
||||
event: "set",
|
||||
value: {
|
||||
drive: drive,
|
||||
name: propName,
|
||||
value: propValue
|
||||
}
|
||||
};
|
||||
this.socket.send(JSON.stringify(jsonMessage));
|
||||
},
|
||||
ctrl_set: function(propName, propValue){
|
||||
let jsonMessage = {
|
||||
event: "set",
|
||||
value: {
|
||||
name: propName,
|
||||
value: propValue
|
||||
}
|
||||
};
|
||||
this.socket.send(JSON.stringify(jsonMessage));
|
||||
},
|
||||
ctrl_action: function(methodName, arguments){
|
||||
arguments = arguments || [];
|
||||
let jsonMessage = {
|
||||
event: "action",
|
||||
value: {
|
||||
method: methodName,
|
||||
arguments: arguments
|
||||
}
|
||||
};
|
||||
this.socket.send(JSON.stringify(jsonMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
|
|
@ -22,6 +22,7 @@ main, .flex {
|
|||
}
|
||||
|
||||
main > *, .flex > * {
|
||||
flex-basis: 100%;
|
||||
flex-grow: 1;
|
||||
margin: 0px 8px;
|
||||
}
|
||||
|
@ -29,9 +30,17 @@ main > *, .flex > * {
|
|||
main > aside, .flex > .aside{
|
||||
flex-basis: 25%;
|
||||
flex-grow: 0;
|
||||
min-width: 25%;
|
||||
}
|
||||
|
||||
|
||||
.group {
|
||||
display: block;
|
||||
border: 1px solid #ccc;
|
||||
padding: 8px;
|
||||
}
|
||||
.group > fieldset {
|
||||
border: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 1px solid black;
|
||||
|
@ -43,20 +52,41 @@ button, span {
|
|||
font-style: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
button.selected {
|
||||
color: #10E010;
|
||||
}
|
||||
button.true {
|
||||
color: #10E010;
|
||||
}
|
||||
button.false {
|
||||
color: #B0B0B0;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
fieldset > label {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
fieldset > input, fieldset > .value {
|
||||
fieldset > :first-child {
|
||||
flex-grow: 1;
|
||||
flex-basis: 50%;
|
||||
}
|
||||
fieldset > :nth-child(2) {
|
||||
flex-grow: 1;
|
||||
flex-basis: 40%;
|
||||
}
|
||||
fieldset > :last-child {
|
||||
flex-grow: 1;
|
||||
flex-basis: 25%;
|
||||
}
|
||||
fieldset.equal > * {
|
||||
flex-basis: 50%;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.panel {
|
||||
padding: 6px;
|
||||
}
|
||||
|
@ -88,6 +118,24 @@ fieldset > input, fieldset > .value {
|
|||
border-radius: 8px;;
|
||||
background-color: #808080;
|
||||
}
|
||||
.state.large {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.state.READY {
|
||||
color: #108010;
|
||||
}
|
||||
.state.OPERATIONAL {
|
||||
color: #10E010;
|
||||
}
|
||||
.state.ERROR, .state.FAULT {
|
||||
color: white;
|
||||
background-color: #C04040;
|
||||
}
|
||||
.state.BOOT, .state.INIT {
|
||||
color: #000080;
|
||||
}
|
||||
|
||||
|
||||
.state.active {
|
||||
background-color: #10E010;
|
||||
|
@ -104,15 +152,10 @@ fieldset > input, fieldset > .value {
|
|||
.state.active.orange {
|
||||
background-color: #e0a810;
|
||||
}
|
||||
|
||||
|
||||
.OPERATIONAL {
|
||||
background-color: #10E010;
|
||||
}
|
||||
.SAFE_OP {
|
||||
.state.SAFE_OP {
|
||||
background-color: #e0a810;
|
||||
}
|
||||
.PRE_OP {
|
||||
.state.PRE_OP {
|
||||
background-color: #B0B0B0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +1,47 @@
|
|||
<div>
|
||||
<h1>Controller</h1>
|
||||
<div class="panel flex">
|
||||
<column>
|
||||
<fieldset>
|
||||
<label>Status</label>
|
||||
<span class="state" :class="controller.State">{{ controller.State }}</span>
|
||||
</fieldset>
|
||||
<fieldset class="equal">
|
||||
<button @click="ctrl_action('DisableDrives');">DISABLE</button>
|
||||
<button @click="ctrl_action('EnableDrives');">ENABLE</button>
|
||||
<button @click="ctrl_action('ClearFaults');">CLEAR FAULT</button>
|
||||
</fieldset>
|
||||
<fieldset class="equal">
|
||||
<button @click="ctrl_set('DisableRemoteWatchdog', !controller.DisableRemoteWatchdog);" :class="controller.DisableRemoteWatchdog.toString()">DisableRemoteWatchdog</button>
|
||||
<button @click="ctrl_set('IgnoreRemoteInterface', !controller.IgnoreRemoteInterface);" :class="controller.IgnoreRemoteInterface.toString()">IgnoreRemoteInterface</button>
|
||||
</fieldset>
|
||||
</column>
|
||||
<column>
|
||||
<div class="group"
|
||||
v-for="drive,key in controller.Drives"
|
||||
>
|
||||
<fieldset>
|
||||
<label>Drive {{ key }}</label>
|
||||
<span class="state" :class="drive.DriveState">{{ drive.DriveState }}</span>
|
||||
<span class="state large" :class="drive.OEMState">{{ drive.OEMState }}</span>
|
||||
</fieldset>
|
||||
<fieldset class="equal">
|
||||
<label>Drive Mode</label>
|
||||
<span class="value">{{ drive.DriveMode }}</span>
|
||||
<label>Velocity</label>
|
||||
<meter :value="Math.abs(drive.ActualSpeed)" min="0.0" max="1.5" low="0.8" high="1.0" optimum="0.7"></meter>
|
||||
</fieldset>
|
||||
<fieldset class="equal">
|
||||
<label>TargetValue</label>
|
||||
<input type="range" step="0.05" min="-1.0" max="1.0" v-model="drive.TargetValue" @input="drive_set(key, 'TargetValue', drive.TargetValue);">
|
||||
<label>Torque</label>
|
||||
<meter :value="Math.abs(drive.ActualTorque)" min="0.0" max="1.5" low="0.8" high="1.0" optimum="0.7"></meter>
|
||||
</fieldset>
|
||||
</div>
|
||||
</column>
|
||||
</div>
|
||||
<p>
|
||||
{{ controller }}
|
||||
</p>
|
||||
<div v-if="drive_controller">
|
||||
<h2>Drive Controller</h2>
|
||||
<button @click="drive_poweroff">Power Off</button>
|
||||
<button @click="drive_poweron" >Power On</button>
|
||||
<button @click="drive_disable" >Disable</button>
|
||||
<button @click="drive_enable">Enable</button>
|
||||
<button @click="drive_clearfault">Clear Fault</button>
|
||||
|
||||
<button @click="drive_drivemode('Position')">Mode: POS</button>
|
||||
<button @click="drive_drivemode('Speed')">Mode: SPEED</button>
|
||||
<button @click="drive_drivemode('Torque')">Mode: TORQUE</button>
|
||||
|
||||
<p>
|
||||
{{ drive_controller }}
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<fieldset>
|
||||
<label>Target Torque:</label>
|
||||
<input type="range" min="-1000" max="1000" v-model="targetTorque" id="targetTorque" @input="setProperty('TargetValue', targetTorque);">
|
||||
<input type="number" v-model="targetTorque" @change="setProperty('TargetValue', targetTorque);">
|
||||
<button @click="targetTorque = 0; setProperty('TargetValue', targetTorque);">ZERO</button>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -7,7 +7,6 @@ using ln.logging;
|
|||
|
||||
namespace ln.ethercat.controller
|
||||
{
|
||||
|
||||
public delegate void ControllerLogicDelegate(Controller controller);
|
||||
public delegate void ControllerStateChangeDelegate(Controller controller, ControllerStates newState);
|
||||
|
||||
|
@ -45,6 +44,8 @@ namespace ln.ethercat.controller
|
|||
|
||||
Thread threadWatchdog;
|
||||
int wdogCounter;
|
||||
public bool DisableRemoteWatchdog { get; set; }
|
||||
int remoteWatchdogCounter;
|
||||
public int WatchdogReset { get; set; } = 5;
|
||||
|
||||
public Controller(ECMaster ecMaster)
|
||||
|
@ -67,7 +68,6 @@ namespace ln.ethercat.controller
|
|||
|
||||
foreach (DriveController driveController in ECMaster.DriveControllers)
|
||||
driveController.Initialize();
|
||||
|
||||
}
|
||||
|
||||
void UpdateControllerState()
|
||||
|
@ -172,15 +172,17 @@ namespace ln.ethercat.controller
|
|||
}
|
||||
}
|
||||
|
||||
public void RemoteTriggerWatchdog() => remoteWatchdogCounter = 5;
|
||||
|
||||
public void RemoteUpdateTarget(int drive, double targetValue)
|
||||
{
|
||||
if (!IgnoreRemoteInterface)
|
||||
{
|
||||
targetValue = Math.Clamp(targetValue, 0, 1);
|
||||
targetValue = Math.Clamp(targetValue, -1, 1);
|
||||
|
||||
if (drive < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(targetValue));
|
||||
if (drive > ECMaster.DriveControllers.Length)
|
||||
if (drive >= ECMaster.DriveControllers.Length)
|
||||
{
|
||||
Logging.Log(LogLevel.WARNING, "Controller: RemoteUpdateTarget(): trying to update non-existent drive {0}", drive);
|
||||
return;
|
||||
|
@ -217,7 +219,19 @@ namespace ln.ethercat.controller
|
|||
try
|
||||
{
|
||||
Thread.Sleep(TimeSpan.FromSeconds(ControllerLoopInterval));
|
||||
if ((wdogCounter--) < 0)
|
||||
|
||||
if (wdogCounter > 0)
|
||||
{
|
||||
wdogCounter--;
|
||||
} else
|
||||
{
|
||||
ChangeState(ControllerStates.FAULT);
|
||||
}
|
||||
|
||||
if (remoteWatchdogCounter > 0)
|
||||
{
|
||||
remoteWatchdogCounter--;
|
||||
} else if (!DisableRemoteWatchdog)
|
||||
{
|
||||
ChangeState(ControllerStates.FAULT);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using ln.logging;
|
||||
|
||||
namespace ln.ethercat.controller.drives
|
||||
|
@ -42,6 +43,8 @@ namespace ln.ethercat.controller.drives
|
|||
SDOValue svModesOfOperation;
|
||||
SDOValue svModesOfOperationDisplay;
|
||||
SDOValue svActualCurrent;
|
||||
SDOValue svVLTargetVelocity;
|
||||
SDOValue svVLActualVelocity;
|
||||
|
||||
SDOValue svMaxSpeed;
|
||||
|
||||
|
@ -62,7 +65,9 @@ namespace ln.ethercat.controller.drives
|
|||
new PDOMappingRequest(slave, 0x6077, 0, false),
|
||||
new PDOMappingRequest(slave, 0x6060, 0, true),
|
||||
new PDOMappingRequest(slave, 0x6061, 0, false),
|
||||
new PDOMappingRequest(slave, 0x6078, 0, false)
|
||||
new PDOMappingRequest(slave, 0x6078, 0, false),
|
||||
new PDOMappingRequest(slave, 0x6042, 0, true),
|
||||
new PDOMappingRequest(slave, 0x6044, 0, false),
|
||||
};
|
||||
ecMaster.RequestPDOMapping(mappingRequests);
|
||||
}
|
||||
|
@ -82,20 +87,30 @@ namespace ln.ethercat.controller.drives
|
|||
ECMaster.GetSDOValue(Slave, 0x6060, 0, out svModesOfOperation) &&
|
||||
ECMaster.GetSDOValue(Slave, 0x6061, 0, out svModesOfOperationDisplay) &&
|
||||
ECMaster.GetSDOValue(Slave, 0x6080, 0, out svMaxSpeed) &&
|
||||
ECMaster.GetSDOValue(Slave, 0x6044, 0, out svVLActualVelocity) &&
|
||||
ECMaster.GetSDOValue(Slave, 0x6042, 0, out svVLTargetVelocity) &&
|
||||
ECMaster.GetSDOValue(Slave, 0x6078, 0, out svActualCurrent)
|
||||
))
|
||||
throw new ArgumentOutOfRangeException("CIA402Controller could not retrieve SDOvalues for CiA402 profile");
|
||||
|
||||
MotorMaxSpeed = svMaxSpeed.GetValue<UInt32>();
|
||||
}
|
||||
|
||||
public override void UpdateStates() {
|
||||
CIA402State = GetCIA402State();
|
||||
}
|
||||
public override void UpdateDrive() {
|
||||
|
||||
public override void UpdateDrive()
|
||||
{
|
||||
if (CIA402TargetState != CIA402States.UNDEFINED)
|
||||
{
|
||||
if (CIA402State != CIA402TargetState)
|
||||
{
|
||||
switch (CIA402State)
|
||||
{
|
||||
case CIA402States.FAULT:
|
||||
case CIA402States.FAULT_REACTION_ACTIVE:
|
||||
CIA402TargetState = CIA402States.UNDEFINED;
|
||||
break;
|
||||
case CIA402States.NOT_READY_TO_SWITCH_ON:
|
||||
svControlWord.SetValue((ushort)0x0000);
|
||||
ModeOfOperation = CIA402ModesOfOperation.CYCLIC_SYNC_TORQUE;
|
||||
|
@ -140,10 +155,13 @@ namespace ln.ethercat.controller.drives
|
|||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
CIA402TargetState = CIA402States.UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
if (DriveMode == DriveMode.UNDEFINED)
|
||||
DriveMode = DriveMode.TORQUE;
|
||||
DriveMode = DriveMode.SPEED;
|
||||
}
|
||||
|
||||
public override DriveStates DriveState
|
||||
|
@ -182,6 +200,7 @@ namespace ln.ethercat.controller.drives
|
|||
case CIA402ModesOfOperation.CYCLIC_SYNC_POSITION:
|
||||
return DriveMode.POSITION;
|
||||
case CIA402ModesOfOperation.CYCLIC_SYNC_VELOCITY:
|
||||
case CIA402ModesOfOperation.VL_VELOCITY_MODE:
|
||||
return DriveMode.SPEED;
|
||||
case CIA402ModesOfOperation.CYCLIC_SYNC_TORQUE:
|
||||
return DriveMode.TORQUE;
|
||||
|
@ -196,7 +215,7 @@ namespace ln.ethercat.controller.drives
|
|||
ModeOfOperation = CIA402ModesOfOperation.CYCLIC_SYNC_POSITION;
|
||||
break;
|
||||
case DriveMode.SPEED:
|
||||
ModeOfOperation = CIA402ModesOfOperation.CYCLIC_SYNC_VELOCITY;
|
||||
ModeOfOperation = CIA402ModesOfOperation.VL_VELOCITY_MODE;
|
||||
break;
|
||||
case DriveMode.TORQUE:
|
||||
ModeOfOperation = CIA402ModesOfOperation.CYCLIC_SYNC_TORQUE;
|
||||
|
@ -214,11 +233,19 @@ namespace ln.ethercat.controller.drives
|
|||
|
||||
public CIA402ModesOfOperation ModeOfOperation {
|
||||
get => (ECMaster.EthercatState==ECSlaveState.OPERATIONAL) ? (CIA402ModesOfOperation)(svModesOfOperationDisplay?.GetValue<sbyte>() ?? 0) : CIA402ModesOfOperation.NO_MODE_CHANGE;
|
||||
set => svModesOfOperation.SetValue((sbyte)value);
|
||||
set {
|
||||
svModesOfOperation.SetValue((sbyte)value);
|
||||
}
|
||||
}
|
||||
|
||||
public override double ActualPosition => (svActualPosition?.GetValue<int>() ?? 0) ;
|
||||
public override double ActualSpeed => (double)(svActualSpeed?.GetValue<int>() ?? 0) / (1000.0 * MotorMaxSpeed);
|
||||
public override double ActualSpeed {
|
||||
get {
|
||||
if (ModeOfOperation == CIA402ModesOfOperation.CYCLIC_SYNC_VELOCITY)
|
||||
return (double)(svActualSpeed?.GetValue<int>() ?? 0) / (1000.0 * MotorMaxSpeed);
|
||||
return (double)(svVLActualVelocity?.GetValue<short>() ?? 0) / MotorMaxSpeed;
|
||||
}
|
||||
}
|
||||
public override double ActualTorque => (double)(svActualTorque?.GetValue<short>() ?? 0) / 1000.0;
|
||||
public override double ActualLoad => (double)(svActualCurrent?.GetValue<short>() ?? 0) / 1000.0;
|
||||
|
||||
|
@ -228,8 +255,16 @@ namespace ln.ethercat.controller.drives
|
|||
}
|
||||
|
||||
public override double TargetSpeed {
|
||||
get => (double)svTargetSpeed.GetValue<int>() / (1000.0 * MotorMaxSpeed);
|
||||
set => svTargetSpeed.SetValue((int)(value * (1000.0 * MotorMaxSpeed)));
|
||||
get {
|
||||
if (ModeOfOperation == CIA402ModesOfOperation.CYCLIC_SYNC_VELOCITY)
|
||||
return (double)svTargetSpeed.GetValue<int>() / (1000.0 * MotorMaxSpeed);
|
||||
return (double)(svVLTargetVelocity?.GetValue<short>() ?? 0) / MotorMaxSpeed;
|
||||
}
|
||||
set {
|
||||
if (ModeOfOperation == CIA402ModesOfOperation.CYCLIC_SYNC_VELOCITY)
|
||||
svTargetSpeed.SetValue((int)(value * (1000.0 * MotorMaxSpeed)));
|
||||
svVLTargetVelocity.SetValue((short)(value * MotorMaxSpeed));
|
||||
}
|
||||
}
|
||||
public override double TargetTorque {
|
||||
get => (double)svTargetTorque.GetValue<short>() / 1000.0;
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ln.logging;
|
||||
using ln.type;
|
||||
using ln.ethercat.controller.drives;
|
||||
|
||||
namespace ln.ethercat.controller.remote
|
||||
{
|
||||
|
@ -33,15 +30,29 @@ namespace ln.ethercat.controller.remote
|
|||
LOAD100 = (1<<15),
|
||||
ALL = -1
|
||||
}
|
||||
|
||||
public enum FeederOperation
|
||||
{
|
||||
NONE,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
TORQUE
|
||||
}
|
||||
|
||||
public class StupidSerialRemote : ControllerRemote
|
||||
{
|
||||
public string SerialPortName { get; }
|
||||
|
||||
public FeederOperation FeederOperation { get; set; }
|
||||
|
||||
SerialPort serialPort;
|
||||
|
||||
bool stopReceiverThread;
|
||||
Thread threadReceiver;
|
||||
|
||||
public double MainTarget { get; set; }
|
||||
public double FeedTarget { get; set; }
|
||||
|
||||
public StupidSerialRemote(Controller controller)
|
||||
:this(controller, SerialPort.GetPortNames()[0]){}
|
||||
public StupidSerialRemote(Controller controller, string serialDevice)
|
||||
|
@ -77,12 +88,50 @@ namespace ln.ethercat.controller.remote
|
|||
if (Controller.ECMaster.DriveControllers[0].ActualLoad >= 1)
|
||||
leds |= StupidLEDs.LOAD100;
|
||||
SetLEDs(leds);
|
||||
|
||||
Controller.RemoteUpdateTarget(0, MainTarget);
|
||||
|
||||
switch (FeederOperation)
|
||||
{
|
||||
case FeederOperation.NONE:
|
||||
Controller.RemoteUpdateTarget(1, 0);
|
||||
break;
|
||||
case FeederOperation.LEFT:
|
||||
if (Controller.ECMaster.DriveControllers[1].DriveMode == DriveMode.SPEED)
|
||||
{
|
||||
Controller.RemoteUpdateTarget(1, FeedTarget);
|
||||
} else {
|
||||
Controller.ECMaster.DriveControllers[1].DriveMode = DriveMode.SPEED;
|
||||
Controller.RemoteUpdateTarget(1, 0);
|
||||
}
|
||||
break;
|
||||
case FeederOperation.RIGHT:
|
||||
if (Controller.ECMaster.DriveControllers[1].DriveMode == DriveMode.SPEED)
|
||||
{
|
||||
Controller.RemoteUpdateTarget(1, -FeedTarget);
|
||||
} else {
|
||||
Controller.ECMaster.DriveControllers[1].DriveMode = DriveMode.SPEED;
|
||||
Controller.RemoteUpdateTarget(1, 0);
|
||||
}
|
||||
break;
|
||||
case FeederOperation.TORQUE:
|
||||
if (Controller.ECMaster.DriveControllers[1].DriveMode == DriveMode.TORQUE)
|
||||
{
|
||||
Controller.RemoteUpdateTarget(1, FeedTarget);
|
||||
} else {
|
||||
Controller.ECMaster.DriveControllers[1].DriveMode = DriveMode.TORQUE;
|
||||
Controller.RemoteUpdateTarget(1, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case ControllerStates.ENABLING:
|
||||
break;
|
||||
case ControllerStates.DISABLING:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Receiver()
|
||||
|
@ -93,17 +142,24 @@ namespace ln.ethercat.controller.remote
|
|||
//Logging.Log(LogLevel.DEBUGDETAIL, rxLine);
|
||||
if (rxLine.Length >= 6)
|
||||
{
|
||||
ushort av = ushort.Parse(rxLine.Substring(2,4), System.Globalization.NumberStyles.HexNumber);
|
||||
ushort av = 0;
|
||||
ushort.TryParse(rxLine.Substring(2,4), System.Globalization.NumberStyles.HexNumber, null, out av);
|
||||
|
||||
switch (rxLine[0])
|
||||
{
|
||||
case 'A':
|
||||
int drive = rxLine[1] - '0';
|
||||
if (drive == 0) drive = 1;
|
||||
else if (drive == 1) drive = 2;
|
||||
else if (drive == 2) drive = 0;
|
||||
double rel = (double)av / 65535;
|
||||
if ((drive >= 0) && (drive < Controller.ECMaster.DriveControllers.Length))
|
||||
Controller.RemoteUpdateTarget(drive, rel);
|
||||
switch (drive)
|
||||
{
|
||||
case 0:
|
||||
FeedTarget = rel;
|
||||
break;
|
||||
case 2:
|
||||
MainTarget = rel;
|
||||
break;
|
||||
}
|
||||
Controller.RemoteTriggerWatchdog();
|
||||
break;
|
||||
case 'B':
|
||||
switch (rxLine[1])
|
||||
|
@ -115,19 +171,36 @@ namespace ln.ethercat.controller.remote
|
|||
if (Controller.ControllerState == ControllerStates.FAULT)
|
||||
Controller.RemoteAction(CRActions.CLEARFAULT);
|
||||
else if (Controller.ControllerState == ControllerStates.READY)
|
||||
{
|
||||
Controller.ECMaster.DriveControllers[0].DriveMode = DriveMode.SPEED;
|
||||
Controller.RemoteAction(CRActions.ENABLE);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
Controller.RemoteAction(CRActions.DISABLE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
switch (av)
|
||||
{
|
||||
case 3:
|
||||
// ToDo: Feeder left
|
||||
FeederOperation = FeederOperation.LEFT;
|
||||
break;
|
||||
case 4:
|
||||
// ToDo: Feeder right
|
||||
FeederOperation = FeederOperation.RIGHT;
|
||||
break;
|
||||
case 14:
|
||||
// ToDo: cycle drilling
|
||||
FeederOperation = FeederOperation.TORQUE;
|
||||
break; }
|
||||
break;
|
||||
case 'U':
|
||||
switch (av)
|
||||
{
|
||||
case 3:
|
||||
case 4:
|
||||
case 14:
|
||||
FeederOperation = FeederOperation.NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue