Bilal Ünal

Arduino registerler ile ADC

Merhaba. Bu yazıyı yazmadan önce bu dönem aldığım mikroişlemci dersinin final sınav sonuçlarının girilmesini bekledim. Harf notu istediğim gibi gelince bi hızla bu yazıyı yazmaya karar verdim. Final sınavına hazırlık sürecinde bu konuyla ilgili türkçe kaynak bulamamıştım. Benimle aynı durumda olan arkadaşlar varsa eğer eminim bu yazı işlerini görecektir. Bu yazıda Arduino kaydedicilerini kullanarak analog veriyi dijital veriye dönüştüreceğiz.

E bunu neden kaydedici kullanarak yapayım ki?Bu dönüştürme işlemini benim yerime yapan fonksiyonlar var zaten!!?

Evet var hatta yazacağımız 10 satır kodun yaptığını tek satırda halledebilecek bir fonksiyon var. Ancak, analog sinyal işleme fonksiyonu, doğruluk, hız ve istenen çıktı açısından oldukça verimsizdir. Bu sebepten dolayı ADCyi kullanacağız. Başlayalım.

Analog ve Dijital Arasındaki Fark

Dijital veri günlük hayattan da bildiğimiz gibi 0/1, kısaca var veya yok şeklindeki sinyallerdir. Fark çok keskindir. Analog sinyali ise bir rengin tonları şeklinde ifade edebiliriz. Günlük hayattan örnek verecek olursak bir sıcaklık sensörünün bize vereceği çıktı dijital olamaz. Çünkü sıcaklık vardır veya yoktur şeklinde bir ölçüm mantıklı olmaz ya da mesela hava sıcak veya değil diyebilirdik ama kaç derece diyemezdik. Analog girişler bize bu fırsatı sunuyor. Arduinoda bulunan analog girişlerden 0 ile 1023 arasında bir değer okuyabiliriz. Yani sıcaklık sensöründen 1024 farklı değer okuyabiliriz.

Analog Sinyali Dijitale Çevirmek

Analog ve dijital arasındaki farkı anladık. Peki neden bu veriyi dönüştürmemiz gerekiyor? Direkt olarak analog veriyi kullanamaz mıyız? Bu sorunun cevabı hayır. Arduino analog sinyalleri işleyememektedir. Bu sebeple analog sinyallere karşılık gelen dijital değerlerin bulunması gerekir.

Şimdi öncelikle teorik olarak dönüştürme işlemini anlayalım ardından bir örnek üzerinden pratiğini yapacağız.

Analog Sinyali

Yukarıdaki resimde 0-5V arasındaki bir analog sinyalinin dijital karşılılıklarını görüyoruz. Yukarıda bahsettiğim gibi 0 ile 1023 arasında bir dijital veri elde edeceğiz. Örnek olarak;

  • 0V analog giriş = 0
  • 2.5V analog giriş = 512
  • 5V analog giriş = 1023

olarak çevirilecektir. Kısacası yapacağımız işlem 0V ve 5Voltu 0-1023 arasında oranlamak. Aşağıdaki fotoğrafı inceleyebilirsiniz.

Sensor Analog > ADC

ADC, ADCSRA, ADMUX

ADC Sheet

İncelemek isteyen olursa diye yukarıdaki resim Arduino içerisindeki ADCnin açık halidir. Üzerine tıklayıp büyük halini inceleyerek çalışma mantığı hakkında bilgi sahibi olabilirsiniz.

Çevirme işlemi yapmak için arduinonun 3 adet registeri bulunuyor. Bunlar;

  • ADMUX(ADC Multiplexer Select Register)
  • ADCSRA(ADC Control & Status Register)
  • ADC(ADC Data Register)

Kısaca hangi registeri hangi amaçla kullanacağımızdan bahsetmek istiyorum.

ADMUX

Admux Register

Bu registerin açılımı “ADC Multiplexer Select”. Adından da anlaşılacağı gibi bir seçim işlemi yapacağız. Bu register;

  • Çevirme işlemi için kullanılacak analog portun seçilmesi(MUX3…MUX0)
  • Sonucun sola göre mi yoksa sağa göre mi saklanacağının seçilmesi(ADLAR)
  • Referans voltajın kaynağının seçilmesi için kullanılır.(REFS1,REFS0)

Mux

Bu registerin ilk 4 bitini (MUX3…MUX0) değiştirerek convert işleminin hangi pinden gelecek veri ile gerçekleştireceğini seçeceğiz. Bizim örneğimizde potansiyometre A0 pinine bağlı olacak, bu pini seçmeliyiz. Aşağıdaki tabloyu kontrol ettiğimizde A0 pinini seçmek için son 4 biti 0000 olarak set etmemiz gerekiyor.

Mux Bits

ADLAR

Bu bitten detaylı olarak bahsetmeyeceğim ve örnekte kullanmayacağım. Kısaca özet geçmek gerekirse çevirme işlemi tamamlandığı zaman sonuç 2 adet registerde saklanır(ADCH ve ADCL). Bu sonuç ya sola ya da sağa yaslanmış olabilir. ADLAR biti 1 ise, sola yaslanmış 0 ise sağa yaslanmış. Varsayılan olarak, bit temizlenmiş ve sağa yaslanmış haldedir. Detaylı bilgiye bu linkten ulaşabilirsiniz.

REFS

