Arşiv

Archive for Eylül 2011

Multitasking

29 Eylül 2011 1 yorum

Multitasking, birbirinden bağımsız birden çok görevin, eş zamanlı çalıştırılıyormuş gibi görüntülenme yeteneğidir. “Çalıştırılıyormuş gibi” kısmının altını çizmek gerekir çünki birden çok işlemcinin olmadığı bir yerde aynı anda birden çok görevin icrası mümkün değildir. Fakat görevlerin aynı anda icra ediliyormuş gibi gösterilmesi mümkündür. Eğer işlemci zamanı görevler için bölünürse ve görevler arasındaki geçiş hızlı bir şekilde anahtarlanırsa, işlemci birden çok görevi aynı anda yapıyormuş gibi görünür.

Daha rahat anlaşılması için şöyle bir örnek verelim. Diyelimki 3 adet arabamız ve bir motorumuz var. Arabaların oldukları yerden bir noktaya gitmesini istiyoruz. Sırayla ilk arabaya motoru takıyor ve t sürede ilk arabayı hedefine ulaştırıyoruz. Daha sonra motoru diğer arabaya ve sonra diğer arabaya takıp yaklaşık 3t zamanında 3 arabayıda teker teker hedefine ulaştırıyoruz. Kısaca özetlersek bir araba hedefine ulaşmadan diğer araba hareket ettirilmedi.

3 arabayı aynı anda hedefe ulaştırmak içinse t/x kadar bir süre motoru ilk araca sonra t/x kadar bir süre için motoru diğer araca sonra t/x kadar süre için de motoru son araca takmak süretiyle bu işlemi x kere tekrarladığımızda 3t süresi sonunda yine 3 araç da hedefine ulaşmış olacaktır fakat bu sefer 3 üde aynı anda ve 3 üde aynı sürede hedeflerine ulaşmış olacaklardır. Dışarıdan 3 arabaya bakıldığında 3üde aynı anda hareket ediyormuş gibi görülür işte buna multitasking denir. Multitasking çalışan bir işlemci, belirli bir süre belirli bir görevi icra edip, bu göreve ara verir ve diğer göreve geçer. Tüm görevler belirli bir süre icra edilir ve son görevden sonra yeniden başa dönülüp ara verilen göreve kaldığı yerden devam edilir. Bu şekilde tüm görevler aynı anda yaplıyormuş gibi görünür.

8051 için basit bir örnek verelim:

#include <AT89X52.H>
#include <intrins.h>

#define TASK_COUNT 3

unsigned char x,y,z;

unsigned char osOnStartSP;
unsigned char osOnIntSP;

unsigned char osTaskNumber=1;
unsigned short osTaskAddress[TASK_COUNT+1];
void (*osTaskPointer)(void);

void osTask1(void)
{
 while(1)
 {
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
   x++;
  x–;
  x++;
  x–;
 }
}

void osTask2(void)
{
 while(1)
 {
   y++;
  y–;
  y++;
  y–;
 }
}

void osTask3(void)
{
 while(1)
 {
   z++;
  z–;
  z++;
  z–;
 }
}
 
void main(void)
{
 //Init Task Scheduler
 TMOD &= 0xF0;
 TH0 = 0x00;
 TL0 = 0x00;
 ET0=1;
 EA=1;
 TR0=1;

    osTaskPointer=&osTask1;
 osTaskAddress[1]=*osTaskPointer;
    osTaskPointer=&osTask2;
 osTaskAddress[2]=*osTaskPointer;
    osTaskPointer=&osTask3;
 osTaskAddress[3]=*osTaskPointer;

 osOnStartSP=SP;
 
  while(1);
}

void osTaskScheduler(void) interrupt TF0_VECTOR
{      
 TF0 = 0;
 osOnIntSP=SP;
 SP=osOnStartSP+2;
 _pop_(DPL); 
 _pop_(DPH);
 osTaskAddress[–osTaskNumber]=(DPL<<8)|DPH;
 DPL=osTaskAddress[++osTaskNumber]>>8;
 DPH=osTaskAddress[osTaskNumber]&0xFF;
 _push_(DPH);
 _push_(DPL);    
 SP=osOnIntSP;

 osTaskNumber++;
 if(osTaskNumber>TASK_COUNT) osTaskNumber=1;
 
}

