ESP32 - iOS Uygulama ile Bluetooth Tabanlı Robot

En son güncellendiği tarih: 4 gün önce

Merhaba, bu paylaşımda ESP32 kartıyla tasarlanacak, L298N sürücü kartı ile motorları sürülecek ve bluetooth ile mobil uygulama üzerinden kontrol edilecek robotu ve mobil uygulamasını hazırlayacağız.



Gerekli Donanım

  • ESP32

  • L298N Voltaj Regulatörlü Çift Motor Sürücü Kartı

  • Dişi-Erkek ve Dişi-Dişi Jumper kablolar

  • Yardımcı Breadboard

  • 9 V Pil ve Pil Başlığı

  • Araç kasa ve lastikler + 2 adet 6 V motor (Bu noktada ben elimdeki hazır rc aracımın donanımını kullandım, içindeki devreyi iptal edip söktüm. Sadece motorlar, tekerler ve araç kasası ihtiyacımı karşıladı. Robowars.dev yarışmasında bu konuda bir kısıtlama yok, kurallara uyması dahilinde elinizdeki bir aracı da değerlendirebilirsiniz.) Alternatif donanım için link1, link2, link3


Devre Şeması


Devre şemasına geçmeden önce ESP32 ve L298N motor sürücü kartıyla ilgili bazı temel bilgileri paylaşmak istiyorum.


ESP32


ESP32 dev modül kartı tüm projelerimde kullandığım favori devre kartım. Tercih etmemin ana nedeni bluetooth ve wifi bağlantı çözümlerinin kart üzerinde bütünleşik olarak sunulması. Böylece ek bir donanım alıp, ana devre kartına entegre etmeden bluetooth ve wifi bağlantısına sahip oluyorsunuz. Ayrıca fiyatı çok uygun, boyutu çok küçük ve çok sayıda dijital ve analog pin'e sahip . Son olarak Arduino Sketch ile programlayabiliyorsunuz ve çok sayıda sdk için desteği bulunmakta.


L298N

L298N regulatörlü çift motor sürücü kartı aynı anda 2 adet motoru kontrol etmenizi sağlayan bir devre. Bu kartın en güzel yanı 5V - 35V arası gerilim ile beslenebilmesi ve üzerindeki regülatör sayesinde 5V çıkış gücü elde edebilmeniz. 9V'luk pilimizi direk L298N'e bağlayacağız. Üzerinde bulunan 5V pininden de ESP32'nin ihtiyaç duyacağı enerjiyi elde edeceğiz.


Ek not: Bu projede ilk denememde L9110 sürücü kartını kullandım, ancak L9110 çok daha hassas bir devre. En ufak hatadan ya da dış etkenden (bağlantı kablolarının dirençli olması gibi durumlar dahil) etkileniyor. Motor gücünüz fazla ise beslemeyi düzgün yapamıyor ve kartta aşırı ısınma sonucu duman çıkışı ve yanma gerçekleşiyor. L98N bu bakımdan projemize daha uygun.



Devremize gelecek olursak yukarıda gördüğünüz gibi;

  • 9V güç kaynağımızın artı ucunu L298N'in 12V girişine, eksi ucunu L298N'in GND pinine bağlıyoruz,

  • L298N'den çıkan +5V'u ESP32'nin 5V girişine, L298N'in GND pinini de ESP32'nin GND pinine bağlıyoruz.

  • L298N'de bulunan IN1, IN2, IN3 ve IN4 pinlerini sırasıyla ESP32'nin 18,19,26 ve 27.pinlerine bağlıyoruz.

  • Son olarak L298N'in üzerinde bulunan motor giriş ve çıkışlarını motorlarımızın + ve - uçlarına bağlıyoruz.

L298N'in IN1 ve IN2 girişleri soldaki motorun ileri ve geri yönde devir yapmasını sağlayacak input için kullanılmaktadır. IN3 ve IN4 de sağ motor için aynı görevi yerine getirmektedir.


Aracın İleri-Geri ve Sağ-Sol Hareket Mantığı

Kullanacağımız aracın 2 adet motoru bulunmaktadır. Sol motor hem sol-ön hem de sol-arka lastiğe bağlıdır. Aynı şekilde sağ motor da hem sağ-ön hem de sağ-arka lastiğe bağlıdır. Özetle sol motor + yönde çalıştığında sol tekerler ileri yöne, - yöne çalıştığında sol tekeler arka yöne hareket eder. Bu sağ motor ve tekerler için de geçerlidir.

