튜토리얼 · Chapter 2
title: "첫 프로젝트 — 컨베이어 + 센서 + 시퀀스" chapter: 2 source: "Doc/QMachineStudio UserManaul.pdf"
첫 프로젝트 — 컨베이어 + 센서
빈 프로젝트에서 시작해 컨베이어 모터 1축 + 도착 센서 1개 + 간단한 Pick & Place 시퀀스 를 완성하는 튜토리얼입니다.
이 과정을 마치면 XScript 에서 모터·IO·시퀀스가 어떻게 엮이는지 전체 그림이 보입니다.
프로젝트 생성
- File → New Project →
FirstProject이름으로 생성. - 화면 해상도는 기본값(1920×1080) 유지.
- Solution Explorer 에
Run1,View1모듈이 자동 생성됨.
IO 정의
Tools → IO Editor 에서 입력 2개와 출력 1개를 등록합니다.
| 이름 | 타입 | 설명 |
|---|---|---|
I_StartBtn | DI | 시작 버튼 |
I_CnvSens | DI | 컨베이어 도착 센서 |
O_CnvRun | DO | 컨베이어 모터 기동 릴레이 (테스트용) |
모터 정의
Tools → Motor Editor 에서 축 하나를 등록합니다.
| 항목 | 값 |
|---|---|
| Name | M_Cnv |
| Board | (실제 보드 또는 가상 축) |
| UnitPerPulse | 1.0 |
| JogVel / RunVel | 100 / 300 |
| JogAccel / RunAccel | 0.2 / 0.3 |
시퀀스 작성
Run1.xms 에 다음 코드를 작성. 여는 중괄호는 항상 다음 줄.
// 모듈 변수
int cycleCount = 0;
FUNCTION OnSystemStart()
{
Log("Start");
TOWERLAMP.SetLamp("RUN");
return true;
}
FUNCTION OnSystemStop()
{
MOTOR["M_Cnv"].Stop();
IO["O_CnvRun"] = OFF;
TOWERLAMP.SetLamp("STOP");
return true;
}
////SEQUENCE,Seq
////STEP,STEP_Idle
Sleep(100);
if (IO["I_StartBtn"] == OFF)
{
return false;
}
Log($"Cycle {cycleCount} begin");
////STEP,STEP_Run
IO["O_CnvRun"] = ON;
MOTOR["M_Cnv"].SetSpeed("RUN");
if (MOTOR["M_Cnv"].MoveVel(true) == false)
{
MOTOR["M_Cnv"].ShowMotorError(ModuleName);
goto "STEP_Error";
}
////STEP,STEP_WaitSensor
if (IO["I_CnvSens"].CheckContiOn(500) == false)
{
// 아직 도착하지 않음
return false;
}
MOTOR["M_Cnv"].Stop();
IO["O_CnvRun"] = OFF;
cycleCount++;
Log($"Cycle {cycleCount} done");
goto "STEP_Idle";
////STEP,STEP_Error
TOWERLAMP.SetLamp("ERROR");
Sleep(1000);
goto "STEP_Idle";화면 배치
View1.xdf 를 열어 버튼 1개, 텍스트 1개 를 배치합니다.
- Button
btnStart→ Click 이벤트에OnStartClick함수 연결 - TextBlock
txtCount→{Binding Run1::cycleCount}
// View1.xms
FUNCTION OnStartClick(string sender, int tag, array params)
{
IO["I_StartBtn"].WriteBit(ON);
Sleep(200);
IO["I_StartBtn"].WriteBit(OFF);
}실행과 확인
- Build → Build All → 에러가 없는지 확인.
- Run 버튼 (Ctrl+R) 으로 시작.
- View1 화면의 Start 버튼을 눌러 사이클 시작.
I_CnvSens가 ON 되면cycleCount가 증가하고 IDLE 로 복귀.
무엇을 배웠나
////STEP,STEP_이름으로 시퀀스를 상태 기반으로 분할하는 방법goto "STEP_이름"으로 상태 전이IO["이름"].CheckContiOn(ms)로 노이즈 방지 대기MOTOR["이름"].MoveVel(true)속도 모드 +Stop()정지 패턴TOWERLAMP.SetLamp(state)로 사용자 시각 피드백- View 와 Run 모듈 간 변수 바인딩 (
Run1::cycleCount)