Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Robot Pemecah Labirin Berbasis AI Menggunakan Arduino dan Bluetooth

Komponen dan Perlengkapan

Aplikasi dan layanan online:

Tentang Proyek Ini

Pendahuluan

Tutorial ini dikembangkan berdasarkan proyek terakhir saya: Line Follower Robot - PID Control - Android Setup. Setelah Anda memiliki robot dengan kemampuan mengikuti garis, langkah alami berikutnya adalah memberinya beberapa tingkat kecerdasan. Jadi, robot kesayangan kami "Rex, the Robot" sekarang akan mencoba menemukan cara untuk keluar dari "labirin" dengan cara yang tercepat dan paling efisien (sepasang, dia benci Minotaurus).

Untuk memulai, apa perbedaan antara Maze dan Labyrinth? Menurut https://www.labyrinthos.net, di dunia berbahasa Inggris sering dianggap bahwa untuk memenuhi syarat sebagai labirin, desain harus memiliki pilihan di dalam jalan. Jelas, ini akan mencakup banyak instalasi modern di taman hiburan dan atraksi wisata, termasuk labirin 2D kami di sini. Konsensi populer juga menunjukkan bahwa labirin memiliki satu jalan yang mengarah tak terhindarkan dari pintu masuk ke tujuan, meskipun sering kali melalui rute yang paling kompleks dan berbelok-belok.

Sebagian besar labirin, seberapa kompleks pun desainnya tampak, pada dasarnya dibentuk dari satu dinding yang kontinu dengan banyak persimpangan dan cabang. Jika dinding yang mengelilingi tujuan labirin terhubung dengan perimeter labirin di pintu masuk, labirin selalu dapat diselesaikan dengan memegang satu tangan dalam kontak dengan dinding, seberapa banyak lintasan yang mungkin terlibat. Labirin 'sederhana' ini dengan benar dikenal sebagai 'Simply-connected' atau 'perfect maze' atau dengan kata lain, yang tidak mengandung loop.

Kembali ke proyek kami, ini akan dibagi menjadi dua bagian (atau 'passes'):

Video di bawah ini akan menunjukkan contoh Rex menemukan jalan keluar. Pada kali pertama robot menjelajahi labirin, tentu saja itu akan membuang banyak waktu 'memikirkan' apa yang harus dilakukan di setiap persimpangan. Menguji kemungkinan yang banyak, itu akan mengambil beberapa jalan salah dan jalan buntu, yang memaksa dia untuk menjalani jalur yang lebih panjang dan melakukan 'U-Turns' yang tidak perlu. Selama '1st Pass' ini, robot akan mengumpulkan pengalaman, 'mencatat catatan' tentang persimpangan yang berbeda dan menghapus cabang yang buruk. Pada '2nd Pass'nya, robot lurus dan cepat ke akhir tanpa kesalahan atau ragu-ragu. Sepanjang tutorial ini, kita akan menjelajahi secara rinci cara melakukannya:

Langkah 1: Daftar Bahan

Daftar bahan pada dasarnya sama dengan yang digunakan dengan Line Follower Robot, kecuali bahwa saya menyertakan 2 sensor tambahan untuk akurasi yang lebih baik dalam mendeteksi persimpangan KIRI dan KANAN:

Robot akhir masih sangat murah (sekitar $ 85,00):

Tubuh (Anda dapat menyesuaikannya dengan kebutuhan atau bahan yang tersedia):

Catatan: Saya menggunakan item 7 di atas dengan output analog, karena saya tidak memiliki sensor dengan output digital seperti pada item 6. Idealnya memiliki semua sensor yang sama, jika memungkinkan. Saya juga menguji proyek hanya dengan 5 sensor asli. Itu akan bekerja, tetapi memerlukan penyesuaian yang lebih sensitif dalam menemukan persimpangan.

Langkah 2: Perubahan pada Tubuh

Hapus set asli 5 Line Follow Sensors dan pasang sensor refleksi 'Far LEFT' dan 'Far RIGHT' baru di setiap ujung baris plastik pendukung. Disarankan untuk memiliki 7 sensor yang sejajar sebaik mungkin.

