Etiket arşivi: digital barometer

DPS310

Infineon firmasının duyarlılığı yüksek ve düşük güç tüketimli basınç sensörü DPS310’u birkaç sene önce bir reklamda görmüştüm. Orada bu malzemenin giyilebilir teknolojiler için ideal olduğu vurgulanıyordu.
Ardından bir süre önce, bugünlerin popüler konusu iç ortamda konum bulma (indoor navigation) ile ilgili bir proje için çalışırken aklıma bu malzeme geldi ve bunun demo board‘undan sipariş verdim.
Board çiklet kutusu gibi bir kutuda geldi. İçinden de Infineon’un standart hale getirdiği bir form faktöründe üretilmiş (ki sonra bunun host tarafı için bir board da sipariş ettim), prototip çalışması yapması kolay bir kart çıktı. Aslında bu board’un herhangi bir özelliği yok. Tek işlevi montajı kolay olmayabilecek olan sensörü üzerinde taşımak.

İvme ölçerlerde gördüğümüz hem SPI hem I2C ile kullanılabilen senkron seri port bunda da var. Ben mümkün oldukça SPI seçen biri olduğum için bu sensörde de SPI bağlantısını kullanıyorum.
Bu sensörü çalıştırmak için elimdeki PIC32MM USB Curiosity dev. board’u kullandım.
Geliştirme kartının üstündeki USB ile PC bağlantısı kurup I2C üzerinden de bir LCD ekran bağlayıp sensör ölçümlerini izlemeyi planladım.

Söylemeye gerek yok, hassas basınç ölçümü düşey konumun belirlenmesi için kullanılabilir (benim bu sensörü ilgi alanıma almamın ilk nedeni aslında böyle bir kullanım değildi, bundan ileride söz edeceğim).
Bu sensörlerde aradığım meziyet mutlak doğruluktan çok (atmosfer basıncının o anki tam değerini bize söyleyecek bir barometre istemiyoruz) ölçüm çözünürlüğünün yüksek olması ve bağıl duyarlılık. Bu sayede 2-3 santimetrelik yükseklik değişimlerini yanılgısız ayırt edebiliyoruz.

Sensörün düşük güç tüketimli olması ve çalışma modu için farklı seçeneklerimiz olması da elbette pille çalışacak bir cihazda olmazsa olmazlarımızdan ikisi.

Bu sensörde beğenmediğim tek şey düzeltme katsayılarını kullanarak ölçüm değerini kullanıcının hesaplamak zorunda olması. (Düzeltme işine dökümantasyonlarda kaibrasyon demişler, düzeltme/kompanzasyon sanki daha uygun bir tabir). 8 bitlik bir işlemci ile bunu arabirimlemeyi düşünüyorsanız makineyi epey yoracaksınız demektir. Diğer taraftan deneme yanılmalarla, düzeltme uygulamadan da anlamlı sayısal sonuçlar elde edebilirsiniz (kompanzasyon işi sıcaklığa göre de yapıldığı için bunu tavsiye etmem).

Arayüz

Bu çipe SPI üzerinden erişiyorum. Çipte 3 telli SPI modu da var, bu modu etkinleştirdiğimizde SDO çıkışı INT çıkışına dönüşüyor. Ben bunu kullanmıyorum. 4-wire SPI çalışması için mode ’10’ olarak ayarladım. Yani mikrodenetleyicinin SPI ayarlarında;
CKP = 1  // clock polarity = 1 (Boşta iken 1)
CKE = 0  // MOSI 1->0 geçişinde güncellenir.
SMP =1 // MISO 0->1 geçişinde güncellenir.
Prototip kurulumumda sensor board’unu yaklaşık 15cm’lik jumper kablolarıyla geliştirme kartına bağlamıştım. Bu şekilde 1MHz SPI hızında sorunsuz haberleşme yapabiliyorum. Bu iş için yapılmış bir board’da bu hız çok daha fazla olabilir. Datasheet 10MHz SPI hızında çalışılabilir diyor.

