Parazitli DC sinyallerin yazılımsal olarak filtrelenmesi

Başlatan Mucit23, 16 Ocak 2013, 23:02:14

Mucit23

Arkadaşlar merhaba.

STM32F107 ADC si ile Loadceller den ağırlık okuyorum.

Okuduğum ağırlık değerinin birler hanesi çok değişken, Hatta bu değişmeler bazen 10lar hanesinde bile görülüyor.

Yazılımsal olarak en basitinden ortalama alma yaptım. 200 defa örnek alıp aldığım örnekleri toplayıp örnek sayısına bölüyordum. Değişmeler buunla birlikte azıcık azaldı ama kesin çözüm olamadı. Değişmeler devam ediyor.

Osiloskopla ADC girişine baktığımda çok ufak parazitler dışında aşırı birşey göremiyorum. Yani okadar fazla bir değişme olmaması gerekir. Ölçü aletiylede baktığımda yine stabil bir gelirim görüyorum. Ayrıca ADC girişlerinde RC filtrede var.

Sorunun STM32F107 nin adc ayarlarıyla ilgili olabileceğini düşündüm. Çok hızlı bir ölçüm yapmam gerekmiyor. Hatta çözüm olurmu blmiyorum ama ölçüm sıklığını 1-2 sn ye kadar düşürebilirim.

ADC de dikkat etmem gereken ayarlar varmıdır bilmek istiyorum.

ADC okuması için adc.h şeklinde bir dosya oluşturup programıma dahil ediyorum. İçeriğide aşağıdaki gibi.
#include "stm32f10x_lib.h"

void  initADC1(void);
u16 readADC1(u8 channel);
u8 ADC1H(u8 channel); /*Okunan ADC kanalinin yuksek degerlikli 8 bitini donderir*/
u8 ADC1L(u8 channel); /*Okunan ADC kanalinin dusuk degerlikli 8 bitini donderir*/

/*
	*	ADC baslanagic ayarlari yuklenme islemini yaparç
*/
void initADC1(){
	
     
     	ADC_InitTypeDef ADC_InitStructure;
	
   		RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
	
				/* ADC pin analog input yapiliyor ( PORTC-1 )*/
				GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  
				GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
				GPIO_Init(GPIOA, &GPIO_InitStructure);

				/* ADC1 AYARLAMALARI ------------------------------------------------------*/
		  	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
				ADC_InitStructure.ADC_ScanConvMode = ENABLE;
		  	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
		  	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
		  	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
		  	ADC_InitStructure.ADC_NbrOfChannel = 1;
		  	ADC_Init(ADC1, &ADC_InitStructure);

				/* ADC1 Kanal ve clk secimi yapiliyor ( kanal_11 )  */
     		//ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_55Cycles5);
		  	/* ADC1 aktif */
				ADC_Cmd(ADC1, ENABLE);
	
		  	/* ADC1 Reset Kalibrasyonu yapilacak */
		  	ADC_ResetCalibration(ADC1);
		  	/* Kalibrasyon bekleniyor */
		  	while(ADC_GetResetCalibrationStatus(ADC1));

		  	/* ADC1 calibrasyonu yapilacak */
		  	ADC_StartCalibration(ADC1);
		  	/* Kalibrasyon bekleniyor */
		  	while(ADC_GetCalibrationStatus(ADC1));
}

/*
	* ADC den okunan 12 bitlik degeri donderir.
	* 'chalnnel' parametresi adc kanalini secmek icin kullanilir.
	* -> ADC_Channel_0
	* -> ADC_Channel_1
	* -> ADC_Channel_2
	* ->......
*/
u16 readADC1(u8 channel){
	u16 adc=0;
	ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_55Cycles5);
	 /* Adc dönüsümü baslatiliyor */
	  	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	  /* Adc dönüsümü bekleniyor */
	    while(ADC_GetSoftwareStartConvStatus(ADC1));
	  /* Adc sonucu okunuyor */
		adc=ADC_GetConversionValue(ADC1);
	
		return adc;
}

	/*
		*
		* Belilen ADC kanalinin okunan dusuk degerlikli 8 bitini donderir
		*
	*/
u8 ADC1L(u8 channel){
		u8 adc_low=0xFF&readADC1(channel);
	return adc_low;
}

