C18 Diliyle Robot Programlama – ADC Okuma

ADC (Analog to Digital Converter) okumanın mantığı elimizde analog halde bulunan voltaj değerlerini ona karşılık gelecek dijital değerlere çevirip işlem yapmaktır. Benim kullandığım    PIC18F4585 mikrodenetleyicisi içerisinde ADC modülü bulunmakta. Bu modülü kullanarak şu an mikrodenetleyicimin üzerinde bulunduğu kartan analog değer okuma işlemini yapacağım.

Kart üzerindeki bağlantıları kontrol ettiğimizde analog sinyal üreteceğimiz birimin mikrodenetleyicinin 2. pinine bağlı olduğunu görüyoruz. Datasheet’te bu pin AN0 girişine karşılık gelmekte.

Amacımız bu pin üzerinden açacağımız bir kanalla ADC fonksiyonlarını kullanarak dijital çıkış değerleri okumak ve bu dijital çıkış değerlerini Adım Büyüklüğü (1 LSB) ile çarparak    analog voltaj değerine karşılık gelen dijital voltaj değerini bulmak.

Önce adım büyüklüğünün nasıl hesaplandığına değinmek gerekir. Adım büyüklüğü, referans aldığımız voltaj değerleri arasındaki büyüklüğü, hesaplayabildiğimiz maksimum aralık   sayısına bölerek elde ettiğimiz bir değerdir.

{Adim Buyuklugu(1 LSB)} = \frac {{V}_{ref+} + {V}_{ref-}}{2^n} 

Formüldeki n sayısı kullandığımız ADC modülünün çözünürlüğünü ifade etmektedir. Yani kabaca tanımlarsak. Ben analog kaynağımın en düşük ve en yüksek gerilimlerini ölçüyorum. Bunlardan en düşüğü (Vref-) en büyüğü (Vref+) oluyor. Daha sonra ADC modülüm kaç bitlik ise (çözümürlük) referans farkını bu bitlerle ifade edebildiğim değer sayısına bölüyorum. Ben elimdeki ADC kaynağının gerilimlerini Vref+ = 3.97 V ve Vref- = 0 V olarak ölçtüm. Elimdeki ADC modülü 10 bitlik (Datasheet’te bu bilgi yer alıyor), dolayısıyla ben 10 bit ile 2^10 = 1024 tane değer ifade edebilirim. Adım büyüklüğüm ise;

{Adim Buyuklugu(1 LSB)} = \frac {3.97V - 0V}{1024} = 0.003876953125 

Bu değeri kod içerisinde kullanacağım. O yüzden hesapladım.

Kodları yazarken “adc.h” kütüphanesinden faydalanacağız. Bu kütüphaneden kullanacağımız fonksiyonlar;

  • OpenADC(): Bu fonksiyon ADC modülünü kullanıma açmak için kullanılır. 2 ya da 3 adet parametre alır. Frekans, referans değerleri, ADC kesmesi oluşturma, analog veya dijital girişleri ayarlama gibi işlemleri yapmamıza olanak tanır.
  • SetChanADC(): Bu fonksiyon tek parametre olarak kullanacağımız kanalı alır. Hangi kanal üzerinden okuma yapmak istiyorsak (Biz AD0 kanalını kullanacağız) o kanalı kullanıma açtırır.
  • ConvertADC(): Seçilen kanal üzerinden analog-to-digital convert işlemini gerçekleştir. Bu işlem sonucunda elde bir dijital değer oluşur.
  • ReadADC(): ConvertADC() fonksiyonu ile oluşturulan dijital değeri döndürür. Bu değeri herhangi bir tamsayı değişkenine atayabiliriz.
  • CloseADC(): ADC modülünü kullanıma kapatır.

(Bu fonksiyonların geniş tanımları “C18 Kütüphaneleri ve Özellikleri” bölümünde anlatıldı)

Programda yapacağımız şey şu olacak. Benim elimde ayarlanabilir bir ADC kaynağı var,              düğmesini çevirdikçe voltajı da değişiyor. Ben bu ADC kaynağının düğmesini çevireceğim      ve elde ettiğim voltaj değeri, belirlediğim kontrol değerlerine eşit oldukça ledlerden birini yakacağım. (Değerleri görüntüleyebileceğim bir ekran donanımına sahip olmadığım için değer kontrolünü program içerisinde yapıp uygun ledleri yakacağım).

Daha önceden ölçüm yaptığım için değerlerin 0 – 3.97 arasında değişmesi gerektiğini   biliyorum. Buna göre dijitale çevirdiğim voltaj değerleri;

  • 0.5 – 0.7 arasında ise; RB5 pinine bağlı led yanacak.
  • 2.4 – 2.6 arasında ise; RB4 pinine bağlı led yanacak.
  • 3.8 – 4    arasında ise; RB3 pinine bağlı led yanacak.

