RTC doğruluk ayarlama

Bowman

Aktif Üye
Katılım
7 Ekim 2022
Mesajlar
112
NXP'nin PCF85063A RTC entegresini kullanıyorum. Mikroişlemcim ise M032SG8AE. 10 gündür çalışıyordu elektronik kartım. Bugün baktığımda RTC'den okuduğum saat bilgisinin gerçek zamana göre 3 dakika ileride olduğunu gördüm. Bu benim için sıkıntı çıkaracak bir durum. Datasheeti okuduğumda offset registerının varlığını gördüm. Doğruluğu ayarlamak için kullanabileceğim yazıyor. Fakat daha önce hiç yapmadım. O yüzden şuan doğruluğu ayarlamayı tam olarak nasıl yapacağımı anlamaya çalışıyorum. Datasheette 8.2.3.3. başlıkta offset calibration workflow anlatılmış.

rtc_offset.png


Ben de bu workflow'u baz alarak bir fonksiyon yazdım.

C:
#define CRYSTAL_VALUE    32768.48

void offset_calibration()
{   
    uint8_t offsetValue;
    float frequency,deviationPpm,period,differenceToIdealPeriod;
    
    frequency = CRYSTAL_VALUE;
    period = (1 / CRYSTAL_VALUE);
    
    differenceToIdealPeriod = (1 / 32768) - period;
    deviationPpm = (1000000 * differenceToIdealPeriod) / period;
    
    offsetValue = I2C_ReadByteOneReg(I2C0,I2CADDR,RTC_OFFSET);
    
    if((offsetValue & 0x80))
    {
        offsetValue = deviationPpm / 4.34;
    }
    else if((offsetValue & 0x80) == 0)
    {
        offsetValue = deviationPpm / 4.069;
    }
    
    I2C_WriteByteOneReg(I2C0,I2CADDR,RTC_OFFSET,offsetValue);
}

Bu da offset registerı.

offset.png

Merak ettiğim öncelikle doğru bir yolda mı gidiyorum ? Bu fonksiyonu nerede nasıl kullanmam gerektiğini de tam anlamadım çünkü elektronik kartıma gerçek zaman bilgisi bir yerden gelmeyecek sadece RTC entegrem var. Her türlü yoruma ve tavsiyeye açığım.
 
Ben workflowda anlatılan işlem için osilaskop vs ile ölçüm yapman gerektiğini anladım. Bunun için bir fonksiyon yazmana gerek yok. 32768 frekansında ne kadar sapma var bunu ölçüp yukarıdaki hesabı elle yapıp sonucu registere yazacaksın. Bir kerelik bir işlem.
 
Ben workflowda anlatılan işlem için osilaskop vs ile ölçüm yapman gerektiğini anladım. Bunun için bir fonksiyon yazmana gerek yok. 32768 frekansında ne kadar sapma var bunu ölçüp yukarıdaki hesabı elle yapıp sonucu registere yazacaksın. Bir kerelik bir işlem.
Fakat register açıklamasında iki farklı mod var. Birincisi 4 dakikada bir kalibrasyon. Diğeri ise 2 saatte bir kalibrasyon. Ben bu yüzden bir fonksiyona ihtiyacım olduğunu düşündüm.
 
Sen hangi modu kullanacağına karar veriyorsun. Workflow un son adımında modlar için farklı hesap yöntemi verilmiş. Mod 0 kullanırsan sapmayı her iki saatte bir düzeltiyor. Mod 1 kullanırsan her 4 dakikada bir düzeltme yapıyor. Dediğim gibi bir kerelik ölçüm ve işlem yapacaksın. Sonra o arka planda kendi işini kendi yapacak. Yani ben böyle anlıyorum....
 
Benim anladığım şu. Entegre üzerindeki (ya da yanındaki) osilatörün ideal frekansı 32768 Hz. Ancak gerçek hayatta biraz farklı olabiliyor. Bunu düzeltmek için önce bu saat frekansını çalışma koşulları altında (sıcaklık vs) ölçüyorsunuz (osiloskop ya da frekans sayacıyla) (ADIM-1). Daha sonra bu değeri kullanarak sapmayı hesaplıyorsunuz (ppm) (ADIM-2, 3, 4).

Bu sapmayı kompanse etmek için iki farklı algoritma var entegrenin kullandığı. Birini seçip onu uyguluyorsunuz (ADIM-5) (yani o "if" ile register üzerinden Mode değerini okumak yerine kararı siz vermelisiniz):

1- Düşük güçlü uygulamalar için "Mode=0". Bunda bulduğunuz sapmayı 4.34'e bölüp tamsayı kısmını alıyor ve register üzerine yazıyorsunuz (bilgisi ile birlikte). Düzeltme işlemini 2 saatte bir uyguluyor.

2- Seri mod için "Mode=1". Bunda bulduğunuz sapmayı 4.069'a bölüyorsunuz. Tamsayı kısmını alıyor ve register üzerine yazıyorsunuz (mode bilgisi ile birlikte). Düzeltme işini 4 dakikada bir uyguluyor.