Yani ön tekerleri sağ ve sol yöne döndürmek için bir servo kullanmıyoruz. Bunun yerine sol ve sağ motorları zıt yönlerde hareket ettirerek aracın sol veya sağ yöne dönmesini sağlayacağız.


L298N'de bulunan IN1, IN2, IN3 ve IN4 pinlerine yukardaki analog değerleri vererek ileri, geri, sol ve sağ hareketleri elde edeceğiz. Analog değer aralığı 0-255 arasındadır. Motorların çalışma devrini düşürmek için bu değerler arasında analog değerler de kullanılabilir.


Ek Not: Hazırladığım örnekte mobil uygulama üzerinden ileri ve sağ yön tuşlarına aynı anda basarak aracın sağa ileri gitmesini de sağladık. Bunun için IN1:250 IN2:0, IN3:150 IN4:0 gibi değerler kullandık. Sol tekerler tam devir, sağ tekerler daha az devirle hareket edince araç sağ ileri gitmeye başlıyor.


Donanım Kodlama: Arduino Sketch


Arduino IDE ve Gerekli Kütüphanelerin Kurulumu


  • Öncelikle aşağıdaki url'den Arduino IDE'sini indiriyoruz.

https://www.arduino.cc/en/software


  • IDE'mizi açıyoruz. İlk olarak Tools -> Board -> Board Manager'dan aşağıdaki şekilde ESP32 board'unu bulup install ediyoruz. Artık Board seçeneklerimizin arasına ESP32'nin geldiğini göreceksiniz.


  • Şimdi de projemizde kullanacağımız analogWrite fonksiyonu için bu kütüphaneyi indireceğiz. Tools -> Manage Libraries'i tıklıyoruz. Library Manager'da aşağıdaki şekilde ESP32 AnalogWrite'ı bulup indiriyoruz.


  • ESP32'yi usb port üzerinden bilgisayarımıza bağlıyoruz. Kullanacağınız usb kablosunun data iletimi desteği olduğundan emin olmalısınız. 2 uçlu şarj görevi gören usb kablolar uygun değildir. 4 uçlu data aktarım destekli usb kablosu edinmeniz gerekir. Ben mac üzerinden işlemlerimi yapıyorum. Usb bağlantısını yaptıktan sonra Tools -> Serial Port altında usbserial seçeneğinin olduğundan emin olun. Arduino ide'si düzgün şekilde yüklenmezse aşağıdaki şekilde usbserial yüklenmemiş olabilir.

Bu durumda FTDI Driver'ını indirip yüklemeniz gerekiyor. Detaylı bilgi.


OS X 10.9 (Mavericks) veya üstü için: https://cdn.sparkfun.com/assets/learn_tutorials/7/4/FTDIUSBSerialDriver_v2_4_2.dmg


OS X 10.8 (Mountain Lion) veya altı için:

https://cdn.sparkfun.com/assets/learn_tutorials/7/4/FTDIUSBSerialDriver_v2_2_18.dmg


  • Son olarak ESP32 IDE ayarlarını (Board, Upload Speed, CPU Frequency etc.) Tools altında aşağıdaki şekilde yapmalısınız.


Artık IDE'miz kodlayamaya ve yazdığımız kodu build edip ESP32'ye yüklemeye hazır.



Donanım Kodlama


ESP32 kartımızın bluetooth özelliğini kullanarak Peripheal modda kullanacağız. Mobil uygulamamız ise Central modda kullanılacak. Önceden bluetooth bağlantısı üzerinde hiç çalışmamış olanlar için kısaca bahsedeyim.



Bağlantı kuracak 2 cihazdan biri Peripheral modda server olarak programlanır. Bu moddaki cihaz advertise oluşturarak belli bilgilerle (UUID, DeviceInfo vs gibi) sürekli etrafına sinyal yollar. Bu noktada robotumuzdaki esp32 kartı Peripheral modda bağlantı öncesi sinyal yollayacak.


Diğer cihaz da Central modda etrafını scan edip ilgilendiği bir peripheral sinyali yakaladığında client olarak server'a bağlantı isteğinde bulunabilir olacak. Bu noktada da yazacağımız mobil uygulama scan etme özelliğine sahip central modda çalışan bir uygulama olacak. İlgilendiği sinyali yakalayınca Esp32'ye bağlantı isteğinde bulunacak.


