1. 파워 메터
다양한 상용 파워메터를 이용한 레이저의 출력 에너지 측정을 지원합니다. 우선 아래와 같이 파워메터 객체를 생성하고 이를 편집기(SiriusEditorForm) 에 지정해 줍니다.
var pm = new PowerMeterVirtual(0, "Virtual");
//var pm = new PowerMeterOphir(0, "USBI", "SERIALNO");
//var pm = new PowerMeterCoherentPowerMax(0, "Coherent", 1);
//var pm = new PowerMeterThorLabsPMSeries(0, "PM100USB", "SERIALNO");
pm.Initialize();
this.siriusEditorForm1.PowerMeter = pm;
파워메터 객체를 편집기에 지정하게 되면 팝업 가능한 메뉴가 활성화 됩니다. (단축키: F8)

계측 시작 (Start)을 하게 되면 파워메터에 설정된 샘플링 주기(Hz) 에 의해 측정된 값(모델에 따라 다양한 계측 정보들 예를 들어 Watt, Joules, Density 등)이 그래프로 출력됩니다.

2. 파워 매핑
파워메터를 이용하여 레이저 소스의 설정 파워 vs 실제 파워 에 해당하는 매핑 테이블을 구성할 수 있습니다.

이런 계측 테이블 값을 구하기 위해서는 레이저 소스의 출력을 점차 가변 하면서 파워메터를 이용한 계측을 하는 사용자 코드가 필요하며, 실제 구현을 위해서는 Demos\PowerMap 데모 프로젝트를 참고해 주시기 바랍니다. 참고 프로젝트에서는 이 파워 매핑을 진행 후 매핑파일을 생성/저장하게 됩니다.
이후 매핑 파일을 이용한 레이저 출력을 보정하는 방법은 다음과 같습니다.
//파워맵 (기본 버전) 생성
IPowerMap powerMap = new PowerMapDefault();
//혹은 이미 저장된 파워맵 파일 불러오기
var powerMapFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "map", "test.pmap");
PowerMapSerializer.Open(powerMap , powerMapFile);
//편집기에 지정
this.siriusEditorForm1.PowerMap = powerMap ;
//레이저 소스에 출력 보정을 위한 파워 매핑 지정
laser.PowerMap = powerMap ;
//레이저 출력을 2W 로 설정하기 (조회할 매핑 카테고리는 Default)
laser.CtlPower(2, "Default");
위와 같이 파워 매핑 파일을 불러들여 편집기에 지정해 줍니다. 이는 앞의 그래프를 이용한 파워매핑을 출력하는 용도로 사용됩니다. 또한 레이저 소스(ILaser)의 파워맵(PowerMap) 항목에 해당 매핑을 사용할 것을 지정해 준 후 레이저 출력을 2W 로 설정하게 되면 (CtlPower) 파워 매핑 테이블을 참고하여 보정된 출력값으로 변환됩니다.

통상 펜(IPen) 을 이용해 레이저 가공 파워(W)를 설정해 사용하게 되는데 이때 파워매핑을 사용하고자 하면, 파워 카테고리(Power Category)에서 해당 항목을 지정해 주어야 합니다.
3. 파워 매핑 루틴 사용자화 하기
파워맵 윈폼에서는 파워 매핑의 시작(Start), 중지(Stop) 를 제공합니다. 기본 제공되는 내부의 매핑 루틴은 아래와 유사합니다. (예를 들어 레이저 출력을 10단계로 나누어 파워를 측정 한 후 테이블에 저장하는 방식으로 구현됨)
protected virtual bool DoPowerMapping(IPowerMap powerMap, IPowerMeter powerMeter, IRtc rtc, ILaser laser, string category, uint holdTimeMs = 5000, int steps = 10, float thresholdWatt = 0)
{
bool success = true;
var powerControl = laser as SpiralLab.Sirius.IPowerControl;
Task.Run(() =>
{
rtc.CtlMove(0, 0);
powerMap.Clear(category);
powerMap.XGap = (float)Math.Round(laser.MaxPowerWatt / steps, 3);
powerMap.XName = "Watt (W)";
Logger.Log(Logger.Type.Warn, $"trying to start powermapping. target category= {category}");
powerMeter.CtlClear();
success &= powerMeter.CtlStart();
var sw = Stopwatch.StartNew();
for (int step = 1; step <= steps; step++)
{
sw.Restart();
if (Rtc.CtlGetStatus(RtcStatus.Aborted) || laser.IsError || powerMeter.IsError)
{
success &= false;
break;
}
float targetWatt = (laser.MaxPowerWatt / (float)steps) * (float)step;
targetWatt = (float)Math.Round(targetWatt, 1);
success &= powerControl.CtlPower(targetWatt, string.Empty); //not mapped
success &= rtc.CtlLaserOn();
do
{
Thread.Sleep(50);
} while (sw.ElapsedMilliseconds < holdTimeMs); //gathering after 5secs
if (!success)
break;
if (isMappingTerminated)
break;
float[] measuredArray = powerMeter.Data.ToArray();
float detectedWatt = measuredArray[measuredArray.Length - 1];
success &= rtc.CtlLaserOff();
if (thresholdWatt > 0)
{
if (detectedWatt < targetWatt) // 출력이 더 나오는건 허용
{
if (Math.Abs(targetWatt - detectedWatt) > thresholdWatt)
{
Logger.Log(Logger.Type.Error, $"powermap: out of range threshold: {thresholdWatt}W");
success &= false;
break;
}
}
}
success &= powerMap.Update(category, targetWatt, detectedWatt);
Logger.Log(Logger.Type.Info, $"powermap: target= {targetWatt}W -> detected= {detectedWatt}W. category= {category}");
if (!success)
break;
}
success &= rtc.CtlLaserOff();
success &= powerMeter.CtlStop();
if (success)
{
Logger.Log(Logger.Type.Info, $"success to mapping power. target category= {category}");
}
else
{
Logger.Log(Logger.Type.Error, $"fail to mapping power. target category= {category}");
}
});
return success;
}
이 루틴을 사용하지 않고 사용자가 직접 구현해야 한다면, PowerMap 객체를 상속받아 CtlStart/CtlStop 함수를 직접 구현(override) 할 수 있습니다. 이는 powermap 데모(Demos) 프로젝트에서 구현 방법을 참고해 주시기 바랍니다.

