Arduino
OKUDUĞUNUZ KONU
ARDUINO – TINKERCAD Proje #3
0

ARDUINO – TINKERCAD Proje #3

Yazar : Turgut Güneysu18 Eylül 2018
IRRemote ile CD4511 Entegreli 7-Segment LED Kontrolü

Merhaba,

Üçüncü ve son Tinkercad / Arduino projemize hoş geldiniz. İlk iki projemizi daha görmediyseniz, buradan ulaşabilirsiniz:

ARDUINO – TINKERCAD PROJE ÖZELLEŞTİRME #1 ,

ARDUINO – TINKERCAD PROJE ÖZELLEŞTİRME #2 .

IRRemote ile CD4511 Entegreli 7-Segment LED Kontrolü

Bu projemizde tamamen sıfırdan başlayıp UNO’ya önce bir IRRemote ve IRSensör, sonra bir 7-Segment LED ve onu kontrol edecek CD4511 entegre devresini ekleyeceğiz. CD4511 seçmenin sebebi LED’i BCD (ikili kodlanmış onlu) sayı sistemi ile çalıştırmayı öğrenmemiz.

Amacımız:  IRRemote 0 – 9 düğmelerine bastığımızda LEDde bu numaraları göreceğiz. Ayrıca  güç butonuna bastığımızda da CD4511 bir LEDTest yapacak. Bu yazılımda teknik olarak IRRemote’un kullandığı değişik HEX kodları deşifre etmeye ve CD4511 entegresinin girdilerini BCD kodlarıyla sürmeye odaklanacağız.

 

1. UNO + IRRemote + IRSensör

Devreyi bu üç komponentle aşağıda göründüğü gibi kurun:

IRSensörün sarı SİNYAL bağlantısı (D12) IRRemote’un HEX kodlarını sisteme yolladığı pindir. Bu herhangi bir pine bağlanabilir. Uzaktan kumanda birimleri üretici tipine göre değişik protokollar kullanarak HEX kodlar oluşturuyorlar. Yazacağımız kodun bir özelliği de IRRemote HEX kodlarını Seri Monitöre yazdırmak olacak. Böylece hakiki Arduino ile çalıştığınızda bu özelliği kullanarak herhangi model uzaktan kumandanın kodlarını öğrenebilirsiniz.

Yukarıdaki devreyi doğru kurduysanız Aşağıdaki kodu ekleyerek uzaktan kumanda HEX kodlarını yazdırabilirsiniz:

#include <IRremote.h>

// IR atamalari
#define IRPIN 12 // IR girdi pini
IRrecv IRSensor(IRPIN);
decode_results results; 
unsigned long int oncekiIRKod = 0;

void setup()
{
 Serial.begin(9600);
 IRSensor.enableIRIn(); // IR baslat.
}

void loop() {
 if(IRSensor.decode(&results)) { // IR kod algılanmışsa
 Serial.print(results.value, HEX);
 Serial.print("\t");
 Serial.println(results.value, DEC);
 IRSensor.resume();
 }
}

Her şey doğru çalıştıysa projemize devam edebiliriz.

2. CD4511 ve 7-Segment LED

Projemizi en gelişmiş haline getirmek için CD4511 entegresini ve 7-Segment LED’i ekleyerek aşağıdaki gibi kurun.

Dikkat edeceğiniz noktalar:

  • CD4511’a bağlı rezistans değeri 1K Ohm, LED’e bağlı rezistans değeri ise 220 Ohm olarak ayarlanmalıdır.
  • LED tipi Common Cathode (ortak katod) olarak seçilmelidir.
  • LED in en alt sağdaki DP – Decimal Point (Ondalık Nokta) pini kullanılmıyor.
  • LED’de iki tane ortak katod pini vardır ve bunlar entegre içinde birbirlerine bağlıdırlar. Bundan dolayı sadece bir tanesini toprağa bağlamak yeterlidir.
  • IRSensör 3,3V ve CD4511 5V güç alarak çalışmaktadır.
  • CD4511’ın alt kenarındaki pin 4 – 7 (sarı, turuncu, mavi, yeşil) bağlantıları karmaşık olmasına rağmen böyle sıralanmaları kodumuzdaki BCD uygulamasına yardımcı olacaktır.
  • CD4511’in sinyal pinleri dijital olarak çalıştığından, Arduino’da nereye bağlandıkları önemli değildir.

 

