Robot Penghindar Rintangan dengan Arduino: Panduan HC-SR04 dan Servo
Buat robot penghindar rintangan dengan Arduino: HC-SR04 yang memindai di atas servo, pengkabelan L298N atau L293D, logika berhenti-mundur-belok, sensor IR, dan mode manual lewat Bluetooth.
Robot penghindar rintangan adalah mobil robot yang berjalan sendiri, menyadari dinding, kursi, atau kotak di depannya tanpa menabraknya, lalu mencari jalan baru. Rakitan yang paling umum memakai Arduino Uno, sensor jarak ultrasonik HC-SR04, motor servo SG90 yang memutar sensor ke kiri dan kanan, dua motor DC bergearbox, dan driver motor L298N (atau L293D). Robot berjalan lurus, berhenti ketika sudah dekat dengan rintangan, mundur sedikit, menoleh ke kedua sisi untuk mengukur, lalu melanjutkan perjalanan ke arah yang paling lega.
Di panduan ini kita mengubah mobil 2WD dari artikel Mobil Robot Arduino menjadi robot otonom dengan susunan pin yang sama. Langkah demi langkah kita bahas tabel pengkabelan, cara menghitung ambang jarak, kode yang berkembang dalam tiga tahap, permukaan yang tidak terlihat oleh sensor dan cara menutup celah itu dengan sensor inframerah, dan terakhir beralih ke mode manual lewat Bluetooth dari ponselmu. Kode untuk menjalankan robot yang sama dengan ESP32 atau Raspberry Pi Pico ada di akhir artikel.

Bagaimana cara kerja robot penghindar rintangan?
Setiap robot otonom mengulang siklus tiga langkah yang sama puluhan kali per detik: merasakan, memutuskan, bertindak. HC-SR04 yang merasakan: ia mengirim suara 40 kHz pendek yang tidak bisa didengar telingamu dan mengukur berapa lama pantulannya kembali; bagi waktu dalam mikrodetik itu dengan 58 dan kamu mendapat jarak dalam sentimeter. Arduino yang memutuskan dengan membandingkan jarak terukur dengan ambang yang kamu tetapkan. L298N dan motor yang bertindak. Karena sensornya terpasang di servo, robot bisa “melihat” ke kiri dan kanan tanpa memutar badannya, jadi keputusan beloknya jauh lebih baik daripada robot dengan sensor yang diam. Detail cara kerja sensor ini ada di artikel Sensor Jarak HC-SR04.
| Komponen | Tugas | Catatan |
|---|---|---|
| Arduino Uno (atau Nano) | Otak: mengukur, memutuskan, dan memerintah motor | ESP32 atau Pico juga bisa |
| HC-SR04 | Mata: mengukur jarak ke rintangan di depan | Bekerja di 5 V, 2–400 cm |
| Servo SG90 | Leher: memutar sensor ke kiri dan kanan | Sensor dipasang ke lengan servo dengan braket plastik |
| L298N atau shield L293D | Otot: memberi arah dan kecepatan ke motor | Pin Arduino tidak sanggup memberi arus motor |
| 2 motor TT bergearbox dan roda caster | Differential drive | Belok dilakukan dengan memutar kedua roda ke arah berlawanan |
| 2 × sel 18650 (7,4 V) | Daya | Baterai 9 V tidak cukup |
| 2 sensor rintangan IR (opsional) | Menangkap rintangan di sudut dan samping | Modul berbasis LM393 seperti FC-51 |
| HC-05 (opsional) | Kendali manual dari ponselmu | Hanya bisa dengan Android |




Catu daya: jangan biarkan servo me-reset robot
Karena robot penghindar rintangan menambahkan servo ke motor, pembagian daya lebih penting daripada di mobil robot biasa. SG90 menarik sekitar 10 mA ketika diam; begitu mulai bergerak, arusnya melonjak ke 100–250 mA, dan ketika terbebani ia mendekati setengah ampere. Kalau lonjakan ini bersamaan dengan arus start motor, jalur 5 V Arduino anjlok sekejap dan board restart. Solusinya sederhana: motor mendapat daya dari baterai lewat L298N, Arduino dari baterai lewat VIN, sedangkan servo, HC-SR04, sensor IR, dan HC-05 berbagi pin 5V Arduino, dengan kapasitor 470 µF dipasang di dekat kabel catu servo. Bahkan ketika servo bergerak, total beban di jalur 5 V tetap di bawah setengah ampere, dan karena singkat, regulator Uno masih sanggup menanganinya. Untuk menghitung umur baterai dengan angkamu sendiri, pakai alat Umur baterai.
| Bagian | Sumber daya | Arus umum |
|---|---|---|
| 2 motor TT | Terminal 12V L298N ← 2 × 18650 (7,4 V) | 0,3–0,6 A ketika berjalan, sampai 2 A ketika start |
| Arduino Uno | VIN ← positif baterai (setelah sakelar) | Sekitar 50 mA |
| Servo SG90 | 5V Arduino + kapasitor 470 µF | ~10 mA ketika diam, 100–250 mA ketika bergerak |
| HC-SR04 | 5V Arduino | Sekitar 15 mA |
| 2 sensor IR | 5V Arduino | Masing-masing 20–40 mA |
| HC-05 | 5V Arduino | 30–40 mA ketika pairing, sekitar 10 mA ketika terhubung |
Skema pengkabelan: Arduino Uno, ESP32, dan Pico
Pin motornya sama dengan di panduan mobil robot, jadi kamu bisa beralih ke proyek ini hanya dengan menambahkan kepala sensor tanpa membongkar mobilmu. Pin kecepatan sengaja ditaruh di 5 dan 6: di Uno, library Servo memakai Timer1 sehingga mematikan PWM di pin 9 dan 10; kalau kecepatan motor ada di pin itu, kendali kecepatan langsung rusak begitu servo dipasang. HC-SR04 dan sensor IR dipasang di A0–A3. Pin analog Uno juga bisa berfungsi sebagai pin digital 14–19 kalau perlu, dan pilihan ini memudahkan pemakaian kode yang sama dengan shield L293D, karena shield tidak menyentuh pin-pin ini. Susunan pin board-mu bisa kamu lihat di alat Pinout.
| Koneksi | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| L298N ENA (kecepatan motor kiri) | D5 | GPIO 25 | GP15 |
| L298N IN1, IN2 | D7, D8 | GPIO 27, 33 | GP14, GP13 |
| L298N ENB (kecepatan motor kanan) | D6 | GPIO 26 | GP10 |
| L298N IN3, IN4 | D9, D4 | GPIO 32, 4 | GP12, GP11 |
| Sinyal servo (oranye) | D3 | GPIO 13 | GP16 |
| Servo + (merah), − (cokelat) | 5V, GND | 5V L298N, GND | 5V L298N, GND |
| HC-SR04 TRIG | A0 | GPIO 18 | GP17 |
| HC-SR04 ECHO | A1 (langsung) | GPIO 19, lewat pembagi 1 kΩ / 2 kΩ | GP18, lewat pembagi 1 kΩ / 2 kΩ |
| HC-SR04 VCC | 5V | 5V L298N | 5V L298N |
| OUT IR kiri, OUT IR kanan | A2, A3 | GPIO 23, 22 | GP19, GP20 |
| VCC sensor IR | 5V | 3V3 | 3V3 |
| HC-05 TXD, RXD | D10, D11 (RXD lewat pembagi) | Tidak perlu (Bluetooth bawaan) | GP1, GP0 (UART0) |
| Daya board | VIN ← baterai (setelah sakelar) | 5V (VIN) ← 5V L298N | VSYS ← 5V L298N |
Pasang dan uji kepala sensor

