back to top

Arduino Temelleri 3: 74HC595 Shift Register Kullanımı

Merhaba arkadaşlar. Bugünkü dersimizde sizlerle Arduino ve 74HC595 shift register entegresi kullanarak 8 adet LED’i az sayıda pin harcayarak yakmayı öğreneceğiz.

Gerekli malzemelerimiz:

Hepimizin bildiği üzere Arduino UNO kartımızda 13 adet dijital giriş/çıkış pini bulunmakta. Fakat bu pinlerin hepsini LED sürmek için kullanmak istemeyebiliriz. Yada LED haricinde diğer pinlere sensör, switch, buton v.b. diğer girişler bağlamış olabiliriz. Burada kullanacağımız metot sayesinde Arduino’da sadece 3 adet dijital çıkış pini kullanarak 8 adet LED’i kontrol etmemiz mümkün olacak.

74HC595 Shift Register Entegresi

Shift register devresi, peş peşe bağlanmış flip-flop adındaki hafıza elemanı devrelerinden oluşur. Tiplerine göre paralel girişi seri çıkışa (parallel-in, serial-out, PISO) dönüştüren ya da bizim projemizde kullandığımız 74HC595 gibi seri girişi paralel çıkışa (serial-in, parallel-out, SIPO) dönüştüren işlevde olabilirler.

Kullandığımız entegrede Arduino’ya bağlayacağımız 3 adet bacağa sahiptir: Seri data girişi (DS, pin 14), latch (ST_CP, pin 12) ve clock pini (SH_CP, pin 11). Shift register şu şekilde çalışır: veri girişi yapılmak isteniyorsa latch pini lojik 0 seviyesine çekilir, data girişi yapılır (lojik 1 veya 0) ve saat darbesi (clock pulse) clock pinine uygulanır. Bu şekilde 8 bitlik veri tek bir seri giriş pininden girilir ve işlem sonucunda seri olarak girilen veri paralel çıkışlardan (Q0 – Q7 pinleri) alınmış olur.

Eğer shift register’ın çalışma mantığı size karmaşık geldiyse endişelenmenize gerek yok. Arduino yazılımında bulunan shiftOut fonksiyonu bu işlemlerin hepsini üstlenerek size sadece bağlantıda kullandığınız pinleri tanımlamayı bırakıyor.

Entegremizi LED’lerimize ve Arduino’muza şu şekilde bağlıyoruz:

Devre şeması 17/01/2017 tarihinde güncellenmiştir.

Kodumuz şu şekilde:

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
byte leds = 0;
 
void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
 
void loop() 
{
  leds = 0;
  registeraYaz();
  delay(500);
  for (int i = 0; i < 8; i++)
  {
    bitSet(leds, i);
    registeraYaz();
    delay(500);
  }
  for (int i = 8; i >= 0; i--)
{
    bitClear(leds, i);
    registeraYaz();
    delay(500);
  }
}
void registeraYaz()
{
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, LSBFIRST, leds);
   digitalWrite(latchPin, HIGH);
}

Kodumuzun ilk kısmında her zaman yaptığımız gibi çıkış pinlerimizi tanımladık. leds isimli 8 bitlik bir değişken tanımladık (byte tipindeki değişkenler 8 bit büyüklüğündedir). Bu baytın her bir biti, bizim shift register’ımızın çıkışına bağlı olan LED’leri temsil ediyor. registeraYaz fonksiyonumuz, shift register’ın çalışması için gerekli işlemleri yapıyor. loop fonksiyonumuzda bu fonksiyonu çağırarak leds değişkeninde yaptığımız değişiklikleri LED’lerimize aktarmak için bu fonksiyonu çağırıyoruz. loop fonksiyonumuzda ise iki adet for döngüsü kullandık. İlk for döngüsü, leds değişkenimizdeki 8 bitten her birini sırayla 1 yaparak 00000001, 00000011, 00000111… şeklinde bir desen elde etmemizi sağlayacak. Her bir bit 1 olduktan sonra (11111111), ikinci for döngüsü başlayarak bu sefer bitleri 0’layarak 01111111, 00111111,00011111… desenini oluşturacak.

Sizler for döngüsü kullanmayıp, örneğin leds = B00000001, leds = B00000010, leds = B00000100, şeklinde sıralayarak kara şimşek ışıkları yapmayı deneyebilirsiniz. Her komuttan sonra registeraYaz fonksiyonunu çağırmayı unutmayın.

NOT: Eğer derslerimizi sırayla takip ediyorsanız bu dersimizde yaptığımız devreyi sökmeyin. Bir sonraki dersimizde seri haberleşme kullanarak LED yakmayı öğreneceğiz.

Son Çıkan Yazılar

