Analog to Digital Converter'a (ADC) Giriş ve Potansiyometre Uygulaması

Günlük hayatta etrafımızda gerçekleşen olaylar süreklilik arz eder yani analogtur. Bu verilerin ölçümlerde belirli yollarla dijitize edilmesi gerekir. Yani analogtan belli örnekler alarak dijitale çevirilir, bu da sinyallerle 0 ve 1’lerle işlem yapılması anlamına gelir. ADC'ler de analogtan dijitale çevrim yapan birim olarak bir mikrodenetleyicinin en önemli başlıklarından biridir.


Stm32’de ADC 3 şekilde kullanılabilir. Bunlardan biri pollingtir. Bu kullanımda dönüştürme (çevrim) süresi boyunca farklı bir işlem yapılamaz ve çevrimin bitmesi beklenir. Polling, tek ölçüm gereken ve çok hızlı ölçüm alınması gerekmeyen durumlarda kullanılır. Diğer yöntem interrupt olarak kullanmaktır. Bu yöntemde mikrodenetleyici ADC’ye komut verir ADC dönüşüm işlemlerini yaparken kendisi diğer işlemleri yapmaya devam eder, dönüştürme işleminin sonunda bir interrupt (kesme) meydana gelir ve kesme sırasında çalışacak fonksiyon çağırılır. Bu kullanımda ADC dönüştürme yaparken beklemek gerekmez. Diğer ve son kullanım ise DMA’dır. Bu kullanımda da yine mikrodenetleyici diğer işlemleri yaparken dönüştürmeye devam eder fakat interrupt kullanımından farkı DMA’da elde edilen dönüşüm verileri hafızaya kaydedilir


STM32F100xx ADC'nin bazı özellikleri şu şekildedir:

  • 12 bitlik çözünütlüğe sahiptir bu da 2^12 -1’den 0 ile 4095 arasında analog değerleri kapsar. (Arduino'da bu 10 bittir yani 2^10-1 den 0 ile 1023 arası okuma yapılabilir.)

  • Blok diyagramda da dörüldüğü gibi 16 harici 2 tane de dahili kaynaktan gelen

analog sinayallerin ölçülmesine izin veren toplam 18 tane çoklanmış kanala sahiptir.

  • Farklı modlarda kaynaktan okuma yapabilir bunlar tek, sürekli, tarama veya süreksiz moddur. (Single, continuous, scan or discontinuous mode.)

  • ADC’nin okumasının sonucu sola veya sağa hizalı olacak şekilde 16 bitlik registerlarda saklanır.

  • End of Conversion, End of Injected conversion and Analog watchdog event sonunda interrupt gerçekleştirilebilir.

  • ADC dönüştürme (çevrim) zamanı 1.17 µs at 24 MHz’dir. 2.4-3.6 V ile beslenmesi gerekir.

  • Blok diyagramda da görüldüğü gibi dahili ve harici ADC’ler (ADCx_IN0, ADCx_IN1,….ADCx_IN15, Temp sensor, VREFINT) geldiğinde analog multiplexer ile seçilir ve Regular Channels’a gelir. Burdan da data registera iletilir. Ayrıca End Of Conversion ile interrupt kullanımı da sağlanmaktadır.



STM32'de ADC, ADON bitinin aktif duruma getirilmesiyle kontrol edilir. Timing diyagramında da görüldüğü gibi, ADON biti aktif haldeyken dönüştürme sinyali ilk geldiğinde, dönüşüme başlamadan önce tSTAB adı verilen kararlılık süresi geçmektedir. Bu süre doğru dönüşüm sağlanması için gerekli görülmüştür. Dönüşüm bitince EOC biti temizlenir, ve tekrar dönüştürme sinyali geldiğinde diğer ADC dönüşümü başlar.




ADC çevrimlerinde çözünürlük hassas sonuçlar için önemlidir. ADC için adım aralığı ADC’nin ölçebileceği en yüksek ve en düşük gerilim değerine (Vmax-Vmin)/(2^n-1) şeklinde formülle bulunur. Formülde görüldüğü üzere n yani çözünürlük değeri (bit) arttıkça adım aralığı düşmekte yani ölçüm daha hassas olmaktadır. En düşük volt değeri ADC için 0 olarak alınır. Bu uygulamada da Vmax değeri 2.98 Volt olarak potansiyometre üzerinden ölçülmüştür. 12 bitlik ADC kullanıldığı için n=12’dir. Yani bir adımda okunacak değer formülden 7,27x 10^-4 Volt olarak hesaplanır.



Bu uygulamada C portunun 0. pininden yani C0'dan potansiyometreyle ADC okuması yapılmıştır. Okunan değer 0-4095 arasındadır. Bu değer daha sonra volta çevrilmiş ve volt aralıklarına göre de ledler yanıp söndürülmüştür. Dikkat edilmesi gereken yerlerden biri C0 channel 10'a bağlıdır. Pinlere göre bağlı oldukları channellar değişiklik göstermektedir bunlar kartın user manuelinden pinout tablosuna bakılarak ayarlanabilir.



Malzemeler:


  • Jumper Kablolar

  • 3 adet Led

  • Potansiyometre

  • STM32VL Discovery


Devre Şeması ve Kod:





#include "stm32f10x.h"  // Device header



void gpioConfig(); // giris cikis pinlerinin ayarlanmasi fonksiyonu  
void adcConfig(); // ADC'nin ayarlanmasi fonksiyonu 
void delay(); // gecikme fonksiyonu 


uint16_t readADC(); //ADC çevrim yaparken calisacak fonksiyon 

uint16_t adcValue=0;
float voltage;

int main (){
  
	gpioConfig();
	adcConfig();

	
	while (1){
		
	
	   adcValue=readADC(); //ADC'den okunan deger
		 voltage=adcValue*(2.98/4095); // okunan degeri tekrar volta cevirmek (adcValue*(Vmax-Vmin)/(2^n-1))
		  
		if(voltage<1.5){ //volt degeri 1.5 altindaysa B portunun 0. pini yansin sönsün 
		   
			GPIO_SetBits(GPIOB,GPIO_Pin_0 );
			delay(360000);
			GPIO_ResetBits(GPIOB,GPIO_Pin_0);
			delay(360000);
	}
		
		
		else if (voltage>=1.5 && voltage<2.5){ //volt degeri 1.5 ve 2.5 arasindaysa B portunun 1. pini yansin sönsün 
		  
     GPIO_SetBits (GPIOB,GPIO_Pin_1);
			delay(360000);
    GPIO_ResetBits(GPIOB,GPIO_Pin_1);
			delay(360000);			
		}
		
		else if(voltage>=2.5){ //volt degeri 2.5 üstündeyse B portunun 2. pini yansin sönsün 
		
		 GPIO_SetBits (GPIOB,GPIO_Pin_2);
			delay(360000);
     GPIO_ResetBits(GPIOB,GPIO_Pin_2);
			delay(360000);
		
		}
		
		else { // yukardaki sartlarin hicbiridegilse ledler sönüyor
		  GPIO_ResetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2);
		}
	
	
	}


}