Not: Tasklar içerisinde yapılan işlemler göstermeliktir!

Yukarıdaki programda while(1) sonsuz döngüsü ile oluşturulmuş 3 görev (task) vardır. Ana program içerisinde de görev zamanlayıcısı olarak bir timer kurulur. 

Timerın her kesmesinde interrupt alt programına girilir ve stack pointer a kesmeden önce hangi program counter adresi yazılmışsa o geri alınır, kaydedilir ve bir sonraki görevin kaldığı adres daha önce kaydedilmiş bir değişken içerisinden çekilerek stack pointer a geri yüklenir ve intterupt alt programından çıkılır. Otomatik olarak işlemci interrupttan çıkışta stack pointer değerini geri yüklediği için bir sonraki göreve atlanmış olur.

Her görev,

void osTask(void)
{
 while(1)
 { }
}

şeklinde yazıldığından, sonsuz döngü nedeniyle hiçbir görevden geri dönülemez.

Her görevin icra süresi ise timer süresi kadardır. Herbir görevin timerın belirlediğ süre aralıklarında parça parça işlenmesinden dolayı tüm görevler aynı andan icra ediliyormuş gibi görünür, dolayısı ile multitasking yapılmış olur.

Aşağıdaki keil projesinde simulasyon yapıp tasklar arasında nasıl geçiş yapıldığını ve aynı taska gelindiğinde nasıl kalındığı yerden devam edildiğini görebilirsiniz.

Keil u2 project (farklı kaydet ile indirip dosya uzantısını .rar olarak değiştirin)

Reklamlar
Kategoriler:Donanım/Yazılım Etiketler:,

PSoC nem ve sıcaklık ölçer

27 Eylül 2011 1 yorum

PSoC hem dijital hem de analog yapıları bir arada bulunduran bir mikro olduğundan kullanıldığı projenin de hem dijital hem de analog bileşenlerden oluşması mikronun hakkının verilmesinde önemlidir. Mesela PSoC bir kayan yazı projesi için uygun değildir, böyle bir proje pekâlâ 8051 ile de yapılabilir. Aynı şekilde PSoC RC5 kodlarının çözülmesi içinde uygun değildir, bu projede pekâlâ basit bir PIC ile de gerçekleştirilebilir. Daha basit bir örnekle müzik dinlemek için mp3 player almak yerine PC almaya benzer.

Bu projede yukarıda anlattığımız olumsuzlukları ortadan kaldıracak, PSoC a hak ettiği değeri bir nebzede olsa verecek işleri yaptıracağız.

Başlıktan da anlaşılacağı gibi projemiz LCD ekran üzerinde sıcaklık ve nemin gösterilmesinden ibaret. Devrenin dijital kısmını büyük ölçüde DS1621 sıcaklık sensorü oluşturuyor. Hem analog hem de dijital kısmı kullanan sensör ise VS-H25K5A nem sensörü.

Projede kullanılan nem sensörü datasheetini incelendiğinde karşımıza bir değerler tablosu ve birkaç uyarı çıkıyor. Değerler tablosu sensörün bağıl neme maruz kaldığı durumdaki direnç değerini, sıcaklık bazında veriyor. O yüzden DS1621 gibi bir sıcaklık sensörüne ihtiyacımız var. Yani sensörün direnci neme bağlı olarak değişiyor fakat sıcaklıktan da etkileniyor. Dolayısı ile tablodan ölçülen nem değerini bulabilmemiz için bize sıcaklık bilgiside gerekiyor. O yüzden DS1621 e ihtiyacımız var. Bir diğer konu ise uyarılar. Üretici nem sensörünün polarize olmaması için AC işaret ile sürülmesi gerektiğini hem de bu işaretin değerinin de 1Vrms i geçmemesi gerektiğini söylüyor.

Peki tüm bunları PSoC ile nasıl yapacağız.

