App Inventor Arduino Bluetooth: HC-05 ile Android Uygulaması Yap
App Inventor ile Arduino Bluetooth kontrolü: HC-05 bağlantısı, ListPicker, buton ve kaydırıcı blokları, LED, röle, servo, sensör verisi, APK ve Android 12 izni.
App Inventor ile Arduino'yu Bluetooth üzerinden kontrol etmek, tek satır Java ya da Kotlin yazmadan kendi Android uygulamanı yapmanın en hızlı yoludur. MIT'nin ücretsiz ve tarayıcıda çalışan MIT App Inventor aracında butonları, kaydırıcıları ve yazı alanlarını ekrana sürükleyip bırakır, ne yapacaklarını da yapboz parçalarına benzeyen bloklarla kurarsın. Telefon, Arduino'ya bağlı bir HC-05 Bluetooth modülüne bağlanır; uygulamadaki her dokunuş Arduino'ya kısa bir metin komutu olarak gider, Arduino da sensör ölçümlerini aynı yoldan telefona geri yollar.
Bu rehberin sonunda elinde gerçekten çalışan bir kumanda uygulaması olacak: listeden HC-05'i seçip bağlanan bir ListPicker, LED'i ve bir röleyi açıp kapatan butonlar, LED parlaklığını ve servo açısını ayarlayan iki kaydırıcı (Slider) ve DHT11'den gelen sıcaklık ile nemi canlı gösteren yazılar. Arduino kodunu, App Inventor bloklarını tek tek, APK oluşturmayı ve Android 12 ile gelen Bluetooth izin sorununun çözümünü adım adım göreceksin. HC-05'i ilk kez kullanıyorsan önce HC-05 Bluetooth Modülü yazısına göz atmanı öneririz.

App Inventor nedir, Arduino ile nasıl haberleşir?
MIT App Inventor, Massachusetts Teknoloji Enstitüsü'nün (MIT) geliştirdiği, Google hesabınla giriş yapıp tarayıcıda kullandığın ücretsiz bir uygulama geliştirme ortamıdır. İki ekranı vardır: Designer (Tasarımcı) ekranında uygulamanın görünüşünü bileşenleri sürükleyerek hazırlarsın; Blocks (Bloklar) ekranında ise "butona basılınca şunu yap" gibi kuralları renkli bloklarla yazarsın. Uygulamayı telefona kurmadan denemek için Play Store'daki MIT AI2 Companion uygulaması kullanılır; iş bitince tek tıkla kurulabilir bir APK dosyası üretilir.
Bluetooth tarafında işi BluetoothClient bileşeni yapar. Bu bileşen klasik Bluetooth'un SPP (Serial Port Profile, seri port profili) özelliğini kullanır; HC-05 de tam olarak bu profille çalışır. Sonuçta telefon ile Arduino arasında görünmez bir seri kablo oluşur: uygulama SendText bloğuyla "L1" gönderdiğinde Arduino bu iki karakteri, Seri Monitör'den yazılmış gibi bt.read() ile okur. Arduino'nun bt.print() ile gönderdiği her şey de telefondaki ReceiveText bloğuna ulaşır. Arduino tarafında Bluetooth'a özel hiçbir kütüphane gerekmez.
| Katman | Görevi | Bu projede |
|---|---|---|
| Arayüz (Designer) | Ekranda görünen bileşenler | ListPicker, 5 Button, 2 Slider, Label'lar |
| Mantık (Blocks) | Olaylara tepki veren bloklar | Click, PositionChanged ve Timer olayları |
| BluetoothClient | SPP bağlantısı, veri gönderme ve alma | Connect, SendText, ReceiveText |
| HC-05 | Bluetooth ile UART arasında köprü | 9600 baud, PIN 1234 |
| Arduino | Komutu yorumlar, çıkışları sürer, sensörü okur | LED, röle, servo, DHT11 |
Gerekli malzemeler
| Malzeme | Adet | Not |
|---|---|---|
| Arduino Uno (ya da Nano) | 1 | Kod ve pinler ikisinde de aynıdır |
| HC-05 ya da HC-06 Bluetooth modülü | 1 | Klasik Bluetooth; HM-10 (BLE) bu yöntemle çalışmaz |
| 1 kΩ ve 2 kΩ direnç | 1'er | HC-05 RXD pini için gerilim bölücü (2,2 kΩ da olur) |
| LED ve 220 Ω direnç | 1'er | Parlaklığı ayarlanabilir LED (D5, PWM) |
| 5 V röle modülü | 1 | Lamba ya da fan gibi yükleri açıp kapatmak için |
| SG90 servo motor | 1 | Kaydırıcıyla 0–180° kontrol |
| DHT11 sıcaklık ve nem sensörü | 1 | Telefonda gösterilecek veri |
| Android telefon | 1 | HC-05 iPhone ile çalışmaz |
| Breadboard ve jumper kablolar | — | Ortak GND bağlantısı şart |





