산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

부품 및 소모품

SparkFun 듀얼 H-브리지 모터 드라이버 L298 1개
DC 모터 (일반) 4개
Arduino UNO 1개
LED (일반) 8개
저항 221옴 8개
서보 모터 (Tower Pro MG996R) 1개
초음파 센서 HC-SR04 1개

앱 및 온라인 서비스

프로젝트 소개

여러 실내 로봇을 제작한 후, 험한 지형을 주행할 수 있는 야외 로봇을 만들기로 결심했습니다. 이를 'M1-로봇'이라 명명했습니다.

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

M1 로버의 모터는 Arduino로 4개의 DC 모터를 쉽게 구동할 수 있어, 더 강력한 로봇의 핵심으로 적합하다고 판단했습니다. 이에 처음부터 오프로드 4륜 구동 M1을 설계했습니다.

단순한 RC카가 아닙니다. 일련의 지시를 따라 자율 주행하도록 프로그래밍하거나 원격 컴퓨터에서 제어할 수 있으며, 게임 컨트롤러나 커스텀 조이스틱으로 RC카처럼 조종할 수도 있습니다.

1단계: 설계

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

자체 제품이나 프로토타입을 설계하는 것은 즐거운 일이지만, 실제 크기로 제작하기로 결정하면 더 복잡해집니다. 강력한 설계 도구이자 사용하기 쉬운 Google SketchUp 2017을 선택했으며, 모델의 청사진을 레이저 커팅 머신이나 3D 프린터로 내보낼 수 있습니다.

로봇 선체 설계 및 제작에 첫 3주를 투자했습니다.

재료로는 3mm 두께의 나무 합판이 주어졌습니다.

시간 제약으로 인해 배선을 선체 내부에 모두 밀어 넣느라 깔끔하지 못한 최종 배선 상태입니다.

향후 M2, M3 등 순차적으로 버전을 개발할 계획이기에 'M1 로버'라는 이름이 적절하다고 생각했습니다. 키트 형태로 설계되어 나사만으로 조립하면 됩니다.

2단계: 구성품 및 특징

3단계: 모터 컨트롤러

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

H-브리지는 일반적으로 모터의 속도와 방향을 제어하는 데 사용되지만, 고출력 LED 어레이의 밝기 제어 같은 다른 프로젝트에도 활용할 수 있습니다.

4단계: 섀시 조립

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

섀시는 레이저 커터로 몇 개의 파츠로 절단되었으며, 앞서 언급한 대로 키트 형태로 제작되어 조립이 쉽습니다. 아래 지침을 따라 조립하면 됩니다.

디자인도 중요했습니다. RC카의 경우 전후방 라이트가 필요합니다. M1 로봇 전방에는 220옴 저항과 직렬로 연결된 백색 LED 4개를, 후방에는 마찬가지로 220옴 저항과 직렬로 연결된 적색 LED 2개를 장착했습니다. 이 LED들은 동일한 애플리케이션으로 제어할 수 있습니다.

5단계: 회로 구성

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

여러 전자 부품을 동시에 제어하기로 결정하면 각 부품의 순서를 고려해야 하므로 회로가 다소 복잡해집니다.

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

주요 연결 구성품:

6단계: 소프트웨어

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

M1 로버 코드 작성 시 여러 요소를 고려했으며, GUI 소프트웨어를 통해 로봇 상태에 대한 더 많은 정보를 얻을 수 있습니다.

스타터 키트용 기본 코드로, 블루투스를 통해 모바일이나 노트북에서 제어 가능:

int frontled = 3; // 전방 LED
int rearled = 4;  // 후방 LED
int outPin1 = 5;  // 모터1
int outPin2 = 6;  // 모터1
int outPin4 = 11; // 모터2
int outPin3 = 12; // 모터2
char bt = 0;      // 블루투스 데이터
int buzzerPin = 2;
const int pingPin = 9; // 초음파 센서 트리거 핀
const int echoPin = 8; // 초음파 센서 에코 핀