Langkah 3: Memasang dan Menguji Sensor Baru

Array sensor baru yang sekarang 7 sensor, dipasang dengan cara sehingga 5 asli digunakan secara eksklusif untuk kontrol PID (dan deteksi 'garis penuh', dijelaskan nanti) dan 2 yang baru, kiri dan kanan, digunakan secara eksklusif untuk deteksi persimpangan KIRI dan KANAN.

Sebagai tinjauan cepat, mari kita ingat cara kerja 5 sensor 'digital' asli:

Jika satu sensor berpusat dengan garis hitam, hanya sensor spesifik itu akan menghasilkan HIGH. Di sisi lain, spasi di antara sensor harus dihitung untuk memungkinkan 2 sensor menutupi lebar penuh garis hitam secara bersamaan, juga menghasilkan sinyal HIGH pada kedua sensor.

Cara kerja 2 sensor 'analog' baru:

Jika salah satu sensor berpusat dengan garis hitam, outputnya akan menjadi nilai analog, biasanya menghasilkan output di Arduino ADC di bawah '100' (ingat bahwa ADC menghasilkan output dari 0 hingga 1023). Dengan permukaan yang lebih terang, nilai output akan lebih tinggi (Saya menguji 500 hingga 600 di atas kertas putih, misalnya). Nilai ini harus diuji dalam situasi cahaya dan bahan permukaan yang berbeda untuk menentukan konstanta THRESHOLD yang benar untuk digunakan dalam kasus Anda (lihat gambar di sini).

Melihat kode Arduino, masing-masing sensor akan didefinisikan dengan nama spesifik (anggaplah bahwa sensor Line Follow asli yang lebih ke Kiri harus ditugaskan dengan label '0 '):

const int lineFollowSensor0 = 12; //Using Digital input const int lineFollowSensor1 = 18; //Using Analog Pin A4 as Digital input const int lineFollowSensor2 = 17; //Using Analog Pin A3 as Digital input const int lineFollowSensor3 = 16; //Using Analog Pin A2 as Digital input const int lineFollowSensor4 = 19; //Using Analog Pin A5 as Digital input const int farRightSensorPin = 0; //Analog Pin A0 const int farLeftSensorPin = 1; //Analog Pin A1 

Untuk diingat, output array 5 sensor asli saat mengikuti garis adalah:

1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 

Ditambahkannya 2 sensor baru, output yang mungkin adalah:

Untuk menyimpan nilai setiap sensor, variabel array dibuat untuk 5 sensor digital asli:

int LFSensor[5]={0, 0, 0, 0, 0}; 

Dan dua variabel integer untuk 2 sensor analog baru:

int farRightSensor = 0; int farLeftSensor = 0; 

Setiap posisi array dan variabel akan terus diperbarui dengan output dari masing-masing sensor:

LFSensor[0] = digitalRead(lineFollowSensor0); LFSensor[1] = digitalRead(lineFollowSensor1); LFSensor[2] = digitalRead(lineFollowSensor2); LFSensor[3] = digitalRead(lineFollowSensor3); LFSensor[4] = digitalRead(lineFollowSensor4); farRightSensor = analogRead(farRightSensorPin); farLeftSensor = analogRead(farLeftSensorPin); 

Memiliki 5 sensor, seperti yang terlihat dalam proyek Follower Line Robot, memungkinkan pembuatan 'variabel error' yang akan membantu mengontrol posisi robot di atas garis. Juga, variabel yang disebut 'mode' akan digunakan untuk definisi apakah robot mengikuti garis, di atas garis kontinu, persimpangan atau tidak ada garis sama sekali.

Variabel 'mode' ini juga akan digunakan dengan sensor 'Far LEFT/RIGHT'. Untuk representasi, anggaplah sensor kiri dan kanan jauh memiliki 3 kemungkinan status:

Untuk output digital, akan 0, 1 biasa dan kita juga akan memperkenalkan X:

Jadi, mengimplementasikan logika di atas dalam fungsi:

void readLFSsensors() 

akan mengembalikan variabel 'mode' dan 'error' yang akan digunakan pada logika program. Penting untuk menguji logika sensor sebelum melanjutkan proyek. Fungsi di bawah ini disertakan dalam kode dan dapat digunakan untuk keperluan pengujian:

