Lezzetli Robot Tarifleri Sosyal'e Hoş Geldiniz.. Devamı..

Giriş Yap Üye Ol


Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
IIC Haberleşme Protokolü
#1
Merhabalar;

  Bugünkü konum IIC(I2C) haberleşme protokolünü nasıl kullanacağımızı anlatacağım. Bundan önce yazdığım konuda SPI haberleşme protokolünü inceleyip minik bir uygulama ile desteklemiştik. Bu konuda da aynı düzene göre gideceğiz. Bismillahirrahmanirrahim diyerek başlayım:



    IIC "Inter-Integrated Circuit" anlamına gelen bir haberleşme protokolüdür. Diğer konumda biraz IIC yi kötülemiştik. Ama neredeyse bu yaptığımız projelerde IIC ve SPI ın çok önemli farkları yok. IIC ile küçük ve kısa sürecek verileri aktarabiliriz. IIC yi SPI haberleşme protokolünden ayıran en önemli sebeplerden biri IIC de adres kullanmamızdır. Bunun için slave cihazın adresini bilmemiz gerekmektedir. Örnek verecek olursak IIC ile lcd kullanımı videosunda 0x27 gibi bir değer girmiştik. Bu değer slave cihazın içinde olduğu için fiziksel bir müdahale dışında bu adresi değiştirebilmek için olanağımız yoktu. Bu da IIC haberleşmesi destekleyen modül ve sensörlerde bir dezavantaj olmuş oluyor. Ama kendimiz iki arduinoyu, iki raspberry pı, ya da bir arduino bir raspberry pi gibi haberleşmelerde kendimiz adres belirlediğimiz için adres sorunu kalmamakta. Eğer kullanacağımız slave cihazın içindeki adresini bilmiyorsak ve datasheetlerinden dahi bulamıyorsak aşağıdaki bir kod ile adresini öğrenmemize yardımcı oluyor. Bu kod serial ekranda slave cihazımızın adresini gösteriyor. Bu kod hazır bir kod olarak kullanılmakta. Bu kodu bulduğum kaynak linki[/url]



Kod:
#include <Wire.h>

boolean DeviceFound = false;
byte error, address;

void setup()
{
   Wire.begin();
   Serial.begin(9600);
   Serial.println("\nI2C Araniyor...");
 
   for(address = 0; address <= 127; address++ )
   {
      Wire.beginTransmission(address);
      error = Wire.endTransmission();

      if (error == 0)
      {
        Serial.print("I2C cihaz bulundu. Adresi: 0x");
        if (address<16)   Serial.print("0");
        Serial.println(address,HEX);
 
        DeviceFound = true;
        break;
      }
      else if (error==4)
      {
        Serial.print("Bilinmeyen hata olustu. Adres: 0x");
        if (address<16)  Serial.print("0");
        Serial.println(address,HEX);
      }
   }
   if (DeviceFound == false)
      Serial.println("Herhangi bir bagli I2C bulunamadi\n");
   else
      Serial.println("Tamamlandi. Kolay gelsin.\n");          
}

void loop()
{
}

IIC haberleşme protokolü SDA ve SCL olarak 2 hat kullanır. IIC yi SPI haberleşmesinden ayıran bir özellikte bu olması gerek. SPI haberleşmesine göre daha az hat kullanmakta.

Haberleşmenin gerçekleşmesi:

  1.  SDA hattı start ve stop bitleri gönderen hattır. Tüm slave(köle) cihazlar bu sinyali alınca kendilerini alınacak adres bilgisi için hazırlarlar.
  2.  Mikrodenetleyici haberleşmek istediği slave cihaz üzerinde okuma veya yazma işlemi olup olmadığını kontrol etmek ve adres kontrolü için 1 byte büyüklüğünde bir veriyi SDA hattından yollarlar. Tüm slave cihazlar adres bilgisini alır ve bunun kendi adresleri olup olmadığını kontrol ederler.
  3. Masterın seçtiği slave hazır olduğunu belirtmek için SDA veri hattına ACK sinyali gönderirler. Adresi uymayan slave cihazlar mikrodenetleyiciden gelecek stop bitini beklemeye koyulurlar. Eğer onlar stop bitini göndermezsek programsal hatalar yüzünden onlardan yanlışlıkla sinyal alabilir veya verebiliriz.
  4. Son olarak veri transferleri gerçekleşir. Bundan sonra SDA hattına stop biti gönderilir.