Bu ön bilginin ardından artık açtığımız boş .ino uzantılı dosyamızda Arduino IDE'de kodlamaya geçebiliriz.


Öncelikle ihtiyaç duyacağımız kütüphaneleri ekliyoruz. Ardından belirlediğimiz SERVICE_UUID değerini ve MESSAGE_UUID değerlerini tanımlıyoruz. Tanımladığımız SERVICE_UUID değerini mobil uygulamada ESP32'ye bağlanmak için de kullanacağız.


Device bilgilerini doğru adreslerden DEVINFO_UUID, DEVINFO_MANUFACTURER_UUID, DEVINFO_NAME_UUID, DEVINFO_SERIAL_UUID, DEVICE_MANUFACTURER, DEVICE_NAME alanlarına setliyoruz. Bu bilgileri ESP32'de BLE ile bluetooth sinyali yollarken sinyale iliştireceğiz. Özellikle burada DEVINFO_UUID alanı önemli. Bu değer her Esp32 kartı için tekildir ve kartın unique id'sini temsil eder. Bu nedenle bu id'yi de mobil uygulama ile ESP'ye bağlanırken kullanacağız.



Uygulama içinde kullanacağımız değişkenleri de yukardaki gibi tanımlıyoruz. Bu değişkenlere ESP32 de kullanacağımız pin değerlerini atadık. speed alanına da motor



Setup ve Loop Metodları


ESP32 kartı çalıştırıldığında ilk olarak setup() metodu bir kere çalışır ardından loop() metodu cihaz açık olduğu sürece sonsuza kadar çalışır. Cihazın ayağa kalkerken kullanacağı temel nesneler ve manager'lar setup metodunda ayağa kaldırılır. Cihazın devamlı yapması gereken işler de loop() metodunda programlanır. Bizim örneğimizde biz loop() metodunu hiç kullanmayacağız. Bunun yerine setup() metodu içinde bluetooth server'ını ayağa kaldırırken verdiğimiz callback metodları kullanarak aracı yöneteceğiz.


  • Yukardaki setup metodunun 1.bölümünde ilk olarak Serial değerini 115200 olarak setliyoruz. Bu değer ESP32'nin Arduino IDE'de bulunan SerialMonitor ile mesajlaşmaya hazır olmasını söylemek için setlenir. SerialMonitor ile yazdırdığınız logları izleyebilirsiniz. ESP32 ile 115200 bit veri hızında mesajlaşılabilir.

  • WRITE_PERI_REG metodu ile ESP32'de bulunan Brownout detector'un disable ediyoruz. Brownout detector, voltaj beslemesinde oluşan artma ve azalmaları algılayarak işlemciyi sıfırlar, kartı kapatır ve kartı korur. Ancak robotumuz farklı bir robot ile karşılaştığında birbirine direnç gösterecektir ve bu akım farkı oluşacaktır. Bu nedenle müsabaka sırasında robotun kapanmaması için biraz riske girerek bu detector'u disable etmek durumundayız. (Disable edilmeden yaptığım denemelerde en ufak direnç'de ESP32 kendini kapatıyordu.)

  • pinMode ile kullanacağımız pinleri mode'unu belirliyoruz.

  • BLEServer'ımızı oluşturuyoruz ve callBack sınıfı olarak MyServerCallbacks() sınıfını setliyoruz. Server ile yapılan connect, disconnect eventlerini yakalamak için kullanacağız. Bu sınıfın metodlarını aşağıda anlatacağız.

  • BLEServer'ı kullanarak SERVICE_UUID değeri ile BLEService'i oluşturuyoruz. Bu obje bağlanılan cihazlarla mesajlaşmak için kullanılacak message characteristic'i taşıyacak. İki cihaz arasında mesajların ayrıştırılması için kullanılan kanal değeri olarak düşünebilirsiniz. Bu characteristic'in callBack sınıfına MessageCallback() sınıfını setliyoruz. Mobil cihazdan ileteceğimiz ileri, geri, sağa, sola komutlarını bu sınıfın callback metodunda yakalayacağız. Bu sınıfın metodlarını da aşağıda anlatacağız.


  • Yukarda bulunan setup metodunun devamında ise server objemiz üzerinden yeni bir service objesi oluşturuyoruz. Device bilgilerini bu service objesi üzerine characteristic'ler ile iliştiriyoruz.

  • Son olarak yine server objemiz ile oluşturduğumuz BLEAdvertising objemiz sinyal göndermeye başlıyoruz.

