MOTF (Marking On The Fly)를 사용하기 위해서는 외부 스테이지, 컨베이어 와 같은 이송장치에서 발생되는 엔코더(Encoder) 이동량 신호를 RTC 에 물리적인 배선을 통해 입력시켜주어야 합니다.
이후 1mm 를 이동시켰을때 실제 엔코더 펄스가 몇개 입력되는지를 측정하여 이를 EncXCountsPerMm 속성값에 지정합니다.
‘N’ 을 눌러 MotfWithFollowOnly 함수가 호출되게 되고 MOTF 가동이 시작되고 실제 이송 장치를 조그 혹은 손으로 움직이게 되면, 스캐너의 중심 0,0 위치가 이송 장치를 따라가는 모습을 볼 수 있습니다. 여기까지 완료되었다면 모든 준비는 되었습니다.
리스트에 삽입된 데이타의 가공 시작을 근접 센서등을 이용한 외부 트리거 방식을 사용하고자 하면, RTC 카드의 /START 쪽과 배선을 하고 외부 제어 모드를 사용하도록 설정(CtlExternalControl) 해야 합니다. 또한 매 트리거 입력 마다 엔코더 기준 위치가 리셋(Reset) 되어야 하므로, 이에 대한 추가 기능을 활성화 하세요.
static void Main(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
var rtcMOTF = rtc as IRtcMOTF;
//엔코더 스케일 설정
rtcMOTF.EncXCountsPerMm = 2000;
rtcMOTF.EncYCountsPerMm = 2000;
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("'R' : encoder reset");
Console.WriteLine("'N' : MOTF With Follow Only");
Console.WriteLine("'C' : MOTF With Circle And Wait Encoder");
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.R:
// X,Y 엔코더값을 0,0 으로 리셋합니다.
rtcMOTF.CtlEncoderReset();
// 가상 엔코더를 100mm/s 으로 동작시킵니다.
//rtcMOTF.CtlEncoderSpeed(100, 100);
//rtcMOTF.CtlEncoderSpeed(0, 0);
break;
case ConsoleKey.N:
MotfWithFollowOnly(laser, rtc, false);
break;
case ConsoleKey.C:
MotfWithCircleAndWaitEncoder(laser, rtc, false);
break;
}
Console.WriteLine($"processing time = {timer.ElapsedMilliseconds / 1000.0:F3}s");
} while (true);
rtc.Dispose();
}
/// <summary>
/// 스캐너가 0,0 을 지속적으로 포인팅 한다 (스테이지나 컨베이어를 손으로 밀어보면서 테스트)
/// </summary>
private static void MotfWithFollowOnly(ILaser laser, IRtc rtc, bool externalStart)
{
var motf = rtc as IRtcMOTF;
//리스트 시작
rtc.ListBegin(laser, ListType.Single);
//MOTF 시작
//ListMOTFBegin 부터 ListMOTFEnd 사이의 모든 list 명령어는 엔코더 증감값이 적용됩니다
motf.ListMOTFBegin();
//0,0 으로 점프
rtc.ListJump(new Vector2(0, 0));
//10 초동안 대기
rtc.ListWait(1000 * 10);
// MOTF 중지
motf.ListMOTFEnd(Vector2.Zero);
rtc.ListEnd();
if (externalStart)
{
// RTC 15핀 커넥터에 있는 /START 을 리스트 시작 트리거로 사용합니다.
var extCtrl = new RtcExternalControlMode();
extCtrl.Add(RtcExternalControlMode.Signal.ExternalStart);
extCtrl.Add(RtcExternalControlMode.Signal.ExternalStartAgain);
motf.CtlExternalControl(extCtrl);
}
else
{
//외부 트리거(/START)가 아닌 직접 execute 호출하여 실행
motf.CtlExternalControl(RtcExternalControlMode.Empty);
rtc.ListExecute();
}
}
private static void MotfWithCircleAndWaitEncoder(ILaser laser, IRtc rtc, bool externalStart)
{
var motf = rtc as IRtcMOTF;
//리스트 시작
rtc.ListBegin(laser, ListType.Single);
//직선을 그립니다. (엔코더 입력과 무관합니다)
rtc.ListJump(new Vector2(0, 0));
rtc.ListMark(new Vector2(0, 10));
rtc.ListMark(new Vector2(0, 0));
// ListMOTFBegin 부터 ListMOTFEnd 사이의 모든 list 명령어는 엔코더증감값이 적용됩니다
motf.ListMOTFBegin();
// 엔코더 X 값이 10mm 가 넘을때(Over) 까지 리스트 명령들이 모두 대기됨
motf.ListMOTFWait(RtcEncoder.EncX, 10, EncoderWaitCondition.Over);
//엔코더 X 값이 위 조건을 만족한 이후 원 을 그린다
rtc.ListJump(new Vector2((float)10, 0));
rtc.ListArc(new Vector2(0, 0), 360.0f);
// MOTF 중지및 0,0 위치(스캐너 중심 위치)로 jump 실시
motf.ListMOTFEnd(Vector2.Zero);
rtc.ListEnd();
if (externalStart)
{
// RTC 15핀 커넥터에 있는 /START 을 리스트 시작 트리거로 사용합니다.
var extCtrl = new RtcExternalControlMode();
extCtrl.Add(RtcExternalControlMode.Signal.ExternalStart);
extCtrl.Add(RtcExternalControlMode.Signal.ExternalStartAgain);
motf.CtlExternalControl(extCtrl);
}
else
{
//외부 트리거(/START) 미사용
motf.CtlExternalControl(RtcExternalControlMode.Empty);
rtc.ListExecute();
}
}