void gpioConfig(){

	GPIO_InitTypeDef GPIOInitStructure; // GPIO ayarlamalari icin struct 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//Ledler icin B portu clock hatti aktif edildi 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // Potansiyometre için C portu clock hatti aktif edildi
	
	GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // ledler push pull output 
	GPIOInitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2; // 0 1 ve 2. pinler ledler icin 
	GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz; // hiz ayari 
	
	GPIO_Init(GPIOB,&GPIOInitStructure); // B portu icin ayarlamalarin yapildigi bildiriliyor
	
  GPIOInitStructure.GPIO_Mode=GPIO_Mode_AIN;// analog veri okunacak analog input
	GPIOInitStructure.GPIO_Pin=GPIO_Pin_0; // C portu 0. pin ADC çevrimi yapilacak olan yer 
	GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz; // input olarak ayarlandigi icin hiza gerek yok 
	
	GPIO_Init(GPIOC,&GPIOInitStructure); // C portu icin ayarlamalarin yapildigi bildiriliyor 
	


}

void adcConfig(){
 
	ADC_InitTypeDef ADCInitStructure; //ADC ayarlamalari icin struct 
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); // ADC'nin clock hattini aktif ettik ve ADC1'i kullanildi
	
	ADCInitStructure.ADC_ContinuousConvMode=ENABLE; //sürekli çevrim yapsin 	
  ADCInitStructure.ADC_DataAlign=ADC_DataAlign_Right; // most significant bitin saga dayali olacagi bildirildi
	ADCInitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None; // trigger kullanilmiyor 
	ADCInitStructure.ADC_Mode=ADC_Mode_Independent; // single mod okuma yapilacagi icin independent ayarlandi
  ADCInitStructure.ADC_NbrOfChannel=1; // 1 tane adc oldugu icin
	ADCInitStructure.ADC_ScanConvMode= DISABLE; // multichanel ADC kullanimi yapilacaksa aktif edilir diger verilerin cevrimi yapilacagi zaman
	
	ADC_Init(ADC1,&ADCInitStructure); // ADC'nin ayarlarinin yapildigi bildiriliyor 
	ADC_Cmd (ADC1,ENABLE); //ADC1 aktif ediliyor 
	

}

uint16_t readADC(){ // ADC'nin okuma yapacagi fonksiyon

  ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5); // ADC1,C0 ADC Channel 10'a bagli,1 adet ADC okumasi yapildi, dogruluk artmasi icin kac cyle'da okuma yapilsin parametreleri
	ADC_SoftwareStartConvCmd(ADC1,ENABLE); // okumanin baslayacagi bildiriliyor
	
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);// çevrim devem ediyorsa burda kalsin. EOC 
	
	return ADC_GetConversionValue(ADC1); // çevrim bitince sonucu döndür
	


}

void delay(uint32_t time){

  while(time--);

}


Son Paylaşımlar