Öncelikle kabaca neler yapacağımıza bakalım.

  • – Nem sensörünü datasheetinde verilen tablo 1kHz lik işaret ile oluşturulmuş. Bizde aynı tabloyu kullanacağımıza göre aynı frekansı bizde elde etmeliyiz.
  • – Havadaki neme ve sıcaklığa göre sensör direnci değişeceğinden sensör geriliminden yola çıkarak sensör direncini hesaplamalıyız.
  • – Hesaplanan değer ve sıcaklık sensöründen alınan bilgiye göre tablo üzerinden nem değerini bulmalıyız
  • – Ve tüm bunları LCD göstermeliyiz.

Nem sensörü:

Sensörün 1kHz lik işaret ile sürülebilmesi için bir timer kurulup çıkışı bir pin ile ilişkilendirilebilir. Yalnız dikkat edilmesi gereken şey timer çıkışının %50 duty değerine sahip olmasıdır. Aksi halde sensörün polarize olmasına neden olabiliriz. Böyle bir timer ile pinde elde ettiğimiz gerilim 2.5Vrms dir. O halde bir gerilim bölücü ile bu değeri 1Vrms seviyesine çekmeliyiz. Ayrıca işareti AC yapmak içinde seri bir kondansatör kullanmalıyız.

Sensöre sabit değerli bir direnci seri eklediğimizde sabit direnç üzerindeki gerilim değerinden yola çıkarak sensör direncini, beslemesini (1Vrms) bildiğimiz için bulabiliriz. Nem sensörünün 0 ila %100 bağıl nemli bir ortamda çalışalabileceğini düşünürsek, datasheetinde yazılanlara göre sensörün gösterdiği direnç değeri Ω ila MΩ arasında değerler alabilir. Seri direnç değeri üzerinden ölçüm yaptığımızdan bu direnç üzerindeki gerilim değerleri de sensör direnci arttığında düşecektir. O halde sensör direncini daha hassas hesaplayabilmek için seri direnç üzerindeki gerilimi daha hassas ölçmemiz gerekir. Dolayısı ile seri direnç üzerindeki gerilimi ölçmeden önce PSoC içerisindeki PGA ile kuvvetlendirmeliyiz. Yalnız sensör üzerindeki gerilim AC iken DC işaretleri kuvvetlendirebilen bir PGA ile çalışabilmek için sensör seri direnci üzerinden aldığımız AC işarete offset ekleyerek DC ye çevirmeli ve bu şekilde PGA ile kuvvetlendirmeliyiz. PGA çıkışında ise kuvvetlendirilen işaretin sadece max tepe noktasını ADC ye besleyerek o andaki sensör seri direnci gerilimi üzerinden sensör direncini hesaplayabiliriz. Anlık değeri yakalamak içinse PGA çıkışındaki işareti yarım dalga doğrultup RC üzerine vermeliyiz. Bundan sonraki adım ise sadece RC üzerindeki gerilimi ADC ile okumak olacak.

Sıcaklık sensörü:

Sıcaklık sensörü ile I2C hattı üzerinden haberleşeceğiz. İlgili rutinleri bizim için PSoC designer oluşturacak.

LCD:

Nem bilgilerini LCD de göstermek için öncelikle sensör direncini hesaplamalıyız. Bunun için kurduğumuz analog devrenin AC eşdeğeri devresini çizip ölçüm sonucundan nasıl bir eşitlik ile sensör direncini hesaplayacağımızı bulmalıyız.

Sensör direncini hesapladığımızda ortam sıcaklığı ile birlikte bu bilgileri tablo üzerine koymalı ve nem değerini bulmalıyız.

Sonrasında ise hem nem hem de sıcaklık bilgilisini LCD bastırarak projemizi tamamlamış olacağız.

Nem sensörü Direncinin hesaplanması:

Nem sensörünün analog devresi yukarıda gibi dir. PSoC içerisindeki PWM modülü ile oluşturulan 1kHz lik işaret, R1 ve R2 dirençleri ile 1Vrms değerine indirilir. C1 ile AC yapılan işaret sensör ve seri direnci üzerine uygulanır. Sensör direncini bulabilmek için R3 üzerindeki AC işaret PSoC içerisindeki PGA tarafından kuvvetlendirilir ve çıkışındaki işaretin tepe değeri D1 üzeri den C4 ü şarj etmek için kullanılır. C4 üzerindeki gerilim ise PSoC içerisindeki ADC ye aktarılır. C4 ü boşaltan ise R6 direncidir.