SCLK’ın boşta durumunun 1 olması I2C ile uyumlu olmanın bir zorunluluğu. Çipin açılıştan hemen sonraki varsayılan modu I2C. Ancak CS pinini bir kere 0’a çekip SPI ‘ı etkinleştirince, arayüz sonraki yeniden başlatmaya dek SPI modunda kalır. Ayrıca, 3/4 wire seçimi için de config register’ında bir ayar biti var. Oraya hiçbir şey yazmazsanız 4wire kullanmış oluyorsunuz.

Her konuşmanın ilk byte’ı adrestir. Her adresin ilk biti de (MSB) bu erişimin yazma mı yoksa okuma mı olduğunu belirtir. Yazma yalnızca belirtilen adrese 1 byte olarak yapılabilirken okuma ardışık olarak çok byte devam ettirilebilir. Çipten okuma yapmak bize şu durumlarda lazım:
** Katsayılar 18 byte;
** Ölçüm sonuçları 3’er byte;
** Sensör durumunu öğrenmek için MEAS_CFG’i okumak (1 byte)

Sensörün Başlatılması

Çipin, enerjilenmesi sonrası 40ms kadar bir başlatma süresi var. Başlatma sonrasında alet otomatik olarak ölçüme başlamıyor. Zaten ilk işimiz (eğer daha önceden işlemci üstünde saklamadıysanız) sensörün düzeltme katsayılarını okumak olmalı.

Ben, başlatma kodunda öncelikle MEAS_CFG register’ını okuyup COEF_RDY ve SENSOR_RDY flag’lerinin set edilmiş olup olmadıklarına bakıyorum. Eğer bu bitlerin her ikisi de 1 değilse Init fonksiyonumuz işleme devam etmeyip FALSE dönmeli. Çünkü ana uygulama henüz ölçüm yapamayacağını bilmeli.
Eğer çip çalışmaya hazırsa, ilk işimiz PROD_ID register’ını okumak. Bu register’da DPS310’un ürün kimliği ve revizyon numarası yazılı. Beklenen değer 0x10 olmalıdır.

Her şey normal gözüküyorsa ikinci işimiz kalibrasyon katsayıları denen diziyi okumak olacak. Burada da can sıkıcı bir durum var. Parametreleri burst mode olarak 18 byte’lık bir dizi içine okuyorum. Ancak buradaki bazı katsayılar 24 bit, bazıları ise 12 bitlik işaretli (2’nin tümleyeni) tamsayılardır. Bunları açabileceğimiz uygun değişken boyları 32 bit ve 16 bitlik işaretli sayılar olacağı için bir dönüştürme işlemi yapmamız gerekiyor. Buna örnek datasheet’te verilmiş. Kısaca anlatmak gerekirse, açılacak katsayı kaç byte’lıksa en yüksek anlamlı bitine bakıyorsun, o bit eğer 1 ise sayı – işaretli olduğu için senin değişkenini sayının kendisinden o sayının bit genişliğinin alabileceği değerden çıkarıyorsun. Yani, 12 bitlik 2’s complement bir sayıdan 16 bitlik negatif bir sayı elde etmek için;
signed short c = (okunan sayı) – 4096;
Hedef değişken 15 bit (1 bit de işaret) olduğu için rollover olmadan sayının negatifini buluyoruz. c0 parametresinin üretilmesini aşağıda görebilirsiniz:

    // c0:
    w = (unsigned short) c[0] << 4;
    x = c[1] >> 4;
    dps310_info.c0 = w | x;
    // 2's comp. signed dönüşümü yap:   
    if (w & 0x0800)  dps310_info.c0 = dps310_info.c0  - 4096;

