[TicTacToe/02] CNC Plotter 제어 [TicTacToe/02] CNC Plotter 제어
C++을 이용해 CNC Plotter을 제어하는 라이브러리를 구현했다.
Implemented the library to control CNC plotter by using C++.
01. 스텝 모터
Step Motor 28BYJ-48 기준
스텝 모터는 움직이던 관성에 영향을 받지 않고, 일정한 각도만큼 회전하는 모터다. 스텝 모터는 신호를 읽고 해당하는 동작을 절차적으로 수행하며 모터를 회전시킨다. 구현에 사용한 28BYJ-48 모터는 5 wires 유니폴라 구조며, 정밀한 제어가 가능한 half-step 시퀀스를 이용한다. (더 자세한 서보 모터의 구조와 시퀀스는 아래 참고 자료를 읽는 것을 추천한다.)

28BYJ-48 스텝 모터의 5 wires는 각각 전원선, IN1-4와 연결된다. 5 wires 유니폴라 방식은 두 개의 코일로 구성되어 있는데, 각각의 코일은 IN1과 IN3, IN2와 IN4과 연결되어 있다. 각각의 선에 0-7 순서로 신호를 전달하면 시계 방향으로 모터가 회전한다. 시계 반대 방향으로 모터를 돌리고 싶다면, 역순으로 신호를 전달하면 된다.
// Switching Seq
// Step | IN1 IN2 IN3 IN4
// ----- | ----------------
// 0 | 0 0 0 1
// 1 | 0 0 1 1
// 2 | 0 0 1 0
// 3 | 0 1 1 0
// 4 | 0 1 0 0
// 5 | 1 1 0 0
// 6 | 1 0 0 0
// 7 | 1 0 0 1
- 참고 자료
02. 아두이노용 라이브러리 제작
아두이노는 Stepper라는 스텝 모터 제어 라이브러리를 제공한다. 원래는 Stepper 라이브러리를 이용해 제어 프로그램을 작성할 예정이었으나, 디지털 핀에 꼽힌 x와 y축 담당 스텝 모터가 단방향으로만 이동하는 오류가 발생했다. 이 오류는 랜덤으로 발생해 명확한 원인을 알아내기 어려웠다. 예를 들어, 처음에는 양방향으로 잘 돌아가던 모터가 같은 코드 상에서 갑자기 단방향으로만 돌아가는 모습을 보였다. 이 문제를 해결하고자 28BYJ-48 스텝 모터를 제어하는 전용 라이브러리를 다시 만들었다.
C++ 기초 다지기
스텝 모터 제어 라이브러리와 로봇 제어 코드는 전부 C++으로 구현했다. C++의 클래스와 포인터, 참조, 복사를 다룬 아래 두 글은 라이브러리를 구현하며 공부한 내용이다.
문제 상황 및 해결
-
모터의 속도 저하 문제.
하나 하나 핀을 설정해주는 것과 그 내용을 함수로 묶은거랑 움직임 속도 차이가 난다. 하드웨어적인 문제라서 정확한 원인은 모르겠다. -
병렬 연산을 지원하지 않는 아두이노.
대각선을 그리기 위해서는 x,y 축이 동시에 움직여야 한다. 하지만 아두이노는 병렬 연산을 지원하지 않기 때문에std::thread()를 사용할 수 없다. 처음에는 아두이노에서의 멀티 테스킹을 가능케 만드는Scheduler를 사용하려고 했다. 구현해야 하는 대각선 그리는 코드는 n_steps를 받아 그 크기만큼 x, y 스텝모터를 동시에 움직여야 하는데, 스케줄러는 정적 함수만을 파라미터로 받기 때문에 구현이 불가능했다. 이 문제는MultiStepper(&stepper_x, &stepper_y)클래스를 구현해 해결했다. -
한 방향으로만 도는 모터. Seiral 통신을 통해 direction과 step_signal이 오류 없이 변화하는 것을 확인했음에도 회전 방향이 달라지지 않았다. 이 문제는 step 사이의 더 큰 delay() 값을 주며 해결되었다. 너무 적은 -나의 초깃값은 30이었다- 딜레이 시간은 모터에게 신호를 제대로 전달하지 못한다는 것을 알 수 있었고, 여러 시도 후 500을 딜레이 값으로 설정했다.
03. 그림 그리기 제어 코드
TicTacToeArtist
틱택토 아티스트 클래스는 3개의 스텝 모터를 이용해 O / X, 판을 그리는 제어용 클래스다. StepMotor.h 라이브러리를 이용해 3개의 스텝 모터 클래스를 선언한 후, 인자로 받아 사용한다.
#include "StepMotor.h"
Stepper stepper_x(8, 9, 10, 11);
Stepper stepper_y(3, 4, 5, 6);
Stepper stepper_z(A5, A4, A3, A2);
TicTacToeArtist artist(21, 21, &stepper_x, &stepper_y, &stepper_z);
void setup(){
Serial.begin(115200);
Serial.println("Setup complete");
};
void loop() {
Serial.println("delay");
delay(3000);
artist.resetPosition();
artist.drawGameBoard(); // 게임 보드 그리기
delay(2000); // 잠시 대기
Serial.println("Drawing X...");
artist.drawX(0); // 'X' 그리기
delay(2000); // 잠시 대기
Serial.println("Drawing Circle...");
artist.drawCircle(0); // 'O' 그리기
delay(2000); // 잠시 대기
Serial.println("end");
delay(1000000);
};
04. 시리얼 통신 제어
로봇은 AI의 선택을 현실세계로 가져오는 역할이며, 이를 구현하기 위해 python에서 시리얼 통신을 실행했다. 이 부분은 오목 로봇팔 구현과 매커니즘이 유사하기 때문에 별도로 설명하지 않는다. 방법이 궁금하다면 하단의 오목 문서에서 확인할 수 있다.
실제 움직임

- 이 버전은 최종 완성본으로, 로봇 제작을 제외한 AI • CV 부분은 강화시스터즈 01 세션 부원이 마무리했다.