차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
다음 판 | 이전 판 | ||
platform:ethercat:100_api:20_eg:listmotion [2019/11/20 18:46] winoars 만듦 |
platform:ethercat:100_api:20_eg:listmotion [2024/07/08 18:23] (현재) |
||
---|---|---|---|
줄 1: | 줄 1: | ||
- | ======title====== | + | ======List Motion====== |
<alert type=" | <alert type=" | ||
+ | ListMotion 예제 소스 페이지입니다. | ||
</ | </ | ||
+ | \\ | ||
+ | ====다단속도==== | ||
+ | <callout type=" | ||
+ | \\ | ||
+ | ===example=== | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | ===C#=== | ||
+ | <sxh csharp> | ||
+ | private void btnTest_Click(object sender, EventArgs e) | ||
+ | { | ||
+ | // 하나의 축에 대해 위치별로 속도를 변경하여 속도 프로파일을 생성하는 예제 | ||
+ | // 가속구간과 감속 구간을 세구간으로 나누어 다른 속도 패턴으로 이송 (세단계 가속, 세단계 감속) | ||
+ | // 에러처리는 생략. | ||
+ | // 리스트모션 맵인덱스, | ||
+ | // 최대 8개까지 지원 됨 (0~7) | ||
+ | // 0~31번 축 중에서 리스트 모션에 참여하는 축의 Mask, | ||
+ | // 1,2,3 번 참여시 axisMask1 = 14 | ||
+ | uint axisMask1 = 0; | ||
+ | // 32~63번 축 중에서 리스트 모션에 참여하는 축의 Mask, | ||
+ | uint axisMask2 = 0; | ||
+ | int speedMode = (int)ec.EEcmSpeedMode.ecmSMODE_TRAPE; | ||
+ | int stepID = 0; | ||
+ | | ||
+ | if (axisList.Count() < 31) | ||
+ | { | ||
+ | axisMask1 = (uint)(1 << axisID); | ||
+ | axisMask2 = 0; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | axisMask1 = 0; | ||
+ | axisMask2 = (uint)(0x01 << (axisID - 32)); | ||
+ | } | ||
+ | lmMapIndex = 0; | ||
- | =====Case 1===== | + | double initSpeed |
+ | double endSpeed | ||
+ | double workSpeed | ||
+ | double accel = 0; | ||
+ | double decel = 0; | ||
- | <callout type=" | + | |
+ | // 리스트 모션 기능을 시작한다. | ||
+ | // 이후 실행되는 명령은 리스트모션 테이블에 등록되며, | ||
+ | ec.ecmLmCtl_Begin(netID, | ||
- | | + | // lmMapIndex 에 해당하는 리스트모션 테이블에 등록되어 있는 모든 스텝을 제거한다. |
- | </callout> | + | |
+ | |||
+ | | ||
+ | initSpeed = 0; | ||
+ | endSpeed = 20000; | ||
+ | accel = 10000; | ||
+ | decel = 0; // 감속이 없으므로 decel = 0 | ||
+ | workSpeed = endSpeed; | ||
+ | ec.ecmSxCfg_SetSpeedPatt(netID, | ||
+ | |||
+ | // 실행되는 명령에 ID 를 부여한다. | ||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | // 이송 예약 | ||
+ | ec.ecmSxMot_MoveStart(netID, | ||
+ | | ||
+ | // 다음 속도 패턴으로 이어지고 가속과 정속만 존재하는 경우 | ||
+ | initSpeed = endSpeed; // 이전속도 패턴에서 이어지므로 이전 속도 패턴의 endSpeed가 InitSpeed가 된다. | ||
+ | endSpeed = 40000; // | ||
+ | accel = 20000; | ||
+ | decel = 0; | ||
+ | workSpeed = endSpeed; // 감속이 없는 경우 workSpeed와 endSpeed는 같다. | ||
+ | ec.ecmSxCfg_SetSpeedPatt(netID, | ||
+ | // 이송 예약 | ||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmSxMot_MoveStart(netID, | ||
+ | // 다음 속도 패턴으로 이어지고 가속과 정속, 감속이 존재하는 경우 | ||
+ | initSpeed = endSpeed; // 이전속도 패턴에서 이어지므로 이전 속도 패턴의 endSpeed가 InitSpeed가 된다. | ||
+ | endSpeed = 40000; // | ||
+ | accel = 10000; | ||
+ | decel = 10000; | ||
+ | workSpeed = 50000; | ||
+ | ec.ecmSxCfg_SetSpeedPatt(netID, | ||
- | <callout type=" | + | // 이송 예약 |
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmSxMot_MoveStart(netID, | ||
+ | // 가속 없이 정속 이송 후, 감속하는 경우 | ||
+ | initSpeed = endSpeed; // 이전속도 패턴에서 이어지므로 이전 속도 패턴의 endSpeed가 InitSpeed가 된다. | ||
+ | endSpeed = 20000; // | ||
+ | accel = 0; // 가속이 없으므로 accel = 0 | ||
+ | decel = 20000; | ||
+ | workSpeed = initSpeed; // 이전속도 패턴에서 이어지며, | ||
+ | ec.ecmSxCfg_SetSpeedPatt(netID, | ||
- | </callout> | + | |
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmSxMot_MoveStart(netID, | ||
+ | // 감속 후 이송완료 | ||
+ | initSpeed = endSpeed; // 이전속도 패턴에서 이어지므로 이전 속도 패턴의 endSpeed가 InitSpeed가 된다. | ||
+ | endSpeed = 0; // | ||
+ | accel = 0; // 가속이 없으므로 accel = 0 | ||
+ | decel = 10000; | ||
+ | workSpeed = initSpeed; | ||
+ | ec.ecmSxCfg_SetSpeedPatt(netID, | ||
+ | // 이송 예약 | ||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmSxMot_MoveStart(netID, | ||
+ | | ||
+ | // 등록된 명령 실행 시작 | ||
+ | ec.ecmLmCtl_Run(netID, | ||
+ | | ||
+ | int runStepCount = 0, runStepID = 0, runStepState = 0; | ||
+ | int timeLimit = 100000; | ||
+ | Stopwatch sw = new Stopwatch(); | ||
+ | sw.Start(); | ||
+ | bool isSuccess = false; | ||
- | <callout type=" | + | // 이송 시간이 timeLimit 보다 크면 에러처리. 본 예제에서는 생략한다. |
+ | Task.Factory.StartNew(() | ||
+ | { | ||
+ | while (sw.ElapsedMilliseconds < timeLimit) | ||
+ | { | ||
+ | // 현재 실행되고 있는 스텝에 대한 정보를 확인한다. | ||
+ | ec.ecmLmSt_GetRunStepInfo(netID, | ||
+ | // runStepID : 현재 실행되고 있는 StepID | ||
+ | // runStepState : 현재 실행되고 있는 Step의 상태 (Ready, Busy, Paused, Completed) | ||
+ | // 현재 실행되고 있는 StepID가 마지막 등록된 StepID와 같고, 실행 상태가 Complete 이면 리스토 모션 종료로 판단 | ||
+ | // StepCount로 비교하거나 ecmLmSt_GetRemStepCount 를 이용하여 RemStep 등으로 비교해도 된다. | ||
+ | if (runStepID == stepID && runStepState == (int)ec.EEcmLmCmdItemSts.ecmLM_CMDITEM_STS_COMPLETED) | ||
+ | { | ||
+ | isSuccess = true; | ||
+ | break; | ||
+ | } | ||
+ | // 진행상황 처리 | ||
+ | // lblRunStepCount.BeginInvoke(new Action(() => lblRunStepCount.Text = runStepCount.ToString())); | ||
+ | // lblRunStepID.BeginInvoke(new Action(() => lblRunStepID.Text = runStepID.ToString())); | ||
+ | // lblRunStepState.BeginInvoke(new Action(() => lblRunStepState.Text = ((ec.EEcmLmCmdItemSts)runStepState).ToString())); | ||
+ | Thread.Sleep(10); | ||
+ | } | ||
+ | |||
+ | if (!isSuccess) | ||
+ | { | ||
+ | // 에러처리 | ||
+ | } | ||
+ | //리스토 모션 종료. 이후 이송 명령은 즉시 실행 됨 | ||
+ | ec.ecmLmCtl_End(netID, | ||
+ | }); | ||
+ | |||
+ | if (!isSuccess) | ||
+ | { | ||
+ | // 에러처리 | ||
+ | } | ||
+ | } | ||
+ | </ | ||
</ | </ | ||
+ | \\ | ||
+ | ====연속 보간이송==== | ||
+ | <callout type=" | ||
+ | \\ | ||
+ | ===example=== | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | ===C#=== | ||
+ | <sxh csharp> | ||
+ | private void btnTest2_Click(object sender, EventArgs e) | ||
+ | { | ||
+ | // 말풍선 그리기 예제 | ||
+ | // 에러처리는 생략. | ||
+ | // 리스트모션 맵인덱스, | ||
+ | // 최대 8개까지 지원 됨 (0~7) | ||
+ | | ||
+ | // 보간 제어를 위한 맵인덱스 | ||
+ | lmMapIndex = 0; | ||
+ | int ixMapIndex = 0; | ||
+ | // 0~31번 축 중에서 리스트 모션에 참여하는 축의 Mask, | ||
+ | // 1,2,3 번 참여시 axisMask1 = 14 | ||
+ | uint axisMask1 = 0; | ||
+ | // 32~63번 축 중에서 리스트 모션에 참여하는 축의 Mask, | ||
+ | uint axisMask2 = 0; | ||
+ | | ||
+ | int axisX = axisList[cbxAxisX.SelectedIndex]; | ||
+ | int axisY = axisList[cbxAxisY.SelectedIndex]; | ||
+ | // axisX < 32 & axisY < 32 로 간주 | ||
+ | axisMask1 = (uint)((1 << axisX) + (1 << axisY)); | ||
+ | | ||
+ | // lmMapIndex 에 해당하는 리스트모션 테이블에 등록되어 있는 모든 스텝을 제거한다. | ||
+ | ec.ecmLmCtl_ClearQue(netID, | ||
+ | // 리스트 모션 기능을 시작한다. | ||
+ | // 이후 실행되는 명령은 리스트모션 테이블에 등록되며, | ||
+ | ec.ecmLmCtl_Begin(netID, | ||
- | <button collapse=" | + | // 보간맵 설정을 위한 axisList |
- | <collapse id=" | + | int[] ixAxisList |
- | <well> | + | |
- | {{page> | + | |
- | </well></collapse> | + | ec.ecmIxCfg_MapAxes(netID, |
+ | |||
+ | int speedType = 1; // | ||
+ | int speedMode = (int)ec.EEcmSpeedMode.ecmSMODE_TRAPE; | ||
+ | |||
+ | // 첫번째 이송의 속도 설정 (가속만 설정) | ||
+ | // endSpeed = workSpeed. decel = 0; | ||
+ | ec.ecmIxCfg_SetSpeedPatt(netID, | ||
+ | |||
+ | int stepID = 0; | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | // 두번째 ~ 마지막 두번째 이송까지의 속도 설정 (정속만 설정) | ||
+ | // initSpeed, endSpeed = workSpeed. accel, decel = 0; | ||
+ | ec.ecmIxCfg_SetSpeedPatt(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_ArcAng_A(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_ArcAng_A(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_ArcAng_A(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_ArcAng_A(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | // 마지막 이송 속도 설정 (감속만 설정) | ||
+ | // initSpeed = workSpeed. accel, endSpeed = 0; | ||
+ | ec.ecmIxCfg_SetSpeedPatt(netID, | ||
+ | |||
+ | ec.ecmLmCfg_SetStepId(netID, | ||
+ | ec.ecmIxMot_LineTo(netID, | ||
+ | |||
+ | // 등록된 명령 실행 시작 | ||
+ | ec.ecmLmCtl_Run(netID, | ||
+ | |||
+ | int runStepCount = 0, runStepID = 0, runStepState = 0; | ||
+ | |||
+ | const int timeLimit = 10000; | ||
+ | Stopwatch sw = new Stopwatch(); | ||
+ | sw.Start(); | ||
+ | bool isSuccess = false; | ||
+ | |||
+ | // 이송 시간이 timeLimit 보다 크면 에러처리. 본 예제에서는 생략한다. | ||
+ | // 이송 시간이 timeLimit 보다 크면 에러처리. 본 예제에서는 생략한다. | ||
+ | Task.Factory.StartNew(() => | ||
+ | { | ||
+ | while (sw.ElapsedMilliseconds | ||
+ | { | ||
+ | // 현재 실행되고 있는 스텝에 대한 정보를 확인한다. | ||
+ | ec.ecmLmSt_GetRunStepInfo(netID, | ||
+ | |||
+ | // runStepID : 현재 실행되고 있는 StepID | ||
+ | // runStepState : 현재 실행되고 있는 Step의 상태 (Ready, Busy, Paused, Completed) | ||
+ | |||
+ | // 현재 실행되고 있는 StepID가 마지막 등록된 StepID와 같고, 실행 상태가 Complete 이면 리스토 모션 종료로 판단 | ||
+ | // StepCount로 비교하거나 ecmLmSt_GetRemStepCount 를 이용하여 RemStep 등으로 비교해도 된다. | ||
+ | if (runStepCount | ||
+ | { | ||
+ | isSuccess = true; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | lblRunStepCount.BeginInvoke(new Action(() => lblRunStepCount.Text = runStepCount.ToString())); | ||
+ | | ||
+ | | ||
+ | Thread.Sleep(10); | ||
+ | } | ||
+ | |||
+ | if (!isSuccess) | ||
+ | | ||
+ | // 에러처리 | ||
+ | } | ||
+ | //리스토 모션 종료. 이후 이송 명령은 즉시 실행 됨 | ||
+ | ec.ecmLmCtl_End(netID, | ||
+ | }); | ||
+ | |||
+ | if (!isSuccess) | ||
+ | | ||
+ | // 에러처리 | ||
+ | | ||
+ | } | ||
+ | </sxh> | ||
+ | </callout> | ||