Datasheet Sayfa 37’de buradaki değişkenlerin, 18 byte’lık bir stream içindeki ardışık konumları verilmiş. Ne yazık ki padding olmadığı için dizinin bazı elemanları iki farklı parametrenin nibble’larını taşıyor olacaklar. Burada anlatmanın artık geyiğe gireceği bit kaydırma işlemleri ile zaman harcamak zorundasınız.

Sensörün Ölçmesi

Tıpkı nem ölçümünde olduğu gibi, yalnızca basınç ölçmek diye bir şey yok. Kompanzasyon için, sıcaklığı da hassas biçimde, tam bu çipin üstünde ölçmeniz gerekiyor. O yüzden, ölçüm çevrimlerimizin bir kısmında sıcaklığı da ölçmemiz gerekli (sıcaklığın daha yavaş değiştiğinden eminsek her çevrimde ölçmemiz gerekmez ama bu konuda benim sözüme değil kendi uygulamanızın durumuna bakın).

Bu sensör, süreki ya da talep edildiğinde ölçüm yapacak şekilde çalıştırılabilir. Üzerinde bir FIFO var ve son 32 ölçüm sonucu saklanabiliyor (sıcaklık ve basınç için ortak kullanılan bir buffer). Ben deneme uygulamamda bu özelliği tercih etmedim.
Diğer ölçüm modunda biz sensöre basınç ya da sıcaklık ölçümü yapmasını söylüyoruz, çip ölçümü yapıyor ve duruyor. Sonuç da PRS_Bn ya da TMP_Bn register’larında güncelleniyor.
INT pinini kullanmadığımız için işlemin tamamlandığını MEAS_CFG register’ındaki TMP_RDY ve PRS_RDY flag’lerini okuyarak anlıyoruz. İlgili flag 1 oldu ise TMP_B2 ya da PRS_B2 register’larından itibaren 3’er byte okuyup sonucu alıyoruz (okuma işlemi flag’leri otomatik olarak sıfırlar).
Okuma ile aldığımız değerler 24 bitlik işaretli sayılardır üstelik bunlar big endian’dılar. Ham okumaları, düzeltme işlemi için yapacağımız aritmetik işlemlerde kullanabilmek için 32 bitlik işaretli tamsayılara çevirmemiz gerekir. Bu işlem de yukarıda, kalibrasyon katsayılarını açarken kullandığımız yöntemle dönüşüm gerektirir.

Okumanın ne genlikte sonuç döndüreceği seçtiğimiz oversample ayarına bağlı. Örneğin ben, aşağıdaki ayarları tercih ettim:

Oversampling x ölçüm periyodu değeri 1’i geçmemeli. 32 oversampling seçmekle 0,3 Pascal’lık bir ölçüm duyarlılığına erişiyoruz (3cm). Ancak bu, ölçüm hızımızı 16 Hz ile sınırlıyor. Buna ek olarak bir de bit shift ayarı hikayesi var. x32 oversampling, 24 bitlik sonuç register’ını taşırdığı için sensöre sonucu sağa kaydırıp toplama yapmasını söylememize yarayan bir bit var. O da, CFG_REG register’ının P_SHIFT ve T_SHIFT bitlerini set ederek oluyor.

Peki ölçüm aralığımız oversampling’e göre değişebiliyorsa ama katsayılarımız hep aynıysa sonuçları nasıl normalize edeceğiz? İşte burada Infineon bizi floating point aritmetiğine mecbur bırakan hareketini yapıyor. Kalibrasyon katsayıları, ölçüm sonucunun normalize edilmiş değerine göre verilmiş. Bu normalizasyon için okuma sonucunu kullandığınız oversample değerine göre bir sayıya bölmeniz gerek. Bu da datasheet’in 15. sayfasında verilmiş:

Bu bölme işleminden sonra, ölçüm değerlerini c katsayılarıyla çarpıp toplayıp fiziksel büyüklükleri elde edeceksiniz.

Almanların Dünya Savaşı’nı neden kaybettiklerine bakıyor gibiyiz, değil mi!