Yaklaşımlar:
a-
Bir entegre/devre için bir sefer register değerini dışarıda hesapladıktan sonra o entegrede hep onu kullanabilir, her boot sırasında register üzerine aynı değeri yazabilirsiniz.

b- Kodunuz içerisine ölçtüğünüz osilatör saat frekansını yazıp hesaplamayı yazdığınız gibi bir fonksiyonla yapıp register üzerine yazabilirsiniz.

c- Mikroişlemciniz ile boot sırasında (ya da uygun göreceğiniz bir zaman) dijital giriş üzerinden saat frekansını ölçüp dinamik olarak bu hesaplamayı yapabilir ve register üzerine uygun değeri yazabilirsiniz.

İlk iki seçenekte osilatör frekansını bir kez ölçüp kodda sabit değer (kodda sabit değer yerine EEPROM üzerine yazmak da bir seçenek olabilir) olarak kullandığınızdan sıcaklık ya da zaman içerisinde osilatör frekansında yaşanacak kaymalar tutarlılığı bozabilir. Ama uygulaması kolay ve çoğu zaman yeterli olacaktır.

Üçüncü seçenekte ise osilatör frekansını da işlemciye ölçtürdüğünüz için hem her devre için ayrı ölçüm işlemi ve kod ihtiyacı ortadan kalkar. Ancak geliştirme işi biraz daha zahmetli olur.
 
b- Kodunuz içerisine ölçtüğünüz osilatör saat frekansını yazıp hesaplamayı yazdığınız gibi bir fonksiyonla yapıp register üzerine yazabilirsiniz.

c- Mikroişlemciniz ile boot sırasında (ya da uygun göreceğiniz bir zaman) dijital giriş üzerinden saat frekansını ölçüp dinamik olarak bu hesaplamayı yapabilir ve register üzerine uygun değeri yazabilirsiniz.
Ben b ve c opsiyonlarını anlayamadım. işlemcinin doğru ölçtüğünü nereden bileceğiz? Yada bu tarz ölçümler için işlemciye güvenilir mi?
 
Evet bu da çok güzel bir soru :)

Söz konusu işlemcinin saat frekansına mı yoksa RTCnin osilatör frekansının farklı çalışma koşullarında ya da zaman içinde kaymayacağına mı daha fazla güvenmeliyiz emin olmak zor. Günün sonunda osiloskopun bile kalibrasyonunun kusursuz olup doğru ölçeceğinin garantisi yok. GPSDO filan kullanmaya gider bu iş. Deneyip görmek lazım. Bir ara bunu vakit bulup da denesek 1-2 işlemciyle.


Yukarıdaki açıklama C opsiyonu için. B opsiyonu aslında A opsiyonunun aynısı. Tek fark A'da her şeyi dışarıda hesaplayıp register değerini sabit olarak koda (ya da EEPROM'a) yazıyoruz; B'de ise sadece osilatör saat frekansını koda (ya da EEPROM'a) sabit değer olarak yazıp register değerini fonksiyonla hesaplıyoruz. Anlamlı bir fark yok arada. @Bowman fonksiyonu büyük ölçüde yazmış zaten diye onu ayrı seçenek olarak yazdım.
 
@ozkarah @Endorfin35+ Cevaplarınızla soruma katkıda bulunduğunuz için teşekkürler. Kafamda oturmayan nokta şuydu. Tamam ideal olarak kristal 32768 Hz olmayacak. Fakat çevresel etmenlere göre bu değer atıyorum 32890 Hz veya 33121 Hz gibi değerler olamaz mı ? Yani sapmanın bir ideal değeri yok. Çevresel etmenlere göre değişebilecek bir şey. Ama sanırım şuan ki ofis ortamını ele almam gerekecek. Sanırsam mantıklı olan şuan ki kristalin sapmasına osiloskoptan bakıp gördüğüm frekans değerini yazdığım fonksiyondaki CRYSTAL_VALUE vermek. Sonrasında da main() içerisinde bu fonksiyonu çağırmak böylece program ilk çalıştığında kalibrasyon işlemini gerçekleştirmiş olacağım.
 
Evet aynen öyle. Değer ne olursa olsun yöntem aynı. Ama genel olarak kristalin de belli bir üretici sapma değeri olduğundan öyle çok büyük sapmalar olacağını tahmin etmiyorum. Zaten sizin 10 günde 3 dakikalık sapmanız da kristalde 6.83 Hz civarında bir sapmaya denk geliyor. Bence bu bile az bir sapma değil.

Bir de "Mode" u seçip ona göre kodunuzu revize etmeniz gerekiyor.

Bu arada bir ESP32 Frequency Counter örneği buldum. Akşam fırsat bulursam bir deneyeceğim tutarlılığını.
 
10 günde 3 dakika sapma gerçekten yüksek. @ozkarah ın dediği gibi burada amaç imalattan kaynaklı sapmayı düzeltmek. Ortamdan kaynaklı sapma +/- seyredeceği için bu kadar büyük sorun çıkartmamalı...
 
