Engelden Kaçan Robot Yapımı: Arduino ve HC-SR04 ile Adım Adım
Engelden kaçan robot yapımı: servo üzerinde HC-SR04 ile tarama, L298N ve L293D bağlantısı, dur-geri çekil-dön algoritması, IR sensör ve Bluetooth kodu.
Engelden kaçan robot, önündeki duvarı, sandalyeyi ya da kutuyu çarpmadan fark edip kendine yeni bir yol bulan, kendi kendine hareket eden bir robot arabadır. En yaygın yapıda bir Arduino Uno, bir HC-SR04 ultrasonik mesafe sensörü, sensörü sağa sola çeviren bir SG90 servo motor, iki redüktörlü DC motor ve bir L298N (ya da L293D) motor sürücü kullanılır. Robot düz ilerler, bir engele yaklaşınca durur, biraz geri çekilir, başını iki yana çevirip ölçüm yapar ve en açık yöne dönerek yoluna devam eder.
Bu rehberde Arduino robot araba yazısında kurduğumuz 2WD arabayı, aynı pin düzenini koruyarak otonom bir robota dönüştürüyoruz. Bağlantı tablolarını, mesafe eşiklerinin nasıl hesaplandığını, üç aşamada büyüyen kodu, sensörün göremediği yüzeyleri ve bu açıkları kızılötesi sensörlerle nasıl kapatacağını, son olarak da telefondan Bluetooth ile manuel moda geçmeyi adım adım anlatıyoruz. Aynı robotu ESP32 ve Raspberry Pi Pico ile sürmek için gereken kodlar da yazının sonunda.

Engelden kaçan robot nasıl çalışır?
Her otonom robot aynı üç adımlık döngüyü saniyede onlarca kez tekrarlar: algıla, karar ver, hareket et. Algılama işini HC-SR04 yapar: kulağın duyamadığı 40 kHz'lik kısa bir ses gönderir ve yankının dönme süresini ölçer; mikrosaniye cinsinden süreyi 58'e bölünce mesafeyi santimetre olarak bulursun. Karar işini Arduino yapar ve ölçülen mesafeyi senin belirlediğin eşiklerle karşılaştırır. Hareket işini ise L298N ile motorlar üstlenir. Sensör bir servonun üzerinde durduğu için robot, gövdesini çevirmeden sola ve sağa "bakabilir"; bu da sabit sensörlü robotlara göre çok daha isabetli dönüş kararları verir. Sensörün çalışma ilkesinin ayrıntıları HC-SR04 Mesafe Sensörü yazısında.
| Parça | Görevi | Not |
|---|---|---|
| Arduino Uno (ya da Nano) | Beyin: ölçer, karar verir, motorlara komut gönderir | ESP32 ve Pico da kullanılabilir |
| HC-SR04 | Göz: öndeki engelin uzaklığını ölçer | 5 V ile çalışır, 2–400 cm |
| SG90 servo | Boyun: sensörü sola ve sağa çevirir | Sensör plastik bir aparatla servo başlığına takılır |
| L298N ya da L293D shield | Kas: motorlara yön ve hız verir | Arduino pini motor akımını veremez |
| 2 redüktörlü TT motor ve sarhoş teker | Diferansiyel sürüş | Dönüş, iki tekerleğin zıt yönde dönmesiyle yapılır |
| 2 adet 18650 pil (7,4 V) | Enerji | 9 V kare pil yetmez |
| 2 adet IR engel sensörü (isteğe bağlı) | Köşe ve yan engelleri yakalar | FC-51 gibi LM393'lü modüller |
| HC-05 (isteğe bağlı) | Telefondan manuel kontrol | Yalnızca Android ile çalışır |