3. CD4511 ve 7-Segment LED İlişkisi

CD4511 entegresi BCD kodlarını girdi olarak alıp 7-Segment LED’in yakma sinyallerini kontrol ederek 0 – 9 arası sayıların gösterilmesini sağlıyor. Eğer evvelden BCD kodlarıyla çalışmamışsanız aşağıdaki iki resim ikili sistem ile BCD kodların nasıl oluşturulduğunu ve bunların nasıl LED segment sinyallerine dönüştürüldüğünü anlamanıza yardımcı olacaktır.

A(D4):Sarı B(D5):Turuncu C(D6):Mavi D(D7):Yeşil

 

 

CD4511 kullanmanın bir iyiliği de yedi sinyalle oynamak yerine sadece dört sinyalle sayıları LED’e yazabilmek. Bunun yanısıra, bir dezavantajı sadece 0 – 9 arası sayıları göstermesi. Fakat bunun çalışma ve yazılım prensibini anladığınız zaman HEX numaraları da yazabilen entegreler kullanabilirsiniz. Veya 7-Segment LED’i kendiniz Arduino’dan direkt sürerek çalıştırabilirsiniz.

 

4. KODumuzu yazmaya başlayalım

Programımızın çalışma prensibi söyle:

  • IRSensör ve pin ayarlarını yapıp Seri monitöre “LED ayarlar tamam.” mesajını yazıyoruz.
  • LED’in doğru çalıştığını denetlemek için LEDTest kumandası ile bütün LED segmentleri üç defa yakıp söndürüyoruz.
  • IRSensörü çalıştırmaya başlıyoruz.
  • IRRemote’un 0 – 9 düğmelerine basıldığında yollanan HEX kodu deşifre edip CD4511′ in BCD girişine bu numarayı yazıyoruz.
  • CD4511’de girilen ikili koda göre gereken LED segmentleri yakıp söndürerek istediğimiz numarayı LED ekranında gösteriyor.
  • Eğer güç düğmesine basmışsak CD4511 LEDTest yapıyor ve bütün segmentleri üç defa yakıp söndürüyor.

Detaylarına bakalım:

/* UNO + CD4511 + 7SEGLed _ IRRemote
 Arduino'ya IRRemote ekleyip LED'de sayı gösterme.
 IRRemote kütüphane gerektirdiğinden ve komutları BLOCK modda
 desteklenmediğinden METİN olarak geliştireceğiz. 
 
 CD4511 Entegresi:
 BCD (ikili kodlanmış onlu) kod girişi LED segmentlerine
 çeviren bir eleman. Aşağıdaki tabloya göre çalışıyor.
 
 DEC BCD/7654      DEC BCD/7654
  0    0000         5    0101
  1    0001         6    0110
  2    0010         7    0111
  3    0011         8    1000
  4    0100         9    1001
 
 IRRemote kodları:
 BUTON    HEX        DEC 
   0      FD30CF     16593103
   1      FD08F7     16582903
   2      FD8877     16615543
   3      FD48B7     16599223
   4      FD28D7     16591063
   5      FDA857     16623703
   6      FD6897     16607383
   7      FD18E7     16586983
   8      FD9867     16619623
   9      FD58A7     16603303
  Güç     FD00FF     16580863
  Yine    FFFFFFFF   4294967295
 
*/

Bu uzun açıklama kısmında programımız hakkında kısa bir bilgi verip, sonra hem BCD hem de IRemote HEX kodlarını içeren iki tablo gösteriyoruz.