void testSensorLogic(void) { Serial.print (farLeftSensor); Serial.print (" <== LEFT RIGH==> "); Serial.print (farRightSensor); Serial.print (" mode: "); Serial.print (mode); Serial.print (" error:"); Serial.println (error); } 

Langkah 4: Memecahkan Labirin - Aturan Tangan Kiri

Seperti yang dibahas pada pendahuluan, sebagian besar labirin, seberapa kompleks pun desainnya tampak, pada dasarnya dibentuk dari satu dinding yang kontinu dengan banyak persimpangan dan cabang. Jika dinding yang mengelilingi tujuan labirin terhubung dengan perimeter labirin di pintu masuk, labirin selalu dapat diselesaikan dengan memegang satu tangan dalam kontak dengan dinding, seberapa banyak lintasan yang mungkin terlibat. Labirin 'sederhana' ini dengan benar dikenal sebagai 'Simply-connected .'

Mencari di Wikipedia, kita belajar bahwa:

Singkatnya, Left-Hand Rule dapat dijelaskan sebagai:

Di setiap persimpangan, dan sepanjang labirin, pegang tangan kiri Anda menyentuh dinding di kiri Anda.

Jadi, kunci di sini adalah untuk mengidentifikasi persimpangan, menentukan arah yang akan diambil berdasarkan aturan di atas. Secara khusus dalam jenis labirin 2D kami, kita dapat menemukan 8 jenis persimpangan yang berbeda (lihat gambar pertama di atas):

Melihat gambar, kita dapat menyadari bahwa tindakan yang mungkin di persimpangan adalah:

1. Di 'Cross':

2. Di 'T':

3. Di 'Right Only':

4. Di 'Left Only':

5. Di 'Straight or Left':

6. Di 'Straight or Right':

7. Di 'Dead End':

8. Di 'End of Maze':

Tetapi, menerapkan 'Left-Hand Rule', tindakan akan dikurangi menjadi satu opsi masing-masing:

Kami hampir sampai! 'Tenang!'

Ketika robot mencapai 'Dead End' atau 'End of a Maze', mudah untuk mengidentifikasi mereka, karena tidak ada situasi ambigu (kami telah mengimplementasikan tindakan tersebut pada Line Follower Robot, ingat?). Masalahnya adalah ketika robot menemukan 'LINE' misalnya, karena garis bisa menjadi 'Cross' (1) atau 'T' (2). Juga ketika mencapai 'LEFT or RIGHT TURN', itu bisa menjadi belokan sederhana (opsional 3 atau 4) atau opsi untuk pergi lurus (5 atau 6). Untuk menemukan tepat jenis persimpangan mana tempat robot, langkah tambahan harus diambil: robot harus berjalan 'inci tambahan' dan melihat apa yang ada selanjutnya (lihat gambar kedua di atas, sebagai contoh).

Jadi, dalam hal alur, tindakan yang mungkin sekarang dapat digambarkan sebagai:

1. Di 'DEAD END':

2. Di 'LINE': Jalankan inci tambahan

3. Di 'RIGHT TURN': Jalankan inci tambahan

4. Di 'LEFT TURN': Jalankan inci tambahan

Perhatikan bahwa sebenarnya, dalam kasus 'LEFT TURN', Anda dapat melewati tes, karena Anda akan mengambil KIRI bagaimanapun. Saya biarkan penjelasan lebih umum hanya untuk kejelasan. Dalam kode asli saya akan melewati tes ini. Gambar ke-3 di atas, menunjukkan labirin yang sangat sederhana di lantai laboratorium saya, digunakan untuk keperluan pengujian.

Langkah 5: Menerapkan Algoritma 'Left Hand on the Wall' di Kode Arduino

Setelah kita memiliki fungsi readLFSsensors() yang dimodifikasi untuk menyertakan 2 sensor tambahan, kita dapat menuliskan ulang fungsi Loop untuk menjalankan algoritma seperti yang dijelaskan pada Langkah terakhir:

