Demək olar ki, hər bir quraşdırılmış (embedded) tətbiqdə (proqramda) istifadə edilən ümumi xüsusiyyətlərdən biri ADC moduludur (Analoqdan Rəqəmsala çevirici). Bu Analoq-Rəqəm çeviricilər Temperatur sensoru, Tilt sensoru, Cərəyan sensoru, Flex sensoru və daha çox bu kimi analoq sensorlardan gərginliyi oxuya bilər. Beləliklə, bu dərslikdə biz Energia IDE (və ya Arduino İDE ) istifadə edərək Analoq gərginlikləri oxumaq üçün STM32F103C8-də ADC-dən necə istifadə edəcəyimizi öyrənəcəyik. Biz kiçik potensiometri STM32 Blue Pill lövhəsi ilə əlaqələndirəcəyik və Analoq pininə dəyişən gərginlik verərək, gərginliyi oxuyub 16×2 LCD ekranda göstərəcəyik.
Arduino və STM32F103C8-də ADC-nin müqayisəsi
Arduino lövhəsində 0V-5V giriş gərginliyi diapazonu ilə 6 kanal (Mini və Nano-da 8 kanal, Mega-da 16), 10 bitlik ADC var. Bu o deməkdir ki, o, 0 və 5 volt arasında olan giriş gərginliklərini 0 və 1023 arasındakı tam dəyərlərə uyğunlaşdıracaq. İndi STM32F103C8 olduqda, bizdə 10 kanal, 0V -3.3V giriş diapazonu olan 12-bit ADC var. O, 0 ilə 3,3 volt arasındakı giriş gərginliklərini 0 ilə 4095 arasında tam ədədlərə çevirəcək.
STM32-də ADC
STM32 mikrokontrollerləri,kontrollerə daxil edilmiş ADC SAR (successive approximation register) (ardıcıl yaxınlaşma reyestri) prinsipindən istifadə edir, onun vasitəsilə çecrilmə bir neçə mərhələdə həyata keçirilir. Dönüşüm addımlarının sayı ADC çeviricisindəki bitlərin sayına bərabərdir. Hər bir addım ADC saatı ilə idarə olunur. Hər bir ADC saatı nəticədən çıxışa bir bit istehsal edir. ADC-nin daxili dizaynı keçidli kondensator texnikasına əsaslanır. Əgər STM32-də yenisinizsə, STM32 ilə işə başlama təlimatımızı yoxlayın.
12-bit Resolution (dərəcələndirmə)
Bu ADC 10 kanallı 12 bitlik ADC-dir. Burada 10 kanal termini analoq gərginliyi ölçə biləcəyimiz 10 ADC pininin olduğunu nəzərdə tutur. 12-bit termini ADC-nin dəqiqliyini (resolution) nəzərdə tutur. 12-bit,2 üstü 10-un qüvvəti kimi anlamına gəlir və bu da 4096-dır. Bu, ADC-miz üçün nümunə addımların sayıdır, ona görə də ADC dəyərlərimizin diapazonu 0-dan 4095-ə qədər olacaq. Dəyər düsturla hesablana bilən hər addımda gərginliyin dəyərinə əsaslanaraq 0-dan 4095-ə qədər artacaq.
VOLTAGE / STEP = REFERENCE VOLTAGE / 4096 = (3.3/4096= 8.056mV) per unit.
Analoq Siqnal Rəqəmsal Formaya necə çevrilir
Kompüterlər yalnız ikili/rəqəmsal dəyərləri (1 və 0) saxlayır və emal edir. Beləliklə, sensorun volt olaraq çıxışı kimi analoq siqnallar emal üçün rəqəmsal dəyərlərə çevrilməlidir və çevrilmə dəqiq olmalıdır.STM32-nin analoq girişlərinə ,analoq gərginliyi verildikdə, analoq dəyər oxunur və tam dəyişəndə saxlanılır. . Saxlanılan analoq dəyər (0-3.3V ) aşağıdakı düsturdan istifadə edərək tam ədədlərə (0-4096) çevrilir:
INPUT VOLTAGE = (ADC Value / ADC Resolution) * Reference Voltage
Resolution = 4096
Reference = 3.3V
ADC Pins in STM32F103C8T6
STM32-də PA0-dan PB1-ə qədər 10 Analoq pin var.
Digər mikro kontrollerlərdə ADC-dən necə istifadə olunacağını da yoxlayın: (düzəliş edilir)
- Arduino Uno-da ADC-dən necə istifadə etmək olar?
- ADC0808 ilə 8051 mikrokontroller ilə qarşılıqlı əlaqə
- PIC mikrokontrollerinin ADC Modulundan istifadə
- Raspberry Pi ADC Təlimatı
- MSP430G2-də ADC-dən necə istifadə etmək olar – Analoq gərginliyin ölçülməsi
Tələb olunan komponentlər
- STM32F103C8
- LCD 16*2
- Potensiometr 100k
- Breadboard
- Birləşdirmə telləri
Dövrə diaqramı və izahatları
STM32F103C8T6 lövhəsinə 16*2 LCD və Analoq Giriş interfeysinin qurulması üçün dövrə diaqramı aşağıda göstərilmişdir.
LCD üçün birləşmə aşağıda verilmişdir:
LCD Pin nömrəsi | LCD Pin adı | STM32 Pin adı |
1 | Ground (Gnd) | Ground (G) |
2 | VCC | 5V |
3 | VEE | Potensiometrin mərkəzi pini |
4 | Register Select (RS) | PB11 |
5 | Read/Write (RW) | Ground (G) |
6 | Enable (EN) | PB10 |
7 | Data Bit 0 (DB0) | Bağlantı yoxdur (NC) |
8 | Data Bit 1 (DB1) | Bağlantı yoxdur (NC) |
9 | Data Bit 2 (DB2) | Bağlantı yoxdur (NC) |
10 | Data Bit 3 (DB3) | Bağlantı yoxdur (NC) |
11 | Data Bit 4 (DB4) | PB0 |
12 | Data Bit 5 (DB5) | PB1 |
13 | Data Bit 6 (DB6) | PC13 |
14 | Data Bit 7 (DB7) | PC14 |
15 | LED Positive | 5V |
16 | LED Negative | Ground (G) |
Bağlantılar yuxarıdakı cədvələ uyğun olaraq aparılır. Dövrədə iki Potensiometr var, birincisi gərginliyi dəyişdirmək və STM32-yə analoq giriş təmin etmək üçün istifadə edilə bilən gərginlik bölücü üçün istifadə olunur. Bu potensiometrin sol pini STM32-dən (3.3V) giriş müsbət gərginliyi alır və sağ pini torpağa, potensiometrin mərkəzi pini STM32-nin analoq giriş pininə (PA7) qoşulur. Digər potensiometr LCD displeyinin parlaqlığını dəyişmək üçün istifadə olunur. STM32 üçün enerji mənbəyi kompüterdən və ya noutbukdan USB enerji mənbəyi vasitəsilə təmin edilir.
ADC dəyərlərini oxumaq üçün STM32-nin proqramlaşdırılması
Əvvəlki dərsliyimizdə USB Portundan istifadə edərək STM32F103C8T6 Lövhəsinin Proqramlaşdırılması haqqında öyrəndik. Beləliklə, indi bir FTDI proqramçısına ehtiyacımız yoxdur. Sadəcə onu STM32 USB portu vasitəsilə PC-yə qoşun və ARDUINO IDE ilə proqramlaşdırmağa başlayın. Analoq gərginliyi oxumaq üçün STM32-ni ARDUINO IDE-də proqramlaşdırmaq çox sadədir. Arduino lövhəsi ilə eynidir. STM32-nin jumper pinlərinin dəyişdirilməsinə ehtiyac yoxdur.
Bu proqramda analoq dəyəri oxuyacaq və bu dəyərlə gərginliyi hesablayacaq və sonra həm analoq, həm də rəqəmsal dəyərləri LCD ekranda göstərəcək.
Əvvəlcə LCD pinlərini müəyyənləşdirin. Bunlar LCD pinlərinin STM32-nin hansı pininə qoşulduğunu müəyyən edir. Tələblərinizə uyğun olaraq dəyişdirə bilərsiniz.
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; // LCD-nin qoşulduğu pin adlarını göstərin
Sonra, LCD displey üçün başlıq faylını daxil edirik. Bu, STM32-nin LCD ilə necə əlaqə saxlaması üçün kodu ehtiva edən kitabxananı çağırır. Həmçinin, Liquid Crystal funksiyasının yuxarıda müəyyən etdiyimiz pin adları ilə çağırıldığından əmin olun.
#include <LiquidCrystal.h> // LCD kitabxanasını daxil edin
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //LCD-ni işə salın
setup() funksiyasının içərisində biz sadəcə LCD ekranda göstəriləcək giriş mesajı veririk. Siz STM32 ilə LCD interfeysi haqqında öyrənə bilərsiniz.
lcd.begin(16, 2); //We are using a 16*2 LCD
lcd.clear(); //Clear the screen
lcd.setCursor(0, 0); //At first row first column
lcd.print("CIRCUITDIGEST"); //Print this
lcd.setCursor(0, 1); //At secound row first column
lcd.print("STM32F103C8"); //Print this
delay(2000); //wait for two secounds
lcd.clear(); //Clear the screen
lcd.setCursor(0, 0); //At first row first column
lcd.print("USING ADC IN");//Print this
lcd.setCursor(0,1); //At secound row first column
lcd.print("STM32F103C8");//Print this
delay(2000); //wait for two secounds
lcd.clear(); //Clear the screen
Nəhayət, sonsuz loop() funksiyamızın içərisində potensiometrdən PA7 pininə verilən analoq gərginliyi oxumağa başlayırıq. Artıq müzakirə etdiyimiz kimi, mikrokontroller rəqəmsal bir cihazdır və gərginlik səviyyəsini birbaşa oxuya bilməz. SAR texnikasından istifadə edərək gərginlik səviyyəsi 0-dan 4096-a qədər “map” edilir. Bu dəyərlər ADC dəyərləri adlanır, bu ADC dəyərini əldə etmək üçün sadəcə aşağıdakı sətirdən istifadə edin.
int val = analogRead(A7); // read the ADC value from pin PA7
Burada pinin analoq dəyərini oxumaq üçün analogRead() funksiyasından istifadə olunur. Nəhayət, bu dəyəri “val” adlı dəyişəndə saxlayırıq. Bu dəyişənin növü tam ədəddir, çünki biz bu dəyişəndə saxlanmaq üçün yalnız 0 ilə 4096 arasında dəyişən dəyərlər alacağıq.
Növbəti addım gərginliyin dəyərini ADC dəyərindən hesablamaq olacaq. Bunu etmək üçün aşağıdakı düsturlarımız var
Voltage = (ADC Value / ADC Resolution) * Reference Voltage
Bizim vəziyyətimizdə biz artıq bilirik ki, mikrokontrollerimizin ADC “resolution”-u 4096-dır. ADC dəyəri də əvvəlki sətirdə tapılır və val adlı dəyişəni saxlayır. İstinad gərginliyi (reference voltage) mikrokontrollerin işlədiyi gərginliyə bərabərdir. STM32 lövhəsi USB kabel ilə təchiz edildikdə, işləmə gərginliyi 3.3V-dir. Lövhədəki Vcc və torpaq pinində multimetrdən istifadə edərək, işləmə gərginliyini də ölçə bilərsiniz. Beləliklə, yuxarıdakı düstur aşağıda göstərildiyi kimi bizim vəziyyətimizə uyğun gəlir
float voltage = (float(val)/4096) * 3.3; //ADC dəyərini gərginliyə çevirmək üçün düstur
Siz sətiri float (val) ilə qarışdıra bilərsiniz. Bu, “val” dəyişənini int məlumat növündən “float” məlumat növünə çevirmək üçün istifadə olunur. Bu çevrilmə ona görə lazımdır ki, yalnız floatda val/4096 nəticəsini alsaq, onu 3.3-ə vura bilərik. Əgər dəyər tam ədədlə alınırsa, həmişə 0 olacaq və nəticə də sıfır olacaq. ADC dəyərini və gərginliyini hesabladıqdan sonra yalnız aşağıdakı sətirlərdən istifadə etməklə nəticəni LCD ekranda göstərmək qalır.
lcd.setCursor(0, 0); // set the cursor to column 0, line 0
lcd.print("ADC Val:");
lcd.print(val); //Display ADC value
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("Voltage:");
lcd.print(voltage); //Display voltage
Tam kod və Nümayiş Videosu aşağıda verilmişdir.
Kod
#include <LiquidCrystal.h> // include the LCD library
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD
const int analogip = PA7;//Initialize the analog input pin
void setup()
{
lcd.begin(16, 2); //We are using a 16*2 LCD
lcd.clear(); //Clear the screen
lcd.setCursor(0, 0); //At first row first column
lcd.print("CIRCUITDIGEST"); //Print this
lcd.setCursor(0, 1); //At secound row first column
lcd.print("STM32F103C8"); //Print this
delay(2000); //wait for two secounds
lcd.clear(); //Clear the screen
lcd.setCursor(0, 0); //At first row first column
lcd.print("USING ADC IN");//Print this
lcd.setCursor(0,1); //At secound row first column
lcd.print("STM32F103C8");//Print this
delay(2000); //wait for two secounds
lcd.clear(); //Clear the screen
}
void loop()
{
int val = analogRead(PA7); // read the ADC value from pin A7
float voltage = (float(val)/4096) * 3.3; //formulae to convert the ADC value to voltage
lcd.setCursor(0, 0); // set the cursor to column 0, line 0
lcd.print("ADC Val:");
lcd.print(val); //Display ADC value
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("Voltage:");
lcd.print(voltage); //Display voltage
}