SPI Haberleşme ve Arduino ile SPI Ağ Kurma
|Merhabalar…
Bu konuda SPI haberleşmenin ne olduğuna ve 3 Arduino arasında SPI haberleşme protokolü ile ağ kurup haberleştirmeye değineceğiz.
Öncelik SPI haberleşmenin ne olduğuna bakalım.
Açılımı Serial Peripheral Interface olan ve full dublex olarak çalışan bir haberleşme tekniğidir. Buradaki Full dublex’ in anlamı veri alma ve gönderme işlemini eş zamanlı olarak gerçekleştirebilmesidir. İletişim Master ve slave cihalar arasında gerçekleşir. Master cihaz iletişim kurmak istediği cihazı seçer ve o cihazla iletişime geçer. Bu seçme işini SPI donanımı dahilinde olan SS(Slave Select) pini ile yapar. Master cihazda SS pini kendimiz belirlememiz mümkün ancak slave cihazların SPI donanımında dahil olan SS pini kullanılmalıdır. Bunun sebebini ve nasıl yapıldığını aşağıda değineceğiz.
SPI iletişimi iki cihaz arası basit olarak şekildeki gibidir. Donanım dahilinde olan pinlerin ne oldukları tablodaki gibidir.
SCK haberleşme için kare dalga oluşturur. İletişim bu sinyalin farklı konumlarında gerçekleşebilir. Master cihaz kare dalgayı oluşturması gereken cihazdır.
MOSI haberleşme de Master cihazdan Slave cihazlara giden veri yolunu oluşturur.
MISO haberleşme de Slave cihazdan Master cihaza giden veri yolunu oluşturur.
SS yukarıda da belirttiğimiz gibi Master cihazın Slave cihazları seçmesine yarar. 2 cihaz iletişimi için tek SS pini yeterlidir. Burada dikkat edilmesi gereken donanımda SS pinin üzeri çizgi olmasıdır. Bu çizgi slave seçimi için pinin Ljik-0′ a çekilmesi gerektiğini gösterir.
SPI, I2C gibi iletişim tekniklerine göre daha hızlıdır. 2 den fazla cihaz için bile olsa adresleme gibi işlemler gerektirmez(I2C’ den ayıran özellik). Aynı kablo üzerinden farklı cihazlara farklı verileri aktarabilir (RS-232 den ayıran özellik).
Şimdi gelelim SPI ile birden fazla cihaz arasında iletişim kurmaya.
Artık Slave cihazlarımızın sayısı arttı. Bu yüzden Slave Select Pin sayımızı da arttırmamız gerekir. Yadaki resimde 1 Master ve 3 Slave cihaz arası iletişim gösterilmiştir. 3 Slave cihaz olduğu için 3 SS pini toplamda 6 pin kullandık. Bunu basit bir formülle N tane cihaz için 3 + N tane pin kullanılması gerekir şeklinde düşünebiliriz.
Şekildeki tüm cihazlarda tek SPI donanımı olduğunu farz edelim. Bu durumda master cihaz tek SS pinine sahip demektir. Ancak 3 cihaz ile iletişime geçmemiz gerektiğinden kendimiz SS pinleri belirlemeli ve onları Slave cihazların SPI donanımında bulunan SS pinlerine bağlamamız gerekir. Bu işlem için denetleyicimizin herhangi bir dijital pinini çıkış olarak tanımlayıp, Lojik durumunu veri aktarmak istediğimiz cihaza bağlı olana göre değiştirmemiz yeterlidir. Ancak Slave cihazların bu çağrıya cevap verebilmeleri için kesinlikle donanımsal SS pinleri kullanılmalıdır. Aksi taktirde iletişim gerçekleşmez.
İletişimin Arduino kısmına gelelim. SPI iletişim için Arduino hazır bir kütüphane bulunmakta. Ancak bu kütüphane Arduino her zaman master konumda olacağı düşünülerek hazırlanmış ve iki Arduino arası iletişim için yeterli değildir. Bizde bu yüzden slave cihazlar için yazılımda kütüphanenin içine girmemiz gerekecek.
Ağmızı basit şekilde kuracağız Serial Monitörden yazdığımız veriyi SPI diğer Arduino’ lara aktaracak onlarda belirlediğimiz sıra ile bize veriyi geri döndürecekler. Ağda bulunması gereken Master cihaz için gerekli kod şu şekilde..
#include <SPI.h> byte gidenVeri; byte gelenVeri; int ssPin1 = 8; //Slave Select1 LOW seviyede aktif eder int ssPin2 = 9; //Slave Select2 LOW seviyede aktif eder void setup() { Serial.begin(115200); //Seri haberlşemeyi başlattık //SS leri çıkış ayarladık pinMode(ssPin1, OUTPUT); pinMode(ssPin2, OUTPUT); digitalWrite(ssPin1, HIGH); digitalWrite(ssPin2, HIGH); //SPI başlatıldı SPI.begin(); } void loop() { //seri haberleşme varken SPI ile veri gönderildi while(Serial.available() > 0) { gidenVeri = Serial.read(); gelenVeri = spiVeriOkuYaz(gidenVeri, ssPin1); Serial.write(gelenVeri); gelenVeri = spiVeriOkuYaz(gidenVeri, ssPin2); Serial.write(gelenVeri); } } //spi veriyi göndermek için fonksiyon //parametre olarak gönderilecek veriyi ve SS pini verilir byte spiVeriOkuYaz(byte dout, int pin) { byte din; digitalWrite(pin, LOW); delay(1); din = SPI.transfer(dout); digitalWrite(pin, HIGH); return din; }
Şimdi gelelim Slave cihazlara. Önceden de belirttiğimiz gibi Arduino’ yu Slave olarak kullanabilmek için SPI kütüphanesinin içerisine girmemiz gerekli. SPI kütüphanesinin veri aktarımı için kullandığımız register’ lere bi bakalım.
SPDR(SPI Data Register): Bu register SPI hattında aktarılacak veriyi tutar.
SPSR(SPI Status Register): SPI durumunu belirten register. Bit kaydırma işlemi ile sırada aktarılacak veri olup olmadığı kontrol edilebilir.
SPCR(SPI Control Register): SPI başlangıç ayarlarının yapıldığı register’ dir. İnterrupt setleme ve master slave ayarı bu register üzerinden yapılır. Aşağıdaki resimde bu registerin bitlerini görebilirsiniz.
Slave cihaz veri göndermek için Master cihazdan SS pinin aktif etmesini bekleyecektir. Bu pinin aktif olması durumunda da SPI Interreupt’ u devreye girip veriyi kaydedecek sonraki iletişimde geri gönderecektir. Burdan da anlaşılacağı gibi ilk iletişim denemesi NULL değer döndürecektir.
Şimdide Slave cihazların Kodları..
byte gonderilenVeri; byte dataToPc; void setup() { Serial.begin(115200); pinMode(MISO, OUTPUT); pinMode(SS , INPUT); //SPI Control Register //İnterreupt setlenip Slave mod ayarlanır/////// SPCR |= 0b11000000; //SPI status register SPSR |= 0b00000000; gonderilenVeri = 0; dataToPc = 0; sei(); //interreupt lar aktif edilir } void loop() { if(dataToPc != 0) { Serial.write(dataToPc); dataToPc = 0; } } ISR(SPI_STC_vect) { cli(); //interreuplar sıfırlarınır //SS pinin LOW iken yaz while(digitalRead(SS) == 0) { SPDR = gonderilenVeri; //SPI aktarımı bitene kadar bekle while(!(SPSR & (1 << SPIF))); gonderilenVeri = SPDR; } sei(); }
Bağlantı şemamız basit. herhangi bir ek elemana ihtiyaç yok. Sadece 3 adet Arduino ile iletişimi gerçekleştireceğiz. Bu konuda az kaynak bulunmakta ve bende yeniyim eksiğimiz veya hatamız varsa affola ..
Teşekkürler..
merhabalar. 3 tane RFID kart okuyucum var doğal olarak arduino ile spı protokolü üzerinden haberleşmem gerekiyor. bağlantı şeması yukarıdaki ile aynı mı olmalı ve slave cihaz herhangi bir veri göndermeyeceğim sadece almak istiyorum slave cihaza veri alması için yazdığınız kodları ben master cihaza yazarsam yanlış yapmam değil mi?
Merhaba..
Arduino kullanıyorsanız rfid kart ile kullanabileceğiniz kütüphanesi zaten mevcut. Yani sizin ekstra SPI protokolünü yazmanıza gerek yok. Bağlantınızı da dediğiniz gibi SPI pinlerine paralel şekilde bağlamalısınız. Sadece CS (chip select) pinlerini ayrı bağlamanız ve bu şekilde okuma işlemeni sıra ile yapmanız yeterli olacaktır.
İyi Çalışmalar.
merhaba,
SPI ile yapılacak bağlantıda kablo uzunluğu en fazla ne kadar olabilir.
yaklaşık 15 metreye kadar mesafede ardiuno kartlar arasında haberleşme yaptırmam gerekli. SPI kullanabilirmiyim? SPI kullanılamaz ise nasıl bir bağlantı kullanmamı önerebilirsiniz. Paylaşımınız için çok teşekkür ederim.
İyi çalışmalar.
Merhaba..
Daha önce hiç uzun mesafelerde veri aktarımı için SPI kullanmadım. Ki internette bakındığında da 5-6 metre den sonra kullanımı tavsiye edilmiyor. İhtiyaç halinde de daha yüksek gerilim seviyesinde olması en büyük etken olan RS232 yada RS485 kullandığını duymuştum. Bence sizde bir çeşit 12V seviyesinde veri transferi yapan haberleşme protokollerine yönelmelisiniz. 5V yada 3.3V seviyesinde uzun mesafelere veri aktarımında sorun yaşayabilirsiniz.
İyi çalışmalar.
Merhaba, elimde 1 adet Arduino mega 2560, 2 adet rc522 RFID reader ve 1 adet adafruit dc motor shield v.01 var. Mega’ya shield’i taktiğimda rc522 okuma yapmıyor. Shield SPI pinlerini kullanmıyor diye biliyorum ancak sorunu çözemedim ve SPI haberleşmesindeki bir çakışmadan kaynaklandığını düşünüyorum. Her kartı ayrı ayrı deneyip çalıştırmama rağmen shield mega’ya takılıyken RC522 okuma yapmıyor. Shield takılıyken
SCK-52,
MISO-50,
MOSI-51,
CS(chipselect,SS)-25,
RST-24 pinleri ile arduino’ya bağlıyorum.
Sorunu çözebilmem için yardımınızı bekliyorum.
Bu arada yazınızı çok beğendim çok açıklayıcı olmuş.
Şimdiden teşekkürler.
Merhaba, Arduino Mega üzerinde SPI pinleri sizin de kullandığınız gibi farklı yerlerde. Lakin CS pinini 25 olarak kullandığınızı yazmışsınız kütüphanede bu pin 53 olarak görünmekte. Bu pin tanımını doğru önişlemci direktifi ile yapmadan 25 numaralı pine bağladıysanız RFID okuyucunuz çalışmayacaktır. Sorununuz yine çözülmezse lütfen baser61061@gmail.com adresine mail atınız.
İyi çalışmalar…
Dostum sağlam bir konuya değinmişsin. Eline sağlık. En kısa zamanda bende bu spi yı destekleyen birkaç kart ile deneme yapacam.
Oğuzhan Bey, paylaştığınız değerli bilgiler için teşekkür eder, ayrıca giderek daha seyrek karşılaştığımız güzel Türkçe yazımınız için kutlarım.
Güzel yorumlarınız için teşekkür ederim. Lakin gün geçtikçce meşguliyetimiz arttığı için yazıların sıklıkları da malesef düşüyor ve yazı yazmak çok zaman alıyor. Bunun için gerçekten bende üzgünüm..
elimde rfm96w alıcı verici modülü mevcut.bu modülü arduino uno ve nano ile sorunsuz çalıştırıp bilgi alışverişinde bulanabiliryorum ama mega 2560 ile bunu başaramıyorum.modul spi haberleşme yöntemi ile çalışıyor. tüm bağlantılar doğru yapılmasına rağmen mega ile çalıştıramadım.modülün kütüphanesi ve spi kütüphanesi arasında bir uyumsuzluk fark ettim.verici modül kütüphanesi spi haberleşmeyi kapatıyor.bu sadece mega2560 da oluyor.buna anlam verermedim bu konuda bilgisi olan varmı?
Merhaba, Arduino Mega modelinin SPI pinleri Uno ve Nano’ ya göre farklı yerdedir. Sorununuzun kaynağı bu olabilir. Bağlantıdan kontrol edebilirsiniz. İyi çalışmalar dilerim…
hocam bağlantı bağlantı doğru https://github.com/sandeepmistry/arduino-LoRa kullandığım kütüphane ise bu.bu kütüphanenin içindeki lora dublex uygulması var.normalde bu kütüphanedeki komutlar spi iletişiminide başlatması gerekiyor.ama programın setup kısmına SPI.begin().komutu eklediğimde bir kere senkronu tutturursam 1 kere alma yapıyor.ss pinini ayırdığımda ise sürekli veri gönderiyor ama karşı taraf almıyor.dengesiz bir çalışmaya giriyor.
Merhaba, bahsettiğiniz modülü kullanmadım. Sadece Mega’ da sorun oluyor dediğiniz için pinleri 10 – 13 arasına bağlamış olabileceğinizi düşündüm. Eğer SPI olarak 51- 53 numaralı pinleri kullanıyorsanız sorun şudur diyebilmem pek mümkün değil. Ancak bağlantıdaki sayfada kullandığınız kütüphanenin Mega ile yaşanan sorunları mevcut. Belki sizinki de arakarında vardır. İncelemenizi tavsiye ederim. İyi çalışmalar dilerim…
merhaba. elimde bi tane aurdino mega ve 3 tanede nano var.bu nanoların kendi aralarında haberleşmesini sağlayıp bütün verilri aurdino megaya aktarmak istiyorum burada bunu haberlşeme modülleri ile mi yapmalıyım yoksa SPI haberlşeme ile mi yardımınıza ihtiyacım var
Merhaba, bahsettiğiniz işlem için SPI haberleşme kullanabilirsiniz. Ancak 3 nano’ nun arasında kullanmayı düşündüğünüz haberleşme modülünün ne olduğunu anlamadım. Sormak istediklerinizi baser61061@gmail.com mail adresine detaylı olarak gönderebilirsiniz. İyi çalışmalar dilerim…
merhaba arduino uno da rfıd yi çalıştırdım herhangi bir sıkıntı yok bütün komutlar doğru şekiilde çalışıyor ancak daha bir sıkıntı fark ettim oda şöyle ki ; rc522 modülüne farklı ıd ye sahip iki kart okuyorum biri programda tanımlı ama diğeri değil dogru olanı okutunca seri ekrandan hoş geldiniz yazdırdım yanlış olana yetkisiz giriş burda sıkıntı yok nacak kartları modülün en uzak mesafesinden artık 3-4 cm neyse herhangi bir ıd görmeden sadece hoş geldiniz yazıyor
Merhaba, sorununuzu tam anlamadım ama yazılımsal bir sorun olduğunu düşünüyorum. Daha detaylı olarak baser61061@gmail.com adresine gönderebilirseniz yardımcı olmaya çalışırım. İyi çalışmalar dilerim…
merhaba,
öncelikle emeğiniz için teşekkürler.
aklıma takılan bir durum söz konusu oldukça inceledim kodu gözümden kaçmasın diye fakat loop “dataToPc” değişkenini farklı bir yerde kullanılmamış sadece 0’lanmış.
Acaba “gonderilenVeri” ile karıştırılmış olması söz konusu mu ?
Merhaba, evet dediğiniz şekilde bir sorun olabilir. Kısa sürede kontrol etmeye çalışacağım. İyi çalışmalar dilerim..