Güç beslemesi: servo robotu resetlemesin
Engelden kaçan robotta motorlara bir de servo eklendiği için güç dağıtımı, sıradan bir robot arabadan daha önemlidir. SG90 dururken yaklaşık 10 mA çeker; dönmeye başladığı anda akımı 100–250 mA'e çıkar, zorlandığında ise yarım ampere yaklaşır. Bu ani akım, motorların kalkış akımıyla aynı ana denk gelirse Arduino'nun 5 V hattı bir anlığına çöker ve kart yeniden başlar. Çözüm basit: motorlar pilden L298N üzerinden, Arduino ise pilden VIN üzerinden beslenir; servo, HC-SR04, IR sensörler ve HC-05 Arduino'nun 5V pinini paylaşır ve servonun besleme uçlarının yanına 470 µF'lık bir kondansatör konur. Servo dönerken bile 5 V hattındaki toplam yük yarım amperin altında kalır; bu yük kısa süreli olduğu için Uno'nun regülatörü onu taşır. Pil ömrünü kendi değerlerinle hesaplamak için Pil ömrü aracını kullanabilirsin.
| Bölüm | Nereden beslenir? | Tipik akım |
|---|---|---|
| 2 TT motor | L298N 12V klemensi ← 2 adet 18650 (7,4 V) | Sürüşte 0,3–0,6 A, kalkışta 2 A'e kadar |
| Arduino Uno | VIN ← pilin artısı (anahtardan sonra) | Yaklaşık 50 mA |
| SG90 servo | Arduino 5V + 470 µF kondansatör | Dururken ~10 mA, dönerken 100–250 mA |
| HC-SR04 | Arduino 5V | Yaklaşık 15 mA |
| 2 IR sensör | Arduino 5V | Her biri 20–40 mA |
| HC-05 | Arduino 5V | Eşleşme ararken 30–40 mA, bağlıyken yaklaşık 10 mA |
Bağlantı şeması: Arduino Uno, ESP32 ve Pico
Motor pinleri robot araba rehberindekiyle aynıdır; böylece hazır arabanı sökmeden, yalnızca sensör kafasını ekleyerek bu projeye geçebilirsin. Hız pinlerinin 5 ve 6'da olması bilinçli bir seçimdir: Uno'da Servo kütüphanesi Timer1'i kullandığı için 9 ve 10 numaralı pinlerdeki PWM'i devre dışı bırakır; motor hızları bu pinlerde olsaydı servo takıldığı anda hız kontrolü bozulurdu. HC-SR04 ve IR sensörler A0–A3'e bağlanır. Uno'nun analog pinleri gerektiğinde 14–19 numaralı dijital pinler gibi de çalışır ve bu seçim aynı kodu L293D shield ile kullanmayı kolaylaştırır, çünkü shield bu pinlere dokunmaz. Kartının pin düzenini Pinout aracında görebilirsin.
| Bağlantı | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| L298N ENA (sol motor hızı) | D5 | GPIO 25 | GP15 |
| L298N IN1, IN2 | D7, D8 | GPIO 27, 33 | GP14, GP13 |
| L298N ENB (sağ motor hızı) | D6 | GPIO 26 | GP10 |
| L298N IN3, IN4 | D9, D4 | GPIO 32, 4 | GP12, GP11 |
| Servo sinyal (turuncu) | D3 | GPIO 13 | GP16 |
| Servo + (kırmızı), − (kahverengi) | 5V, GND | L298N 5V, GND | L298N 5V, GND |
| HC-SR04 TRIG | A0 | GPIO 18 | GP17 |
| HC-SR04 ECHO | A1 (doğrudan) | GPIO 19, 1 kΩ / 2 kΩ bölücüyle | GP18, 1 kΩ / 2 kΩ bölücüyle |
| HC-SR04 VCC | 5V | L298N 5V | L298N 5V |
| IR sol OUT, IR sağ OUT | A2, A3 | GPIO 23, 22 | GP19, GP20 |
| IR sensör VCC | 5V | 3V3 | 3V3 |
| HC-05 TXD, RXD | D10, D11 (RXD bölücüyle) | Gerekmez (dahili Bluetooth) | GP1, GP0 (UART0) |
| Kartın beslemesi | VIN ← pil (anahtardan sonra) | 5V (VIN) ← L298N 5V | VSYS ← L298N 5V |
Sensör kafasını monte et ve test et

