하나의 RTC 제어 카드와 하나의 레이저 소스를 연결했더라도 레이저 빔을 분리(Split) 시켜 두 개의 스캐너 장치로 각각 입력 시켜 가공 성능을 2배로 극대화 하기 위해 듀얼 헤드(Dual Head) 옵션을 사용할 수 있습니다.
각각 Primary, Secondary 스캔 헤드로 부르며, 이를 위해 우선 두 번째 스캐너 장치에서도 필드 보정을 실시하고 신규 보정 파일을 준비해야 합니다. 이후 작업은 각각 스캐너의 원점 위치를 이동 시켜야 합니다. 경우에 따라서는 스캐너 장치가 약간 회전 된 상태로 장착되어 있을 수 있으므로, 이를 측정하고 회전량도 오프셋량과 함께 보정되도록 처리해 주세요
static void Main2(string[] args)
{
SpiralLab.Core.Initialize();
var rtc = new Rtc5(0); //create Rtc5 controller
float fov = 60.0f; // scanner field of view : 60mm
float kfactor = (float)Math.Pow(2, 20) / fov; // k factor (bits/mm) = 2^20 / fov
var correctionFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "correction", "cor_1to1.ct5");
rtc.Initialize(kfactor, LaserMode.Yag1, correctionFile); // 스캐너 보정 파일 지정
rtc.CtlFrequency(50 * 1000, 2); // laser frequency : 50KHz, pulse width : 2usec
rtc.CtlSpeed(100, 100); // default jump and mark speed : 100mm/s
rtc.CtlDelay(10, 100, 200, 200, 0); // scanner and laser delays
//이미 table1 에 로드 및 선택 완료 (initialize 의 인자에서 처리됨)
//var correctionFile1 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "correction", "cor_1to1.ct5");
//rtc.CtlLoadCorrectionFile(CorrectionTableIndex.Table1, correctionFile1);
var correctionFile2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "correction", "cor_1to1.ct5");
//secondary 스캐너 장치에 보정 파일 로드 (듀얼헤드용)
rtc.CtlLoadCorrectionFile(CorrectionTableIndex.Table2, correctionFile2);
rtc.CtlSelectCorrection(CorrectionTableIndex.Table1, CorrectionTableIndex.Table2);
ILaser laser = new LaserVirtual(0, "virtual", 20);
ConsoleKeyInfo key;
do
{
Console.WriteLine("Testcase for spirallab.sirius. powered by labspiral@gmail.com (https://sepwind.blogspot.com)");
Console.WriteLine("");
Console.WriteLine("'D' : draw circle with dual head offset");
Console.WriteLine("'Q' : quit");
Console.WriteLine("");
Console.Write("select your target : ");
key = Console.ReadKey(false);
if (key.Key == ConsoleKey.Q)
break;
Console.WriteLine("");
Console.WriteLine("WARNING !!! LASER IS BUSY ...");
var timer = Stopwatch.StartNew();
switch (key.Key)
{
case ConsoleKey.D:
//개별 헤드에 오프셋 및 회전 처리
var rtcDualHead = rtc as IRtcDualHead;
rtcDualHead.CtlHeadOffset(ScannerHead.Primary, new Vector2(5, 0), 0);
rtcDualHead.CtlHeadOffset(ScannerHead.Secondary, new Vector2(-5, 0), 0);
DrawCircle(laser, rtc);
// 원복
rtcDualHead.CtlHeadOffset(ScannerHead.Primary, Vector2.Zero, 0);
rtcDualHead.CtlHeadOffset(ScannerHead.Secondary, Vector2.Zero, 0);
break;
}
Console.WriteLine($"processing time = {timer.ElapsedMilliseconds / 1000.0:F3}s");
} while (true);
rtc.Dispose();
}
private static void DrawCircle(ILaser laser, IRtc rtc)
{
var rtcDualHead = rtc as IRtcDualHead;
//리스트 시작
rtc.ListBegin(laser);
//리스트 명령으로 오프셋 및 회전 처리 방법
//rtcDualHead.ListHeadOffset(ScannerHead.Primary, new Vector2(5, 0), 0);
//rtcDualHead.ListHeadOffset(ScannerHead.Secondary, new Vector2(-5, 0), 0);
for (int i = 0; i < 10; i++)
{
//직선을 그립니다.
rtc.ListJump(new Vector2(0, 0));
rtc.ListMark(new Vector2(10, 0));
rtc.ListJump(new Vector2((float)10, 0));
rtc.ListArc(new Vector2(0, 0), 360.0f);
}
//리스트 명령으로 오프셋 및 회전 처리 방법
//rtcDualHead.ListHeadOffset(ScannerHead.Primary, Vector2.Zero, 0);
//rtcDualHead.ListHeadOffset(ScannerHead.Secondary, Vector2.Zero, 0);
//리스트 종료
rtc.ListEnd();
//가공 실행및 완료 대기
rtc.ListExecute(true);
}