Loop() metodumuzu kullanmayacağımızı iletmiştim. bu metodun içini boş bırakıyoruz.


Callback Metodları


Az önce setlediğimiz 2 callback sınıfını yaratalım.


  • MyServerCallbacks(): Bu sınıfta onConnect ve onDisconnect servercallback metodlarımızı yazıyoruz. Oluşturduğumuz server'a mobil uygulama ile bağlandığımızda bu metodlar çalışacak. Bağlantı kurulduğunda ya da koptuğunda robotun güvenli şekilde başlaması ve durması için motorlara giden analog değeri analogWrite() ile sıfırlıyoruz.


  • MessageCallback(): Bu sınıfta onWrite ve onRead characteristiccallback metodlarımızı kodluyoruz. Biz, BLE bağlantısı sonrası sadece mobil uygulamadan aldığımız komutlarla aracı yöneteceğimiz için onWrite metodunu kulanacağız. Eğer ESP32'den mobil uygulamaya mesaj iletme ihtiyacımız olsaydı onRead'i de kullanmamız gerekirdi. Ama bu projede ESP32 -> Mobil Uygulama yönünde bir veri iletişimine ihtiyacımız yok.

onWrite metodunda, mobil uygulamadan araca yön vermek için ilettiğimiz string değerini yukarda olduğu gibi getValue() metoduyla çekeceğiz. Aracın mobil uygulama komutlarıyla sync bir şekilde çalışması için tüm yön komutlarını tek string ile formatlı şekilde buraya iletmemiz gerekiyor. Bu nedenle ben aşağıdaki gibi bir string data formatı belirledim.

sagIleri;sagGeri;solIleri;solGeri

Mobil uygulamada yön tuşlarına basınca anlık olarak yukardaki string, ESP32'ye iletilecek. Bu nedenle onWrite metodu içinde önce gelen string'i noktalı virgül ile parse ediyorum. Elde ettiğim sağ ileri, sağ geri, sol ileri, sol geri değerlerini ESP32'de kullandığım ilgili pin'lere analogWrite ile geçiriyorum. pin'lere iletilecek analog değer 0-255 arasında olmalıdır.


Özetle aracın yönünü tamamen mobil uygulama tayin edecek. ESP32'de bulunan bu callback metodu sadece gelen değeri parse edip setlemiş olacak.


Donanım kodlamamız bu kadar. Kodlamayı tamamladıktan sonra Arduino IDE'de bulunan upload butonuyla kodumuzu derleyip, usb ile bağladığımız karta yüklüyoruz.



Mobil Kodlama: iOS - Swift


ESP32'yi kontrol etmek için BLE Central görevi görecek basit bir IOS client uygulaması geliştireceğiz.


Öncelikle Xcode üzerinden boş bir uygulama oluşturuyoruz. Gerekli BLE izinlerini vermek için info.plist dosyasına aşağıdaki tanımları giriyoruz.




Ardından Signing Capabilities -> Background Modes -> Uses Bluetooth Accessories'u enable ediyoruz.



Kodlamaya başlamadan önce ileri, geri, sağ, sol ve bağlan butonları olan basit bir önyüz oluşturuyoruz.



Uygulamamız basit olacağı için tek ViewController yeterli olacak. Butonlarımızı controller'a bağladıktan sonra aşağıdaki şekilde CoreBluetooth framework'unu import ederek kodlamaya başlıyoruz. ESP32'yi yakalamak için kullanacağımız Peripheral objesini, mobil uygulamamızı client olarak kullanabilmek için kullanacağımız CentralManager objesini ve mesajlaşma için kullanacağımız Characteristic objesini tanımlıyoruz. Son olarak ESP32'de set ettiğimiz service UUID değerini tanımlıyoruz.



Uygulama açılışı sonrası viewDidLoad metodunda CBCentralManager objemizi ayağa kaldırıyoruz ve bütün yön butonlarımıza longPressGesture özelliğini kazandırıyoruz. Her bir butona farklı bir tag değeri atayarak longPress() metodunda ayrıştırma yapabileceğiz.

  • ileri = 1

  • geri = -1

  • sol = -2

  • sağ = 2