- Servoyu başlığı takılı değilken bağla ve aşağıdaki test kodunu yükle. Kod her taramanın sonunda servoyu 90 dereceye getirip 2 saniye bekler; bu sırada USB kablosunu çıkar, servo olduğu yerde kalır. Başlığı, sensör tam öne bakacak şekilde mile tak; böylece 90 derece "tam ileri" anlamına gelir.
- HC-SR04'ü plastik aparatla ya da sıcak silikonla başlığa sabitle. Sensör kabloları servo dönerken gerilmeyecek kadar uzun olmalı; 140 derecelik tarama sırasında kablonun şasiye takılması sık görülen bir arızadır.
- Sensörü yerden 8–12 cm yükseğe ve gövdenin en ön noktasına yakın yerleştir. Çok alçakta durursa yerden ve halının dokusundan yankı alır; çok yüksekte durursa alçak engelleri göremez.
- Sensörü 3–5 derece yukarı eğik monte et. Tam yatay duran ve alçakta kalan bir sensör, özellikle pürüzlü zeminlerde yerden dönen yankıyı engel sanabilir.
- Seri Monitör'ü 9600 baud ile aç. Elini sensörün soluna tuttuğunda 125 ve 160 derecelik satırlarda küçük değerler görüyorsan sol taraf büyük açılardır; tersi oluyorsa gelişmiş koddaki SERVO_DIR değerini -1 yap, ilk kodda ise LEFT_ANGLE ile RIGHT_ANGLE değerlerinin yerini değiştir.
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}Her satırda bir açı ve o yöndeki mesafe görünür. Sensörün önünde yaklaşık 4 metre içinde hiçbir şey yoksa 0 cm okursun: pulseIn() 25 ms içinde yankı gelmezse 0 döndürür. Ana kodda 0'ı "önü açık" sayacağız, ama kablosu çıkmış ya da TRIG ile ECHO'su ters bağlanmış bir sensör de çoğu zaman 0 okur. Bu yüzden robotu yere koymadan önce elini 10, 30 ve 60 cm'ye tutup değerlerin gerçekten değiştiğini gör; test edilmeden çalıştırılan robot duvara hiç yavaşlamadan gider.
Karar algoritması: dur, geri çekil, en açık yöne dön
Robotun davranışını mesafeye göre bölgelere ayırmak, kodu hem basit hem güvenilir yapar. Önünde engel yokken tam hızla ilerler, engel yaklaştıkça yavaşlar, durma eşiğine geldiğinde durur ve tarama yapar. Tarama sırasında sensör 70 ve 35 derece sola, 35 ve 70 derece sağa bakar; her yönde üç ölçüm alınır ve ortancası kullanılır. Robot en uzun mesafeyi veren yöne, o açı kadar döner. Hiçbir yön açık değilse, örneğin bir köşeye girdiyse, biraz geri gelip 180 derece döner.
| Ölçülen mesafe | Bölge | Robotun yaptığı |
|---|---|---|
| 60 cm'den uzak (ya da yankı yok) | Serbest | Tam hızla ileri (PWM 200) |
| 25–60 cm | Yaklaşma | Mesafeyle orantılı yavaşlar (PWM 200'den 130'a) |
| 12–25 cm | Engel | Durur, ölçümü doğrular, iki yana tarar, en açık yöne döner |
| 12 cm'den yakın | Çok yakın | Önce 350 ms geri çekilir, sonra tarar |
| Bütün yönler 35 cm'den yakın | Çıkmaz | Geri gelir ve 180 derece döner |
Bu eşikler rastgele seçilmedi. Durma mesafesi üç payın toplamıdır: tepki payı (iki ölçüm arasında alınan yol), fren payı (motorlar kesildikten sonra robotun kayması) ve dönüş payı (robot yerinde dönerken burnunun engele değmemesi). 6 V alan TT motorlu bir araba yaklaşık 0,5–0,7 m/s hızla gider ve 60 ms'lik ölçüm aralığında 3–4 cm yol alır. Fren payı yaklaşık 5 cm, 15 cm genişliğinde yerinde dönen bir gövde için dönüş payı da 10 cm civarındadır. Toplam yaklaşık 18–20 cm eder; üstüne birkaç santimetrelik güvenlik payı eklenince STOP_CM = 25 iyi bir başlangıç olur. Robotun daha hızlıysa ya da zemin kayganse eşiği 30–35 cm'ye çıkar. Dar koridorlarda ise çok büyük bir eşik, robotun sürekli durup taramasına yol açar; son ayarı kendi pistinde yap.
Adım adım kod 1: ilk engelden kaçan robot
İlk sürüm algoritmanın iskeletidir: ileri git, 25 cm'de dur, geri çekil, sola ve sağa bak, daha açık tarafa dön. Motor fonksiyonu drive(sol, sağ) robot araba rehberindekinin aynısıdır ve -255 ile 255 arasında değer alır; artı ileri, eksi geri demektir. Kodu yükledikten sonra önce arabayı tekerlekleri boşta kalacak şekilde bir kutunun üstüne koy ve elini sensöre yaklaştırarak durma ve dönme davranışını izle; her şey doğruysa robotu yere indir.
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}Bu kod işini görür ama birkaç zayıflığı vardır: tek bir hatalı ölçüm robotu boşuna durdurur, robot engele hep aynı hızla yaklaşır, yalnızca iki yöne bakar ve dönüş süreleri açıya göre ayarlanmaz. Ayrıca delay() ile beklediği için tarama sırasında hiçbir şeye tepki veremez. Bekleme mantığının ayrıntıları millis() ve delay() yazısında; sonraki sürüm bu sorunların çoğunu çözüyor.
Adım adım kod 2: filtre, kademeli yavaşlama, IR ve Bluetooth
Gelişmiş sürüm aynı bağlantılarla çalışır; IR sensörleri ve HC-05'i henüz takmadıysan da sorun olmaz. IR girişleri INPUT_PULLUP ile tanımlandığı için takılı olmayan bir sensör "engel yok" (HIGH) okunur; HC-05 yoksa robot zaten otomatik modda başlar. Kodun her parçasının ne yaptığını aşağıdaki tabloda bulabilirsin.
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}| Fonksiyon ya da ayar | Ne yapar? |
|---|---|
| pingCm() | Tek ölçüm yapar; 25 ms içinde yankı gelmezse 400 cm (açık alan) döndürür |
| distanceCm() | 60 ms arayla 3 ölçüm alır ve ortancasını verir; tek bir sıçrayan değeri eler |
| autoStep() | 60 ms'de bir ölçer; mesafeye ve IR'lere göre ilerler, yavaşlar, kaçar ya da avoid() çağırır |
| avoid() | Durur, ölçümü doğrular, gerekirse geri çekilir, 4 yöne bakar ve en açık yöne döner |
| turnBy(derece) | Robotu verilen açı kadar yerinde döndürür; süre MS_PER_DEG ile hesaplanır |
| manualStep() | Telefondan gelen yönü uygular; ileri giderken 15 cm'de durur, 600 ms komut gelmezse durur |
| SERVO_CENTER, SERVO_DIR | Sensörün tam öne baktığı açı ve sol tarafın yönü |
| STOP_CM, SLOW_CM, BACK_CM | Durma, yavaşlama ve geri çekilme eşikleri |
Ortanca (medyan) filtre, engelden kaçan robot için ortalamadan daha iyidir: 24, 26 ve 400 cm gibi üç ölçümün ortalaması 150 cm çıkar ve robotu yanıltır, ortanca ise 26 cm'yi seçer. Konuyu daha derin incelemek istersen sensör verisi filtreleme yazısına bakabilirsin. Otomatik ve manuel mod ayrımı da aslında küçük bir durum makinesidir; bu yaklaşımı Arduino durum makinesi rehberinde ayrıntılı anlatıyoruz. Kodu yükledikten sonra robotu kendi odana göre şu sırayla ayarla:
- Servo merkezi: Robot düz bir duvara dik dururken sensör tam karşıya bakmıyorsa SERVO_CENTER değerini 85 ya da 95 gibi küçük adımlarla değiştir.
- Dönüş süresi: setup()'ın sonuna geçici olarak turnBy(360); satırını ekle ve robotun tam bir tur atıp atmadığını izle. 360 yerine 300 derece döndüyse MS_PER_DEG değerini 4,0 × 360 / 300 = 4,8 yap. Bu değer pile ve zemine göre değiştiği için ayarı dolu pille, robotun gezeceği zeminde yap.
- Durma eşiği: Robotu duvara doğru gönder ve durduğu yerde burnunun duvara uzaklığını ölç. 10 cm'den az kalıyorsa STOP_CM değerini 5 cm artır.
- Yavaş hız: SLOW değeri motorların kalkış eşiğinin altında kalırsa robot yaklaşma bölgesinde durup kalır; bu durumda SLOW değerini 150'ye çıkar.
HC-SR04'ün kör noktaları: yumuşak yüzeyler, eğik duvarlar ve ince engeller
Ultrasonik sensör, sesi geri yansıtan yüzeyleri iyi görür; ama her engel sesi sensöre geri göndermez. Üretici, iyi sonuç için hedefin en az 0,5 m² büyüklüğünde ve olabildiğince düz olmasını önerir. Gerçek bir odada ise robotun önüne perde, koltuk, sandalye ayağı ve duvar köşeleri çıkar. Ses, bilardo topu gibi geldiği açıyla yansır: duvara dik bakan sensör güçlü bir yankı alır, ama bakış açısı dikten yaklaşık 30–40 dereceden fazla saparsa ses başka yöne seker ve hiç geri dönmez. Bu durumda pulseIn() 0 döndürür ve kod önü açık sanır. Robotların duvara sürtünerek çarpmasının en sık sebebi budur.
| Engel ya da yüzey | Neden görülmez? | Çözüm |
|---|---|---|
| Perde, koltuk, minder, kıyafet, hayvan tüyü | Yumuşak ve gözenekli yüzey sesi emer, yankı çok zayıf döner | Yakın mesafe için IR sensör ekle, robotu yavaş sür |
| Duvara eğik yaklaşmak | Ses başka yöne yansır, yankı sensöre dönmez | Ön köşelere dışa açılı IR sensör ekle, tarama açılarını sık tut |
| Sandalye ve masa ayağı, ince direk | Yansıtan yüzey çok küçük, yankı zayıf | Hızı düşür, ortanca filtre kullan, yanlara IR ekle |
| Sensörün altında kalan alçak engel (kablo, eşik, terlik) | Ses konisinin altında kalır | Ön tampona aşağı bakan bir IR sensör ya da mikro anahtar ekle |
| Masa kenarı, merdiven boşluğu | Ultrasonik sensör öne bakar, zemindeki boşluğu görmez | Zemine bakan TCRT5000 ile boşluk algılama |
| 2 cm'den yakın nesneler | Sensörün ölü bölgesi: yankı, ses gönderimi bitmeden döner | Robotu 12 cm'de geri çekilecek şekilde ayarla |
| Köşeler ve dar koridorlar | Ses iki duvar arasında sekip geç döner, mesafe uzun görünür | Ortanca filtre ve birden fazla açıdan ölçüm |
IR sensörlerle güçlendirme
Ultrasonik ve kızılötesi (IR) sensörler birbirinin eksiğini kapatır. FC-51 gibi IR engel sensörleri bir kızılötesi LED ile bir alıcıdan oluşur; LM393 karşılaştırıcısı yansıyan ışık yeterince güçlüyse çıkışı LOW yapar ve kart üzerindeki LED yanar. Menzili trimpotla yaklaşık 2–30 cm arasında ayarlanır ama mesafe ölçmez, yalnızca "engel var" ya da "yok" der. İki IR sensörü robotun ön köşelerine, dışa doğru 30–45 derece açıyla yerleştirirsen ultrasonik sensörün dar konisinin dışında kalan sandalye ayaklarını ve eğik duvarları yakalarsın. Gelişmiş kodda sol IR tetiklenince robot kısa bir an sağa, sağ IR tetiklenince sola kaçar; ikisi birden tetiklenirse önünde engel varmış gibi durup tarar.
| Özellik | HC-SR04 (ultrasonik) | FC-51 (IR engel) | TCRT5000 (IR yansıma) |
|---|---|---|---|
| Çıktı | Mesafe (cm) | Var / yok (dijital) | Analog değer ve dijital çıkış |
| Menzil | 2–400 cm | Yaklaşık 2–30 cm (ayarlanabilir) | Yaklaşık 1–15 mm |
| Algılama açısı | Yaklaşık 15° | Yaklaşık 35° | Çok dar |
| Zayıf olduğu durum | Yumuşak, eğik ve ince yüzeyler | Siyah ve mat yüzeyler, güneş ışığı | Yükseklik değişimi, güneş ışığı |
| İyi gördüğü | Cam, siyah nesneler, büyük düz yüzeyler | Kumaş, köşeler, yakın engeller | Zemin rengi ve masa kenarı |
| Robottaki yeri | Servoyla dönen ana göz | Ön köşeler | Ön tamponun altı, zemine bakar |

