아두이노 안드로이드 로봇청소기 만들기

2021. 8. 9. 22:51카테고리 없음

아두이노 안드로이드 로봇청소기 만들기

요즘 시나리오에서는 우리 모두가 일이 바빠서 집을 제대로 청소할 시간이 없습니다. 문제 해결 방법은 간단합니다. 버튼을 눌러 집을 청소하는 irobot roomba와 같은 가정용 진공청소기 로봇을 구매하시면 됩니다. 그러나 이러한 상업용 제품들은 하나의 공통적인 이슈인 비용입니다. 그래서 우리는 오늘 간단한 플로어 클리너 로봇을 만들기로 했습니다. 이것은 시중에 나와 있는 상업용 제품에 비해 제작이 간단할 뿐만 아니라 가격도 매우 저렴합니다. 독자들은 우리가 오래 전에 만든 아두이노 진공청소 로봇을 기억하겠지만, 그 로봇은 부피가 매우 크고 이동하기 위해서는 큰 납산 배터리가 필요했습니다. 이번에 새로 만들 아두이노 진공청소기는 소형으로 실용적일 것입니다. 여기에 초음파 센서와 IR 근접 센서가 장착됩니다. 초음파 센서는 실내가 제대로 청소될 때까지 로봇이 자유롭게 움직일 수 있도록 장애물을 피할 수 있도록 하며, 근접 센서는 계단에서 떨어지지 않도록 도와줍니다. 이 모든 특징들이 흥미롭게 들리죠? 그럼 시작해 볼까요?

이전 기사에서는 셀프 밸런싱 로봇, 자동 표면 소독 로봇, 장애물 회피 로봇과 같은 많은 봇을 만들었습니다. 그게 당신에게 흥미롭게 들리는지 확인해보세요.

아두이노 기반 바닥 청소 로봇을 만드는 데 필요한 재료입니다.
우리는 진공청소기 로봇의 하드웨어 부분을 만들기 위해 매우 일반적인 부품을 사용해 왔기 때문에, 당신은 동네 취미 가게에서 그것들을 모두 찾을 수 있을 것입니다. 여기 모든 구성 요소의 이미지와 함께 필요한 재료의 전체 목록이 있습니다.

아두이노 프로 미니 - 1
HC-SR04 초음파 모듈 - 3
L293D 모터 드라이버 - 1
5V N20 모터 및 마운팅 브래킷 - 2
N20 모터 휠 - 2
스위치 - 1
LM7805 전압 레귤레이터 - 1
7.4V 리튬 이온 배터리 - 1
IR 모듈 - 1
Perfboard - 1
캐스터 휠 - 1
MDF
일반 휴대용 진공 청소기

 