ADC nin C4 üzerinden ölçtüğü gerilim değeri nem sensörünün direnci ile değişir. Bu değişim devrenin AC modeli üzerinden eşitliğe dökülebilir. Bu eşitlik aşağıdaki gibidir.

Eşitlikteki GAIN PGA kazancı, VALUE ADC ölçüm değeri, V ise 1N4148 diyodunu ileri yöndeki gerilimidir. Eşitlik programda değişkenlerine göre hesaplandığında o anki nem sensörü değeri bulunabilir.

NOT: PGA girişinde Vdd/2 kadar ofset olduğu için PGA referansını AGND olarak ayarlayın ve AGNDBypass parametresini aktif edin. ADC referansınıda 0-5V olarak Ref MUX parametresinden ayarlayın.

Tablonun okunması:

Nem sensörünün datasheettinde verilen direnç tablosu PSoC programı içerisinde 2 boyutlu bir dizinin içerisinde tutulmaktadır. Hesaplanan direnç değerine karşılık gelen RH değeri ise tablodan elde edilir. RH değerinin elde edilmesi için gereken sıcaklık değişkeni ise DS1621 üzerinden I2C ile elde edilir.

Tabloda bulunmayan RH ve sıcaklık değerleri ise programda yakınsama ile elde edilir.

Örneğin: sıcaklık 28°C, hesaplanan direnç değeri ise 50KΩ olsun. Bu durumda 25°C ve 30°C sütunları kullanılarak orantı yardımıyla 28°C sütunu elde edilir. Bu sütun da her sütun gibi %5 lik adımlar ile oluşturulur. Bu işlemden sonra direnç değerinin hangi %5 lik aralıkta olduğu bulunur. Sonrasında ise orantı yardımıyla tam RH değeri hesaplanır.

Sıcaklığın ölçülmesi:

Sıcaklık değeri yukarıdaki devre ile DS1621 üzerinden elde edilir.

LCD de gösterme:

2×16 lık bir LCD yukarıdaki gibi bağlanmalıdır. LCD üzerinde sıcaklık ve nem bilgisi görülecektir. Ayrıca sıcaklık okumada bir hata oluşması durumunda LCD ekranda hata mesajı belirir.

Yazılım:

Yazılımın büyük bir kısmını sensör direncinin hesaplanması ve ADC filtreleme oluşturur. ADC giriş gerilimin 10 kez örnekler ardından alınan örnekler ortanca filtresinden geçirilir ve son olarak değerlerin ortalaması alınır. Elde edilen değer sensör direncinin hesaplanmasında kullanılır. Sensör direnci hesaplandıktan sonra nemin belirlenebilmesi için tabloya başvurulur. Tabloyu okumak için gereken bir diğer değişkende sıcaklık bilgisi olduğu için I2C üzerinden DS1621 ile haberleşilerek sıcaklık bilgisi alınır. Sıcaklık ve sensör direnç bilgileri ile tabloya bakılır. Eğer elde edilen sıcaklık bilgisi ile ilgili bir tablo değişkeni yoksa ( 22 derece gibi ) ilk önce yakın komşuları kullanılarak ( 20 ve 25 derece ) yeni bir sıcaklık nem serisi elde edilir. Bu seri kullanılarak nem sensörü direncine en yakın bulunmaya çalışılır. Aynı şekilde yeni seri bu değeri ( 59K ) içermiyorsa en yakın komşuları kullanılarak ( %55 ve %60 ) nem değeri hesaplanır.

Devre şeması:

VS-H25K5A (nem sensörü datasheeti)

PSoC Designer Project (dosya uzantısını .rar olarak değiştirin. Bir PSoC designer 5 projesidir)

Kategoriler:Donanım/Yazılım Etiketler:

Freelance nedir?

25 Eylül 2011 Yorum bırakın

Freelance’ın kelime anlamı kendi hesabına çalışandır. Freelance, belirli bir iş için bireysel olarak proje bitimine kadar bir firma veya kişi veya kurum adına önceden kararlaştırılmış bir ücret karşılığında çalışan deneyimli kişidir. Bu tip çalışma şekline ise Freelance Çalışma denir.