- Hubungkan servo tanpa lengannya dan upload sketch uji di bawah. Di akhir setiap sapuan, kode memutar servo ke 90 derajat dan menunggu 2 detik; cabut kabel USB selama jeda itu dan servo akan diam di posisinya. Pasang lengan ke porosnya sehingga sensor menghadap lurus ke depan; dengan begitu 90 derajat berarti “lurus ke depan”.
- Pasang HC-SR04 ke lengan servo dengan braket plastik atau lem tembak. Kabel sensor harus cukup panjang supaya tidak tertarik kencang ketika servo berputar; kabel yang tersangkut di sasis selama sapuan 140 derajat adalah kerusakan yang umum.
- Pasang sensor 8–12 cm di atas lantai dan dekat dengan titik paling depan badan robot. Terlalu rendah, ia menangkap pantulan dari lantai dan tekstur karpet; terlalu tinggi, ia tidak bisa melihat rintangan yang rendah.
- Miringkan sensor 3–5 derajat ke atas. Sensor yang benar-benar datar dan rendah bisa mengira pantulan dari lantai sebagai rintangan, terutama di lantai yang kasar.
- Buka Serial Monitor pada 9600 baud. Kalau kamu melihat nilai kecil di baris 125 dan 160 derajat ketika tanganmu ada di sebelah kiri sensor, sisi kiri adalah sudut-sudut besar; kalau sebaliknya, atur SERVO_DIR ke -1 di sketch lanjutan dan tukar nilai LEFT_ANGLE dan RIGHT_ANGLE di sketch pertama.
1#include <Servo.h>
2
3const int SERVO_PIN = 3;
4const int TRIG = A0, ECHO = A1; // analog pinler dijital pin olarak / analog pins used as digital pins
5Servo head;
6
7int pingCm() {
8 digitalWrite(TRIG, LOW); delayMicroseconds(2);
9 digitalWrite(TRIG, HIGH); delayMicroseconds(10); // 10 µs tetik darbesi / 10 µs trigger pulse
10 digitalWrite(TRIG, LOW);
11 unsigned long t = pulseIn(ECHO, HIGH, 25000UL); // en fazla 25 ms bekle (~4,3 m) / wait at most 25 ms (~4.3 m)
12 return t / 58; // 0 = yankı yok / 0 = no echo
13}
14
15void setup() {
16 Serial.begin(9600);
17 pinMode(TRIG, OUTPUT);
18 pinMode(ECHO, INPUT);
19 head.attach(SERVO_PIN);
20 head.write(90); // önce ortala / center first
21 delay(1000);
22}
23
24void loop() {
25 const int angles[] = {20, 55, 90, 125, 160};
26 for (int a : angles) {
27 head.write(a);
28 delay(400); // servo yerine otursun / let the servo settle
29 Serial.print(a);
30 Serial.print(F(" derece / degrees: "));
31 Serial.print(pingCm());
32 Serial.println(F(" cm"));
33 }
34 Serial.println();
35 head.write(90);
36 delay(2000);
37}Setiap baris menunjukkan satu sudut dan jarak ke arah itu. Kalau tidak ada apa-apa dalam jarak sekitar 4 meter dari sensor, kamu akan membaca 0 cm: pulseIn() mengembalikan 0 kalau tidak ada pantulan dalam 25 ms. Di kode utama kita akan menganggap 0 sebagai “jalan kosong”, tapi sensor dengan kabel longgar atau TRIG dan ECHO yang tertukar biasanya juga membaca 0. Jadi sebelum menaruh robot di lantai, tahan tanganmu di 10, 30, dan 60 cm dan pastikan nilainya benar-benar berubah; robot yang dijalankan tanpa uji ini akan menabrak dinding tanpa melambat.
Algoritma keputusan: berhenti, mundur, belok ke arah yang paling lega
Membagi perilaku robot ke dalam zona berdasarkan jarak membuat kodenya sederhana sekaligus andal. Tanpa rintangan di depan, robot melaju dengan kecepatan penuh, melambat ketika rintangan makin dekat, dan begitu mencapai ambang berhenti, ia berhenti dan memindai. Selama pemindaian, sensor melihat 70 dan 35 derajat ke kiri serta 35 dan 70 derajat ke kanan; di setiap arah diambil tiga pembacaan dan nilai mediannya yang dipakai. Robot berbelok ke arah dengan jarak terpanjang, sebesar sudut itu. Kalau tidak ada arah yang lega, misalnya ketika ia masuk ke sudut ruangan, ia mundur sedikit dan berbelok 180 derajat.
| Jarak terukur | Zona | Yang dilakukan robot |
|---|---|---|
| Di atas 60 cm (atau tanpa pantulan) | Kosong | Maju dengan kecepatan penuh (PWM 200) |
| 25–60 cm | Mendekat | Melambat sebanding dengan jarak (PWM 200 turun ke 130) |
| 12–25 cm | Rintangan | Berhenti, memastikan pembacaan, memindai ke dua arah, belok ke arah yang paling lega |
| Di bawah 12 cm | Terlalu dekat | Mundur dulu selama 350 ms, lalu memindai |
| Semua arah di bawah 35 cm | Jalan buntu | Mundur dan berbelok 180 derajat |
Ambang-ambang ini tidak dipilih asal-asalan. Jarak berhenti adalah jumlah tiga margin: margin reaksi (jarak yang ditempuh di antara dua pembacaan), margin pengereman (seberapa jauh robot masih meluncur setelah motor diputus), dan margin belok (agar moncongnya tidak menyentuh rintangan ketika berputar di tempat). Mobil dengan motor TT di 6 V melaju sekitar 0,5–0,7 m/dtk dan menempuh 3–4 cm dalam interval pengukuran 60 ms. Margin pengereman sekitar 5 cm, dan untuk badan selebar 15 cm yang berputar di tempat, margin beloknya sekitar 10 cm. Totalnya sekitar 18–20 cm; ditambah beberapa sentimeter margin keamanan, STOP_CM = 25 adalah titik awal yang baik. Kalau robotmu lebih cepat atau lantainya licin, naikkan ambangnya ke 30–35 cm. Sebaliknya, di koridor sempit, ambang yang terlalu besar membuat robot terus berhenti dan memindai, jadi lakukan penyetelan akhir di lintasanmu sendiri.
Kode langkah demi langkah 1: robot penghindar rintangan pertamamu
Versi pertama adalah kerangka algoritmanya: maju, berhenti di 25 cm, mundur, lihat ke kiri dan kanan, belok ke sisi yang lebih lega. Fungsi motor drive(left, right) sama dengan di panduan mobil robot dan menerima nilai dari -255 sampai 255; positif berarti maju, negatif berarti mundur. Setelah meng-upload kode, taruh dulu mobilnya di atas kotak dengan roda tidak menyentuh lantai, lalu perhatikan bagaimana ia berhenti dan berbelok ketika kamu mendekatkan tangan ke sensor; kalau semuanya terlihat benar, taruh robot di lantai.
1#include <Servo.h>
2
3const int ENA = 5, IN1 = 7, IN2 = 8; // sol motor / left motor
4const int ENB = 6, IN3 = 9, IN4 = 4; // sağ motor / right motor
5const int SERVO_PIN = 3;
6const int TRIG = A0, ECHO = A1;
7
8const int STOP_CM = 25; // bu mesafede dur / stop at this distance
9const int SPEED = 170; // düz gidiş hızı / cruising speed
10const int TURN = 170; // dönüş hızı / turning speed
11const int LEFT_ANGLE = 160, RIGHT_ANGLE = 20; // ters ise yer değiştir / swap if reversed
12
13Servo head;
14
15void drive(int left, int right) { // her biri -255 … 255 / each -255 … 255
16 digitalWrite(IN1, left > 0); digitalWrite(IN2, left < 0);
17 digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
18 analogWrite(ENA, abs(left));
19 analogWrite(ENB, abs(right));
20}
21
22int pingCm() {
23 digitalWrite(TRIG, LOW); delayMicroseconds(2);
24 digitalWrite(TRIG, HIGH); delayMicroseconds(10);
25 digitalWrite(TRIG, LOW);
26 unsigned long t = pulseIn(ECHO, HIGH, 25000UL);
27 if (t == 0) return 400; // yankı yok: önü açık say / no echo: treat as open
28 return t / 58;
29}
30
31int lookAt(int angle) {
32 head.write(angle);
33 delay(400); // servo dönsün ve dursun / let the servo turn and settle
34 return pingCm();
35}
36
37void setup() {
38 int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4, TRIG};
39 for (int p : pins) pinMode(p, OUTPUT);
40 pinMode(ECHO, INPUT);
41 drive(0, 0);
42 head.attach(SERVO_PIN);
43 head.write(90);
44 delay(3000); // yere koyman için süre / time to put it on the floor
45}
46
47void loop() {
48 int front = pingCm();
49 if (front > STOP_CM) {
50 drive(SPEED, SPEED); // yol açık: ileri / path clear: forward
51 delay(60); // ölçümler arası 60 ms / 60 ms between readings
52 return;
53 }
54
55 drive(0, 0); // 1) dur / 1) stop
56 delay(150);
57 drive(-SPEED, -SPEED); // 2) biraz geri çekil / 2) back off a little
58 delay(300);
59 drive(0, 0);
60
61 int left = lookAt(LEFT_ANGLE); // 3) iki yana bak / 3) look both ways
62 int right = lookAt(RIGHT_ANGLE);
63 head.write(90);
64 delay(300);
65
66 if (left < STOP_CM && right < STOP_CM) { // iki yan kapalı: geri dön / both blocked: turn around
67 drive(-TURN, TURN);
68 delay(700);
69 } else if (left > right) { // 4) daha açık tarafa dön / 4) turn to the more open side
70 drive(-TURN, TURN);
71 delay(350);
72 } else {
73 drive(TURN, -TURN);
74 delay(350);
75 }
76 drive(0, 0);
77 delay(100);
78}Kode ini menjalankan tugasnya, tapi punya beberapa kelemahan: satu pembacaan yang salah membuat robot berhenti tanpa alasan, ia selalu mendekati rintangan dengan kecepatan yang sama, ia hanya melihat ke dua arah, dan lama beloknya tidak bergantung pada sudut. Selain itu, karena menunggu dengan delay(), ia tidak bisa bereaksi terhadap apa pun selama pemindaian. Detail logika menunggu ada di artikel millis() dan delay(); versi berikutnya memperbaiki sebagian besar masalah ini.
Kode langkah demi langkah 2: filter, perlambatan bertahap, IR, dan Bluetooth
Versi lanjutan bekerja dengan pengkabelan yang sama, dan tidak masalah kalau kamu belum memasang sensor IR dan HC-05. Karena input IR diatur dengan INPUT_PULLUP, sensor yang tidak terhubung terbaca “tidak ada rintangan” (HIGH); tanpa HC-05, robot langsung mulai dalam mode otomatis. Tabel di bawah menjelaskan fungsi setiap bagian kode.
1#include <Servo.h>
2#include <SoftwareSerial.h>
3
4// Pinler / Pins
5const int ENA = 5, IN1 = 7, IN2 = 8; // sol motor / left motor
6const int ENB = 6, IN3 = 9, IN4 = 4; // sağ motor / right motor
7const int SERVO_PIN = 3;
8const int TRIG = A0, ECHO = A1;
9const int IR_LEFT = A2, IR_RIGHT = A3; // LOW = engel (takılı değilse HIGH) / LOW = obstacle (HIGH if not fitted)
10SoftwareSerial bt(10, 11); // RX, TX → HC-05 TXD, RXD (RXD bölücüyle / RXD via divider)
11
12// Ayarlar / Settings
13const int BACK_CM = 12; // daha yakınsa geri çekil / closer: back off first
14const int STOP_CM = 25; // dur ve tara / stop and scan
15const int SLOW_CM = 60; // yavaşlamaya başla / start slowing down
16const int GUARD_CM = 15; // manuel modda çarpışma koruması / collision guard in manual mode
17const int MAX_CM = 400;
18const int CRUISE = 200, SLOW = 130, TURN = 170; // PWM hızları / PWM speeds
19const int SERVO_CENTER = 90; // sensör öne bakmıyorsa düzelt / adjust if not facing ahead
20const int SERVO_DIR = 1; // +70 sola bakmıyorsa -1 yap / set to -1 if +70 doesn't look left
21const float MS_PER_DEG = 4.0; // derece başına ms, kalibre et / ms per degree, calibrate
22const unsigned long BT_TIMEOUT = 600; // manuelde komut kesilirse dur / stop if commands stop
23
24Servo head;
25bool autoMode = true;
26int manualLeft = 0, manualRight = 0, manualSpeed = 200;
27unsigned long lastCmd = 0, lastPing = 0;
28
29void drive(int left, int right) { // her biri -255 … 255 / each -255 … 255
30 left = constrain(left, -255, 255);
31 right = constrain(right, -255, 255);
32 digitalWrite(IN1, left > 0); digitalWrite(IN2, left < 0);
33 digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
34 analogWrite(ENA, abs(left));
35 analogWrite(ENB, abs(right));
36}
37
38int pingCm() {
39 digitalWrite(TRIG, LOW); delayMicroseconds(2);
40 digitalWrite(TRIG, HIGH); delayMicroseconds(10);
41 digitalWrite(TRIG, LOW);
42 unsigned long t = pulseIn(ECHO, HIGH, 25000UL); // ~4,3 m zaman aşımı / ~4.3 m timeout
43 return t == 0 ? MAX_CM : (int)(t / 58); // yankı yok = açık alan / no echo = open space
44}
45
46int distanceCm() { // 3 ölçümün ortancası / median of 3 readings
47 int a = pingCm(); delay(60);
48 int b = pingCm(); delay(60);
49 int c = pingCm();
50 return max(min(a, b), min(max(a, b), c));
51}
52
53bool irBlocked(int pin) {
54 return digitalRead(pin) == LOW;
55}
56
57int lookAt(int offset) { // + sol, - sağ (derece) / + left, - right (degrees)
58 head.write(SERVO_CENTER + SERVO_DIR * offset);
59 delay(300); // servo yerine otursun / let the servo settle
60 return distanceCm();
61}
62
63void turnBy(int deg) { // + sola, - sağa / + left, - right
64 if (deg > 0) drive(-TURN, TURN);
65 else drive(TURN, -TURN);
66 delay((unsigned long)(abs(deg) * MS_PER_DEG));
67 drive(0, 0);
68 delay(100);
69}
70
71void avoid() {
72 drive(0, 0); // 1) dur / 1) stop
73 delay(120);
74 int front = distanceCm(); // ortancayla doğrula / confirm with the median
75 bool sides = irBlocked(IR_LEFT) || irBlocked(IR_RIGHT);
76 if (front >= STOP_CM && !sides) return; // yanlış alarm / false alarm
77
78 if (front < BACK_CM || sides) { // 2) çok yakın: geri çekil / 2) too close: back off
79 drive(-TURN, -TURN);
80 delay(350);
81 drive(0, 0);
82 }
83
84 const int offsets[] = {70, 35, -35, -70}; // 3) tara / 3) scan
85 int bestOffset = 0, bestCm = 0;
86 for (int off : offsets) {
87 int cm = lookAt(off);
88 if (cm > bestCm) { bestCm = cm; bestOffset = off; }
89 }
90 head.write(SERVO_CENTER);
91 delay(200);
92
93 if (bestCm < STOP_CM + 10) { // her yön kapalı: çıkmaz / every way blocked: dead end
94 drive(-TURN, -TURN);
95 delay(400);
96 turnBy(180);
97 } else {
98 turnBy(bestOffset); // 4) en açık yöne dön / 4) turn to the most open direction
99 }
100}
101
102void autoStep() {
103 if (millis() - lastPing < 60) return; // 60 ms'de bir ölç / measure every 60 ms
104 lastPing = millis();
105 int d = pingCm();
106 bool l = irBlocked(IR_LEFT), r = irBlocked(IR_RIGHT);
107
108 if (d < STOP_CM || (l && r)) {
109 avoid();
110 } else if (l) { // sol köşede engel: sağa kaç / front-left: dodge right
111 drive(TURN, -TURN);
112 delay(150);
113 } else if (r) { // sağ köşede engel: sola kaç / front-right: dodge left
114 drive(-TURN, TURN);
115 delay(150);
116 } else if (d < SLOW_CM) {
117 int s = map(d, STOP_CM, SLOW_CM, SLOW, CRUISE); // yaklaştıkça yavaşla / slow down as you get closer
118 drive(s, s);
119 } else {
120 drive(CRUISE, CRUISE);
121 }
122}
123
124void manualStep() {
125 if (millis() - lastCmd > BT_TIMEOUT) { // komut yok: dur / no commands: stop
126 manualLeft = 0;
127 manualRight = 0;
128 }
129 static int front = MAX_CM;
130 if (millis() - lastPing >= 60) {
131 lastPing = millis();
132 front = pingCm();
133 }
134 bool forward = manualLeft > 0 && manualRight > 0;
135 if (forward && front < GUARD_CM) drive(0, 0); // çarpışma koruması / collision guard
136 else drive(manualLeft, manualRight);
137}
138
139void handleBluetooth() {
140 while (bt.available()) {
141 char c = bt.read();
142 Serial.println(c); // gelen harfi göster / show the incoming letter
143 lastCmd = millis();
144 if (c == 'A') { // otomatik mod / auto mode
145 autoMode = true;
146 continue;
147 }
148 if (c == 'M') { // manuel mod / manual mode
149 autoMode = false;
150 manualLeft = manualRight = 0;
151 drive(0, 0);
152 head.write(SERVO_CENTER);
153 continue;
154 }
155 if (autoMode) continue; // otomatikte yön harflerini yok say / ignore in auto mode
156 int s = manualSpeed;
157 switch (c) {
158 case 'F': manualLeft = s; manualRight = s; break; // ileri / forward
159 case 'B': manualLeft = -s; manualRight = -s; break; // geri / backward
160 case 'L': manualLeft = -s; manualRight = s; break; // yerinde sola / spin left
161 case 'R': manualLeft = s; manualRight = -s; break; // yerinde sağa / spin right
162 case 'S': manualLeft = 0; manualRight = 0; break; // dur / stop
163 default:
164 if (c >= '0' && c <= '9') manualSpeed = map(c - '0', 0, 9, 100, 240); // hız kademesi / speed level
165 }
166 }
167}
168
169void setup() {
170 int outs[] = {ENA, IN1, IN2, ENB, IN3, IN4, TRIG};
171 for (int p : outs) pinMode(p, OUTPUT);
172 drive(0, 0);
173 pinMode(ECHO, INPUT);
174 pinMode(IR_LEFT, INPUT_PULLUP);
175 pinMode(IR_RIGHT, INPUT_PULLUP);
176 Serial.begin(9600);
177 bt.begin(9600); // HC-05 veri modu hızı / HC-05 data mode baud rate
178 head.attach(SERVO_PIN);
179 head.write(SERVO_CENTER);
180 delay(3000); // yere koyman için süre / time to put it on the floor
181}
182
183void loop() {
184 handleBluetooth();
185 if (autoMode) autoStep();
186 else manualStep();
187}| Fungsi atau pengaturan | Fungsinya |
|---|---|
| pingCm() | Mengambil satu pembacaan; mengembalikan 400 cm (ruang kosong) kalau tidak ada pantulan dalam 25 ms |
| distanceCm() | Mengambil 3 pembacaan berjarak 60 ms dan mengembalikan mediannya; membuang satu nilai pencilan |
| autoStep() | Mengukur setiap 60 ms; berdasarkan jarak dan sensor IR, robot terus melaju, melambat, mengelak, atau memanggil avoid() |
| avoid() | Berhenti, memastikan pembacaan, mundur kalau perlu, melihat ke 4 arah, dan berbelok ke arah yang paling lega |
| turnBy(degrees) | Memutar robot di tempat sebesar sudut yang diberikan; lamanya dihitung dengan MS_PER_DEG |
| manualStep() | Menjalankan arah yang dikirim dari ponsel; berhenti di 15 cm ketika maju, berhenti kalau tidak ada perintah selama 600 ms |
| SERVO_CENTER, SERVO_DIR | Sudut ketika sensor menghadap lurus ke depan dan arah mana yang kiri |
| STOP_CM, SLOW_CM, BACK_CM | Ambang berhenti, melambat, dan mundur |
Untuk robot penghindar rintangan, filter median lebih unggul daripada rata-rata: untuk tiga pembacaan seperti 24, 26, dan 400 cm, rata-ratanya 150 cm dan menyesatkan robot, sedangkan median memilih 26 cm. Kalau ingin mendalaminya, lihat artikel memfilter data sensor. Pembagian mode otomatis dan manual sebenarnya juga state machine kecil; pendekatan ini kami jelaskan secara detail di panduan state machine Arduino. Setelah meng-upload kode, setel robot sesuai ruanganmu dengan urutan ini:
- Titik tengah servo: Dengan robot menghadap tegak lurus ke dinding datar, kalau sensor tidak menunjuk lurus ke dinding itu, ubah SERVO_CENTER sedikit demi sedikit, misalnya ke 85 atau 95.
- Lama belok: Untuk sementara tambahkan baris turnBy(360); di akhir setup() dan perhatikan apakah robot berputar penuh. Kalau ia berputar 300 derajat dan bukan 360, atur MS_PER_DEG ke 4.0 × 360 / 300 = 4.8. Karena nilai ini berubah tergantung baterai dan lantai, setel dengan baterai penuh di lantai tempat robot akan berjalan.
- Ambang berhenti: Arahkan robot ke dinding dan ukur seberapa jauh moncongnya dari dinding ketika ia berhenti. Kalau kurang dari 10 cm, naikkan STOP_CM sebesar 5 cm.
- Kecepatan lambat: Kalau SLOW di bawah ambang start motor, robot macet di zona mendekat; dalam hal itu, naikkan SLOW ke 150.
Titik buta HC-SR04: permukaan lunak, dinding miring, dan rintangan tipis
Sensor ultrasonik melihat permukaan yang memantulkan suara dengan baik, tapi tidak semua rintangan mengembalikan suara ke sensor. Pabrikan menyarankan target minimal 0,5 m² yang sedatar mungkin untuk hasil yang baik. Padahal di ruangan sungguhan, robot bertemu gorden, sofa, kaki kursi, dan sudut dinding. Suara memantul dengan sudut yang sama seperti datangnya, mirip bola biliar: sensor yang menghadap dinding secara tegak lurus mendapat pantulan yang kuat, tapi kalau garis pandangnya menyimpang lebih dari sekitar 30–40 derajat dari tegak lurus, suaranya terpantul ke arah lain dan tidak pernah kembali. Dalam kasus itu pulseIn() mengembalikan 0 dan kode mengira jalannya kosong. Inilah alasan paling umum robot menyerempet dinding.
| Rintangan atau permukaan | Kenapa tidak terlihat | Solusi |
|---|---|---|
| Gorden, sofa, bantal, pakaian, bulu hewan peliharaan | Permukaan lunak dan berpori menyerap suara dan pantulannya kembali sangat lemah | Tambahkan sensor IR untuk jarak dekat dan jalankan robot pelan-pelan |
| Mendekati dinding dengan sudut miring | Suara terpantul menjauh dan pantulannya tidak sampai ke sensor | Tambahkan sensor IR yang dimiringkan ke luar di sudut depan dan pindai dengan sudut yang lebih rapat |
| Kaki kursi dan meja, tiang tipis | Permukaan pemantulnya sangat kecil dan pantulannya lemah | Turunkan kecepatan, pakai filter median, tambahkan sensor IR di samping |
| Rintangan rendah di bawah sensor (kabel, ambang pintu, sandal) | Berada di bawah kerucut suara | Tambahkan sensor IR yang menghadap ke bawah atau microswitch di bumper depan |
| Tepi meja, lubang tangga | Sensor ultrasonik menghadap ke depan dan tidak bisa melihat celah di lantai | Deteksi jurang dengan TCRT5000 yang menghadap lantai |
| Benda yang lebih dekat dari 2 cm | Zona mati sensor: pantulan kembali sebelum semburan suaranya selesai | Atur robot agar mundur di 12 cm |
| Sudut ruangan dan koridor sempit | Suara memantul di antara dua dinding dan kembali terlambat, jadi jaraknya tampak lebih jauh | Filter median dan pembacaan dari beberapa sudut |
Menambahkan sensor IR
Sensor ultrasonik dan inframerah (IR) saling menutup kelemahan masing-masing. Sensor rintangan IR seperti FC-51 terdiri dari LED inframerah dan penerima; ketika cahaya pantulannya cukup kuat, komparator LM393 menarik output ke LOW dan LED di board menyala. Jangkauannya bisa diatur dengan trimpot dari sekitar 2 sampai 30 cm, tapi sensor ini tidak mengukur jarak, ia hanya bilang “ada rintangan” atau “tidak ada rintangan”. Kalau kamu memasang dua sensor IR di sudut depan robot, dimiringkan 30–45 derajat ke luar, keduanya menangkap kaki kursi dan dinding miring yang berada di luar kerucut sempit sensor ultrasonik. Di kode lanjutan, robot mengelak sebentar ke kanan ketika IR kiri terpicu dan ke kiri ketika IR kanan terpicu; kalau keduanya terpicu bersamaan, ia berhenti dan memindai seolah-olah ada rintangan di depan.
| Fitur | HC-SR04 (ultrasonik) | FC-51 (rintangan IR) | TCRT5000 (pantulan IR) |
|---|---|---|---|
| Output | Jarak (cm) | Ya / tidak (digital) | Nilai analog dan output digital |
| Jangkauan | 2–400 cm | Sekitar 2–30 cm (bisa diatur) | Sekitar 1–15 mm |
| Sudut deteksi | Sekitar 15° | Sekitar 35° | Sangat sempit |
| Titik lemah | Permukaan lunak, miring, dan tipis | Permukaan hitam dan doff, sinar matahari | Perubahan ketinggian, sinar matahari |
| Melihat dengan baik | Kaca, benda hitam, permukaan datar yang luas | Kain, sudut, rintangan dekat | Warna lantai dan tepi meja |
| Posisi di robot | Mata utama, disapukan oleh servo | Sudut depan | Di bawah bumper depan, menghadap lantai |