//SERI monitöre IR Kod yazma kontrolü:
// Düğmelerin IR kodlarını görmek istiyorsanız
// aşağıdaki satırın başındaki // silin.
//#define IRKodYaz

Programımızın özelliklerinden biri değişik IRRemote’lar kullanırken bunların hangi HEX kodlarla çalıştığını anlayabilmek için her düğmeye basıldığında hem HEX hem de onluk kodu Seri monitöre yazmak. Bunu kendi kontrolümüzde uygulamak için kodumuza bir #define ekliyoruz. Bu satır eğer comment (açıklama) değilse (yani önünde // yoksa) o zaman kodumuz HEX ve DEC kodları seri monitöre yazacaktır. Bunu istemediğimiz takdirde bu satırın önüne // koyarak bu özelliği devre dışı bırakacağız. Buradaki seçeneğe göre uygulama LOOP() kısmında yapılıyor.

#include <IRremote.h>
// IR atamalari
#define IRPIN 12 // IR girdi pini
IRrecv IRSensor(IRPIN);
decode_results results;
unsigned long int oncekiIRKod = 0;

Önce IRRemote’umuzu çalıştırmak için gereken kütüphaneyi #include kullanarak programımıza ekliyoruz. Arkasından IR kumanda ve sensör ile ilgili değişken ve atamaları yapıyoruz. IR Sensörü D12 pinine bağlı olduğu için bunu bir #define ile belirliyoruz. IRSensör nesnemize IRSensor adını vererek belirliyoruz ve kullanacağımız pin de nesnemize atanıyor. IR sensör okuma sonuçlarını içerecek results değişkenini belirliyoruz. Son olarak da düğmelere devamlı basıldığında seçilen sayıyı yineleyerek LED’e yazmak için oncekiIRKod  adlı bir değişken belirliyoruz.

void setup()
{
  Serial.begin(9600);
  IRSensor.enableIRIn(); // IR baslat.

  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  Serial.println("LED ayarlar tamam.");
  LEDTest();
}

Şimdi programımızın setup() kısmına geldik. burada Seri monitör baud ayarını yapıyoruz ve IR sensörümüzü çalıştıracak enableIRIn() fonksiyonu başlatıyoruz. CD4511’e girdi olarak kullanılacak pinleri OUTPUT olarak tanımlıyoruz. Her şeyin hazır olduğunu belirleyen mesajı Seri monitöre yazıyoruz. Son olarak LEDTest() işleviyle LED segmentleri test ediyoruz.

void loop() {
  if(IRSensor.decode(&results)) { // IR kod algılanmışsa

    switch (results.value) {
    case 0xFD30CF: // 0
        LEDYakBCD(0); break;
    case 0xFD08F7: // 1
        LEDYakBCD(1); break;
    case 0xFD8877: // 2
        LEDYakBCD(2); break;
    case 0xFD48B7: // 3
        LEDYakBCD(3); break;
    case 0xFD28D7: // 4
        LEDYakBCD(4); break;
    case 0xFDA857: // 5
        LEDYakBCD(5); break;
    case 0xFD6897: // 6
        LEDYakBCD(6); break;
    case 0xFD18E7: // 7
        LEDYakBCD(7); break;
    case 0xFD9867: // 8
        LEDYakBCD(8); break;
    case 0xFD58A7: // 9
        LEDYakBCD(9); break;
    case 0xFD00FF: // GÜÇ Düğmesi
        LEDTest(); break;
    case 0xFFFFFFFF: // YINELE
        LEDYakBCD(oncekiIRKod); break;
    }

Programımızın ana döngüsü  olan loop() kısmında IR sensörün algıladığı HEX kodları deşifre edip, 0 – 9 arası hangi düğmeye basıldığını buluyoruz, ve bunu CD4511 BCD girdisine yollayacak olan LEDYakBCD() işlevini değişik buton değerlerle çalıştırıyoruz.

HEX kodları deşifrede kullandığımız switch/case deyimi bu işi en etkili yapacak komuttur.

Son karşılaştırmaya dikkatinizi çekerim: IRRemote aygıtları herhangi bir buton devamlı olarak basıldığında ilk önce basılan butonun HEX kodunu, arkasından buton basıldığı sürece de YİNELE  (0xFFFFFFFF) kodunu yollarlar. Biz her kodu deşifre edip işlediğimizde onu oncekiIRKod değişkenine kaydettiğimiz için, YİNELE kodu geldiğinde bu önceki buton değerini kullanarak aynı sayıyı LED’de göstermeye devam ediyoruz.

    // Eğer program başındaki #define IRKodYaz ı açtıysanız IR kodlar yazılır
    #ifdef IRKodYaz
      Serial.print(results.value, HEX);
      Serial.print("\t");
      Serial.println(results.value, DEC);
    #endif

    IRSensor.resume();
  }
}

