12 Nisan 2020 Pazar

BLE 5 ile data transferi ne kadar hızlı? - Kısa Yazılar 2



Yazıya başlamadan önce belirtmen gereken bazı noktalar var. Bu yazıda bahsedilen terimleri ya da konseptleri çok iyi bildiğimi iddia etmiyorum. Yazı boyunca kullandığım bazı terminolojiler ya da bilgiler yanlış olabilir. Temel amacım ise diğer mühendis arkadaşlara ulaşabilmek ve sizlerin yanlışlarımı görmemi sağlamanız. Bu yüzden olumlu ya da olumsuz yorum yaparsanız sevinirim. Umarım karşılıklı bir fayda sağlamış oluruz.

Bluetooth 5 ile birlikte kullanıma sunulan high throughput (2 Mbps) özelliğini bu yazıda değerlendirmeye çalışacağım. Testleri yaptığım kartın fotoğrafını aşağıda bulabilirsiniz.




Bu kart üzerinde 2 Mbps hızı destekleyen NRF52832 işlemcisi bulunuyor. Bu işlemciyi programlamak için bu test kapsamında Nordic firması tarafından yayınlanan SDK’in 16. versiyonunu ve 7. softdevice versiyonunu kullandım. Oluşturduğum test kodlarına GitHub üzerinden ulaşabilirsiniz.

Bluetooth 5 ile birlikte 2M PHY yani 2Mbits/sec data transfer hızı hayatımıza girdi. Bluetooth 4.2 döneminde bu hız 1Mbits/sec idi. Aslında burada bahsedilen 1M ve 2M modülasyon frekansları. Transfer hızını etkileyen bir çok faktör var ve bu faktörler bu yazının konusu olacak.

Öncelikle maximum hıza ulaşabilmek için data paketlerimizin boyutunu güncellememiz gerekiyor. BLE 4.2 ve BLE 5 protokolleri data length extension destekliyor. Eğer bu yazıyı okursanız 2016 yılında Android ve iOS işletim sistemlerinin büyük paket boyutlarına destek vermediğini göreceksiniz. Örneğin elinizde bu yıllardan kalan ve güncelleme almamış bir cihaz var ise paket boyutunu 20 byte üzerine çıkarmanız mümkün değil. Paket boyutunu artırabilmek için kod içerisinde BLE gap data boyutunu 251 byte ve ATT_MTU değerini ise 247 byte çıkarmamız gerekiyor. Tabi ki bu değerlerde haberleştiğiniz cihaza göre değişecektir. Örneğin iOS cihazlar için bu değer maximum 158-byte. Bluetooth spesifikasyonlarına göre bu değer 512-byte kadar çıkabilir. Bu ATT_MTU içerisinde bizim kullanabileceğimiz boyutu bulabilmek için ise ATT_MTU değerinden 3 byte çıkarmamız gerekiyor (1-byte “Op Code” ve 2-byte Attribute Handle). Yani bize kalan alan 244 byte oluyor.

Hızımızı etkileyen diğer bir durum ise connection interval ve bir connection interval da kaç paket gönderilebileceğidir. Connection Interval değeri Android cihazlarda 7.5ms’ye kadar düşebilirken, iOS cihazlarda bu değer 15ms’ye kadar düşebiliyor. İkinci parametre ise bir connection intervalda kaç adet paket aktarılacağıdır. Bu değerde yine cihazdan cihaza değişiyor. Örnek vermek gerekirse eski bir Android sürümü kullanıyorsanız bu değer maximum 6 paket ve ya eski bir iOS cihazı için 4 paketdir.

Şimdi ise teorik olarak ulaşabileceğimiz maximum hızı hesaplayalım. 244 bytelık bir paketi 1M PHY ile aktarabilmek için gereken süre;

Empty packet = 1 + 4 + 2 + 3 bytes = 10 bytes = 80 bits
Data packet size = 1 + 4 + 2 + 4 + 1 + 2 + 244 + 3 bytes = 261 bytes = 261*8 bits = 2088 bits
Time to transmit data packet = 2088 bits / 1 Mbps = 2,088 micro seconds.
Data packet time = Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 80 + 2*150 + 2088 = 2,468 microsecs


Aynı şekilde 244 bytelık bir paketi 2M PHY ile aktarabilmek için gereken süre ise ;

Empty packet = 2 + 4 + 2 + 3 bytes = 11 bytes = 88 bits
Data packet size = 2 + 4 + 2 + 4 + 1 + 2 + 244 + 4 + 3 bytes = 262 bytes = 2096 bits
Time to transmit data packet = 2096 bits / 2 Mbps = 1048 micro seconds
Data_Packet_Time = Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 44 + 2*150 + 1048 = 1392 microsecs.


Bu hesaplamalara göre bir connection intervalda gönderebileceğimiz maximum paket sayısı ise aşağıdaki gibi hesaplanabilir. Yine burada bulacağımız değerde aslında cihazdan cihaza değişiyor. Burada hesapladığınız paket sayısını bir connection intervalda göndereceğimizin bir garantisi yok.

Paket sayısı = (Connection Interval) / (Data packet time)


Benim kullandığımız connection interval değeri bu test için 20ms olduğuna göre bir connection intervalda gönderebileceğimiz paket sayısı 1M PHY için (20*1000/2468) = 8 pakettir. 2M PHY için ise (20*1000/1392) = 14 pakettir.