/*
	* Belirlenen ADC kanalinin yuksek degerlikli 8 bitini donderir 
	* fakat okunan adc 12 bitlik oldugundan gelen 8 bitlik datanin
	* dusuk degerlikli 4. bitine kadar degerler yuklenir.
	*	ornek olarak okunan yuksek degerlikli data: 0x02
	* 
*/
u8 ADC1H(u8 channel){
		u16 temp=0xFF00&readADC1(channel);
		u8 adc_high=temp>>8;
	
	return adc_high;
}


Bunun dışında başka nasıl filtreler uygulayabilirim. mesela True RMS burada iş görürmü?


muhittin_kaplan

#1
Mucit konusu geçmişti yine stm32 ile alakalı ADC nin ölçümünde
Unutulan Geçmiş yada Oynar merkezli ortalama yada basit kalman ı kullanabilirsin

mesaj birleştirme:: 16 Ocak 2013, 23:15:00

https://www.picproje.org/index.php/topic,43892.msg323718.html#msg323718

pisayisi

Adc yi en yavaş hızda çalıştırarak okumayı deneyin. Yazılımsal olarak yapılcak basit bir filtreleme en değersiz birinci ya da ikinci bitin her ikisinin lojik sıfır yapılması böylece çözünürlükte 2 bit kaybederken hızlı değişen işaretleri basitce ve kod karmaşası oluşturmadan süzerek, gürültüsüz bir adc çıkışı elde edebilirsiniz...
Murat

Yuunus

 muhittin hocam yazdiklarim belki arkadasin sorusuna karsilik yazilmis bir cevap degil ama ornegin DISCOVERY nin ADC den pil voltaji olcerken bile olculen degerler yerinde duramiyor, bu degeri kalman yada ortalama alarak sabitlemenin kime ne faydasi var anlayamiyorum, sonucta olctugun deger gercek deger degil cunki ortalamasini aliyorsun. adc den okunan degerler arasinda kucuk farklar olsa birkac ortalama alarak hata oranini azaltmayi anlarim ama Allah icin iyi farklar var.(birde adc den anlik hassas degisken degerleri olcmemiz gerektigini dusunun o zaman ne olacak)

muhittin_kaplan

hocam sabit değerlerde problem yaşamadım, filtre vs kullanmadan sıkıntısız ölçtüm.
ama gürültülü ortamlarda küçük sapmalar oluyor, bunuda yazılımla hallettim. akım ölçme örneği yaptım bugün
oradada ölçü aletiyle felan takip ettim neredeyse bire bir aynı.(hatta iki farklı ölçü aletiyle kontrol ettim) Ama genel kanı şu sanırım forumda, STM in adc si pek verimli değil.

z

ADC init rutinlerini vs tekrar tekrar kontrol etmek lazım. Çok kanallı ölçümlerde ADC sample alma süresi de önemli.

ADC girilerini 50 Ohm ile şaseye bağlayın. Sonra 0..3v voltaj girin. Bahsettiğiniz hatalar hala varmı bir daha test edin.

Açıkcası ben CM3 çiplerin ADC lerinde asla sorun olduğunu düşünmüyorum.


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Mucit23

Hocam belliki henüz adc kullanımını bilmiyoruz. Yada doğru bildiğimiz yanlışlar var.

Suanda sadece tek kanaldan ölçüm yapıyorum.

Forumu takip ediyorum. Discovery dede benzer sorunlar yaşayanlar olmuş ama ben pek inanmiyorum. Bence yanlış yaptığımız birşeyler var. Muhtemelen bende bir hata yapıyorum. Yarın Adc yi yavaslatmayı deneyelim bakalım.

Bülent hocam Kart yapılmış durumda. Yani pek fazla değişiklik yapma imkanım yok. Bu oynamaları imkanım olduğu müddetçe yazılımla gormezden gelmeye çalışacağım.


HexfeT

Sizin durumla ne kadar alakalı bilemem ama ADC nin referans kabul ettiği şase noktası ile ölçüm alınan sensörün ya da kaynağın şase noktası arasındaki hattan ekstra akım geçmesine neden olacak bir durum varsa ölçüm sapacaktır. Bu hattın direnci ve üzerinden akan akım ile orantılı olarak (U=IxR) ölçüm sonucu sapar.Bunu önlemek için girişleri doğrudan sensörün şase ve çıkışına bağlı bir diferansiyel opamp ile tamponlama yapmak gerekiyor sanırım.