loop() kısmının son bölümünde, basılan buton numaralarını LED’e yazmayı bitirdikten sonra,  butonların HEX ve DEC kodları seri monitöre yazıyoruz. Bunu kontrolü programın başında tanımladığımız #define IRKodYaz deyimi. Eğer bunu aktif etmişsek (önündeki // yi silip) #ifdef IRKodYaz değerlendirmesi DOĞRU olacaktır ve #endif ‘e kadar içerdiği komutlar işlenecektir. Sonuç olarak, eğer // kullanmışsak yazılmayacak, kullanmamışsak yazılacak.

IRSensor.resume() komutu da sensörümüzü reset edip tekrar okumaya hazırlıyor.

Burada loop() ana döngümüzün sonuna varmış oluyoruz. Geriye kalan sadece bir kaç tane yardımcı işlevler.

Onları da inceleyelim:

void LEDSoff() {
  // İki LED söndürme tekniği:
  digitalWrite(9, LOW); // BL off: LED yakma sinyalini söndür

  // LED'e 0 - 9 harici bir sinyal yollayıp LED'i söndürme
  //byte LEDoff = 0xF0; // E0, D0, C0, B0, A0 da olabilir
  //PORTD = LEDoff;
}

Bu işlev LED segmentleri söndüren iki teknik içeriyor. Denemek istediğiniz tekniğin kod önündeki // leri kaldırın ve ötekini de // olarak ayarlayın.

Birincisi en basit şekilde CD4511 çipinin BL sinyalini kontrol eden D9 pinine LOW değer atamak. Bu pindeki voltajı sıfır (0) değerine indirip LEDlerin sönmesini sağlayacaktır.

İkinci teknik gene CD4511 çipinin bir özelliğinden yararlanarak uygulanıyor. Eğer çipe yollanan BCD sinyalleri 0-9 haricinde ise, çip bunu yoksayıp ekranı karartır. Bu bilgiye dayanarak BCD portlarına 10-15 kodlarından birini yollarsak ekranı silmiş oluruz. Bunu yapabilmek için önce bu sayıların HEX değerlerine bakalım: 0A – 0F. Yani ikili sistem bazlı olarak incelersek: 0000 1010, 0000 1011, 0000 1100, 0000 1101, 0000 1110, 0000 1111.
Bu tekniği Arduino’nun PORT register (saymaç) değerlerini değiştirerek uygulayacağız. Önce PORT saymaçlarının nasıl çalıştığına bakalım.

PORT saymaçları Arduino port girdi çıktılarını en süratli şekilde değiştirmenizi sağlar. Arduino’larda üç set PORT’lar bulunur:

  • B (digital pin 8 to 13)
  • C (analog input pins)
  • D (digital pins 0 to 7)

Bu portlar üçer tane PORT saymaçı tarafından kontrol edilir:

  • DDR – pinlerin INPUT (girdi) ve OUTPUT (çıktı) olarak ayarlanmasını
  • PORT – pinlerin HIGH (yüksek) ve LOW (alçak) değerlerine ayarlanmasını
  • PIN – pinlerin pinMode() kullanarak ayarlanan girdi çıktı modlarının okunmasını