void setup() {
  Serial.begin(9600);
  pinMode(outPin1, OUTPUT);
  pinMode(outPin2, OUTPUT);
  pinMode(outPin3, OUTPUT);
  pinMode(outPin4, OUTPUT);
  pinMode(frontled, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    bt = Serial.read();
    digitalWrite(frontled, HIGH);
    
    long duration, inches, cm;
    pinMode(pingPin, OUTPUT);
    digitalWrite(pingPin, LOW);
    delayMicroseconds(2);
    digitalWrite(pingPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(pingPin, LOW);
    pinMode(echoPin, INPUT);
    duration = pulseIn(echoPin, HIGH);
    inches = microsecondsToInches(duration);
    cm = microsecondsToCentimeters(duration);
    
    if (cm > 10) { // 장애물 감지 거리 10cm 이상일 때만 동작
      if (bt == 'F') { // 전진
        digitalWrite(outPin1, HIGH);
        digitalWrite(outPin2, LOW);
        digitalWrite(outPin3, HIGH);
        digitalWrite(outPin4, LOW);
      } else if (bt == 'B') { // 후진
        digitalWrite(outPin1, LOW);
        digitalWrite(outPin2, HIGH);
        digitalWrite(outPin3, LOW);
        digitalWrite(outPin4, HIGH);
      } else if (bt == 'S') { // 정지
        digitalWrite(outPin1, LOW);
        digitalWrite(outPin2, LOW);
        digitalWrite(outPin3, LOW);
        digitalWrite(outPin4, LOW);
      } else if (bt == 'R') { // 우회전
        digitalWrite(outPin1, HIGH);
        digitalWrite(outPin2, LOW);
        digitalWrite(outPin3, LOW);
        digitalWrite(outPin4, LOW);
      } else if (bt == 'L') { // 좌회전
        digitalWrite(outPin1, LOW);
        digitalWrite(outPin2, LOW);
        digitalWrite(outPin3, HIGH);
        digitalWrite(outPin4, LOW);
      } else if (bt == 'I') { // 전진 우회전
        digitalWrite(outPin1, HIGH);
        digitalWrite(outPin2, LOW);
        digitalWrite(outPin3, LOW);
        digitalWrite(outPin4, HIGH);
      } else if (bt == 'G') { // 전진 좌회전
        digitalWrite(outPin1, LOW);
        digitalWrite(outPin2, HIGH);
        digitalWrite(outPin3, HIGH);
        digitalWrite(outPin4, LOW);
      }
    } else {
      // 장애물 감지 시 부저 울림
      digitalWrite(buzzerPin, HIGH);
      delay(500);
      digitalWrite(buzzerPin, LOW);
      delay(500);
    }
  }
}

long microsecondsToInches(long microseconds) {
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds) {
  return microseconds / 29 / 2;
}

Arduino 코드는 시리얼 포트 명령을 통해 모든 전자 부품이 작동하도록 프로그래밍되어 있어, 블루투스 모듈, PC, 휴대폰 등 어떤 종류의 컨트롤러와도 호환됩니다.

7단계: 패키지 구성

스타터 패키지

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

기본 구성품이 포함되며, 상단 플레이트에 센서, 매니퓰레이터, 컴퓨터 하드웨어를 쉽게 장착할 수 있습니다. 온보드 및 로버 전원 공급장치에 센서를 연결하기만 하면 시작할 수 있습니다.

익스플로러 패키지

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

기본적인 실내외 자율 주행 기능을 제공하며, IP 카메라 대신 IP 주소로 인터넷에 연결된 휴대폰 카메라를 사용합니다.

매핑 패키지

기본적인 GPS 추적 기능을 제공합니다. 야외 주행 시 실시간으로 좌표 경로를 확인할 수 있어 매우 유용합니다.

매니퓰레이션 패키지

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

로봇 팔과 50mm 2핑거 그리퍼로 세상과 상호작용합니다.

중요 팁:

모든 서보가 180도 전체 회전 범위를 가지지는 않습니다. 많은 서보가 그렇지 않습니다. 기계적 한계가 어디인지 확인하는 테스트 코드를 작성할 수 있습니다. servo.write 대신 servo.writeMicroseconds를 사용하는 것이 좋습니다. 1000-2000을 기본 범위로 사용할 수 있기 때문입니다. 많은 서보가 이 범위 밖인 600-2400까지 지원하기도 합니다.

여러 값을 시도해보고 버즈가 발생하는 지점(한계 도달)을 찾으세요. 그런 다음 코드 작성 시 그 한계 내에서만 작동하도록 하세요. servo.attach(pin, min, max)를 사용할 때 이 한계를 설정할 수 있습니다.

한계에서 계속 유지하면 높은 전류를 끌어당겨 급격히 과열됩니다. 이런 식으로 장시간 부하를 주면 서보가 쉽게 '타버릴' 수 있습니다.

실제 이동 범위를 찾아 코드가 엔드스톱을 넘지 않도록 하세요. Arduino의 constrain() 함수가 유용합니다:

servo.write(constrain(angle, 10, 160)); // 각도를 10~160 범위로 제한

커스텀 파츠 및 인클로저

m1rover_dxf_hackaday_4o7WTGHUGE.dxf

회로도

M1 로버: 험한 지형을 위한 야외 자율 주행 로봇

제조공정

  1. 가변 자기저항 모터: 유형, 작동 원리 및 응용 분야
  2. Raspoulette: 태양광 자율 닭장 문 시스템 프로토타입
  3. 윈도우 IoT 코어 라즈베리파이 2 로버: 초보자부터 고급까지 완전 가이드
  4. 심플 파이 로봇 – 라즈베리파이로 2WD 자율 로버 만들기
  5. 아두이노 우노 & MAX7219로 만드는 UFO 어택 게임 – 직접 만드는 레트로 아케이드
  6. 3D RGB 아두클락(Arduclock) - 블루투스 제어 LED 타임피스 with RTC
  7. 아두이노용 양극성 스테퍼 모터 종합 라이브러리
  8. DIY 기타 스피드 픽 & 스톰프 페달 - 3D 프린팅 모터식 픽 직접 만들기
  9. 리니어 모터 이해: 전기 에너지에서 정밀 직선 운동으로
  10. 서보 모터 설명: 작동 원리와 중요성