Robot Omnidireksional Dirancang untuk Pelacakan Orang yang Aman
Komponen dan Perlengkapan
| Komponen | Jumlah |
| L298N Dual Stepper Motor Driver Controller Board Module | 2 |
| LM2596 DC DC Switching Adjustable Step Down Voltage Regulator | 1 |
| Onboard Lipo Alarm Battery Checker Low Voltage Detector | 1 |
| 24RPM DC 12V 4mm Shaft Geared Motor | 3 |
| Arduino Nano R3 | 1 |
| Microsoft LifeCam HD-3000 Web camera | 1 |
| Jumper wires (generik) | 10 |
| Creator Ci20 | 1 |
| 11.1V 3Cell Lipo Battery | 1 |
Alat dan Mesin yang Diperlukan
- Printer 3D (generik)
- Paku las (generik)
Aplikasi dan Layanan Online
Tentang Proyek
Submisi awal saya untuk kompetisi "Hackster Terminate the competition" adalah menciptakan robot yang mencari manusia, tetapi tidak seperti yang ada di alam semesta Terminator, ia tidak berkeliling membunuh orang, melainkan menggunakan kekuatannya untuk kebaikan.
Robot omnidireksional ini akan menemukan Anda, mendeteksi Anda, mendekati Anda, dan memuji Anda!
Syarat yang saya tetapkan untuk diri sendiri adalah saya akan memastikan bahwa ia dapat dibuat tanpa harus membangun elektronik sendiri. Setiap bagian di dalam robot ini dapat dibeli dari eBay, dihubungkan menggunakan tutorial yang tersedia secara gratis dan seharusnya berfungsi. Kotaknya kemudian dapat dicetak 3D sehingga Anda dapat mencetaknya sendiri atau membuatnya dicetak di 3D Hubs. Saya pikir proyek ini memenuhi tujuan ini dan saya sekarang akan memandu Anda melalui langkah-langkah pembuatan robot Hunter Flatterer Robot Anda sendiri.
Cara Semua Ini Bekerja!
Jadi mari kita mulai dengan diagram sistem yang menunjukkan semua bagian robot dan bagaimana mereka saling terhubung. Kami akan mereferensikan ini selama pembuatan dan mencoretnya seiring berjalannya waktu.
Jangan terlalu takut dengan diagram ini jika Anda belum pernah menggunakan motor sebelumnya. Ini pada dasarnya menyedot menjadi Empat bagian utama:
- Sisi kiri berurusan dengan mengambil baterai dan memastikan tegangan yang benar untuk sistem.
- Bagian cerdas dilakukan pada ci20
- Arduino digunakan untuk memberitahu motor apa yang harus dilakukan
Empat bagian berikutnya akan mencerminkan daftar ini dan memandu Anda melalui pengaturan setiap bagian.
Menangani Listrik
Jadi Anda sudah memiliki baterai, apa selanjutnya?
Diagram di atas menunjukkan cara menghubungkan semua komponen untuk daya, jika Anda mengikuti kabel dalam skematik ini adalah representasi kehidupan nyata.
Menghubungkan Arduino ke L298N
Saya bisa menjelaskan ini, tetapi lebih baik untuk hanya mengikuti tutorial yang saya buat: https://www.instructables.com/id/Arduino-Modules-L298N-Dual-H-Bridge-Motor-Controll.
Jadi sekarang Anda telah menyambungkan semuanya, ada lampu biru berkedip di mana-mana dan tidak ada asap biru jadi Anda siap. Mari kita lanjutkan untuk membuat anak liar ini bekerja.
Mencetak 3D Kotak Anda Sendiri
Saat saya mendesain ini, saya memutuskan bahwa saya ingin dua hal terjadi, ia tampak keren & menunjukkan Ci20 setampilan mungkin. Saya artinya ini adalah poin kompetensi kan?
Saya mendesain robot ini untuk sepenuhnya dapat dicetak 3D dan desainnya semua tersedia di bawah. Pada dasarnya pada titik ini pergi dan cetak bagian atas, bawah & roda sendiri. Jika Anda tidak memiliki akses ke Printer 3D Anda dapat memeriksa www.3dhubs.com untuk mendapatkan seseorang untuk mencetaknya untuk Anda! Anda dapat memeriksa desain di bawah
Ini adalah render yang cukup yang saya buat dari desain untuk memastikan bahwa ci20 akan muat dan berada di tempat yang paling terhormat
Membuat Ci20 Melakukan Beberapa Magi
Ci20 adalah bos, otak dari operasi. Tanpa itu robot akan keluar dari jalur. Jadi apa yang dilakukannya?
Nah ci20 akan menggunakan OpenCV untuk mendeteksi wajah Anda dan kemudian mengirim perintah yang sesuai melalui serial ke Arduino untuk menggerakkan motor ke arah yang benar.
Langkah 1: Instal OpenCV
Seperti yang saya katakan selama panduan ini, saya tidak mencoba untuk menemukan roda lagi. Saya mencoba untuk membangun sesuatu yang dapat Anda lakukan di rumah dan memperluasnya dengan relatif mudah. Jadi untuk menginstal OpenCV pergi dan ikuti tutorial ini:
Ini memandu Anda langkah demi langkah untuk mendapatkan OpenCV berjalan.
Langkah 2: Jalankan Kode
Kode Pelacakan Wajah akan perlu dikompilasi dan dijalankan, jalankan perintah ini pada file di Ci20.
g++ -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L/usr/local/lib/ -g -o binary main.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching
File biner yang akan dibuat: FaceTracking: main.cpp > File sumber: FaceTracking.cpp
Mudah kan?
Ci20 & Arduino Magic
Setelah memflash Arduino dengan kode dalam lampiran di bawah. Hubungkan Arduino ke port USB pada Ci20 dan jalankan FaceTracker yang baru saja Anda buat. Anda akan melihat umpan kamera muncul (Oh ya, hubungkan webcam) dan jika Anda menempelkan wajah Anda di tengah roda pada robot seharusnya mulai membuatnya berjalan maju!
Pekerjaan Selesai?
Sekarang karena keterbatasan waktu saya tidak sepenuhnya membuatnya melakukan hal lain, jadi inilah tantangan untuk siapa pun yang telah sampai sejauh ini. Ada dua hal yang dapat Anda tambahkan untuk membuat bot ini super hebat:
- Tambahkan sekumpulan speaker dan beberapa file suara sehingga ketika wajah cukup besar di layar ia memutar file suara kepada orang
- Jika robot tidak mendeteksi wajah dalam 1-2 menit buatlah ia berputar di tempat. Anda dapat melakukan ini dengan mengirim perintah "R XX" ke Arduino. Ganti XX dengan jumlah waktu yang ingin Anda putar.
Kode
Arduino Sketch - Main
Kode Arduino ini menerima perintah pengemudi dari Ci20 melalui serial dan memastikan bahwa motor dijalankan dengan cara yang benar untuk pergi ke arah yang benar. Saya awalnya menulis ini untuk Raspberry Pi tetapi juga bekerja dengan Ci20.
// Motor 1
int dir1PinA = 3;
int dir2PinA = 2;
int speedPinA = 9; // Perlu pin PWM untuk mengontrol kecepatan motor
// Motor 2
int dir1PinB = 4;
int dir2PinB = 5;
int speedPinB = 8; // Perlu pin PWM untuk mengontrol kecepatan motor
// Motor 3
int dir1PinC = 6;
int dir2PinC = 7;
int speedPinC = 10; // Perlu pin PWM untuk mengontrol kecepatan motor
int x = 0;
int y = 0;
int dominantUltrasonic = 0;
bool moveMotor = false;
int startTime = 0;
void setup() {
Serial.begin(9600);
pinMode(dir1PinA,OUTPUT);
pinMode(dir2PinA,OUTPUT);
pinMode(speedPinA,OUTPUT);
pinMode(dir1PinB,OUTPUT);
pinMode(dir2PinB,OUTPUT);
pinMode(speedPinB,OUTPUT);
pinMode(dir1PinC,OUTPUT);
pinMode(dir2PinC,OUTPUT);
pinMode(speedPinC,OUTPUT);
startTime = millis();
}
String rpiString;
void loop() {
readDataFromRPi();
delay(30);
}
void readDataFromRPi() {
while (Serial.available()) {
delay(3);
if (Serial.available() >0) {
char c = Serial.read();
rpiString += c;
if(c == 'n') { break; }
}
}
if (rpiString.length() >0) {
Serial.println(rpiString);
String isRotate = getValue(rpiString, ' ',0);
String xval = getValue(rpiString, ' ', 1);
String yval = getValue(rpiString, ' ', 2);
x = xval.toInt();
y = yval.toInt();
startTime = millis();
if (isRotate == "r") {
rotate(x);
} else {
driveInDirection(x,y);
}
rpiString="";
}
}
String getValue(String data, char separator, int index) {
int found = 0;
int strIndex[] = {0, -1 };
int 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) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
Arduino Sketch - MotorControl
/* * Motor control code * * This class will include code to make the robot go in any direction * and rotate around the center point. */
void driveInDirection(float newX, float newY) {
delay(20);
float x = newX;
float y = newY;
float theta = atan2(y,x);
float mag = sqrt((x*x) + (y*y));
float vx = mag * cos(theta);
float vy = mag * sin(theta);
float w1 = -vx;
float w2 = 0.5 * vx - sqrt(3)/2 * vy;
float w3 = 0.5 * vx + sqrt(3)/2 * vy;
float wSet[] = {w1, w2, w3};
float largestValue = 0.0;
for (int i = 0; i < 3; i++) {
if(abs(wSet[i]) > largestValue) { largestValue = abs(wSet[i]); }
}
float speedCoef = (float)147.0 / largestValue;
w1 = w1 * speedCoef;
w2 = w2 * speedCoef;
w3 = w3 * speedCoef;
if (x ==0 && y == 0) { w1 = 0; w2 = 0; w3 = 0; }
Serial.println(w1);
Serial.println(w2);
Serial.println(w3);
w1 = constrain(w1, -150, 150);
w2 = constrain(w2, -150, 150);
w3 = constrain(w3, -150, 150);
boolean w1_ccw = w1 < 0 ? true : false;
boolean w2_ccw = w2 < 0 ? true : false;
boolean w3_ccw = w3 < 0 ? true : false;
byte w1_speed = (byte) map(abs(w1), 0, 150, 0, 255);
byte w2_speed = (byte) map(abs(w2), 0, 150, 0, 255);
byte w3_speed = (byte) map(abs(w3), 0, 150, 0, 255);
printMotorSpeed(w1_speed, 1);
printMotorSpeed(w2_speed, 2);
printMotorSpeed(w3_speed, 3);
analogWrite(speedPinA, w1_speed);
analogWrite(speedPinB, w2_speed);
analogWrite(speedPinC, w3_speed);
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 rotate(float milliseconds) {
float w1 = 255;
float w2 = 255;
float w3 = 255;
boolean w1_ccw = w1 < 0 ? true : false;
boolean w2_ccw = w2 < 0 ? true : false;
boolean w3_ccw = w3 < 0 ? true : false;
byte w1_speed = (byte) map(abs(w1), 0, 150, 0, 255);
byte w2_speed = (byte) map(abs(w2), 0, 150, 0, 255);
byte w3_speed = (byte) map(abs(w3), 0, 150, 0, 255);
printMotorSpeed(w1_speed, 1);
printMotorSpeed(w2_speed, 2);
printMotorSpeed(w3_speed, 3);
analogWrite(speedPinA, w1_speed);
analogWrite(speedPinB, w2_speed);
analogWrite(speedPinC, w3_speed);
digitalWrite(dir1PinA, !w1_ccw);
digitalWrite(dir2PinA, w1_ccw);
digitalWrite(dir1PinB, !w2_ccw);
digitalWrite(dir2PinB, w2_ccw);
digitalWrite(dir1PinC, w3_ccw);
digitalWrite(dir2PinC, !w3_ccw);
delay(milliseconds);
analogWrite(speedPinA, 0);
analogWrite(speedPinB, 0);
analogWrite(speedPinC, 0);
}
void printMotorSpeed(byte motorSpeed, int motor) {
Serial.print("Motor");
Serial.print(motor);
Serial.print(": ");
Serial.println(motorSpeed);
}
FaceTracking C++ Untuk Ci20
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
CascadeClassifier face_cascade, eyes_cascade;
String window_name = "Face Detection";
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
int sendSerial(char* message) {
int fd = open("/dev/ttyUSB0", O_RDWR);
if (fd == -1) { perror("dev/ttyUSB0"); return 1; }
struct 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);
write(fd, message, strlen(message));
return 0;
}
void detectFaces(Mat frame) {
std::vector<Rect> faces;
Mat frame_gray;
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 < faces.size(); i++) {
Point center(faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2);
ellipse(frame, center, Size(faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
if(center.x > frame.cols/3 && center.x < frame.cols/3*2) {
char msg[] = "F 50 50";
sendSerial(msg);
} else {
char msg[] = "0 0 ";
sendSerial(msg);
}
}
imshow( window_name, frame );
}
int main() {
char msg[] = "0 0 ";
sendSerial(msg);
VideoCapture cap(0);
cap.set(CV_CAP_PROP_FRAME_WIDTH, 480);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
Mat frame;
if(!face_cascade.load("haarcascade_frontalface_default.xml")) {
std::cout << "classifier";
return -1;
}
while(cap.read(frame)) {
detectFaces(frame);
if( waitKey(30) >= 0) break;
}
return 0;
}
Bagian dan Kotak Khusus
Ini adalah dasar robot omnidireksional, dirancang oleh saya untuk menempatkan semua bagian di dalam dan memiliki tutup yang terpasang. Ini adalah tutup yang menunjukkan Ci20 dalam semua kemuliaannya.
Roda Omnidireksional
Ini adalah desain asli roda omnidireksional. Saya menggunakan separuh dari ini dengan velg dan kemudian mengeditnya untuk memasukkan sumbu motor. File CAD di thingiverse.com
Skematik
Lihat deskripsi yang lebih baik di bagian cerita. Skematik tersedia sebagai gambar dalam dokumen proyek.