Rehberler · 14 dk okuma

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.

HC-05 Bluetooth modülü
HC-05, App Inventor'daki BluetoothClient bileşeninin konuştuğu klasik Bluetooth (SPP) modülüdür; telefonla Arduino arasında kablosuz bir seri hat kurar.

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.

KatmanGöreviBu projede
Arayüz (Designer)Ekranda görünen bileşenlerListPicker, 5 Button, 2 Slider, Label'lar
Mantık (Blocks)Olaylara tepki veren bloklarClick, PositionChanged ve Timer olayları
BluetoothClientSPP bağlantısı, veri gönderme ve almaConnect, SendText, ReceiveText
HC-05Bluetooth ile UART arasında köprü9600 baud, PIN 1234
ArduinoKomutu yorumlar, çıkışları sürer, sensörü okurLED, röle, servo, DHT11

Gerekli malzemeler

MalzemeAdetNot
Arduino Uno (ya da Nano)1Kod ve pinler ikisinde de aynıdır
HC-05 ya da HC-06 Bluetooth modülü1Klasik Bluetooth; HM-10 (BLE) bu yöntemle çalışmaz
1 kΩ ve 2 kΩ direnç1'erHC-05 RXD pini için gerilim bölücü (2,2 kΩ da olur)
LED ve 220 Ω direnç1'erParlaklığı ayarlanabilir LED (D5, PWM)
5 V röle modülü1Lamba ya da fan gibi yükleri açıp kapatmak için
SG90 servo motor1Kaydırıcıyla 0–180° kontrol
DHT11 sıcaklık ve nem sensörü1Telefonda gösterilecek veri
Android telefon1HC-05 iPhone ile çalışmaz
Breadboard ve jumper kablolar—Ortak GND bağlantısı şart
Arduino Uno
Arduino Uno
HC-06
HC-06
SG90
SG90
DHT11
DHT11
LED
LED

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 UnoESP32Raspberry Pi Pico
HC-05 VCC5VGerekmez (dahili Bluetooth)VBUS (5 V)
HC-05 GNDGND—GND
HC-05 TXDD10 (SoftwareSerial RX)—GP1 (UART0 RX)
HC-05 RXDD11, 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ü IND7GPIO 26GP14
Servo sinyal (turuncu)D9— (ESP32Servo ile eklenebilir)GP13
DHT11 veriD2GPIO 4GP16
Üç kurala dikkat et: Tüm GND'ler (Arduino, HC-05, röle, servo ve varsa harici kaynak) birbirine bağlı olmalı. HC-05'in RXD pinine bölücüsüz 5 V verme; modül bir süre dayansa da zamanla bozulabilir. Servo hareket ederken kısa süreliğine yüzlerce miliamper çekebilir; Arduino'yu USB'den besliyorsan bu ani akım gerilimi düşürür, HC-05 bağlantıyı koparır ya da Arduino yeniden başlar. Servoyu ve röleyi ayrı bir 5 V kaynaktan beslemek bu sorunu kökten çözer.

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.

KomutYönAnlamı
L1 / L0Telefon → ArduinoLED'i tam parlaklıkta yak / söndür
P0 … P255Telefon → ArduinoLED parlaklığı (analogWrite değeri)
R1 / R0Telefon → ArduinoRöleyi çek / bırak
S0 … S180Telefon → ArduinoServo açısı (derece)
24.5;41Arduino → telefonSı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.

Arduino (C++)
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'a geçmeden önce Arduino tarafını tek başına test et: Play Store'daki Serial Bluetooth Terminal gibi bir uygulamayla HC-05'e bağlan, "L1" yazıp gönder; LED yanmalı ve Seri Monitör'de L1 görünmeli. Ekranda 2 saniyede bir "24.5;41" gibi satırlar akıyorsa veri dönüşü de çalışıyor demektir. İleride bir sorun çıkarsa hatanın uygulamada mı devrede mi olduğunu böylece hemen anlarsın.

App Inventor'da arayüzü tasarlamak (Designer)

  1. 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.
  2. 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.
  3. 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.
  4. İ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.
  5. Sıcaklık ve nem için iki Label daha ekle ve FontSize değerini 20 civarına çıkar.
  6. Connectivity grubundan BluetoothClient ekle; Properties panelinde DelimiterByte değerini 10 yap ve NoLocationNeeded kutusunu işaretle.
  7. 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şenAd (Rename)Önemli ayar
ListPickerLP_BaglanText: Bağlan
Button × 5BTN_Kes, BTN_LedAc, BTN_LedKapat, BTN_RoleAc, BTN_RoleKapatWidth: Fill parent
SliderSLD_ParlaklikMinValue 0, MaxValue 255
SliderSLD_ServoMinValue 0, MaxValue 180, ThumbPosition 90
LabelLBL_Durum, LBL_Sicaklik, LBL_NemFontSize 20 (değerler için)
BluetoothClientBluetoothClient1DelimiterByte 10, NoLocationNeeded işaretli
ClockClock1TimerInterval 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.

  1. 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.
  2. when LP_Baglan.AfterPicking olayına bir if bloğu ekle ve koşuluna call BluetoothClient1.Connect address: LP_Baglan.Selection bloğunu tak.
  3. 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.
  4. 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.