41 YORUMLAR

  1. Merhaba , birşey soracaktım, bu yöntemle bu 8 ledi ayrı ayrı nasıl kontrol edebiliriz. Yani mesela bir if komutu koyup 1. ledi kontrol edip, başka bir if koyup 2. ledi kontrol nasıl ederiz? Birinci if sonucunu ikinci if etkilemeyecek , bu yapılabilir mi shift registerda ? Teşekkürler.

    • Biraz geç olacak cevap ama belki başkasının işine yarar.Dediğin işlem şu şekilde yapılabilir

      shiftOut(dataPin, clockPin, LSBFIRST, leds); komutunda leds yerine yakmak istediğin ledin bağlı olduğu çıkışın decimal sayı sistemindeki karşılığını yazarsan olur

      Örnek-1: Q5 çıkışına bağladığın ledi yakmak için Q5 in binary karşılığı 00100000 bunun decimal karşılığı 32 olduğundan shiftOut(dataPin, clockPin, LSBFIRST, 32); yaparsan Q5 yanar

      Örnek-2: Q4,Q5,Q6 yakmak istersen bunların binary karşılığı 01110000 olduğundan decimal sayı sistemindeki karşılığı olan 16+32+64 =112 yazarsan bu çıkışlar aktif olur

      if döngüsünde de şu şekil yapabilirsin;

      if( a >= b)
      {
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, 112);
      digitalWrite(latchPin, HIGH);
      }

      yanlız bu şekil yaptığında void registeraYaz() fonksiyonunu kullanmayacaksın direk void loop() içine yazacaksın.

  2. Merhaba, çalışmalarınızda kolaylıklar dilerim.

    74HC595 entegrenin toprak ucu 8 numaralı bacak gibi gözüküyor. Şemadaki boardda ise 8 numaradan çıkan siyah kablo +V hattına bağlanmış gibi.

    Teşekkürler…

  3. Merhabalar,
    Hocam peki devreye birbirine seri şekilde 3 veya 4 tane 74hc595 bağlarsak diğer 595 ‘in bacaklarına bağladığımız ledleri nasıl kontrol edebiliriz.
    Cevaplarsanız çok memnun olurum..

  4. Arduino:1.6.11 (Windows Store 1.6.11.0) (Windows 10), Kart:”Arduino/Genuino Uno”

    C:\Users\admın\Documents\Arduino\_74hc595\_74hc595.ino: In function ‘void loop()’:

    _74hc595:16: error: ‘registeraYaz’ was not declared in this scope

    exit status 1
    ‘registeraYaz’ was not declared in this scope

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.
    kodda bi hata olabilirmi??

    • Merhaba. Çok geç cevaplıyorum ama sorun şu. Kodunuz derlenirken, yani Arduino IDE kodunuzu Arduino’nuza yüklemek için işlerken kodu yukarıdan aşağı satır satır okuyor. Bunun sonucunda void loop()’un içeriğini okurken registeraYaz() diye bir fonksiyonun çağrıldığını görüyor. Oysaki bizim registeraYaz fonksiyonu az daha sonra tanımlandığı için henüz daha orayı görmemiş oluyor. Dolayısıyla bu registeraYaz da ne ben böyle bir şey bilmiyorum deyip hata veriyor. Yine en yukarıdan satır satır aşağı indiği için. Sorunu iki yolla çözebiliriz. Birincisi: registeraYaz fonksiyonunu komple void loop()’tan önceki satırlara taşımak. Böylece derleyici (Arduino IDE) void loop() içindeyken de registeraYaz’ın ne olduğunu biliyor. İkinci yol da registeraYaz fonksiyonuna dokunmayıp void loop()’tan önceki satıra şu kodu yerleştirmek:
      void registeraYaz();
      Bu kod parçasında fonksiyondan sonra küme parantezi açmak yerine sadece noktalı virgül kulandık. Böylece şunu demiş oluyoruz: “Oralarda bir yerde registeraYaz diye bir fonksiyon var. Eğer registeraYaz diye bir şey görürsen bu ne deme. Zaten az sonra ne olduğunu öğreneceksin”.
      Saygılarımla.

  5. Oktay, yukarıda tanımladığın leds=0; registeraYaz(); olan yerde registeraYaz başına byte eklersen sorun düzelir yani;
    void loop()
    {
    leds = 0;
    byte registeraYaz();
    delay(500); ……. ..} şekinde yazarsan çalışır.

  6. RegisteraYaz Türkçe bir komut. Arduino programı türkçe desteklemeyenlerde var benim gibi. Onlar ne yazıcak bu komut yerine. Register mi yazıcak yalnızca?

  7. iyi günler kerem bey,bu komutları uyguladım fakat ilk çalıştırdığımda tüm ledler yanıktı hızlı bir şekilde tüm ledler yanıp söndü.Sonra dediğiniz şekilde tek tek yanmaya başladı.Başlangıçta hepsinin sönük olması gerekmiyor muydu?Bir de shiftout un içindeki LSBFIRST ne işe yarıyor?

    • Shift register’a ilk bilgi gönderildiğinde oluşan bir durumdan dolayı tüm LED’ler yanıyor. Bu durumun önüne geçmek için 13 numaralı Output Enable pini kullanılabilir. Bu pin lojik 1 seviyesinde iken tüm çıkışlar 0 olarak kalır. shiftOut fonksiyonundaki LSBFIRST seçeneği, gönderilen verinin en önemsiz biti (least significant bit, LSB) ile başlayacağını belirtiyor. Örneğin 11010010 gönderdiğimizi düşünecek olursak, shift register’a sırasıyla 0, 1, 0, 0, 1, 0, 1, 1 şeklinde gönderilecektir.

    • LED’lerimiz 0 verdiğimizde sönecek, 1 verdiğimizde yanacaktır. Varsayılan durum olarak tüm LED’lerin sönük kalması için başlangıçta 0 değeri atıyoruz.

  8. Merhaba. Ben aynı bu şekilde uyguladım ancak ne yaptıysam sorunu çözemedim. Problemim şu- ledlerin en baştan 1-2-3-4 numaralı olanları çalışıyor diğerleri çalışmıyor. Anlamadım gitti. Neden kaynaklanabilir? Tüm elektriksel bağlantılara baktım. Malzemelerin sağlamlığını test ettim ama çözemedim sorunu.

    • Bu örnekteki leds değişkeni 8 adet integer’a sahip bir array’dir. Siz 3 adet entegrenin her birisi için ayrı birer registeraYaz fonksiyonu tanımlamanız ve parça parça 8-bitlik değişkenleri bu fonksiyonlar içerisinde yazdırmanız gerekecektir.

    • Entegrenin OE pinine PWM sinyal uygulamayı deneyebilirsiniz. Fakat bu durumda tüm çıkışlara tek bir pinden PWM uygulamış olacaksınız. Alternatif olarak buradaki gibi bir PWM sürücü kartı kullanabilirsiniz.

  9. 74HC595 entegresiyle kullanım için burada bir kütühane bulunuyor.
    https://github.com/Simsso/ShiftRegister-PWM-Library
    Kütüphane sahibine ait makale de burada
    https://timodenk.com/blog/shiftregister-pwm-library
    Ben buradaki şemaya göre bağlantıları yaptım. entegreye ardiuno’daki D1,D2 ve D9 pinini bağladım. verilen örnek kodu da kendime uyarladım.
    Ama bir türlü istediğim sonuçları alamadım. Sizin makalenizi de inceledim.
    Bu 74HC595 ile “pwm çıkışı” elde edilebiliyor mu?
    benim yapmak istediğim uno’ya ait pwm çıkışları yetersiz geldiğinden bunları çoğaltmak.
    yani entegre den “pwm” çıkışı almam gerekiyor ki “dc motor” sürücü kartında bulunan “enA” pinine bağlayabileyim.
    Bu konu da yardımcı olabilirmisiniz?

  10. D2, D3,D4 pinlerine bağladım. tercihli olarak pinleri değiştirmedim.
    brada anlatıldığı gibi yaptım.
    https://timodenk.com/blog/shiftregister-pwm-library
    entegrenin ilk 3 ayağına 1 adet rgb led bağlamıştım.(rgb led 4 ayaklı, 3 ayağını entegreye bağladım.) entegredeki 4 ve 5nci pinleri de birbirinden ayrı 2 dc motorun enA pinleri olarak bağladım.
    motorları hareket ettirip, durdurabiliyorum.
    rgb led’de ise henüz istediğim rengi yakamadım.
    motor ve rgb led için şöyle bir sorun var ki benim entegreye bağlantı yaptığım sırayı takip etmiyorlar.
    sanırım bazen de pinlerin yeri değişiyor. ilginç ama led’e renk emri veriyorum bazen 2 motor birden hareket ediyor.
    yine bir yerde yanlışlık yapıyorum galiba ama ardiunodan entegreye 2,3,4ncü pinleri bağladım bunlarda sorun yok. sadece nasıl çalışıyor onu anlamaya çalışıyorum.

  11. Arduino dan bağımsız bir sistem de 5 adet 74hc595 kullanılarak 5 adet 7segment display e değer yazdırılıyor . Sistem kendi içinde 3 adet kablo ile kontrol ediyor bunu bu kablolar clock latch ve data pinine gidiyor. Benim sorum ise biz bu 3 kabloyu arduinoya bağlayarak display de yazan yazıyı nasıl okuruz.

CEVAP VER

Lütfen yorumunuzu giriniz!
Lütfen isminizi buraya giriniz