sağlar. DDR ve PORT saymaçları hem yazılır hem okunur. PIN saymacı yalnız okunur. Bu saymaçların her bir bit’i Arduino’nun bir portunu kontrol eder. Daha fazla bilgi için Arduino referans sayfasına bakın: PORT işlemleri

Şimdi bu bilgiyi uygulayarak CD4511 çipi BCD portlarının bağlı olduğu Arduino dijital 4, 5, 6, 7 portlarını yukarıda belirttiğimiz HEX değerlere ayarlayalım. Değiştirmek istediğimiz portlar 4-7 olduğu için kullanmamız gereken PORT saymaç adının PORTD olması gerekir. PORTD saymacı sağdan sola 0-7 dijital pinlerini kontol eder. Yani:

             --BCD--
PİNler:      7 6 5 4 3 2 1 0
PORTD bit:   7 6 5 4 3 2 1 0
HEX F0:      1 1 1 1 0 0 0 0

Bizim istediğimiz PORTD saymacının 7-4 pinlerini HEX değer F olarak ayarlamak. 3-0 pinleri de sıfır (0) olarak kalsın. Bunun için PORTD saymacına HEX değer F0  yazmamız lazım. Gereken kod:

byte LEDoff = 0xF0; // E0, D0, C0, B0, A0 da olabilir 
PORTD = LEDoff;

Burada dikkat etmeniz gereken bir nokta var. Bizim uygulamamızda 0-3 Arduino portları kullanılmıyor. Bundan dolayı PORTD ye yazdığımız değerin sağ bayt yarısını sıfır olarak ayarladık. Aslında bu tam doğru olmayıp 0-3 pinlerinin kullanıldığı başka uygulamalarda problem yaratabilir. En doğru PORTD değiştirme işlemi lojik OR ile yapılmalıdır. Yani:
PORTD = LEDoff;
yerine:
PORTD = PORTD | B11110000;
veya:
PORTD = PORTD | LEDoff;
Böyle yapıldığında yalnız 7-4 pinleri HIGH değere ayarlanıp 3-0 pinlerine dokunulmamış olur.

Şimdi yardımcı işlevleri incelemeye devam edelim.

void LEDTest() {
   Serial.println("LED TEST basladi...");
   LEDSoff();
   // CD4511 LT(LEDTest) on pin D10
   for (int i = 0; i < 3; ++i) {
     digitalWrite(10, LOW);
     delay(200);
     digitalWrite(10, HIGH);
     delay(200);
   }
   Serial.println("LED TEST bitti...");
 }

LEDTest() işlevi CD4511’in LT (D10) sinyalini kontrol ederek bütün LED segmentleri yakıp söndürüyor. Ben bunu üç seferlik bir döngüde uyguladım. Arzuladığınız gibi değiştirebilirsiniz.

 

void LEDYakBCD(byte rakam) {
  // CD4511'e BCD kod girip LED segmentleri yakıyor. 
  // BL (BLANK) on D9 is ON 
  digitalWrite(9, HIGH); 
  oncekiIRKod = rakam;  // TEKRAR için hatırla

  // Aşağıdaki satır BCD kodu portlara direkt olarak yazıyor 
  PORTD = (rakam << 4); // dijital pinler 7,6,5,4 

  delay(2); 
  LEDSoff(); 
}

Kodumuzun son ve en önemli kısmına geldik. LED segmentleri yakan işlev: LEDYakBCD(byte rakam)

Burada yapılan iş gayet basit – LED’e yazılacak sayı işleve parametre olarak geliyor (byte rakam) ve CD4511 çipinin  BCD portları buna göre ayarlanıyor. Bu ayarlamayı yukarıda incelediğimiz LEDSoff() rutinindeki PORTD tekniğini uygulayarak yapıyoruz.