Devre: HC-05, LED, röle, servo ve DHT11 bağlantısı
HC-05'in kartında regülatör olduğu için VCC pini 5 V ile beslenir, ama veri pinleri 3,3 V mantıkla çalışır. Modülün TXD çıkışından gelen 3,3 V'luk sinyali Arduino sorunsuz okur; Arduino'nun 5 V'luk TX sinyalini ise RXD pinine bir gerilim bölücü üzerinden vermelisin: D11 → 1 kΩ → RXD, RXD → 2 kΩ → GND. Böylece RXD'ye 5 × 2 / 3 ≈ 3,3 V ulaşır. HC-05'i Uno'nun donanım seri pinlerine (0 ve 1) değil, SoftwareSerial ile D10 ve D11'e bağlıyoruz; böylece modül takılıyken kod yükleyebilir, Seri Monitör'ü de hata ayıklamak için kullanabilirsin. LED'in direncini LED direnç hesaplayıcı ile kontrol edebilirsin.
| Bağlantı | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| HC-05 VCC | 5V | Gerekmez (dahili Bluetooth) | VBUS (5 V) |
| HC-05 GND | GND | — | GND |
| HC-05 TXD | D10 (SoftwareSerial RX) | — | GP1 (UART0 RX) |
| HC-05 RXD | D11, 1 kΩ / 2 kΩ bölücüyle | — | GP0 (UART0 TX), bölücüsüz |
| LED (+ 220 Ω) | D5 (PWM) | GPIO 2 (kart üstü LED) | GP15 |
| Röle modülü IN | D7 | GPIO 26 | GP14 |
| Servo sinyal (turuncu) | D9 | — (ESP32Servo ile eklenebilir) | GP13 |
| DHT11 veri | D2 | GPIO 4 | GP16 |
Haberleşme protokolü: telefon ne gönderecek?
Kod yazmadan önce telefonla Arduino'nun hangi "dili" konuşacağına karar vermek gerekir. Bu projede her komut bir harf, ardından bir sayı ve en sonda bir satır sonu karakterinden (\n, ASCII 10) oluşur. Satır sonu çok önemlidir: Bluetooth verisi parça parça gelebilir; "S1" ile "35" ayrı ayrı ulaştığında Arduino satır sonunu görene kadar bekler ve "S135" komutunu tek parça olarak işler. Metin komutları okunabilir olduğu için herhangi bir Bluetooth terminal uygulamasıyla elle de deneyebilirsin.
| Komut | Yön | Anlamı |
|---|---|---|
| L1 / L0 | Telefon → Arduino | LED'i tam parlaklıkta yak / söndür |
| P0 … P255 | Telefon → Arduino | LED parlaklığı (analogWrite değeri) |
| R1 / R0 | Telefon → Arduino | Röleyi çek / bırak |
| S0 … S180 | Telefon → Arduino | Servo açısı (derece) |
| 24.5;41 | Arduino → telefon | Sıcaklık (°C) ve nem (%), noktalı virgülle ayrılmış |
App Inventor'da metin yerine Send1ByteNumber bloğuyla tek bir bayt (0–255) da gönderebilirsin; Arduino bu baytı doğrudan sayı olarak okur. Bu yöntem kısa ve hızlıdır ama yalnızca tek bir kaydırıcı için uygundur: iki kaydırıcı ve dört buton aynı anda bayt gönderirse Arduino gelen 90'ın servo açısı mı yoksa parlaklık mı olduğunu ayırt edemez. Harf + sayı + satır sonu biçimi birkaç bayt fazla tutar, ama 9600 baud'da saniyede yaklaşık 960 karakter gidebildiği için bu fark hiç hissedilmez.
Arduino tarafı kodu
Servo ve SoftwareSerial kütüphaneleri Arduino IDE ile birlikte gelir. DHT11 için Kütüphane Yöneticisi'nden DHT sensor library (Adafruit) kütüphanesini kur; bağımlılıkları sorduğunda Install all seçerek Adafruit Unified Sensor'ı da ekle. 0 ve 1 numaralı pinleri kullanmadığımız için kodu yüklerken HC-05'i çıkarmana gerek yok.
1#include <SoftwareSerial.h>
2#include <Servo.h>
3#include <DHT.h>
4
5SoftwareSerial bt(10, 11); // RX, TX → HC-05 TXD, RXD (bölücü üzerinden / via divider)
6Servo servo;
7DHT dht(2, DHT11); // DHT11 veri pini D2 / data pin D2
8
9const int LED_PIN = 5; // PWM destekli pin / PWM-capable pin
10const int ROLE_PIN = 7;
11const int SERVO_PIN = 9;
12const int ROLE_ACIK = LOW; // çoğu röle modülü LOW ile çeker / most relay modules are active LOW
13const int ROLE_KAPALI = HIGH;
14
15String komut = ""; // gelen satırın tamponu / buffer for the incoming line
16unsigned long sonGonderim = 0;
17
18void komutIsle(String k) {
19 k.trim(); // boşluk ve \r temizle / strip spaces and \r
20 if (k.length() == 0) return;
21 Serial.println(k); // hata ayıklama / debugging
22 char tur = k.charAt(0); // komut harfi / command letter
23 int deger = k.substring(1).toInt(); // harften sonraki sayı / number after the letter
24
25 switch (tur) {
26 case 'L': // L1 / L0 → LED aç, kapat / LED on, off
27 analogWrite(LED_PIN, deger == 1 ? 255 : 0);
28 break;
29 case 'P': // P0..P255 → parlaklık / brightness
30 analogWrite(LED_PIN, constrain(deger, 0, 255));
31 break;
32 case 'R': // R1 / R0 → röle / relay
33 digitalWrite(ROLE_PIN, deger == 1 ? ROLE_ACIK : ROLE_KAPALI);
34 break;
35 case 'S': // S0..S180 → servo açısı / servo angle
36 servo.write(constrain(deger, 0, 180));
37 break;
38 }
39}
40
41void setup() {
42 pinMode(LED_PIN, OUTPUT);
43 pinMode(ROLE_PIN, OUTPUT);
44 digitalWrite(ROLE_PIN, ROLE_KAPALI); // açılışta röle kapalı / relay off at start
45 servo.attach(SERVO_PIN);
46 servo.write(90); // orta konum / centre position
47 dht.begin();
48 Serial.begin(9600); // Seri Monitör / Serial Monitor
49 bt.begin(9600); // HC-05 veri modu hızı / HC-05 data mode baud rate
50}
51
52void loop() {
53 // 1) Telefondan gelen komutları satır satır oku / read commands from the phone line by line
54 while (bt.available()) {
55 char c = bt.read();
56 if (c == '\n') { // satır bitti / line complete
57 komutIsle(komut);
58 komut = "";
59 } else if (komut.length() < 16) { // aşırı uzun satırı kes / cap overlong lines
60 komut += c;
61 }
62 }
63
64 // 2) 2 saniyede bir sensör verisini gönder / send sensor data every 2 seconds
65 if (millis() - sonGonderim >= 2000) {
66 sonGonderim = millis();
67 float t = dht.readTemperature();
68 float h = dht.readHumidity();
69 if (!isnan(t) && !isnan(h)) {
70 bt.print(t, 1); // örnek / example: 24.5
71 bt.print(';');
72 bt.print(h, 0); // örnek / example: 41
73 bt.print('\n'); // println değil, \r gitmesin / not println, no \r
74 }
75 }
76}- Satır tamponu: loop() gelen her karakteri komut değişkenine ekler; \n gelince satırı komutIsle() fonksiyonuna verir ve tamponu boşaltır. Satır 16 karakteri geçerse fazlası atılır, böylece bozuk veri belleği doldurmaz.
- trim(): Bazı terminal uygulamaları satırın sonuna \r de ekler; trim() bu karakteri ve boşlukları temizler, "L1\r" yine "L1" olarak tanınır.
- Harf ve sayı: charAt(0) komut harfini, substring(1).toInt() harften sonraki sayıyı verir. constrain() gelen değeri güvenli aralığa sıkıştırır; telefondan yanlışlıkla 300 gelse bile servo 180°'nin ötesine zorlanmaz.
- Bekletmeyen gönderim: Sensör millis() ile 2 saniyede bir okunur. delay() kullanılmadığı için bu arada gelen komutlar gecikmeden işlenir; ayrıntılar millis ve delay yazısında.
- println yerine print('\n'): println() satırın sonuna \r\n ekler. App Inventor yalnızca \n'yi ayraç olarak kullandığı için \r nem değerinin sonuna yapışır; yalnız \n göndermek telefondaki ayrıştırmayı temiz tutar.
- Aktif LOW röle: Çoğu röle modülü IN pini LOW olunca çeker. Seninki HIGH ile çekiyorsa yalnızca ROLE_ACIK ve ROLE_KAPALI sabitlerinin değerlerini yer değiştir.
App Inventor'da arayüzü tasarlamak (Designer)
- Tarayıcıda ai2.appinventor.mit.edu adresine gir, Google hesabınla oturum aç ve Projects > Start new project ile BlueGraysKumanda adlı bir proje oluştur.
- Palette'teki Layout grubundan bir HorizontalArrangement sürükle; içine bir ListPicker (Text: Bağlan), bir Button (Text: Kes) ve bir Label (Text: Bağlı değil) koy.
- Altına iki HorizontalArrangement daha ekle: birincisine LED Aç ve LED Kapat, ikincisine Röle Aç ve Röle Kapat butonlarını yerleştir. Butonların Width değerini Fill parent yaparsan parmakla basmak kolaylaşır.
- İki Slider ekle: parlaklık için MinValue 0, MaxValue 255, ThumbPosition 0; servo için MinValue 0, MaxValue 180, ThumbPosition 90. Her birinin üstüne ne işe yaradığını yazan bir Label koy.
- Sıcaklık ve nem için iki Label daha ekle ve FontSize değerini 20 civarına çıkar.
- Connectivity grubundan BluetoothClient ekle; Properties panelinde DelimiterByte değerini 10 yap ve NoLocationNeeded kutusunu işaretle.
- Sensors grubundan bir Clock ekle; TimerInterval 200 olsun ve TimerEnabled kutusunun işaretini kaldır. Zamanlayıcıyı bağlantı kurulunca bloklarla açacağız.
| Bileşen | Ad (Rename) | Önemli ayar |
|---|---|---|
| ListPicker | LP_Baglan | Text: Bağlan |
| Button × 5 | BTN_Kes, BTN_LedAc, BTN_LedKapat, BTN_RoleAc, BTN_RoleKapat | Width: Fill parent |
| Slider | SLD_Parlaklik | MinValue 0, MaxValue 255 |
| Slider | SLD_Servo | MinValue 0, MaxValue 180, ThumbPosition 90 |
| Label | LBL_Durum, LBL_Sicaklik, LBL_Nem | FontSize 20 (değerler için) |
| BluetoothClient | BluetoothClient1 | DelimiterByte 10, NoLocationNeeded işaretli |
| Clock | Clock1 | TimerInterval 200, TimerEnabled kapalı |
ListPicker ile HC-05'e bağlanmak
Önce HC-05'i telefonun Bluetooth ayarlarından eşleştir (PIN çoğunlukla 1234, olmazsa 0000). Bu adım şarttır: BluetoothClient1.AddressesAndNames yalnızca eşleştirilmiş cihazları listeler, çevredeki yeni cihazları aramaz. Listedeki her eleman "98:D3:31:F5:2A:10 HC-05" gibi önce MAC adresi, sonra cihaz adı olan bir metindir. Connect bloğuna bu metnin tamamını verebilirsin; App Inventor ilk boşluktan sonrasını kendisi atar. Bağlantı kurulursa blok true, kurulamazsa false döndürür.
- when LP_Baglan.BeforePicking olayına set LP_Baglan.Elements to BluetoothClient1.AddressesAndNames bloğunu koy. Liste her açılışta eşleştirilmiş cihazlarla yeniden dolar.
- when LP_Baglan.AfterPicking olayına bir if bloğu ekle ve koşuluna call BluetoothClient1.Connect address: LP_Baglan.Selection bloğunu tak.
- if'in then kısmında LBL_Durum.Text'i "Bağlandı" yap ve set Clock1.TimerEnabled to true ile veri okumayı başlat; else kısmına "Bağlanamadı" yaz.
- when BTN_Kes.Click olayında önce set Clock1.TimerEnabled to false, sonra call BluetoothClient1.Disconnect, en son LBL_Durum.Text'i "Bağlı değil" yap. Zamanlayıcıyı önce durdurmak, bağlantı kesildikten sonra okuma yapılmasını ve hata mesajını önler.
Veri göndermek: butonlar ve kaydırıcılar
Gönderme işi tek bir blokla yapılır: call BluetoothClient1.SendText text. Metin bloğuna "L1\n" yazdığında App Inventor sondaki \n'yi satır sonu karakterine çevirir. Bağlantı yokken gönderim yapmak 515 hatasına yol açtığı için her gönderimi if BluetoothClient1.IsConnected koşuluyla sarmak iyi bir alışkanlıktır. Kaydırıcıda sayıyı join bloğuyla harfe ve satır sonuna eklersin: join("S", round(thumbPosition), "\n").
| Olay (event) | Gönderilen metin | Arduino'da sonuç |
|---|---|---|
| BTN_LedAc.Click | L1\n | LED tam parlak yanar |
| BTN_LedKapat.Click | L0\n | LED söner |
| BTN_RoleAc.Click | R1\n | Röle çeker, bağlı lamba yanar |
| BTN_RoleKapat.Click | R0\n | Röle bırakır |
| SLD_Parlaklik.PositionChanged | join("P", round(thumbPosition), "\n") | analogWrite(5, değer) |
| SLD_Servo.PositionChanged | join("S", round(thumbPosition), "\n") | servo.write(açı) |
Kaydırıcıyı parmağınla sürüklerken PositionChanged olayı saniyede onlarca kez tetiklenir ve thumbPosition 87,4 gibi küsuratlı değerler verir. Her olayda gönderim yaparsan aynı açı defalarca gider, HC-05'in tamponu dolar ve servo titreyerek, gecikmeyle hareket eder. Çözüm basit: global sonAci adlı bir değişken oluştur; round(thumbPosition) ile yuvarladığın değer bu değişkenden farklıysa gönder ve değişkeni güncelle. Böylece yalnızca açı gerçekten değiştiğinde veri gider. Parlaklık kaydırıcısı için de aynı yöntemi global sonParlaklik ile uygula.
Veri almak: sensör değerini telefonda göstermek
Arduino 2 saniyede bir "24.5;41" satırını gönderiyor. App Inventor'da veri gelince kendiliğinden tetiklenen bir olay yoktur; bu yüzden Clock bileşeniyle düzenli aralıklarla "yeni veri var mı?" diye bakarız. Designer'da DelimiterByte değerini 10 yaptığımız için ReceiveText bloğuna numberOfBytes olarak -1 verdiğimizde blok satır sonu karakterine kadar okur ve satırı \n olmadan döndürür. 200 ms'lik zamanlayıcı, 2000 ms'de bir gelen veriden çok daha sık baktığı için tamponda veri birikmez.
- when Clock1.Timer olayına if BluetoothClient1.IsConnected koşulunu koy.
- İçine ikinci bir koşul ekle: call BluetoothClient1.BytesAvailableToReceive > 0.
- initialize local satir to call BluetoothClient1.ReceiveText numberOfBytes: -1 ile gelen satırı yerel bir değişkene al.
- split text satir at ";" bloğuyla satırı listeye çevir: "24.5;41" iki elemanlı [24.5, 41] listesine dönüşür. Sonucu parcalar adlı yerel değişkende tut.
- if length of list parcalar = 2 ise LBL_Sicaklik.Text'i join("Sıcaklık: ", select list item parcalar index 1, " °C"), LBL_Nem.Text'i join("Nem: %", select list item parcalar index 2) yap. Eleman sayısı kontrolü, yarım ya da bozuk gelen satırların hata vermesini önler.
Android 12 ve üzeri Bluetooth izin sorunu
Android 12 (API 31) ile Bluetooth izinleri değişti. Eskiden kurulumda kendiliğinden verilen BLUETOOTH izninin yerine, kullanıcının uygulama çalışırken onaylaması gereken BLUETOOTH_CONNECT ve BLUETOOTH_SCAN izinleri geldi; telefon ayarlarında bunlar Yakındaki cihazlar izni olarak görünür. İzin verilmemişse App Inventor ilk denemede izin penceresini açar ama o anda çalışan bloğu durdurur. Sonuç tanıdık belirtilerdir: Bağlan'a ilk basışta liste boş açılır, "Error 908: The permission ... has been denied" mesajı çıkar (izin adı olarak BLUETOOTH_CONNECT ya da BLUETOOTH_SCAN yazar) ya da kullanıcı izni bir kez reddettiyse uygulama bir daha hiç sormaz.
- when Screen1.Initialize olayında Android sürümünü kontrol et: select list item (split Screen1.PlatformVersion at ".") index 1 ≥ 12 ise call Screen1.AskForPermission bloğuna Permission listesinden BluetoothConnect ver. Android 11 ve öncesinde bu izinler yoktur; orada sormak da 908 hatası doğurur, bu yüzden sürüm kontrolü önemlidir.
- when Screen1.PermissionGranted olayında, verilen izin BLUETOOTH_CONNECT ise (contains text: permissionName, piece: "CONNECT") bu kez BluetoothScan iste. AskForPermission bir seferde yalnızca tek izin aldığı için izinleri böyle zincirlemek gerekir.
- when Screen1.PermissionDenied olayında bir Notifier ile "Ayarlar > Uygulamalar > BlueGraysKumanda > İzinler > Yakındaki cihazlar > İzin ver" yolunu gösteren bir mesaj göster. Bu olayı yakalamak, kullanıcının karşısına İngilizce hata kutusu yerine anlaşılır bir açıklama çıkarır.
- Designer'da BluetoothClient'ın NoLocationNeeded kutusunu işaretli tut; bu ayar Android'e Bluetooth'u konum bulmak için kullanmadığını bildirir.
- Testi mutlaka APK ile de yap: AI2 Companion'ın izinleri kendi uygulamasına aittir, senin APK'nın izinleri kurulumdan sonra ayrıca istenir.
| Hata | Anlamı | Çözüm |
|---|---|---|
| Error 507: Unable to connect. Is the device turned on? | Modüle bağlanılamadı | HC-05'in enerjisini, başka bir telefona bağlı olmadığını ve eşleştirmeyi kontrol et; olmazsa BluetoothClient'ın Secure kutusunu kaldırıp dene |
| Error 515: Not connected to a Bluetooth device. | Bağlantı yokken gönderim ya da okuma yapıldı | Gönderim ve Clock bloklarını IsConnected koşuluyla sar |
| Error 516: Unable to write: Broken pipe | Bağlantı yarıda koptu (enerji gitti, menzil aşıldı) | Clock'u durdur, Disconnect çağır ve yeniden bağlan; servo ve röle beslemesini ayır |
| Error 908: The permission … has been denied | Android 12+ Yakındaki cihazlar izni yok | İzni bloklarla iste ya da ayarlardan elle ver |
| Liste boş açılıyor | Modül eşleştirilmemiş ya da izin yeni istendi | HC-05'i telefon ayarlarından eşleştir, izni verdikten sonra Bağlan'a tekrar bas |
Uygulamayı test etmek ve APK oluşturmak
Geliştirme sırasında her değişiklikte APK kurmana gerek yok. Telefona Play Store'dan MIT AI2 Companion uygulamasını kur; bilgisayar ile telefon aynı Wi-Fi ağındayken App Inventor'da Connect > AI Companion menüsünü seç ve ekranda çıkan 6 harfli kodu ya da QR kodu Companion'a okut. Designer'da ya da bloklarda yaptığın her değişiklik telefonda anında görünür. Uygulama tamamlanınca kurulabilir dosyayı şöyle üretirsin:
- Designer'da Screen1'i seç; AppName (telefonda görünen ad), Icon (kare bir PNG), VersionCode ve VersionName alanlarını doldur.
- Üst menüden Build > Android App (.apk) seç. Derleme genellikle bir iki dakika sürer.
- Derleme bitince açılan pencerede bir QR kod ve bir indirme düğmesi çıkar. QR kodu telefonla okutup dosyayı doğrudan indirebilir ya da APK'yı bilgisayarına kaydedip kabloyla telefona aktarabilirsin. QR bağlantısı yalnızca kısa bir süre (yaklaşık 2 saat) geçerlidir.
- Telefonda APK'yı açtığında Android, tarayıcıya ya da dosya yöneticisine bilinmeyen uygulamaları yükleme izni vermeni ister. Play Protect bir uyarı gösterirse ayrıntılar bölümündeki yine de yükle seçeneğiyle devam edebilirsin; bu uyarı Play Store dışından gelen ve imzası tanınmayan uygulamalarda sık görülür.
- Uygulamanın ilk açılışında Yakındaki cihazlar iznini onayla, Bağlan'a bas ve listeden HC-05'i seç.
ESP32 ile HC-05'siz aynı uygulama

