RnD_Welder a7bec5220d 원복 코드 -> 레이저 출사 X
기존 코드에서 완료 플래그 초기화 추가 및 왕복 스테이지 동작으로 변경
2026-04-17 13:50:08 +09:00

653 lines
26 KiB
C#

// WeldingCommon/Devices/ACS/ScannerACS.cs
// Gun(PrismaticGunACS.cs) 기반으로 Scanner용으로 통합
// 변경점:
// 1. 네임스페이스/클래스명 변경 (PrismaticGunACS → ScannerACS)
// 2. MOTF 메서드 3개 추가 (MOTFStart/Stop/CheckMOTFComp)
// 3. MOTF 파라미터 세팅 메서드 추가 (SetMOTFParams)
// 4. 모터 취득 try-catch null-safe 적용
// 5. TeachingPosition 체크 로직 단순화 (Scanner는 X2축만 사용)
// 6. xlsx 글로벌 변수 맵 기준 미사용 변수 제거
// - iAStageLCType (iPCset_ALINE_LCTYPE) → SetLCILserOn stub 처리
// - iALaserShotMode (iPCset_ALASER_SHOT_MODE) → SetWeldingType stub 처리
// - rLaserONOffset / rLaserOFFPosX / rLaserOFFOffset → SetLaserOnOff에서 제거
// 26.04.06 NDY 최초 작성
// 26.04.09 NDY xlsx 글로벌 변수 맵 기준 미사용 변수 정리, SetMOTFParams 추가
using Aurora;
using Aurora.Api;
using Aurora.Api.Devices;
using AuroraACS;
using ACS.SPiiPlusNET;
using Hermes;
using System.Windows;
using WeldingCommon.Settings;
using AuroraOCT;
using WeldingCommon.Device.ACS;
namespace WeldingCommon.Devices.ACS
{
// ── 인터페이스 ────────────────────────────────────────────────────────────
public interface IScannerACS
{
bool IsActivated();
// 홈
bool AllAxisHomeStart();
bool AllAxisHomeStop();
bool CheckAllAxisHome();
// MOTF (Scanner 전용 - Gun에 없음)
bool SetMOTFParams(double posX, double negX, double velocity, double acc, int interval);
bool MOTFStart();
bool MOTFStop();
bool CheckMOTFComp();
bool ResetMOTFComp(); // ← 여기에 추가 BUFFER 17에서 완료에 대한 플래그 리셋 0 으로 하는 것 260417
// OneShot
bool SetOneShot(int msecShotTime, double secPhzShotPulse1, double secPhzShotPulse2);
bool OneShotStart();
bool OneShotStop();
bool CheckOneShotComp();
// LineShot
bool SetLineShot(double corePower, double ringPower,
double startPosX, double endPosX,
double startPosY, double endPosY,
double velocity, double acc);
bool LineShotStart();
bool LineShotStop();
bool CheckLineShotComp();
// Welding
bool SetWeldingVel(double acc, double svel, double cvel);
bool SetWeldingPos(double startPosX, double startPosY,
double endPosX, double endPosY,
double camOffsetX, double camOffsetY);
bool SetWeldingArc(double point1, double point2, double point3, double point4);
bool SetWeldingType(eOutType type);
bool SetWeldingPulse(double coreMaxPower, double coreMinPower,
double ringMaxPower, double ringMinPower);
bool SetLaserOnOff(double onPosX, double onOffSet,
double offPosX, double offOffSet,
double camOffsetX, double camOffsetY);
bool SetRamppingOffParameter(double pos, double overlap, double endpower,
double camOffsetX, double camOffsetY);
bool SetRamppingOnParameter(double overlap, double startpower);
bool WeldingStart();
bool WeldingStop();
bool CheckWeldingComp();
// Teaching Position
bool SetWeldingTeachingPosition1(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition2(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition3(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition4(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition5(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition6(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition7(double PosX, double PosY, double camOffsetX, double camOffsetY);
bool SetWeldingTeachingPosition8(double PosX, double PosY, double camOffsetX, double camOffsetY);
// 레이저
bool SetLaserIOUse(bool on);
bool SetLCILserOn(bool on);
bool SetWeldingAxes(int axisXnum, int axisYnum);
bool IsLaserOn();
// 알람
bool ResetAlarm();
void AllAxisServoOff();
}
// ── 구현 ──────────────────────────────────────────────────────────────────
public partial class ScannerACS : ACSDevice, IScannerACS
{
//IsReachedTeachingPosition
private ACSDeviceSetting _setting;
// Scanner는 Stage X (X2) 1축만 사용 | Z 축까지 사용 스캐너 높이
// Gun은 X1, X2, Y1, Y2, Z 5축 사용
private ACSMotor MotorStageX; // AxisX2 = Scanner Stage X
private ACSMotor MotorStageZ; // 26.04.14 = AxisZ
public MotionVariable _motorVariable;
public bool HasHeavyAlarm { get; private set; }
public bool HasLightAlarm { get; private set; }
public int[] HaveAlarmCodes { get => _HaveAlarmCodes; }
private int[] _HaveAlarmCodes = new int[11];
public ScannerACS(bool isSimulation, bool useTerminateUMD = false)
: base(isSimulation, useTerminateUMD)
{
_motorVariable = new MotionVariable();
}
protected override int DoActivate(IDeviceConfig config)
{
if (base.DoActivate(config) != E1.OK)
return E2.ABORTED;
var env = Application.Current.AuroraEnv();
// TODO: Scanner용 SettingIds 확정 후 교체
// _setting = env.SettingEntry[ScannerSettingIds.ACS] as ACSDeviceSetting;
// Scanner는 Stage X (X2) 1축만 취득
// null-safe: 변수 맵 수신 전 예외 방지
// TODO: 이정인 선임 변수 맵 수신 후 축 번호 검증
try { MotorStageX = env.DeviceManager[CommonDeviceIds.AxisX2] as ACSMotor; }
catch { MotorStageX = null; }
try { MotorStageZ = env.DeviceManager[CommonDeviceIds.AxisZ] as ACSMotor; }
catch { MotorStageZ = null; }
SetMonitoringService(UpdateACSParam, 50);
StartMonitoringService();
return E1.OK;
}
private void UpdateACSParam()
{
// Scanner는 Stage X만 모니터링
if (MotorStageX != null)
{
_motorVariable.X2AxisPosition = MotorStageX.GetActualPos();
_motorVariable.X2InPosition = MotorStageX.IsInpos();
_motorVariable.X2AxisVelocity = MotorStageX.GetFeedbackVelocity();
_motorVariable.X2AxisAcceleration = MotorStageX.GetAcceleration();
_motorVariable.IsHome |= MotorStageX.GetServoStatus() == 1;
}
if (MotorStageZ != null)
{
_motorVariable.ZAxisPosition = MotorStageZ.GetActualPos();
_motorVariable.ZInPosition = MotorStageZ.IsInpos();
_motorVariable.ZAxisVelocity = MotorStageZ.GetFeedbackVelocity();
_motorVariable.ZAxisAcceleration = MotorStageZ.GetAcceleration();
_motorVariable.IsHome |= MotorStageZ.GetServoStatus() == 1;
}
// 알람 상태 갱신
HasHeavyAlarm = ReadVariableInt(HeavyAlarm) == 1;
HasLightAlarm = ReadVariableInt(LightAlarm) == 1;
ReadVariableIntArrRef(AlarmCodes, ref _HaveAlarmCodes, ProgramBuffer.ACSC_NONE, 0, 10);
}
protected override int DoDeactivate()
{
StopMonitoringService();
return base.DoDeactivate();
}
// ── 홈 ───────────────────────────────────────────────────────────────
bool IScannerACS.AllAxisHomeStart()
{
if (RunBuffer((ProgramBuffer)eBuffer.All_Axis_Home))
{
Log.D("AllAxisHomeStart >> Complete");
return true;
}
Log.D("AllAxisHomeStart >> Fail");
return false;
}
bool IScannerACS.AllAxisHomeStop()
{
StopBuffer((ProgramBuffer)eBuffer.All_Axis_Home);
Log.D("AllAxisHomeStop >> Complete");
return true;
}
bool IScannerACS.CheckAllAxisHome()
=> ReadVariableInt(iAllAxisHomeComplete) > 0;
// ── MOTF (Scanner 전용 - Gun에 없음) ─────────────────────────────────
// 26.04.09 NDY SetMOTFParams 추가 — xlsx 글로벌 변수 맵 기준 확정
bool IScannerACS.SetMOTFParams(double posX, double negX,
double velocity, double acc, int interval)
{
if (WriteRealVariable(rMOTFPosX, posX) &
WriteRealVariable(rMOTFNegX, negX) &
WriteRealVariable(rMOTFVelocity, velocity) &
WriteRealVariable(rMOTFAcc, acc) &
WriteVariableInt(iMOTFInterval, interval))
{
Log.I($"SetMOTFParams >> Complete | PosX:{posX} NegX:{negX} " +
$"Vel:{velocity} Acc:{acc} Interval:{interval}ms");
return true;
}
Log.E("SetMOTFParams >> Fail");
return false;
}
// TODO: 이정인 선임 변수 맵 수신 후 버퍼 번호 및 완료 변수명 검증
bool IScannerACS.MOTFStart()
{
if (IsSimul) return true;
if (RunBuffer((ProgramBuffer)eBuffer.MOTF_Start))
{
Log.I("MOTFStart >> Complete");
return true;
}
Log.E("MOTFStart >> Fail");
return false;
}
bool IScannerACS.MOTFStop()
{
StopBuffer((ProgramBuffer)eBuffer.MOTF_Start);
Log.D("MOTFStop >> Complete");
return true;
}
bool IScannerACS.CheckMOTFComp()
{
if (IsSimul) return true;
return ReadVariableInt(iMOTFComplete) > 0;
}
// 260417여기 추가
bool IScannerACS.ResetMOTFComp()
{
if (IsSimul) return true;
if (WriteVariableInt(iMOTFComplete, 0))
{
Log.I("ResetMOTFComp >> Complete (iPCset_MOF_WEL_COMP = 0)");
return true;
}
Log.E("ResetMOTFComp >> Fail");
return false;
}
// ── OneShot ──────────────────────────────────────────────────────────
bool IScannerACS.SetOneShot(int msecShotTime, double secPhzShotPulse1, double secPhzShotPulse2)
{
if (WriteRealVariable(rOneShotTime, msecShotTime) &
WriteRealVariable(rOneShotCoreVoltage, secPhzShotPulse1) &
WriteRealVariable(rOneShotRingVoltage, secPhzShotPulse2))
{
Log.D("SetOneShot >> Complete");
return true;
}
Log.D("SetOneShot >> Fail");
return false;
}
bool IScannerACS.OneShotStart()
{
if (RunBuffer((ProgramBuffer)eBuffer.Welding_OneShot))
{
Log.D("OneShotStart >> Complete");
return true;
}
Log.D("OneShotStart >> Fail");
return false;
}
bool IScannerACS.OneShotStop()
{
IScannerACS acs = this;
acs.SetLCILserOn(false);
StopBuffer((ProgramBuffer)eBuffer.Welding_OneShot);
Log.D("OneShotStop >> Complete");
return true;
}
bool IScannerACS.CheckOneShotComp()
=> ReadVariableInt(iOneShotComplete) > 0;
// ── LineShot ─────────────────────────────────────────────────────────
bool IScannerACS.SetLineShot(double corePower, double ringPower,
double startPosX, double endPosX,
double startPosY, double endPosY,
double velocity, double acc)
{
if (WriteRealVariable(rLineWeldingLaserOnX, startPosX) &
WriteRealVariable(rLineWeldingLaserOnY, startPosY) &
WriteRealVariable(rLineWeldingLaserOffX, endPosX) &
WriteRealVariable(rLineWeldingLaserOffY, endPosY) &
WriteRealVariable(rLineWeldingVel, velocity) &
WriteRealVariable(rLineWeldingAcc, acc) &
WriteRealVariable(rLineWeldingCoreVoltage, corePower) &
WriteRealVariable(rLineWeldingRingVoltage, ringPower))
{
Log.D("SetLineShot >> Complete");
return true;
}
Log.D("SetLineShot >> Fail");
return false;
}
bool IScannerACS.LineShotStart()
{
if (RunBuffer((ProgramBuffer)eBuffer.Welding_Line))
{
Log.D("LineShotStart >> Complete");
return true;
}
Log.D("LineShotStart >> Fail");
return false;
}
bool IScannerACS.LineShotStop()
{
IScannerACS acs = this;
acs.SetLCILserOn(false);
StopBuffer((ProgramBuffer)eBuffer.Welding_Line);
Log.D("LineShotStop >> Complete");
return true;
}
bool IScannerACS.CheckLineShotComp()
=> ReadVariableInt(iLineWeldingComplete) > 0;
// ── Welding ──────────────────────────────────────────────────────────
bool IScannerACS.WeldingStart()
{
if (IsSimul) return true;
if (RunBuffer((ProgramBuffer)eBuffer.Welding_AllRound))
{
Log.I("WeldingStart >> Complete");
return true;
}
Log.D("WeldingStart >> Fail");
return false;
}
bool IScannerACS.WeldingStop()
{
IScannerACS acs = this;
acs.SetLCILserOn(false);
StopBuffer((ProgramBuffer)eBuffer.Welding_AllRound);
Log.D("WeldingStop >> Complete");
return true;
}
bool IScannerACS.CheckWeldingComp()
{
if (IsSimul) return true;
return ReadVariableInt(iWeldingComplete) > 0;
}
bool IScannerACS.SetWeldingVel(double acc, double svel, double cvel)
{
if (WriteRealVariable(rWeldingAcc, acc) &
WriteRealVariable(rWeldingSVel, svel) &
WriteRealVariable(rWeldingCVel, cvel))
{
Log.D("SetWeldingVel >> Complete");
return true;
}
Log.D("SetWeldingVel >> Fail");
return false;
}
bool IScannerACS.SetWeldingPos(double startPosX, double startPosY,
double endPosX, double endPosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingStartPosX, startPosX + camOffsetX) &
WriteRealVariable(rWeldingStartPosY, startPosY + camOffsetY) &
WriteRealVariable(rWeldingEndPosX, endPosX + camOffsetX) &
WriteRealVariable(rWeldingEndPosY, endPosY + camOffsetY))
{
Log.D("SetWeldingPos >> Complete");
return true;
}
Log.D("SetWeldingPos >> Fail");
return false;
}
bool IScannerACS.SetWeldingArc(double point1, double point2,
double point3, double point4)
{
if (WriteRealVariable(rWeldingEdgePointRad1, point1) &
WriteRealVariable(rWeldingEdgePointRad2, point2) &
WriteRealVariable(rWeldingEdgePointRad3, point3) &
WriteRealVariable(rWeldingEdgePointRad4, point4))
{
Log.D("SetWeldingArc >> Complete");
return true;
}
Log.D("SetWeldingArc >> Fail");
return false;
}
// 26.04.09 NDY iPCset_ALASER_SHOT_MODE — Scanner xlsx 기준 미사용
bool IScannerACS.SetWeldingType(eOutType type)
{
Log.D("SetWeldingType >> Not Used in Scanner");
return true;
}
bool IScannerACS.SetWeldingPulse(double coreMaxPower, double coreMinPower,
double ringMaxPower, double ringMinPower)
{
if (WriteRealVariable(rWeldingCorePowerMax, coreMaxPower) &
WriteRealVariable(rWeldingCorePowerMin, coreMinPower) &
WriteRealVariable(rWeldingRingPowerMax, ringMaxPower) &
WriteRealVariable(rWeldingRingPowerMin, ringMinPower))
{
Log.D("SetWeldingPulse >> Complete");
return true;
}
Log.D("SetWeldingPulse >> Fail");
return false;
}
// 26.04.09 NDY rLaserONOffset / rLaserOFFPosX / rLaserOFFOffset — xlsx 미사용 제거
// rLaserONPosX (rPCset_ALINE_LASER_ONPOS_X) 만 유효
bool IScannerACS.SetLaserOnOff(double onPosX, double onOffSet,
double offPosX, double offOffSet,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rLaserONPosX, onPosX + camOffsetX))
{
Log.D("SetLaserOnOff >> Complete");
return true;
}
Log.D("SetLaserOnOff >> Fail");
return false;
}
bool IScannerACS.SetRamppingOffParameter(double pos, double overlap, double endpower,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rRampingOFFStartPosX, pos + camOffsetX) &
WriteRealVariable(rRampingOFFOverlapDist, overlap) &
WriteRealVariable(rRampingOFFEndPower, endpower))
{
Log.D("SetRamppingOffParameter >> Complete");
return true;
}
Log.D("SetRamppingOffParameter >> Fail");
return false;
}
bool IScannerACS.SetRamppingOnParameter(double overlap, double startpower)
{
if (WriteRealVariable(rRampingONOverlapDist, overlap) &
WriteRealVariable(rRampingONStartPower, startpower))
{
Log.D("SetRamppingOnParameter >> Complete");
return true;
}
Log.D("SetRamppingOnParameter >> Fail");
return false;
}
// ── Teaching Position ─────────────────────────────────────────────────
bool IScannerACS.SetWeldingTeachingPosition1(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition1PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition1PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition1 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition1 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition2(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition2PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition2PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition2 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition2 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition3(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition3PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition3PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition3 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition3 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition4(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition4PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition4PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition4 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition4 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition5(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition5PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition5PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition5 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition5 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition6(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition6PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition6PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition6 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition6 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition7(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition7PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition7PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition7 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition7 >> Fail");
return false;
}
bool IScannerACS.SetWeldingTeachingPosition8(double PosX, double PosY,
double camOffsetX, double camOffsetY)
{
if (WriteRealVariable(rWeldingPosition8PosX, PosX + camOffsetX) &
WriteRealVariable(rWeldingPosition8PosY, PosY + camOffsetY))
{
Log.D($"SetWeldingTeachingPosition8 ({PosX}/{PosY}) >> Complete");
return true;
}
Log.D("SetWeldingTeachingPosition8 >> Fail");
return false;
}
// ── 레이저 ───────────────────────────────────────────────────────────
bool IScannerACS.SetLaserIOUse(bool on)
{
if (WriteRealVariable(iLaserUse, on ? 1 : 0))
{
Log.D($"SetLaserIOUse {on} >> Complete");
return true;
}
Log.D("SetLaserIOUse >> Fail");
return false;
}
// 26.04.09 NDY iPCset_ALINE_LCTYPE — Scanner xlsx 기준 미사용
bool IScannerACS.SetLCILserOn(bool on)
{
Log.D("SetLCILserOn >> Not Used in Scanner");
return true;
}
bool IScannerACS.SetWeldingAxes(int axisXnum, int axisYnum)
{
if (WriteVariableInt(iXAxisNumber, axisXnum) &
WriteVariableInt(iYAxisNumber, axisYnum))
{
Log.D("SetWeldingAxes >> Complete");
return true;
}
Log.D("SetWeldingAxes >> Fail");
return false;
}
bool IScannerACS.IsLaserOn()
{
if (!IsActivated || !IsConnected) return false;
return ReadVariableInt(IsLaserOn) > 0;
}
// ── 알람 ─────────────────────────────────────────────────────────────
bool IScannerACS.ResetAlarm()
{
TerminalCommand("FCLEAR ALL");
return WriteVariableInt(AlarmReset, 1);
}
void IScannerACS.AllAxisServoOff()
{
if (!IsActivated || !IsConnected) return;
SetMotorDisableAll();
}
bool IScannerACS.IsActivated() => IsActivated;
// 왜 없앴지.. 26.04.13
internal bool IsReachedTeachingPosition(eTeachingPosition targetPos)
{
switch (targetPos)
{
case eTeachingPosition.Load:
return _motorVariable.IsLoadPosition;
case eTeachingPosition.UnLoad:
return _motorVariable.IsUnloadPosition;
case eTeachingPosition.SafetyPosition:
return _motorVariable.IsSafetyPosition;
case eTeachingPosition.StageWeldingStartPos:
return _motorVariable.IsWeldingStartPosition;
default:
return false;
}
}
}
}