-------------------------------------------------------------------------------
Şu "Bu ileti bir moderatörden onay beklemektedir." olayı ne zaman ortadan kalkıyor acaba? :)

z

Sen gene de imkanın varsa ADC girişi ile şase arasına bir 50 Ohm atıp test programı yazmayı dene.

Ben çok üşeniyorum. (Şu sıralar notalarla başım dertte) Ama sonucu da çok merak ediyorum.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Elektroemre

Merhaba,

ADC modülü ve giren sinyal kadar ADC'nin REFeransında önemli.
ADC referansı ne kullanıyorsun?
En temizi VREF pininde harici kaliteli bir referans entegresi ve PCB tasarımındada analog GND'yi ayrı yapmak.


KOlay gelsin.

Mucit23

Hocam 50Ohm yok şuanda elimde 47 ohm var. Eğer sıkıntı olmazsa hemen deneyeyim.

ADC referans girişlerini kullanmıyorum. Yani beslemeye bağlı olması gerekir. Bunun yanı sıra ADC nin beslemesinide direk VDD ye bağlı değil. 3.3V gelirimi 1ohm dirençden geçirip sonra çıkışına 100nf ekledikten sonra VDDA ya bağlamışım.

Edit; Arkadaşlar internette filtre yöntemlerini araştırırken "Self Adaptive pseudo-moving average filter" diye bir yöntem buldum. Bu filtreleme yöntemi hakkında bilgisi olan varmı? Nedir, Nasıl çalışır, Hangi alanlarda kullanılır. Bu konuda bilgi edinmek istiyorum.

z

Evet dene hocam. İçimden bir ses çok doğru ölçümler yapılacağını söylüyor.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

sadogan


Mucit23

Bülent hocam dediğinizi yaptım. Fakat sizin dediğiniz şekilde yapınca opampın çıkış gelirimini neredeyse sıfıra çekmiş oluyorum. ADC değeri çok düşüyor.

ADC girişine direk 1uF elektrolitik kondansatör bağladım.Bununda faydası birazcık oldu. Ölçüm hızını çok yavaşlattım. 1ms aralıklarla ölçüm yapıyorum. Şimdilik problemi virgülden sonraki 1 haneye düşürdüm. (Aslında daha doğru dürüst yazılımsal filtre uygulamadım. Yine ortalama alıyorum.)

Elimde 3000kg lık loadcell ler var. Bu loadcelleri paralel şekilde bağlayıp devreme bağladım. Kendi devremde yükseltip ADC ile okuyorum. Loadcelleri ise büyükçe bir masanın 4 ayağına yerleştirdim. Bu sayede masanın üstündeki nesnelerin ağırlıklarını ölçüyorum. Şimdilik tek bir problemim kaldı. Oda 5kg eksik ölçmem. Yani masanın üzerine çıktığımda beni 5kg eksik ölçüyor.  :)

Bunun birkaç sebebi olabilir.
1. si Loadcellere dengesiz yüklenme(Bukadar büyük fark oluşturmaması gerekir.
2. si Yanlış Hesap yapıyorum.
3. sü Loadcell kazanç direnci düzgün ayarlanmamış.

Bunları inceleyeceğim. Umarım bu sorunuda çözerim.

Alıntı yapılan: sadogan - 17 Ocak 2013, 14:35:45
Loadcell devresini görebilirmiyiz ?

Loadcell ölçüm devresinde özel bir yöntem şema vs yok. INA114 kullanıyorum.
http://www.ti.com/lit/ds/symlink/ina114.pdf

z

Yok yok, öyle yaparsan tabiki opamp çıkışı aşırı yüklenir. 50 Ohm uçlarına harici bir güç kaynağından ayarlı voltaj verecektin.

Böylece okunan değerlerin gene eskisi gibi zıplayıp zıplamadığına bakacaktın.

Eğer ADC girişlerinde yada en azından zıpladığını söylediğin ADC girişinde opamp var ve opamp çıkışı doğrudan yada düşük sayılabilecek bir direnç üzerinden ADC ye gidiyorsa zaten yapmanı istediğim düşük empedansla sürme devrende var demektir.

Opamp çıkışı ADC ye nasıl bağlı?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com