Masa üstünde gezen robotlar için en tehlikeli engel aslında boşluktur. Ön tamponun altına zemine bakan bir TCRT5000 modülü takarsan zemin altından kaybolduğu anda bunu fark edersin. Modülün dijital çıkışını Uno'da boş kalan D2'ye bağla; zemin görünmediğinde çıkışın hangi seviyeye geçtiğini önce Seri Monitör'de gör, sonra autoStep() fonksiyonunun en başında bu pini oku ve zemin kaybolduysa motorları hemen durdurup robotu geri çek. Bu kontrol mesafe ölçümünden önce yapılmalıdır; düşmek, çarpmaktan her zaman daha pahalıdır.
Bluetooth ile manuel moda geçiş
Otonom robotu bazen elle sürmek istersin: onu bir odadan diğerine götürmek, bir engelin önüne getirip tepkisini denemek ya da sadece oynamak için. Gelişmiş koddaki HC-05 bağlantısı bunu sağlar. Telefon A harfini gönderince robot otomatik moda, M harfini gönderince manuel moda geçer. Manuel modda robot araba rehberindeki kumanda harfleri (F, B, L, R, S) kullanılır, ama bir farkla: robot ileri giderken önünde 15 cm'den yakın bir engel görürse senin komutuna rağmen durur. Bu çarpışma koruması, otonom robotun sensörlerinden manuel sürüşte de yararlanmanı sağlar. HC-05'in eşleştirme adımları ve AT komutları HC-05 Bluetooth Modülü yazısında.
| Harf | Görevi | Hangi modda? |
|---|---|---|
| A | Otomatik moda geç | Her iki modda |
| M | Manuel moda geç, robotu durdur | Her iki modda |
| F / B | İleri / geri | Manuel |
| L / R | Yerinde sola / sağa dön | Manuel |
| S | Dur | Manuel |
| 0–9 | Hız kademesi (PWM 100–240) | Manuel |
- HC-05'in TXD pinini D10'a, RXD pinini 1 kΩ / 2 kΩ bölücü üzerinden D11'e, VCC'yi 5V'a, GND'yi GND'ye bağla.
- Android telefonunun Bluetooth ayarlarında HC-05'i 1234 (olmazsa 0000) şifresiyle eşleştir.
- Play Store'dan bir Bluetooth araba kumandası uygulaması kur ve HC-05'e bağlan. Arduino'yu USB'ye bağlı tutup Seri Monitör'ü 9600 baud ile açarsan kod, telefondan gelen her harfi ekrana yazar.
- Çoğu kumanda uygulamasında far ya da korna gibi fazladan tuşlar bulunur ve her biri ayrı bir harf gönderir. Bu harfleri Seri Monitör'de gör ve koddaki 'A' ile 'M' yerine yaz; tuşlarını kendin belirlemek istersen App Inventor ile Arduino Bluetooth rehberiyle kendi kumandanı yapabilirsin.
- USB kablosunu çıkar ve anahtarı aç; robot 3 saniye sonra otomatik modda yola çıkar. Manuel moda geçip telefondan sür.
L293D motor shield ile kurulum