Program kodları aşağıdaki gibi olacak;

<pre>/*
 * File: main.c
 * Author: cagatay
 *
 * Created on 23 Ocak 2012 Pazartesi, 13:19
 */

#include <p18f4585.h>
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <adc.h>

#pragma config OSC = HS, WDT = OFF, LVP = OFF

void main(void) {
     unsigned int result;
     float voltage;

     TRISB = 0;

     OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST , ADC_CH0 &
             ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS, 15);

     SetChanADC(ADC_CH0);
     Delay1KTCYx(5);

     while(1) {
          PORTB = 0;

          ConvertADC();

          while( BusyADC() );

          result = ReadADC();
          Delay1KTCYx(5);

          voltage = 0.003876953125 * result;

          if(voltage > 0.5 && voltage < 0.8)
               PORTBbits.RB5 = 1;
          Delay1KTCYx(5);

          if(voltage > 2.4 && voltage < 2.5)
               PORTBbits.RB4 = 1;
          Delay1KTCYx(5);

          if(voltage > 3.9 && voltage < 4)
               PORTBbits.RB3 = 1;
          Delay1KTCYx(5);

     }
     CloseADC();

     return;
}

Gerekli ayarlamalar yapıldıktan sonra 17 ve 18. satırda kullanacağımız değişkenleri tanımlıyoruz. result değişkeni ReadADC() fonksiyonu ile döndürülen değeri tutacak. Bu fonksiyon bize analog-to-digital converter işleminin sonucu olan  bir tamsayı değeri döndürür. Bu değeri Adım Sayısı ile çarpıp voltage değişkenine atacağız.

Satır 20’de ledleri yakacağımız B portunu çıkış için ayarlıyoruz.

Satır 22 ve 23’te OpenADC() fonksiyonu ile ADC modülünü nasıl kullanacağımızı belirtiyoruz. Bu fonksiyon 2 kısımdan oluşur. Bu iki kısım birbirinden virgül ile ayrılırken, aynı kısma ait belirtilen değerler “&” operatörü ile birbirine bağlanır.

  • ADC_FOSC_RC: Dahili osilatör frekansını kullan.
  • ADC_RIGHT_JUST: Elde ettiğin değeri düşük anlamlı bitten başlayarak yaz.
  • ADC_CH0: ADC okuma için AN0 pinini kullan.
  • ADC_INT_OFF: ADC işlemi sonucu interrupt oluşmasın.
  • ADC_VREFPLUS_VDD: Yüksek voltajı kaynağın maksimum voltajı olarak al.
  • ADC_VREFMINUS_VSS: Düşük voltajı kaynağın minimum voltajı olarak al.
  • 14: Bu değer hangi kanalların analog hangi kanalların dijital sinyalle işlem yapacağını gösterir.
    Elimizde okuma yapmak için 10 adet kanal bulunmakta. Aşağıdaki tabloyu baz alarak kanalların  analog/dijital olma durumlarını belirlemiş oluruz.

Bu tabloya göre 0,1,2,3,4 değerlerinde tüm girişler analog olacak. Sonraki değerlerden itibaren büyükten küçüğe doğru sırasıyla kanallar dijitale dönmeye başlıyor. 16 eğerinde ise tüm kanallar dijital değerlerle işlem görecek.

Satır 25’te SetChanADC() fonksiyonu ile de hangi kanalı kullanacağımızı belirtebiliriz. Ama daha önce OpenADC() fonksiyonunda bunu belirttiğimiz için bu fonksiyonu yazmasakta programımız düzgün kanaldan işlem yapardı.

Satır 31’de ConvertADC() fonksiyonu ile AD0 kanalından dijital değeri okuyoruz.  Daha sonra bu değeri satır 36’da ReadADC() fonksiyonu ile result değişkenine atıyoruz. Şu anda elimizde henüz anlamlandıramadığımız bir dijital değer var. Bu değeri yukarıda bahsedilen formül uyarınca elimizdeki Adım Sayısı ile çarparsak voltmetre ile ölçtüğümüz değere paralel bir değer elde etmiş oluruz. (Satır 39)

Satır 41, 45 ve 49’da ise başta bahsettiğim şekilde  kaynağın voltajını değiştirirken belirlediğim kontrol değerlerinde ledlerin yanmasını sağlıyorum. Değişen voltaj değerleri ufak bir ekran kullanılarak veya PicKit2 üzerinden debug işlemi yapılarak da okunabilir.

Kendim ölçtüğüm voltaj değerleri ile ADC modülü tarafından okunan voltaj değerlerinin karşılaştırılması ise şöyle;

  • Voltmetre: 0,002V       ADC: 0.5V – 0.7V arası
  • Voltmetre: 2,21V           ADC: 2,4V – 2,6V arası
  • Voltmetre: 3,9V             ADC: 3,8V – 4V arası

 

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s