휴대용 진공 청소기
부품 요구사항 부분에서 휴대용 진공청소기에 대해 이야기했는데, 아래 이미지는 정확히 그것을 보여줍니다. 그것은 아마존에서 나온 휴대용 진공청소기입니다. 이것은 매우 간단한 메커니즘과 함께 제공됩니다. 하단에는 3개의 부품(먼지를 저장하는 작은 챔버, 상단에는 모터, 팬, 배터리 소켓(배터리 덮개 또는 캡)이 있습니다. DC 모터와 팬이 있습니다. 이 모터는 간단한 스위치를 통해 3V(2*1.5V AA 배터리)에 직접 연결됩니다. 7.4V 배터리로 로봇에 전원을 공급하기 때문에 내부 배터리에서 연결을 끊고 5V 전원 공급 장치에서 전원을 공급합니다. 그래서 불필요한 부품은 다 제거하고 모터만 2와이어 스테이로 제거하였습니다. 아래 이미지에서 볼 수 있습니다.

HC-SR04 초음파 센서 모듈

장애물을 감지하기 위해 인기 있는 HC-SR04 초음파 거리 센서를 사용하거나 장애물 회피 센서라고 부를 수 있습니다. 작업은 매우 간단합니다. 첫째, 송신기 모듈은 초음파를 보내 공기를 통과하고 장애물에 부딪혔다가 되돌아오면 수신기가 그 파장을 수신합니다. 아두이노로 시간을 계산하면 거리를 알 수 있습니다. 아두이노 기반 초음파 거리 센서 프로젝트에 대한 이전 기사에서 우리는 이 센서의 작동 원리를 매우 철저하게 논의했습니다. HC-SR04 초음파 거리 센서 모듈에 대해 자세히 알고 싶으시면 확인하실 수 있습니다.                         

계단 감지를 위한 바닥 센서(IR 센서)

특징 부분에서는 로봇이 계단을 감지하고 스스로 떨어지는 것을 방지할 수 있는 기능에 대해 이야기했습니다. 그러기 위해 우리는 IR 센서를 사용하고 있습니다. 우리는 IR 센서와 아두이노 사이에 인터페이스를 만들 것입니다. IR 근접센서의 작동은 매우 간단하며 IR LED와 포토다이오드가 내장되어 있으며 IR LED는 IR 빛을 방출하며 이 방출광 앞에 장애물이 들어오면 반사되어 포토다이오드로 반사된 빛이 감지됩니다. 그러나 반사로부터 생성되는 전압은 매우 낮을 것입니다. 그것을 증가시키기 위해, 우리는 op-amp 비교기를 사용할 수 있고, 증폭하고 출력을 얻을 수 있습니다. IR 모듈에는 Vcc, 접지 및 출력의 세 가지 핀이 있습니다. 보통 센서 앞에 장애물이 들어오면 출력이 낮아집니다. 바닥을 감지하는 데 사용할 수 있습니다. 센서에서 고도를 감지하면 로봇을 멈추거나 뒤로 돌리거나 계단에서 떨어지지 않도록 할 수 있습니다. 이전 기사에서는 IR 근접 센서 모듈의 Breadboard 버전을 제작하여 작동 원리를 자세히 설명하였는데, 이 센서에 대해 자세히 알고 싶으시면 확인하실 수 있습니다.

아두이노 기반 바닥청소 로봇 회로도

우리는 장애물을 감지하는 초음파 센서를 3개 가지고 있습니다. 그래서 초음파 센서의 모든 접지를 연결하여 공통 접지에 연결해야 합니다. 또한 센서의 VCC 3개를 모두 연결하여 공통 VCC 핀에 연결합니다. 다음으로 트리거 핀과 에코 핀을 아두이노의 PWM 핀에 연결합니다. 또한 IR 모듈의 VCC를 5V에 연결하고 접지를 아두이노의 접지 핀에 연결하여 IR 센서 모듈의 출력 핀을 아두이노의 디지털 핀 D2에 연결합니다. 모터 드라이버의 경우 5V 모터를 사용하기 때문에 두 개의 활성화 핀을 5V에 연결하고 드라이버 전압 핀도 5V에 연결합니다. 이전 기사에서 아두이노 모터 드라이버 실드를 제작했는데 L293D 모터 드라이버 IC와 그 작동에 대해 자세히 알아보실 수 있습니다. 아두이노, 초음파 모듈, 모터 드라이버, 모터는 5V로 동작하며, 전압이 높을수록 5V로 전환되는 7.4V 배터리를 사용합니다. LM7805 전압 조절기가 사용됩니다. 진공 청소기를 메인 회로에 직접 연결하십시오.

아두이노 기반 바닥 청소 로봇 회로 구축

모든 부품을 함께 납땜하기 위해 먼저, 저는 매우 작은 크기의 점선식 퍼프보드 조각을 가져다가 회로도에 따라 모든 부품을 배치하고 모든 부품을 납땜했습니다. 이 부분은 아주 간단하지만 주의해서 하세요. 또한 우리는 아두이노 프로미니를 두 개의 여성 헤더를 사용하여 배치했습니다. Perfboard 납땜을 완료한 후 도식처럼 초음파 모듈에 와이어를 연결하고 해당 핀에 연결합니다.

아두이노 기반 바닥 청소 로봇 하우징 구축
나의 로봇에 대한 아이디어를 얻기 위해 진공청소기 로봇을 인터넷에서 찾아보고 둥근 모양의 로봇 이미지를 얻었어요. 그래서 나는 둥근 모양의 로봇을 만들기로 결심했어요. 로봇의 체이스와 차체를 만들기 위해 폼 시트, MDF, 카드보드 등 다양한 옵션을 가지고 있습니다. 하지만 MDF는 딱딱하고 방수성이 있어서 선택했어요. 이 작업을 하는 경우 봇에 사용할 재료를 선택할 수 있습니다.

로봇을 제작하기 위해 MDF 시트를 가져와서 반지름이 8CM인 두 개의 원을 그렸고, 그 원 안에는 진공청소기를 장착할 반지름이 4CM인 다른 원도 그렸습니다. 그리고 동그라미를 잘라내죠. 또한 휠 경로에 적합한 조각을 절단하고 제거했습니다(이미지 참조). 마지막으로 바퀴에 작은 구멍 세 개를 뚫었습니다. 다음 단계에서는 브래킷을 사용하여 베이스에 모터를 장착하고 캐스터 휠을 제자리에 배치하고 고정합니다. 그런 다음 초음파 센서를 로봇의 왼쪽, 오른쪽, 가운데에 놓습니다. 또한 IR 모듈을 로봇의 아래쪽에 연결합니다. 밖에 스위치 추가하는 거 잊지 마. 지금까지 로봇을 제작했습니다. 이 시점에서 혼란스러우면 다음 이미지를 참고할 수 있습니다.

윗부분도 폼 시트에 반지름 11cm의 원을 그려 커팅했습니다. 상단과 하단 사이의 간격을 위해 4cm 길이의 플라스틱 튜브 3개를 절단했습니다. 그 다음에 밑에 플라스틱 스페이서를 붙이고 윗부분을 붙였어요. 원한다면 봇의 옆부분을 플라스틱이나 비슷한 재질로 덮을 수 있습니다.

아두이노 기반 바닥 청소 로봇 - 코드
이 프로젝트의 전체 코드는 문서 끝에 지정되어 있습니다. 이 아두이노 코드는 아두이노 기반 초음파 거리 센서 코드와 유사하며 바닥 감지만 변경됩니다. 다음 줄에서 코드가 어떻게 작동하는지 설명합니다. 이 경우 추가 라이브러리는 사용하지 않습니다. 아래에서는 코드를 단계별로 설명했습니다. HC-SR04 센서의 거리 데이터를 디코딩하기 위해 추가 라이브러리를 사용하지 않습니다. 매우 간단하기 때문입니다. 다음 줄에서, 우리는 방법을 설명했습니다. 먼저 아두이노 보드에 연결된 초음파 거리 센서 3개 모두에 대해 트리거 핀과 에코 핀을 정의해야 합니다. 이 프로젝트에는 에코 핀 3개와 트리거 핀 3개가 있습니다. 1은 좌측 센서, 2는 전방 센서, 3은 우측 센서입니다.

const int trigPin1 = 3;
const int echoPin1 = 5; 
const int trigPin2 = 6;
const int echoPin2 =9; 
const int trigPin3 = 10;
const int echoPin3 = 11;
int irpin =2;

그런 다음 모든 (int) 유형 변수인 거리에 대한 변수를 정의하고 기간 동안 (긴)을 사용하도록 선택했습니다. 다시 말하지만, 우리는 각각 3개씩 있다. 또한 이동 상태를 저장하기 위한 정수를 정의했는데, 이 섹션의 뒷부분에서 설명하겠습니다.

 long duration1;
 long duration2;
 long duration3;
int distanceleft;
int distancefront;
int distanceright;
int a=0;

다음으로 설정 섹션에서 pinMode() 기능을 사용하여 모든 투시 핀을 입력 또는 출력으로 만들어야 합니다. 모듈에서 초음파를 보내려면 트리거 핀을 하이로 활성화해야 합니다. 즉, 모든 트리거 핀을 OUTPUT으로 정의해야 합니다. 그리고 에코를 받기 위해서는 에코 핀의 상태를 읽어야 모든 에코 핀이 INPUT으로 정의되어야 합니다. 또한 문제 해결을 위해 직렬 모니터를 활성화합니다. IR 모듈의 상태를 읽기 위해 입력 핀을 정의했습니다.

pinMode(trigPin1, OUTPUT);
pinMode(trigPin2, OUTPUT);
pinMode(trigPin3, OUTPUT);
pinMode(echoPin1, INPUT); 
pinMode(echoPin2, INPUT);
pinMode(echoPin3, INPUT);
 pinMode(irpin, INPUT);

그리고 이러한 디지털 핀은 모터 드라이버의 입력을 위한 OUTPUT으로 정의됩니다.

pinMode(4, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(12, OUTPUT);

메인 루프에는 3개의 센서를 위한 3개의 섹션이 있습니다. 모든 섹션은 동일하지만 각각 다른 센서에 대해 작동합니다. 이 섹션에서는 각 센서로부터의 장애물 거리를 읽고 정의된 각 정수에 저장합니다. 거리를 읽으려면 먼저 트리거 핀이 깨끗한지 확인해야 합니다. 그러기 위해서는 트리거 핀을 2µs 동안 LOW로 설정해야 합니다. 자, 초음파를 발생시키기 위해서, 우리는 10 µs 동안 트리거 핀을 HIGH로 돌려야 합니다. 그러면 초음파가 전송되고 펄스 In() 기능을 통해 이동 시간을 판독하여 해당 값을 변수 "duration"에 저장할 수 있습니다. 이 기능에는 2개의 파라미터가 있습니다. 첫 번째 파라미터는 에코 핀의 이름이고 두 번째 파라미터는 HIGH 또는 LOW 중 하나를 쓸 수 있습니다. HIGH는 펄스 In() 함수가 튕겨진 음파로 인해 핀이 HIGH가 될 때까지 기다렸다가 카운트를 시작하여 사운드 파형이 종료될 때까지 LOW가 될 때까지 기다립니다. 세는 것. 이 기능은 펄스 길이를 마이크로초 단위로 제공합니다. 거리 계산을 위해 지속시간을 0.034(공기 중 음속은 340m/s)로 곱한 후 2(음파의 앞뒤 이동 때문이다)로 나눈다. 마지막으로 각 센서의 거리를 해당하는 정수로 저장합니다.

digitalWrite(trigPin1, LOW);
delayMicroseconds(2);
digitalWrite(trigPin1, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin1, LOW);
duration1 = pulseIn(echoPin1, HIGH);
distanceleft = duration1 * 0.034 / 2;

각 센서와의 거리를 파악한 후 if 문장의 도움으로 모터를 제어할 수 있어 로봇의 움직임을 제어할 수 있습니다. 이것은 매우 간단합니다, 먼저 장애물 거리 값을 부여했습니다, 이 경우 15cm입니다(원하는 대로 변경). 그리고 그 값에 맞는 조건을 제시했습니다. 예를 들어, 장애물이 왼쪽 센서 앞에 오고(왼쪽 센서의 거리가 15cm 이하 또는 같아야 함을 의미) 다른 두 개의 거리가 높을 때(즉, 장애물이 센서 앞에 없음을 의미) 디지털 쓰기 기능의 도움을 받아 모터를 오른쪽으로 구동할 수 있습니다. 나중에 IR 센서의 상태를 확인했습니다. 로봇이 바닥에 있으면 IR 핀 값이 LOW가 되고 그렇지 않으면 HIGH가 됩니다. 그리고 그 값을 ints 변수에 저장했습니다. 우리는 이 상태에 따라 로봇을 제어할 것입니다.

 

이 코드 섹션은 로봇을 전진 및 후진 이동에 사용됩니다.

if(s==HIGH)
  { 
    digitalWrite(4, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(12, HIGH);
      delay(1000);
    a=1;
        }

그러나 모터가 뒤로 이동하면 바닥이 뒤로 이동하며 봇이 앞으로 이동하면 봇이 고착되는 문제가 반복된다. 이를 극복하기 위해 층이 파악되지 않은 후 int에 값 (1)을 저장합니다. 다른 움직임도 이 상태를 확인합니다.

바닥이 없음을 감지한 후 로봇이 앞으로 나아가지 않습니다. 대신 왼쪽으로 이동하게 되고, 이렇게 하면 문제를 피할 수 있습니다.

if ((a==0)&&(s==LOW)&&(distanceleft <= 15 && distancefront > 15 && distanceright <= 15) || (a==0)&&(s==LOW)&&(distanceleft > 15 && distancefront > 15 && distanceright > 15))

위와 같은 조건에서. 먼저 로봇이 바닥 상태와 정수 값을 확인합니다. 모든 조건이 충족되어야만 봇이 앞으로 이동합니다.

이제, 우리는 모터 드라이버의 명령을 쓸 수 있습니다. 그러면 오른쪽 모터가 뒤로, 왼쪽 모터가 앞으로 구동되어 로봇이 오른쪽으로 회전합니다.

이 코드 섹션은 로봇을 오른쪽으로 이동하기 위해 사용됩니다.

 digitalWrite(4, HIGH);
 digitalWrite(7, LOW);
 digitalWrite(8, HIGH);
 digitalWrite(12, LOW);

바닥이 없음을 로봇이 감지하면 값이 1로 변경되고 봇이 왼쪽으로 이동합니다. 왼쪽으로 돌면 'a' 값이 1에서 0으로 바뀝니다.

 if ((a==1) &&(s==LOW) ||(s==LOW) && (distanceleft <= 15 && distancefront <= 15 && distanceright > 15) || (s== LOW) && (distanceleft <= 15 && distancefront <= 15 && distanceright > 15) || (s==LOW) && (distanceleft <= 15 && distancefront > 15 && distanceright > 15) || (distanceleft <= 15 && distancefront > 15 && distanceright > 15))
  {
    digitalWrite(4, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(12, HIGH);
    delay(100);
    a=0;
  }

코드의 이 섹션은 로봇을 왼쪽으로 이동시키는 데 사용됩니다.

if ((s==LOW)&&(distanceleft > 15 && distancefront <= 15 && distanceright <= 15) ||(s==LOW)&& (distanceleft > 15 && distancefront > 15 && distanceright <= 15) ||(s==LOW)&& (distanceleft > 15 && distancefront <= 15 && distanceright > 15) )
    {
    digitalWrite(4, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(12, LOW);
  }

아두이노 기반의 스마트 진공청소기 로봇을 만드는 것입니다. 프로젝트의 전체 작업은 이 페이지 하단에 연결된 비디오에서 확인할 수 있습니다. 궁금한 점이 있으면 아래에 적어주세요.

// defining the pins
const int trigPin1 = 3;
const int echoPin1 = 5;
const int trigPin2 = 6;
const int echoPin2 = 9;
const int trigPin3 = 10;
const int echoPin3 = 11;
int irpin =2;
// defining variables
long duration1;
long duration2;
long duration3;
int distanceleft;
int distancefront;
int distanceright;
int a=0;
void setup() {
  pinMode(trigPin1, OUTPUT);
  pinMode(trigPin2, OUTPUT);
  pinMode(trigPin3, OUTPUT);// Sets the trigPin as an Output
  pinMode(echoPin1, INPUT); // Sets the echoPin as an Input
  pinMode(echoPin2, INPUT);
  pinMode(echoPin3, INPUT);
  pinMode(irpin, INPUT);
  pinMode(4, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(12, OUTPUT);
}
void loop() {
  digitalWrite(trigPin1, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin1, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin1, LOW);
  duration1 = pulseIn(echoPin1, HIGH);
  distanceleft = duration1 * 0.034 / 2;
  Serial.print("Distance1: ");
  Serial.println(distanceleft);
  digitalWrite(trigPin2, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin2, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin2, LOW);
  duration2 = pulseIn(echoPin2, HIGH);
  distancefront = duration2 * 0.034 / 2;
  Serial.print("Distance2: ");
  Serial.println(distancefront);
  digitalWrite(trigPin3, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin3, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin3, LOW);
  duration3 = pulseIn(echoPin3, HIGH);
  distanceright = duration3 * 0.034 / 2;
  Serial.print("Distance3: ");
  Serial.println(distanceright);
  int s = digitalRead(irpin);
  if(s==HIGH)
  { 
    digitalWrite(4, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(12, HIGH);
      delay(1000);
    a=1;
    }
  if ((a==0)&&(s==LOW)&&(distanceleft <= 15 && distancefront > 15 && distanceright <= 15) || (a==0)&&(s==LOW)&&(distanceleft > 15 && distancefront > 15 && distanceright > 15))
  {
    digitalWrite(4, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(12,LOW);
  }
  if ((a==1)&&(s==LOW)||(s==LOW)&&(distanceleft <= 15 && distancefront <= 15 && distanceright > 15)||(s==LOW)&&(distanceleft <= 15 && distancefront <= 15 && distanceright > 15)||(s==LOW)&& (distanceleft <= 15 && distancefront > 15 && distanceright > 15)||(distanceleft <= 15 && distancefront > 15 && distanceright > 15))
  {
    digitalWrite(4, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(12, HIGH);
    delay(100);
    a=0;
  }
  if ((s==LOW)&&(distanceleft > 15 && distancefront <= 15 && distanceright <= 15) ||(s==LOW)&& (distanceleft > 15 && distancefront > 15 && distanceright <= 15) ||(s==LOW)&& (distanceleft > 15 && distancefront <= 15 && distanceright > 15) )
  {
    digitalWrite(4, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(12, LOW);
  } 
}