Kablo karmaşasını sevmiyorsan L298N yerine Arduino Uno'nun üstüne doğrudan takılan L293D motor shield'i (Adafruit Motor Shield V1 ve klonları) kullanabilirsin. Shield dört DC motor sürebilir, iki servo başlığı vardır ve servoları Arduino'nun 5 V hattından besler. Motorlar Arduino pinlerine doğrudan değil, kart üzerindeki 74HC595 kaydırmalı yazmacı üzerinden bağlıdır; bu yüzden onları Kütüphane Yöneticisi'nden kuracağın Adafruit Motor Shield library (V1 için olan, V2 değil) ile, yani AFMotor ile sürersin. Shield D3, D4, D5, D6, D7, D8, D11 ve D12'yi motorlar, D9 ve D10'u servolar için kullanır; A0–A5, D2 ve D13 boş kalır. HC-SR04 ve IR sensörler zaten A0–A3'te olduğu için yalnızca motor kodunu, servo pinini ve HC-05 pinlerini değiştirmen yeter.
| Ayar | L298N ile | L293D shield ile |
|---|---|---|
| Motor bağlantısı | OUT1–OUT4 klemensleri | M1 (sol) ve M2 (sağ) klemensleri |
| Motor kodu | drive() içinde digitalWrite ve analogWrite | drive() içinde AFMotor |
| SERVO_PIN | 3 | Servoyu taktığın başlığa göre 9 ya da 10 |
| HC-05 | D10, D11 | A4 (RX) ve A5 (TX): SoftwareSerial bt(A4, A5) |
| Kanal başına akım | 2 A sürekli | 0,6 A sürekli, 1,2 A anlık |
| Motor beslemesi | 12V klemensi | EXT_PWR klemensi; PWR jumper'ı takılıysa Arduino da aynı kaynaktan beslenir |
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}L293D'nin kanal başına 0,6 A'lik sınırı, TT motorlu bir 2WD robotun normal sürüşü için yeterlidir; ama tekerlek bir engele dayanıp sıkıştığında motor 1 A'in üzerinde akım çekebilir ve entegre hızla ısınır. Tarama algoritmasının robotu engele dayamadan durdurması bu yüzden shield'in de ömrünü uzatır. Shield'in jumper ayarları ve dört motorlu araba kodu L293D Motor Shield yazısında, L298N'in iç yapısı ise L298N ile DC Motor Kontrolü rehberinde.
ESP32 ile engelden kaçan robot
ESP32'de iki önemli fark var. Birincisi, Arduino'nun Servo kütüphanesi ESP32'de çalışmaz; servo sinyalini kartın PWM birimi olan LEDC ile doğrudan üretiyoruz: 50 Hz'lik sinyalde 0,544–2,4 ms'lik darbe 0–180 dereceye karşılık gelir. Motorlar 1 kHz'te, servo 50 Hz'te çalıştığı için önce motor kanalları, sonra servo kanalı açılır; böylece servo kendi zamanlayıcısını kullanır. İkincisi, ESP32'nin içinde klasik Bluetooth olduğu için HC-05'e gerek kalmaz; robot telefonda "BlueGrays-Robot" adıyla görünür ve yön ile mod harfleri Uno sürümüyle aynıdır. Kod, ESP32 Arduino çekirdeğinin 3.x sürümü içindir (ledcAttach ve ledcWrite pin numarasıyla çalışır) ve klasik Bluetooth gerektirdiği için ESP32-S3 ile ESP32-C3'te derlenmez.
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}Raspberry Pi Pico (MicroPython) ile engelden kaçan robot
Raspberry Pi Pico'da MicroPython'un time_pulse_us() fonksiyonu Arduino'daki pulseIn() gibi çalışır; yankı gelmezse negatif bir değer döndürdüğü için bunu 400 cm, yani açık alan sayıyoruz. Servo için 50 Hz'lik PWM ve darbe genişliğini nanosaniye olarak alan duty_ns() kullanılır. GP16'daki servo ile GP15 ve GP10'daki motor hız pinleri farklı PWM dilimlerinde olduğu için birbirinin frekansını bozmaz. Hızlar bu kez yüzde olarak verilir. Pico'da Bluetooth olmadığından manuel mod istersen HC-05'i robot araba rehberindeki gibi UART0'a (GP0, GP1) bağlayabilirsin.
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 readingsEngelden kaçan robot ile proje fikirleri
- Radar ekranı: Taramada ölçtüğün açı ve mesafeleri seri porttan gönderip bilgisayarda yeşil bir radar ekranı çiz; ayrıntılar Arduino Radar Projesi yazısında.
- Çizgi ve engel: Robot çizgi izleyen robot gibi pistte ilerlerken önüne çıkan kutunun etrafından dolaşıp çizgiye geri dönsün; yarışmalarda sık görülen bir görevdir.
- Duvar takip eden robot: Sensörü sürekli 60 derece sağa çevirip duvara sabit 20 cm uzaklıkta ilerle; labirent çözmenin ilk adımıdır.
- Ekranlı robot: Mesafeyi ve modu küçük bir OLED ekranda göster; hata ayıklama çok kolaylaşır.
- Süpürge robotu prototipi: Rastgele yön seçimi, çarpma anahtarları ve boşluk sensörüyle evde dolaşan bir temizlik robotu taslağı yap.
- Akıllı baston: Aynı mesafe ölçme mantığını görme engelliler için titreşimli bir uyarıya dönüştür; bkz. Arduino Akıllı Baston.
- Okul ve yarışma projesi: Engel parkuru, süre tutma ve otomatik ya da manuel mod gösterisiyle sun; fikirler için TÜBİTAK Arduino proje fikirleri yazısına göz at.
Sık yapılan hatalar ve çözümleri
| Sorun | Olası neden | Çözüm |
|---|---|---|
| Robot duvara hiç durmadan çarpıyor | Sensör 0 okuyor (kablo kopuk, TRIG ve ECHO ters) ve kod bunu açık alan sayıyor | Test kodunu çalıştır, elinle 10–60 cm arasını dene, TRIG ve ECHO pinlerini kontrol et |
| Duvara eğik yaklaşınca sürtüyor | Ses eğik yüzeyden başka yöne yansıyor | Ön köşelere IR sensör ekle, hızı düşür |
| Durup tarama yaparken Arduino resetleniyor | Servo ve motor akımı 5 V hattını çökertiyor | Servoya 470 µF kondansatör, dolu 18650 piller; gerekirse servoyu ayrı 5 V kaynaktan besle |
| Robot sebepsiz yere durup tarıyor | Tek bir hatalı ölçüm ya da zeminden gelen yankı | Sensörü 8–12 cm yükseğe al ve biraz yukarı eğ; ortanca doğrulamayı kullan |
| Robot kapalı tarafa dönüyor | Servo montajı ters, sol ve sağ karışmış | SERVO_DIR değerini -1 yap |
| Dönüşler çok kısa ya da çok uzun | MS_PER_DEG kalibre edilmemiş ya da pil zayıf | turnBy(360) ile ölç, dolu pille yeniden ayarla |
| Köşede sağa sola dönüp duruyor | İki yan da eşiğe yakın, karar sürekli değişiyor | Çıkmaz eşiğini (STOP_CM + 10) büyüt ya da son dönülen yönü tercih ettir |
| Sensör kafası seğiriyor | Servo beslemesi zayıf ya da SoftwareSerial kesmeleri | Servo kablosunu kısalt, kondansatör ekle, gereksiz sık Bluetooth komutundan kaçın |
Engelden kaçan robot; sensör okuma, filtreleme, karar verme ve motor kontrolünü tek projede birleştirdiği için robotiğe geçişin en iyi adımıdır. Önce ilk kodla temel davranışı gör, sonra gelişmiş sürümle eşikleri kendi odana göre ayarla, en son IR sensörler ve Bluetooth ile robotunu güçlendir. BlueGrays uygulamasında engelden kaçan robot, L298N ile Bluetooth kontrollü araba, HC-SR04 ile mesafe ölçme ve park sensörü projelerini devre şemaları ve kodlarıyla adım adım bulabilirsin.
Sıkça sorulan sorular
Engelden kaçan robot için hangi malzemeler gerekir?
Temel bir engelden kaçan robot için Arduino Uno, HC-SR04 ultrasonik sensör, SG90 servo, L298N ya da L293D motor sürücü, iki redüktörlü DC motorlu 2WD şasi kiti ve iki adet 18650 pil yeterlidir. Köşeleri görmek için iki IR engel sensörü, telefondan sürmek için de bir HC-05 Bluetooth modülü ekleyebilirsin.
Engelden kaçan robot servo olmadan yapılabilir mi?
Evet. Sensör sabit olarak öne bakar; robot engel görünce önce bir yöne döner ve yeniden ölçer, yol hâlâ kapalıysa diğer yöne döner. Bu yöntem daha ucuzdur ama robot her denemede gövdesini çevirdiği için daha yavaş karar verir; servo ise dönmeden önce en açık yönü bulmayı sağlar.
HC-SR04 neden bazı engelleri görmüyor?
Ultrasonik sensör yankıya göre ölçer. Perde ve koltuk gibi yumuşak yüzeyler sesi emer, eğik duvarlar sesi başka yöne yansıtır, sandalye ayağı gibi ince nesneler ise çok zayıf yankı verir. Sensör, yaklaşık 15 derecelik konisinin dışında ya da altında kalan engelleri de göremez; bu açıkları IR sensörlerle kapatabilirsin.
Engelden kaçan robot kaç cm'de durmalı?
Başlangıç için 25 cm iyi bir değerdir: iki ölçüm arasında alınan yol, fren mesafesi ve yerinde dönmek için gereken pay toplanınca yaklaşık 20 cm eder, üstüne de küçük bir güvenlik payı eklenir. Hızlı robotlarda ve kaygan zeminde eşiği 30–35 cm'ye çıkar; 12 cm'den yakın bir engelde ise önce geri çekilmek gerekir.
Robot için L298N mi, L293D shield mi daha iyi?
L298N kanal başına 2 A verebildiği için daha dayanıklıdır ve pinleri istediğin gibi seçmeni sağlar. L293D shield Uno'nun üstüne takıldığı için kablolamayı azaltır ve dört motor sürebilir, ama kanal başına sürekli akımı 0,6 A'dir ve birçok pini kullanır. TT motorlu küçük bir 2WD robot için ikisi de iş görür.
Engelden kaçan robot telefondan kontrol edilebilir mi?
Evet. Robota bir HC-05 Bluetooth modülü ekleyip Android telefondaki bir kumanda uygulamasından harf göndererek otomatik ve manuel mod arasında geçebilirsin. Manuel modda ultrasonik sensörü çarpışma koruması olarak kullanmak robotun duvara sürülmesini engeller. ESP32 kullanırsan dahili Bluetooth sayesinde ayrı bir modüle gerek kalmaz.
Bu yazıdan sonra yapabileceğin projeler
Tüm projeleri gör
HC-SR04 Mesafe Ölçme (Serial Ekran)
Yarasalar karanlıkta yollarını nasıl buluyorsa HC-SR04 sensörü de öyle çalışır: duyamadığın bir ses gönderir, yankısını dinler ve önündeki cismin ne kadar uzakta olduğunu ölçer. Arduino bu mesafeyi sa