Freelance çalışanlar, evden çalıştıkları ve giderlerin az olmalarından dolayı, işverenin dışarıya çok büyük ücretlerle yaptırabileceği bir işi daha az bir ücret karşılığında yaparlar. Bu yüzden işveren için freelance çalışma hem maliyet hemde birebir görüşerek çalışma imkanı tanıdığından büyük bir avantajdır.

Freelance çalışanın ödemesi; iş bitiminde, saat başına, peşin veya belirli bir yüzdesi peşin kalanı iş bitiminde olacak şekilde yapılabilir. Projenin tüm hakları işveren ile freelance çalışan arasındaki anlaşmaya bağlıdır.

Alçak geçiren sayısal filtre

25 Eylül 2011 3 yorum

Yukarıdaki devre alçak geçiren bir filtredir. Mesela ADC gibi analog bir girişin önüne koyularak, işaret ADC ye girmeden önce filtrelenebilir fakat bu işlem R ve C elemanları kullanılmadan yazılımsal olarak da yapılabilir.

Çok fazla detayına inmeden yazılımsal olarak alçak geçiren bir filtre nasıl yapılır bunu anlatmaya çalışayım.

Yukarıdaki devreyi bir gerilim bölücü olarak düşünüp çıkışındaki ( mavi nokta ) gerilimi veren matematiksel ifadeyi yazarsak.

Burada, Vout çıkış gerilimini ( mavi nokta ), Vin giriş gerilimini ( kırmızı nokta ), R dirençi, Xc ise kapasitif endüktansı temsil eder. Buradan s domain e geçersek. Bu ifade aşağıdaki gibi olacaktır.

Bu eşitlik devrenin s domain deki ifadesidir. İfade için bilinear transfor kullanırsak, s yerine

ifadesini yazmamız gerekir. Burada T örnekleme periodudur.

Bu denklemi ayrık zamanda ( discrete time ) yazarsak

ifadesi elde edilir. Burada y filtrenin cevabı, x ise ADC değeridir. [n] şimdiki örneği, [n-1] ise bundan bir önceki örneği ifade eder.

Buradan yola çıkarak kesim frekansı yaklaşık 60Hz olan bir filtre tasarlayalım:

R yi 1K seçersek 60Hz için C 2,65µF dır. Örnek alma zamanını da 1.6ms ( 625Hz) seçersek yukarıdaki denklem

şeklini alır. Burada x[n] ADC nin şuanki değerini, x[n-1] ADC nin bir önceki aldığı değeri, y[n-1] ise filtrenin bir önceki değeri temsil eder.

Filtrenin katsayıları reel sayılar olduğundan floating point bir işlemci ile rahatlıkla hayata geçirilebilir. Fixed point bir işlemci kullanılacaksada hesaplamanın daha hızlı yapılabilmesi için Q formatları ( Q15 veya Q16 ) kullanılabilir.

Filter excel dosyası içerisindeki 60Hz filtre simulasyonu ile kabaca filtrenin nasıl çalıştırığına göz atılabilir. Excel dosyasının ilk sayfasında simulasyon bulunmaktadır. Bu sayfada Fgiriş olarak verilen değer değiştirilerek filtrenin farklı giriş frekanlarına cevabı sayfaya eklenmiş genlik-zaman grafiği ile izlenebilir. Giriş frekansı arttıkça filtrenin çıkış genliğini azalttığı görülmektedir.

Excel dosyanın diğer bir sayfasında ise filtrenin hesabı yer almaktadır. İstenilen kesim frekansı ve örnekleme periodu girilerek filtrenin katsayıları hesaplanabilir.

Ortanca filtresi ( median filter )

14 Eylül 2011 5 yorum

Ortanca filtresi, özellikle görüntü işlemede sıklıkla kullanılan bir filtredir. Görüntüyü keskinleştirmek veya gürültüyü azaltmak için kullanılır fakat daha basit işler içinde kullabilir. Bunu bir örnekle anlatalım.

Gürültülü ortamda ADC okuma işinde uygulanan en yaygın yöntemlerden biri; okunan değerleri bir diziye yerleştirmek ve n kadar okuma sonunda bütün değerlerin ortalamasını almaktır. Fakat bu yöntem gürültünün geniliğine ve n sayısına göre sonucu gerçek değerden saptırır.