Önce BL (D9) sinyali HIGH olarak ayarlanıyor – CD4511 gereksinimi.

LED’e yazacağımız sayıyı oncekiIRKod değişkenine kaydediyoruz. Bunu sebebi, eğer IRRemote kumandasında düğmeye devamlı basılırsa, kumanda TEKRARLA kodunu (FFFFFFFF) yolluyor. Bu gelince bizim tekrar aynı sayıyı gösterebilmemiz lazım.

PORTD = (rakam << 4); koduna detaylı bakalım:

İşleve gelen rakam 0-9 arası bir değer. Rakam parametresi byte olarak tanımlandığından, bu rakamların HEX değerleri 0x00 ile 0x09 arası olacaktır.  Bu HEX değerlerıi PORTD saymacına yazabilmek için önce rakamın değerini tutan alt 4 bit’i baytın üst yarısına kaydırmamız gerekiyor. Yani, örneğin rakam = 6 ise, HEX değer 06, ikili değer ise 0000 0110 dır. Bu 0000 0110 deki alt bayt yarısını (0110) üst bayt yarısına kaydırıp baytı 0110 0000 haline getirmemiz gerekiyor.

Bu işlemi yapmak için Arduino’nun << bitshift left (bit sola kaydırma) işlemini kullanıyoruz.

değişken << bit_sayısı; olarak tanımlanan bu işlem değişken‘de belirtilen sayının bitlerini bit_sayısı kere sola kaydırır.

Biz rakam = 6 örneğimizi bu uygulamayla 0000 0110 halinden dört kere sola kaydırarak 0110 0000 haline getirebiliriz. Bunun kodlaması:  rakam << 4. Sonra da bu yeni değeri PORTD saymacına atayarak BCD pinlerini bu değere ayarlamış oluruz.

Kısa bir beklemeden sonra LED segmentleri söndürüp işlevden çıkıyoruz.

Arduino komple yazılım:
https://www.projehocam.com/wp-content/uploads/2018/09/TCProj_03.txt

DEĞİŞİK UYGULAMA:

Yukarıda sunulan PORTD kod satırı yerine normal digitalWrite deyimini kullanan ve rakamın bitlerini teker teker Arduino portlarına yazan değişik bir kod tekniğini aşağıda sunuyorum. Denemek isteyenler PORTD satırını // ile kapatıp aşağıdaki kodu onun yerine koyarak test edebilirler.

//PORTD = (rakam << 4);

int port = 7;
for (int k = 8; k >= 1; k = k/2) {
  if (rakam & k) digitalWrite(port, HIGH); // bitsel AND
  else digitalWrite(port, LOW);

--port;

Bu projemizin de sonuna ulaştık. IRRemote ve Sensör kullanmadan başlayarak HEX kodları deşifre etmeyi öğrendik. Bunları switch / case deyimiyle istediğimiz şekilde yönlendirmeyi yaptık. İki değişik teknik kullanarak Arduino portlarına BCD değer yazmayı öğrendik. Bit Shift deyimi ile bayt değer kontrolünü başardık.

Umarım bu teknikler Arduino uygulamalarınızda size yardımcı olacaktır.

İyi çalışmalar.

 

SİZCE NASIL OLMUŞ?
Beğendim
83%
İlginç
17%
Eh İşte
0%
Anlamadım
0%
Kötü
0%
Berbat
0%
YAZAR HAKKINDA
Turgut Güneysu
Turgut Güneysu
Anadolu'nun tam ortasında ufak bir köyden memleketimizin çocuklarına STEM programlarına uygun bilgisayar, robotik, yazılım, donanım, mikro işlemciler hakkında yardımcı olmaya çalışıp, emekli hayatımın zevkini çıkarıyorum. Gençlerimizin kabiliyetlerinin sonsuz olduğuna ve onları doğru yönlendirirsek değerli katkılarla ortamımızı dünya çapına ulaştıracaklarına inanıyorum.
YORUMLAR

YORUM YAP