Engelden Kaçan Robot
Kendi yolunu bulan akıllı bir araç yapmaya ne dersin? Engelden Kaçan Robot, önündeki ultrasonik sensör sayesinde çevresini sürekli tarar. Bir engelle karşılaştığında durur, servo motoruyla sağına ve s

L298N ile Bluetooth Kontrollü Araba
Telefonunu kumandaya çevirip kendi robot arabanı sür. Arduino, Bluetooth modülü üzerinden telefondaki bir kumanda uygulamasından gelen komutları alır ve motor sürücüyle tekerlekleri döndürür; araba il

Servo Motor Kullanım
Küçük bir servo motorun kolu sırayla üç konuma döner: en başa, tam ortaya ve en sona, her durakta iki saniye bekleyerek. Arduino motora hangi açıda durması gerektiğini söyler, motor da oraya gidip ora

HC-SR04 ile Park Sensörü
Arabalardaki park sensörünün küçük bir benzeri: bir şey yaklaştıkça bip sesleri hızlanır. Mesafe sensörü önündeki nesneyi ölçer; 20 santimetreden uzaktaysa yeşil LED yanar, daha yakına gelince kırmızı

TCRT5000 ile Yansıma (Yakınlık) Okuma
Görünmez ışık yollayıp yansımasını ölçen küçük bir sensörle önündeki yüzeyi algılarsın. Sensör bir cisme ya da açık renkli bir yüzeye yaklaştıkça daha çok ışık geri döner; Arduino bu değeri her yarım

