지금까지 AI Turret을 기능별로 두 가지 부분으로 나뉘어 제작 및 실험을 진행하였다. Stbilizer와 Turret 부분 모두 원활하게 동작하지 않았지만, 드디어 개별 테스트를 성공적으로 마무리 하였다!
앞으로 두 기능을 합쳐 AI Turret을 구성하는 일만 남았다!! 😸
아래에서 설명할 코드가 너무 길어서, 설명하기 편하게 일부만 업로드하였다.
이전 일지에서 PC-ESP32 간의 통신을 위해, 데이터 전송의 실시간성을 확보하고자 YOLOv5에서 Object를 탐지하였을 때만 인위적으로 Delay를 주었다.
- detect.py 중 일부
for *xyxy, conf, cls in reversed(det):
c = int(cls)
label = names[c] if hide_conf else f'{names[c]}'
confidence = float(conf)
confidence_str = f'{confidence:.2f}'
x_center = (xyxy[0] + xyxy[2]) / 2
y_center = (xyxy[1] + xyxy[3]) / 2
print(f"{x_center:.2f}, {y_center:.2f}\n")
time.sleep(1) # 동일한 송-수신 타이밍을 위한 Delay
결과적으로 정상적으로 동작하는 듯 보였으나, Delay가 발생하는 만큼 YOLO의 FPS가 급격하게 감소하였다.
따라서 “time.sleep(1)”를 대체하여, 통신을 정상 작동시켜줄 다른 문제 해결 방안이 필요하였다.
종합설계 일지#6 YOLOv5...에 있는 방법과 동일하게 YOLOv5 내에 있는 detect.py가 아닌 별도의 “ESP32.py”을 만들어 문제를 해결하는 방향으로 접근하였다.
- ESP32.py 중 일부
while True:
output = process.stdout.readline().strip()
match = re.search('(\d+\.\d+), (\d+\.\d+)', output)
if match:
x = float(match.group(1))
y = float(match.group(2))
packet = f"{x:.2f},{y:.2f}\n"
ser.write(packet.encode())
ser.flush()
print(packet)
ser.close()
위 코드를 통해 인위적으로 Delay를 주어 싱크를 맞추지 않아도, 바운딩 박스 중앙값이 원활히 전송되었다.
지금까지 PC-ESP32 통신 중, YOLO에서 추출된 B.Box의 중앙 좌표값이 ESP32.py를 거쳐 제대로 전송이 이루어지지 않았기에 불완전한 통신이 이루어진 것으로 보인다.
마치 ESP32.py를 detect.py의 데이터를 잠시 저장해주는 버퍼로 사용 하여 ESP32와 안정적인 통신을 한 것이다.
PC-ESP32 간의 안정적인 통신이 가능해졌기에 WebCam을 활용하여 Tracking 실험을 진행하였다. 정상적인 통신을 기반으로 성공적인 실험이 가능하다는 판단을 하였지만, Tracking이 이루어지기는 하나 정상적으로 동작한다고 판단할 수 없었다.
이동평균 필터를 더하여 갑작스러운 좌표값의 변화에도 Airsoft Gun이 안정적으로 동작할 수 있도록 설계하였다.
- AI_Turret.ino 중 일부
while (mySerial.available() > 0) {
String command = mySerial.readStringUntil('\n');
Serial.println(command);
int index1 = command.indexOf(',');
int index2 = command.length();
int x = command.substring(0, index1).toInt();
int y = command.substring(index1 + 1, index2).toInt();
xValues[xIndex] = x;
yValues[yIndex] = y;
int xSum = 0;
int ySum = 0;
for (int i = 0; i < filterSize; i++) {
xSum += xValues[i];
ySum += yValues[i];
}
int filteredX = xSum / filterSize;
int filteredY = ySum / filterSize;
xIndex = (xIndex + 1) % filterSize;
yIndex = (yIndex + 1) % filterSize;
int centerX = 640; // X 중앙 위치 (1280의 중앙)
int centerY = 200; // Y 중앙 위치 (720의 중앙)
~~~
이동평균필터를 거친 중앙 좌표값의 X, Y를 사용하여 Servo Motor가 동작하도록 만들었다. 이때, Tilt Servo Motor 2개가 서로 뒤집혀서 위치해있기에 각각 반대 방향으로 동작하도록 설계하였다.
- ESP.ino 중 일부
if(filteredY >= 40 && filteredY < 80){
servoY1.write(a-5);
servoY2.write(b+5);
}
else if(filteredY >= 80 && filteredY < 120){
servoY1.write(a-3);
servoY2.write(b+3);
}
else if(filteredY >= 120 && filteredY < 160){
servoY1.write(a-1);
servoY2.write(b+1);
}
else if(filteredY >= 160 && filteredY < 200){
Serial.println("shotting");
}
else if(filteredY >= 200 && filteredY < 240){
Serial.println("shotting");
}
else if(filteredY >= 240 && filteredY < 280){
Serial.println("shotting");
}
else if(filteredY >= 280 && filteredY < 320){
servoY1.write(a+1);
servoY2.write(b-1);
}
else if(filteredY >= 320 && filteredY < 360){
servoY1.write(a+3);
servoY2.write(b-3); }
else if(filteredY >= 360 && filteredY < 400){
servoY1.write(a+4);
servoY2.write(b-4);
}
else if(filteredY >= 400 && filteredY < 450){
servoY1.write(a+5);
servoY2.write(b-5);
}
~~~
위 코드를 보면 YOLO가 탐지하는 픽셀 크기를 기반으로 동작 영역을 만들어 둔 것을 볼 수 있다. 이전에 “map” 함수를 사용하여 Tracking을 시도하였는데, WebCam의 화면 비율과 픽셀 수를 정확히 파악하기 어려워 위와 같이 영역 별로 동작을 설정해두었다.
AI Turret의 동작에 필요한 전원을 별도의 Power Supply(5V-7A)를 사용하여 회로를 구성할 계획이었다. 이때, Power Supply에서 220V를 5V로 승압하는 과정을 거쳐, OutPut-V로 출력이 된다.
기존 계획은 OutPut-V을 브레드보드를 사용하여 서보모터와 ESP32를 연결할 계획이었지만, 브레드보드는 1A까지의 허용 범위를 가졌기에 사용할 수 없었다.
따라서 이 문제를 해결할 수 있는 방안이 필요하였고, 대안으로 “고정식 단자대”와 “쇼트바”로 정했다.
현재 AI Turret에 사용되는 Servo Motor는 총 7개로 서보모터 1개당 소요되는 최대 전 압은 6V 환경에서의 800mA이다. 따라서 모든 Servo Motor가 동작한다고 가정하였을 때, Servo Motor만 5.6A를 소요하게 된다.
이외에도 ESP32에 연결되어 있는 각종 Sensor 및 여러 장비들을 포함하면 충분히 6A를 넘기게 된다. 이러한 전압을 얇은 배선을 통하여 분배하게 되면, 배선이 과열되어 문제를 발생시킨다.
이러한 문제를 해결하기 위해 단자대를 사용하였으며, Power Supply에서 들어온 전원을 병렬로 분배하기 위해 단자대에 알맞은 쇼트바를 사용하였다.
위 사진과 동일하게 Power Supply, 단자대와 Servo Motor를 구성하여 AI Turret을 구동할 계획이다.
또한 Power Supply를 사용하는 도중, 어떠한 문제나 사고가 발생하였을 때 전원을 바로 차단해줄 수 있는 "Kill Switch“를 전원 회로에 포함시키기로 하였다.
Object를 사격하는 기능을 담당한 Airsoft Gun Module에 대한 동작 실험을 진행하였는데, BB탄이 격발되지 않는 문제가 발생하였다.
원인으로는 Module Frame에 피스톤이 끼여서 동작을 하지 못하는 것이었다.
Module 설계 전 실측 단계에서 문제가 발생한 것으로 판단되며, 이를 해결하기 위해 기존 Module 설계를 수정하여 피스톤의 움직임에 제한이 발생하지 않도록 재설계하였다.
재설계를 진행하기 전에, 기존 설계 파일을 확인하여 문제점을 파악하였다. 아래의 Airsoft Gun Gear Box을 살펴보면 양 옆으로 구조물이 튀어나온 것을 확인할 수 있다.
기존 설계에서는 이러한 부분까지 고려하여 설계를 하지 못하였고, 그 결과 정상적으로 동작하지 못하는 상황이 발생하였다.
또한 Airsoft Gun의 정확한 동작 메커니즘을 이해하지 못하였기에 문제가 발생했다고 판단한다. 이전까지는 피스톤은 정지된 상태로 뒤의 실린더가 왕복 운동을 하며, 장전된 BB탄을 사격하는 메커니즘으로 이해하였다.
하지만 BB탄을 장전하기 위해 피스톤을 뒤로 당기는 “리로딩 스프링”이 존재하였으며, 이에 의해 피스톤도 작은 범위로 왕복 운동을 하게 되었다.
이전에 발생하였던 피스톤 걸림 문제나 Gear Box의 측면 형상에 의한 끼임 문제는 없었다!!
AI Turret은 목표물을 탐지 및 사격하는 과정에서 사람이 개입하지 않는 가정을 두고 System을 설계하였다. 하지만 탄알 보충은 사람의 도움을 필요로 하되 연발에 필요한 적당한 탄알을 적재하는 것이 이상적이다 판단하였다.
빨대와 비슷한 형상을 가진 원통형 탄창을 고안했으며, 탄창 맨 뒷부분에 탈부착이 가능한 Stopper에 스프링을 부착하여 BB탄을 앞으로 밀어내 탄을 수급하는 구조이다.
설계한 탄창을 3D Printer로 출력하여 실제 Gear Box와 T자 Frame과의 조립을 시도해보았다.
지금까지 3D Printer 출력을 총 5번을 시도한 Tilt Module이 이번에는 출력에 성공하여 Turret 동작 실험의 진행이 가능하게 되었다.
최종 지지대였던 2st Axis Stabilizer Support Module도 함께 출력이 되어 최종 형상을 구성해 볼 수 있을 것이다.
Pan Module에서 Servo Motor의 제한 각도에 영향을 받지 않도록 360°회전이 가능한 Servo Motor인 FS-5113R을 사용하였다. 하지만 FS-5113R를 사용함에 따라 발생하는 두 가지 문제가 있었다.
문제 1) 360°회전에 의해 Airsoft Gun Module과 Tilt Module 배선 꼬임
Pan Module이 360°회전이 가능해졌으나, 제한 없이 회전함에 따라 Pan Module 상단부에 위치할 각종 Sensor 및 장비들의 배선이 망가질 정도로 꼬인다.
회전 각도를 제한시키면 상관없어지지만, 각도 값을 이용하여 제어하는 것이 아니기에 어려운 일로 판단된다... 🙈
문제 2) 기존 Servo Motor(HS-311)와는 다른 제어 방식
사실 가장 큰 문제는 기존 Servo Motor와 다른 제어방식을 가진다는 것이다. FS-5113R은 PWM 신호를 기반으로 동작하는 것은 동일하지만, 이를 통해 동작 각도를 선택하는 것이 아닌 회전 방향과 회전 속도를 결정하게 된다.
참고자료 : 서보모터-제어하기(코코아팹)
아래의 그림을 보면 Stop Position이 1500usec인 것을 볼 수 있다. 이는 90°에 해당되며, 90°를 Servo Motor에 입력으로 넣을 경우 아무런 동작 없이 정지하는 것을 볼 수 있다.
이러한 문제들로 인해 회전에 있어 180°로 제한되어 있으며, Object를 Tracking하는 데에 있어 더욱 적합한 HS-311 Servo Motor로 변경하게 되었다.
FS-5113R과 HS-311의 크기가 전반적으로 비슷해서 해당 Servo Motor로 변경하였다고 해서 기존 설계에 영향을 미치지는 않았다.
최종 형상을 구성하기 위한 마지막 부품인 아크릴 판이 도착하여, 설계 오류가 있는지 확인하기 위해 각 Module과 여러 부품들을 조립해보았다.
AI Turret의 최하단 부분을 아크릴판과 볼트를 통한 고정으로, 동작 시 발생하는 진동이나 탄알 발사 시의 반동 등 여러 충격들을 견딜 수 있도록 고정시켰다.
AI Turret의 최종 형상을 구성하였지만, 동작 실험을 진행하기 위해 Stabilizer와 Turret 기능별로 분리하여 실험을 하였다.
Part 1) Turret
Pan Servo Motor를 제어하기 까다롭다는 것을 최근에 인지하여 Tilt만 동작 실험을 하고 있었으며, 완성되는 즉시 Pan Module도 동작 실험을 진행할 계획이다.
전반적으로 Object를 Tracking하는 과정에 있어 많은 문제들이 있었지만, 결과적으로 준수한 성능을 보인다.
Part 2) Stabilizer
1st, 2st Axis Stabilizer 모두 정상적으로 작동을 하며 Roll, Pitch에서 발생하는 움직임을 상쇄하는 것을 볼 수 있었다.
Stabilizer가 필요 없이 Turret의 기능만 구현하는 상황에서는, Stabilizer가 지지대 역할을 할 수 있도록 추가적인 기능을 구상해 보았다.