Reference Selection Bits yani referans seçme bitleri. Peki referans nedir? Neyi seçeceğiz? ADCnin ölçüm işlemini yapabilmesi bir referans veya karşılaştırma değerine ihtiyacı vardır. Çevirme işlemini yapmadan önce bir referans voltajı belirlememiz gerekiyor. ADC referans değeri ölçüm aralığını belirler. Örnek olarak sinyal seviyesinin 2V üzerine çıkmayacağını bildiğiniz bir ölçümde referans voltajını 5V yerine 2.5V olarak ayarlamak daha iyi bir çevirme işlemi yapmanızı sağlar. Aşağıdaki tabloya göre referans voltajınızı belirleyebilirsiniz. Ben örneğimde yalnızca REFS0 bitini set edeceğim. Bu şekilde AREF pinine uygulanan voltajı (0V-5V) referans olarak alacağım.

Refs Bits

ADCSRA

ADCSRA

2.registerin içeriğini yukarıdaki resimde görebilirsiniz. Bu registeri kullanarak ADCnin ayarlarını yapıp durumunu kontrol edeceğiz. Sırası ile tüm bitleri inceleyelim.

  • ADEN (ADC Enable) : Bu biti 1 yaparak ADCyi aktif hale getiriyoruz.
  • ADSC (ADC Start Conversion) : Çevirme işlemini başlatmak için kullanacağımız bit. 1 olarak set edersek ADC çevirme işlemine başlayacaktır, çevirme işlemi bittikten sonra Arduino bu biti 0 olarak atayacaktır. Bu yüzden bu biti çevirme işleminin tamamlandığını kontrol etmek için flag olarak kullanabiliriz.
  • ADATE (ADC Auto Trigger Enable) : Pek bilgim yok. Datasheetten baktığımda şöyle bir şeyle karşılaştım. “Bu bit 1 olarak set edildiği zaman Auto Trigger aktif hale gelir. ADC çevirme işlemine seçilen tetikleme sinyalinin pozitif kenarında başlayacaktır. Tetikleme sinyalinin kaynağı ADCSRB registerindeki ADC Trigger Select bitleri ile seçilir.”
  • ADIF (ADC Interrupt Flag) : Bu bit çevirme işlemi tamamlanıp data registerleri güncellendikten sonra ADC tarafından 1 olarak set edilir.
  • ADIE (ADC Interrupt Enable) : ADIE biti 1 olarak ayarlanırsa ADC kesmesi kullanılabilir. Not: ADIE biti dışında SREG registerinin Global interrupt enable biti de 1 olarak ayarlanmalıdır.
  • ADPS[2:0] (ADC Prescaler Select) : Bu 3 bit ADCnin clock sinyalinin frekansını ayarlamak için kullanılıyor. ADCnin maksimum çözünürlükte çalışabilmesi için, 50 kHz ila 200 kHz frekans sağlanmalıdır. Fakat kullandığımız sistemin clock frekansı genelde daha yüksektir. Benim örnekte kullanacağım Arduinonun frekansı 16MHz. Bizim sistem frekansını ADC için 50-200 kHz arasına düşürmemiz gerekiyor. Bu sebepten biraz matematik kullanarak bir prescaler değeri seçmemiz gerek. Örnek; 16MHz(Arduino Osilatör Hızı) / 128(Seçtiğim prescaler) = 125000Hz = 125kHz (50 ile 250 arasında yani bu prescaleri kullanabilirim)

ADCSRA Bits

ADC(ADC Data Register)

Çevirme işlemi tamamlandığında, sonuç 2 adet registerde saklanır. ADCL ve ADCH.

ADCH 2 MSB(most significant bits) tutar. Geriye kalan bitler ADCLde saklanır. ADCL okunduğunda, ADC registeri, ADCH okunana kadar güncellenmez. Bu registerde herhangi bir biti set etmeyeceğiz sadece okuma yapacağız. Bu konuda daha detaylı bilgi için şurayı inceleyebilirsiniz.

Örnek ADC projesi

Şimdi bir örnek üzerinden ilerleyerek ADCyi nasıl kullanacağımızı öğrenelim. Ben örnek olarak ledin parlaklığını potansiyometre üzerinden değiştirebileceğim bir proje yapacağım. Gerekenler;

  • 1 x Arduino UNO
  • 1 x Breadboard
  • 1 x 220 Ohm direnç
  • 1 x LED
  • 1 x 10k Ohm potansiyometre
  • 7 x Jumper erkek kablo

Bağlantılarım şu şekilde olacak;

Example Arduino Circ

Kodumuzu yazmaya başlayalım;

int ledPin = 9; //Ledimizi PWM pinlerinden herhangi birine bağlıyoruz(3,5,6,9,10,11)
 
void setup() {
  Serial.begin(9600); //Çevirdiğimiz değeri serial monitore yazdırmak için iletişimi başlatıyoruz.
  DDRB |= (1<<1); //Ledin bağlı olduğu pin OUTPUT olarak ayarlandı.
  ADMUX |= (1<<REFS0); //Referans voltajımızı seçtik.
  ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); //Yalnızca ADCyi aktif edip prescaleri seçtim.
}
 
void loop() {
  ADCSRA |= (1<<ADSC); //Çevirme işlemini başlattım
  while(ADCSRA & (1 << ADSC)); //Çevirme işlemi sonlanana kadar hiçbir işlem yapmamak için bir while döngüsü.
  Serial.println(ADC); //Çevirme işleminin sonucunu ekrana yazdırıyoruz.
  analogWrite(ledPin,map(ADC,0,1023,0,255)); //Elde ettiğim sonucu 0-255 arasında oranlayarak lede yazdım.
}

Çalıştırdıktan sonra serial monitör üzerinden kontrol edebilirsiniz.

Yazıyı burada sonlandırıyorum. Umarım yeterli olmuştur. Seneye bu dersi alttan alacak olan Abdullah, Behlül ve Savaş'a selamlarla 🙂

Edit : Abdullah, Behlül ve Savaş da dersi geçti 🙂