ADC girişine uyguladığımız gürültülü gerilimin 1000 değeri civarında olması gerektiğini ve 6 adet örnek sonunda da tüm değerlerin ortalamasını aldığımızı düşünelim ve bu 6 değer içerisinde de 2 adet gürültülü peak değeri olsun.

ADC nin aldığı değerlerin ise sırasıyla 996, 1718, 1002, 993, 1692, 1003 olduğunu düşünelim. Değerlere şöyle bir göz attığımızda 1718 ile 1692 nin gürültü olduğunu veya yanlış ölçtüğünü rahatlıkla söyleyebiliriz. Diğerleri ise asıl olması gereken 1000 değerinden çok az sapmıştır ve bunlarıda ölçüm hatası olarak adlandırabiliriz. Bu 6 sayının ortalamasını aldığımızda ise 1234 sayısını elde ederiz. Yani 6 adet okuma sonunda filtrelenmiş değer 1234 dür. Birde ortanca filtresini uygulayarak bakalım.

Sayıları tekrar yazarsak 996, 1718, 1002, 993, 1692, 1003 . Bu sayıları 3 erli gruplar halinde ele alıp her 3 erli grubun ortancasını asıl sayı ile yer değiştirelim. Yanlız ilk ve son sayılar için kendilerini birer kez daha yazarak 3 er grup oluşturacağız.

1. gurup: ilk sayı 2 kez yazılarak 996, 996, 1718 bu üç sayının ortancası 996 dır. O halde ilk sayının yeni değeri ( değişmedi ) 996 dır.

2. gurup: 996, 1718, 1002 bu üç sayının ortancası 1002 dır. O halde ikinci sayının yeni değeri ( değişti ) 1002 dir.

3. gurup: 1718, 1002, 993 bu üç sayının ortancası 1002 dır. O halde üçüncü sayının yeni değeri ( değişmedi ) 1002 dir.

4. gurup: 1002, 993, 1692 bu üç sayının ortancası 1002 dır. O halde dördüncü sayının yeni değeri ( değişti ) 1002 dir.

5. gurup: 993, 1692, 1003 bu üç sayının ortancası 1003 dür. O halde beşinci sayının yeni değeri ( değişti ) 1003 dür.

6. gurup: son sayı 2 kez yazılarak 1692, 1003, 1003 bu üç sayının ortancası 1003 dür. O halde son sayının yeni değeri ( değişmedi ) 1003 dür.

Buna göre 996, 1718, 1002, 993, 1692, 1003 sayılarının yeni değerleri 996, 1002, 1002, 1002, 1003, 1003 dür. Görüldüğü üzere gürültüden kaynaklı 1718 ve 1692 sayıları kaybolmuştur. Yeni değerlerin ortalaması ise 1001,3 dür.

Değerleri ortanca filtresine sokmadan önce ortalama 1234 idi, ortanca filtresi sonucundaki ortalama ise 1001,3 oldu. Görüldüğü gibi ortaca filtresinden sonra değerlerin ortalamasını almak ile değerlerin ortalamasını doğrudan almak arasında ciddi bir fark var.

Ortanca filtresi dokunmatik ekran ve dijital terazi uygulamalarında sıklıkla kullanılmaktadır.

Örnek bir C kodu aşağıdaki gibidir.

#define ADC_SAMPLE_PIECES     10

unsigned int wADCValues[ADC_SAMPLE_PIECES];

