Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => Atmel => Konuyu başlatan: zakbay - 29 Şubat 2012, 15:33:05

Başlık: Atmega88 hesap hatam nerede?
Gönderen: zakbay - 29 Şubat 2012, 15:33:05
Arkadaşlar merhaba

atmega88 dahili 1v1 dahili referans ile adc sini kullanmaya başladım. lm35 okuyorum

hesaplarım 1 volt üzerinden olduğu için
okuma yaptıktan sonra değeri 1.1 le çarpmak istiyorum. Ama bir yerde hata yapıyorum galiba sonuçlar alakasız çıkıyor.


uint16_t gecici;

gecici = ADCL + (ADCH<<8);
        sicaklik = (gecici * 110 ) /100;       bu olmuyor
        sicaklik = (unsigned int)((gecici * 110 ) /100);       bu da olmuyor


float değişken kullanmadan bunu nasıl halledebilirim

ecilipse ve winavr kullanıyorum
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: Kabil ATICI - 29 Şubat 2012, 16:15:15
Bu tür işlerde hesap işlerini işlemcide yapmak yerine ben doğrudan tablolama yöntemini kullanıyorum. Program biraz büyüyor ama, daha hızlı işlem yapıyor. Hatta ekrana yazdıracağım değeri tablodan alıp kullanıyorum. Tabloyu da exel programını kullanarak gerekli hesaplamaları yaparak oluşturuyorum.
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: zakbay - 29 Şubat 2012, 16:22:13
Picte sorun olmuyor her türlü kabul ediyordu.
Atmel de yeni şeylerle karşılaşınca bocalıyorum  ;D
Bakalım bulacağız çözümü bir şekilde
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: Kabil ATICI - 29 Şubat 2012, 16:25:25
Anlattığım çözümü Atmel serisi işlemcilerde kullanıyorum. asm'de bazı işleri yapmak  zor olduğu için kestirmeden gitmek iyi oluyor...
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: tmcone - 29 Şubat 2012, 22:21:14
"gecici" değişkenin 16 bitlik bir değer tutabilir. ADC sonucun 1023 ise 110 ile çarptığında sonuç 20 bitlik bir sonuç olur; bu da taşmaya neden olacaktır. Değişkenini 32 bit tanımlarsan sorun çözülür. ADC sonucunu ölçeklerken 2 nin katları şeklinde bir bölen seçmen optimizasyon açısından çok daha iyi olur. Örneğin 1.1 katsayısı için basitçe sonucu aşağıdaki gibi 1.1 * 32 = 35.2 nin tam sayı kısmı ile çarpıp 5 sağa kaydırma yaparsan 32 bitlik bir değişkene ihtiyacın olmaz ve işlem süresi oldukça kısalır. Bu durumda azami hatan 1023 için 1023 * (1.1 - (35 / 32)) = 7 olur. Çarpanı büyüterek bu hatayı azaltabilirsin.

sicaklik = (gecici *35)  >>  5;
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: tmcone - 29 Şubat 2012, 22:30:55
Alıntı yapılan: ambar7 - 29 Şubat 2012, 16:15:15
Bu tür işlerde hesap işlerini işlemcide yapmak yerine ben doğrudan tablolama yöntemini kullanıyorum. Program biraz büyüyor ama, daha hızlı işlem yapıyor. Hatta ekrana yazdıracağım değeri tablodan alıp kullanıyorum. Tabloyu da exel programını kullanarak gerekli hesaplamaları yaparak oluşturuyorum.

Bir önceki mesajımda belirttiğim yöntemi kullarsanız (ek olarak * 1000)  32 bitlik bir çarpan ile virgülden sonra 3 basamak doğrulukta bile sonucu hesaplayabilirsiniz. Ayrıca ekrana yazdırmanız için de float sayılar gerekmez.
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: zakbay - 01 Mart 2012, 12:34:49
ilginç ama yine olmadı
Garip şimdilik ondalık kısma ihtiyacım olmadığı için ilkini kullanacağım daha sonra tekrar bakacağım
selamlar

program ilk hali
sicaklik = (unsigned int)((Temp * 11)/100);    ondalık kısmı kaybetmeyi göze alırsak bu oluyor
-----------------------------------------
sicaklik = (unsigned int)((Temp * 110)/100.0); olmadı
-----------------------------------------
sicaklik = (unsigned int) (Temp *35)>>5; olmadı
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: zakbay - 01 Mart 2012, 16:14:18
sorun çözüldü  type casting olayını diğerleri içinde yapmak gerekiyormuş.

Sicaklik = (unsigned int)((unsigned long)Temptemp * (unsigned long)110 / 100);


Çözüm adresi
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=36708 (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=36708)
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: tmcone - 01 Mart 2012, 17:15:41
Alıntı yapılan: zakbay - 01 Mart 2012, 16:14:18
sorun çözüldü  type casting olayını diğerleri içinde yapmak gerekiyormuş.

Sicaklik = (unsigned int)((unsigned long)Temptemp * (unsigned long)110 / 100);


Çözüm adresi
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=36708 (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=36708)

Sorununa çözüm bulmuşsun ama sorunun nedenini  anlayamamışsın...
Başlık: Ynt: Atmega88 hesap hatam nerede?
Gönderen: zakbay - 21 Mart 2012, 10:47:10
Alıntı yapılan: tmcone - 01 Mart 2012, 17:15:41
Sorununa çözüm bulmuşsun ama sorunun nedenini  anlayamamışsın...

Cevabınızı Yeni gördüm
Siz daha detaylı anlatırsanız hep birlikte öğreniriz iyi olur ilerlememiz adına :)

Bugüne kadar ağırlıklı olarak basic ve pic kullandım.

Bu işin üstadları kadar c bilgim yok hala öğreniyorum.
Ben anladığımı yazayım eksikleri siz tamamlayın o zaman 

Sicaklik = (unsigned int)  burada sağ tarafta yapılan işlemlerin sonucunun unsigned int tipinde olacağı belirtiliyor

((unsigned long)Temptemp * (unsigned long)110 / 100);

buradaki unsigned long lar temptemp ve 110 un unsigned long tipinde işleme alınacağını belirtir. çıkan sonuçta 100 e bölünerek ilk kullanılan unsigned int sınırları içine inmesini sağlıyor.


Biraz karışık oldu galiba ama siz toparlarsınız anlatmak istediklerimi

Selamlar