Untuk robot yang berkeliling di atas meja, rintangan paling berbahaya justru jurang. Kalau kamu memasang modul TCRT5000 yang menghadap lantai di bawah bumper depan, kamu langsung tahu begitu lantai di bawahnya hilang. Hubungkan output digital modul ke D2, yang masih kosong di Uno; cek dulu di Serial Monitor ke level mana output-nya berubah ketika tidak ada lantai, lalu baca pin ini di bagian paling awal autoStep() dan, kalau lantainya hilang, hentikan motor seketika dan mundurkan robot. Pengecekan ini harus didahulukan sebelum pengukuran jarak; jatuh selalu lebih mahal daripada menabrak.
Beralih ke mode manual lewat Bluetooth
Kadang kamu ingin mengemudikan robot otonom ini dengan tangan: memindahkannya dari satu ruangan ke ruangan lain, membawanya ke depan rintangan untuk menguji reaksinya, atau sekadar bermain. Koneksi HC-05 di kode lanjutan memungkinkan hal itu. Ketika ponsel mengirim huruf A, robot beralih ke mode otomatis; ketika mengirim M, ia beralih ke mode manual. Di mode manual dipakai huruf kendali dari panduan mobil robot (F, B, L, R, S), dengan satu perbedaan: kalau robot melihat rintangan lebih dekat dari 15 cm ketika maju, ia berhenti meskipun ada perintahmu. Pelindung tabrakan ini membuatmu tetap mendapat manfaat dari sensor robot otonom ketika mengemudi manual. Langkah pairing HC-05 dan perintah AT ada di artikel Modul Bluetooth HC-05.
| Huruf | Aksi | Di mode apa? |
|---|---|---|
| A | Beralih ke mode otomatis | Kedua mode |
| M | Beralih ke mode manual, hentikan robot | Kedua mode |
| F / B | Maju / mundur | Manual |
| L / R | Berputar di tempat ke kiri / kanan | Manual |
| S | Berhenti | Manual |
| 0–9 | Level kecepatan (PWM 100–240) | Manual |
- Hubungkan pin TXD HC-05 ke D10, pin RXD-nya ke D11 lewat pembagi 1 kΩ / 2 kΩ, VCC ke 5V, dan GND ke GND.
- Pair HC-05 di pengaturan Bluetooth ponsel Android-mu dengan PIN 1234 (atau 0000 kalau gagal).
- Instal aplikasi remote mobil Bluetooth dari Play Store dan hubungkan ke HC-05. Kalau Arduino tetap terhubung ke USB dan kamu membuka Serial Monitor pada 9600 baud, kode akan mencetak setiap huruf yang datang dari ponsel.
- Kebanyakan aplikasi remote punya tombol tambahan seperti lampu atau klakson, dan masing-masing mengirim hurufnya sendiri. Cari huruf-huruf itu di Serial Monitor lalu ganti 'A' dan 'M' di kode dengannya; kalau kamu lebih suka menentukan tombolnya sendiri, kamu bisa membuat remote sendiri dengan panduan App Inventor Arduino Bluetooth.
- Cabut kabel USB dan nyalakan sakelar; setelah 3 detik robot mulai berjalan dalam mode otomatis. Beralihlah ke mode manual dan kemudikan dari ponselmu.
Membuatnya dengan motor shield L293D