Bağlantı kurulunca HC-05'in LED'i hızlı yanıp sönmeyi bırakır ve 2 saniyede bir çift kısa yanıp söner. Uygulamaya bakmadan bağlantının durumunu böyle anlayabilirsin; LED yeniden hızlı yanıp sönmeye başlarsa bağlantı kopmuş demektir.

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 metinArduino'da sonuç
BTN_LedAc.ClickL1\nLED tam parlak yanar
BTN_LedKapat.ClickL0\nLED söner
BTN_RoleAc.ClickR1\nRöle çeker, bağlı lamba yanar
BTN_RoleKapat.ClickR0\nRöle bırakır
SLD_Parlaklik.PositionChangedjoin("P", round(thumbPosition), "\n")analogWrite(5, değer)
SLD_Servo.PositionChangedjoin("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.

  1. when Clock1.Timer olayına if BluetoothClient1.IsConnected koşulunu koy.
  2. İçine ikinci bir koşul ekle: call BluetoothClient1.BytesAvailableToReceive > 0.
  3. initialize local satir to call BluetoothClient1.ReceiveText numberOfBytes: -1 ile gelen satırı yerel bir değişkene al.
  4. 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.
  5. 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.
ReceiveText bloğuna -1 verip DelimiterByte değerini 10 yapmayı unutursan (varsayılan değer 0'dır) blok hiç gelmeyecek 0 baytını bekler ve uygulama donmuş gibi görünür. Arduino satırı println() ile gönderiyorsa da \r karakteri ikinci değerin sonuna eklenir; bu yüzden kodda yalnızca '\n' gönderiyoruz.
Değerleri yalnızca yazı olarak göstermekle kalma: sıcaklık 30 °C'yi geçince LBL_Sicaklik.TextColor'ı kırmızı yapabilir, Notifier bileşeniyle uyarı penceresi açabilir ya da bir Canvas üzerinde son ölçümlerin çizgi grafiğini çizebilirsin.

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.

  1. 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.
  2. 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.
  3. 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.
  4. Designer'da BluetoothClient'ın NoLocationNeeded kutusunu işaretli tut; bu ayar Android'e Bluetooth'u konum bulmak için kullanmadığını bildirir.
  5. Testi mutlaka APK ile de yap: AI2 Companion'ın izinleri kendi uygulamasına aittir, senin APK'nın izinleri kurulumdan sonra ayrıca istenir.
HataAnlamıÇö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 pipeBağ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 deniedAndroid 12+ Yakındaki cihazlar izni yokİzni bloklarla iste ya da ayarlardan elle ver
Liste boş açılıyorModül eşleştirilmemiş ya da izin yeni istendiHC-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:

  1. Designer'da Screen1'i seç; AppName (telefonda görünen ad), Icon (kare bir PNG), VersionCode ve VersionName alanlarını doldur.
  2. Üst menüden Build > Android App (.apk) seç. Derleme genellikle bir iki dakika sürer.
  3. 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.
  4. 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.
  5. Uygulamanın ilk açılışında Yakındaki cihazlar iznini onayla, Bağlan'a bas ve listeden HC-05'i seç.
Projenin yedeğini Projects > Export selected project (.aia) to my computer ile al; .aia dosyasını arkadaşınla paylaşabilir ya da başka bir hesaba aktarabilirsin. Uygulamayı Google Play'de yayınlamak istersen Build > Android App Bundle (.aab) seçeneğini kullan ve Projects > Export keystore ile imza anahtarını mutlaka sakla: güncellemeleri aynı anahtarla imzalaman gerekir. Her güncellemede VersionCode'u 1 artırmayı da unutma.

ESP32 ile HC-05'siz aynı uygulama

ESP32 geliştirme kartı
Klasik ESP32'nin içinde klasik Bluetooth bulunur; App Inventor'daki BluetoothClient ona HC-05'e bağlanır gibi bağlanır.

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.

Arduino (C++)
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

Raspberry Pi Pico
Raspberry Pi Pico 3,3 V ile çalıştığı için HC-05'in RXD pinine doğrudan bağlanır; gerilim bölücü gerekmez.

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.

MicroPython
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.
Sorun ararken zinciri ikiye böl: önce Serial Bluetooth Terminal ile Arduino tarafını, sonra App Inventor uygulamasını dene. Terminal çalışıyor ama uygulama çalışmıyorsa sorun bloklardadır; terminal de çalışmıyorsa kablolama ya da Arduino kodu kontrol edilmelidir. Pin numaralarını doğrulamak için pin haritası aracını kullanabilirsin.

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.

Tüm projeleri gör
Led Yakma
#1Başlangıç

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

4.6(179)
977
DHT11 İle Sıcaklık Ve Nem
#55Orta

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

4.7(47)
64
Bluetooth İle Telefondan Led Yakma
#34Başlangıç
Premium

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

4.8(68)
88
L298N ile Bluetooth Kontrollü Araba
#80İleri
Premium

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

5.0(38)
65
Servo Motor Kullanım
#35Başlangıç
Premium

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

4.7(48)
67
RGB Led Kullanımı
#39Başlangıç
Premium

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

4.9(73)
98
220V Ampülü Buton(Push) İle Yakma
#19İleri
Premium

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

4.4(30)
38
2 Arduino Tek Yönlü Haberleşme
#57Orta
Premium

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

4.4(37)
50