Aşağıdaki fotoğrafta IIC haberleşmesinin örnek veri grafiğini görmektesiniz. Gördüğünüz şekilde SDA ACK gibi sinyallari gönderdiğini görebilirsiniz. SCL hattından akan veri transferini görüyorsunuz ki pwm bir şekilde haberleşmekte. [url=https://www.youtube.com/watch?v=i2UpqGcRacg&t=1s]Arduino ile pwm videosunda gördüğünüz gibi pwm bir sinyal digital sinyalleri kullanarak periyot aralarını öyle bir şekilde ayarlayıp ki bir analog sinyal şeklinde okunmasını sağlıyordu. 

              i2c-tutorial-typical-signals.png

Çok sıklıkla duyduğunuz "Logic elektronik", "Digital elektronik" gibi isimlerle geçen buna biraz değinelim:

   Öncelikle buna değinmeden önce "SPI Haberleşme Protokolü" adlı konumda da bahsetmem gerekliydi ama unuttuğum için malesef ona eklemedim. Şimdi başlayalım:

  Digital elektronik veya başka bir adı ile logic elektronik Ömer abinin videolarında da çok sıklıkla değindiği elektroniğin 1 ve 0 lardan oluştuğu bilgisiydi. Tüm mikrodenetleyicileri programlarken normalde ona 1 ve 0 yani 5v ve 0v sinyallari vererek bu işlemi gerçekleştiyoruz. Pic, Atmega, Arm gibi mikrodenetleyicileri programlarken neden biz logic sinyaller vermiyoruz diyecek olursanız bu çok zor bir iş. Bu yüzden derleyici programları bu işi kolaylaştırmakta. Normalde arduinoyu programlamak için örnek olarak delay() fonksiyonunu programlamak için "11111001011110000111001" gibi sallaması bile zor olan kodu yazmamız gerekiyor. Bizim bu usb/ttl dönüştürücü (Arduino uno üzerindeki atmega16u2) buna yardımcı olarak derleyicinin gönderdiği data verisini logic 0 ve logic 1 vererek atmega mikrodenetleyicimizi programlıyor. Bizim bu atmega mikrodenetleyici 11100100111001001 verisi gelmiş bana, ben x pinini çıkış olarak atayım gibi bir mantık ile programlamamız gerçekleşiyor. Bu 1 ve 0 lardan oluşan bu sinyale pwm sinyal denmekte. Bizim örneğin arduinomuz pwm destekli pinlerinden sanki analog çıkış veriyor gibi gözükse de bunu analiz yapan bir avometre ile ölçersek keskin hatlı ve sadece 5v ve 0v tan oluşan bir sinyal olduğunu görürüz. Eğer analog sinyal olsaydı bize deve hörgücüne benzeyen bir sinyal alacaktık. İşte bunların hepsine "digital elektronik" veya "logic elektronik" denir.

Kısacası 1 ve 0 yani pwm sinyallerden oluşan elektroniğe "digital elektronik" denir. 

Aşağıda pwm ve analog sinyalin şeklini görmektesiniz.

                pwm_wave.png?itok=rLbenFz-                                                img_analogwave.gif 




Evet IIC konusundan biraz saptık ama IIC veri haberleşme protokolü pwm data ile veri alışverişi yapıyor.




Aşağıdaki fotoğrafta görmektesiniz ki istediğimiz kadar slave cihaz bağlayabiliriz. Ayrıca SDA ve SCL hatlarına takılan pull_up direçlerimiz istemediğimiz havadan, manyetik alan gibi sebeplerden dolayı haberleşmemize analog sinyaller karışabileceğinden dolayı pull_up dirençleri koyduk. Teorik olarak 4.7 K lık dirençler yeterlidir. Ama garantiye almak istiyorsanız 10K gibi 4.7 K dan yüksek değerler koyabilirsiniz.

                                  %C4%B12c.png



Teorik bilgileri ve teknik bilgilerimizi öğrendiğimize göre artık bu öğrenilen bilgileri pekiştirmek için öğrendiklerimizi pratiğe dökelim:

Burada arduino uno kullanacağız.



Kütüphane olarak arduinonun kendi içinde bulunan "Wire.h" kütüphanesini kullanacağız.

Kütüphanenin içinde olan kullanacağımız fonksiyonlar:

wire.begin()  IIC haberleşmesini başlatır. Master olan cihazlarda parametre girilmez, slave cihazlarda ise parametre olarak slave cihaza vereceğimiz adresi yazıyoruz. Örnek:25.
wire.available()  Bu fonksiyon eğer bir veri geldiyse değeri 0 dan büyük bir sayı döndürüyor.
wire.beginTransmission(slave adresi)  Bu fonksiyon master cihazlarda kullanılır. Parametre olarak seçeceğimiz slave cihazın adresini gireriz. Örn:25
wire.endTransmission()    Hat üzerindeki veri aktarımını sona erdirir.
wire.write()    Veri yollamak için kullanılır. Parametre olarak göndereceğimiz veri yazılır.
wire.read()     Veri hattından veri okur.
wire.onReceive(Fonksiyon adı)    Slave cihaza bir veri geldiğinde parametre olarak yazılan fonksiyon çalıştırılır.
wire.requestFrom()    Slave cihazdan veri ister. İlk parametreye istenilecek slave cihazın adı, ikinci parametreye kaç byte büyüklüğünde bir veri isteyeceğimizi yazarız.
wire.onRequest()       Slave cihazda kullanacağımız bu fonksiyon master cihazdan bir veri geldiyse parametresindeki fonksiyonu çağırır.


Fonksiyonlar bu kadar. Zaten az önce pull_Up direncinden bahsetmiştim. Bağlantılar basit aşağıdaki şeması var(Ben çizmedim)

Malzemeler:
  • 2 adet arduino uno
  • 1 adet breadboard
  • 2 adet 4.7 K direnç
  • 1 adet 220 ohm direnç
  • Çeşitli jumper kablolar
  • 1 adet led
                                                                   resim2_0.png






Master cihaz kodu:

Kod:
/* IIC haberleşmesinde Master olarak görev yapan Arduino kodu */

#include <Wire.h>
/*
* IIC fonksiyonlarını kullanabilmek için
* Wire.h kütüphanesini projemize ekledik
*/
int i=0;
void setup()
{
 Wire.begin();
 /* IIC haberleşmesi master olarak başlatıldı */
 
 Serial.begin(9600);
 /* Bilgisayara veri yazdırabilmek için seri haberleşme başlatıldı */
}

void loop()
{
 
while(1){             // led 10 kere yakılıp söndürülüyor
  i++;
  led_yak();
  delay(500);
  led_sondur();
  delay(500);
  if(i==10){break;}
 
}

while(1){led_yak();} // led sınırsız yakıldı.

}

void led_yak(){
 
 Wire.beginTransmission(25);
 // 25 adresine sahip Slave (köle) cihazına veri yollanacağı bildiriliyor
 Wire.write("x");
 // x verisi gönderildi
 Wire.endTransmission();
 // veri aktarımını kapattık
}


void led_sondur(){
   Wire.beginTransmission(25);
 // 25 adresine sahip Slave (köle) cihazına veri yollanacağı bildiriliyor
 Wire.write("y");
 // y verisi gönderildi
 Wire.endTransmission();
 // veri aktarımını kapattık
}

Yorumlayalım:

Öncelikle gerekli kütüphanemizi aktif edip i adlı bir değişken oluşturduk. Sonra led_yak ve led_sondur adlı iki fonksiyon yazdık. Bunlar x ve y verilerini gönderecek fonksiyonlar. Ve loop döngüsünde minik bir animasyon yaptık.

Slave görevindeki arduinonun kodu:

Kod:
/* Slave (köle) görevindeki Arduino'nun kodu */
#include <Wire.h>
/*
* IIC fonksiyonlarını kullanabilmek için
* Wire.h kütüphanesini projemize ekledik
*/

const int LED = 13;
/* LED 13. pinde bulunmaktadır */

void setup()
{
 Wire.begin(25);
 /* I2C haberleşmesi, haberleşme adresi 1 olan bir slave cihaz olarak başlatıldı */

 Wire.onReceive(veriGeldiginde);
 /*
 Master olan cihazdan bu Arduino'ya veri geldiğinde yapılacak işlem seçildi
 */
 
 pinMode(LED,OUTPUT);
 /* LED pini çıkış olarak ayarlandı */
}

void loop()
{
 /*
 * Tüm işlemler veri isteği geldiğinde veya yeni veri geldiğinde
 * yapılacağı için loop fonksiyonunun içi boş bırakılmıştır
 */
 delay(1);
}

void veriGeldiginde(int veri)
{
 /* IIC hattında bu cihaz için yeni veri olduğunda bu fonksiyon çalışır */
 char gelenKarakter;
 /* Hattaki veri okunarak gelenKarakter değişkenine kaydedilir */
 while(Wire.available()){
   gelenKarakter = Wire.read();
 }
 /* Eğer gelen veri 'x' ise LED yakılır, 'y' ise LED söndürülür */
 if(gelenKarakter == 'x')
   digitalWrite(LED,HIGH);
 else if(gelenKarakter == 'y')
   digitalWrite(LED,LOW);
}

Yorumlayalım:

İlk önce kütüphane ve gerekli değişkenleri tanımladık. Ardından led olan pini çıkış olarak atadık. veriGeldiginde adlı fonksiyonda ise bir while döngüsü ile şartına veri hattında istek var ve 0 dan büyük ise şartını girdik. Bir değişkene gelen veriyi okuduktan sonra o veriyi kaydettik. Ve bir if-else yapısı ile minik bir tek ledli bir flip flop yapmış olduk.

Bu konumda olan fritzing şeması ve slave görevindeki kodu bu kaynaktaki kod üzerinde oynama yaparak bir şekil verdim. 

Bugünkü konum bu kadardı. Hatam varsa yazarsanız sevinirim. Sorularınızı bekliyorum.  İyi günler!!!
Maker by : Alperen Alpaydın   
     TEŞEKKÜR İÇİN REP BUTONUNU KULLANINIZ



Cevapla
#2
peki birden fazla aynı sensörü(aynı adrese sahip) kullanırsak nasıl yapmamız gerekiyor
Ara
Cevapla
#3
Adresleri degistirilebiliyor kisa devre ile.
Maker by : Alperen Alpaydın   
     TEŞEKKÜR İÇİN REP BUTONUNU KULLANINIZ



Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
Lightbulb nRF24L01 - KABLOSUZ ALICI/VERİCİ HABERLEŞME MODÜLÜ z1rqdym 32 17,154 15-02-2018, Saat: 20:39
Son Yorum: sakgoo
  Xbee ile Haberleşme taco111 0 391 24-07-2017, Saat: 03:39
Son Yorum: taco111
  Hc- 06 veya infrared alıcı ile haberleşme Bayfenci 1 314 20-07-2017, Saat: 02:49
Son Yorum: Online
Exclamation NRF24L01 İLE ARAÇLAR ARASI SERİ HABERLEŞME YAPAMADIM VeyselCan ERKAN 4 690 04-03-2017, Saat: 21:40
Son Yorum: z1rqdym
Photo C# ve arduino UDP Cliend haberleşme mesutgul55 1 528 24-02-2017, Saat: 15:55
Son Yorum: mesutgul55

Hızlı Menü:


Konuyu Okuyanlar:
1 Ziyaretçi