ViewController sınıfımızı CBCentralManagerDelegate ve CBPeripheralDelegate sınıflarından türetiyoruz. Mobil uygulamamız CentralManager görevi görecek, bundan türetmemiz bu nedenle normal. Ancak CBPeripheralDelegate'den de türetmemizin nedeni mobil cihazın etrafında yakaladığımız peripheral BLE cihazların (ESP32 gibi) message characterstic objesini discover edip mesajlaşmayı sağlayabilmek. Bu arada önyüzden butonlara basıldığında butonların state'lerini tutmak için de up, down, left ve right bool flaglerini oluşturuyoruz. Özellikle aynı anda hem ileri hem sağa basıldığı durumda bu flagler doğru analog değerleri ESP32'ye göndermemiz için bize yardımcı olacak.



Connect butonuna basarak scanButtonTouch metodunu çalıştırıyoruz ve manager ile peripheral cihazları scan ediyoruz. Scan ederken ESP32'de set ettiğimiz serviceUUID değerini kullanıyoruz. Eğer ESP32, BLE range'inde ise yani mobil cihaza yakın ve açık ise didDiscover peripheral metoduna düşecektir. Bu metoda debug koyarak ESP32'nin UUID değerini elde edebilirsiniz. Ardından aşağıda olduğu gibi peripheral.identifier.uuidString bu değere eşit ise manager üzerinden peripheral'a (yani ESP32'ye) connect işlemini gerçekleştirebilirsiniz. Bu arada elde edilen ESP32 peripheral objesini de lokalde oluşturduğumu myPeripheral'a setliyorz.


connect metodu çağrımı sonrası didConnect peripheral metodu çalışacaktır. Bu metoda bağlantı kurulan peripheral nesnesi dönecektir. Bu defa bu nesne üzerinden discoverServices metodunu serviceUUID değeri ile call ediyoruz.


Şimdi de CBPeripheralDelegate sınıfının override edilen metodlarına gelelim. peripheral didDiscoverServices metoduna gelen peripheral objesinden servislerini çekip bu servislerin characterisctic'lerini tarıyoruz. Bu tarama sonucunda yakaladığımız characterisctic'leri lokal'de tuttuğumuz myCharacteristic nesnesine setliyoruz. Özetle ESP32'ye veri ileteceğimiz zaman artık myCharacteristic objesini kullanabiliriz.


Yön Vermek


Şimdi gelelim butonlara basınca çalışacağını bildirdiğimiz longPress metoduna. Bu metod butonlara basınca ya da butonlara basmayı bırakınca çalışıyor. Ayrı flagler sayesinde bir butona basıldığı an bu bilgiyi lokal variable'da saklamış oluyoruz. Aynı anda ikinci butona basılırsa bu iki değeri elde etmiş oluyoruz. (Örnek: önce ileri butonuna bastık ve basılı tutarken sağ yön butonuna da bastık)


İleri butonuna basıldığı durumda geri butonunu disable ediyoruz. Yönler için de aynı durum geçerli. Sağ'a basınca sol butonu disable ediyoruz. Her longPress metodu çalışmasında run() metodunu çağırıyoruz. Bu metod myCharacteristic üzerinden ESP32'ye verileri geçiyor.


run() metodu içinde lokal flaglerde tuttuğumuz buton statelerine göre ESP32'ye iletmemiz gereken analog değerleri hesaplayıp, belirlediğimiz aşağıdaki formatla ESP32'ye iletiyoruz.

sagIleri;sagGeri;solIleri;solGeri

Data gönderimi için lokale setlediğimiz ESP32'nin myPeripheral ve myCharacteristic nesnelerini kullanıyoruz. writeValue metodu ESP32'de oluşturduğumuz MessageCallback sınıfının onWrite metoduna ilgili string'i aktarmış oluyor.




Test


Kodlamamızı tamamladığımıza göre artık deneme yapabiliriz.




Kaynak Kodlar:

https://github.com/dogukantizer/robowars-esp32-l298n-ios-swift-project


#mobirobotics #ios #esp32 #L298N #arduino #robotic #bluetooth #BLE


0 yorum

Son Paylaşımlar

Hepsini Gör