unsigned int wGetMedianFilteredResult(unsigned int *p)
{
char cResult;
unsigned char i;
unsigned int wLastValue;
unsigned int wFirstValue;
unsigned int wReturned;
unsigned int MedianFilterBuffer[ADC_SAMPLE_PIECES];
wLastValue=*(p+ADC_SAMPLE_PIECES-1);
wFirstValue=*p;

for (i = 0; i < ADC_SAMPLE_PIECES; i++) {

 if(i==0) {
  cResult=0;
   if(wFirstValue<*(p)) cResult++;
    else cResult–;
   if(wFirstValue<*(p+1)) cResult++;
    else cResult–;
   if( (wFirstValue==*(p))||(wFirstValue==*(p+1)) ) MedianFilterBuffer[i]=wFirstValue;
    else if(cResult==0) MedianFilterBuffer[i]=wFirstValue;
  cResult=0;
   if(*(p)<wFirstValue) cResult++;
    else cResult–;
   if(*(p)<*(p+1)) cResult++;
    else cResult–;
   if( (*(p)==*(p+1))||(*(p)==*(p+1)) ) MedianFilterBuffer[i]=*(p);
    else if(cResult==0) MedianFilterBuffer[i]=*(p);
  cResult=0;
   if(*(p+1)<wFirstValue) cResult++;
    else cResult–;
   if(*(p+1)<*(p)) cResult++;
    else cResult–;
   if( (*(p+1)==wFirstValue)||(*(p+1)==*(p)) ) MedianFilterBuffer[i]=*(p+1);
    else if(cResult==0) MedianFilterBuffer[i]=*(p+1);
  p++; continue;
 }

 if(i==ADC_SAMPLE_PIECES-1) {
  cResult=0;
   if(*(p-1)<*(p)) cResult++;
    else cResult–;
   if(*(p-1)<wLastValue) cResult++;
    else cResult–;
   if( (*(p-1)==*(p))||(*(p-1)==wLastValue) ) MedianFilterBuffer[i]=*(p-1);
    else if(cResult==0) MedianFilterBuffer[i]=*(p-1);
  cResult=0;
   if(*(p)<*(p-1)) cResult++;
    else cResult–;
   if(*(p)<wLastValue) cResult++;
    else cResult–;
   if( (*(p)==wLastValue)||(*(p)==wLastValue) ) MedianFilterBuffer[i]=*(p);
    else if(cResult==0) MedianFilterBuffer[i]=*(p);
  cResult=0;
   if(wLastValue<*(p-1)) cResult++;
    else cResult–;
   if(wLastValue<*(p)) cResult++;
    else cResult–;
   if( (wLastValue==*(p-1))||(*(p+1)==*(p)) ) MedianFilterBuffer[i]=wLastValue;
    else if(cResult==0) MedianFilterBuffer[i]=wLastValue;
  p++; continue;
 }

 cResult=0;
  if(*(p-1)<*(p)) cResult++;
   else cResult–;
  if(*(p-1)<*(p+1)) cResult++;
   else cResult–;
  if( (*(p-1)==*(p))||(*(p-1)==*(p+1)) ) MedianFilterBuffer[i]=*(p-1);
   else if(cResult==0) MedianFilterBuffer[i]=*(p-1);
 cResult=0;
  if(*(p)<*(p-1)) cResult++;
   else cResult–;
  if(*(p)<*(p+1)) cResult++;
   else cResult–;
  if( (*(p)==*(p+1))||(*(p)==*(p+1)) ) MedianFilterBuffer[i]=*(p);
   else if(cResult==0) MedianFilterBuffer[i]=*(p);
 cResult=0;
  if(*(p+1)<*(p-1)) cResult++;
   else cResult–;
  if(*(p+1)<*(p)) cResult++;
   else cResult–;
  if( (*(p+1)==*(p-1))||(*(p+1)==*(p)) ) MedianFilterBuffer[i]=*(p+1);
   else if(cResult==0) MedianFilterBuffer[i]=*(p+1);
 p++;
}
wReturned=0;
for (i = 0; i < ADC_SAMPLE_PIECES; i++) wReturned+=MedianFilterBuffer[i];
wReturned/=ADC_SAMPLE_PIECES;

return wReturned;
}

Yukarıdaki kodlarda ADC_SAMPLE_PIECES, ADC den alınan örnek sayısıdır. Bu değer değiştirilerek filtrasyon genişliği artırılabilir. unsigned int wADCValues[ADC_SAMPLE_PIECES] ise ADC sonuçlarının tutulduğu tampon bellektir. Her ADC ölçüm sonucunu bu alana kaydırmalı olarak kaydetmek gerekir. unsigned int wGetMedianFilteredResult(unsigned int *p) fonksiyonu ise işaret edilen tampon bellekteki değerleri ortanca filtresine tabi tutup sonucun ortalamasını geri döndürür.