제조공정
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 10 | ||||
| × | 1 | ||||
| × | 1 |
| ||||
|
|
초기 제출
"Hackster Terminate the competition" 대회에 대한 나의 첫 번째 제출은 인간을 찾는 로봇을 만드는 것이었지만 터미네이터 세계의 로봇과 달리 사람을 죽이지 않고 그 힘을 영원히 사용했습니다.
이 전방향 로봇이 당신을 찾고, 감지하고, 집에 돌아와 칭찬할 것입니다!
내가 나 자신에게 지정한 한 가지 요구 사항은 전자 제품을 직접 만들지 않고도 만들 수 있다는 것입니다. 이 로봇의 모든 부품은 eBay에서 구입할 수 있으며 무료로 제공되는 자습서를 사용하여 연결하면 제대로 작동합니다. 그런 다음 케이스를 3D로 인쇄할 수 있으므로 직접 인쇄하거나 3D Hubs에서 제작할 수 있습니다. 이 프로젝트가 이 목표를 충족한다고 생각하며 이제 나만의 Hunter Flatterer Robot을 구축하는 단계를 안내해 드리겠습니다.
작동 원리!
로봇의 모든 부분과 서로 연결되는 방식을 보여주는 시스템 다이어그램부터 시작하겠습니다. 빌드 전반에 걸쳐 이를 참조하고 진행하면서 확인할 것입니다.
이전에 모터를 사용한 적이 없다면 이 다이어그램에 너무 겁먹지 마십시오. 기본적으로 네 가지 주요 부분으로 요약됩니다.
<울>다음 4개 섹션은 이 목록을 반영하고 각 부분을 설정하는 과정을 안내합니다.
전기 취급
이제 배터리가 생겼습니다. 다음은 무엇인가요?
위의 다이어그램은 전원을 위해 모든 구성 요소를 연결하는 방법을 보여줍니다. 회로도의 배선을 따르면 이것이 실제 표현입니다.
Arduino를 L298N에 연결
나는 이것을 설명할 수 있지만 내가 했던 튜토리얼을 따르는 것이 더 낫습니다:http://www.instructables.com/id/Arduino-Modules-L298N-Dual-H-Bridge-Motor-Controll.
이제 모든 연결이 완료되었으며 모든 곳에서 파란색 표시등이 깜박이고 파란색 연기가 나지 않으므로 계속 진행할 수 있습니다. 계속해서 이 나쁜 놈이 일을 하도록 합시다.
케이스를 3D 프린팅하기
내가 이것을 디자인할 때 나는 두 가지 일이 일어나기를 원했다. 멋있게 보이고 가능한 한 Ci20을 과시한다. 이게 경쟁의 포인트죠?
나는 이 로봇을 완전히 3D로 인쇄할 수 있도록 디자인했으며 디자인은 모두 아래에서 사용할 수 있습니다. 기본적으로 이 시점에서 상단, 하단 및 휠을 직접 인쇄하십시오. 3D 프린터에 액세스할 수 없는 경우 www.3dhubs.com을 방문하여 인쇄를 요청할 수 있습니다! 아래에서 디자인을 확인할 수 있습니다.
다음은 ci20이 적합하고 위치에 자부심을 가질 수 있도록 디자인을 멋지게 렌더링한 것입니다.
인쇄가 완료되면 위와 같이 모든 부품을 붙일 수 있습니다(또는 자신이 없으면 마스킹 테이프를 사용하십시오. 모터를 고정하려면 M4 볼트가 필요합니다.
CI20이 마법을 부리게 하기
CI20은 보스, 작전의 두뇌입니다. 그것 없이는 로봇이 허둥지둥할 것입니다. 그래서 그것은 무엇을합니까?
ci20은 OpenCV를 사용하여 얼굴을 감지한 다음 직렬을 통해 Arduino에 적절한 명령을 보내 모터가 올바른 방향으로 가게 합니다.
1단계:OpenCV 설치
이 가이드 전체에서 말했듯이 나는 사과 카트를 재발명하려고 한 것이 아닙니다. 집에서 할 수 있고 비교적 쉽게 확장할 수 있는 것을 만들려고 합니다. 따라서 OpenCV를 설치하려면 다음 튜토리얼을 따르십시오.
OpenCV를 시작하고 실행하는 방법을 단계별로 설명합니다.
2단계:코드 실행
얼굴 추적 코드를 컴파일하고 실행해야 합니다. Ci20의 파일에서 이 명령을 실행하십시오.
<사전><코드>g++ -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L/usr/local/lib/ -g -o 바이너리 main.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching생성할 바이너리 파일:FaceTracking:main.cpp> 소스 파일:FaceTracking.cpp
쉽죠?
Ci20 및 Arduino Magic
아래 첨부 파일의 코드로 Arduino를 플래시한 후. Arduino를 CI20의 USB 포트에 연결하고 최근에 만든 FaceTracker를 실행합니다. 카메라 피드 팝업이 표시되고(예, 웹캠을 연결합니다) 얼굴을 가운데에 대면 로봇의 바퀴가 앞으로 나아가기 시작합니다!
작업 완료?
이제 시간 제약으로 인해 다른 작업을 수행할 수 없었으므로 여기까지 온 사람을 위한 도전 과제가 있습니다. 이 봇을 매우 멋지게 만들기 위해 두 가지를 추가할 수 있습니다.
스피커 세트와 일부 사운드 파일을 추가하여 화면에 얼굴이 충분히 표시될 때 사람에게 사운드 파일을 재생하도록 합니다.
<울>// Motor 1int dir1PinA =3;int dir2PinA =2;int speedPinA =9; // 모터 속도를 제어하려면 PWM 핀이어야 합니다. // 모터 2int dir1PinB =4;int dir2PinB =5;int speedPinB =8; // 모터 속도를 제어하려면 PWM 핀이어야 합니다. // 모터 3int dir1PinC =6;int dir2PinC =7;int speedPinC =10; // 모터 속도를 제어할 수 있으려면 PWM 핀이어야 합니다.int x =0;int y =0;int 지배적 초음파 =0;bool moveMotor =false;int startTime =0;void setup() { Serial.begin(9600); 핀모드(dir1PinA,OUTPUT); 핀모드(dir2PinA,OUTPUT); 핀모드(속도핀A,출력); 핀모드(dir1PinB,OUTPUT); 핀모드(dir2PinB,OUTPUT); 핀모드(속도핀B,출력); 핀모드(dir1PinC,OUTPUT); 핀모드(dir2PinC,OUTPUT); 핀모드(스피드핀C,출력); startTime =millis();}문자열 rpiString; 무효 루프() { readDataFromRPi(); // 마지막 1초 동안 RPi에서 값을 받았는지 여부를 테스트합니다. // 이동 명령이 연속적이지 않아 정지 및 시작을 계속하지 않도록 효과적으로 버퍼 역할을 합니다. // RPi에서 아무 것도 들어오지 않으면 정지도 허용합니다. // int elapsedTime =millis() - startTime; // if (elapsedTime> 1000)// {// x =0;// y =0;//dominantUltrasonic =0;// moveMotor =false;// startTime =millis();// // } // X &Y를 모터로 보냅니다. //if(moveMotor ==true &&(x !=0 &&y !=0)) //{ //Serial.println("MovingMotor"); // 드라이브인디렉션(x,y); //} //if(x ==0 &&y ==0) //{ //Serial.println("ZeroMMotor"); // 드라이브인디렉션(x,y); //} // 이것은 초음파에서 남겨질 수 있습니다. - delay(30) 제거를 주저함;}void readDataFromRPi(){ // Rpi에서 읽기 while (Serial.available()) { delay(3); // 버퍼가 채워지도록 지연 if (Serial.available()>0) { char c =Serial.read(); // 직렬 버퍼에서 1바이트를 가져옵니다. rpiString +=c; //문자열을 readString으로 만듭니다. if(c =='n') { break; } } } // ENDWHILE // RPi에서 읽은 것이 있으면 x,y &domniantUltrasonic에 넣습니다. if (rpiString.length()>0) { Serial.println(rpiString); //받은 내용 확인 String isRotate =getValue(rpiString, ' ',0); 문자열 xval =getValue(rpiString, ' ', 1); 문자열 yval =getValue(rpiString, ' ', 2); x =xval.toInt(); y =yval.toInt(); 시작 시간 =밀리(); if (isRotate =="r") { 회전(x); } else { driveInDirection(x,y); } rpiString=""; } //ENDIF} String getValue(문자열 데이터, 문자 구분 기호, 정수 색인){ int found =0; 정수 strIndex[] ={0, -1}; 정수 maxIndex =data.length()-1; for(int i=0; i<=maxIndex &&found<=index; i++){ if(data.charAt(i)==separator || i==maxIndex){ found++; strIndex[0] =strIndex[1]+1; strIndex[1] =(i ==maxIndex) ? 나+1 :나; } } 반환 발견>색인 ? data.substring(strIndex[0], strIndex[1]) :"";}
/* * 모터 제어 코드 * * 이 클래스에는 로봇이 임의의 방향으로 * 이동하고 중심점을 중심으로 회전하도록 하는 코드가 포함됩니다. */void driveInDirection(float newX, float newY){ delay(20); float x =newX; float y =newY; 부동 세타 =atan2(y,x); float mag =sqrt((x*x) + (y*y)); float vx =mag * cos(세타); float vy =mag * sin(세타); 부동 w1 =-vx; float w2 =0.5 * vx - sqrt(3)/2 * vy; float w3 =0.5 * vx + sqrt(3)/2 * vy; // 가장 큰 w 값 가져오기 float wSet[] ={w1, w2, w3}; float 최대값 =0.0; for (int i =0; i <3; i++) { if(abs(wSet[i])> maximumValue) { 가장 큰 값 =abs(wSet[i]); } } float speedCoef =(float)147.0 / 가장 큰 값; w1 =w1 * 속도 계수; w2 =w2 * 속도 계수; w3 =w3 * 속도 계수; if (x ==0 &&y ==0) { w1 =0; w2 =0; w3 =0; } 직렬.println(w1); 직렬.println(w2); Serial.println(w3); w1 =제약(w1, -150, 150); w2 =제약(w2, -150, 150); w3 =제약(w3, -150, 150); 부울 w1_ccw =w1 <0 ? 허위 사실; 부울 w2_ccw =w2 <0 ? 허위 사실; 부울 w3_ccw =w3 <0 ? 허위 사실; 바이트 w1_speed =(바이트) 맵(abs(w1), 0, 150, 0, 255); 바이트 w2_speed =(바이트) 맵(abs(w2), 0, 150, 0, 255); 바이트 w3_speed =(바이트) 맵(abs(w3), 0, 150, 0, 255); printMotorSpeed(w1_speed, 1); printMotorSpeed(w2_speed, 2); printMotorSpeed(w3_speed, 3); analogWrite(speedPinA, w1_speed); // PWM을 통한 속도 변수 설정 analogWrite(speedPinB, w2_speed); analogWrite(speedPinC, w3_speed); // PWM을 통한 속도 변수 설정 digitalWrite(dir1PinA, !w1_ccw); digitalWrite(dir2PinA, w1_ccw); digitalWrite(dir1PinB, !w2_ccw); digitalWrite(dir2PinB, w2_ccw); digitalWrite(dir1PinC, w3_ccw); digitalWrite(dir2PinC, !w3_ccw);}void 회전(float 밀리초){ float w1 =255; 부동 소수점 w2 =255; 부동 소수점 w3 =255; 부울 w1_ccw =w1 <0 ? 허위 사실; 부울 w2_ccw =w2 <0 ? 허위 사실; 부울 w3_ccw =w3 <0 ? 허위 사실; 바이트 w1_speed =(바이트) 맵(abs(w1), 0, 150, 0, 255); 바이트 w2_speed =(바이트) 맵(abs(w2), 0, 150, 0, 255); 바이트 w3_speed =(바이트) 맵(abs(w3), 0, 150, 0, 255); printMotorSpeed(w1_speed, 1); printMotorSpeed(w2_speed, 2); printMotorSpeed(w3_speed, 3); analogWrite(speedPinA, w1_speed); // PWM을 통한 속도 변수 설정 analogWrite(speedPinB, w2_speed); analogWrite(speedPinC, w3_speed); // PWM을 통한 속도 변수 설정 digitalWrite(dir1PinA, !w1_ccw); digitalWrite(dir2PinA, w1_ccw); digitalWrite(dir1PinB, !w2_ccw); digitalWrite(dir2PinB, w2_ccw); digitalWrite(dir1PinC, w3_ccw); digitalWrite(dir2PinC, !w3_ccw); 지연(밀리초); analogWrite(speedPinA, 0); // PWM을 통한 속도 변수 설정 analogWrite(speedPinB, 0); analogWrite(speedPinC, 0);//PWM을 통해 속도 변수 설정 }void printMotorSpeed(byte motorSpeed, int motor){ Serial.print("Motor"); Serial.print(모터); Serial.print(":"); Serial.println(모터 속도); }
#include "opencv2/objdetect/objdetect.hpp#include "opencv2/highgui/highgui.hpp#include "opencv2/imgproc/imgproc.hpp#include섹션>#include #include 의 가이드를 따르세요. h>이름 공간 std 사용;이름 공간 사용 cv;CascadeClassifier face_cascade, eyes_cascade;String window_name ="얼굴 감지";#include #include #include #include #include #include #include #include int sendSerial(char* 메시지){int fd =open("/ dev/ttyUSB0", O_RDWR);if (fd ==-1){ perror("dev/ttyUSB0"); 반환 1;}구조체 termios tios;tcgetattr(fd, &tios);tios.c_iflag =IGNBRK | IGNPAR;tios.c_oflag =0;tios.c_lflag =0;cfsetspeed(&tios, B9600);tcsetattr(fd, TCSAFLUSH,&tios);usleep(1000);//char msg[] ="50 50"; write(fd , message, strlen(message));return 0;}/** * 얼굴을 감지하고 그 주위에 타원을 그립니다. */void detectFaces(Mat frame) { std::vector faces; 매트 프레임_회색; // 그레이 스케일로 변환 cvtColor(frame, frame_gray, COLOR_BGR2GRAY); // 히스토그램 균등화 equalizeHist(frame_gray, frame_gray); // 얼굴 감지 face_cascade.detectMultiScale(frame_gray, faces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(30,30)); // 모든 면에 대해 반복 for(size_t i =0; i 눈; // 각 얼굴 내부의 눈 감지 시도 // eyes_cascade.detectMultiScale(face, eyes, 1.1, 2, // 0 |CASCADE_SCALE_IMAGE, Size(50, 50) ); // if(eyes.size()> 0) // 얼굴 주위에 타원 그리기 ellipse(frame, center, Size(faces[i].width/2, faces[i].height/2), 0, 0, 360 , 스칼라( 255, 0, 255 ), 4, 8, 0 ); if(center.x> frame.cols/3 &¢er.x =0) // 일시 중지 break; } 반환 0;}
제조공정
구성품 및 소모품 Arduino UNO × 1 Arduino용 PHPoC WiFi 실드 × 1 6DOF 암 로봇 × 1 이 프로젝트 정보 초보자인 경우 다음 자습서를 읽는 것이 좋습니다. Arduino - 모터 Arduino - 서보 모터 아두이노 - 와이파이 1. 시연 2. 사용자 인터페이스 로봇 팔에는 6개의 모터가 있습니다. 영역 A:모터 2, 3, 4 제어(손 관절 3개 제어) 영역 B:제어 모터 1(제어 베이스) 영역
구성품 및 소모품 Arduino UNO × 1 Adafruit L293D 모터 실드 저가 장치이며 사용하기 쉽습니다. 이전 기술이 필요하지 않은 일반적으로 사용 가능한 모터 실드입니다. Adafruit 라이브러리를 사용하여 쉽게 프로그래밍할 수도 있습니다. × 1 HC-SR4 초음파 센서 × 1 HC-05 블루투스 모듈 × 1 기어드 모터 × 2 휠 × 2 캐스터 휠 × 2 9V 배터리(일반)