Tüm bu hesaplar sonucunda ulaşabileceğimiz maximum teorik hızlar yaklaşık olarak 1M PHY için (8 packet * 244 byte * 8 bit / 20 ms) = 780 kbits/sec(kbps) ve 2M PHY için (14 paket * 244 byte * 8 bit / 20 ms) = 1366 kbps’dır.

Aşağıdaki videoda ise gerçek hayattaki aktarım hızlarını görebilirsiniz. 1 megabytelık bir arrayi aktarmamız 1M PHY ile 13.76 saniye sürerken, 2M PHY ile 7.4 saniye sürdü. Pratikteki hızlarımız ise 1M PHY için 609 kbps iken 2M PHY için 1132 kbps oldu.



Peki yazıda gördüğünüz hatalar neler, siz daha yüksek hızlara ulaşabiliyor musunuz? Daha detaylı bilgi için kaynakları okumanızı öneririm. Yorumlarınızı bekliyorum.


Kaynaklar:

https://www.novelbits.io/bluetooth-5-speed-maximum-throughput/
https://punchthrough.com/maximizing-ble-throughput-on-ios-and-android/
https://punchthrough.com/maximizing-ble-throughput-part-2-use-larger-att-mtu-2/
https://punchthrough.com/maximizing-ble-throughput-part-3-data-length-extension-dle-2/
https://interrupt.memfault.com/blog/ble-throughput-primer

1 Nisan 2020 Çarşamba

Fonksiyon Pointerları ve Soyutlama - Kısa Yazılar 1

Garip dönemlerden geçiyoruz ve yaşadığımız hadisenin çapını pek algılayabilmişiz gibi gelmiyor bana. Belki de ben kötümserimdir. Fakat henüz her şeyin başındaymışız gibi geliyor ve anladığım kadarıyla bir süre sonra bugünkilerden çok daha fazla boş zamanımız olacak gibi. Bende bu evdeki zamanları yeni yazılar yazarak değerlendirmek istedim.

Yazıya başlamadan önce belirtmen gereken bazı noktalar var. Bu yazıda bahsedilen terimleri ya da konseptleri çok iyi bildiğimi iddia etmiyorum. Yazı boyunca kullandığım bazı terminolojiler ya da bilgiler yanlış olabilir. Temel amacım ise diğer mühendis arkadaşlara ulaşabilmek ve sizlerin yanlışlarımı görmemi sağlamanız. Bu yüzden olumlu ya da olumsuz yorum yaparsanız sevinirim. Umarım karşılıklı bir fayda sağlamış oluruz.

Bugün fonksiyon pointerları ve soyutlamadan bahsetmek istiyorum. Benim soyutlamadan anladığım donanım ile yazılımın birbirinden soyutlanması. Yazı boyunca çok basit bir problemden yola çıkarak bu soyutlama işleminin nasıl yapılabileceğini göstermeye çalışacağım.

Örneğin, elimizde bir sıcaklık sensörü bulunuyor ve bu sensör ile I2C üzerinden haberleşiyoruz. Amacımız ise bu sıcaklık sensörü kodlarını, ya da kütüphanesini diyebiliriz, donanımdan soyutlamak. Yani yazdığımız tek bir sıcaklık sensörü kütüphanesi ile istediğimiz herhangi bir işlemci ile hiçbir ekstra düzenleme yapmadan kullanabilmek.

İşte tam bu noktada fonksiyon pointerları hayatımıza girmeye başlıyor ve aşağıdaki şekilde tanımlıyoruz. 

typedef uint32_t (*comm_fptr_t)(uint8_t slave_address, uint8_t *p_data, uint32_t length);
typedef void (*delay_fptr_t)(uint32_t ms);


Daha sonra ise fonksiyon pointerların ve gerekli diğer değişkenlerin olduğu bir structure oluşturuyoruz.

typedef struct shtc3_dev_s {
    /*! Device Id */
    uint8_t dev_id;
    /*! Bus read function pointer */
    comm_fptr_t i2c_read;
    /*! Bus write function pointer */
    comm_fptr_t i2c_write;
    /*! delay function pointer */
    delay_fptr_t delay_us;
} shtc3_dev_t;


Son olarak ise bir initialization fonksiyonu ile tanımlanmalarımızı bitiriyoruz. Artık “_shtc3_dev” yapısını “_shtc3_dev.i2c_write(…)” yapısı ile istediğimiz yerde kullanabiliriz.

shtc3_dev_t _shtc3_dev;
void SHTC3_Init(shtc3_dev_t shtc3_dev){
  _shtc3_dev = shtc3_dev;
}

Main fonksiyonu içerisinde ise “SHTC3_Init(…)” fonksiyonunu tanımlayarak işlemi bitirebiliriz.

// initalize sensor module with the i2c address 0x70
shtc3_dev_t shtc3_dev;
shtc3_dev.dev_id = 0x70;
shtc3_dev.i2c_write = &my_i2c_write;
shtc3_dev.i2c_read = &my_i2c_read;
shtc3_dev.delay_us = &nrfx_coredep_delay_us;
SHTC3_Init(shtc3_dev);

Github sayfasında da görebileceğiniz gibi hazırladığım bu örnekle artık işlemci bağımsız bir kütüphane oluşturabildik. Bu sayede SHTC3 sıcaklık sensörü ile alakalı kodlarımızı donanımdan soyutlamış olduk.


Peki yazıda gördüğünüz hatalar neler, sizin daha iyi olduğunu düşündüğünüz bir yöntem var mı?Bu yazıdaki yöntemin olumlu ya da olumsuz yönleri sizce neler. Yorumlarınızı bekliyorum.