Klasik ESP32'nin içinde hem klasik Bluetooth hem de BLE vardır. BluetoothSerial kütüphanesi ESP32'yi telefona bir SPP cihazı olarak tanıtır; yani yukarıda yaptığın uygulamayı hiç değiştirmeden kullanabilirsin. Telefonun Bluetooth ayarlarında "BlueGrays-ESP32" adlı cihazı eşleştir, uygulamada listeden seç, o kadar. Dikkat: ESP32-S3, ESP32-C3 ve ESP32-C6 yalnızca BLE destekler; bu kartlarda BluetoothSerial yoktur ve App Inventor tarafında BluetoothLE eklentisi gerekir. BLE ile çalışmanın ayrıntıları ESP32 Bluetooth ve BLE yazısında.
1#include "BluetoothSerial.h"
2#include <DHT.h>
3
4BluetoothSerial SerialBT;
5DHT dht(4, DHT11); // DHT11 veri pini GPIO 4 / data pin GPIO 4
6
7const int LED_PIN = 2; // çoğu DevKit'te kart üstü LED / onboard LED on most DevKits
8const int ROLE_PIN = 26;
9
10String komut = "";
11unsigned long sonGonderim = 0;
12
13void setup() {
14 pinMode(ROLE_PIN, OUTPUT);
15 digitalWrite(ROLE_PIN, HIGH); // aktif LOW röle kapalı / active-LOW relay off
16 dht.begin();
17 SerialBT.begin("BlueGrays-ESP32"); // telefonda görünecek ad / name shown on the phone
18}
19
20void loop() {
21 while (SerialBT.available()) {
22 char c = SerialBT.read();
23 if (c == '\n') {
24 komut.trim();
25 int deger = komut.substring(1).toInt();
26 if (komut.startsWith("L")) {
27 analogWrite(LED_PIN, deger == 1 ? 255 : 0); // LED aç, kapat / LED on, off
28 } else if (komut.startsWith("P")) {
29 analogWrite(LED_PIN, constrain(deger, 0, 255)); // parlaklık / brightness
30 } else if (komut.startsWith("R")) {
31 digitalWrite(ROLE_PIN, deger == 1 ? LOW : HIGH); // röle / relay
32 }
33 komut = "";
34 } else if (komut.length() < 16) {
35 komut += c;
36 }
37 }
38
39 if (millis() - sonGonderim >= 2000) { // Uno koduyla aynı biçim / same format as the Uno
40 sonGonderim = millis();
41 float t = dht.readTemperature();
42 float h = dht.readHumidity();
43 if (!isnan(t) && !isnan(h)) {
44 SerialBT.print(t, 1);
45 SerialBT.print(';');
46 SerialBT.print(h, 0);
47 SerialBT.print('\n');
48 }
49 }
50}Kod, Uno sürümüyle aynı komutları anlar ve aynı "sıcaklık;nem" biçiminde veri gönderir; S komutlarını ise servo bağlı olmadığı için yok sayar. ESP32'de Arduino'nun Servo kütüphanesi çalışmaz; servo eklemek istersen ESP32Servo kütüphanesini kurup aynı attach() ve write() komutlarıyla örneğin GPIO 13'ü kullanabilirsin. Röle modülünü VIN (5 V) pininden besle; IN girişi ESP32'nin 3,3 V sinyaliyle güvenilir tetiklenmiyorsa 3,3 V uyumlu bir röle modülü seç. Ayrıntılar için Röle Modülü Nedir? yazısına bakabilirsin.
Raspberry Pi Pico ve MicroPython ile

