Update workstation code for YB4 0107

This commit is contained in:
Andy6M
2026-01-07 11:59:32 +08:00
parent 915a6a04c3
commit 936834f8c3
36 changed files with 3860 additions and 26826 deletions

View File

@@ -257,7 +257,7 @@ class BioyondCellWorkstation(BioyondWorkstation):
def auto_feeding4to3(
self,
# ★ 修改点:默认模板路径
xlsx_path: Optional[str] = "/Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx",
xlsx_path: Optional[str] = "D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\material_template.xlsx",
# ---------------- WH4 - 加样头面 (Z=1, 12个点位) ----------------
WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0,
WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0,
@@ -394,9 +394,13 @@ class BioyondCellWorkstation(BioyondWorkstation):
return response
# 等待完成报送
result = self.wait_for_order_finish(order_code)
print("\n" + "="*60)
print("实验记录本结果auto_feeding4to3")
print("="*60)
print(json.dumps(result, indent=2, ensure_ascii=False))
print("="*60 + "\n")
return result
def auto_batch_outbound_from_xlsx(self, xlsx_path: str) -> Dict[str, Any]:
"""
3.31 自动化下料Excel -> JSON -> POST /api/lims/storage/auto-batch-out-bound
@@ -474,7 +478,7 @@ class BioyondCellWorkstation(BioyondWorkstation):
- totalMass 自动计算为所有物料质量之和
- createTime 缺失或为空时自动填充为当前日期YYYY/M/D
"""
default_path = Path("/Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx")
default_path = Path("D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\2025122301.xlsx")
path = Path(xlsx_path) if xlsx_path else default_path
print(f"[create_orders] 使用 Excel 路径: {path}")
if path != default_path:
@@ -610,19 +614,63 @@ class BioyondCellWorkstation(BioyondWorkstation):
print(f"[create_orders] 即将提交订单数量: {len(orders)}")
response = self._post_lims("/api/lims/order/orders", orders)
print(f"[create_orders] 接口返回: {response}")
# 等待任务报送成功
# 提取所有返回的 orderCode
data_list = response.get("data", [])
if data_list:
order_code = data_list[0].get("orderCode")
else:
order_code = None
if not order_code:
logger.error("上料任务未返回有效 orderCode")
if not data_list:
logger.error("创建订单未返回有效数据!")
return response
# 等待完成报送
result = self.wait_for_order_finish(order_code)
return result
# 收集所有 orderCode
order_codes = []
for order_item in data_list:
code = order_item.get("orderCode")
if code:
order_codes.append(code)
if not order_codes:
logger.error("未找到任何有效的 orderCode")
return response
print(f"[create_orders] 等待 {len(order_codes)} 个订单完成: {order_codes}")
# 等待所有订单完成并收集报文
all_reports = []
for idx, order_code in enumerate(order_codes, 1):
print(f"[create_orders] 正在等待第 {idx}/{len(order_codes)} 个订单: {order_code}")
result = self.wait_for_order_finish(order_code)
# 提取报文数据
if result.get("status") == "success":
report = result.get("report", {})
all_reports.append(report)
print(f"[create_orders] ✓ 订单 {order_code} 完成")
else:
logger.warning(f"订单 {order_code} 状态异常: {result.get('status')}")
# 即使订单失败,也记录下这个结果
all_reports.append({
"orderCode": order_code,
"status": result.get("status"),
"error": result.get("message", "未知错误")
})
print(f"[create_orders] 所有订单已完成,共收集 {len(all_reports)} 个报文")
print("实验记录本========================create_orders========================")
# 返回所有订单的完成报文
final_result = {
"status": "all_completed",
"total_orders": len(order_codes),
"reports": all_reports,
"original_response": response
}
print(f"返回报文数量: {len(all_reports)}")
for i, report in enumerate(all_reports, 1):
print(f"报文 {i}: orderCode={report.get('orderCode', 'N/A')}, status={report.get('status', 'N/A')}")
print("========================")
return final_result
# 2.7 启动调度
def scheduler_start(self) -> Dict[str, Any]:
@@ -650,6 +698,146 @@ class BioyondCellWorkstation(BioyondWorkstation):
"""
return self._post_lims("/api/lims/scheduler/reset")
def scheduler_start_and_auto_feeding(
self,
# ★ Excel路径参数
xlsx_path: Optional[str] = "D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\material_template.xlsx",
# ---------------- WH4 - 加样头面 (Z=1, 12个点位) ----------------
WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0,
WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0,
WH4_x3_y1_z1_3_materialName: str = "", WH4_x3_y1_z1_3_quantity: float = 0.0,
WH4_x4_y1_z1_4_materialName: str = "", WH4_x4_y1_z1_4_quantity: float = 0.0,
WH4_x5_y1_z1_5_materialName: str = "", WH4_x5_y1_z1_5_quantity: float = 0.0,
WH4_x1_y2_z1_6_materialName: str = "", WH4_x1_y2_z1_6_quantity: float = 0.0,
WH4_x2_y2_z1_7_materialName: str = "", WH4_x2_y2_z1_7_quantity: float = 0.0,
WH4_x3_y2_z1_8_materialName: str = "", WH4_x3_y2_z1_8_quantity: float = 0.0,
WH4_x4_y2_z1_9_materialName: str = "", WH4_x4_y2_z1_9_quantity: float = 0.0,
WH4_x5_y2_z1_10_materialName: str = "", WH4_x5_y2_z1_10_quantity: float = 0.0,
WH4_x1_y3_z1_11_materialName: str = "", WH4_x1_y3_z1_11_quantity: float = 0.0,
WH4_x2_y3_z1_12_materialName: str = "", WH4_x2_y3_z1_12_quantity: float = 0.0,
# ---------------- WH4 - 原液瓶面 (Z=2, 9个点位) ----------------
WH4_x1_y1_z2_1_materialName: str = "", WH4_x1_y1_z2_1_quantity: float = 0.0, WH4_x1_y1_z2_1_materialType: str = "", WH4_x1_y1_z2_1_targetWH: str = "",
WH4_x2_y1_z2_2_materialName: str = "", WH4_x2_y1_z2_2_quantity: float = 0.0, WH4_x2_y1_z2_2_materialType: str = "", WH4_x2_y1_z2_2_targetWH: str = "",
WH4_x3_y1_z2_3_materialName: str = "", WH4_x3_y1_z2_3_quantity: float = 0.0, WH4_x3_y1_z2_3_materialType: str = "", WH4_x3_y1_z2_3_targetWH: str = "",
WH4_x1_y2_z2_4_materialName: str = "", WH4_x1_y2_z2_4_quantity: float = 0.0, WH4_x1_y2_z2_4_materialType: str = "", WH4_x1_y2_z2_4_targetWH: str = "",
WH4_x2_y2_z2_5_materialName: str = "", WH4_x2_y2_z2_5_quantity: float = 0.0, WH4_x2_y2_z2_5_materialType: str = "", WH4_x2_y2_z2_5_targetWH: str = "",
WH4_x3_y2_z2_6_materialName: str = "", WH4_x3_y2_z2_6_quantity: float = 0.0, WH4_x3_y2_z2_6_materialType: str = "", WH4_x3_y2_z2_6_targetWH: str = "",
WH4_x1_y3_z2_7_materialName: str = "", WH4_x1_y3_z2_7_quantity: float = 0.0, WH4_x1_y3_z2_7_materialType: str = "", WH4_x1_y3_z2_7_targetWH: str = "",
WH4_x2_y3_z2_8_materialName: str = "", WH4_x2_y3_z2_8_quantity: float = 0.0, WH4_x2_y3_z2_8_materialType: str = "", WH4_x2_y3_z2_8_targetWH: str = "",
WH4_x3_y3_z2_9_materialName: str = "", WH4_x3_y3_z2_9_quantity: float = 0.0, WH4_x3_y3_z2_9_materialType: str = "", WH4_x3_y3_z2_9_targetWH: str = "",
# ---------------- WH3 - 人工堆栈 (Z=3, 15个点位) ----------------
WH3_x1_y1_z3_1_materialType: str = "", WH3_x1_y1_z3_1_materialId: str = "", WH3_x1_y1_z3_1_quantity: float = 0,
WH3_x2_y1_z3_2_materialType: str = "", WH3_x2_y1_z3_2_materialId: str = "", WH3_x2_y1_z3_2_quantity: float = 0,
WH3_x3_y1_z3_3_materialType: str = "", WH3_x3_y1_z3_3_materialId: str = "", WH3_x3_y1_z3_3_quantity: float = 0,
WH3_x1_y2_z3_4_materialType: str = "", WH3_x1_y2_z3_4_materialId: str = "", WH3_x1_y2_z3_4_quantity: float = 0,
WH3_x2_y2_z3_5_materialType: str = "", WH3_x2_y2_z3_5_materialId: str = "", WH3_x2_y2_z3_5_quantity: float = 0,
WH3_x3_y2_z3_6_materialType: str = "", WH3_x3_y2_z3_6_materialId: str = "", WH3_x3_y2_z3_6_quantity: float = 0,
WH3_x1_y3_z3_7_materialType: str = "", WH3_x1_y3_z3_7_materialId: str = "", WH3_x1_y3_z3_7_quantity: float = 0,
WH3_x2_y3_z3_8_materialType: str = "", WH3_x2_y3_z3_8_materialId: str = "", WH3_x2_y3_z3_8_quantity: float = 0,
WH3_x3_y3_z3_9_materialType: str = "", WH3_x3_y3_z3_9_materialId: str = "", WH3_x3_y3_z3_9_quantity: float = 0,
WH3_x1_y4_z3_10_materialType: str = "", WH3_x1_y4_z3_10_materialId: str = "", WH3_x1_y4_z3_10_quantity: float = 0,
WH3_x2_y4_z3_11_materialType: str = "", WH3_x2_y4_z3_11_materialId: str = "", WH3_x2_y4_z3_11_quantity: float = 0,
WH3_x3_y4_z3_12_materialType: str = "", WH3_x3_y4_z3_12_materialId: str = "", WH3_x3_y4_z3_12_quantity: float = 0,
WH3_x1_y5_z3_13_materialType: str = "", WH3_x1_y5_z3_13_materialId: str = "", WH3_x1_y5_z3_13_quantity: float = 0,
WH3_x2_y5_z3_14_materialType: str = "", WH3_x2_y5_z3_14_materialId: str = "", WH3_x2_y5_z3_14_quantity: float = 0,
WH3_x3_y5_z3_15_materialType: str = "", WH3_x3_y5_z3_15_materialId: str = "", WH3_x3_y5_z3_15_quantity: float = 0,
) -> Dict[str, Any]:
"""
组合函数:先启动调度,然后执行自动化上料
此函数简化了工作流操作,将两个有顺序依赖的操作组合在一起:
1. 启动调度scheduler_start
2. 自动化上料auto_feeding4to3
参数与 auto_feeding4to3 完全相同,支持 Excel 和手动参数两种模式
Returns:
包含调度启动结果和上料结果的字典
"""
logger.info("=" * 60)
logger.info("开始执行组合操作:启动调度 + 自动化上料")
logger.info("=" * 60)
# 步骤1: 启动调度
logger.info("【步骤 1/2】启动调度...")
scheduler_result = self.scheduler_start()
logger.info(f"调度启动结果: {scheduler_result}")
# 检查调度是否启动成功
if scheduler_result.get("code") != 1:
logger.error(f"调度启动失败: {scheduler_result}")
return {
"success": False,
"step": "scheduler_start",
"scheduler_result": scheduler_result,
"error": "调度启动失败"
}
logger.info("✓ 调度启动成功")
# 步骤2: 执行自动化上料
logger.info("【步骤 2/2】执行自动化上料...")
feeding_result = self.auto_feeding4to3(
xlsx_path=xlsx_path,
WH4_x1_y1_z1_1_materialName=WH4_x1_y1_z1_1_materialName, WH4_x1_y1_z1_1_quantity=WH4_x1_y1_z1_1_quantity,
WH4_x2_y1_z1_2_materialName=WH4_x2_y1_z1_2_materialName, WH4_x2_y1_z1_2_quantity=WH4_x2_y1_z1_2_quantity,
WH4_x3_y1_z1_3_materialName=WH4_x3_y1_z1_3_materialName, WH4_x3_y1_z1_3_quantity=WH4_x3_y1_z1_3_quantity,
WH4_x4_y1_z1_4_materialName=WH4_x4_y1_z1_4_materialName, WH4_x4_y1_z1_4_quantity=WH4_x4_y1_z1_4_quantity,
WH4_x5_y1_z1_5_materialName=WH4_x5_y1_z1_5_materialName, WH4_x5_y1_z1_5_quantity=WH4_x5_y1_z1_5_quantity,
WH4_x1_y2_z1_6_materialName=WH4_x1_y2_z1_6_materialName, WH4_x1_y2_z1_6_quantity=WH4_x1_y2_z1_6_quantity,
WH4_x2_y2_z1_7_materialName=WH4_x2_y2_z1_7_materialName, WH4_x2_y2_z1_7_quantity=WH4_x2_y2_z1_7_quantity,
WH4_x3_y2_z1_8_materialName=WH4_x3_y2_z1_8_materialName, WH4_x3_y2_z1_8_quantity=WH4_x3_y2_z1_8_quantity,
WH4_x4_y2_z1_9_materialName=WH4_x4_y2_z1_9_materialName, WH4_x4_y2_z1_9_quantity=WH4_x4_y2_z1_9_quantity,
WH4_x5_y2_z1_10_materialName=WH4_x5_y2_z1_10_materialName, WH4_x5_y2_z1_10_quantity=WH4_x5_y2_z1_10_quantity,
WH4_x1_y3_z1_11_materialName=WH4_x1_y3_z1_11_materialName, WH4_x1_y3_z1_11_quantity=WH4_x1_y3_z1_11_quantity,
WH4_x2_y3_z1_12_materialName=WH4_x2_y3_z1_12_materialName, WH4_x2_y3_z1_12_quantity=WH4_x2_y3_z1_12_quantity,
WH4_x1_y1_z2_1_materialName=WH4_x1_y1_z2_1_materialName, WH4_x1_y1_z2_1_quantity=WH4_x1_y1_z2_1_quantity,
WH4_x1_y1_z2_1_materialType=WH4_x1_y1_z2_1_materialType, WH4_x1_y1_z2_1_targetWH=WH4_x1_y1_z2_1_targetWH,
WH4_x2_y1_z2_2_materialName=WH4_x2_y1_z2_2_materialName, WH4_x2_y1_z2_2_quantity=WH4_x2_y1_z2_2_quantity,
WH4_x2_y1_z2_2_materialType=WH4_x2_y1_z2_2_materialType, WH4_x2_y1_z2_2_targetWH=WH4_x2_y1_z2_2_targetWH,
WH4_x3_y1_z2_3_materialName=WH4_x3_y1_z2_3_materialName, WH4_x3_y1_z2_3_quantity=WH4_x3_y1_z2_3_quantity,
WH4_x3_y1_z2_3_materialType=WH4_x3_y1_z2_3_materialType, WH4_x3_y1_z2_3_targetWH=WH4_x3_y1_z2_3_targetWH,
WH4_x1_y2_z2_4_materialName=WH4_x1_y2_z2_4_materialName, WH4_x1_y2_z2_4_quantity=WH4_x1_y2_z2_4_quantity,
WH4_x1_y2_z2_4_materialType=WH4_x1_y2_z2_4_materialType, WH4_x1_y2_z2_4_targetWH=WH4_x1_y2_z2_4_targetWH,
WH4_x2_y2_z2_5_materialName=WH4_x2_y2_z2_5_materialName, WH4_x2_y2_z2_5_quantity=WH4_x2_y2_z2_5_quantity,
WH4_x2_y2_z2_5_materialType=WH4_x2_y2_z2_5_materialType, WH4_x2_y2_z2_5_targetWH=WH4_x2_y2_z2_5_targetWH,
WH4_x3_y2_z2_6_materialName=WH4_x3_y2_z2_6_materialName, WH4_x3_y2_z2_6_quantity=WH4_x3_y2_z2_6_quantity,
WH4_x3_y2_z2_6_materialType=WH4_x3_y2_z2_6_materialType, WH4_x3_y2_z2_6_targetWH=WH4_x3_y2_z2_6_targetWH,
WH4_x1_y3_z2_7_materialName=WH4_x1_y3_z2_7_materialName, WH4_x1_y3_z2_7_quantity=WH4_x1_y3_z2_7_quantity,
WH4_x1_y3_z2_7_materialType=WH4_x1_y3_z2_7_materialType, WH4_x1_y3_z2_7_targetWH=WH4_x1_y3_z2_7_targetWH,
WH4_x2_y3_z2_8_materialName=WH4_x2_y3_z2_8_materialName, WH4_x2_y3_z2_8_quantity=WH4_x2_y3_z2_8_quantity,
WH4_x2_y3_z2_8_materialType=WH4_x2_y3_z2_8_materialType, WH4_x2_y3_z2_8_targetWH=WH4_x2_y3_z2_8_targetWH,
WH4_x3_y3_z2_9_materialName=WH4_x3_y3_z2_9_materialName, WH4_x3_y3_z2_9_quantity=WH4_x3_y3_z2_9_quantity,
WH4_x3_y3_z2_9_materialType=WH4_x3_y3_z2_9_materialType, WH4_x3_y3_z2_9_targetWH=WH4_x3_y3_z2_9_targetWH,
WH3_x1_y1_z3_1_materialType=WH3_x1_y1_z3_1_materialType, WH3_x1_y1_z3_1_materialId=WH3_x1_y1_z3_1_materialId, WH3_x1_y1_z3_1_quantity=WH3_x1_y1_z3_1_quantity,
WH3_x2_y1_z3_2_materialType=WH3_x2_y1_z3_2_materialType, WH3_x2_y1_z3_2_materialId=WH3_x2_y1_z3_2_materialId, WH3_x2_y1_z3_2_quantity=WH3_x2_y1_z3_2_quantity,
WH3_x3_y1_z3_3_materialType=WH3_x3_y1_z3_3_materialType, WH3_x3_y1_z3_3_materialId=WH3_x3_y1_z3_3_materialId, WH3_x3_y1_z3_3_quantity=WH3_x3_y1_z3_3_quantity,
WH3_x1_y2_z3_4_materialType=WH3_x1_y2_z3_4_materialType, WH3_x1_y2_z3_4_materialId=WH3_x1_y2_z3_4_materialId, WH3_x1_y2_z3_4_quantity=WH3_x1_y2_z3_4_quantity,
WH3_x2_y2_z3_5_materialType=WH3_x2_y2_z3_5_materialType, WH3_x2_y2_z3_5_materialId=WH3_x2_y2_z3_5_materialId, WH3_x2_y2_z3_5_quantity=WH3_x2_y2_z3_5_quantity,
WH3_x3_y2_z3_6_materialType=WH3_x3_y2_z3_6_materialType, WH3_x3_y2_z3_6_materialId=WH3_x3_y2_z3_6_materialId, WH3_x3_y2_z3_6_quantity=WH3_x3_y2_z3_6_quantity,
WH3_x1_y3_z3_7_materialType=WH3_x1_y3_z3_7_materialType, WH3_x1_y3_z3_7_materialId=WH3_x1_y3_z3_7_materialId, WH3_x1_y3_z3_7_quantity=WH3_x1_y3_z3_7_quantity,
WH3_x2_y3_z3_8_materialType=WH3_x2_y3_z3_8_materialType, WH3_x2_y3_z3_8_materialId=WH3_x2_y3_z3_8_materialId, WH3_x2_y3_z3_8_quantity=WH3_x2_y3_z3_8_quantity,
WH3_x3_y3_z3_9_materialType=WH3_x3_y3_z3_9_materialType, WH3_x3_y3_z3_9_materialId=WH3_x3_y3_z3_9_materialId, WH3_x3_y3_z3_9_quantity=WH3_x3_y3_z3_9_quantity,
WH3_x1_y4_z3_10_materialType=WH3_x1_y4_z3_10_materialType, WH3_x1_y4_z3_10_materialId=WH3_x1_y4_z3_10_materialId, WH3_x1_y4_z3_10_quantity=WH3_x1_y4_z3_10_quantity,
WH3_x2_y4_z3_11_materialType=WH3_x2_y4_z3_11_materialType, WH3_x2_y4_z3_11_materialId=WH3_x2_y4_z3_11_materialId, WH3_x2_y4_z3_11_quantity=WH3_x2_y4_z3_11_quantity,
WH3_x3_y4_z3_12_materialType=WH3_x3_y4_z3_12_materialType, WH3_x3_y4_z3_12_materialId=WH3_x3_y4_z3_12_materialId, WH3_x3_y4_z3_12_quantity=WH3_x3_y4_z3_12_quantity,
WH3_x1_y5_z3_13_materialType=WH3_x1_y5_z3_13_materialType, WH3_x1_y5_z3_13_materialId=WH3_x1_y5_z3_13_materialId, WH3_x1_y5_z3_13_quantity=WH3_x1_y5_z3_13_quantity,
WH3_x2_y5_z3_14_materialType=WH3_x2_y5_z3_14_materialType, WH3_x2_y5_z3_14_materialId=WH3_x2_y5_z3_14_materialId, WH3_x2_y5_z3_14_quantity=WH3_x2_y5_z3_14_quantity,
WH3_x3_y5_z3_15_materialType=WH3_x3_y5_z3_15_materialType, WH3_x3_y5_z3_15_materialId=WH3_x3_y5_z3_15_materialId, WH3_x3_y5_z3_15_quantity=WH3_x3_y5_z3_15_quantity,
)
logger.info("=" * 60)
logger.info("组合操作完成")
logger.info("=" * 60)
return {
"success": True,
"scheduler_result": scheduler_result,
"feeding_result": feeding_result
}
# 2.24 物料变更推送
def report_material_change(self, material_obj: Dict[str, Any]) -> Dict[str, Any]:

View File

@@ -0,0 +1,197 @@
{
"token": "",
"request_time": "2025-12-24T15:32:09.2148671+08:00",
"data": {
"orderId": "3a1e614d-a082-c44a-60be-68647a35e6f1",
"orderCode": "BSO2025122400024",
"orderName": "DP20251224001",
"startTime": "2025-12-24T14:51:50.549848",
"endTime": "2025-12-24T15:32:09.000765",
"status": "30",
"workflowStatus": "completed",
"completionTime": "2025-12-24T15:32:09.000765",
"usedMaterials": [
{
"materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-4da7-cf62-3a40-7e5879255c0c",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-53a7-2850-42c8-a7a2de8ff4bf",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f",
"locationId": "3a1abd46-18fe-1f56-6ced-a1f7fe08e36c",
"typemode": "0",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829",
"locationId": "3a19da43-57b5-294f-d663-154a1cc32270",
"typemode": "2",
"usedQuantity": 3.51,
"realQuantity": 3.5155000000000000000000000000
},
{
"materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d",
"locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"typemode": "2",
"usedQuantity": 0.33,
"realQuantity": 0.3336000000000000000000000000
}
]
}
}
{
"token": "",
"request_time": "2025-12-24T15:32:09.9999039+08:00",
"data": {
"orderId": "3a1e614d-a0a2-f7a9-9360-610021c9479d",
"orderCode": "BSO2025122400025",
"orderName": "DP20251224002",
"startTime": "2025-12-24T14:53:03.44259",
"endTime": "2025-12-24T15:32:09.828261",
"status": "30",
"workflowStatus": "completed",
"completionTime": "2025-12-24T15:32:09.828261",
"usedMaterials": [
{
"materialId": "3a1e614b-4da7-6527-9f1c-b39e3de8ff2b",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-53a8-8474-cac8-0fd7d349e4b2",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f",
"locationId": null,
"typemode": "0",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829",
"locationId": "3a19da43-57b5-294f-d663-154a1cc32270",
"typemode": "2",
"usedQuantity": 0.7,
"realQuantity": 0
},
{
"materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d",
"locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"typemode": "2",
"usedQuantity": 1.15,
"realQuantity": 1.1627000000000000000000000000
}
]
}
}
{
"token": "",
"request_time": "2025-12-24T15:34:00.4139986+08:00",
"data": {
"orderId": "3a1e614d-a0cd-81ca-9f7f-2f4e93af01cd",
"orderCode": "BSO2025122400026",
"orderName": "DP20251224003",
"startTime": "2025-12-24T14:54:24.443344",
"endTime": "2025-12-24T15:34:00.26321",
"status": "30",
"workflowStatus": "completed",
"completionTime": "2025-12-24T15:34:00.26321",
"usedMaterials": [
{
"materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2",
"locationId": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-4da8-b678-f204-207076f09c83",
"locationId": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-53a8-e3f2-dee0-fa97b600b652",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f",
"locationId": null,
"typemode": "0",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829",
"locationId": "3a19da43-57b5-294f-d663-154a1cc32270",
"typemode": "2",
"usedQuantity": 2.0,
"realQuantity": 2.0075000000000000000000000000
},
{
"materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d",
"locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"typemode": "2",
"usedQuantity": 1.2,
"realQuantity": 1.2126000000000000000000000000
}
]
}
}

View File

@@ -0,0 +1,113 @@
# Bioyond Cell 工作站 - 多订单返回示例
本文档说明了 `create_orders` 函数如何收集并返回所有订单的完成报文。
## 问题描述
之前的实现只会等待并返回第一个订单的完成报文,如果有多个订单(例如从 Excel 解析出 3 个订单),只能得到第一个订单的推送信息。
## 解决方案
修改后的 `create_orders` 函数现在会:
1. **提取所有 orderCode**:从 LIMS 接口返回的 `data` 列表中提取所有订单编号
2. **逐个等待完成**:遍历所有 orderCode调用 `wait_for_order_finish` 等待每个订单完成
3. **收集所有报文**:将每个订单的完成报文存入 `all_reports` 列表
4. **统一返回**:返回包含所有订单报文的 JSON 格式数据
## 返回格式
```json
{
"status": "all_completed",
"total_orders": 3,
"reports": [
{
"token": "",
"request_time": "2025-12-24T15:32:09.2148671+08:00",
"data": {
"orderId": "3a1e614d-a082-c44a-60be-68647a35e6f1",
"orderCode": "BSO2025122400024",
"orderName": "DP20251224001",
"status": "30",
"workflowStatus": "completed",
"usedMaterials": [...]
}
},
{
"token": "",
"request_time": "2025-12-24T15:32:09.9999039+08:00",
"data": {
"orderId": "3a1e614d-a0a2-f7a9-9360-610021c9479d",
"orderCode": "BSO2025122400025",
"orderName": "DP20251224002",
"status": "30",
"workflowStatus": "completed",
"usedMaterials": [...]
}
},
{
"token": "",
"request_time": "2025-12-24T15:34:00.4139986+08:00",
"data": {
"orderId": "3a1e614d-a0cd-81ca-9f7f-2f4e93af01cd",
"orderCode": "BSO2025122400026",
"orderName": "DP20251224003",
"status": "30",
"workflowStatus": "completed",
"usedMaterials": [...]
}
}
],
"original_response": {...}
}
```
## 使用示例
```python
# 调用 create_orders
result = workstation.create_orders("20251224.xlsx")
# 访问返回数据
print(f"总订单数: {result['total_orders']}")
print(f"状态: {result['status']}")
# 遍历所有订单的报文
for i, report in enumerate(result['reports'], 1):
order_data = report.get('data', {})
print(f"\n订单 {i}:")
print(f" orderCode: {order_data.get('orderCode')}")
print(f" orderName: {order_data.get('orderName')}")
print(f" status: {order_data.get('status')}")
print(f" 使用物料数: {len(order_data.get('usedMaterials', []))}")
```
## 控制台输出示例
```
[create_orders] 即将提交订单数量: 3
[create_orders] 接口返回: {...}
[create_orders] 等待 3 个订单完成: ['BSO2025122400024', 'BSO2025122400025', 'BSO2025122400026']
[create_orders] 正在等待第 1/3 个订单: BSO2025122400024
[create_orders] ✓ 订单 BSO2025122400024 完成
[create_orders] 正在等待第 2/3 个订单: BSO2025122400025
[create_orders] ✓ 订单 BSO2025122400025 完成
[create_orders] 正在等待第 3/3 个订单: BSO2025122400026
[create_orders] ✓ 订单 BSO2025122400026 完成
[create_orders] 所有订单已完成,共收集 3 个报文
实验记录本========================create_orders========================
返回报文数量: 3
报文 1: orderCode=BSO2025122400024, status=30
报文 2: orderCode=BSO2025122400025, status=30
报文 3: orderCode=BSO2025122400026, status=30
========================
```
## 关键改进
1.**等待所有订单**:不再只等待第一个订单,而是遍历所有 orderCode
2.**收集完整报文**:每个订单的完整推送报文都被保存在 `reports` 数组中
3.**详细日志**:清晰显示正在等待哪个订单,以及完成情况
4.**错误处理**:即使某个订单失败,也会记录其状态信息
5.**统一格式**:返回的 JSON 格式便于后续处理和分析

View File

@@ -8,8 +8,10 @@ import os
# BioyondCellWorkstation 默认配置(包含所有必需参数)
API_CONFIG = {
# API 连接配置
# "api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.1.143:44389"),#实机
"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.219:44388"),# 仿真机
# 实机
#"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.118:44389"),
# 仿真机
"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.219:44388"),
"api_key": os.getenv("BIOYOND_API_KEY", "8A819E5C"),
"timeout": int(os.getenv("BIOYOND_TIMEOUT", "30")),
@@ -17,7 +19,7 @@ API_CONFIG = {
"report_token": os.getenv("BIOYOND_REPORT_TOKEN", "CHANGE_ME_TOKEN"),
# HTTP 服务配置
"HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.16.11.2"), # HTTP服务监听地址监听计算机飞连ip地址
"HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.16.11.206"), # HTTP服务监听地址监听计算机飞连ip地址
"HTTP_port": int(os.getenv("BIOYOND_HTTP_PORT", "8080")),
"debug_mode": False,# 调试模式
}

View File

@@ -0,0 +1,84 @@
# Modbus CSV 地址映射说明
本文档说明 `coin_cell_assembly_a.csv` 文件如何将命名节点映射到实际的 Modbus 地址,以及如何在代码中使用它们。
## 1. CSV 文件结构
地址表文件位于同级目录下:`coin_cell_assembly_a.csv`
每一行定义了一个 Modbus 节点,包含以下关键列:
| 列名 | 说明 | 示例 |
|------|------|------|
| **Name** | **节点名称** (代码中引用的 Key) | `COIL_ALUMINUM_FOIL` |
| **DataType** | 数据类型 (BOOL, INT16, FLOAT32, STRING) | `BOOL` |
| **Comment** | 注释说明 | `使用铝箔垫` |
| **Attribute** | 属性 (通常留空或用于额外标记) | |
| **DeviceType** | Modbus 寄存器类型 (`coil`, `hold_register`) | `coil` |
| **Address** | **Modbus 地址** (十进制) | `8340` |
### 示例行 (铝箔垫片)
```csv
COIL_ALUMINUM_FOIL,BOOL,,使用铝箔垫,,coil,8340,
```
- **名称**: `COIL_ALUMINUM_FOIL`
- **类型**: `coil` (线圈,读写单个位)
- **地址**: `8340`
---
## 2. 加载与注册流程
`coin_cell_assembly.py` 的初始化代码中:
1. **加载 CSV**: `BaseClient.load_csv()` 读取 CSV 并解析每行定义。
2. **注册节点**: `modbus_client.register_node_list()` 将解析后的节点注册到 Modbus 客户端实例中。
```python
# 代码位置: coin_cell_assembly.py (L174-175)
self.nodes = BaseClient.load_csv(os.path.join(os.path.dirname(__file__), 'coin_cell_assembly_a.csv'))
self.client = modbus_client.register_node_list(self.nodes)
```
---
## 3. 代码中的使用方式
注册后,通过 `self.client.use_node('节点名称')` 即可获取该节点对象并进行读写操作,无需关心具体地址。
### 控制铝箔垫片 (COIL_ALUMINUM_FOIL)
```python
# 代码位置: qiming_coin_cell_code 函数 (L1048)
self.client.use_node('COIL_ALUMINUM_FOIL').write(not lvbodian)
```
- **写入 True**: 对应 Modbus 功能码 05 (Write Single Coil),向地址 `8340` 写入 `1` (ON)。
- **写入 False**: 向地址 `8340` 写入 `0` (OFF)。
> **注意**: 代码中使用了 `not lvbodian`,这意味着逻辑是反转的。如果 `lvbodian` 参数为 `True` (默认),写入的是 `False` (不使用铝箔垫)。
---
## 4. 地址转换注意事项 (Modbus vs PLC)
CSV 中的 `Address` 列(如 `8340`)是 **Modbus 协议地址**
如果使用 InoProShop (汇川 PLC 编程软件),看到的可能是 **PLC 内部地址** (如 `%QX...``%MW...`)。这两者之间通常需要转换。
### 常见的转换规则 (示例)
- **Coil (线圈) %QX**:
- `Modbus地址 = 字节地址 * 8 + 位偏移`
- *例子*: `%QX834.0` -> `834 * 8 + 0` = `6672`
- *注意*: 如果 CSV 中配置的是 `8340`,这可能是一个自定义映射,或者是基于不同规则(如直接对应 Word 地址的某种映射,或者可能就是地址写错了/使用了非标准映射)。
- **Register (寄存器) %MW**:
- 通常直接对应,或者有偏移量 (如 Modbus 40001 = PLC MW0)。
### 验证方法
由于 `test_unilab_interact.py` 中发现 `8450` (CSV风格) 不工作,而 `6760` (%QX845.0 计算值) 工作正常,**建议对 CSV 中的其他地址也进行核实**,特别是像 `8340` 这样以 0 结尾看起来像是 "字节地址+0" 的数值,可能实际上应该是 `%QX834.0` 对应的 `6672`
如果发现设备控制无反应,请尝试按照标准的 Modbus 计算方式转换 PLC 地址。

View File

@@ -634,6 +634,12 @@ class CoincellDeck(Deck):
self.assign_child_resource(waste_tip_box, Coordinate(x=778.0, y=622.0, z=0))
def YH_Deck(name=""):
cd = CoincellDeck(name=name)
cd.setup()
return cd
if __name__ == "__main__":
deck = create_coin_cell_deck()
print(deck)

View File

@@ -1,4 +1,3 @@
import csv
import inspect
import json
@@ -21,6 +20,39 @@ from unilabos.ros.nodes.presets.workstation import ROS2WorkstationNode
from unilabos.devices.workstation.coin_cell_assembly.YB_YH_materials import CoincellDeck
from unilabos.resources.graphio import convert_resources_to_type
from unilabos.utils.log import logger
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
def _decode_float32_correct(registers):
"""
正确解码FLOAT32类型的Modbus寄存器
Args:
registers: 从Modbus读取的原始寄存器值列表
Returns:
正确解码的浮点数值
Note:
根据test_glove_box_pressure.py验证的配置:
- Byte Order: Big (Modbus标准)
- Word Order: Little (PLC配置)
"""
if not registers or len(registers) < 2:
return 0.0
try:
# 使用正确的字节序配置
decoder = BinaryPayloadDecoder.fromRegisters(
registers,
byteorder=Endian.Big, # 字节序始终为Big
wordorder=Endian.Little # 字序为Little (根据PLC配置)
)
return decoder.decode_32bit_float()
except Exception as e:
logger.error(f"解码FLOAT32失败: {e}, registers: {registers}")
return 0.0
def _ensure_modbus_slave_kw_alias(modbus_client):
@@ -139,7 +171,7 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
time.sleep(2)
if not modbus_client.client.is_socket_open():
raise ValueError('modbus tcp connection failed')
self.nodes = BaseClient.load_csv(os.path.join(os.path.dirname(__file__), 'coin_cell_assembly_1105.csv'))
self.nodes = BaseClient.load_csv(os.path.join(os.path.dirname(__file__), 'coin_cell_assembly_b.csv'))
self.client = modbus_client.register_node_list(self.nodes)
else:
print("测试模式,跳过连接")
@@ -502,48 +534,72 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
"""单颗电池组装时间 (秒, REAL/FLOAT32)"""
if self.debug_mode:
return 0
time, read_err = self.client.use_node('REG_DATA_ASSEMBLY_PER_TIME').read(2, word_order=WorderOrder.LITTLE)
return time
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_ASSEMBLY_PER_TIME').address, count=2)
if result.isError():
logger.error(f"读取组装时间失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_open_circuit_voltage(self) -> float:
"""开路电压值 (FLOAT32)"""
if self.debug_mode:
return 0
vol, read_err = self.client.use_node('REG_DATA_OPEN_CIRCUIT_VOLTAGE').read(2, word_order=WorderOrder.LITTLE)
return vol
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_OPEN_CIRCUIT_VOLTAGE').address, count=2)
if result.isError():
logger.error(f"读取开路电压失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_axis_x_pos(self) -> float:
"""分液X轴当前位置 (FLOAT32)"""
if self.debug_mode:
return 0
pos, read_err = self.client.use_node('REG_DATA_AXIS_X_POS').read(2, word_order=WorderOrder.LITTLE)
return pos
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_AXIS_X_POS').address, count=2)
if result.isError():
logger.error(f"读取X轴位置失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_axis_y_pos(self) -> float:
"""分液Y轴当前位置 (FLOAT32)"""
if self.debug_mode:
return 0
pos, read_err = self.client.use_node('REG_DATA_AXIS_Y_POS').read(2, word_order=WorderOrder.LITTLE)
return pos
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_AXIS_Y_POS').address, count=2)
if result.isError():
logger.error(f"读变Y轴位置失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_axis_z_pos(self) -> float:
"""分液Z轴当前位置 (FLOAT32)"""
if self.debug_mode:
return 0
pos, read_err = self.client.use_node('REG_DATA_AXIS_Z_POS').read(2, word_order=WorderOrder.LITTLE)
return pos
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_AXIS_Z_POS').address, count=2)
if result.isError():
logger.error(f"读取Z轴位置失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_pole_weight(self) -> float:
"""当前电池正极片称重数据 (FLOAT32)"""
if self.debug_mode:
return 0
weight, read_err = self.client.use_node('REG_DATA_POLE_WEIGHT').read(2, word_order=WorderOrder.LITTLE)
return weight
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_POLE_WEIGHT').address, count=2)
if result.isError():
logger.error(f"读取极片质量失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_assembly_pressure(self) -> int:
@@ -573,11 +629,28 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
def data_coin_cell_code(self) -> str:
"""电池二维码序列号 (STRING)"""
try:
# 尝试不同的字节序读取
# 读取 STRING 类型数据
code_little, read_err = self.client.use_node('REG_DATA_COIN_CELL_CODE').read(10, word_order=WorderOrder.LITTLE)
# logger.debug(f"读取电池二维码原始数据: {code_little}")
clean_code = code_little[-8:][::-1]
return clean_code
# 处理 bytes 或 string 类型
if isinstance(code_little, bytes):
code_str = code_little.decode('utf-8', errors='ignore')
elif isinstance(code_little, str):
code_str = code_little
else:
logger.warning(f"电池二维码返回的类型不支持: {type(code_little)}")
return "N/A"
# 取前8个字符
raw_code = code_str[:8]
# LITTLE字节序需要每2个字符交换位置
clean_code = ''.join([raw_code[i+1] + raw_code[i] for i in range(0, len(raw_code), 2)])
# 去除空字符和空格
decoded = clean_code.replace('\x00', '').replace('\r', '').replace('\n', '').strip()
return decoded if decoded else "N/A"
except Exception as e:
logger.error(f"读取电池二维码失败: {e}")
return "N/A"
@@ -585,12 +658,30 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
@property
def data_electrolyte_code(self) -> str:
"""电解液二维码序列号 (STRING)"""
try:
# 尝试不同的字节序读取
# 读取 STRING 类型数据
code_little, read_err = self.client.use_node('REG_DATA_ELECTROLYTE_CODE').read(10, word_order=WorderOrder.LITTLE)
# logger.debug(f"读取电解液二维码原始数据: {code_little}")
clean_code = code_little[-8:][::-1]
return clean_code
# 处理 bytes 或 string 类型
if isinstance(code_little, bytes):
code_str = code_little.decode('utf-8', errors='ignore')
elif isinstance(code_little, str):
code_str = code_little
else:
logger.warning(f"电解液二维码返回的类型不支持: {type(code_little)}")
return "N/A"
# 取前8个字符
raw_code = code_str[:8]
# LITTLE字节序需要每2个字符交换位置
clean_code = ''.join([raw_code[i+1] + raw_code[i] for i in range(0, len(raw_code), 2)])
# 去除空字符和空格
decoded = clean_code.replace('\x00', '').replace('\r', '').replace('\n', '').strip()
return decoded if decoded else "N/A"
except Exception as e:
logger.error(f"读取电解液二维码失败: {e}")
return "N/A"
@@ -598,27 +689,39 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
# ===================== 环境监控区 ======================
@property
def data_glove_box_pressure(self) -> float:
"""手套箱压力 (bar, FLOAT32)"""
"""手套箱压力 (mbar, FLOAT32)"""
if self.debug_mode:
return 0
status, read_err = self.client.use_node('REG_DATA_GLOVE_BOX_PRESSURE').read(2, word_order=WorderOrder.LITTLE)
return status
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_GLOVE_BOX_PRESSURE').address, count=2)
if result.isError():
logger.error(f"读取手套箱压力失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_glove_box_o2_content(self) -> float:
"""手套箱氧含量 (ppm, FLOAT32)"""
if self.debug_mode:
return 0
value, read_err = self.client.use_node('REG_DATA_GLOVE_BOX_O2_CONTENT').read(2, word_order=WorderOrder.LITTLE)
return value
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_GLOVE_BOX_O2_CONTENT').address, count=2)
if result.isError():
logger.error(f"读取手套箱氧含量失败")
return 0.0
return _decode_float32_correct(result.registers)
@property
def data_glove_box_water_content(self) -> float:
"""手套箱水含量 (ppm, FLOAT32)"""
if self.debug_mode:
return 0
value, read_err = self.client.use_node('REG_DATA_GLOVE_BOX_WATER_CONTENT').read(2, word_order=WorderOrder.LITTLE)
return value
# 读取原始寄存器并正确解码FLOAT32
result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_GLOVE_BOX_WATER_CONTENT').address, count=2)
if result.isError():
logger.error(f"读取手套箱水含量失败")
return 0.0
return _decode_float32_correct(result.registers)
# @property
# def data_stack_vision_code(self) -> int:
@@ -690,6 +793,130 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
print("waiting for start_cmd")
time.sleep(1)
def func_pack_device_init_auto_start_combined(self) -> bool:
"""
组合函数:设备初始化 + 切换自动模式 + 启动
整合了原有的三个独立函数:
1. func_pack_device_init() - 设备初始化
2. func_pack_device_auto() - 切换自动模式
3. func_pack_device_start() - 启动设备
Returns:
bool: 操作成功返回 True失败返回 False
"""
logger.info("=" * 60)
logger.info("开始组合操作:设备初始化 → 自动模式 → 启动")
logger.info("=" * 60)
# 步骤0: 前置条件检查
logger.info("\n【步骤 0/3】前置条件检查...")
try:
# 检查 REG_UNILAB_INTERACT (应该为False表示使用Unilab交互)
unilab_interact_node = self.client.use_node('REG_UNILAB_INTERACT')
unilab_interact_value, read_err = unilab_interact_node.read(1)
if read_err:
error_msg = "❌ 无法读取 REG_UNILAB_INTERACT 状态!请检查设备连接。"
logger.error(error_msg)
raise RuntimeError(error_msg)
# 提取实际值(处理可能的列表或单值)
if isinstance(unilab_interact_value, (list, tuple)):
unilab_interact_actual = unilab_interact_value[0] if len(unilab_interact_value) > 0 else None
else:
unilab_interact_actual = unilab_interact_value
logger.info(f" REG_UNILAB_INTERACT 当前值: {unilab_interact_actual}")
if unilab_interact_actual != False:
error_msg = (
"❌ 前置条件检查失败!\n"
f" REG_UNILAB_INTERACT = {unilab_interact_actual} (期望值: False)\n"
" 说明: 当前设备设置为'忽略Unilab交互'模式\n"
" 操作: 请在HMI上确认并切换为'使用Unilab交互'模式\n"
" 提示: REG_UNILAB_INTERACT应该为False才能继续"
)
logger.error(error_msg)
raise RuntimeError(error_msg)
logger.info(" ✓ REG_UNILAB_INTERACT 检查通过 (值为False使用Unilab交互)")
# 检查 COIL_GB_L_IGNORE_CMD (应该为False表示使用左手套箱)
gb_l_ignore_node = self.client.use_node('COIL_GB_L_IGNORE_CMD')
gb_l_ignore_value, read_err = gb_l_ignore_node.read(1)
if read_err:
error_msg = "❌ 无法读取 COIL_GB_L_IGNORE_CMD 状态!请检查设备连接。"
logger.error(error_msg)
raise RuntimeError(error_msg)
# 提取实际值
if isinstance(gb_l_ignore_value, (list, tuple)):
gb_l_ignore_actual = gb_l_ignore_value[0] if len(gb_l_ignore_value) > 0 else None
else:
gb_l_ignore_actual = gb_l_ignore_value
logger.info(f" COIL_GB_L_IGNORE_CMD 当前值: {gb_l_ignore_actual}")
if gb_l_ignore_actual != False:
error_msg = (
"❌ 前置条件检查失败!\n"
f" COIL_GB_L_IGNORE_CMD = {gb_l_ignore_actual} (期望值: False)\n"
" 说明: 当前设备设置为'忽略左手套箱'模式\n"
" 操作: 请在HMI上确认并切换为'使用左手套箱'模式\n"
" 提示: COIL_GB_L_IGNORE_CMD应该为False才能继续"
)
logger.error(error_msg)
raise RuntimeError(error_msg)
logger.info(" ✓ COIL_GB_L_IGNORE_CMD 检查通过 (值为False使用左手套箱)")
logger.info("✓ 所有前置条件检查通过!")
except ValueError as e:
# 节点未找到
error_msg = f"❌ 配置错误:{str(e)}\n请检查CSV配置文件是否包含必要的节点。"
logger.error(error_msg)
raise RuntimeError(error_msg)
except Exception as e:
# 其他异常
error_msg = f"❌ 前置条件检查异常:{str(e)}"
logger.error(error_msg)
raise
# 步骤1: 设备初始化
logger.info("\n【步骤 1/3】设备初始化...")
try:
self.func_pack_device_init()
logger.info("✓ 设备初始化完成")
except Exception as e:
logger.error(f"❌ 设备初始化失败: {e}")
return False
# 步骤2: 切换自动模式
logger.info("\n【步骤 2/3】切换自动模式...")
try:
self.func_pack_device_auto()
logger.info("✓ 切换自动模式完成")
except Exception as e:
logger.error(f"❌ 切换自动模式失败: {e}")
return False
# 步骤3: 启动设备
logger.info("\n【步骤 3/3】启动设备...")
try:
self.func_pack_device_start()
logger.info("✓ 启动设备完成")
except Exception as e:
logger.error(f"❌ 启动设备失败: {e}")
return False
logger.info("\n" + "=" * 60)
logger.info("组合操作完成:设备已成功初始化、切换自动模式并启动")
logger.info("=" * 60)
return True
def func_pack_send_bottle_num(self, bottle_num):
bottle_num = int(bottle_num)
#发送电解液平台数
@@ -774,14 +1001,59 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
while self.request_send_msg_status == False:
print("waiting for send_read_msg_status to True")
time.sleep(1)
data_open_circuit_voltage = self.data_open_circuit_voltage
data_pole_weight = self.data_pole_weight
# 处理开路电压 - 确保是数值类型
try:
data_open_circuit_voltage = self.data_open_circuit_voltage
if isinstance(data_open_circuit_voltage, (list, tuple)) and len(data_open_circuit_voltage) > 0:
data_open_circuit_voltage = float(data_open_circuit_voltage[0])
else:
data_open_circuit_voltage = float(data_open_circuit_voltage)
except Exception as e:
print(f"读取开路电压失败: {e}")
logger.error(f"读取开路电压失败: {e}")
data_open_circuit_voltage = 0.0
# 处理极片质量 - 确保是数值类型
try:
data_pole_weight = self.data_pole_weight
if isinstance(data_pole_weight, (list, tuple)) and len(data_pole_weight) > 0:
data_pole_weight = float(data_pole_weight[0])
else:
data_pole_weight = float(data_pole_weight)
except Exception as e:
print(f"读取正极片重量失败: {e}")
logger.error(f"读取正极片重量失败: {e}")
data_pole_weight = 0.0
data_assembly_time = self.data_assembly_time
data_assembly_pressure = self.data_assembly_pressure
data_electrolyte_volume = self.data_electrolyte_volume
data_coin_num = self.data_coin_num
data_electrolyte_code = self.data_electrolyte_code
data_coin_cell_code = self.data_coin_cell_code
# 处理电解液二维码 - 确保是字符串类型
try:
data_electrolyte_code = self.data_electrolyte_code
if isinstance(data_electrolyte_code, str):
data_electrolyte_code = data_electrolyte_code.strip()
else:
data_electrolyte_code = str(data_electrolyte_code)
except Exception as e:
print(f"读取电解液二维码失败: {e}")
logger.error(f"读取电解液二维码失败: {e}")
data_electrolyte_code = "N/A"
# 处理电池二维码 - 确保是字符串类型
try:
data_coin_cell_code = self.data_coin_cell_code
if isinstance(data_coin_cell_code, str):
data_coin_cell_code = data_coin_cell_code.strip()
else:
data_coin_cell_code = str(data_coin_cell_code)
except Exception as e:
print(f"读取电池二维码失败: {e}")
logger.error(f"读取电池二维码失败: {e}")
data_coin_cell_code = "N/A"
logger.debug(f"data_open_circuit_voltage: {data_open_circuit_voltage}")
logger.debug(f"data_pole_weight: {data_pole_weight}")
logger.debug(f"data_assembly_time: {data_assembly_time}")
@@ -792,8 +1064,25 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
logger.debug(f"data_coin_cell_code: {data_coin_cell_code}")
#接收完信息后读取完毕标志位置True
liaopan3 = self.deck.get_resource("成品弹夹")
#把物料解绑后放到另一盘上
battery = ElectrodeSheet(name=f"battery_{self.coin_num_N}", size_x=14, size_y=14, size_z=2)
# 生成唯一的电池名称(使用时间戳确保唯一性)
timestamp_suffix = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
battery_name = f"battery_{self.coin_num_N}_{timestamp_suffix}"
# 检查目标位置是否已有资源,如果有则先卸载
target_slot = liaopan3.children[self.coin_num_N]
if target_slot.children:
logger.warning(f"位置 {self.coin_num_N} 已有资源,将先卸载旧资源")
try:
# 卸载所有现有子资源
for child in list(target_slot.children):
target_slot.unassign_child_resource(child)
logger.info(f"已卸载旧资源: {child.name}")
except Exception as e:
logger.error(f"卸载旧资源时出错: {e}")
# 创建新的电池资源
battery = ElectrodeSheet(name=battery_name, size_x=14, size_y=14, size_z=2)
battery._unilabos_state = {
"electrolyte_name": data_coin_cell_code,
"data_electrolyte_code": data_electrolyte_code,
@@ -801,7 +1090,16 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
"assembly_pressure": data_assembly_pressure,
"electrolyte_volume": data_electrolyte_volume
}
liaopan3.children[self.coin_num_N].assign_child_resource(battery, location=None)
# 分配新资源到目标位置
try:
target_slot.assign_child_resource(battery, location=None)
logger.info(f"成功分配电池 {battery_name} 到位置 {self.coin_num_N}")
except Exception as e:
logger.error(f"分配电池资源失败: {e}")
# 如果分配失败,尝试使用更简单的方法
raise
#print(jipian2.parent)
ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{
"resources": [self.deck]
@@ -879,11 +1177,14 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
return self.success
def func_allpack_cmd(self, elec_num, elec_use_num, elec_vol:int=50, assembly_type:int=7, assembly_pressure:int=4200, file_path: str="/Users/sml/work") -> bool:
def func_allpack_cmd(self, elec_num, elec_use_num, elec_vol:int=50, assembly_type:int=7, assembly_pressure:int=4200, file_path: str="/Users/sml/work") -> Dict[str, Any]:
elec_num, elec_use_num, elec_vol, assembly_type, assembly_pressure = int(elec_num), int(elec_use_num), int(elec_vol), int(assembly_type), int(assembly_pressure)
summary_csv_file = os.path.join(file_path, "duandian.csv")
# 如果断点文件存在,先读取之前的进度
# 用于收集所有电池的数据
battery_data_list = []
# 如果断点文件存在,先读取之前的进度
if os.path.exists(summary_csv_file):
read_status_flag = True
with open(summary_csv_file, 'r', newline='', encoding='utf-8') as csvfile:
@@ -900,7 +1201,12 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
print("断点文件与当前任务匹配,继续")
else:
print("断点文件中elec_num、elec_use_num与当前任务不匹配请检查任务下发参数或修改断点文件")
return False
return {
"success": False,
"error": "断点文件参数不匹配",
"total_batteries": 0,
"batteries": []
}
print(f"从断点文件读取进度: elec_num_N={elec_num_N}, elec_use_num_N={elec_use_num_N}, coin_num_N={coin_num_N}")
else:
@@ -935,13 +1241,63 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
for j in range(j_start, elec_use_num):
print(f"开始第{last_i+i+1}瓶电解液的第{j+j_start+1}个电池组装")
#读取电池组装数据并存入csv
self.func_pack_get_msg_cmd(file_path)
# 收集当前电池的数据
# 处理电池二维码
try:
battery_qr_code = self.data_coin_cell_code
except Exception as e:
print(f"读取电池二维码失败: {e}")
battery_qr_code = "N/A"
# 处理电解液二维码
try:
electrolyte_qr_code = self.data_electrolyte_code
except Exception as e:
print(f"读取电解液二维码失败: {e}")
electrolyte_qr_code = "N/A"
# 处理开路电压 - 确保是数值类型
try:
open_circuit_voltage = self.data_open_circuit_voltage
if isinstance(open_circuit_voltage, (list, tuple)) and len(open_circuit_voltage) > 0:
open_circuit_voltage = float(open_circuit_voltage[0])
else:
open_circuit_voltage = float(open_circuit_voltage)
except Exception as e:
print(f"读取开路电压失败: {e}")
open_circuit_voltage = 0.0
# 处理极片质量 - 确保是数值类型
try:
pole_weight = self.data_pole_weight
if isinstance(pole_weight, (list, tuple)) and len(pole_weight) > 0:
pole_weight = float(pole_weight[0])
else:
pole_weight = float(pole_weight)
except Exception as e:
print(f"读取正极片重量失败: {e}")
pole_weight = 0.0
battery_info = {
"battery_index": coin_num_N + 1,
"battery_barcode": battery_qr_code,
"electrolyte_barcode": electrolyte_qr_code,
"open_circuit_voltage": open_circuit_voltage,
"pole_weight": pole_weight,
"assembly_time": self.data_assembly_time,
"assembly_pressure": self.data_assembly_pressure,
"electrolyte_volume": self.data_electrolyte_volume
}
battery_data_list.append(battery_info)
print(f"已收集第 {coin_num_N + 1} 个电池数据: 电池码={battery_info['battery_barcode']}, 电解液码={battery_info['electrolyte_barcode']}")
time.sleep(1)
# TODO:读完再将电池数加一还是进入循环就将电池数加一需要考虑
# 生成断点文件
# 生成包含elec_num_N、coin_num_N、timestamp的CSV文件
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
@@ -960,8 +1316,284 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
os.remove(summary_csv_file)
#全部完成后等待依华发送完成信号
self.func_pack_send_finished_cmd()
# 返回JSON格式数据
result = {
"success": True,
"total_batteries": len(battery_data_list),
"batteries": battery_data_list,
"summary": {
"electrolyte_bottles_used": elec_num,
"batteries_per_bottle": elec_use_num,
"electrolyte_volume": elec_vol,
"assembly_type": assembly_type,
"assembly_pressure": assembly_pressure
}
}
print(f"\n{'='*60}")
print(f"组装完成统计:")
print(f" 总组装电池数: {result['total_batteries']}")
print(f" 使用电解液瓶数: {elec_num}")
print(f" 每瓶电池数: {elec_use_num}")
print(f"{'='*60}\n")
return result
def func_allpack_cmd_simp(
self,
elec_num,
elec_use_num,
elec_vol: int = 50,
# 电解液双滴模式参数
dual_drop_mode: bool = False,
dual_drop_first_volume: int = 25,
dual_drop_suction_timing: bool = False,
dual_drop_start_timing: bool = False,
assembly_type: int = 7,
assembly_pressure: int = 4200,
# 来自原 qiming_coin_cell_code 的参数
fujipian_panshu: int = 0,
fujipian_juzhendianwei: int = 0,
gemopanshu: int = 0,
gemo_juzhendianwei: int = 0,
qiangtou_juzhendianwei: int = 0,
lvbodian: bool = True,
battery_pressure_mode: bool = True,
battery_clean_ignore: bool = False,
file_path: str = "/Users/sml/work"
) -> Dict[str, Any]:
"""
简化版电池组装函数,整合了原 qiming_coin_cell_code 的参数设置和双滴模式
此函数是 func_allpack_cmd 的增强版本,自动处理以下配置:
- 负极片和隔膜的盘数及矩阵点位
- 枪头盒矩阵点位
- 铝箔垫片使用设置
- 压力模式和清洁忽略选项
- 电解液双滴模式(分两次滴液)
Args:
elec_num: 电解液瓶数
elec_use_num: 每瓶电解液组装的电池数
elec_vol: 电解液吸液量 (μL)
dual_drop_mode: 电解液添加模式 (False=单次滴液, True=二次滴液)
dual_drop_first_volume: 二次滴液第一次排液体积 (μL)
dual_drop_suction_timing: 二次滴液吸液时机 (False=正常吸液, True=先吸液)
dual_drop_start_timing: 二次滴液开始滴液时机 (False=正极片前, True=正极片后)
assembly_type: 组装类型 (7=不用铝箔垫, 8=使用铝箔垫)
assembly_pressure: 电池压制力 (N)
fujipian_panshu: 负极片盘数
fujipian_juzhendianwei: 负极片矩阵点位
gemopanshu: 隔膜盘数
gemo_juzhendianwei: 隔膜矩阵点位
qiangtou_juzhendianwei: 枪头盒矩阵点位
lvbodian: 是否使用铝箔垫片
battery_pressure_mode: 是否启用压力模式
battery_clean_ignore: 是否忽略电池清洁
file_path: 实验记录保存路径
Returns:
dict: 包含组装结果的字典
"""
# 参数类型转换
elec_num = int(elec_num)
elec_use_num = int(elec_use_num)
elec_vol = int(elec_vol)
dual_drop_first_volume = int(dual_drop_first_volume)
assembly_type = int(assembly_type)
assembly_pressure = int(assembly_pressure)
fujipian_panshu = int(fujipian_panshu)
fujipian_juzhendianwei = int(fujipian_juzhendianwei)
gemopanshu = int(gemopanshu)
gemo_juzhendianwei = int(gemo_juzhendianwei)
qiangtou_juzhendianwei = int(qiangtou_juzhendianwei)
# 步骤1: 设置设备参数(原 qiming_coin_cell_code 的功能)
logger.info("=" * 60)
logger.info("设置设备参数...")
logger.info(f" 负极片盘数: {fujipian_panshu}, 矩阵点位: {fujipian_juzhendianwei}")
logger.info(f" 隔膜盘数: {gemopanshu}, 矩阵点位: {gemo_juzhendianwei}")
logger.info(f" 枪头盒矩阵点位: {qiangtou_juzhendianwei}")
logger.info(f" 铝箔垫片: {lvbodian}, 压力模式: {battery_pressure_mode}")
logger.info(f" 压制力: {assembly_pressure}")
logger.info(f" 忽略电池清洁: {battery_clean_ignore}")
logger.info("=" * 60)
# 写入基础参数到PLC
self.client.use_node('REG_MSG_NE_PLATE_NUM').write(fujipian_panshu)
self.client.use_node('REG_MSG_NE_PLATE_MATRIX').write(fujipian_juzhendianwei)
self.client.use_node('REG_MSG_SEPARATOR_PLATE_NUM').write(gemopanshu)
self.client.use_node('REG_MSG_SEPARATOR_PLATE_MATRIX').write(gemo_juzhendianwei)
self.client.use_node('REG_MSG_TIP_BOX_MATRIX').write(qiangtou_juzhendianwei)
self.client.use_node('COIL_ALUMINUM_FOIL').write(not lvbodian)
self.client.use_node('REG_MSG_PRESS_MODE').write(not battery_pressure_mode)
self.client.use_node('REG_MSG_BATTERY_CLEAN_IGNORE').write(battery_clean_ignore)
# 设置电解液双滴模式参数
self.client.use_node('COIL_ELECTROLYTE_DUAL_DROP_MODE').write(dual_drop_mode)
self.client.use_node('REG_MSG_DUAL_DROP_FIRST_VOLUME').write(dual_drop_first_volume)
self.client.use_node('COIL_DUAL_DROP_SUCTION_TIMING').write(dual_drop_suction_timing)
self.client.use_node('COIL_DUAL_DROP_START_TIMING').write(dual_drop_start_timing)
if dual_drop_mode:
logger.info(f"✓ 双滴模式已启用: 第一次排液={dual_drop_first_volume}μL, "
f"吸液时机={'先吸液' if dual_drop_suction_timing else '正常吸液'}, "
f"滴液时机={'正极片后' if dual_drop_start_timing else '正极片前'}")
else:
logger.info("✓ 单次滴液模式")
logger.info("✓ 设备参数设置完成")
# 步骤2: 执行组装流程(复用 func_allpack_cmd 的主体逻辑)
summary_csv_file = os.path.join(file_path, "duandian.csv")
# 用于收集所有电池的数据
battery_data_list = []
# 如果断点文件存在,先读取之前的进度
if os.path.exists(summary_csv_file):
read_status_flag = True
with open(summary_csv_file, 'r', newline='', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
header = next(reader) # 跳过标题行
data_row = next(reader) # 读取数据行
if len(data_row) >= 2:
elec_num_r = int(data_row[0])
elec_use_num_r = int(data_row[1])
elec_num_N = int(data_row[2])
elec_use_num_N = int(data_row[3])
coin_num_N = int(data_row[4])
if elec_num_r == elec_num and elec_use_num_r == elec_use_num:
print("断点文件与当前任务匹配,继续")
else:
print("断点文件中elec_num、elec_use_num与当前任务不匹配请检查任务下发参数或修改断点文件")
return {
"success": False,
"error": "断点文件参数不匹配",
"total_batteries": 0,
"batteries": []
}
print(f"从断点文件读取进度: elec_num_N={elec_num_N}, elec_use_num_N={elec_use_num_N}, coin_num_N={coin_num_N}")
else:
read_status_flag = False
print("未找到断点文件,从头开始")
elec_num_N = 0
elec_use_num_N = 0
coin_num_N = 0
for i in range(20):
print(f"剩余电解液瓶数: {elec_num}, 已组装电池数: {elec_use_num}")
print(f"剩余电解液瓶数: {type(elec_num)}, 已组装电池数: {type(elec_use_num)}")
print(f"剩余电解液瓶数: {type(int(elec_num))}, 已组装电池数: {type(int(elec_use_num))}")
last_i = elec_num_N
last_j = elec_use_num_N
for i in range(last_i, elec_num):
print(f"开始第{last_i+i+1}瓶电解液的组装")
# 第一个循环从上次断点继续后续循环从0开始
j_start = last_j if i == last_i else 0
self.func_pack_send_msg_cmd(elec_use_num-j_start, elec_vol, assembly_type, assembly_pressure)
for j in range(j_start, elec_use_num):
print(f"开始第{last_i+i+1}瓶电解液的第{j+j_start+1}个电池组装")
# 读取电池组装数据并存入csv
self.func_pack_get_msg_cmd(file_path)
# 收集当前电池的数据
try:
battery_qr_code = self.data_coin_cell_code
except Exception as e:
print(f"读取电池二维码失败: {e}")
battery_qr_code = "N/A"
try:
electrolyte_qr_code = self.data_electrolyte_code
except Exception as e:
print(f"读取电解液二维码失败: {e}")
electrolyte_qr_code = "N/A"
try:
open_circuit_voltage = self.data_open_circuit_voltage
if isinstance(open_circuit_voltage, (list, tuple)) and len(open_circuit_voltage) > 0:
open_circuit_voltage = float(open_circuit_voltage[0])
else:
open_circuit_voltage = float(open_circuit_voltage)
except Exception as e:
print(f"读取开路电压失败: {e}")
open_circuit_voltage = 0.0
try:
pole_weight = self.data_pole_weight
if isinstance(pole_weight, (list, tuple)) and len(pole_weight) > 0:
pole_weight = float(pole_weight[0])
else:
pole_weight = float(pole_weight)
except Exception as e:
print(f"读取正极片重量失败: {e}")
pole_weight = 0.0
battery_info = {
"battery_index": coin_num_N + 1,
"battery_barcode": battery_qr_code,
"electrolyte_barcode": electrolyte_qr_code,
"open_circuit_voltage": open_circuit_voltage,
"pole_weight": pole_weight,
"assembly_time": self.data_assembly_time,
"assembly_pressure": self.data_assembly_pressure,
"electrolyte_volume": self.data_electrolyte_volume
}
battery_data_list.append(battery_info)
print(f"已收集第 {coin_num_N + 1} 个电池数据: 电池码={battery_info['battery_barcode']}, 电解液码={battery_info['electrolyte_barcode']}")
time.sleep(1)
# 生成断点文件
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
with open(summary_csv_file, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['elec_num','elec_use_num', 'elec_num_N', 'elec_use_num_N', 'coin_num_N', 'timestamp'])
writer.writerow([elec_num, elec_use_num, elec_num_N, elec_use_num_N, coin_num_N, timestamp])
csvfile.flush()
coin_num_N += 1
self.coin_num_N = coin_num_N
elec_use_num_N += 1
elec_num_N += 1
elec_use_num_N = 0
# 循环正常结束,则删除断点文件
os.remove(summary_csv_file)
# 全部完成后等待依华发送完成信号
self.func_pack_send_finished_cmd()
# 返回JSON格式数据
result = {
"success": True,
"total_batteries": len(battery_data_list),
"batteries": battery_data_list,
"summary": {
"electrolyte_bottles_used": elec_num,
"batteries_per_bottle": elec_use_num,
"electrolyte_volume": elec_vol,
"assembly_type": assembly_type,
"assembly_pressure": assembly_pressure,
"dual_drop_mode": dual_drop_mode
}
}
print(f"\n{'='*60}")
print(f"组装完成统计:")
print(f" 总组装电池数: {result['total_batteries']}")
print(f" 使用电解液瓶数: {elec_num}")
print(f" 每瓶电池数: {elec_use_num}")
print(f" 双滴模式: {'启用' if dual_drop_mode else '禁用'}")
print(f"{'='*60}\n")
return result
def func_pack_device_stop(self) -> bool:
"""打包指令:设备停止"""
for i in range(3):

View File

@@ -0,0 +1,159 @@
Name,DataType,Comment,DeviceType,Address,,
COIL_SYS_START_CMD,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8010,,
COIL_SYS_STOP_CMD,BOOL,<EFBFBD>豸ֹͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8020,,
COIL_SYS_RESET_CMD,BOOL,<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8030,,
COIL_SYS_HAND_CMD,BOOL,<EFBFBD><EFBFBD>ֶ<EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8040,,
COIL_SYS_AUTO_CMD,BOOL,<EFBFBD><EFBFBD>Զ<EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8050,,
COIL_SYS_INIT_CMD,BOOL,<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8060,,
COIL_SYS_STOP_STATUS,BOOL,<EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>,coil,8220,,
,,,,,,
,BOOL,UNILAB<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Һƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8720,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>Һƿ<EFBFBD><EFBFBD>,coil,8520,,
REG_MSG_ELECTROLYTE_NUM,WORD,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һʹ<EFBFBD><EFBFBD>ƿ<EFBFBD><EFBFBD>,hold_register,496,,
,WORD,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD>̾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ0<EFBFBD><EFBFBD>,hold_register,440,,
,WORD,<EFBFBD><EFBFBD>Ĥ<EFBFBD>̾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ0<EFBFBD><EFBFBD>,hold_register,450,,
,WORD,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һƿ<EFBFBD><EFBFBD>_<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ0<EFBFBD><EFBFBD>,hold_register,460,,
,WORD,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һƿ<EFBFBD><EFBFBD>_<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>վ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ0<EFBFBD><EFBFBD>,hold_register,430,,
,WORD,g_<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һƿ<EFBFBD><EFBFBD>_<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸˸׾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ0<EFBFBD><EFBFBD>,hold_register,470,,
,WORD,<EFBFBD><EFBFBD>Һǹͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ0<EFBFBD><EFBFBD>,hold_register,480,,
,WORD,<EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,443,,
,WORD,<EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD>Ĥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,453,,
,,,,,,
COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,UNILAB<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8700,,
COIL_REQUEST_REC_MSG_STATUS,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8500,,
REG_MSG_ELECTROLYTE_USE_NUM,INT16,<EFBFBD><EFBFBD>ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һʹ<EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>,hold_register,11000,,
REG_MSG_ELECTROLYTE_VOLUME,INT16,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>,hold_register,11004,,
REG_MSG_ASSEMBLY_PRESSURE,INT16,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,11008,,
REG_DATA_ELECTROLYTE_CODE,STRING,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>,hold_register,10020,,
,BOOL,<EFBFBD>Ӿ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8300,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD>죨false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8310,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>_<EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8320,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>_<EFBFBD>Ҳ֣<EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8420,,
,BOOL,<EFBFBD><EFBFBD>е<EFBFBD>ְ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8330,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8340,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>֪<EFBFBD><EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8350,,
,BOOL,ѹ<EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>false:ѹ<><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>True:<3A><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>,coil,8360,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>false:<3A><><EFBFBD>ε<EFBFBD>Һ<EFBFBD><D2BA>true:<3A><><EFBFBD>ε<EFBFBD>Һ<EFBFBD><D2BA>,coil,8370,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8380,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>false:<3A><>װ<EFBFBD><D7B0>true:<3A><>װ<EFBFBD><D7B0>,coil,8390,,
,BOOL,ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣨfalse:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8400,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰<EFBFBD><EFBFBD>̷<EFBFBD>ʽ<EFBFBD><EFBFBD>false:ˮƽ<CBAE><C6BD><EFBFBD>̣<EFBFBD>true:<3A>ѵ<EFBFBD><D1B5><EFBFBD><EFBFBD>̣<EFBFBD>,coil,8410,,
COIL_SYS_UNILAB_INTERACT ,BOOL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Unilab<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>false:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,coil,8450,,
,BOOL,<EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣨfalse:ʹ<>ã<EFBFBD>true:<3A><><EFBFBD>ԣ<EFBFBD>,colil,8460,,
,,,,,,
COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,UNILAB<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8510,,
COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,UNILAB<EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,8710,,
REG_DATA_POLE_WEIGHT,FLOAT32,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,10010,,
REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װʱ<EFBFBD><EFBFBD>,hold_register,10012,,
REG_DATA_ASSEMBLY_PRESSURE,INT16,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,10014,,
REG_DATA_ELECTROLYTE_VOLUME,INT16,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>,hold_register,10016,,
REG_DATA_ASSEMBLY_TYPE,INT16,<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD>ʽ(7/8),hold_register,10018,,
REG_DATA_ELECTROLYTE_CODE,STRING,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>,hold_register,10020,,
REG_DATA_COIN_CELL_CODE,STRING,<EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>,hold_register,10030,,
REG_DATA_STACK_VISON_CODE,STRING,<EFBFBD><EFBFBD><EFBFBD>϶ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼƬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,10040,,
REG_DATA_ELECTROLYTE_USE_NUM,INT16,<EFBFBD><EFBFBD>ǰ<EFBFBD>缫Һ<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10000,,
REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,10002,,
,INT,<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ϼĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1-<2D><><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD>2-<2D><><EFBFBD>桢3-<2D><><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC>4-<2D><>Ĥ<EFBFBD><C4A4>5-<2D><><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC>6-ƽ<>桢7-<2D><><EFBFBD>桢8-<2D><><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>,hold_register,10060,,
,,,,,,
,INT,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10062,PLC<EFBFBD><EFBFBD>ַ,1223-<2D><><EFBFBD><EFBFBD>
,INT,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>Ĥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10064,,
,INT,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ״̬<EFBFBD>루R<EFBFBD><EFBFBD>,hold_register,10066,,
,REAL,<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ѹOK<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10068,,
,REAL,<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ѹOK<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10070,,
,INT,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10072,,
,INT,<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,10074,,
,REAL,10mm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,520,HMI<EFBFBD><EFBFBD>ַ,
,REAL,12mm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,522,,
,REAL,16mm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,524,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,526,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,528,,
,REAL,ƽ<EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,530,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,532,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,534,,
,REAL,<EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,536,,
,REAL,<EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>NG<EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><EFBFBD>,hold_register,538,,
,,,,,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>10mm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,540,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>12mm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,542,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>16mm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,544,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,546,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,548,,
,REAL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,550,,
,REAL,<EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,552,,
,REAL,<EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,554,,
,REAL,<EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD>غ<EFBFBD><EFBFBD>ȣ<EFBFBD>W<EFBFBD><EFBFBD>,hold_register,556,,
,,,,,,
,,,,,,
REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>,hold_register,10050,,
REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˮ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,10052,,
REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,hold_register,10054,,
,,,,,,
,BOOL,<EFBFBD>쳣100-ϵͳ<CFB5>,coil,1000,,
,BOOL,<EFBFBD>쳣101-<2D><>ͣ,coil,1010,,
,BOOL,<EFBFBD>쳣111-<2D><><EFBFBD><EFBFBD><EFBFBD>伱ͣ,coil,1110,,
,BOOL,<EFBFBD>쳣112-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD>դ<EFBFBD>ڵ<EFBFBD>,coil,1120,,
,BOOL,<EFBFBD>쳣160-<2D><>Һǹͷȱ<CDB7><C8B1>,coil,1600,,
,BOOL,<EFBFBD>쳣161-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1>,coil,1610,,
,BOOL,<EFBFBD>쳣162-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1>,coil,1620,,
,BOOL,<EFBFBD>쳣163-<2D><><EFBFBD><EFBFBD>Ƭȱ<C6AC><C8B1>,coil,1630,,
,BOOL,<EFBFBD>쳣164-<2D><>Ĥȱ<C4A4><C8B1>,coil,1640,,
,BOOL,<EFBFBD>쳣165-<2D><><EFBFBD><EFBFBD>Ƭȱ<C6AC><C8B1>,coil,1650,,
,BOOL,<EFBFBD>쳣166-ƽ<><C6BD>ȱ<EFBFBD><C8B1>,coil,1660,,
,BOOL,<EFBFBD>쳣167-<2D><><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1>,coil,1670,,
,BOOL,<EFBFBD>쳣168-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1>,coil,1680,,
,BOOL,<EFBFBD>쳣169-<2D><>Ʒ<EFBFBD><C6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,1690,,
,BOOL,<EFBFBD>쳣201-<2D>ŷ<EFBFBD><C5B7><EFBFBD>01<30>,coil,2010,,
,BOOL,<EFBFBD>쳣202-<2D>ŷ<EFBFBD><C5B7><EFBFBD>02<30>,coil,2020,,
,BOOL,<EFBFBD>쳣203-<2D>ŷ<EFBFBD><C5B7><EFBFBD>03<30>,coil,2030,,
,BOOL,<EFBFBD>쳣204-<2D>ŷ<EFBFBD><C5B7><EFBFBD>04<30>,coil,2040,,
,BOOL,<EFBFBD>쳣205-<2D>ŷ<EFBFBD><C5B7><EFBFBD>05<30>,coil,2050,,
,BOOL,<EFBFBD>쳣206-<2D>ŷ<EFBFBD><C5B7><EFBFBD>06<30>,coil,2060,,
,BOOL,<EFBFBD>쳣207-<2D>ŷ<EFBFBD><C5B7><EFBFBD>07<30>,coil,2070,,
,BOOL,<EFBFBD>쳣208-<2D>ŷ<EFBFBD><C5B7><EFBFBD>08<30>,coil,2080,,
,BOOL,<EFBFBD>쳣209-<2D>ŷ<EFBFBD><C5B7><EFBFBD>09<30>,coil,2090,,
,BOOL,<EFBFBD>쳣210-<2D>ŷ<EFBFBD><C5B7><EFBFBD>10<31>,coil,2100,,
,BOOL,<EFBFBD>쳣211-<2D>ŷ<EFBFBD><C5B7><EFBFBD>11<31>,coil,2110,,
,BOOL,<EFBFBD>쳣212-<2D>ŷ<EFBFBD><C5B7><EFBFBD>12<31>,coil,2120,,
,BOOL,<EFBFBD>쳣213-<2D>ŷ<EFBFBD><C5B7><EFBFBD>13<31>,coil,2130,,
,BOOL,<EFBFBD>쳣214-<2D>ŷ<EFBFBD><C5B7><EFBFBD>14<31>,coil,2140,,
,BOOL,<EFBFBD>쳣250-<2D><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>,coil,2500,,
,BOOL,<EFBFBD>쳣251-<2D><>ҺǹͨѶ<CDA8>,coil,2510,,
,BOOL,<EFBFBD>쳣252-<2D><>Һǹ<D2BA><C7B9><EFBFBD><EFBFBD>,coil,2520,,
,BOOL,<EFBFBD>쳣256-<2D><>צ<EFBFBD>,coil,2560,,
,BOOL,<EFBFBD>쳣262-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ֪<CEB4><D6AA>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>,coil,2620,,
,BOOL,<EFBFBD>쳣263-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>X<EFBFBD><58>Y<EFBFBD><59>Z<EFBFBD><5A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,2630,,
,BOOL,<EFBFBD>쳣264-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӿ<EFBFBD><D3BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,2640,,
,BOOL,<EFBFBD>쳣265-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1#<23><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ʧ<EFBFBD><CAA7>,coil,2650,,
,BOOL,<EFBFBD>쳣266-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2#<23><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ʧ<EFBFBD><CAA7>,coil,2660,,
,BOOL,<EFBFBD>쳣267-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3#<23><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ʧ<EFBFBD><CAA7>,coil,2670,,
,BOOL,<EFBFBD>쳣268-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>4#<23><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ʧ<EFBFBD><CAA7>,coil,2680,,
,BOOL,<EFBFBD>쳣269-RB<52><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>,coil,2690,,
,BOOL,<EFBFBD>쳣280-RB<52><42>ײ<EFBFBD>,coil,2800,,
,BOOL,<EFBFBD>쳣290-<2D>Ӿ<EFBFBD>ϵͳͨѶ<CDA8>,coil,2900,,
,BOOL,<EFBFBD>쳣291-<2D>Ӿ<EFBFBD><D3BE><EFBFBD>λNG<4E>,coil,2910,,
,BOOL,<EFBFBD>쳣292-ɨ<><C9A8>ǹͨѶ<CDA8>,coil,2920,,
,BOOL,<EFBFBD>쳣310-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3100,,
,BOOL,<EFBFBD>쳣311-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3110,,
,BOOL,<EFBFBD>쳣312-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3120,,
,BOOL,<EFBFBD>쳣313-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3130,,
,BOOL,<EFBFBD>쳣340-<2D><>·<EFBFBD><C2B7>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3400,,
,BOOL,<EFBFBD>쳣342-<2D><>·<EFBFBD><C2B7>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3420,,
,BOOL,<EFBFBD>쳣344-<2D><>·<EFBFBD><C2B7>ѹ<EFBFBD><D1B9>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD>,coil,3440,,
,BOOL,<EFBFBD>쳣350-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3500,,
,BOOL,<EFBFBD>쳣352-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3520,,
,BOOL,<EFBFBD>쳣354-<2D><>ϴ<EFBFBD>޳<EFBFBD><DEB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3540,,
,BOOL,<EFBFBD>쳣356-<2D><>ϴ<EFBFBD>޳<EFBFBD><DEB3><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3560,,
,BOOL,<EFBFBD>쳣360-<2D><><EFBFBD><EFBFBD>Һƿ<D2BA><C6BF>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>,coil,3600,,
,BOOL,<EFBFBD>쳣362-<2D><>Һǹͷ<C7B9>ж<EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>,coil,3620,,
COIL ALARM_364_SERVO_DRIVE_ERROR,BOOL,<EFBFBD>쳣364-<2D>Լ<EFBFBD>ƿ<EFBFBD><C6BF>צ<EFBFBD><D7A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3640,,
COIL ALARM_367_SERVO_DRIVER_ERROR,BOOL,<EFBFBD>쳣366-<2D>Լ<EFBFBD>ƿ<EFBFBD><C6BF>צ<EFBFBD><D7A6><EFBFBD><EFBFBD><EFBFBD>,coil,3660,,
COIL ALARM_370_SERVO_MODULE_ERROR,BOOL,<EFBFBD>쳣370-ѹ<><D1B9>ģ<EFBFBD><EFBFBD><E9B4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,coil,3700,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
COIL + <20><><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>/<2F><><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д+<2B>»<EFBFBD><C2BB>߷ָ<DFB7><D6B8><EFBFBD>--<2D><><EFBFBD><EFBFBD>boolֵ,,,,,,
REG + <20><><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>/<2F><><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д+<2B>»<EFBFBD><C2BB>߷ָ<DFB7><D6B8><EFBFBD>--<2D><><EFBFBD>ԼĴ<D4BC><C4B4><EFBFBD>,,,,,,
1 Name DataType Comment DeviceType Address
2 COIL_SYS_START_CMD BOOL 设备启动命令 coil 8010
3 COIL_SYS_STOP_CMD BOOL 设备停止命令 coil 8020
4 COIL_SYS_RESET_CMD BOOL 设备复位命令 coil 8030
5 COIL_SYS_HAND_CMD BOOL 设备手动模式命令 coil 8040
6 COIL_SYS_AUTO_CMD BOOL 设备自动模式命令 coil 8050
7 COIL_SYS_INIT_CMD BOOL 设备初始化模式命令 coil 8060
8 COIL_SYS_STOP_STATUS BOOL 设备暂停中 coil 8220
9
10 BOOL UNILAB发送电解液瓶数完毕 coil 8720
11 BOOL 设备请求接受电解液瓶数 coil 8520
12 REG_MSG_ELECTROLYTE_NUM WORD 电解液使用瓶数 hold_register 496
13 WORD 负极片盘矩阵点位(初始位0) hold_register 440
14 WORD 隔膜盘矩阵点位(初始位0) hold_register 450
15 WORD 电解液瓶盘_缓存上料矩阵点位(初始位0) hold_register 460
16 WORD 电解液瓶盘_缓存回收矩阵点位(初始位0) hold_register 430
17 WORD g_电解液瓶盘_手套箱无杆缸矩阵点位(初始位0) hold_register 470
18 WORD 移液枪头矩阵点位(初始位0) hold_register 480
19 WORD 设置负极片盘数 hold_register 443
20 WORD 设置隔膜盘数 hold_register 453
21
22 COIL_UNILAB_SEND_MSG_SUCC_CMD BOOL UNILAB发送配方完毕 coil 8700
23 COIL_REQUEST_REC_MSG_STATUS BOOL 设备请求接受配方 coil 8500
24 REG_MSG_ELECTROLYTE_USE_NUM INT16 单瓶电解液使用次数 hold_register 11000
25 REG_MSG_ELECTROLYTE_VOLUME INT16 电解液吸取量 hold_register 11004
26 REG_MSG_ASSEMBLY_PRESSURE INT16 电池组装压制力 hold_register 11008
27 REG_DATA_ELECTROLYTE_CODE STRING 电解液二维码序列号 hold_register 10020
28 BOOL 视觉对位(false:使用,true:忽略) coil 8300
29 BOOL 复检(false:使用,true:忽略) coil 8310
30 BOOL 手套箱_左仓(false:使用,true:忽略) coil 8320
31 BOOL 手套箱_右仓(false:使用,true:忽略) coil 8420
32 BOOL 机械手搬送料盘(false:使用,true:忽略) coil 8330
33 BOOL 铝箔物料(false:使用,true:忽略) coil 8340
34 BOOL 真空检知(false:使用,true:忽略) coil 8350
35 BOOL 压制模式(false:压力检测模式,True:距离模式) coil 8360
36 BOOL 电解液添加模式(false:单次滴液,true:二次滴液) coil 8370
37 BOOL 正极片称重(false:使用,true:忽略) coil 8380
38 BOOL 正负极片组装方式(false:正装,true:倒装) coil 8390
39 BOOL 压制清洁(false:使用,true:忽略) coil 8400
40 BOOL 物料盘摆盘方式(false:水平摆盘,true:堆叠摆盘) coil 8410
41 COIL_SYS_UNILAB_INTERACT BOOL 忽略Unilab交互(false:使用,true:忽略) coil 8450
42 BOOL 忽略电池清洁(false:使用,true:忽略) colil 8460
43
44 COIL_UNILAB_SEND_MSG_SUCC_CMD BOOL UNILAB发送配方完毕 coil 8510
45 COIL_UNILAB_REC_MSG_SUCC_CMD BOOL UNILAB接受测试数据完毕 coil 8710
46 REG_DATA_POLE_WEIGHT FLOAT32 当前电池正极片称重数据 hold_register 10010
47 REG_DATA_ASSEMBLY_PER_TIME FLOAT32 当前单颗电池组装时间 hold_register 10012
48 REG_DATA_ASSEMBLY_PRESSURE INT16 当前电池组装压制力 hold_register 10014
49 REG_DATA_ELECTROLYTE_VOLUME INT16 当前电解液加注量 hold_register 10016
50 REG_DATA_ASSEMBLY_TYPE INT16 组装参数:极片堆叠方式(7/8) hold_register 10018
51 REG_DATA_ELECTROLYTE_CODE STRING 电解液二维码序列号 hold_register 10020
52 REG_DATA_COIN_CELL_CODE STRING 电池二维码序列号 hold_register 10030
53 REG_DATA_STACK_VISON_CODE STRING 物料堆叠复检图片编码 hold_register 10040
54 REG_DATA_ELECTROLYTE_USE_NUM INT16 当前电极液组装电池数量(R) hold_register 10000
55 REG_DATA_OPEN_CIRCUIT_VOLTAGE FLOAT32 当前电池电压数据 hold_register 10002
56 INT 机械手吸取物料寄存器(1-正极壳、2-铝垫、3-正极片、4-隔膜、5-负极片、6-平垫、7-弹垫、8-负极壳) hold_register 10060
57
58 INT 当前负极片剩余盘数量(R) hold_register 10062 PLC地址 1223-新增
59 INT 当前隔膜神域盘数量(R) hold_register 10064
60 INT 电解液状态码(R) hold_register 10066
61 REAL 开路电压OK下限值(R) hold_register 10068
62 REAL 开路电压OK上限值(R) hold_register 10070
63 INT 当前进行组装电池数量(R) hold_register 10072
64 INT 当前完成组装电池数量(R) hold_register 10074
65 REAL 10mm正极片剩余物料数量(R) hold_register 520 HMI地址
66 REAL 12mm正极片剩余物料数量(R) hold_register 522
67 REAL 16mm正极片剩余物料数量(R) hold_register 524
68 REAL 铝箔剩余物料数量(R) hold_register 526
69 REAL 正极壳剩余物料数量(R) hold_register 528
70 REAL 平垫剩余物料数量(R) hold_register 530
71 REAL 负极壳剩余物料数量(R) hold_register 532
72 REAL 弹垫剩余物料数量(R) hold_register 534
73 REAL 成品电池剩余可容纳数量(R) hold_register 536
74 REAL 成品电池NG槽剩余可容纳数量(R) hold_register 538
75
76 REAL 设置10mm正极片厚度(W) hold_register 540
77 REAL 设置12mm正极片厚度(W) hold_register 542
78 REAL 设置16mm正极片厚度(W) hold_register 544
79 REAL 设置铝箔厚度(W) hold_register 546
80 REAL 设置正极壳厚度(W) hold_register 548
81 REAL 设置平垫厚度(W) hold_register 550
82 REAL 设置负极壳厚度(W) hold_register 552
83 REAL 设置弹垫厚度(W) hold_register 554
84 REAL 设置成品电池厚度(W) hold_register 556
85
86
87 REG_DATA_GLOVE_BOX_PRESSURE FLOAT32 手套箱压力 hold_register 10050
88 REG_DATA_GLOVE_BOX_WATER_CONTENT FLOAT32 手套箱水含量 hold_register 10052
89 REG_DATA_GLOVE_BOX_O2_CONTENT FLOAT32 手套箱氧含量 hold_register 10054
90
91 BOOL 异常100-系统异常 coil 1000
92 BOOL 异常101-急停 coil 1010
93 BOOL 异常111-手套箱急停 coil 1110
94 BOOL 异常112-手套箱内光栅遮挡 coil 1120
95 BOOL 异常160-移液枪头缺料 coil 1600
96 BOOL 异常161-正极壳缺料 coil 1610
97 BOOL 异常162-铝箔垫缺料 coil 1620
98 BOOL 异常163-正极片缺料 coil 1630
99 BOOL 异常164-隔膜缺料 coil 1640
100 BOOL 异常165-负极片缺料 coil 1650
101 BOOL 异常166-平垫缺料 coil 1660
102 BOOL 异常167-弹垫缺料 coil 1670
103 BOOL 异常168-负极壳缺料 coil 1680
104 BOOL 异常169-成品电池满料 coil 1690
105 BOOL 异常201-伺服轴01异常 coil 2010
106 BOOL 异常202-伺服轴02异常 coil 2020
107 BOOL 异常203-伺服轴03异常 coil 2030
108 BOOL 异常204-伺服轴04异常 coil 2040
109 BOOL 异常205-伺服轴05异常 coil 2050
110 BOOL 异常206-伺服轴06异常 coil 2060
111 BOOL 异常207-伺服轴07异常 coil 2070
112 BOOL 异常208-伺服轴08异常 coil 2080
113 BOOL 异常209-伺服轴09异常 coil 2090
114 BOOL 异常210-伺服轴10异常 coil 2100
115 BOOL 异常211-伺服轴11异常 coil 2110
116 BOOL 异常212-伺服轴12异常 coil 2120
117 BOOL 异常213-伺服轴13异常 coil 2130
118 BOOL 异常214-伺服轴14异常 coil 2140
119 BOOL 异常250-其他元件异常 coil 2500
120 BOOL 异常251-移液枪通讯异常 coil 2510
121 BOOL 异常252-移液枪报警 coil 2520
122 BOOL 异常256-电爪异常 coil 2560
123 BOOL 异常262-RB报警:未知点位错误 coil 2620
124 BOOL 异常263-RB报警:X、Y、Z参数超限制 coil 2630
125 BOOL 异常264-RB报警:视觉参数误差过大 coil 2640
126 BOOL 异常265-RB报警:1#吸嘴取料失败 coil 2650
127 BOOL 异常266-RB报警:2#吸嘴取料失败 coil 2660
128 BOOL 异常267-RB报警:3#吸嘴取料失败 coil 2670
129 BOOL 异常268-RB报警:4#吸嘴取料失败 coil 2680
130 BOOL 异常269-RB报警:取物料盘失败 coil 2690
131 BOOL 异常280-RB碰撞异常 coil 2800
132 BOOL 异常290-视觉系统通讯异常 coil 2900
133 BOOL 异常291-视觉对位NG异常 coil 2910
134 BOOL 异常292-扫码枪通讯异常 coil 2920
135 BOOL 异常310-开电移载吸嘴吸真空异常 coil 3100
136 BOOL 异常311-开电移载吸嘴破真空异常 coil 3110
137 BOOL 异常312-称重移载吸嘴吸真空异常 coil 3120
138 BOOL 异常313-称重移载吸嘴破真空异常 coil 3130
139 BOOL 异常340-开路电压吸嘴移载气缸异常 coil 3400
140 BOOL 异常342-开路电压吸嘴升降气缸异常 coil 3420
141 BOOL 异常344-开路电压旋压气缸异常 coil 3440
142 BOOL 异常350-称重吸嘴移载气缸异常 coil 3500
143 BOOL 异常352-称重吸嘴升降气缸异常 coil 3520
144 BOOL 异常354-清洗无尘布移载气缸异常 coil 3540
145 BOOL 异常356-清洗无尘布压紧气缸异常 coil 3560
146 BOOL 异常360-电解液瓶定位气缸异常 coil 3600
147 BOOL 异常362-移液枪头盒定位气缸异常 coil 3620
148 COIL ALARM_364_SERVO_DRIVE_ERROR BOOL 异常364-试剂瓶夹爪升降气缸异常 coil 3640
149 COIL ALARM_367_SERVO_DRIVER_ERROR BOOL 异常366-试剂瓶夹爪气缸异常 coil 3660
150 COIL ALARM_370_SERVO_MODULE_ERROR BOOL 异常370-压制模块吹气气缸异常 coil 3700
151
152
153
154
155
156
157
158 COIL + 功能模块/类型 + 具体描述(大写+下划线分隔)--针对bool值
159 REG + 功能模块/类型 + 具体描述(大写+下划线分隔)--针对寄存器

View File

@@ -1,64 +0,0 @@
Name,DataType,InitValue,Comment,Attribute,DeviceType,Address,
COIL_SYS_START_CMD,BOOL,,,,coil,8010,
COIL_SYS_STOP_CMD,BOOL,,,,coil,8020,
COIL_SYS_RESET_CMD,BOOL,,,,coil,8030,
COIL_SYS_HAND_CMD,BOOL,,,,coil,8040,
COIL_SYS_AUTO_CMD,BOOL,,,,coil,8050,
COIL_SYS_INIT_CMD,BOOL,,,,coil,8060,
COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,,,,coil,8700,
COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,,,,coil,8710,unilab_rec_msg_succ_cmd
COIL_SYS_START_STATUS,BOOL,,,,coil,8210,
COIL_SYS_STOP_STATUS,BOOL,,,,coil,8220,
COIL_SYS_RESET_STATUS,BOOL,,,,coil,8230,
COIL_SYS_HAND_STATUS,BOOL,,,,coil,8240,
COIL_SYS_AUTO_STATUS,BOOL,,,,coil,8250,
COIL_SYS_INIT_STATUS,BOOL,,,,coil,8260,
COIL_REQUEST_REC_MSG_STATUS,BOOL,,,,coil,8500,
COIL_REQUEST_SEND_MSG_STATUS,BOOL,,,,coil,8510,request_send_msg_status
REG_MSG_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,11000,
REG_MSG_ELECTROLYTE_NUM,INT16,,,,hold_register,11002,unilab_send_msg_electrolyte_num
REG_MSG_ELECTROLYTE_VOLUME,INT16,,,,hold_register,11004,unilab_send_msg_electrolyte_vol
REG_MSG_ASSEMBLY_TYPE,INT16,,,,hold_register,11006,unilab_send_msg_assembly_type
REG_MSG_ASSEMBLY_PRESSURE,INT16,,,,hold_register,11008,unilab_send_msg_assembly_pressure
REG_DATA_ASSEMBLY_COIN_CELL_NUM,INT16,,,,hold_register,10000,data_assembly_coin_cell_num
REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,,,,hold_register,10002,data_open_circuit_voltage
REG_DATA_AXIS_X_POS,FLOAT32,,,,hold_register,10004,
REG_DATA_AXIS_Y_POS,FLOAT32,,,,hold_register,10006,
REG_DATA_AXIS_Z_POS,FLOAT32,,,,hold_register,10008,
REG_DATA_POLE_WEIGHT,FLOAT32,,,,hold_register,10010,data_pole_weight
REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,,,,hold_register,10012,data_assembly_time
REG_DATA_ASSEMBLY_PRESSURE,INT16,,,,hold_register,10014,data_assembly_pressure
REG_DATA_ELECTROLYTE_VOLUME,INT16,,,,hold_register,10016,data_electrolyte_volume
REG_DATA_COIN_NUM,INT16,,,,hold_register,10018,data_coin_num
REG_DATA_ELECTROLYTE_CODE,STRING,,,,hold_register,10020,data_electrolyte_code()
REG_DATA_COIN_CELL_CODE,STRING,,,,hold_register,10030,data_coin_cell_code()
REG_DATA_STACK_VISON_CODE,STRING,,,,hold_register,12004,data_stack_vision_code()
REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,,,,hold_register,10050,data_glove_box_pressure
REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,,,,hold_register,10052,data_glove_box_water_content
REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,,,,hold_register,10054,data_glove_box_o2_content
UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8720,
UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8520,
REG_MSG_ELECTROLYTE_NUM_USED,INT16,,,,hold_register,496,
REG_DATA_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,10000,
UNILAB_SEND_FINISHED_CMD,BOOL,,,,coil,8730,
UNILAB_RECE_FINISHED_CMD,BOOL,,,,coil,8530,
REG_DATA_ASSEMBLY_TYPE,INT16,,,,hold_register,10018,ASSEMBLY_TYPE7or8
COIL_ALUMINUM_FOIL,BOOL,,使用铝箔垫,,coil,8340,
REG_MSG_NE_PLATE_MATRIX,INT16,,负极片矩阵点位,,hold_register,440,
REG_MSG_SEPARATOR_PLATE_MATRIX,INT16,,隔膜矩阵点位,,hold_register,450,
REG_MSG_TIP_BOX_MATRIX,INT16,,移液枪头矩阵点位,,hold_register,480,
REG_MSG_NE_PLATE_NUM,INT16,,负极片盘数,,hold_register,443,
REG_MSG_SEPARATOR_PLATE_NUM,INT16,,隔膜盘数,,hold_register,453,
REG_MSG_PRESS_MODE,BOOL,,压制模式false:压力检测模式True:距离模式),,coil,8360,电池压制模式
,,,,,,,
,BOOL,,视觉对位false:使用true:忽略),,coil,8300,视觉对位
,BOOL,,复检false:使用true:忽略),,coil,8310,视觉复检
,BOOL,,手套箱_左仓false:使用true:忽略),,coil,8320,手套箱左仓
,BOOL,,手套箱_右仓false:使用true:忽略),,coil,8420,手套箱右仓
,BOOL,,真空检知false:使用true:忽略),,coil,8350,真空检知
,BOOL,,电解液添加模式false:单次滴液true:二次滴液),,coil,8370,滴液模式
,BOOL,,正极片称重false:使用true:忽略),,coil,8380,正极片称重
,BOOL,,正负极片组装方式false:正装true:倒装),,coil,8390,正负极反装
,BOOL,,压制清洁false:使用true:忽略),,coil,8400,压制清洁
,BOOL,,物料盘摆盘方式false:水平摆盘true:堆叠摆盘),,coil,8410,负极片摆盘方式
REG_MSG_BATTERY_CLEAN_IGNORE,BOOL,,忽略电池清洁false:使用true:忽略),,coil,8460,
1 Name DataType InitValue Comment Attribute DeviceType Address
2 COIL_SYS_START_CMD BOOL coil 8010
3 COIL_SYS_STOP_CMD BOOL coil 8020
4 COIL_SYS_RESET_CMD BOOL coil 8030
5 COIL_SYS_HAND_CMD BOOL coil 8040
6 COIL_SYS_AUTO_CMD BOOL coil 8050
7 COIL_SYS_INIT_CMD BOOL coil 8060
8 COIL_UNILAB_SEND_MSG_SUCC_CMD BOOL coil 8700
9 COIL_UNILAB_REC_MSG_SUCC_CMD BOOL coil 8710 unilab_rec_msg_succ_cmd
10 COIL_SYS_START_STATUS BOOL coil 8210
11 COIL_SYS_STOP_STATUS BOOL coil 8220
12 COIL_SYS_RESET_STATUS BOOL coil 8230
13 COIL_SYS_HAND_STATUS BOOL coil 8240
14 COIL_SYS_AUTO_STATUS BOOL coil 8250
15 COIL_SYS_INIT_STATUS BOOL coil 8260
16 COIL_REQUEST_REC_MSG_STATUS BOOL coil 8500
17 COIL_REQUEST_SEND_MSG_STATUS BOOL coil 8510 request_send_msg_status
18 REG_MSG_ELECTROLYTE_USE_NUM INT16 hold_register 11000
19 REG_MSG_ELECTROLYTE_NUM INT16 hold_register 11002 unilab_send_msg_electrolyte_num
20 REG_MSG_ELECTROLYTE_VOLUME INT16 hold_register 11004 unilab_send_msg_electrolyte_vol
21 REG_MSG_ASSEMBLY_TYPE INT16 hold_register 11006 unilab_send_msg_assembly_type
22 REG_MSG_ASSEMBLY_PRESSURE INT16 hold_register 11008 unilab_send_msg_assembly_pressure
23 REG_DATA_ASSEMBLY_COIN_CELL_NUM INT16 hold_register 10000 data_assembly_coin_cell_num
24 REG_DATA_OPEN_CIRCUIT_VOLTAGE FLOAT32 hold_register 10002 data_open_circuit_voltage
25 REG_DATA_AXIS_X_POS FLOAT32 hold_register 10004
26 REG_DATA_AXIS_Y_POS FLOAT32 hold_register 10006
27 REG_DATA_AXIS_Z_POS FLOAT32 hold_register 10008
28 REG_DATA_POLE_WEIGHT FLOAT32 hold_register 10010 data_pole_weight
29 REG_DATA_ASSEMBLY_PER_TIME FLOAT32 hold_register 10012 data_assembly_time
30 REG_DATA_ASSEMBLY_PRESSURE INT16 hold_register 10014 data_assembly_pressure
31 REG_DATA_ELECTROLYTE_VOLUME INT16 hold_register 10016 data_electrolyte_volume
32 REG_DATA_COIN_NUM INT16 hold_register 10018 data_coin_num
33 REG_DATA_ELECTROLYTE_CODE STRING hold_register 10020 data_electrolyte_code()
34 REG_DATA_COIN_CELL_CODE STRING hold_register 10030 data_coin_cell_code()
35 REG_DATA_STACK_VISON_CODE STRING hold_register 12004 data_stack_vision_code()
36 REG_DATA_GLOVE_BOX_PRESSURE FLOAT32 hold_register 10050 data_glove_box_pressure
37 REG_DATA_GLOVE_BOX_WATER_CONTENT FLOAT32 hold_register 10052 data_glove_box_water_content
38 REG_DATA_GLOVE_BOX_O2_CONTENT FLOAT32 hold_register 10054 data_glove_box_o2_content
39 UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM BOOL coil 8720
40 UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM BOOL coil 8520
41 REG_MSG_ELECTROLYTE_NUM_USED INT16 hold_register 496
42 REG_DATA_ELECTROLYTE_USE_NUM INT16 hold_register 10000
43 UNILAB_SEND_FINISHED_CMD BOOL coil 8730
44 UNILAB_RECE_FINISHED_CMD BOOL coil 8530
45 REG_DATA_ASSEMBLY_TYPE INT16 hold_register 10018 ASSEMBLY_TYPE7or8
46 COIL_ALUMINUM_FOIL BOOL 使用铝箔垫 coil 8340
47 REG_MSG_NE_PLATE_MATRIX INT16 负极片矩阵点位 hold_register 440
48 REG_MSG_SEPARATOR_PLATE_MATRIX INT16 隔膜矩阵点位 hold_register 450
49 REG_MSG_TIP_BOX_MATRIX INT16 移液枪头矩阵点位 hold_register 480
50 REG_MSG_NE_PLATE_NUM INT16 负极片盘数 hold_register 443
51 REG_MSG_SEPARATOR_PLATE_NUM INT16 隔膜盘数 hold_register 453
52 REG_MSG_PRESS_MODE BOOL 压制模式(false:压力检测模式,True:距离模式) coil 8360 电池压制模式
53
54 BOOL 视觉对位(false:使用,true:忽略) coil 8300 视觉对位
55 BOOL 复检(false:使用,true:忽略) coil 8310 视觉复检
56 BOOL 手套箱_左仓(false:使用,true:忽略) coil 8320 手套箱左仓
57 BOOL 手套箱_右仓(false:使用,true:忽略) coil 8420 手套箱右仓
58 BOOL 真空检知(false:使用,true:忽略) coil 8350 真空检知
59 BOOL 电解液添加模式(false:单次滴液,true:二次滴液) coil 8370 滴液模式
60 BOOL 正极片称重(false:使用,true:忽略) coil 8380 正极片称重
61 BOOL 正负极片组装方式(false:正装,true:倒装) coil 8390 正负极反装
62 BOOL 压制清洁(false:使用,true:忽略) coil 8400 压制清洁
63 BOOL 物料盘摆盘方式(false:水平摆盘,true:堆叠摆盘) coil 8410 负极片摆盘方式
64 REG_MSG_BATTERY_CLEAN_IGNORE BOOL 忽略电池清洁(false:使用,true:忽略) coil 8460

View File

@@ -0,0 +1,130 @@
Name,DataType,InitValue,Comment,Attribute,DeviceType,Address,
COIL_SYS_START_CMD,BOOL,,,,coil,8010,
COIL_SYS_STOP_CMD,BOOL,,,,coil,8020,
COIL_SYS_RESET_CMD,BOOL,,,,coil,8030,
COIL_SYS_HAND_CMD,BOOL,,,,coil,8040,
COIL_SYS_AUTO_CMD,BOOL,,,,coil,8050,
COIL_SYS_INIT_CMD,BOOL,,,,coil,8060,
COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,,,,coil,8700,
COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,,,,coil,8710,unilab_rec_msg_succ_cmd
COIL_SYS_START_STATUS,BOOL,,,,coil,8210,
COIL_SYS_STOP_STATUS,BOOL,,,,coil,8220,
COIL_SYS_RESET_STATUS,BOOL,,,,coil,8230,
COIL_SYS_HAND_STATUS,BOOL,,,,coil,8240,
COIL_SYS_AUTO_STATUS,BOOL,,,,coil,8250,
COIL_SYS_INIT_STATUS,BOOL,,,,coil,8260,
COIL_REQUEST_REC_MSG_STATUS,BOOL,,,,coil,8500,
COIL_REQUEST_SEND_MSG_STATUS,BOOL,,,,coil,8510,request_send_msg_status
REG_MSG_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,11000,
REG_MSG_ELECTROLYTE_NUM,INT16,,,,hold_register,11002,unilab_send_msg_electrolyte_num
REG_MSG_ELECTROLYTE_VOLUME,INT16,,,,hold_register,11004,unilab_send_msg_electrolyte_vol
REG_MSG_ASSEMBLY_TYPE,INT16,,,,hold_register,11006,unilab_send_msg_assembly_type
REG_MSG_ASSEMBLY_PRESSURE,INT16,,,,hold_register,11008,unilab_send_msg_assembly_pressure
REG_DATA_ASSEMBLY_COIN_CELL_NUM,INT16,,,,hold_register,10000,data_assembly_coin_cell_num
REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,,,,hold_register,10002,data_open_circuit_voltage
REG_DATA_AXIS_X_POS,FLOAT32,,,,hold_register,10004,
REG_DATA_AXIS_Y_POS,FLOAT32,,,,hold_register,10006,
REG_DATA_AXIS_Z_POS,FLOAT32,,,,hold_register,10008,
REG_DATA_POLE_WEIGHT,FLOAT32,,,,hold_register,10010,data_pole_weight
REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,,,,hold_register,10012,data_assembly_time
REG_DATA_ASSEMBLY_PRESSURE,INT16,,,,hold_register,10014,data_assembly_pressure
REG_DATA_ELECTROLYTE_VOLUME,INT16,,,,hold_register,10016,data_electrolyte_volume
REG_DATA_COIN_NUM,INT16,,,,hold_register,10018,data_coin_num
REG_DATA_ELECTROLYTE_CODE,STRING,,,,hold_register,10020,data_electrolyte_code()
REG_DATA_COIN_CELL_CODE,STRING,,,,hold_register,10030,data_coin_cell_code()
REG_DATA_STACK_VISON_CODE,STRING,,,,hold_register,12004,data_stack_vision_code()
REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,,,,hold_register,10050,data_glove_box_pressure
REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,,,,hold_register,10052,data_glove_box_water_content
REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,,,,hold_register,10054,data_glove_box_o2_content
UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8720,
UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8520,
REG_MSG_ELECTROLYTE_NUM_USED,INT16,,,,hold_register,496,
REG_DATA_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,10000,
UNILAB_SEND_FINISHED_CMD,BOOL,,,,coil,8730,
UNILAB_RECE_FINISHED_CMD,BOOL,,,,coil,8530,
REG_DATA_ASSEMBLY_TYPE,INT16,,,,hold_register,10018,ASSEMBLY_TYPE7or8
REG_UNILAB_INTERACT,BOOL,,,,coil,8450,
,,,,,coil,8320,
COIL_ALUMINUM_FOIL,BOOL,,,,coil,8340,
REG_MSG_NE_PLATE_MATRIX,INT16,,,,hold_register,440,
REG_MSG_SEPARATOR_PLATE_MATRIX,INT16,,,,hold_register,450,
REG_MSG_TIP_BOX_MATRIX,INT16,,,,hold_register,480,
REG_MSG_NE_PLATE_NUM,INT16,,,,hold_register,443,
REG_MSG_SEPARATOR_PLATE_NUM,INT16,,,,hold_register,453,
REG_MSG_PRESS_MODE,BOOL,,,,coil,8360,
,BOOL,,,,coil,8300,
,BOOL,,,,coil,8310,
COIL_GB_L_IGNORE_CMD,BOOL,,,,coil,8320,
COIL_GB_R_IGNORE_CMD,BOOL,,,,coil,8420,
,BOOL,,,,coil,8350,
COIL_ELECTROLYTE_DUAL_DROP_MODE,BOOL,,,,coil,8370,
,BOOL,,,,coil,8380,
,BOOL,,,,coil,8390,
,BOOL,,,,coil,8400,
,BOOL,,,,coil,8410,
REG_MSG_DUAL_DROP_FIRST_VOLUME,INT16,,,,hold_register,4001,
COIL_DUAL_DROP_SUCTION_TIMING,BOOL,,,,coil,8430,
COIL_DUAL_DROP_START_TIMING,BOOL,,,,coil,8470,
REG_MSG_BATTERY_CLEAN_IGNORE,BOOL,,,,coil,8460,
COIL_ALARM_100_SYSTEM_ERROR,BOOL,,,,coil,1000,异常100-系统异常
COIL_ALARM_101_EMERGENCY_STOP,BOOL,,,,coil,1010,异常101-急停
COIL_ALARM_111_GLOVEBOX_EMERGENCY_STOP,BOOL,,,,coil,1110,异常111-手套箱急停
COIL_ALARM_112_GLOVEBOX_GRATING_BLOCKED,BOOL,,,,coil,1120,异常112-手套箱内光栅遮挡
COIL_ALARM_160_PIPETTE_TIP_SHORTAGE,BOOL,,,,coil,1600,异常160-移液枪头缺料
COIL_ALARM_161_POSITIVE_SHELL_SHORTAGE,BOOL,,,,coil,1610,异常161-正极壳缺料
COIL_ALARM_162_ALUMINUM_FOIL_SHORTAGE,BOOL,,,,coil,1620,异常162-铝箔垫缺料
COIL_ALARM_163_POSITIVE_PLATE_SHORTAGE,BOOL,,,,coil,1630,异常163-正极片缺料
COIL_ALARM_164_SEPARATOR_SHORTAGE,BOOL,,,,coil,1640,异常164-隔膜缺料
COIL_ALARM_165_NEGATIVE_PLATE_SHORTAGE,BOOL,,,,coil,1650,异常165-负极片缺料
COIL_ALARM_166_FLAT_WASHER_SHORTAGE,BOOL,,,,coil,1660,异常166-平垫缺料
COIL_ALARM_167_SPRING_WASHER_SHORTAGE,BOOL,,,,coil,1670,异常167-弹垫缺料
COIL_ALARM_168_NEGATIVE_SHELL_SHORTAGE,BOOL,,,,coil,1680,异常168-负极壳缺料
COIL_ALARM_169_FINISHED_BATTERY_FULL,BOOL,,,,coil,1690,异常169-成品电池满料
COIL_ALARM_201_SERVO_AXIS_01_ERROR,BOOL,,,,coil,2010,异常201-伺服轴01异常
COIL_ALARM_202_SERVO_AXIS_02_ERROR,BOOL,,,,coil,2020,异常202-伺服轴02异常
COIL_ALARM_203_SERVO_AXIS_03_ERROR,BOOL,,,,coil,2030,异常203-伺服轴03异常
COIL_ALARM_204_SERVO_AXIS_04_ERROR,BOOL,,,,coil,2040,异常204-伺服轴04异常
COIL_ALARM_205_SERVO_AXIS_05_ERROR,BOOL,,,,coil,2050,异常205-伺服轴05异常
COIL_ALARM_206_SERVO_AXIS_06_ERROR,BOOL,,,,coil,2060,异常206-伺服轴06异常
COIL_ALARM_207_SERVO_AXIS_07_ERROR,BOOL,,,,coil,2070,异常207-伺服轴07异常
COIL_ALARM_208_SERVO_AXIS_08_ERROR,BOOL,,,,coil,2080,异常208-伺服轴08异常
COIL_ALARM_209_SERVO_AXIS_09_ERROR,BOOL,,,,coil,2090,异常209-伺服轴09异常
COIL_ALARM_210_SERVO_AXIS_10_ERROR,BOOL,,,,coil,2100,异常210-伺服轴10异常
COIL_ALARM_211_SERVO_AXIS_11_ERROR,BOOL,,,,coil,2110,异常211-伺服轴11异常
COIL_ALARM_212_SERVO_AXIS_12_ERROR,BOOL,,,,coil,2120,异常212-伺服轴12异常
COIL_ALARM_213_SERVO_AXIS_13_ERROR,BOOL,,,,coil,2130,异常213-伺服轴13异常
COIL_ALARM_214_SERVO_AXIS_14_ERROR,BOOL,,,,coil,2140,异常214-伺服轴14异常
COIL_ALARM_250_OTHER_COMPONENT_ERROR,BOOL,,,,coil,2500,异常250-其他元件异常
COIL_ALARM_251_PIPETTE_COMM_ERROR,BOOL,,,,coil,2510,异常251-移液枪通讯异常
COIL_ALARM_252_PIPETTE_ALARM,BOOL,,,,coil,2520,异常252-移液枪报警
COIL_ALARM_256_ELECTRIC_GRIPPER_ERROR,BOOL,,,,coil,2560,异常256-电爪异常
COIL_ALARM_262_RB_UNKNOWN_POSITION_ERROR,BOOL,,,,coil,2620,异常262-RB报警未知点位错误
COIL_ALARM_263_RB_XYZ_PARAM_LIMIT_ERROR,BOOL,,,,coil,2630,异常263-RB报警X、Y、Z参数超限制
COIL_ALARM_264_RB_VISION_PARAM_ERROR,BOOL,,,,coil,2640,异常264-RB报警视觉参数误差过大
COIL_ALARM_265_RB_NOZZLE_1_PICK_FAIL,BOOL,,,,coil,2650,异常265-RB报警1#吸嘴取料失败
COIL_ALARM_266_RB_NOZZLE_2_PICK_FAIL,BOOL,,,,coil,2660,异常266-RB报警2#吸嘴取料失败
COIL_ALARM_267_RB_NOZZLE_3_PICK_FAIL,BOOL,,,,coil,2670,异常267-RB报警3#吸嘴取料失败
COIL_ALARM_268_RB_NOZZLE_4_PICK_FAIL,BOOL,,,,coil,2680,异常268-RB报警4#吸嘴取料失败
COIL_ALARM_269_RB_TRAY_PICK_FAIL,BOOL,,,,coil,2690,异常269-RB报警取物料盘失败
COIL_ALARM_280_RB_COLLISION_ERROR,BOOL,,,,coil,2800,异常280-RB碰撞异常
COIL_ALARM_290_VISION_SYSTEM_COMM_ERROR,BOOL,,,,coil,2900,异常290-视觉系统通讯异常
COIL_ALARM_291_VISION_ALIGNMENT_NG,BOOL,,,,coil,2910,异常291-视觉对位NG异常
COIL_ALARM_292_BARCODE_SCANNER_COMM_ERROR,BOOL,,,,coil,2920,异常292-扫码枪通讯异常
COIL_ALARM_310_OCV_TRANSFER_NOZZLE_SUCTION_ERROR,BOOL,,,,coil,3100,异常310-开电移载吸嘴吸真空异常
COIL_ALARM_311_OCV_TRANSFER_NOZZLE_BREAK_ERROR,BOOL,,,,coil,3110,异常311-开电移载吸嘴破真空异常
COIL_ALARM_312_WEIGHT_TRANSFER_NOZZLE_SUCTION_ERROR,BOOL,,,,coil,3120,异常312-称重移载吸嘴吸真空异常
COIL_ALARM_313_WEIGHT_TRANSFER_NOZZLE_BREAK_ERROR,BOOL,,,,coil,3130,异常313-称重移载吸嘴破真空异常
COIL_ALARM_340_OCV_NOZZLE_TRANSFER_CYLINDER_ERROR,BOOL,,,,coil,3400,异常340-开路电压吸嘴移载气缸异常
COIL_ALARM_342_OCV_NOZZLE_LIFT_CYLINDER_ERROR,BOOL,,,,coil,3420,异常342-开路电压吸嘴升降气缸异常
COIL_ALARM_344_OCV_CRIMPING_CYLINDER_ERROR,BOOL,,,,coil,3440,异常344-开路电压旋压气缸异常
COIL_ALARM_350_WEIGHT_NOZZLE_TRANSFER_CYLINDER_ERROR,BOOL,,,,coil,3500,异常350-称重吸嘴移载气缸异常
COIL_ALARM_352_WEIGHT_NOZZLE_LIFT_CYLINDER_ERROR,BOOL,,,,coil,3520,异常352-称重吸嘴升降气缸异常
COIL_ALARM_354_CLEANING_CLOTH_TRANSFER_CYLINDER_ERROR,BOOL,,,,coil,3540,异常354-清洗无尘布移载气缸异常
COIL_ALARM_356_CLEANING_CLOTH_PRESS_CYLINDER_ERROR,BOOL,,,,coil,3560,异常356-清洗无尘布压紧气缸异常
COIL_ALARM_360_ELECTROLYTE_BOTTLE_POSITION_CYLINDER_ERROR,BOOL,,,,coil,3600,异常360-电解液瓶定位气缸异常
COIL_ALARM_362_PIPETTE_TIP_BOX_POSITION_CYLINDER_ERROR,BOOL,,,,coil,3620,异常362-移液枪头盒定位气缸异常
COIL_ALARM_364_REAGENT_BOTTLE_GRIPPER_LIFT_CYLINDER_ERROR,BOOL,,,,coil,3640,异常364-试剂瓶夹爪升降气缸异常
COIL_ALARM_366_REAGENT_BOTTLE_GRIPPER_CYLINDER_ERROR,BOOL,,,,coil,3660,异常366-试剂瓶夹爪气缸异常
COIL_ALARM_370_PRESS_MODULE_BLOW_CYLINDER_ERROR,BOOL,,,,coil,3700,异常370-压制模块吹气气缸异常
COIL_ALARM_151_ELECTROLYTE_BOTTLE_POSITION_ERROR,BOOL,,,,coil,1510,异常151-电解液瓶定位在籍异常
COIL_ALARM_152_ELECTROLYTE_BOTTLE_CAP_ERROR,BOOL,,,,coil,1520,异常152-电解液瓶盖在籍异常
1 Name DataType InitValue Comment Attribute DeviceType Address
2 COIL_SYS_START_CMD BOOL coil 8010
3 COIL_SYS_STOP_CMD BOOL coil 8020
4 COIL_SYS_RESET_CMD BOOL coil 8030
5 COIL_SYS_HAND_CMD BOOL coil 8040
6 COIL_SYS_AUTO_CMD BOOL coil 8050
7 COIL_SYS_INIT_CMD BOOL coil 8060
8 COIL_UNILAB_SEND_MSG_SUCC_CMD BOOL coil 8700
9 COIL_UNILAB_REC_MSG_SUCC_CMD BOOL coil 8710 unilab_rec_msg_succ_cmd
10 COIL_SYS_START_STATUS BOOL coil 8210
11 COIL_SYS_STOP_STATUS BOOL coil 8220
12 COIL_SYS_RESET_STATUS BOOL coil 8230
13 COIL_SYS_HAND_STATUS BOOL coil 8240
14 COIL_SYS_AUTO_STATUS BOOL coil 8250
15 COIL_SYS_INIT_STATUS BOOL coil 8260
16 COIL_REQUEST_REC_MSG_STATUS BOOL coil 8500
17 COIL_REQUEST_SEND_MSG_STATUS BOOL coil 8510 request_send_msg_status
18 REG_MSG_ELECTROLYTE_USE_NUM INT16 hold_register 11000
19 REG_MSG_ELECTROLYTE_NUM INT16 hold_register 11002 unilab_send_msg_electrolyte_num
20 REG_MSG_ELECTROLYTE_VOLUME INT16 hold_register 11004 unilab_send_msg_electrolyte_vol
21 REG_MSG_ASSEMBLY_TYPE INT16 hold_register 11006 unilab_send_msg_assembly_type
22 REG_MSG_ASSEMBLY_PRESSURE INT16 hold_register 11008 unilab_send_msg_assembly_pressure
23 REG_DATA_ASSEMBLY_COIN_CELL_NUM INT16 hold_register 10000 data_assembly_coin_cell_num
24 REG_DATA_OPEN_CIRCUIT_VOLTAGE FLOAT32 hold_register 10002 data_open_circuit_voltage
25 REG_DATA_AXIS_X_POS FLOAT32 hold_register 10004
26 REG_DATA_AXIS_Y_POS FLOAT32 hold_register 10006
27 REG_DATA_AXIS_Z_POS FLOAT32 hold_register 10008
28 REG_DATA_POLE_WEIGHT FLOAT32 hold_register 10010 data_pole_weight
29 REG_DATA_ASSEMBLY_PER_TIME FLOAT32 hold_register 10012 data_assembly_time
30 REG_DATA_ASSEMBLY_PRESSURE INT16 hold_register 10014 data_assembly_pressure
31 REG_DATA_ELECTROLYTE_VOLUME INT16 hold_register 10016 data_electrolyte_volume
32 REG_DATA_COIN_NUM INT16 hold_register 10018 data_coin_num
33 REG_DATA_ELECTROLYTE_CODE STRING hold_register 10020 data_electrolyte_code()
34 REG_DATA_COIN_CELL_CODE STRING hold_register 10030 data_coin_cell_code()
35 REG_DATA_STACK_VISON_CODE STRING hold_register 12004 data_stack_vision_code()
36 REG_DATA_GLOVE_BOX_PRESSURE FLOAT32 hold_register 10050 data_glove_box_pressure
37 REG_DATA_GLOVE_BOX_WATER_CONTENT FLOAT32 hold_register 10052 data_glove_box_water_content
38 REG_DATA_GLOVE_BOX_O2_CONTENT FLOAT32 hold_register 10054 data_glove_box_o2_content
39 UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM BOOL coil 8720
40 UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM BOOL coil 8520
41 REG_MSG_ELECTROLYTE_NUM_USED INT16 hold_register 496
42 REG_DATA_ELECTROLYTE_USE_NUM INT16 hold_register 10000
43 UNILAB_SEND_FINISHED_CMD BOOL coil 8730
44 UNILAB_RECE_FINISHED_CMD BOOL coil 8530
45 REG_DATA_ASSEMBLY_TYPE INT16 hold_register 10018 ASSEMBLY_TYPE7or8
46 REG_UNILAB_INTERACT BOOL coil 8450
47 coil 8320
48 COIL_ALUMINUM_FOIL BOOL coil 8340
49 REG_MSG_NE_PLATE_MATRIX INT16 hold_register 440
50 REG_MSG_SEPARATOR_PLATE_MATRIX INT16 hold_register 450
51 REG_MSG_TIP_BOX_MATRIX INT16 hold_register 480
52 REG_MSG_NE_PLATE_NUM INT16 hold_register 443
53 REG_MSG_SEPARATOR_PLATE_NUM INT16 hold_register 453
54 REG_MSG_PRESS_MODE BOOL coil 8360
55 BOOL coil 8300
56 BOOL coil 8310
57 COIL_GB_L_IGNORE_CMD BOOL coil 8320
58 COIL_GB_R_IGNORE_CMD BOOL coil 8420
59 BOOL coil 8350
60 COIL_ELECTROLYTE_DUAL_DROP_MODE BOOL coil 8370
61 BOOL coil 8380
62 BOOL coil 8390
63 BOOL coil 8400
64 BOOL coil 8410
65 REG_MSG_DUAL_DROP_FIRST_VOLUME INT16 hold_register 4001
66 COIL_DUAL_DROP_SUCTION_TIMING BOOL coil 8430
67 COIL_DUAL_DROP_START_TIMING BOOL coil 8470
68 REG_MSG_BATTERY_CLEAN_IGNORE BOOL coil 8460
69 COIL_ALARM_100_SYSTEM_ERROR BOOL coil 1000 异常100-系统异常
70 COIL_ALARM_101_EMERGENCY_STOP BOOL coil 1010 异常101-急停
71 COIL_ALARM_111_GLOVEBOX_EMERGENCY_STOP BOOL coil 1110 异常111-手套箱急停
72 COIL_ALARM_112_GLOVEBOX_GRATING_BLOCKED BOOL coil 1120 异常112-手套箱内光栅遮挡
73 COIL_ALARM_160_PIPETTE_TIP_SHORTAGE BOOL coil 1600 异常160-移液枪头缺料
74 COIL_ALARM_161_POSITIVE_SHELL_SHORTAGE BOOL coil 1610 异常161-正极壳缺料
75 COIL_ALARM_162_ALUMINUM_FOIL_SHORTAGE BOOL coil 1620 异常162-铝箔垫缺料
76 COIL_ALARM_163_POSITIVE_PLATE_SHORTAGE BOOL coil 1630 异常163-正极片缺料
77 COIL_ALARM_164_SEPARATOR_SHORTAGE BOOL coil 1640 异常164-隔膜缺料
78 COIL_ALARM_165_NEGATIVE_PLATE_SHORTAGE BOOL coil 1650 异常165-负极片缺料
79 COIL_ALARM_166_FLAT_WASHER_SHORTAGE BOOL coil 1660 异常166-平垫缺料
80 COIL_ALARM_167_SPRING_WASHER_SHORTAGE BOOL coil 1670 异常167-弹垫缺料
81 COIL_ALARM_168_NEGATIVE_SHELL_SHORTAGE BOOL coil 1680 异常168-负极壳缺料
82 COIL_ALARM_169_FINISHED_BATTERY_FULL BOOL coil 1690 异常169-成品电池满料
83 COIL_ALARM_201_SERVO_AXIS_01_ERROR BOOL coil 2010 异常201-伺服轴01异常
84 COIL_ALARM_202_SERVO_AXIS_02_ERROR BOOL coil 2020 异常202-伺服轴02异常
85 COIL_ALARM_203_SERVO_AXIS_03_ERROR BOOL coil 2030 异常203-伺服轴03异常
86 COIL_ALARM_204_SERVO_AXIS_04_ERROR BOOL coil 2040 异常204-伺服轴04异常
87 COIL_ALARM_205_SERVO_AXIS_05_ERROR BOOL coil 2050 异常205-伺服轴05异常
88 COIL_ALARM_206_SERVO_AXIS_06_ERROR BOOL coil 2060 异常206-伺服轴06异常
89 COIL_ALARM_207_SERVO_AXIS_07_ERROR BOOL coil 2070 异常207-伺服轴07异常
90 COIL_ALARM_208_SERVO_AXIS_08_ERROR BOOL coil 2080 异常208-伺服轴08异常
91 COIL_ALARM_209_SERVO_AXIS_09_ERROR BOOL coil 2090 异常209-伺服轴09异常
92 COIL_ALARM_210_SERVO_AXIS_10_ERROR BOOL coil 2100 异常210-伺服轴10异常
93 COIL_ALARM_211_SERVO_AXIS_11_ERROR BOOL coil 2110 异常211-伺服轴11异常
94 COIL_ALARM_212_SERVO_AXIS_12_ERROR BOOL coil 2120 异常212-伺服轴12异常
95 COIL_ALARM_213_SERVO_AXIS_13_ERROR BOOL coil 2130 异常213-伺服轴13异常
96 COIL_ALARM_214_SERVO_AXIS_14_ERROR BOOL coil 2140 异常214-伺服轴14异常
97 COIL_ALARM_250_OTHER_COMPONENT_ERROR BOOL coil 2500 异常250-其他元件异常
98 COIL_ALARM_251_PIPETTE_COMM_ERROR BOOL coil 2510 异常251-移液枪通讯异常
99 COIL_ALARM_252_PIPETTE_ALARM BOOL coil 2520 异常252-移液枪报警
100 COIL_ALARM_256_ELECTRIC_GRIPPER_ERROR BOOL coil 2560 异常256-电爪异常
101 COIL_ALARM_262_RB_UNKNOWN_POSITION_ERROR BOOL coil 2620 异常262-RB报警:未知点位错误
102 COIL_ALARM_263_RB_XYZ_PARAM_LIMIT_ERROR BOOL coil 2630 异常263-RB报警:X、Y、Z参数超限制
103 COIL_ALARM_264_RB_VISION_PARAM_ERROR BOOL coil 2640 异常264-RB报警:视觉参数误差过大
104 COIL_ALARM_265_RB_NOZZLE_1_PICK_FAIL BOOL coil 2650 异常265-RB报警:1#吸嘴取料失败
105 COIL_ALARM_266_RB_NOZZLE_2_PICK_FAIL BOOL coil 2660 异常266-RB报警:2#吸嘴取料失败
106 COIL_ALARM_267_RB_NOZZLE_3_PICK_FAIL BOOL coil 2670 异常267-RB报警:3#吸嘴取料失败
107 COIL_ALARM_268_RB_NOZZLE_4_PICK_FAIL BOOL coil 2680 异常268-RB报警:4#吸嘴取料失败
108 COIL_ALARM_269_RB_TRAY_PICK_FAIL BOOL coil 2690 异常269-RB报警:取物料盘失败
109 COIL_ALARM_280_RB_COLLISION_ERROR BOOL coil 2800 异常280-RB碰撞异常
110 COIL_ALARM_290_VISION_SYSTEM_COMM_ERROR BOOL coil 2900 异常290-视觉系统通讯异常
111 COIL_ALARM_291_VISION_ALIGNMENT_NG BOOL coil 2910 异常291-视觉对位NG异常
112 COIL_ALARM_292_BARCODE_SCANNER_COMM_ERROR BOOL coil 2920 异常292-扫码枪通讯异常
113 COIL_ALARM_310_OCV_TRANSFER_NOZZLE_SUCTION_ERROR BOOL coil 3100 异常310-开电移载吸嘴吸真空异常
114 COIL_ALARM_311_OCV_TRANSFER_NOZZLE_BREAK_ERROR BOOL coil 3110 异常311-开电移载吸嘴破真空异常
115 COIL_ALARM_312_WEIGHT_TRANSFER_NOZZLE_SUCTION_ERROR BOOL coil 3120 异常312-称重移载吸嘴吸真空异常
116 COIL_ALARM_313_WEIGHT_TRANSFER_NOZZLE_BREAK_ERROR BOOL coil 3130 异常313-称重移载吸嘴破真空异常
117 COIL_ALARM_340_OCV_NOZZLE_TRANSFER_CYLINDER_ERROR BOOL coil 3400 异常340-开路电压吸嘴移载气缸异常
118 COIL_ALARM_342_OCV_NOZZLE_LIFT_CYLINDER_ERROR BOOL coil 3420 异常342-开路电压吸嘴升降气缸异常
119 COIL_ALARM_344_OCV_CRIMPING_CYLINDER_ERROR BOOL coil 3440 异常344-开路电压旋压气缸异常
120 COIL_ALARM_350_WEIGHT_NOZZLE_TRANSFER_CYLINDER_ERROR BOOL coil 3500 异常350-称重吸嘴移载气缸异常
121 COIL_ALARM_352_WEIGHT_NOZZLE_LIFT_CYLINDER_ERROR BOOL coil 3520 异常352-称重吸嘴升降气缸异常
122 COIL_ALARM_354_CLEANING_CLOTH_TRANSFER_CYLINDER_ERROR BOOL coil 3540 异常354-清洗无尘布移载气缸异常
123 COIL_ALARM_356_CLEANING_CLOTH_PRESS_CYLINDER_ERROR BOOL coil 3560 异常356-清洗无尘布压紧气缸异常
124 COIL_ALARM_360_ELECTROLYTE_BOTTLE_POSITION_CYLINDER_ERROR BOOL coil 3600 异常360-电解液瓶定位气缸异常
125 COIL_ALARM_362_PIPETTE_TIP_BOX_POSITION_CYLINDER_ERROR BOOL coil 3620 异常362-移液枪头盒定位气缸异常
126 COIL_ALARM_364_REAGENT_BOTTLE_GRIPPER_LIFT_CYLINDER_ERROR BOOL coil 3640 异常364-试剂瓶夹爪升降气缸异常
127 COIL_ALARM_366_REAGENT_BOTTLE_GRIPPER_CYLINDER_ERROR BOOL coil 3660 异常366-试剂瓶夹爪气缸异常
128 COIL_ALARM_370_PRESS_MODULE_BLOW_CYLINDER_ERROR BOOL coil 3700 异常370-压制模块吹气气缸异常
129 COIL_ALARM_151_ELECTROLYTE_BOTTLE_POSITION_ERROR BOOL coil 1510 异常151-电解液瓶定位在籍异常
130 COIL_ALARM_152_ELECTROLYTE_BOTTLE_CAP_ERROR BOOL coil 1520 异常152-电解液瓶盖在籍异常

View File

@@ -0,0 +1,2 @@
Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code
20251224_172304,-5.537573695435827e-37,-48.45097351074219,1.372190511464448e+16,3820,30,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n'
1 Time open_circuit_voltage pole_weight assembly_time assembly_pressure electrolyte_volume coin_num electrolyte_code coin_cell_code
2 20251224_172304 -5.537573695435827e-37 -48.45097351074219 1.372190511464448e+16 3820 30 7 b'\x00\x00d\x00eaoR' b'\x00\x00\x01\x00\x00\x00\r\n'

View File

@@ -0,0 +1,2 @@
Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code
20251225_105600,5.566961054206384e-37,-53149746331648.0,3271557120.0,3658,10,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n'
1 Time open_circuit_voltage pole_weight assembly_time assembly_pressure electrolyte_volume coin_num electrolyte_code coin_cell_code
2 20251225_105600 5.566961054206384e-37 -53149746331648.0 3271557120.0 3658 10 7 b'\x00\x00d\x00eaoR' b'\x00\x00\x01\x00\x00\x00\r\n'

View File

@@ -0,0 +1,2 @@
Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code
20251229_161836,-5.537573695435827e-37,8.919000478163591e+20,-3.806253867691382e-29,3544,20,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n'
1 Time open_circuit_voltage pole_weight assembly_time assembly_pressure electrolyte_volume coin_num electrolyte_code coin_cell_code
2 20251229_161836 -5.537573695435827e-37 8.919000478163591e+20 -3.806253867691382e-29 3544 20 7 b'\x00\x00d\x00eaoR' b'\x00\x00\x01\x00\x00\x00\r\n'

View File

@@ -0,0 +1,9 @@
Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code
20251230_182319,0.01600000075995922,13.899999618530273,175.0,3836,20,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n'
20251230_185306,0.01600000075995922,13.639999389648438,625.0,3819,20,7,deaoR,
20251230_192124,0.0,8.949999809265137,414.0,3803,20,8,deaoR,
20251230_195621,3.8359999656677246,10.069999694824219,205.0,3350,20,8,LG600001,19311909
20251230_200830,0.7929999828338623,9.34999942779541,18.0,3318,20,8,LG600001,19533419
20251230_201123,0.0,9.169999122619629,17.0,3269,20,8,LG600001,20054389
20251230_201410,0.0,9.569999694824219,18.0,3237,20,8,LG600001,YS102704
20251230_201659,0.0,9.699999809265137,169.0,3318,20,8,LG600001,20112754
1 Time open_circuit_voltage pole_weight assembly_time assembly_pressure electrolyte_volume coin_num electrolyte_code coin_cell_code
2 20251230_182319 0.01600000075995922 13.899999618530273 175.0 3836 20 7 b'\x00\x00d\x00eaoR' b'\x00\x00\x01\x00\x00\x00\r\n'
3 20251230_185306 0.01600000075995922 13.639999389648438 625.0 3819 20 7 deaoR 
4 20251230_192124 0.0 8.949999809265137 414.0 3803 20 8 deaoR 
5 20251230_195621 3.8359999656677246 10.069999694824219 205.0 3350 20 8 LG600001 19311909
6 20251230_200830 0.7929999828338623 9.34999942779541 18.0 3318 20 8 LG600001 19533419
7 20251230_201123 0.0 9.169999122619629 17.0 3269 20 8 LG600001 20054389
8 20251230_201410 0.0 9.569999694824219 18.0 3237 20 8 LG600001 YS102704
9 20251230_201659 0.0 9.699999809265137 169.0 3318 20 8 LG600001 20112754

View File

@@ -0,0 +1,3 @@
Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code
20260106_221708,0.03200000151991844,26.26999855041504,18.0,3803,30,7,NoRead88,22000063
20260106_221957,0.11299999803304672,26.26999855041504,170.0,3787,30,7,LG600001,22124813
1 Time open_circuit_voltage pole_weight assembly_time assembly_pressure electrolyte_volume coin_num electrolyte_code coin_cell_code
2 20260106_221708 0.03200000151991844 26.26999855041504 18.0 3803 30 7 NoRead88 22000063
3 20260106_221957 0.11299999803304672 26.26999855041504 170.0 3787 30 7 LG600001 22124813

View File

@@ -0,0 +1,536 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""扣式电池组装系统 - 交互式CSV导出演示脚本增强版
此脚本专为交互式使用优化,提供清洁的命令行界面,
禁用了所有调试信息输出,确保用户可以顺畅地输入命令。
主要功能:
1. 手动导出设备数据到CSV文件包含6个关键数据字段
2. 查看CSV文件内容和导出状态
3. 兼容原有的电池组装完成状态自动导出功能
4. 实时查看设备数据和电池数量
数据字段:
- timestamp: 时间戳
- assembly_time: 单颗电池组装时间(秒)
- open_circuit_voltage: 开路电压值V
- pole_weight: 正极片称重数据g
- battery_qr_code: 电池二维码序列号
- electrolyte_qr_code: 电解液二维码序列号
使用方法:
1. 确保设备已连接并可正常通信
2. 运行此脚本: python interactive_battery_export_demo.py
3. 使用交互式命令控制导出功能
"""
import time
import os
import sys
import logging
import csv
from datetime import datetime
from pathlib import Path
# 完全禁用所有调试和信息级别的日志输出
logging.getLogger().setLevel(logging.CRITICAL)
logging.getLogger('pymodbus').setLevel(logging.CRITICAL)
logging.getLogger('unilabos').setLevel(logging.CRITICAL)
logging.getLogger('pymodbus.logging').setLevel(logging.CRITICAL)
logging.getLogger('pymodbus.logging.tcp').setLevel(logging.CRITICAL)
logging.getLogger('pymodbus.logging.base').setLevel(logging.CRITICAL)
logging.getLogger('pymodbus.logging.decoders').setLevel(logging.CRITICAL)
# 添加当前目录到Python路径以便正确导入模块
current_dir = Path(__file__).parent
sys.path.insert(0, str(current_dir.parent.parent.parent)) # 添加unilabos根目录
sys.path.insert(0, str(current_dir)) # 添加当前目录
# 导入扣式电池组装系统
try:
from unilabos.devices.coin_cell_assembly.coin_cell_assembly_system import Coin_Cell_Assembly
except ImportError:
# 如果上述导入失败,尝试直接导入
try:
from coin_cell_assembly_system import Coin_Cell_Assembly
except ImportError as e:
print(f"导入错误: {e}")
print("请确保在正确的目录下运行此脚本或者将unilabos添加到Python路径中")
sys.exit(1)
def clear_screen():
"""清屏函数"""
os.system('cls' if os.name == 'nt' else 'clear')
def print_header():
"""打印程序头部信息"""
print("="*60)
print(" 扣式电池组装系统 - 交互式CSV导出控制台")
print("="*60)
print()
def print_commands():
"""打印可用命令"""
print("可用命令:")
print(" start - 启动电池组装完成状态导出")
print(" stop - 停止导出")
print(" status - 查看导出状态")
print(" data - 查看当前设备数据")
print(" count - 查看当前电池数量")
print(" export - 手动导出当前数据到CSV")
print(" setpath - 设置自定义CSV文件路径")
print(" view - 查看CSV文件内容")
print(" force - 强制继续CSV导出(即使设备停止)")
print(" detail - 显示详细设备状态")
print(" clear - 清屏")
print(" help - 显示帮助信息")
print(" quit - 退出程序")
print("-"*60)
def print_status_info(device, csv_file_path):
"""打印状态信息"""
try:
status = device.get_csv_export_status()
is_running = status.get('running', False)
export_file = status.get('file_path', None)
thread_alive = status.get('thread_alive', False)
device_status = status.get('device_status', 'N/A')
battery_count = status.get('battery_count', 'N/A')
print(f"导出状态: {'运行中' if is_running else '已停止'}")
print(f"导出文件: {export_file if export_file else 'N/A'}")
print(f"线程状态: {'活跃' if thread_alive else '非活跃'}")
print(f"设备状态: {device_status}")
print(f"电池计数: {battery_count}")
# 检查手动导出的CSV文件
if os.path.exists(csv_file_path):
file_size = os.path.getsize(csv_file_path)
print(f"手动导出文件: {csv_file_path} ({file_size} 字节)")
else:
print(f"手动导出文件: {csv_file_path} (不存在)")
# 显示设备运行状态
try:
print("\n=== 设备运行状态 ===")
print(f"系统启动状态: {device.sys_start_status}")
print(f"系统停止状态: {device.sys_stop_status}")
print(f"自动模式状态: {device.sys_auto_status}")
print(f"手动模式状态: {device.sys_hand_status}")
except Exception as e:
print(f"获取设备运行状态失败: {e}")
except Exception as e:
print(f"获取状态失败: {e}")
def collect_device_data(device):
"""收集设备的六个关键数据"""
try:
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 读取各项数据,添加错误处理和重试机制
try:
assembly_time = device.data_assembly_time # 单颗电池组装时间(秒)
# 确保返回的是数值类型
if isinstance(assembly_time, (list, tuple)) and len(assembly_time) > 0:
assembly_time = float(assembly_time[0])
else:
assembly_time = float(assembly_time)
except Exception as e:
print(f"读取组装时间失败: {e}")
assembly_time = 0.0
try:
open_circuit_voltage = device.data_open_circuit_voltage # 开路电压值(V)
# 确保返回的是数值类型
if isinstance(open_circuit_voltage, (list, tuple)) and len(open_circuit_voltage) > 0:
open_circuit_voltage = float(open_circuit_voltage[0])
else:
open_circuit_voltage = float(open_circuit_voltage)
except Exception as e:
print(f"读取开路电压失败: {e}")
open_circuit_voltage = 0.0
try:
pole_weight = device.data_pole_weight # 正极片称重数据(g)
# 确保返回的是数值类型
if isinstance(pole_weight, (list, tuple)) and len(pole_weight) > 0:
pole_weight = float(pole_weight[0])
else:
pole_weight = float(pole_weight)
except Exception as e:
print(f"读取正极片重量失败: {e}")
pole_weight = 0.0
try:
assembly_pressure = device.data_assembly_pressure # 电池压制力(N)
# 确保返回的是数值类型
if isinstance(assembly_pressure, (list, tuple)) and len(assembly_pressure) > 0:
assembly_pressure = int(assembly_pressure[0])
else:
assembly_pressure = int(assembly_pressure)
except Exception as e:
print(f"读取压制力失败: {e}")
assembly_pressure = 0
try:
battery_qr_code = device.data_coin_cell_code # 电池二维码序列号
# 处理字符串类型数据
if isinstance(battery_qr_code, str):
battery_qr_code = battery_qr_code.strip()
else:
battery_qr_code = str(battery_qr_code)
except Exception as e:
print(f"读取电池二维码失败: {e}")
battery_qr_code = "N/A"
try:
electrolyte_qr_code = device.data_electrolyte_code # 电解液二维码序列号
# 处理字符串类型数据
if isinstance(electrolyte_qr_code, str):
electrolyte_qr_code = electrolyte_qr_code.strip()
else:
electrolyte_qr_code = str(electrolyte_qr_code)
except Exception as e:
print(f"读取电解液二维码失败: {e}")
electrolyte_qr_code = "N/A"
# 获取电池数量
try:
battery_count = device.data_assembly_coin_cell_num
# 确保返回的是数值类型
if isinstance(battery_count, (list, tuple)) and len(battery_count) > 0:
battery_count = int(battery_count[0])
else:
battery_count = int(battery_count)
except Exception as e:
print(f"读取电池数量失败: {e}")
battery_count = 0
return {
'Timestamp': timestamp,
'Battery_Count': battery_count,
'Assembly_Time': assembly_time,
'Open_Circuit_Voltage': open_circuit_voltage,
'Pole_Weight': pole_weight,
'Assembly_Pressure': assembly_pressure,
'Battery_Code': battery_qr_code,
'Electrolyte_Code': electrolyte_qr_code
}
except Exception as e:
print(f"收集数据时出错: {e}")
return None
def export_to_csv(data, csv_file_path):
"""将数据导出到CSV文件"""
try:
# 检查文件是否存在,如果不存在则创建并写入表头
file_exists = os.path.exists(csv_file_path)
# 确保目录存在
csv_dir = os.path.dirname(csv_file_path)
if csv_dir:
os.makedirs(csv_dir, exist_ok=True)
# 确保数值字段为正确的数值类型,避免前导单引号问题
processed_data = data.copy()
# 处理数值字段,确保它们是数值类型而不是字符串,增强错误处理
numeric_fields = ['Battery_Count', 'Assembly_Time', 'Open_Circuit_Voltage', 'Pole_Weight', 'Assembly_Pressure']
for field in numeric_fields:
if field in processed_data:
try:
value = processed_data[field]
# 处理可能的列表或元组类型
if isinstance(value, (list, tuple)) and len(value) > 0:
value = value[0]
if field == 'Battery_Count' or field == 'Assembly_Pressure':
processed_data[field] = int(float(value)) # 先转float再转int处理字符串数字
else:
processed_data[field] = float(value)
except (ValueError, TypeError, IndexError) as e:
print(f"字段 {field} 类型转换失败: {e}, 使用默认值")
processed_data[field] = 0 if field == 'Battery_Count' else 0.0
# 处理字符串字段
for field in ['Battery_Code', 'Electrolyte_Code']:
if field in processed_data:
try:
value = processed_data[field]
if isinstance(value, (list, tuple)) and len(value) > 0:
value = value[0]
processed_data[field] = str(value).strip()
except Exception as e:
print(f"字段 {field} 处理失败: {e}, 使用默认值")
processed_data[field] = "N/A"
with open(csv_file_path, 'a', newline='', encoding='utf-8') as csvfile:
fieldnames = ['Timestamp', 'Battery_Count', 'Assembly_Time', 'Open_Circuit_Voltage',
'Pole_Weight', 'Assembly_Pressure', 'Battery_QR_Code', 'Electrolyte_QR_Code']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, quoting=csv.QUOTE_MINIMAL)
# 如果文件不存在,写入表头
if not file_exists:
writer.writeheader()
print(f"创建新的CSV文件: {csv_file_path}")
# 写入数据
writer.writerow(processed_data)
print(f"数据已导出到: {csv_file_path}")
return True
except Exception as e:
print(f"导出CSV时出错: {e}")
return False
def view_csv_content(csv_file_path, lines=10):
"""查看CSV文件内容"""
try:
if not os.path.exists(csv_file_path):
print("CSV文件不存在")
return
with open(csv_file_path, 'r', encoding='utf-8') as csvfile:
content = csvfile.readlines()
if not content:
print("CSV文件为空")
return
print(f"CSV文件内容 (显示最后{min(lines, len(content))}行):")
print("-" * 80)
# 显示表头
if len(content) > 0:
print(content[0].strip())
print("-" * 80)
# 显示最后几行数据
start_line = max(1, len(content) - lines + 1)
for i in range(start_line, len(content)):
print(content[i].strip())
print("-" * 80)
print(f"总共 {len(content)-1} 条数据记录")
except Exception as e:
print(f"读取CSV文件时出错: {e}")
def interactive_demo():
"""
交互式演示模式(优化版)
"""
clear_screen()
print_header()
print("正在初始化设备连接...")
print("设备地址: 192.168.1.20:502")
print("正在尝试连接...")
try:
device = Coin_Cell_Assembly(address="192.168.1.20", port="502")
print("✓ 设备连接成功")
# 测试设备数据读取
print("正在测试设备数据读取...")
try:
test_count = device.data_assembly_coin_cell_num
print(f"✓ 当前电池数量: {test_count}")
except Exception as e:
print(f"⚠ 数据读取测试失败: {e}")
print("设备连接正常,但数据读取可能存在问题")
except Exception as e:
print(f"✗ 设备连接失败: {e}")
print("请检查以下项目:")
print("1. 设备是否已开机并正常运行")
print("2. 网络连接是否正常")
print("3. 设备IP地址是否为192.168.1.20")
print("4. Modbus服务是否在端口502上运行")
input("按回车键退出...")
return
csv_file_path = "battery_data_export.csv"
print(f"CSV文件路径: {os.path.abspath(csv_file_path)}")
print()
print("功能说明:")
print("- 支持手动导出当前设备数据到CSV文件")
print("- 包含六个关键数据: 组装时间、开路电压、正极片重量、电池码、电解液码")
print("- 电池码和电解液码可能显示为N/A当二维码读取失败时")
print("- 支持查看CSV文件内容和导出状态")
print("- 兼容原有的电池组装完成状态自动导出功能")
print()
print_commands()
while True:
try:
command = input("\n请输入命令 > ").strip().lower()
if command == "start":
print("启动电池组装完成状态导出...")
try:
success, message = device.start_battery_completion_export(csv_file_path)
if success:
print(f"{message}")
print("系统正在监控电池组装完成状态...")
else:
print(f"{message}")
except Exception as e:
print(f"启动导出时出错: {e}")
elif command == "stop":
print("停止导出...")
try:
success, message = device.stop_csv_export()
if success:
print(f"{message}")
else:
print(f"{message}")
except Exception as e:
print(f"停止导出时出错: {e}")
elif command == "force":
print("强制继续CSV导出...")
try:
success, message = device.force_continue_csv_export()
if success:
print(f"{message}")
print("注意: CSV导出将继续监控数据变化即使设备处于停止状态")
else:
print(f"{message}")
except AttributeError:
print("✗ 当前版本不支持强制继续功能")
except Exception as e:
print(f"✗ 强制继续失败: {e}")
elif command == "detail":
print("=== 详细设备状态 ===")
print_status_info(device, csv_file_path)
elif command == "status":
print_status_info(device, csv_file_path)
elif command == "data":
print("读取当前设备数据...")
try:
data = collect_device_data(device)
if data:
print("\n=== 当前设备数据 ===")
print(f"时间戳: {data['Timestamp']}")
print(f"电池数量: {data['Battery_Count']}")
print(f"单颗电池组装时间: {data['Assembly_Time']:.2f}")
print(f"开路电压值: {data['Open_Circuit_Voltage']:.4f} V")
print(f"正极片称重数据: {data['Pole_Weight']:.4f} g")
print(f"电池压制力: {data['Assembly_Pressure']} N")
print(f"电池二维码序列号: {data['Battery_Code']}")
print(f"电解液二维码序列号: {data['Electrolyte_Code']}")
print("===================")
else:
print("无法获取设备数据")
except Exception as e:
print(f"读取数据时出错: {e}")
elif command == "count":
print("读取当前电池数量...")
try:
count = device.data_assembly_coin_cell_num
print(f"当前已完成电池数量: {count}")
except Exception as e:
print(f"读取电池数量时出错: {e}")
elif command == "export":
print("正在收集设备数据并导出到CSV...")
data = collect_device_data(device)
if data:
print(f"收集到数据: 电池数量={data.get('Battery_Count', 'N/A')}, 组装时间={data.get('Assembly_Time', 'N/A')}s")
if export_to_csv(data, csv_file_path):
print("✓ 数据已成功导出到CSV文件")
print(f"导出数据: 时间={data['Timestamp']}, 电池数量={data['Battery_Count']}, 组装时间={data['Assembly_Time']}秒, "
f"电压={data['Open_Circuit_Voltage']}V, 重量={data['Pole_Weight']}g, 压制力={data['Assembly_Pressure']}N")
print(f"电池码={data['Battery_Code']}, 电解液码={data['Electrolyte_Code']}")
else:
print("✗ 导出失败")
else:
print("✗ 数据收集失败,无法导出!请检查设备连接状态。")
# 尝试重新连接设备
try:
if hasattr(device, 'connect'):
device.connect()
print("尝试重新连接设备...")
except Exception as e:
print(f"重新连接失败: {e}")
elif command == "setpath":
print("设置自定义CSV文件路径")
print(f"当前CSV文件路径: {csv_file_path}")
new_path = input("请输入新的CSV文件路径包含文件名如: D:/data/my_battery_data.csv: ").strip()
if new_path:
try:
# 确保目录存在
new_dir = os.path.dirname(new_path)
if new_dir and not os.path.exists(new_dir):
os.makedirs(new_dir, exist_ok=True)
print(f"✓ 已创建目录: {new_dir}")
csv_file_path = new_path
print(f"✓ CSV文件路径已更新为: {os.path.abspath(csv_file_path)}")
# 检查文件是否存在
if os.path.exists(csv_file_path):
file_size = os.path.getsize(csv_file_path)
print(f"文件已存在,大小: {file_size} 字节")
else:
print("文件不存在,将在首次导出时创建")
except Exception as e:
print(f"✗ 设置路径失败: {e}")
else:
print("路径不能为空")
elif command == "view":
print("查看CSV文件内容...")
view_csv_content(csv_file_path)
elif command == "clear":
clear_screen()
print_header()
print_commands()
elif command == "help":
print_commands()
elif command == "quit" or command == "exit":
print("正在退出...")
# 停止导出
try:
device.stop_csv_export()
print("✓ 导出已停止")
except:
pass
print("程序已退出")
break
elif command == "":
# 空命令,不做任何操作
continue
else:
print(f"未知命令: {command}")
print("输入 'help' 查看可用命令")
except KeyboardInterrupt:
print("\n\n检测到 Ctrl+C正在退出...")
try:
device.stop_csv_export()
print("✓ 导出已停止")
except:
pass
print("程序已退出")
break
except Exception as e:
print(f"执行命令时出错: {e}")
if __name__ == '__main__':
interactive_demo()

