Birkaç haftadır kullandığım işlemcide yazılım sıkıntısı yaşıyorum. (Stm32f100)
Float sayılarla 4 işlem yapıp kendi aralarında karşılaştırıyorum.
Örnek:
Dizi elemanlarım en büyük değer: 8.123 (A)
Çarpan en büyük değer: 1.23 (B)
Bölen en küçük değer: 1.1 (C)
Sonuç (D)
Sonucun en büyük değeri gerçek hayatta atıyorum 15.83 oluyor.
D= (A*B) / C;
İşlemciye bu işlemi yaptırıyorum sonra diyorum ki
D eğer 20 den büyükse bana uyarı ver. Aynı zamanda da hep sonucun en büyük değerini tutuyorum gözlüyorum.
Bu işlemi 1 gün boyunca yaptırdığımda 2 veya 3 kez saçma sapan değerler dönüyor 15.83 olması gerekirken 40-50 gibi bişey oluyor.
Hatalı sonuçların hiçbir periyodikliği yok birbiri ile ilişkiside yok.
Veri tiplerini doğru tanımladım.
İşlemci hata yapmıyordur da Float sayılarla çalışırken dikkat etmem gereken nokta nedir?
Eşitlikten ziyade büyük ve küçük olduklarını kontrol
ediniz. Virgülden sonra hassasiyet fazla olduğu için
eşitlik bulmanız çok zor...
Evet hocam eşitlik kullanmıyorum büyük mü küçük mü ona bakıyorum.
Asıl mesele, virgülden sonra hata olmasını beklerim ama sayının bütünüyle yanlış olmasını anlayamadım.
hocam hepsini aynı satırda yapmaktansa ayrı ayrı satırlarda yapıp takip ediniz
z=a*b
D=z/C gibi
Birde öyle deniyeyim hocam, hangi işlemde sonucun bozulduğunu tespit edebilirim belki.
Alıntı yapılan: gerbay - 16 Mart 2014, 20:48:24
kod yokmu kod? kodsuz bir şey söylenemez..
vayyt hinzir @gerbay, vay!
tabii bi tek uyanik sensin dimi programa bakacam bahanesi ile programi calacan dimi! :P
seni taniyoozz artik! ;D
aslinda anlatilanlara bakilirsa kullanilan formullerde integer/float mixed islemler yapiliyordur. Bu yuzdende bazi ara hesaplamalarda integer/float donusumlerinden dolayi yanlis hesaplamalar oluyordur.
bu konuda daha once 137bin 476 kere konusulmustur, picprojede vede hatta butun dunyada.
cozum nedir?
cevabi basit arkadaslar gomulu program yazacaksaniz fixed-point matematik kullanmayi ogrenin.
gomulu sistemlerde float kullanmadan once 2, 3 hatta 5 yok yok 10 kere dusunun! :-[
Alıntı yapılan: gerbay - 16 Mart 2014, 20:48:24
kod yokmu kod? kodsuz bir şey söylenemez..
Hocam istediğiniz kod olsun :D
#include "stm32f10x.h"
#define ADC_CEVIR 0.0008056640625
#define GERILIM_BOLUCU 18.4358
float Volt=0.0;
float enyuksektutucu(void);
int main(void)
{
while(1)
{
Volt = (float) Volt_Oku() * ADC_CEVIR * GERILIM_BOLUCU; //Volt oku fonksiyonu geriye sadece ADC kanalı değerini döndürür. Max 4095
if( 60.0 < Voltaj)
Led_Yak;
printf("V=%0.2f",enyuksektutucu()); //En fazla geleceği değer 60-61 olması lazım ama ekrana 70-80 gibi bir değer yazdırıyor.
}
}
float enyuksektutucu(void)
{
static float oncekivoltaj=0;
static float suankivoltaj=0;
static float enyuksek=0;
suankivoltaj = Volt;
if( oncekivoltaj < suankivoltaj )
{
oncekivoltaj = suankivoltaj;
enyuksek = oncekivoltaj;
}
return enyuksek;
}
@mufitsozen hocam daha önce problemle karşılaşmadığım için float kullanıyordum eğerki arada böyle sapıtması söz konusu ise ona göre tedbir almakta fayda var.
Hocam o fonksiyon basit DMA nın ADC datasını yazdığı sayıyı geri döndürüyor.
uint16_t Volt_ADC=0;
int16_t Volt_Oku(void)
{
return Volt_ADC;
}
Karışık olmasın diye eklemedim ADC ve DMA ayarlarınıda koyabilirim isterseniz?
Birde buraya yazarken farkettim. Volt_ADC değişkeni unsigned tanımlamışım ancak fonksiyon geri döndürürken int16 yapıyor bu arada bozulma olur mu? Nasıl gözümden kaçtı acaba :o
Ya da bir ihtimal DMA ilgili registera yazma yaparken bende o sırada okuma yapıyorsam data bozuluyor olabilir mi?
Alıntı yapılan: mistek - 16 Mart 2014, 21:53:56
Hocam istediğiniz kod olsun :D
#include "stm32f10x.h"
#define ADC_CEVIR 0.0008056640625
#define GERILIM_BOLUCU 18.4358
float Volt=0.0;
float enyuksektutucu(void);
int main(void)
{
while(1)
{
Volt = (float) Volt_Oku() * ADC_CEVIR * GERILIM_BOLUCU; //Volt oku fonksiyonu geriye sadece ADC kanalı değerini döndürür. Max 4095
if( 60.0 < Voltaj)
Led_Yak;
printf("V=%0.2f",enyuksektutucu()); //En fazla geleceği değer 60-61 olması lazım ama ekrana 70-80 gibi bir değer yazdırıyor.
}
}
float enyuksektutucu(void)
{
static float oncekivoltaj=0;
static float suankivoltaj=0;
static float enyuksek=0;
suankivoltaj = Volt;
if( oncekivoltaj < suankivoltaj )
{
oncekivoltaj = suankivoltaj;
enyuksek = oncekivoltaj;
}
return enyuksek;
}
@mufitsozen hocam daha önce problemle karşılaşmadığım için float kullanıyordum eğerki arada böyle sapıtması söz konusu ise ona göre tedbir almakta fayda var.
hocam benim ilk gozlemim sizin kullandiginiz compiler cok akilli bence Voltaj ve Led_Yak icin "not declared" demesi lazim. Sizin kod hem compile ediyor, yukleniyor vede kosarken 60dan fazla filan birseyler buluyor kendi basina. :P
saskinim vallahi! :o :o
mesaj birleştirme:: 16 Mart 2014, 23:08:48
bu arada gerbay bir cevap yazmis bile.
sizin hatayi veren kodu değilde ondan sizin yaptiginiz ozetleri vermeniz yuzunden iki kisinin vaktini bosa harcadiniz bile. Yani sikayet icin değil, valla hakkimiz helal olsun ama sevkimiz kiriliyor. boyle mesajlari onemsememeye, gormezden gelmemeye basliyoruz.
@mufitsozen hocam
Kodun tamamını koymamamın sebebi 10-15 sayfa civarında oldu ve karman çorman yazılım yaptığım için çok karışık olacak diye bende özetleyerek en muhtemel kısmı koymayı uygun gördüm. Sizin açınızdan bakınca evet ortada kod yok bişey yok ucu açık bir soru sormuşum gibi gözüküyor söylediklerinizde çok haklısınız biraz benim tez canlılığımdan kaynaklanıyor özür diliyorum. Siz böyle yazınca kendimi kötü hissettim.
/*********************************************/
Aslında sorum şuydu koddan bağımsız olarak float sayılarda pik oluşur mu oluşmaz mı? Yani ihtimalde olsa böyle bişey varmı onu bilmek istemiştim.
@gerbay hocam yine kodu çalamadınız ::)
ADCyi fazla hassas ayarlayınca böyle sorun çıkabiliyor. Bit derinliğini azaltalım. Misal 12 bit fazladır. 10 bit neyinize yetmiyor.
Ben de picle uğraşırken bu durumu gördüm. Hesap kitap yapıyorum . Pis işlemci, itinayla ölçtüğüm sonucları mahfetmiş, bozmuş. tükaka..
Çözünürlüğü nasıl değiştiriyorsunuz hocam? (Stm32f100 ve Keil kullanıyorum.)
12 Bitin tamamini degil de kac tane istiyorsan soldan o kadar bit al.
Yani;
Sonuc=ADC_Val>>(12-Cozunurluk);
8 bit cozunurluk istiyorsan
Sonuc=ADC_Val>>4;
Alıntı yapılan: z - 18 Mart 2014, 00:22:04
12 Bitin tamamini değil de kac tane istiyorsan soldan o kadar bit al.
Yani;
Sonuc=ADC_Val>>(12-Cozunurluk);
8 bit cozunurluk istiyorsan
Sonuc=ADC_Val>>4;
Sağolun hocam yazılımsal düşünemedim.
@t2'nin yazdıklarında kafam bi an donanımsal olarak nasıl oluyor tarafına gitti.
Bir sorun da şu olabilir float sayılarla
#define ADC_CEVIR 0.0008056640625
Bu sayıyı ifade edemezsiniz. Single Precision Float Sayılarda belirttiğiniz sayı : 8.0566405e-4 haline geliyor. Bu da biriken bir hataya sebep olabilir. Float sayılarda hassasiyet kavramı ayrı bir dünya. Çok ufak sayılarla uğraşmıyorsanız çoğunlukla farkına varmazsınız ama sınırlarda dolaşmaya başlayınca önemli hale geliyor.
İşte böyle şeyleri bilmek istiyorum hocam. Teşekkürler.
Amerika'nın zamanında Körfez savaşı'nda kullandığı Patriot füzelerinde Floatin sayı kullanımında yuvarlama sorunu nedeniyle hata oluşuyor ve askerler ölüyor:
http://www.ual.es/~plopez/docencia/itis/patriot.htm (http://www.ual.es/~plopez/docencia/itis/patriot.htm)
http://autarkaw.wordpress.com/2008/06/02/round-off-errors-and-the-patriot-missile/ (http://autarkaw.wordpress.com/2008/06/02/round-off-errors-and-the-patriot-missile/)
En büyük sonuç 15.83 demişsin. Katsıylarını ve aldığın analog değerleri 100'le çarpıp float yerine işlemleri integer'da yaparak en son sonucu 100'e bölmeyi denedin mi ? Ben genelde bu şekilde kullanıyorum float'ı.
güzel bir döküman
http://www2.bayar.edu.tr/muhendislik/makine/ihsan.dolapci/Say2013/Sayisal_Yontemler_2.pdf (http://www2.bayar.edu.tr/muhendislik/makine/ihsan.dolapci/Say2013/Sayisal_Yontemler_2.pdf)