무료한 일상.. 갑자기 명사수가 되고 싶었다.
그래서 바로 실행에 옮긴 미니미니한 토이 프로젝트이다.
일단 명사수가 되려면 총이 필요하고, 정확도를 체크해줄 상대가 필요하다.
사람을 쏠순 없으니 과녁을 만들고, 과녁 난이도에 따라 점수를 다르게 주어 일정 거리에서 총으로 점수를 내는 것을 목표로 진행해보겠다.
일단 준비물은 3D프린터기와 3D 모델링 툴, 스프링(용수철), STM32, 충격감지센서, 7세그먼트, 충전식 리튬배터리가 기본적으로 생각난다.
사실 과녁이 넘어가는걸 어떻게 알아낼까가 고민이 많았다.
그러면서 아래 방법들이 생각났다.
1. 물리적인 눌림 (리미트 스위치?)
2. 과녁의 기울기 (가속도센서?)
3. 과녁의 충격 (진동 감지 센서?)
하지만 중요한 조건이 있다.
- 확실하게 과녁이 넘어가는 것을 알아낼수 있는가?
- 가격적인 측면을 고려했는가?
- 만드려는 디자인에 들어갈만한 크기인가?
스위치는 눌리지 않으면 과녁을 맞춰도 점수가 올라가지 않는다.
기울기는 센서를 과녁마다 부착할건데 가격 측면이 조금 비쌌다.
3번이 그나마 가격도 스위치의 가격을 웃돌면서 가속도 보다 싸서 3번으로 결정했다.
이렇게 재료들을 선정하여 준비물을 구비했다.
먼저 총은 다음 링크에서 모델링을 얻어 뽑았고, 조립하였다.
https://youtu.be/bGmhSpl-vTs?si=0lJh5QyreEU0Imvk
이렇게 총은 만들었고, 다음은 과녁을 만들차례이다.
과녁을 만들기 전에 먼저 진동센서로 소프트웨어적인 부분을 구현해보겠다.
해당 부분은 다음 링크에서 확인해보자
과녁은 다음과 같이 진행했다.
전부 납떔하고, 배치하고, 고정 및 배치도 진행하였다.
참고로 배터리는 1.5V 2개를 직렬로하여 3V로 전원공급을 하였고, 커넥터를 사용하여 선 정리 및 확실한 연결을 하였다.
조금 조잡하지만 이 프로젝트는 1월 안에 끝내고 싶어서 외형은 크게 신경쓰지 않고 진행했고,
권총은 생각보다 파워가 약해서 잘 안나라간다..
따라서 권총을 쿠팡에서 하나 구매했다 ㅎ..
권총 오기전에 미리 툭툭 건드려서 진행해보았다.
(생각보다 진동 감지 센서가 민감함)
+ 버튼은 점수 초기화
아래는 실험 영상이다.
혹시 코드가 필요한 사람을 위해 아래 남겨두겠다.
+ 진동 감지 센서에서 인터럽트를 활용하여 맞았나를 인식했는데 문제점이 발생했다.
총의 위력이 쎄면 진동 감지 센서 3개가 동시에 값이 올라갔다.
이것을 방지하기 위해 블로킹을 사용하여 인터럽트가 발생한 뒤 500ms동안은 다른 인터럽트를 받지 않게 끔한다.
수정된 코드는 다음과 같다.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
static uint32_t block_time = 0; // 인터럽트를 블록할 기준 시간 저장
static uint8_t is_blocking = 0; // 블록 상태를 나타내는 플래그
uint32_t current_time = HAL_GetTick();
// 블록 상태 확인
if (is_blocking && (current_time - block_time < 500)) {
// 현재 블록 상태이며 500ms 이내라면 인터럽트를 무시
return;
}
// 블록 상태를 해제 (500ms 경과 시)
if (current_time - block_time >= 500) {
is_blocking = 0; // 블록 해제
}
// 인터럽트 핀에 따른 처리
if (GPIO_Pin == han_Pin) {
current_tick_1 = HAL_GetTick();
int32_t diff_1 = (int32_t)(current_tick_1 - old_tick_1);
if (diff_1 < 0) {
diff_1 += UINT32_MAX + 1;
}
if (diff_1 > 200) {
state++;
old_tick_1 = current_tick_1;
}
} else if (GPIO_Pin == han2_Pin) {
current_tick_2 = HAL_GetTick();
int32_t diff_2 = (int32_t)(current_tick_2 - old_tick_2);
if (diff_2 < 0) {
diff_2 += UINT32_MAX + 1;
}
if (diff_2 > 200) {
state_1++;
old_tick_2 = current_tick_2;
}
} else if (GPIO_Pin == han3_Pin) {
current_tick_3 = HAL_GetTick();
int32_t diff_3 = (int32_t)(current_tick_3 - old_tick_3);
if (diff_3 < 0) {
diff_3 += UINT32_MAX + 1;
}
if (diff_3 > 200) {
state_2++;
old_tick_3 = current_tick_3;
}
}
// 인터럽트 처리 완료 후 다른 인터럽트를 블록 상태로 설정
is_blocking = 1;
block_time = HAL_GetTick(); // 블록 시작 시간 설정
}
이렇게 완전히 완성되었다.
최종적으로 만든 권총으로 점수를 얻는 부분을 영상으로 보여주고 마무리하겠다.
(만든 총은 멀리까지 총알이 날아가지 않아 비비탄 총 하나 구매하여 가족과 게임을 하였다 ㅎㅎ)
https://youtube.com/shorts/cVAhy9UrTc0?feature=share
'잡다한일상' 카테고리의 다른 글
LED 회로 기판 가지고 놀기 (0) | 2025.01.04 |
---|---|
롤링포토(?) 만들기 (1) | 2024.11.27 |