Kalau kamu tidak suka kabel yang semrawut, kamu bisa memakai motor shield L293D (Adafruit Motor Shield V1 dan klonnya) yang langsung ditancapkan ke Arduino Uno sebagai pengganti L298N. Shield ini bisa mengendalikan empat motor DC, punya dua header servo, dan memberi daya servo dari jalur 5 V Arduino. Motornya tidak dihubungkan langsung ke pin Arduino, tapi lewat shift register 74HC595 di board, jadi kamu mengendalikannya dengan library Adafruit Motor Shield (yang untuk V1, bukan V2), yaitu AFMotor, yang diinstal dari Library Manager. Shield ini memakai D3, D4, D5, D6, D7, D8, D11, dan D12 untuk motor serta D9 dan D10 untuk servo; A0–A5, D2, dan D13 tetap kosong. Karena HC-SR04 dan sensor IR sudah ada di A0–A3, kamu hanya perlu mengubah kode motor, pin servo, dan pin HC-05.
| Pengaturan | Dengan L298N | Dengan shield L293D |
|---|---|---|
| Koneksi motor | Terminal OUT1–OUT4 | Terminal M1 (kiri) dan M2 (kanan) |
| Kode motor | digitalWrite dan analogWrite di dalam drive() | AFMotor di dalam drive() |
| SERVO_PIN | 3 | 9 atau 10, tergantung header tempat servo ditancapkan |
| HC-05 | D10, D11 | A4 (RX) dan A5 (TX): SoftwareSerial bt(A4, A5) |
| Arus per kanal | 2 A kontinu | 0,6 A kontinu, puncak 1,2 A |
| Daya motor | Terminal 12V | Terminal EXT_PWR; dengan jumper PWR terpasang, Arduino mendapat daya dari catu yang sama |
1// L293D shield: ENA–IN4 tanımlarını ve setup()'taki pinMode listesinden bu pinleri sil, drive() fonksiyonunu aşağıdakiyle değiştir
2// L293D shield: delete the ENA–IN4 definitions, remove them from the pinMode list in setup() and replace drive() with the one below
3// Ayrıca / Also: SERVO_PIN = 9 ya da / or 10, SoftwareSerial bt(A4, A5)
4#include <AFMotor.h> // Adafruit Motor Shield V1 kütüphanesi / library
5
6AF_DCMotor leftMotor(1); // M1 klemensi / M1 terminal
7AF_DCMotor rightMotor(2); // M2 klemensi / M2 terminal
8
9void drive(int left, int right) { // her biri -255 … 255 / each -255 … 255
10 leftMotor.setSpeed(min(abs(left), 255));
11 rightMotor.setSpeed(min(abs(right), 255));
12 leftMotor.run(left > 0 ? FORWARD : (left < 0 ? BACKWARD : RELEASE));
13 rightMotor.run(right > 0 ? FORWARD : (right < 0 ? BACKWARD : RELEASE));
14}Batas 0,6 A per kanal pada L293D cukup untuk mengemudikan robot 2WD dengan motor TT secara normal, tapi ketika roda mendorong rintangan dan macet, motor bisa menarik lebih dari 1 A dan chip-nya cepat panas. Karena itu algoritma pemindaian yang menghentikan robot sebelum menekan rintangan juga memperpanjang umur shield. Pengaturan jumper shield dan sketch mobil empat motor ada di artikel Motor Shield L293D, dan cara kerja L298N di panduan Mengendalikan Motor DC dengan L298N.
Robot penghindar rintangan dengan ESP32
Ada dua perbedaan penting di ESP32. Pertama, library Servo Arduino tidak bisa dipakai di ESP32, jadi kita membuat sinyal servo langsung dengan LEDC, unit PWM board ini: pada sinyal 50 Hz, pulsa 0,544–2,4 ms sama dengan 0–180 derajat. Karena motor bekerja di 1 kHz dan servo di 50 Hz, kanal motor diatur lebih dulu dan kanal servo setelahnya, sehingga servo mendapat timer sendiri. Kedua, ESP32 sudah punya Bluetooth klasik bawaan, jadi HC-05 tidak diperlukan; robot muncul di ponsel sebagai “BlueGrays-Robot” dan huruf arah serta mode sama dengan versi Uno. Kodenya untuk versi 3.x dari ESP32 Arduino core (ledcAttach dan ledcWrite bekerja dengan nomor pin), dan karena butuh Bluetooth klasik, kode ini tidak bisa dikompilasi untuk ESP32-S3 atau ESP32-C3.
1// ESP32 Arduino çekirdeği 3.x / ESP32 Arduino core 3.x
2#include "BluetoothSerial.h"
3
4const int ENA = 25, IN1 = 27, IN2 = 33; // sol motor / left motor
5const int ENB = 26, IN3 = 32, IN4 = 4; // sağ motor / right motor
6const int SERVO_PIN = 13;
7const int TRIG = 18, ECHO = 19; // ECHO 1 kΩ / 2 kΩ bölücüyle / ECHO via a 1 kΩ / 2 kΩ divider
8const int IR_LEFT = 23, IR_RIGHT = 22; // LOW = engel / LOW = obstacle
9
10const int BACK_CM = 12, STOP_CM = 25, SLOW_CM = 60, GUARD_CM = 15, MAX_CM = 400;
11const int CRUISE = 200, SLOW = 130, TURN = 170;
12const int SERVO_CENTER = 90, SERVO_DIR = 1;
13const float MS_PER_DEG = 4.0; // kalibre et / calibrate
14
15BluetoothSerial bt;
16bool autoMode = true;
17int manualLeft = 0, manualRight = 0;
18unsigned long lastCmd = 0, lastPing = 0;
19
20void drive(int left, int right) { // her biri -255 … 255 / each -255 … 255
21 left = constrain(left, -255, 255);
22 right = constrain(right, -255, 255);
23 digitalWrite(IN1, left > 0); digitalWrite(IN2, left < 0);
24 digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
25 ledcWrite(ENA, abs(left));
26 ledcWrite(ENB, abs(right));
27}
28
29void servoWrite(int angle) { // 0–180° → 544–2400 µs
30 angle = constrain(angle, 0, 180);
31 uint32_t us = map(angle, 0, 180, 544, 2400);
32 ledcWrite(SERVO_PIN, us * 16384 / 20000); // 14 bit, 20 ms periyot / 14-bit, 20 ms period
33}
34
35int pingCm() {
36 digitalWrite(TRIG, LOW); delayMicroseconds(2);
37 digitalWrite(TRIG, HIGH); delayMicroseconds(10);
38 digitalWrite(TRIG, LOW);
39 unsigned long t = pulseIn(ECHO, HIGH, 25000UL);
40 return t == 0 ? MAX_CM : (int)(t / 58);
41}
42
43int distanceCm() { // 3 ölçümün ortancası / median of 3 readings
44 int a = pingCm(); delay(60);
45 int b = pingCm(); delay(60);
46 int c = pingCm();
47 return max(min(a, b), min(max(a, b), c));
48}
49
50bool irBlocked(int pin) { return digitalRead(pin) == LOW; }
51
52void turnBy(int deg) { // + sola, - sağa / + left, - right
53 if (deg > 0) drive(-TURN, TURN);
54 else drive(TURN, -TURN);
55 delay((unsigned long)(abs(deg) * MS_PER_DEG));
56 drive(0, 0);
57 delay(100);
58}
59
60void avoid() {
61 drive(0, 0);
62 delay(120);
63 int front = distanceCm();
64 bool sides = irBlocked(IR_LEFT) || irBlocked(IR_RIGHT);
65 if (front >= STOP_CM && !sides) return; // yanlış alarm / false alarm
66 if (front < BACK_CM || sides) { // geri çekil / back off
67 drive(-TURN, -TURN);
68 delay(350);
69 drive(0, 0);
70 }
71 const int offsets[] = {70, 35, -35, -70};
72 int bestOffset = 0, bestCm = 0;
73 for (int off : offsets) {
74 servoWrite(SERVO_CENTER + SERVO_DIR * off);
75 delay(300);
76 int cm = distanceCm();
77 if (cm > bestCm) { bestCm = cm; bestOffset = off; }
78 }
79 servoWrite(SERVO_CENTER);
80 delay(200);
81 if (bestCm < STOP_CM + 10) { // çıkmaz / dead end
82 drive(-TURN, -TURN);
83 delay(400);
84 turnBy(180);
85 } else {
86 turnBy(bestOffset);
87 }
88}
89
90void setup() {
91 int outs[] = {IN1, IN2, IN3, IN4, TRIG};
92 for (int p : outs) pinMode(p, OUTPUT);
93 pinMode(ECHO, INPUT);
94 pinMode(IR_LEFT, INPUT_PULLUP);
95 pinMode(IR_RIGHT, INPUT_PULLUP);
96 ledcAttach(ENA, 1000, 8); // motor PWM: 1 kHz, 8 bit
97 ledcAttach(ENB, 1000, 8);
98 ledcAttach(SERVO_PIN, 50, 14); // servo: 50 Hz, 14 bit
99 drive(0, 0);
100 servoWrite(SERVO_CENTER);
101 bt.begin("BlueGrays-Robot"); // telefonda görünecek ad / name shown on the phone
102 delay(3000);
103}
104
105void loop() {
106 while (bt.available()) {
107 char c = bt.read();
108 lastCmd = millis();
109 if (c == 'A') autoMode = true; // otomatik / auto
110 else if (c == 'M') { // manuel / manual
111 autoMode = false;
112 manualLeft = manualRight = 0;
113 servoWrite(SERVO_CENTER);
114 }
115 else if (!autoMode) {
116 if (c == 'F') { manualLeft = 200; manualRight = 200; } // ileri / forward
117 else if (c == 'B') { manualLeft = -200; manualRight = -200; } // geri / backward
118 else if (c == 'L') { manualLeft = -200; manualRight = 200; } // sola / left
119 else if (c == 'R') { manualLeft = 200; manualRight = -200; } // sağa / right
120 else if (c == 'S') { manualLeft = 0; manualRight = 0; } // dur / stop
121 }
122 }
123
124 if (millis() - lastPing < 60) return; // 60 ms'de bir / every 60 ms
125 lastPing = millis();
126 int d = pingCm();
127
128 if (!autoMode) {
129 if (millis() - lastCmd > 600) manualLeft = manualRight = 0; // komut yok: dur / no command: stop
130 bool forward = manualLeft > 0 && manualRight > 0;
131 if (forward && d < GUARD_CM) drive(0, 0); // çarpışma koruması / collision guard
132 else drive(manualLeft, manualRight);
133 return;
134 }
135
136 bool l = irBlocked(IR_LEFT), r = irBlocked(IR_RIGHT);
137 if (d < STOP_CM || (l && r)) avoid();
138 else if (l) { drive(TURN, -TURN); delay(150); }
139 else if (r) { drive(-TURN, TURN); delay(150); }
140 else if (d < SLOW_CM) { int s = map(d, STOP_CM, SLOW_CM, SLOW, CRUISE); drive(s, s); }
141 else drive(CRUISE, CRUISE);
142}Robot penghindar rintangan dengan Raspberry Pi Pico (MicroPython)
Di Raspberry Pi Pico, fungsi time_pulse_us() di MicroPython bekerja seperti pulseIn() di Arduino; ia mengembalikan nilai negatif kalau tidak ada pantulan, jadi kita menganggapnya 400 cm, yaitu ruang kosong. Untuk servo kita memakai PWM 50 Hz dan duty_ns(), yang menerima lebar pulsa dalam nanodetik. Servo di GP16 dan pin kecepatan motor di GP15 dan GP10 berada di slice PWM yang berbeda, jadi frekuensinya tidak saling mengganggu. Kali ini kecepatan diberikan dalam persen. Pico tidak punya Bluetooth, jadi kalau kamu ingin mode manual, kamu bisa menghubungkan HC-05 ke UART0 (GP0, GP1) seperti di panduan mobil robot.
1from machine import Pin, PWM, time_pulse_us
2import time
3
4ena = PWM(Pin(15)); ena.freq(1000) # sol motor hızı / left motor speed
5enb = PWM(Pin(10)); enb.freq(1000) # sağ motor hızı / right motor speed
6in1, in2 = Pin(14, Pin.OUT), Pin(13, Pin.OUT)
7in3, in4 = Pin(12, Pin.OUT), Pin(11, Pin.OUT)
8servo = PWM(Pin(16)); servo.freq(50) # servo sinyali, 50 Hz / servo signal, 50 Hz
9trig = Pin(17, Pin.OUT, value=0)
10echo = Pin(18, Pin.IN) # 1 kΩ / 2 kΩ bölücü üzerinden / via a 1 kΩ / 2 kΩ divider
11ir_left = Pin(19, Pin.IN, Pin.PULL_UP) # 0 = engel / 0 = obstacle
12ir_right = Pin(20, Pin.IN, Pin.PULL_UP)
13
14STOP_CM, BACK_CM = 25, 12
15CRUISE, TURN = 75, 65 # hız yüzdesi / speed in percent
16MS_PER_DEG = 4 # kalibre et / calibrate
17SERVO_CENTER = 90 # öne bakmıyorsa düzelt / adjust if not facing ahead
18
19def drive(left, right): # -100 … 100 (%)
20 in1.value(left > 0); in2.value(left < 0)
21 in3.value(right > 0); in4.value(right < 0)
22 ena.duty_u16(int(min(abs(left), 100) * 655))
23 enb.duty_u16(int(min(abs(right), 100) * 655))
24
25def head(offset): # + sol, - sağ / + left, - right
26 angle = max(0, min(180, SERVO_CENTER + offset))
27 servo.duty_ns((544 + angle * 1856 // 180) * 1000) # 0,544–2,4 ms darbe / 0.544–2.4 ms pulse
28
29def ping_cm():
30 trig.value(1); time.sleep_us(10); trig.value(0) # 10 µs tetik / 10 µs trigger
31 t = time_pulse_us(echo, 1, 25000)
32 return 400 if t < 0 else t // 58 # negatif = yankı yok / negative = no echo
33
34def distance_cm(): # 3 ölçümün ortancası / median of 3 readings
35 r = []
36 for _ in range(3):
37 r.append(ping_cm())
38 time.sleep_ms(60)
39 return sorted(r)[1]
40
41def turn_by(deg): # + sola, - sağa / + left, - right
42 if deg > 0:
43 drive(-TURN, TURN)
44 else:
45 drive(TURN, -TURN)
46 time.sleep_ms(int(abs(deg) * MS_PER_DEG))
47 drive(0, 0)
48 time.sleep_ms(100)
49
50def avoid():
51 drive(0, 0)
52 time.sleep_ms(120)
53 front = distance_cm()
54 sides = not ir_left.value() or not ir_right.value()
55 if front >= STOP_CM and not sides:
56 return # yanlış alarm / false alarm
57 if front < BACK_CM or sides: # geri çekil / back off
58 drive(-TURN, -TURN); time.sleep_ms(350); drive(0, 0)
59 best_off, best_cm = 0, 0
60 for off in (70, 35, -35, -70): # tara / scan
61 head(off)
62 time.sleep_ms(300)
63 cm = distance_cm()
64 if cm > best_cm:
65 best_off, best_cm = off, cm
66 head(0)
67 time.sleep_ms(200)
68 if best_cm < STOP_CM + 10: # çıkmaz / dead end
69 drive(-TURN, -TURN); time.sleep_ms(400)
70 turn_by(180)
71 else:
72 turn_by(best_off)
73
74drive(0, 0)
75head(0)
76time.sleep(3) # yere koyman için süre / time to put it down
77while True:
78 d = ping_cm()
79 left_hit, right_hit = not ir_left.value(), not ir_right.value()
80 if d < STOP_CM or (left_hit and right_hit):
81 avoid()
82 elif left_hit:
83 drive(TURN, -TURN); time.sleep_ms(150) # sağa kaç / dodge right
84 elif right_hit:
85 drive(-TURN, TURN); time.sleep_ms(150) # sola kaç / dodge left
86 else:
87 drive(CRUISE, CRUISE)
88 time.sleep_ms(60) # ölçümler arası / between readingsIde proyek dengan robot penghindar rintangan
- Tampilan radar: Kirim sudut dan jarak dari pemindaian lewat port serial dan gambar layar radar hijau di komputermu; detailnya ada di artikel Proyek Radar Arduino.
- Garis plus rintangan: Buat robot memutari kotak yang menghalangi jalannya sambil mengikuti lintasan seperti Robot Pengikut Garis, lalu kembali ke garis; ini tugas lomba yang umum.
- Robot penyusur dinding: Biarkan sensor menoleh 60 derajat ke kanan dan jalankan robot dengan jarak tetap 20 cm dari dinding; ini langkah pertama untuk memecahkan labirin.
- Robot dengan layar: Tampilkan jarak dan mode di layar OLED kecil; debugging jadi jauh lebih mudah.
- Prototipe robot penyedot debu: Rancang robot pembersih yang berkeliling rumah dengan pilihan arah acak, sakelar tabrak, dan sensor jurang.
- Tongkat pintar: Ubah logika pengukuran jarak yang sama menjadi peringatan getar untuk penyandang tunanetra; lihat Tongkat Pintar Arduino.
- Proyek sekolah atau lomba: Presentasikan dengan lintasan rintangan, pengukuran waktu, dan demo mode otomatis dan manual; untuk ide, lihat artikel ide proyek Arduino untuk lomba sains.
Kesalahan umum dan cara memperbaikinya
| Masalah | Kemungkinan penyebab | Solusi |
|---|---|---|
| Robot menabrak dinding tanpa berhenti | Sensor membaca 0 (kabel putus, TRIG dan ECHO tertukar) dan kode menganggapnya ruang kosong | Jalankan sketch uji, coba 10–60 cm dengan tanganmu, cek pin TRIG dan ECHO |
| Robot menyerempet dinding ketika mendekat dengan sudut miring | Suara terpantul dari permukaan miring ke arah lain | Tambahkan sensor IR di sudut depan dan turunkan kecepatan |
| Arduino reset ketika berhenti untuk memindai | Arus servo dan motor membuat jalur 5 V anjlok | Kapasitor 470 µF di servo, sel 18650 yang terisi penuh; kalau perlu, beri daya servo dari sumber 5 V terpisah |
| Robot berhenti dan memindai tanpa alasan | Satu pembacaan salah atau pantulan dari lantai | Naikkan sensor ke 8–12 cm dan miringkan sedikit ke atas; pakai konfirmasi median |
| Robot berbelok ke sisi yang terhalang | Servo terpasang terbalik, kiri dan kanan tertukar | Atur SERVO_DIR ke -1 |
| Beloknya terlalu pendek atau terlalu panjang | MS_PER_DEG belum dikalibrasi atau baterai lemah | Ukur dengan turnBy(360) dan setel ulang dengan baterai penuh |
| Robot terus belok kiri-kanan di sudut ruangan | Kedua sisi mendekati ambang dan keputusannya terus berganti | Naikkan ambang jalan buntu (STOP_CM + 10) atau buat robot mengutamakan arah belok terakhir |
| Kepala sensor berkedut | Catu servo lemah atau interrupt SoftwareSerial | Perpendek kabel servo, tambahkan kapasitor, jangan mengirim perintah Bluetooth lebih sering dari yang perlu |
Karena menggabungkan pembacaan sensor, filter, pengambilan keputusan, dan kendali motor dalam satu proyek, robot penghindar rintangan adalah pintu masuk terbaik ke dunia robotika. Pertama, amati perilaku dasarnya dengan sketch pertama, lalu setel ambangnya sesuai ruanganmu dengan versi lanjutan, dan terakhir perkuat robotmu dengan sensor IR dan Bluetooth. Di aplikasi BlueGrays kamu akan menemukan proyek Robot Penghindar Rintangan, Mobil Kendali Bluetooth dengan L298N, Pengukuran Jarak HC-SR04, dan Sensor Parkir langkah demi langkah, lengkap dengan skema rangkaian dan kode.
Pertanyaan umum
Apa saja yang dibutuhkan untuk membuat robot penghindar rintangan?
Robot penghindar rintangan dasar butuh Arduino Uno, sensor ultrasonik HC-SR04, servo SG90, driver motor L298N atau L293D, kit sasis 2WD dengan dua motor DC bergearbox, dan dua sel 18650. Kamu bisa menambahkan dua sensor rintangan IR untuk melihat sudut dan modul Bluetooth HC-05 untuk mengemudikannya dari ponsel.
Bisakah membuat robot penghindar rintangan tanpa servo?
Bisa. Sensornya menghadap lurus ke depan; ketika robot melihat rintangan, ia berbelok dulu ke satu arah dan mengukur lagi, dan kalau jalannya masih terhalang, ia berbelok ke arah lain. Cara ini lebih murah, tapi robot memutuskan lebih lambat karena harus memutar seluruh badannya di setiap percobaan; servo memungkinkannya menemukan arah yang paling lega sebelum berbelok.
Kenapa HC-SR04 tidak melihat beberapa rintangan?
Sensor ultrasonik mengukur dengan pantulan. Permukaan lunak seperti gorden dan sofa menyerap suara, dinding miring memantulkannya ke arah lain, dan benda tipis seperti kaki kursi memberi pantulan yang sangat lemah. Sensor ini juga tidak bisa melihat rintangan di luar atau di bawah kerucutnya yang sekitar 15 derajat; celah ini bisa kamu tutup dengan sensor IR.
Di jarak berapa robot penghindar rintangan sebaiknya berhenti?
25 cm adalah nilai awal yang baik: jarak yang ditempuh di antara dua pembacaan, jarak pengereman, dan margin untuk berputar di tempat totalnya sekitar 20 cm, ditambah sedikit margin keamanan. Untuk robot yang lebih cepat dan lantai yang licin, naikkan ke 30–35 cm; dengan rintangan yang lebih dekat dari 12 cm, robot sebaiknya mundur dulu.
Mana yang lebih baik untuk robot, L298N atau shield L293D?
L298N bisa memberi 2 A per kanal, jadi lebih tangguh dan pinnya bebas kamu pilih. Shield L293D ditancapkan ke Uno, jadi mengurangi kabel dan bisa mengendalikan empat motor, tapi arus kontinunya 0,6 A per kanal dan memakai banyak pin. Untuk robot 2WD kecil dengan motor TT, keduanya sama-sama bisa.
Bisakah robot penghindar rintangan dikendalikan dari ponsel?
Bisa. Tambahkan modul Bluetooth HC-05 dan kirim huruf dari aplikasi remote di ponsel Android untuk beralih antara mode otomatis dan manual. Memakai sensor ultrasonik sebagai pelindung tabrakan di mode manual mencegahmu menabrakkan robot ke dinding. Dengan ESP32, kamu tidak perlu modul terpisah berkat Bluetooth bawaannya.
Proyek untuk dibuat setelah membaca ini
Lihat semua proyek
Pengukuran Jarak HC-SR04 (Tampilan Serial)
Sensor HC-SR04 bekerja persis seperti kelelawar yang mencari jalan dalam gelap: ia mengirim suara yang tidak bisa kamu dengar, mendengarkan pantulannya, dan mengukur seberapa jauh benda di depannya. A

Robot Penghindar Rintangan
Bagaimana kalau membuat kendaraan pintar yang mencari jalannya sendiri? Robot Penghindar Rintangan terus memindai sekelilingnya berkat sensor ultrasonik di depannya. Ketika menemui rintangan, robot be

Mobil Kendali Bluetooth dengan L298N
Jadikan ponselmu remote dan kendarai mobil robotmu sendiri. Arduino menerima perintah dari aplikasi remote control di ponselmu lewat modul Bluetooth dan memutar roda dengan driver motor; mobil maju, m

Menggunakan Motor Servo
Lengan motor servo kecil berputar ke tiga posisi bergantian: penuh ke awal, tepat ke tengah, dan penuh ke akhir, menunggu dua detik di setiap perhentian. Arduino memberi tahu motor sudut mana yang har

Sensor Parkir dengan HC-SR04
Versi mini sensor parkir mobil: makin dekat sesuatu, makin cepat bunyi bipnya. Sensor jarak mengukur benda di depannya; jika jaraknya lebih dari 20 sentimeter LED hijau tetap menyala, dan begitu lebih

Membaca Pantulan (Kedekatan) dengan TCRT5000
Dengan sensor kecil yang memancarkan cahaya tak terlihat dan mengukur berapa banyak yang terpantul kembali, kamu bisa mendeteksi permukaan di depannya. Makin dekat sebuah benda atau permukaan berwarna

Deteksi Permukaan Hitam dan Putih TCRT5000
Dengan sensor kecil yang menjadi mata robot pengikut garis, kamu bisa tahu apakah lantainya hitam atau putih. TCRT5000 menyinari lantai dengan cahaya tak terlihat dan mengecek berapa banyak yang terpa

Sensor Jarak Ultrasonik HC-SR04 ESP32
Sensor ultrasonik HC-SR04 menghitung jarak dengan mengukur waktu yang dibutuhkan gelombang suara yang dipancarkannya untuk memantul dari benda lalu kembali (Time of Flight). Di proyek ini, kita mengirim pulsa 10 mikrodetik dari ESP32 ke pin TRIG sensor dan membaca durasi pantulan dari pin ECHO dengan pulseIn(). Jarak hasil hitung ditampilkan dalam sentimeter di LCD I2C 16x2. Karena HC-SR04 bekerja di 5V, pembagi tegangan wajib dipasang di pin ECHO.
Artikel lainnya
Aplikasi BlueGrays
Rakit rangkaian ini langkah demi langkah di ponselmu
Skema pengkabelan, kode, dan daftar komponen dalam satu layar. 200+ proyek Arduino, ESP32, dan Pico siap dibuat.
Pindai dengan ponselmu
Arahkan kamera ke kode ini dan toko aplikasi di ponselmu akan terbuka.
atau buka toko aplikasi