TCRT5000 Siyah Beyaz Zemin Tespiti
Çizgi izleyen robotların gözü olan küçük bir sensörle zeminin siyah mı beyaz mı olduğunu anlarsın. TCRT5000 sensörü zemine gözle görülmeyen bir ışık gönderip ne kadarının geri döndüğüne bakar; beyaz z

ESP32 HC-SR04 Ultrasonik Mesafe Ölçer
HC-SR04 ultrasonik sensör, gönderdiği ses dalgasının nesneye çarpıp geri dönme süresini (Time of Flight) ölçerek mesafe hesaplar. Bu projede ESP32 ile TRIG pinine 10 mikrosaniyelik darbe gönderip, ECHO pininden gelen yankı süresini `pulseIn()` ile okuyacağız. Hesaplanan mesafeyi cm cinsinden 16x2 I2C LCD'de göstereceğiz. HC-SR04 5V çalıştığı için ECHO pinine **gerilim bölücü** zorunludur — aksi halde ESP32'nin 3.3V GPIO'su zarar görür.
Diğer yazılar
BlueGrays uygulaması
Bu devreyi telefonunda adım adım kur
Devre şeması, kod ve parça listesi tek ekranda. 160'tan fazla Arduino, ESP32 ve Pico projesi seni bekliyor.
Telefonunla tara
Kamerayı koda tut; telefonunun uygulama mağazası açılır.
ya da mağazada aç

