C00225155-02/C00225155/MegaRobo.C00225155/MegaRobo.C00225155.AppServer/ExecuteWorks/StationService_MaterialDosi...

1482 lines
72 KiB
C#
Raw Permalink Normal View History

2026-04-13 09:12:49 +00:00
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手套箱传送平台 2Tip托盘存放平台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手套箱传送平台 2Tip托盘存放平台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);
}
}
}