4. 모터 제어 연동
다양한 3rd Party 모션 제어기를 연동할 수 있도록, 최근 IMotor, IMotors 인터페이스 가 개선되었습니다. 예를 들어 3개의 모터축을 생성하여 이를 편집기와 연결한다면
var motorX = new MotorVirtual(0, "X");
motorX.Initialize();
var motorY = new MotorVirtual(1, "Y");
motorY.Initialize();
var motorZ = new MotorVirtual(2, "Z");
motorZ.Initialize();
var motorArray = new IMotor[3]
{
motorX,
motorY,
motorZ,
};
var motors = new MotorsDefault(0, "Group", motorArray);
this.siriusEditorForm1.Motors = motors;
여기에서는 가상의 모터축(MotorVirtual)객체를 생성하였습니다.

편집기에서 모터축 메뉴을 선택하면 아래와 같이 제어용 윈폼이 출력됩니다.

개별축에 대한 원점(홈) 초기화, -/+ 조그 이동, 리셋, 정지 등의 기본 제어를 제공하며, 개별축을 좀더 상세히 제어 (절대/상대 위치 이동 등) 하려면, 모터축 이름을 더블 클릭해 줍니다. 그러면 아래와 같이 개별축 제어용 윈폼창이 출력되어 상세한 제어가 가능합니다.

또한 모터창에서는 위치 테이블을 제공합니다. 여기서는 X,Y,Z 3축을 사용하므로 3축에 대한 위치/속도 테이블을 생성, 저장 할 수 있으며, 이동 명령시 개별 축의 이동 명령이 발생합니다. 사용자는 여러 위치등을 등록(Add) 하고 이동(Move)하는 기능으로 활용 가능합니다.

만약 특정 모터축만 구동하고자 한다면, 해당 모터 축의 위치(Position), 속도(Velocity) 값을 삭제(null) 해 주시기 바랍니다.

5. 스크립트 기능을 이용한 동적 텍스트 개체 변경
텍스트 개체의 가공시 스크립트를 이용해 사용자가 코드를 작성하고 이를 이용해 마킹 내용을 실시간 변경하는 기능을 제공하고 있습니다.

파일 이름 속성 항목에서 … 을 선택하게 되면 아래와 같이 스크립트 편집기 (C# 프로그램 언어) 가 나타납니다. 설정이 필요한 항목은 인스턴스 이름 (SpiralLab.Sirius.ScripDemo), 속성 이름 (CustomFormat1)가 필수적으로 필요합니다. 만약 인자 (Argument)를 전달하고자 한다면 “이름=값” 형태로 지정해 주시기 바랍니다.

해당 스크립트 코드를 작성 후에는 반드시 빌드, 실행을 통해 정상적인 코드 인지를 확인해야 합니다.


스크립트 기능을 활성화(Enabled) 한 후 마커창을 통해 실제 가공을 실시하게 되면, 해당 마킹 내용이 스크립트에 의해 변환된 모습을 확인할 수 있습니다.