Standart Raspberry Pi Pico'da Bluetooth yoktur; HC-05'i UART0 pinlerine (GP0 ve GP1) bağlarsın. Pico'nun pinleri 3,3 V ile çalıştığı için bu kez gerilim bölücüye gerek kalmaz; modülü USB'den gelen 5 V'u veren VBUS pininden besle. Pico W ve Pico 2 W'da dahili Bluetooth bulunur, ancak MicroPython bu kartlarda yalnızca BLE'yi destekler; App Inventor'ın klasik BluetoothClient bileşeniyle konuşmak için yine HC-05 en kolay yoldur. Aşağıdaki kod aynı komutları anlar, servoyu 50 Hz PWM ile sürer ve aynı biçimde veri gönderir; dht modülü Pico'nun MicroPython sürümünde hazır gelir.
1from machine import UART, Pin, PWM
2import dht
3import time
4
5bt = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) # GP0 → HC-05 RXD, GP1 ← HC-05 TXD
6led = PWM(Pin(15))
7led.freq(1000)
8role = Pin(14, Pin.OUT, value=1) # aktif LOW röle kapalı / active-LOW relay off
9servo = PWM(Pin(13))
10servo.freq(50) # servo 50 Hz ister / servos need 50 Hz
11sensor = dht.DHT11(Pin(16))
12
13def komut_isle(k):
14 if not k:
15 return
16 tur, deger = k[0], int(k[1:] or 0) # harf + sayı / letter + number
17 if tur == 'L':
18 led.duty_u16(65535 if deger == 1 else 0)
19 elif tur == 'P':
20 led.duty_u16(min(max(deger, 0), 255) * 257) # 0-255 → 0-65535
21 elif tur == 'R':
22 role.value(0 if deger == 1 else 1)
23 elif tur == 'S':
24 aci = min(max(deger, 0), 180)
25 servo.duty_ns(544000 + aci * 1856000 // 180) # 544-2400 µs darbe / pulse
26
27tampon = b''
28son = time.ticks_ms()
29while True:
30 if bt.any():
31 tampon += bt.read()
32 while b'\n' in tampon: # tam satır geldi mi? / full line received?
33 satir, tampon = tampon.split(b'\n', 1)
34 try:
35 komut_isle(satir.decode().strip())
36 except ValueError:
37 pass # bozuk komutu atla / skip malformed command
38 if len(tampon) > 32:
39 tampon = b'' # satır sonu hiç gelmedi / no newline arrived
40 if time.ticks_diff(time.ticks_ms(), son) >= 2000:
41 son = time.ticks_ms()
42 try:
43 sensor.measure()
44 bt.write('{:.1f};{}\n'.format(sensor.temperature(), sensor.humidity()))
45 except OSError:
46 pass # sensör okunamadı / sensor read failed
47 time.sleep_ms(10)App Inventor ve Arduino ile proje fikirleri
- Bluetooth kontrollü araba: Yön butonlarını F, B, L ve R harflerine bağla, motorları L298N ile sür; tüm adımlar Arduino Araba Yapımı yazısında.
- Akıllı ev paneli: Dört kanallı bir röle modülüyle lamba, priz ve fanı tek ekrandan yönet; fikirler için Arduino Akıllı Ev Projesi yazısına bak.
- Renk seçici lamba: Üç kaydırıcıyla bir RGB LED'in kırmızı, yeşil ve mavi değerlerini ayrı ayrı ayarla.
- Robot kol: Her eklem için bir kaydırıcı ekleyip servo motorları telefondan yönet.
- Sera izleme: DHT11 ve toprak nem sensörü verilerini telefonda göster, toprak kuruyunca pompayı çalıştıran bir buton ekle.
- Sesli komut: App Inventor'ın SpeechRecognizer bileşeniyle "ışığı aç" dediğinde L1 gönderen bir uygulama yap.
Sık yapılan hatalar ve çözümleri
- Uygulama bağlanıyor ama LED yanmıyor: HC-05'in TXD ve RXD kabloları ters ya da kodda SoftwareSerial pinleri devreyle uyuşmuyor. Modülün TXD'si Arduino'nun RX'ine (D10) gitmeli.
- Komutlar işlenmiyor: Metin bloğunda \n unutulmuş; Arduino satır sonunu bekler. Seri Monitör'de gelen komutların görünüp görünmediğine bak.
- Anlamsız karakterler: HC-05'in hızı ile bt.begin() hızı farklı. Modül fabrikada 9600 baud'dur; AT komutlarıyla değiştirildiyse kodu ona göre düzenle.
- Servo titriyor ya da bağlantı kopuyor: Servo Arduino'nun 5 V hattını çökertiyor; servoyu ayrı bir 5 V kaynaktan besle ve GND'leri birleştir. SoftwareSerial veri alırken kesmeleri kısa süre durdurduğu için hafif titreme de görülebilir; kalıcı çözüm için donanım seri portu bol olan Arduino Mega ya da ESP32 kullan. Servo nadiren bir anlığına yanlış açıya da sıçrayabilir: DHT kütüphanesi her ölçümde kesmeleri yaklaşık 5 ms kapatır ve tam o anda gelen bir komut bozulabilir; kaydırıcının bir sonraki komutu servoyu düzeltir.
- Telefondaki değerler gecikiyor: Clock aralığı Arduino'nun gönderme aralığından uzun olduğu için satırlar birikiyor. TimerInterval'ı gönderim aralığından kısa tut.
- Uygulama donuyor: DelimiterByte 0'da kalmış ya da Arduino satırı \n ile bitirmiyor; ReceiveText(-1) hiç gelmeyecek ayracı bekler.
- iPhone'da çalışmıyor: HC-05 klasik Bluetooth kullanır ve iOS buna izin vermez. iPhone için BLE kullanan bir modül (HM-10) ya da ESP32 gerekir.
App Inventor ile Arduino'yu birleştirmek, mobil uygulama geliştirmeyi ve elektroniği aynı projede öğrenmenin en eğlenceli yoludur. Bağlantı ve protokol mantığını bir kez kurduğunda aynı iskeletle araba, akıllı ev ya da sera kumandası yapabilirsin; değişen tek şey butonların gönderdiği harfler olur. BlueGrays uygulamasında Bluetooth ile telefondan LED yakma ve L298N ile Bluetooth kontrollü araba projelerini devre şemaları ve kodlarıyla adım adım bulabilirsin.
Sıkça sorulan sorular
App Inventor ile yaptığım Bluetooth uygulaması iPhone'da çalışır mı?
HC-05 ve HC-06 ile çalışmaz. Bu modüller klasik Bluetooth (SPP) kullanır ve iOS, sıradan uygulamaların bu tür seri bağlantı kurmasına izin vermez. iPhone ile haberleşmek için HM-10 gibi BLE kullanan bir modüle ya da ESP32'ye geçmen gerekir; HC-05 projelerinde Android telefon en sorunsuz seçenektir.
App Inventor'da Bluetooth listesi neden boş geliyor?
AddressesAndNames yalnızca telefonla önceden eşleştirilmiş cihazları listeler; HC-05'i önce Bluetooth ayarlarından 1234 PIN'iyle eşleştir. Android 12 ve üzerinde Yakındaki cihazlar izni verilmemişse liste ilk açılışta boş gelir; izni verip Bağlan'a tekrar bas. Telefonun Bluetooth'unun açık olduğundan da emin ol.
App Inventor Error 507 hatası nasıl çözülür?
Error 507, "Unable to connect. Is the device turned on?" anlamına gelir; telefon modüle bağlantı açamamıştır. HC-05'e enerji geldiğini, LED'inin hızlı yanıp söndüğünü ve başka bir telefona bağlı olmadığını kontrol et. Sorun sürerse eşleştirmeyi silip yeniden eşleştir ya da BluetoothClient'ın Secure özelliğini kapatıp dene.
App Inventor'da APK nasıl oluşturulur?
Projeyi açıp üst menüden Build > Android App (.apk) seçeneğine tıkla. Derleme bitince çıkan QR kodu telefonla okutabilir ya da APK dosyasını bilgisayarına indirip telefona aktarabilirsin. Kurulum sırasında bilinmeyen uygulamaları yükleme izni vermen gerekir.
App Inventor ile ESP32'ye Bluetooth üzerinden bağlanılır mı?
Evet. Klasik ESP32, BluetoothSerial kütüphanesiyle bir SPP cihazı gibi davranır ve App Inventor'ın BluetoothClient bileşeni ona HC-05'e bağlanır gibi bağlanır. ESP32-S3 ve ESP32-C3 yalnızca BLE desteklediği için bu kartlarda BluetoothLE eklentisi kullanmalısın.
App Inventor ile yaptığım uygulamayı Google Play'de yayınlayabilir miyim?
Evet. Build menüsündeki Android App Bundle (.aab) seçeneğiyle Google Play'e yüklenebilen dosyayı üretirsin; bunun için bir Google Play geliştirici hesabı gerekir. Güncellemeleri aynı imza anahtarıyla yapman gerektiğinden Projects > Export keystore ile anahtarını yedekle.
Bu yazıdan sonra yapabileceğin projeler
Tüm projeleri gör
Led Yakma
Elektroniğin ilk merhabası: tek bir LED'i yakıp söndürmek. Arduino LED'i çok kısa aralıklarla yakıp söndürür, ışık hızlı hızlı göz kırpar. Kartın bir ışığı nasıl yönettiğini en sade haliyle görür, son

DHT11 İle Sıcaklık Ve Nem
Odan kaç derece, hava nemli mi, kuru mu? DHT11 sensörü sıcaklığı ve nemi ölçer, Arduino da bu değerleri iki satırlık LCD ekrana yazar ve birkaç saniyede bir yeniler. Sensöre bir şey olursa ekranda hat

Bluetooth İle Telefondan Led Yakma
Telefonundan odadaki ışıkları açıp kapatmanın küçük bir provası. Bluetooth modülü telefondan gelen harfleri Arduino'ya iletir; bir harf kırmızı LED'i, başka bir harf yeşil LED'i yakar, aynı harflerin

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

RGB Led Kullanımı
Tek bir LED'in içinde üç renk saklı: RGB LED önce kırmızı, sonra yeşil, sonra mavi yanar; her renk yarım saniye yanıp yarım saniye söner ve sıra baştan başlar. Arduino'ya bir RGB LED ve üç direnç bağl

220V Ampülü Buton(Push) İle Yakma
Butona bastığın sürece 220 voltluk gerçek bir ampul yanar, bıraktığın anda söner. Arduino'nun küçük sinyali ampulü doğrudan yakamaz; araya röle denen elektrikli bir anahtar girer ve ampulün devresini

2 Arduino Tek Yönlü Haberleşme
İki Arduino'yu tek bir kabloyla konuşturursun: birindeki butona basınca öbüründeki LED yanar, bir daha basınca söner. Gönderen kart butona basıldığını kısa bir mesajla bildirir, alan kart bu mesajı du
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ç