ESP32 WROVER ile bir frekans ölçme denemesi yaptım.
Kabaca bir counter tanımlayıp 5sn boyunca ölçüm alıyorum. Her 20000 palste bir taşma kesmesi oluşturuyorum.
Her kesme oluştuğunda da önceki kesme zamanı ile mikro saniye cinsinden farkını alıp kesmeler oluştukça ortalamasını alıyorum. Burada elde ettiğim ortalama 20000 palsin toplam periyot süresi. Her iniş ve çıkışta bir pals oluşuyor. Dolayısıyla kaynak sinyalin periyotunun mikro saniye cinsinden 10000 katını buluyorum. Buradan da sinyal frekansını hesaplıyorum.

SDG2042X ile 32768 Hz pulse sinyali üreterek ile denediğimde şöyle bir çıktı alıyorum:
23:12:50.453 -> Frequency : 32767.947266 Hz n=15
23:12:55.545 -> Frequency : 32767.962891 Hz n=15
23:13:00.654 -> Frequency : 32767.968750 Hz n=15
23:13:05.750 -> Frequency : 32767.955078 Hz n=15
23:13:10.851 -> Frequency : 32767.968750 Hz n=15
23:13:15.945 -> Frequency : 32767.962891 Hz n=15
23:13:21.052 -> Frequency : 32767.962891 Hz n=15
23:13:26.128 -> Frequency : 32767.955078 Hz n=15
23:13:31.253 -> Frequency : 32767.947266 Hz n=15
23:13:36.332 -> Frequency : 32767.947266 Hz n=15
23:13:41.441 -> Frequency : 32767.976562 Hz n=15
23:13:46.534 -> Frequency : 32767.976562 Hz n=15
23:13:51.631 -> Frequency : 32767.968750 Hz n=15
23:13:56.737 -> Frequency : 32767.962891 Hz n=15
23:14:01.860 -> Frequency : 32767.955078 Hz n=15

Bu sırada aynı sinyali SDS2104X+ osiloskop 32767.985 Hz ölçüyor. Keithley DMM6500 ise 32768.38 Hz gösteriyor.



Bu sefer 32768.25 Hz bir sinyal oluşturarak aynı testi yapıyorum. Çıktı bu sefer şöyle:
23:17:10.548 -> Frequency : 32768.210938 Hz n=15
23:17:15.653 -> Frequency : 32768.218750 Hz n=15
23:17:20.749 -> Frequency : 32768.226562 Hz n=15
23:17:25.838 -> Frequency : 32768.234375 Hz n=15
23:17:30.953 -> Frequency : 32768.218750 Hz n=15
23:17:36.036 -> Frequency : 32768.199219 Hz n=15
23:17:41.150 -> Frequency : 32768.207031 Hz n=15
23:17:46.247 -> Frequency : 32768.207031 Hz n=15
23:17:51.351 -> Frequency : 32768.218750 Hz n=15
23:17:56.441 -> Frequency : 32768.207031 Hz n=15
23:18:01.555 -> Frequency : 32768.218750 Hz n=15
23:18:06.650 -> Frequency : 32768.226562 Hz n=15
23:18:11.758 -> Frequency : 32768.234375 Hz n=15
23:18:16.853 -> Frequency : 32768.218750 Hz n=15
23:18:21.965 -> Frequency : 32768.210938 Hz n=15
23:18:27.058 -> Frequency : 32768.207031 Hz n=15
23:18:32.149 -> Frequency : 32768.207031 Hz n=15

Osiloskop 32768.23 Hz, DMM6500 32768.63 Hz olarak ölçüyor.


Ölçüm süresi 5 sn. Ancak amaç kalibrasyon olduğundan kabul edilebilir bir süre diye düşünüyorum. Osiloskopun ölçümünün doğru olduğunu varsayarsak arada çok küçük bir fark var. Bunun da hesaplamada geçen süre ile ilişkili olduğunu ve ufak bir düzeltme ile halledebileceğimizi varsayabiliriz.

Tabi burada ESP32nin yüksek hızlı sayaç özelliğini kullanmamızın da faydası var. Aynı kodu 10 MHz sinyal üreterek deniyorum. Osiloskop anlık 9,999,995 Hz olarak ölçüyor. ESP32 is 9,999,988 Hz olarak ölçüyor. 0.7ppm fark hiç fena değil.

Ancak şöyle bir problem var. Pals dalgalarda performans hem yüksek hem de düşük hızlı sinyallerde gayet tatmin edici. Ofset ekleyerek oluşturduğum yüksek hızlı sinüs dalgalarda problem yok. Ancak düşük hızlı <150KHz dalgalarda yükselme ve düşme zamanı uzun olduğu için sayaç kenarları birden fazla kere yakalıyor. Bu sebeple olması gerekenden çok daha yüksek bir frekans buluyor. Bir schmidt trigger ile birlikte kullanmakta fayda var.
 
Son düzenleme:

Çevrimiçi personel

Forum istatistikleri

Konular
6,957
Mesajlar
118,804
Üyeler
2,825
Son üye
karahanli7

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top