void loop() { readLFSsensors(); switch (mode) { case NO_LINE: motorStop(); goAndTurn (LEFT, 180); break; case CONT_LINE: runExtraInch(); readLFSsensors(); if (mode == CONT_LINE) mazeEnd(); else goAndTurn (LEFT, 90); // or it is a "T" or "Cross"). In both cases, goes to LEFT break; case RIGHT_TURN: runExtraInch(); readLFSsensors(); if (mode == NO_LINE) goAndTurn (RIGHT, 90); break; case LEFT_TURN: goAndTurn (LEFT, 90); break; case FOLLOWING_LINE: followingLine(); break; } } 

Beberapa fungsi baru muncul di sini:

void runExtraInch(void) { motorPIDcontrol(); delay(extraInch); motorStop(); } 
void goAndTurn(int direction, int degrees) { motorPIDcontrol(); delay(adjGoAndTurn); motorTurn(direction, degrees); } 

Pada titik ini, robot sebenarnya 'memecahkan labirin'! Anda baru saja menyelesaikan 'Pass Pertama'. Tidak masalah di mana Anda memulai di dalam labirin, Anda akan selalu mencapai akhir.

Di bawah ini, uji fase ini dari proyek:

Langkah 6: Menyimpan Jalur

Mari kita pertimbangkan contoh seperti yang ditunjukkan dalam foto di atas. Di titik awal yang dipilih, robot akan menemukan 15 Persimpangan sebelum mencapai akhir Labirin:

Yang harus dilakukan di salah satu persimpangan tersebut, adalah menyimpan setiap tindakan yang dilakukan tepat dalam urutan yang sama yang terjadi. Untuk itu, mari kita buat variabel baru (array) yang akan menyimpan jalur yang telah ditempuh robot:

char path[100] = " "; 

Kami juga harus membuat 2 variabel indeks yang akan digunakan bersama dengan array:

unsigned char pathLength = 0; // panjang jalur int pathIndex = 0; // digunakan untuk mencapai elemen array tertentu. 

Jadi, jika kita menjalankan contoh yang ditunjukkan dalam gambar, kita akan akhirnya dengan:

path = [LBLLLBSBLLBSLL] dan pathLengh = 14 

Langkah 7: Menyederhanakan (mengoptimalkan) Jalur

Mari kita kembali ke contoh kita. Melihat grup persimpangan pertama, kami menyadari bahwa cabang kiri pertama sebenarnya adalah 'Dead End' dan jadi, jika robot alih-alih 'Kiri-Kembali-Kiri' hanya melewati lurus di persimpangan pertama, banyak energi dan waktu akan terhemat! Dengan kata lain, urutan 'LBL' sebenarnya sama dengan 'S'. Itulah tepatnya bagaimana jalur penuh dapat dioptimalkan. Jika Anda menganalisis semua kemungkinan di mana 'U turn' digunakan, sekumpulan 3 persimpangan di mana 'U-Turn' ('B') muncul ('xBx') dapat dikurangi menjadi hanya satu.

Di atas hanyalah satu contoh, di bawah ini Anda dapat menemukan daftar lengkap kemungkinan (cobalah):

Mengambil jalur penuh dari contoh kami, kita dapat menguranginya:

path = [LBLLLBSBLLBSLL] ==> LBL = S path = [SLLBSBLLBSLL] ==> LBS = R path = [SLRBLLBSLL] ==> RBL = B path = [SLBLBSLL] ==> LBL = S path = [SSBSLL] ==> SBS = B path = [SBLL] ==> SBL = R path = [RL] 

Luar biasa! Melihat contoh ini sangat jelas bahwa jika robot mengambil KANAN di persimpangan pertama dan setelah itu, KIRI, itu akan mencapai Akhir Labirin dengan jalur terpendek!

Path Pertama dari Kode Maze Solver akan dikonsolidasikan dalam fungsi mazeSolve(). Fungsi ini sebenarnya adalah fungsi loop() yang digunakan sebelumnya, tetapi menggabungkan semua langkah penyimpanan dan optimasi jalur tersebut. Ketika path pertama berakhir, array path[] akan memiliki jalur yang dioptimalkan. Variabel baru diperkenalkan:

unsigned int status = 0; // solving = 0; reach Maze End = 1 

Di bawah fungsi Path Pertama:

void mazeSolve(void) { while (!status) { readLFSsensors(); switch (mode) { case NO_LINE: motorStop(); goAndTurn (LEFT, 180); recIntersection('B'); break; case CONT_LINE: runExtraInch(); readLFSsensors(); if (mode != CONT_LINE) {goAndTurn (LEFT, 90); recIntersection('L');} // or it is a "T" or "Cross"). In both cases, goes to LEFT else mazeEnd(); break; case RIGHT_TURN: runExtraInch(); readLFSsensors(); if (mode == NO_LINE) {goAndTurn (RIGHT, 90); recIntersection('R');} else recIntersection('S'); break; case LEFT_TURN: goAndTurn (LEFT, 90); recIntersection('L'); break; case FOLLOWING_LINE: followingLine(); break; } } } 

Di sini fungsi baru diperkenalkan: recIntersection (direction). Fungsi ini akan digunakan untuk menyimpan persimpangan dan juga untuk memanggil fungsi lain simplifyPath(), yang akan mengurangi sekelompok 3 persimpangan yang melibatkan 'U-Turn' seperti yang kita lihat sebelumnya.

void recIntersection(char direction) { path[pathLength] = direction; // Store the intersection in the path variable. pathLength ++; simplifyPath(); // Simplify the learned path. } 

KREDIT untuk fungsi simplifyPath() adalah Patrick McCabe untuk kode Path Solving (untuk detail, kunjungi https://patrickmccabemakes.com)! Strategi Penyederhanaan Jalur adalah setiap kali kita menemui urutan xBx, kita dapat menyederhanakannya dengan menghapus jalan buntu. Misalnya, LBL ==> S seperti yang kita lihat pada contoh.

void simplifyPath() { // only simplify the path if the second-to-last turn was a 'B' if(pathLength < 3 || path[pathLength-2] != 'B') return; int totalAngle = 0; int i; for(i=1;i<=3;i++) { switch(path[pathLength-i]) { case 'R': totalAngle += 90; break; case 'L': totalAngle += 270; break; case 'B': totalAngle += 180; break; } } // Get the angle as a number between 0 and 360 degrees. totalAngle = totalAngle % 360; // Replace all of those turns with a single one. switch(totalAngle) { case 0: path[pathLength - 3] = 'S'; break; case 90: path[pathLength - 3] = 'R'; break; case 180: path[pathLength - 3] = 'B'; break; case 270: path[pathLength - 3] = 'L'; break; } // The path is now two steps shorter. pathLength -= 2; } 

Langkah 8: Pass Kedua: memecahkan Labirin secepat mungkin!

Program utama: loop () sederhana seperti itu:

void loop() { ledBlink(1); readLFSsensors(); mazeSolve(); // First pass to solve the maze ledBlink(2); while (digitalRead(buttonPin) { } pathIndex = 0; status = 0; mazeOptimization(); // Second Pass: run the maze as fast as possible ledBlink(3); while (digitalRead(buttonPin) { } mode = STOPPED; status = 0; // 1st pass pathIndex = 0; pathLength = 0; } 

Jadi, ketika Pass Pertama berakhir, yang harus kita lakukan hanyalah memberi robot array jalur yang dioptimalkan. Robot akan mulai berjalan dan ketika persimpangan ditemukan, sekarang akan menentukan apa yang harus dilakukan berdasarkan apa yang disimpan di path[] .

void mazeOptimization (void) { while (!status) { readLFSsensors(); switch (mode) { case FOLLOWING_LINE: followingLine(); break; case CONT_LINE: if (pathIndex >= pathLength) mazeEnd (); else {mazeTurn (path[pathIndex]); pathIndex++;} break; case LEFT_TURN: if (pathIndex >= pathLength) mazeEnd (); else {mazeTurn (path[pathIndex]); pathIndex++;} break; case RIGHT_TURN: if (pathIndex >= pathLength) mazeEnd (); else {mazeTurn (path[pathIndex]); pathIndex++;} break; } } } 

Untuk memerintahkan apa yang harus dilakukan, fungsi baru mazeTurn(path[]) dibuat. Fungsi mazeTurn (path[]) akan menjadi:

void mazeTurn (char dir) { switch(dir) { case 'L': // Turn Left goAndTurn (LEFT, 90); break; case 'R': // Turn Right goAndTurn (RIGHT, 90); break; case 'B': // Turn Back goAndTurn (RIGHT, 800); break; case 'S': // Go Straight runExtraInch(); break; } } 

Pass Kedua selesai! Video di bawah ini menunjukkan contoh lengkap yang dikerjakan di sini, pass pertama dan kedua. Di bawah ini kode Arduino yang digunakan dalam tutorial ini:

Langkah 9: Menggunakan Android untuk pengaturan

Aplikasi Android yang dikembangkan untuk proyek Following Line juga dapat digunakan di sini (jika diperlukan, Aplikasi Android dan kodenya tersedia di: Line Follower Robot - PID Control - Android Setup. Kode Arduino yang disajikan di langkah terakhir sudah termasuk komunikasi dengan perangkat Android. Jika Anda tidak ingin menggunakan aplikasi Android, tidak masalah karena kode adalah 'transparent '.

Saya menggunakan Android banyak selama proyek untuk mengirim data pengujian dari robot ke perangkat menggunakan field 'Message Received '. Beberapa variabel harus didefinisikan dengan baik untuk memastikan robot akan berputar dengan sudut yang benar. Yang terpenting di bawah ini (yang ditulis tebal saya ubah beberapa kali):

const int adj = 0; float adjTurn = 8; int adjGoAndTurn = 800; THRESHOLD = 150 const int power = 250; const int iniMotorPower = 250; int extraInch = 200; 

Langkah 10: Kesimpulan

Ini adalah bagian kedua dan terakhir dari proyek kompleks, menjelajahi potensi robot Follower Line, di mana konsep sederhana Kecerdasan Buatan (AI) digunakan untuk memecahkan labirin.

Saya bukan ahli AI dan berdasarkan beberapa informasi yang saya dapatkan dari web, saya memahami bahwa apa yang dilakukan robot kecil kami, Rex, memecahkan labirin dapat dianggap sebagai aplikasi AI. Mari kita lihat 2 sumber di bawah ini:

Dari Wikipedia:

Atau dari makalah universitas ini: "Maze Solving Robot Using Freeduino and LSRB Algorithm International Journal of Modern Engineering Research (IJMER)"

File yang diperbarui untuk proyek ini dapat ditemukan di GITHUB. Semoga saya dapat berkontribusi untuk orang lain mempelajari lebih banyak tentang elektronika, robot, Arduino, dll. Untuk tutorial lainnya, kunjungi Blog saya: MJRoBot.org

Saludos dari selatan dunia!

Terima kasih

Marcelo

Kode

Beberapa cuplikan kode tersedia di bagian bawah proyek, termasuk cuplikan #1, #4, #5, #6, #7, #8, #12, #13, #14, #15, #16, dan #17.

Github

https://github.com/Mjrovai/MJRoBot-Maze-Solver

Skematik

File skematik tersedia di bagian bawah proyek.

Proses manufaktur

  1. Membangun Robot Cerdas dengan Bridge Shield – Integrasi Raspberry Pi & Arduino
  2. Robot yang Dikontrol Gestur dengan Raspberry Pi
  3. Membangun Robot Raspberry Pi Dikontrol Wi‑Fi dengan Python – Panduan Langkah demi Langkah
  4. Integrasi Microsoft Kinect dengan Raspberry Pi untuk Deteksi Manusia Real-Time pada Robot Sonbi
  5. Bosch Meluncurkan Solusi Manufaktur Berbasis AI di Hannover Messe
  6. Kecerdasan Buatan di Retail: Manfaat Terbukti, Bukan Tren Sementara
  7. Kubernetes Memberdayakan Start-up AI dengan Solusi Terkontainer yang Skalabel
  8. AI Memberdayakan Robot untuk Mengidentifikasi 90+ Objek dengan Sentuhan
  9. Pelacakan Deforestasi Amazon Berbasis AI
  10. Robotika Berbasis AI: Mesin Cerdas Terkini