View File

@@ -0,0 +1,107 @@
# 电池组装资源冲突问题修复说明
## 问题描述
在运行 `func_allpack_cmd` 函数时,遇到以下错误:
```
ValueError: Resource 'battery_0' already assigned to deck
```
**错误位置**`coin_cell_assembly.py` 第 849 行
```python
liaopan3.children[self.coin_num_N].assign_child_resource(battery, location=None)
```
## 原因分析
1. **资源名称冲突**
- 每次创建电池资源使用固定格式 `battery_{coin_num_N}`
- 如果程序重启或断点恢复,`coin_num_N` 可能重置为 0
- Deck 上可能已存在 `battery_0` 等同名资源
2. **缺少冲突处理**
- 在分配资源前没有检查目标位置是否已有资源
- 没有清理机制来移除旧资源
## 解决方案
### 1. 使用时间戳确保资源名称唯一
```python
# 之前
battery = ElectrodeSheet(name=f"battery_{self.coin_num_N}", ...)
# 修复后
timestamp_suffix = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
battery_name = f"battery_{self.coin_num_N}_{timestamp_suffix}"
battery = ElectrodeSheet(name=battery_name, ...)
```
### 2. 添加资源冲突检查和清理
```python
# 检查目标位置是否已有资源
target_slot = liaopan3.children[self.coin_num_N]
if target_slot.children:
logger.warning(f"位置 {self.coin_num_N} 已有资源,将先卸载旧资源")
try:
# 卸载所有现有子资源
for child in list(target_slot.children):
target_slot.unassign_child_resource(child)
logger.info(f"已卸载旧资源: {child.name}")
except Exception as e:
logger.error(f"卸载旧资源时出错: {e}")
```
### 3. 增强错误处理
```python
# 分配新资源到目标位置
try:
target_slot.assign_child_resource(battery, location=None)
logger.info(f"成功分配电池 {battery_name} 到位置 {self.coin_num_N}")
except Exception as e:
logger.error(f"分配电池资源失败: {e}")
raise
```
## 修复效果
**不再出现重复资源名称错误**
- 每个电池资源都有唯一的时间戳后缀
- 即使 `coin_num_N` 相同,资源名称也不会冲突
**自动清理旧资源**
- 在分配新资源前检查目标位置
- 自动卸载已存在的旧资源
**增强日志记录**
- 记录资源卸载操作
- 记录资源分配成功/失败
- 便于调试和问题追踪
## 测试建议
1. **正常运行测试**
```python
workstation.func_allpack_cmd(
elec_num=1,
elec_use_num=1,
elec_vol=20,
file_path="..."
)
```
2. **断点恢复测试**
- 运行一次后中断
- 再次运行相同参数
- 验证不会出现资源冲突错误
3. **连续运行测试**
- 连续多次运行
- 验证每次都能正常分配资源
## 相关文件
- `coin_cell_assembly.py` - 第 838-875 行(`func_pack_get_msg_cmd` 函数)