1482 lines
72 KiB
C#
1482 lines
72 KiB
C#
using Common;
|
||
using Common.Models;
|
||
using CommunityToolkit.Mvvm.Messaging;
|
||
using MegaRobo.C00225155.ControlDevices;
|
||
using MegaRobo.C00225155.ControlDevices.WeightDevice;
|
||
using MegaRobo.C00225155.Entities;
|
||
using MegaRobo.C00225155.Entities.Entity_DB;
|
||
using MegaRobo.Contract;
|
||
using MegaRobo.Contract.Abstractions;
|
||
using MegaRobo.ControlDevices;
|
||
using MegaRobo.Entities;
|
||
using MegaRobo.Logger;
|
||
using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices;
|
||
using Microsoft.VisualBasic;
|
||
using NetTaste;
|
||
using Newtonsoft.Json.Linq;
|
||
using Nito.AsyncEx;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.Configuration;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using System.Reflection;
|
||
using System.Runtime.InteropServices;
|
||
using System.Security.Policy;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Data;
|
||
using System.Windows.Input;
|
||
using System.Xml.Serialization;
|
||
|
||
namespace MegaRobo.C00225155.AppServer.ExecuteWorks
|
||
{
|
||
/// <summary>
|
||
/// 这里主要写配置工站上位机和PLC通讯的函数
|
||
/// </summary>
|
||
public partial class StationService_MaterialDosing : StationServiceBase
|
||
{
|
||
// /// <summary>
|
||
// /// 下工装---等待信号的锁
|
||
// /// </summary>
|
||
// private static readonly AsyncLock _lockWaitSignal_Dnload = new AsyncLock();
|
||
// /// <summary>
|
||
// /// 上工装---等待信号的锁
|
||
// /// </summary>
|
||
// private static readonly AsyncLock _lockWaitSignal_Upload = new AsyncLock();
|
||
// /// <summary>
|
||
// /// 四轴机械手---等待信号的锁
|
||
// /// </summary>
|
||
// private static readonly AsyncLock _lockWaitSignal_FourAxis = new AsyncLock();
|
||
|
||
// /// <summary>
|
||
// /// 粉末原液瓶---等待信号的锁
|
||
// /// </summary>
|
||
// private static readonly AsyncLock _lockWaitSignal_Powder = new AsyncLock();
|
||
|
||
// /// <summary>
|
||
// /// 六轴机械手下反应瓶工装线程的信号锁,防止多线程同时操作
|
||
// /// </summary>
|
||
// private static readonly AsyncLock _lockBoxDn_SixAxis = new AsyncLock();
|
||
// /// <summary>
|
||
// /// 六轴机械手上反应瓶缓存工装线程的信号锁,防止多线程同时操作
|
||
// /// </summary>
|
||
// private static readonly AsyncLock _lockBoxUp_SixAxis = new AsyncLock();
|
||
|
||
// /// <summary>
|
||
// /// 冷却平台 是否有瓶子 更新属性的锁
|
||
// /// </summary>
|
||
// private static readonly SemaphoreSlim _lockColdStateTrace = new SemaphoreSlim(1, 1);
|
||
// /// <summary>
|
||
// /// 磁力搅拌 是否有瓶子 更新属性的锁
|
||
// /// </summary>
|
||
// private static readonly SemaphoreSlim _lockMagneticStirStateTrace = new SemaphoreSlim(1, 1);
|
||
|
||
#region PLC点位写/读
|
||
/// <summary>
|
||
/// 下料
|
||
/// </summary>
|
||
/// <param name="address"></param>
|
||
/// <returns></returns>
|
||
public async Task<ushort> ReadScannedValueAsync_Dnload(ushort address)
|
||
{
|
||
await Task.Delay(0);
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
return this.ModbusClient.Command.ReadValue<ushort>(address);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站读取PLC信号异常",
|
||
Content = $"ReadScannedValueAsync_Dnload读取 {address} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"ReadScannedValueAsync_Dnload读取 {address} 时发生错误: {ex.Message}");
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 上料
|
||
/// </summary>
|
||
/// <param name="address"></param>
|
||
/// <returns></returns>
|
||
public async Task<ushort> ReadScannedValueAsync_Upload(ushort address)
|
||
{
|
||
await Task.Delay(0);
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
return this.ModbusClient.Command.ReadValue<ushort>(address);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站读取PLC信号异常",
|
||
Content = $"ReadScannedValueAsync_Upload读取 {address} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"ReadScannedValueAsync_Upload读取 {address} 时发生错误: {ex.Message}");
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
public async Task<ushort> ReadScannedValueAsync_FourAxis(ushort address)
|
||
{
|
||
await Task.Delay(0);
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
return this.ModbusClient.Command.ReadValue<ushort>(address);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站读取PLC信号异常",
|
||
Content = $"ReadSixAxis读取 {address} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"ReadScannedValueAsync_SixAxis读取 {address} 时发生错误: {ex.Message}");
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
public async Task<ushort> ReadScannedValueAsync_XZ(ushort address)
|
||
{
|
||
await Task.Delay(0);
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
return this.ModbusClient.Command.ReadValue<ushort>(address);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站读取PLC信号异常",
|
||
Content = $"ReadPowder读取 {address} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"ReadScannedValueAsync_Powder读取 {address} 时发生错误: {ex.Message}");
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
public async Task WriteCommandAsync_Dnload(ushort address, ushort value)
|
||
{
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
//await Task.Delay(30);
|
||
while (await ReadScannedValueAsync_Dnload(address) != value)
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
await Task.Delay(30);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站写入PLC信号异常",
|
||
Content = $"WriteDnload写入 {address}值{value} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WriteCommandAsync_Dnload写入 {address}值{value} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
|
||
public async Task WriteCommandAsync_Upload(ushort address, ushort value)
|
||
{
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
//await Task.Delay(30);
|
||
while (await ReadScannedValueAsync_Upload(address) != value)
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
await Task.Delay(30);
|
||
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站写入PLC信号异常",
|
||
Content = $"WriteUpload写入 {address}值{value} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WriteCommandAsync_Upload写入 {address}值{value} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
public async Task WriteCommandAsync_FourAxis(ushort address, ushort value)
|
||
{
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
//await Task.Delay(30);
|
||
while (await ReadScannedValueAsync_FourAxis(address) != value)
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
await Task.Delay(30);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站写入PLC信号异常",
|
||
Content = $"WriteFourAxis写入 {address}值{value} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WriteCommandAsync_FourAxis写入 {address}值{value} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
|
||
public async Task WriteCommandAsync_XZ(ushort address, ushort value)
|
||
{
|
||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
||
try
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
//await Task.Delay(30);
|
||
while (await ReadScannedValueAsync_XZ(address) != value)
|
||
{
|
||
this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
||
await Task.Delay(30);
|
||
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站写入PLC信号异常",
|
||
Content = $"WritePowder写入 {address}值{value} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WriteCommandAsync_Powder写入 {address}值{value} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
|
||
public async Task WaitForActionFinishAsync_Dnload(ushort point, ushort waitValue, CancellationToken token)
|
||
{
|
||
//using (await _lockWaitSignal_Dnload.LockAsync(token))
|
||
{
|
||
try
|
||
{
|
||
|
||
ushort result = 0;
|
||
do
|
||
{
|
||
token.ThrowIfCancellationRequested();
|
||
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
|
||
result = await ReadScannedValueAsync_Dnload(point);
|
||
await Task.Delay(100, token);
|
||
} while (result != waitValue && !token.IsCancellationRequested);
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
return;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站等待PLC信号异常",
|
||
Content = $"WaitForDnload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WaitForActionFinishAsync_Dnload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task WaitForActionFinishAsync_Upload(ushort point, ushort waitValue, CancellationToken token)
|
||
{
|
||
//using (await _lockWaitSignal_Upload.LockAsync(token))
|
||
{
|
||
try
|
||
{
|
||
ushort result = 0;
|
||
do
|
||
{
|
||
token.ThrowIfCancellationRequested();
|
||
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
|
||
result = await ReadScannedValueAsync_Upload(point);
|
||
await Task.Delay(100, token);
|
||
} while (result != waitValue && !token.IsCancellationRequested);
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
return;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站等待PLC信号异常",
|
||
Content = $"WaitForUpload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WaitForActionFinishAsync_Upload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task WaitForActionFinishAsync_FourAxis(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
||
{
|
||
//using (await _lockWaitSignal_FourAxis.LockAsync(cancellationToken))
|
||
{
|
||
try
|
||
{
|
||
ushort result = 0;
|
||
do
|
||
{
|
||
cancellationToken.ThrowIfCancellationRequested();
|
||
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
|
||
result = await ReadScannedValueAsync_FourAxis(point);
|
||
await Task.Delay(100, cancellationToken);
|
||
} while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
return;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站等待PLC信号异常",
|
||
Content = $"WaitForFourAxis等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WaitForActionFinishAsync_FourAxis等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task WaitForActionFinishAsync_XZ(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
||
{
|
||
//using (await _lockWaitSignal_Powder.LockAsync(cancellationToken))
|
||
{
|
||
try
|
||
{
|
||
ushort result = 0;
|
||
do
|
||
{
|
||
cancellationToken.ThrowIfCancellationRequested();
|
||
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
|
||
result = await ReadScannedValueAsync_XZ(point);
|
||
await Task.Delay(100, cancellationToken);
|
||
} while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
return;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"投料站等待PLC信号异常",
|
||
Content = $"WaitForPowder等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
this.Logger.LogError($"WaitForActionFinishAsync_Powder等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 传送平台
|
||
|
||
/// <summary>
|
||
/// 传送平台到过渡舱外准备上载具
|
||
/// </summary>
|
||
/// <param name="reactBottleModel"></param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task TransferUploadBox(CancellationToken token)
|
||
{
|
||
if (token.IsCancellationRequested) return;
|
||
//传送平台到过渡舱外
|
||
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 1);
|
||
|
||
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token);
|
||
//清除信号
|
||
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0);
|
||
//await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 0, token);
|
||
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); //等待PLC 准备就绪 等待空闲中
|
||
}
|
||
|
||
/// <summary>
|
||
/// 传送平台到手套箱内部
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task TransferToDeviceInner(CancellationToken token)
|
||
{
|
||
if (token.IsCancellationRequested) return;
|
||
//传送平台到手套箱内部
|
||
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 3);
|
||
|
||
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token);
|
||
//清除信号
|
||
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); //等待PLC 准备就绪 等待空闲中
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 四轴机械手
|
||
/// <summary>
|
||
/// 四轴机械手取托盘
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="boxType">托盘类型</param>
|
||
/// <param name="pos">目标托盘位置号</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisTakeBox(ushort aimarea, BoxTypeEnum boxType, ushort pos, CancellationToken token)
|
||
{
|
||
///// 目标区域
|
||
///// 1:手套箱传送平台; 2:Tip托盘存放平台;12:托盘存放平台;
|
||
///// </summary>
|
||
//public readonly static ushort W_Robot_AimArea = 2202;
|
||
///// <summary>
|
||
///// 目标托盘位置号
|
||
///// </summary>
|
||
//public readonly static ushort W_Robot_AimAreaBoxPosid = 2203;
|
||
///// <summary>
|
||
///// 托盘类型:1:40mL瓶; 2:12mL瓶; 3:5mL瓶; 4:TIP头;
|
||
///// </summary>
|
||
//public readonly static ushort W_Robot_BoxType = 2204;
|
||
|
||
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
ushort fixtureType = 0;
|
||
switch (boxType)
|
||
{
|
||
case BoxTypeEnum._40mL原液工装:
|
||
fixtureType = 1;
|
||
break;
|
||
case BoxTypeEnum._12mL样品工装:
|
||
fixtureType = 2;
|
||
break;
|
||
case BoxTypeEnum._5mL样品工装:
|
||
fixtureType = 3;
|
||
break;
|
||
case BoxTypeEnum._50uLTip头工装:
|
||
fixtureType = 4;
|
||
break;
|
||
case BoxTypeEnum._300uLTip头工装:
|
||
fixtureType = 4;
|
||
break;
|
||
case BoxTypeEnum._1000uLTip头工装:
|
||
fixtureType = 4;
|
||
break;
|
||
}
|
||
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, pos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, fixtureType);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 11);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手放托盘
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="boxType">托盘类型</param>
|
||
/// <param name="pos">目标托盘位置号</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisPutBox(ushort aimarea, BoxTypeEnum boxType, ushort pos, CancellationToken token)
|
||
{
|
||
///// 目标区域
|
||
///// 1:手套箱传送平台; 2:Tip托盘存放平台;12:托盘存放平台;
|
||
///// </summary>
|
||
//public readonly static ushort W_Robot_AimArea = 2202;
|
||
///// <summary>
|
||
///// 目标托盘位置号
|
||
///// </summary>
|
||
//public readonly static ushort W_Robot_AimAreaBoxPosid = 2203;
|
||
///// <summary>
|
||
///// 托盘类型:1:40mL瓶; 2:12mL瓶; 3:5mL瓶; 4:TIP头;
|
||
///// </summary>
|
||
//public readonly static ushort W_Robot_BoxType = 2204;
|
||
|
||
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
ushort fixtureType = 0;
|
||
switch (boxType)
|
||
{
|
||
case BoxTypeEnum._40mL原液工装:
|
||
fixtureType = 1;
|
||
break;
|
||
case BoxTypeEnum._12mL样品工装:
|
||
fixtureType = 2;
|
||
break;
|
||
case BoxTypeEnum._5mL样品工装:
|
||
fixtureType = 3;
|
||
break;
|
||
case BoxTypeEnum._50uLTip头工装:
|
||
fixtureType = 4;
|
||
break;
|
||
case BoxTypeEnum._300uLTip头工装:
|
||
fixtureType = 4;
|
||
break;
|
||
case BoxTypeEnum._1000uLTip头工装:
|
||
fixtureType = 4;
|
||
break;
|
||
}
|
||
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, pos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, fixtureType);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 12);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手取粉末加样头
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="aimarea_box">目标托盘号</param>
|
||
/// <param name="bottlepos">目标位置号</param>
|
||
/// <param name="powderbottletype">粉末类型</param>
|
||
/// <param name="token"></param>
|
||
/// <param name="point">plc点位,起始或终点是传递仓到缓存位的话,开始取最终放需要写1</param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisTakePowderHeader(int aimarea, int aimarea_box, int bottlepos, PowderBottleTypeEnum powderbottletype, CancellationToken token, ushort point = 0)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, powderbottletype == PowderBottleTypeEnum._16mL ? (ushort)1 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, point);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 1);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手放粉末加样头
|
||
/// </summary>
|
||
/// <param name="aimarea"></param>
|
||
/// <param name="aimarea_box"></param>
|
||
/// <param name="bottlepos"></param>
|
||
/// <param name="powderbottletype"></param>
|
||
/// <param name="token"></param>
|
||
/// <param name="point">plc点位,起始或终点是传递仓到缓存位的话,开始取最终放需要写1</param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisPutPowderHeader(int aimarea, int aimarea_box, int bottlepos, PowderBottleTypeEnum powderbottletype, CancellationToken token, ushort point = 0)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, powderbottletype == PowderBottleTypeEnum._16mL ? (ushort)1 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, point);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 2);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴运行到扫码位置
|
||
/// </summary>
|
||
/// <param name="liquidBottle">bottle : 1:40 2:12 3:5</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisGoToScannPos_liquid(CancellationToken token, int liquidBottle, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)liquidBottle);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 23); //goto scan pos
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveScanPos, 1, token);
|
||
|
||
string sn = await scannerService.ReadAsnyc(TimeSpan.FromSeconds(5));
|
||
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
sourceLiquidBottle.SNCode = sn;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
sampleBottle.SNCode = sn;
|
||
}
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_ScanResult, 1);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveScanPos, 0, token);
|
||
|
||
//清除信号
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_ScanResult, 0);
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴运行到粉末瓶扫码位置
|
||
/// </summary>
|
||
/// <param name="ispowder">是否是粉末瓶子</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisGoToScannPos_powder(CancellationToken token, SourcePowderBottleModel powderbottle)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 3);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveSideScanPos, 1, token);
|
||
|
||
//触发扫码
|
||
string snCode = await scannerService_Powder.ReadAsnyc(TimeSpan.FromSeconds(5));
|
||
powderbottle.SNCode = snCode;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_SideScanResult, 1); //回复扫码完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveSideScanPos, 0, token);
|
||
//清除信号
|
||
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_SideScanResult, 0);
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
|
||
private async Task<double> FourAxisPutPowderHeaderToPreWeight(CancellationToken token)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return 16;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 4);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 2);
|
||
|
||
//等待PLC回复到预称重位
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArrivePreWeightPos, 1, token);
|
||
|
||
//这边需要称重并返回PLC完成
|
||
double powderWeight = TestMode ? 16 : (await preWeight.ReadWeightValue());
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_PreWeightFinish, 1);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
return powderWeight;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手拿液体瓶子
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="aimarea_box">目标托盘位置号</param>
|
||
/// <param name="bottlepos">目标孔编号</param>
|
||
/// <param name="powderbottletype">瓶类型</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisTakeLiquidBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SourceLiquidBottleModel sourceLiquidBottle)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 1);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sourceLiquidBottle.LiquidBottleLidState == SourceBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 21);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手放液体瓶子
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="aimarea_box">目标托盘位置号</param>
|
||
/// <param name="bottlepos">目标孔编号</param>
|
||
/// <param name="powderbottletype">瓶类型</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisPutLiquidBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SourceLiquidBottleModel sourceLiquidBottle)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 1);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sourceLiquidBottle.LiquidBottleLidState == SourceBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 22);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手取样品瓶子
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="aimarea_box">目标托盘位置号</param>
|
||
/// <param name="bottlepos">目标孔编号</param>
|
||
/// <param name="powderbottletype">瓶类型</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisTakeSampleBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SampleBottleModel sampleBottle)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, sampleBottle.SampleBottleType == SampleBottleTypeEnum._5mL ? (ushort)3 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sampleBottle.SampleBottleLidState == SampleBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 21);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四轴机械手放样品瓶子
|
||
/// </summary>
|
||
/// <param name="aimarea">目标区域编号</param>
|
||
/// <param name="aimarea_box">目标托盘位置号</param>
|
||
/// <param name="bottlepos">目标孔编号</param>
|
||
/// <param name="powderbottletype">瓶类型</param>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
private async Task FourAxisPutSampleBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SampleBottleModel sampleBottle)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, sampleBottle.SampleBottleType == SampleBottleTypeEnum._5mL ? (ushort)3 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sampleBottle.SampleBottleLidState == SampleBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 22);
|
||
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
|
||
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
|
||
}
|
||
#endregion
|
||
|
||
#region XZ模组
|
||
/// <summary>
|
||
/// 假盖子开关盖
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="isOpen"></param>
|
||
/// <param name="sourceLiquidBottle"></param>
|
||
/// <param name="sampleBottle"></param>
|
||
/// <returns></returns>
|
||
private async Task OpenCloseBottleFakeCap(CancellationToken token,bool isOpen, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
int bottletype = 0;
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
bottletype = 1;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
|
||
{
|
||
bottletype = 2;
|
||
}
|
||
else
|
||
{
|
||
bottletype = 3;
|
||
}
|
||
}
|
||
ushort taskNo = isOpen ? (ushort)1 : (ushort)2;
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)2);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, taskNo);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
sourceLiquidBottle.LiquidBottleLidState = isOpen ? SourceBottleLidStateEnum.Open : SourceBottleLidStateEnum.Close;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
sampleBottle.SampleBottleLidState = isOpen ? SampleBottleLidStateEnum.Open : SampleBottleLidStateEnum.Close;
|
||
}
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// XZ模组开盖
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="sourceLiquidBottle"></param>
|
||
/// <param name="sampleBottle"></param>
|
||
/// <returns></returns>
|
||
private async Task OpenBottleLid(CancellationToken token, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
int bottletype = 0;
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
bottletype = 1;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
|
||
{
|
||
bottletype = 2;
|
||
}
|
||
else
|
||
{
|
||
bottletype = 3;
|
||
}
|
||
}
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)1);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 1);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
sourceLiquidBottle.LiquidBottleLidState = SourceBottleLidStateEnum.Open;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
sampleBottle.SampleBottleLidState = SampleBottleLidStateEnum.Open;
|
||
}
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// XZ模组关盖
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="sourceLiquidBottle"></param>
|
||
/// <param name="sampleBottle"></param>
|
||
/// <returns></returns>
|
||
private async Task CloseBottleLid(CancellationToken token, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
int bottletype = 0;
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
bottletype = 1;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
|
||
{
|
||
bottletype = 2;
|
||
}
|
||
else
|
||
{
|
||
bottletype = 3;
|
||
}
|
||
}
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)1);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 2);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
if (sourceLiquidBottle != null)
|
||
{
|
||
sourceLiquidBottle.LiquidBottleLidState = SourceBottleLidStateEnum.Close;
|
||
}
|
||
if (sampleBottle != null)
|
||
{
|
||
sampleBottle.SampleBottleLidState = SampleBottleLidStateEnum.Close;
|
||
}
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// XZ摇匀
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="sampleBottle"></param>
|
||
/// <returns></returns>
|
||
private async Task ShakeSampleBottle(CancellationToken token, SampleBottleModel sampleBottle)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
int bottletype = 0;
|
||
|
||
if (sampleBottle != null)
|
||
{
|
||
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
|
||
{
|
||
bottletype = 2;
|
||
}
|
||
else
|
||
{
|
||
bottletype = 3;
|
||
}
|
||
}
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)10);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 3);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
|
||
//public async Task TestSuckVolume(CancellationToken token, double targetVolume,bool isFirst)
|
||
//{
|
||
// SourceLiquidBottleModel sourceLiquidBottleModel = new SourceLiquidBottleModel()
|
||
// {
|
||
// LiquidBottleLidState = SourceBottleLidStateEnum.Close
|
||
// };
|
||
|
||
// if (isFirst)
|
||
// {
|
||
// await FourAxisTakeLiquidBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, 1, 1, sourceLiquidBottleModel);
|
||
// await FourAxisPutLiquidBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sourceLiquidBottleModel);
|
||
// await OpenBottleLid(_cts.Token, sourceLiquidBottleModel, null);
|
||
// }
|
||
// else
|
||
// {
|
||
// await CloseBottleLid(_cts.Token, sourceLiquidBottleModel, null);
|
||
// await FourAxisTakeLiquidBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sourceLiquidBottleModel);
|
||
// await FourAxisPutLiquidBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, 1, 1, sourceLiquidBottleModel);
|
||
// }
|
||
// List<(int tipVolume, List<double> countlists)> selectedTips = new List<(int tipVolume, List<double> countlists)>();
|
||
// (int tipVolume, List<double> countlists) selectedTip = (50,new List<double>() { 30});
|
||
// selectedTips.Add(selectedTip);
|
||
// for (int i = 0; i < selectedTips.Count; i++)
|
||
// {
|
||
// TipTypeEnum tipType = TipTypeEnum._1000UL;
|
||
// DeviceNames deviceName = DeviceNames.Pipette_Dose_1ml_1;
|
||
// if (selectedTips[i].tipVolume == 1000)
|
||
// {
|
||
// tipType = TipTypeEnum._1000UL; deviceName = DeviceNames.Pipette_Dose_1ml_1;
|
||
// }
|
||
// else if (selectedTips[i].tipVolume == 300)
|
||
// {
|
||
// tipType = TipTypeEnum._300UL; deviceName = DeviceNames.Pipette_Dose_1ml_2;
|
||
// }
|
||
// else if (selectedTips[i].tipVolume == 50)
|
||
// {
|
||
// tipType = TipTypeEnum._50UL; deviceName = DeviceNames.Pipette_Dose_1ml_3;
|
||
// }
|
||
// this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Ongoing) { Tag = "使用中" });
|
||
// while (true)
|
||
// {
|
||
// List<TipBoxModel> targetTipBoxes = workService.ProjectPro.TipHeadArea.Where(tipBox => (tipBox.TipType == tipType) && tipBox.TipItems != null && tipBox.TipItems.Any(item => item.IsAvailable)).ToList();
|
||
// //告诉PLC到取Tip头位置
|
||
// if (targetTipBoxes == null)
|
||
// {
|
||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
// {
|
||
// Header = $"取Tip失败",
|
||
// Content = $"没有tip了!!!",
|
||
// OkButtonContent = "继续",
|
||
// CancelButtonContent = "取消",
|
||
// });
|
||
// continue;
|
||
// }
|
||
// if (isFirst)
|
||
// {
|
||
// await PipetteTakeTip(token, targetTipBoxes.FirstOrDefault(), deviceName);
|
||
// //取Tip
|
||
// var restip = await GunPickUpTip_M1(deviceName, pipetteService_1ml, tipType);
|
||
// if (restip)
|
||
// {
|
||
// break;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// await PipetteDiscardTip(token, deviceName);
|
||
// await GunDiscardTip_M1(deviceName, pipetteService_1ml);
|
||
// return;
|
||
// }
|
||
// }
|
||
// for (int j = 0; j < selectedTips[i].countlists.Count; j++)//用这种枪头要吸液排液多少次
|
||
// {
|
||
// //告诉PLC到吸液位置
|
||
// await PipetteAbsorb(token, deviceName);
|
||
// }
|
||
// //告诉PLC到丢弃Tip头位置
|
||
// //await PipetteDiscardTip(token, deviceName);
|
||
// //await GunDiscardTip_M1(deviceName, pipetteService_1ml);
|
||
// //this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Done));
|
||
// }
|
||
//}
|
||
|
||
private async Task XZ_TakeTip_Absorb_Dispense_DiscardTip(CancellationToken token, string sourceliquidname, double targetVolume, SourceLiquidBottleModel sourceLiquidBottleModel, SampleBottleModel sampleBottleModel)
|
||
{
|
||
if (TestMode) return;
|
||
List<(int tipVolume, List<double> countlists)> selectedTips = new List<(int tipVolume, List<double> countlists)>();
|
||
selectedTips = SelectTipsEx(targetVolume);
|
||
|
||
for (int i = 0; i < selectedTips.Count; i++)
|
||
{
|
||
TipTypeEnum tipType = TipTypeEnum._1000UL;
|
||
DeviceNames deviceName = DeviceNames.Pipette_Dose_1ml_1;
|
||
if (selectedTips[i].tipVolume == 1000)
|
||
{
|
||
tipType = TipTypeEnum._1000UL; deviceName = DeviceNames.Pipette_Dose_1ml_1;
|
||
}
|
||
else if (selectedTips[i].tipVolume == 300)
|
||
{
|
||
tipType = TipTypeEnum._300UL; deviceName = DeviceNames.Pipette_Dose_1ml_2;
|
||
}
|
||
else if (selectedTips[i].tipVolume == 50)
|
||
{
|
||
tipType = TipTypeEnum._50UL; deviceName = DeviceNames.Pipette_Dose_1ml_3;
|
||
}
|
||
this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Ongoing) { Tag = "使用中" });
|
||
while (true)
|
||
{
|
||
List<TipBoxModel> targetTipBoxes = workService.ProjectPro.TipHeadArea.Where(tipBox => (tipBox.TipType == tipType) && tipBox.TipItems != null && tipBox.TipItems.Any(item => item.IsAvailable)).ToList();
|
||
//告诉PLC到取Tip头位置
|
||
if (targetTipBoxes == null)
|
||
{
|
||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
||
{
|
||
Header = $"取Tip失败",
|
||
Content = $"没有tip了!!!",
|
||
OkButtonContent = "继续",
|
||
CancelButtonContent = "取消",
|
||
});
|
||
continue;
|
||
}
|
||
await PipetteTakeTip(token, targetTipBoxes.FirstOrDefault(), deviceName);
|
||
//取Tip
|
||
var restip = await GunPickUpTip_M1(deviceName, pipetteService_1ml, tipType);
|
||
if (restip)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
for (int j = 0; j < selectedTips[i].countlists.Count; j++)//用这种枪头要吸液排液多少次
|
||
{
|
||
//告诉PLC到吸液位置
|
||
await PipetteAbsorb(token, deviceName);
|
||
int bottletype = workService.ProjectPro.SampleBottleType == SampleBottleTypeEnum._12mL ? 1 : 2;
|
||
await GunAbsorb_M1(deviceName, pipetteService_1ml, sourceliquidname, (int)tipType, selectedTips[i].countlists[j] * 10,sourceLiquidBottleModel);
|
||
//告诉PLC到排液位置
|
||
await PipetteDispense(token, deviceName);
|
||
await GunDispensing_M1(deviceName, pipetteService_1ml, sourceliquidname, (int)tipType, (uint)(selectedTips[i].countlists[j] * 10), sampleBottleModel);
|
||
}
|
||
//告诉PLC到丢弃Tip头位置
|
||
await PipetteDiscardTip(token,deviceName);
|
||
await GunDiscardTip_M1(deviceName, pipetteService_1ml);
|
||
this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Done));
|
||
}
|
||
}
|
||
|
||
public async Task UpdateTipBox(TipBoxModel tipBoxModel)
|
||
{
|
||
var tipInStation = await dataAccessService.LoadEntityAsync<TipBoxModel>(t => t.BoxId_inDosingStation == tipBoxModel.BoxId_inDosingStation);
|
||
if (tipInStation == null)
|
||
{
|
||
var tipaddres = await dataAccessService.AddEntityAsync(tipBoxModel);
|
||
}
|
||
else
|
||
{
|
||
await dataAccessService.UpdateEntityAsync(tipBoxModel);
|
||
}
|
||
}
|
||
|
||
public List<(int tipVolume, List<double> absorbVolumnList)> SelectTipsEx(double targetVolumn)
|
||
{
|
||
List<(int tipVolume, List<double> absorbVolumnList)> selectedTips = new List<(int tipVolume, List<double> absorbVolumnList)>();
|
||
bool has50Tip = workService.ProjectPro.TipHeadArea.Any(t => t.HaveBox && t.TipType == TipTypeEnum._50UL && t.TipItems.Any(ti => ti.IsAvailable));
|
||
bool has300Tip = workService.ProjectPro.TipHeadArea.Any(t => t.HaveBox && t.TipType == TipTypeEnum._300UL && t.TipItems.Any(ti => ti.IsAvailable));
|
||
bool has1000Tip = workService.ProjectPro.TipHeadArea.Any(t => t.HaveBox && t.TipType == TipTypeEnum._1000UL && t.TipItems.Any(ti => ti.IsAvailable));
|
||
if (!has50Tip && !has300Tip && !has1000Tip) return selectedTips;
|
||
TipTypeEnum tipType = TipTypeEnum._1000UL;
|
||
if (targetVolumn <= 50)
|
||
{
|
||
tipType = has50Tip ? TipTypeEnum._50UL : (has300Tip ? TipTypeEnum._300UL : TipTypeEnum._1000UL); //优先50 30 1000
|
||
}
|
||
else if (targetVolumn <= 300)
|
||
{
|
||
tipType = has300Tip ? TipTypeEnum._300UL : (has1000Tip ? TipTypeEnum._1000UL : TipTypeEnum._50UL); //优先30 1000 50
|
||
}
|
||
else
|
||
{
|
||
tipType = has1000Tip ? TipTypeEnum._1000UL : (has300Tip ? TipTypeEnum._300UL : TipTypeEnum._50UL); //优先1000 50 30
|
||
}
|
||
|
||
(int tipVolume, List<double> absorbVolumnList) volumeInfo;
|
||
volumeInfo.tipVolume = tipType == TipTypeEnum._50UL ? 50 : (tipType == TipTypeEnum._300UL ? 300 : 1000);
|
||
volumeInfo.absorbVolumnList = new List<double>();
|
||
while (targetVolumn > 0)
|
||
{
|
||
if (targetVolumn > volumeInfo.tipVolume)
|
||
{
|
||
volumeInfo.absorbVolumnList.Add(volumeInfo.tipVolume);
|
||
targetVolumn -= volumeInfo.tipVolume;
|
||
}
|
||
else
|
||
{
|
||
volumeInfo.absorbVolumnList.Add(targetVolumn);
|
||
targetVolumn = 0;
|
||
}
|
||
}
|
||
selectedTips.Add(volumeInfo);
|
||
return selectedTips;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择Tip头的函数
|
||
/// </summary>
|
||
/// <param name="targetVolumn"></param>
|
||
/// <returns></returns>
|
||
public List<(double tipVolume, List<double> absorbVolumnList)> SelectTips(double targetVolumn)
|
||
{
|
||
List<(double tipVolume, List<double> absorbVolumnList)> selectedTips = new List<(double tipVolume, List<double> absorbVolumnList)>();
|
||
|
||
// 1. 查找「存在且有可用Tip头」的工装(判断是否有对应类型的Tip)
|
||
TipBoxModel _1000ulTip = workService.ProjectPro.TipHeadArea.FirstOrDefault(tipBox =>
|
||
tipBox.TipType == TipTypeEnum._1000UL &&
|
||
tipBox.TipItems != null &&
|
||
tipBox.TipItems.Any(item => item.IsAvailable));
|
||
TipBoxModel _300ulTip = workService.ProjectPro.TipHeadArea.FirstOrDefault(tipBox =>
|
||
tipBox.TipType == TipTypeEnum._300UL &&
|
||
tipBox.TipItems != null &&
|
||
tipBox.TipItems.Any(item => item.IsAvailable));
|
||
TipBoxModel _50ulTip = workService.ProjectPro.TipHeadArea.FirstOrDefault(tipBox =>
|
||
tipBox.TipType == TipTypeEnum._50UL &&
|
||
tipBox.TipItems != null &&
|
||
tipBox.TipItems.Any(item => item.IsAvailable));
|
||
|
||
// 2. 整理「可用的Tip容量」(按「从大到小」排序,确保优先用大容量)
|
||
var availableTipVolumes = new List<double>();
|
||
if (_1000ulTip != null) availableTipVolumes.Add(1000); // 有1000UL Tip则加入
|
||
if (_300ulTip != null) availableTipVolumes.Add(300); // 有300UL Tip则加入
|
||
if (_50ulTip != null) availableTipVolumes.Add(50); // 有10UL Tip则加入
|
||
|
||
// 无可用Tip时,直接返回空列表(可根据业务需求抛异常)
|
||
if (!availableTipVolumes.Any())
|
||
{
|
||
//跟BS要Tip头
|
||
return selectedTips;
|
||
}
|
||
|
||
// 3. 初始化剩余体积(保留3位小数,避免精度问题)
|
||
double remainingVolume = Math.Round(targetVolumn, 3, MidpointRounding.ToPositiveInfinity);
|
||
|
||
while (remainingVolume > 0)
|
||
{
|
||
double currentVolumn = 0;
|
||
double tipvolumn = 1000;
|
||
if (remainingVolume > 1000)
|
||
{
|
||
currentVolumn = 1000;
|
||
remainingVolume -= 1000;
|
||
tipvolumn = 1000;
|
||
}
|
||
else if (remainingVolume > 300)
|
||
{
|
||
tipvolumn = 1000;
|
||
currentVolumn = remainingVolume;
|
||
remainingVolume = 0;
|
||
}
|
||
else if (remainingVolume > 50)
|
||
{
|
||
tipvolumn = 300;
|
||
currentVolumn = remainingVolume;
|
||
remainingVolume = 0;
|
||
}
|
||
else
|
||
{
|
||
tipvolumn = 50;
|
||
currentVolumn = remainingVolume;
|
||
remainingVolume = 0;
|
||
}
|
||
var st = selectedTips.FirstOrDefault(s => s.tipVolume == tipvolumn);
|
||
if (st.tipVolume > 0)
|
||
{
|
||
st.absorbVolumnList.Add(currentVolumn);
|
||
}
|
||
else
|
||
{
|
||
List<double> absorbVolumes = new List<double>();
|
||
absorbVolumes.Add(currentVolumn);
|
||
selectedTips.Add((tipvolumn, absorbVolumes));
|
||
}
|
||
|
||
}
|
||
|
||
// 4. 优先用「最大可用Tip」处理剩余体积
|
||
//foreach (var tipVolume in availableTipVolumes)
|
||
//{
|
||
// if (remainingVolume <= 0) break; // 体积处理完则退出循环
|
||
|
||
// List<double> absorbVolumes = new List<double>();
|
||
|
||
// // 步骤1:用当前Tip处理「尽可能多的满容量体积」
|
||
// if (remainingVolume >= tipVolume)
|
||
// {
|
||
// int fullTipCount = (int)(remainingVolume / tipVolume); // 需要的满容量Tip数量
|
||
// absorbVolumes.AddRange(Enumerable.Repeat(tipVolume, fullTipCount)); // 记录满容量吸液
|
||
// remainingVolume -= tipVolume * fullTipCount; // 扣除已处理的体积
|
||
// remainingVolume = Math.Round(remainingVolume, 3, MidpointRounding.ToPositiveInfinity); // 重新校准精度
|
||
// }
|
||
|
||
// // 步骤2:处理「剩余的少量体积」(不足一个满容量Tip)
|
||
// if (remainingVolume > 0)
|
||
// {
|
||
// absorbVolumes.Add(remainingVolume); // 用当前Tip处理剩余体积
|
||
// remainingVolume = 0; // 体积处理完成
|
||
// }
|
||
|
||
// // 将当前Tip的选择结果加入列表
|
||
// selectedTips.Add((tipVolume, absorbVolumes));
|
||
//}
|
||
return selectedTips;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 移液枪取Tip头
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="tipType"></param>
|
||
/// <returns></returns>
|
||
private async Task PipetteTakeTip(CancellationToken token, TipBoxModel tipBox, DeviceNames deviceName)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
ushort pipteId = 1;
|
||
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
|
||
{
|
||
pipteId = (ushort)((int)deviceName - 6);
|
||
}
|
||
TipHeadItem tipHead = tipBox.TipItems.FirstOrDefault(f => f.IsAvailable);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)(3 - tipBox.BoxId_inDosingStation + 1));//(ushort)tipBox.BoxId_inDosingStation);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param3, (ushort)tipHead.UseIndex);//
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 11);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param3, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
tipHead.IsAvailable = false;
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移液枪吸液
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="tipType"></param>
|
||
/// <returns></returns>
|
||
private async Task PipetteAbsorb(CancellationToken token, DeviceNames deviceName)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
ushort pipteId = 1;
|
||
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
|
||
{
|
||
pipteId = (ushort)((int)deviceName - 6);
|
||
}
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 12);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移液枪分液
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="tipType"></param>
|
||
/// <returns></returns>
|
||
private async Task PipetteDispense(CancellationToken token, DeviceNames deviceName)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
ushort pipteId = 1;
|
||
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
|
||
{
|
||
pipteId = (ushort)((int)deviceName - 6);
|
||
}
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 13);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移液枪丢弃Tip头
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <param name="tipType"></param>
|
||
/// <returns></returns>
|
||
private async Task PipetteDiscardTip(CancellationToken token, DeviceNames deviceName)
|
||
{
|
||
if (token.IsCancellationRequested || TestMode) return;
|
||
ushort pipteId = 1;
|
||
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
|
||
{
|
||
pipteId = (ushort)((int)deviceName - 6);
|
||
}
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 14);
|
||
//等待PLC回复执行完成
|
||
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
|
||
|
||
//信号清零
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
|
||
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
|
||
|
||
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
|
||
}
|
||
#endregion
|
||
|
||
|
||
|
||
private async Task RefreshReactBottleState(int boxId, int posId, SampleBottleStateEnum state)
|
||
{
|
||
|
||
await Task.Delay(0);
|
||
}
|
||
|
||
|
||
}
|
||
}
|