Arduino ile MCP2515 CANBUS-SPI Modülü Kullanımı

Arduino ile MCP2515 CAN Bus modülü kullanımı, otomotiv projelerinden, asansör projelerine kadar bir çok alanda karşınıza çıkabilecek bir iletişim protokolü olan CAN Bus veri yolunda çalışan bir modüldür.

Denetleyici Alan Ağı anlamına gelen CAN Bus, genellikle endüstriyel ve otomotiv ortamlarında kullanılan bir tür seri iletişimdir. CAN Bus uygulamasının gerçek örneği, arabaların göstergesine aktarılabilen hız verisidir, hatta asansör çağırma düğmesine bastığınız anda bile CAN Bus veri yolunu kullanıyoruz.

CAN Bus hakkında daha fazla bilgi almak için bu yazımıza bakabilirsiniz.

CAN Bus, çoklu cihaz iletişimi için kullanılabilen mesaj tabanlı bir protokoldür. Aşağıdaki şekil, birkaç CAN cihazı bir ağ gibi birbirine bağlandığında, her cihazın düğümdeki diğer cihazlarla iletişim kurabileceğini gösterir. Genel olarak, CAN iletişim aralığı 50Kbps ila 1Mbps aralığındadır ve mesafe aralığı 40 metre (1 Mbps’de) ila 1000 metre (50 kbps’de) arasındadır.

Arduino ile MCP2515 CANBUS-SPI Modülü Kullanımı mcp2515,mcp2515 canbus-spi haberleşme modülü,canbus-spi,canbus,arduino ile mcp2515 canbus-spi

Bu iletişimde veriler belirli bir mesaj formatında aktarılır. Her mesaj birçok bölümden oluşur, ancak iki ana bölüm vardır: Tanımlayıcı ve Veri. Tanımlayıcı veya CAN Kimliği veya Parametre Grup Numarası (PGN) olarak bilinen, CAN ağındaki CAN cihazını tanımlamak için CAN protokolüne dayalı olarak genellikle 11 (Standart CAN) veya 29 bit (Genişletilmiş CAN) uzunluğunda kullanılır. Veri, gönderilecek mesaj içeriği iken, genellikle 0 ila 8 bayt uzunluğundadır.

CAN Mesaj Formatı

CAN iletişiminde veriler ağda belirli bir mesaj formatı olarak iletilir. Bu mesaj formatı birçok segment içerir, ancak iki ana segment, CAN veri yolunda mesajların gönderilmesine ve yanıtlanmasına yardımcı olan tanımlayıcı ve verilerdir.

Tanımlayıcı veya CAN Kimliği

Tanımlayıcı aynı zamanda CAN ID veya PGN (Parametre Grup Numarası) olarak da bilinir. Bir CAN ağında bulunan CAN cihazlarını tanımlamak için kullanılır. Tanımlayıcının uzunluğu, kullanılan CAN protokolünün türüne bağlı olarak ya 11 ya da 29 bittir.

Standart CAN: 0-2047 (11-bit)

Genişletilmiş CAN: 0-229-1 (29-bit)

Veri: Bu, bir cihazdan diğerine gönderilmesi gereken gerçek sensör/kontrol verileridir. Boyut verileri, 0 ila 8 bayt uzunluğunda herhangi bir yerde olabilir.

Veri Uzunluğu Kodu (DLC): Mevcut veri bayt sayısı için 0 ila 8.

CAN’da kullanılan kablolar:

CAN Protokolü, mesajı göndermek ve almak için CAN_H ve CAN_L olmak üzere iki kablodan oluşur. Bu iki kablo, CAN sinyalinin aralarındaki potansiyel farkla temsil edildiği bir diferansiyel hat görevi görür. Fark pozitif ve belirli bir minimum voltajdan büyükse, sinyal 1’dir ve aralarındaki fark negatifse 0 olacaktır.

Normalde CAN iletişimi için çift bükümlü bir kablo kullanılır. CAN ağının iki ucunda genellikle resimde gösterildiği gibi tek bir 120 ohm direnç kullanılır, bunun nedeni hattın dengelenmesi ve aynı potansiyele bağlanması gerektiğidir.

Bu projede, DHT11 sensöründen sıcaklık verisi göndermek için iki Arduino arasında iletişim kurmak için MCP2515 modülü ile CAN Bus iletişimini uygulayacağız. Bu modül, çalışma voltajı olarak 5V kullanır ve aşağıdaki tabloda gösterildiği gibi pin çıkışı konfigürasyonuna sahiptir.

Arduino ile MCP2515 CANBUS-SPI Modülü Kullanımı mcp2515,mcp2515 canbus-spi haberleşme modülü,canbus-spi,canbus,arduino ile mcp2515 canbus-spi
Pin AdıKullanım
VCC5V giriş
GNDGND(topraklama)
CSSPI bağımlı seçme pini
SOSPI ana giriş bağımlı çıkış
SISPI ana çıkış bağımlı giriş
SCKSPI saat pini
INTInterrupt pini

Slave = Bağımlı , Master = Ana

SPI ve I2C üzerinden CAN karşılaştırması

Arduino ile SPI ve Arduino ile IIC kullanmayı zaten öğrendiğimize göre, SPI ve I2C özelliklerini CAN ile karşılaştıralım.

ParameterSPII2CCAN
Hız3Mbps – 10MbpsStandart: 100Kbps10KBps – 1MBps Ayrıca kullanılan telin uzunluğuna da bağlıdır
Hızlı: 400 Kbps
Yüksek hızlı:3.4Mbps
TipSenkronSenkronAsenkron
Kablo Sayısı3+ (MISO, MOSI, SCK, SS1, SS2…SS(n))2 kablo (SDA, SCL)2 kablo (CAN_H, CAN_L)
DuplexFull Duplex(tam çift yön)Half Duplex(yarım yön)Half Duplex(yarım yön)

CAN Bus Uygulamaları

  • CAN protokolünün sağlamlığı ve güvenilirliği nedeniyle otomotiv, endüstriyel makineler, tarım, tıbbi ekipman vb. sektörlerde kullanılmaktadır.
  • CAN’da kablolama karmaşıklığı azaldığından, bunlar esas olarak araba gibi otomotiv uygulamalarında kullanılır.
  • Düşük maliyetli uygulama ve ayrıca donanım bileşenleri fiyatı da daha düşüktür.
  • CAN veri yolu cihazlarını eklemek ve çıkarmak kolaydır.

Arduino’da CAN Protokolü Nasıl Kullanılır?

Arduino herhangi bir dahili CAN Bus portu içermediği için MCP2515 adlı bir CAN modülü kullanılmaktadır. Bu CAN modülü, SPI iletişimi kullanılarak Arduino ile arayüzlenir. MCP2515 hakkında ayrıntılı olarak ve Arduino ile nasıl arayüzlendiğini görelim.

Arduino ile MCP2515 CANBUS-SPI Modülü Kullanımı mcp2515,mcp2515 canbus-spi haberleşme modülü,canbus-spi,canbus,arduino ile mcp2515 canbus-spi
MCP2515 CAN Modülü

MCP2515 modülü, yüksek hızlı CAN alıcı-vericisi olan bir CAN denetleyicisi MCP2515’e sahiptir. MCP2515 ve MCU arasındaki bağlantı SPI üzerinden yapılır. Bu nedenle, SPI arayüzüne sahip herhangi bir mikrodenetleyici ile arayüz oluşturmak kolaydır.

CAN Bus öğrenmek isteyen yeni başlayanlar için bu modül iyi bir başlangıç olacaktır. Bu CAN SPI kartı, endüstriyel otomasyon, ev otomasyonu ve diğer otomotiv gömülü projeleri için idealdir.

MCP2515’in Özellikleri

  • Yüksek hızlı CAN alıcı-verici TJA1050 kullanır
  • Boyut: 40×28mm
  • Çoklu CAN veri yolu arayüzünü genişletmek için SPI kontrolü
  • 8MHZ kristal osilatör
  • 120Ω terminal direnci
  • Bağımsız anahtar, LED göstergesi, Güç göstergesi vardır
  • 1 Mb/sn CAN işlemini destekler
  • Düşük akım bekleme işlemi
  • 112 düğüme kadar bağlanabilir

Gerekli Malzemeler

Devre Şeması

Burada isterseniz i2c destekli bir 16X2 LCD ekran kullanabilirsiniz. Bu yazımızda LCD kullanımı anlattık, I2C kısmına bakarsanız yapmanız gerekenleri anlayacaksınız.

Arduino ile MCP2515 CANBUS-SPI Modülü Kullanımı mcp2515,mcp2515 canbus-spi haberleşme modülü,canbus-spi,canbus,arduino ile mcp2515 canbus-spi
MCP2515 (Verici)Arduino Nano(Verici)
VCC+5V
GNDGND
CSD10
SOD12
SID11
SCKD13
INTD2
DHT11Arduino Nano(Verici)
VCC+5V
GNDGND
OUTA0
MCP2515 (Alıcı)Arduino Uno(Alıcı)
VCC+5V
GNDGND
CSD10
SOD12
SID11
SCKD13
INTD2
16×2 LCDArduino Uno(Alıcı)
VSSGND
VDD+5V
V010KΩ potansiyometre
RS3
RWGND
E4
D45
D56
D67
D78
A+5V
KGND

İki MCP2515 CAN Modülü Arasındaki Bağlantı

H – CAN High

L – CAN Low

MCP2515 UNOMCP2515 NANO
HH
LL

Tüm bağlantılar yapıldıktan sonra donanımım aşağıdaki gibi görünür.

Arduino ile MCP2515 CANBUS-SPI Modülü Kullanımı mcp2515,mcp2515 canbus-spi haberleşme modülü,canbus-spi,canbus,arduino ile mcp2515 canbus-spi

Arduino Kodu

Öncelikle Arduino IDE’de CAN için bir kütüphane kurmamız gerekiyor. MCP2515 CAN Modülünü Arduino ile arayüzlemek, aşağıdaki kütüphaneyi kullanarak daha kolay hale gelir. Eğer kütüphane kurmayı bilmiyorsanız, bu yazımıza bakabilirsiniz.

Bu eğitimde kodlama, biri CAN verici kodu (Arduino Nano) ve diğeri CAN Alıcı kodu (Arduino UNO) olmak üzere iki bölüme ayrılmıştır ve her ikisi de bu sayfanın altında bulunabilir. Öncelikle kod açıklamlarını yapıp ardından tam kodu vereceğiz.

Veri gönderme ve alma programı yazmadan önce yukarıdaki adımları takip ederek kütüphaneyi kurduğunuzdan ve CAN modülü MCP2515’in aşağıdaki gibi programınızda başlatıldığından emin olun.

MCP2515 CAN Modülünü Başlatma

MCP2515 ile bağlantı oluşturmak için aşağıdaki adımları izleyin:

SPI CS’nin bağlı olduğu pin numarasını ayarlayın (varsayılan olarak 10)

MCP2515 mcp2515(10);

Baud hızını ve osilatör frekansını ayarlayın:

mcp2515.setBitrate(CAN_125KBPS, MCP_8MHZ);

Mevcut Baud Hızları:

CAN_5KBPS, CAN_10KBPS, CAN_20KBPS, CAN_31K25BPS, CAN_33KBPS, CAN_40KBPS, CAN_50KBPS, CAN_80KBPS, CAN_83K3BPS, CAN_95KBPS, CAN_100KBPS, CAN_125KBPS, CAN_200KBPS, CAN_250KBPS, CAN_500KBPS, CAN_1000KBPS.

Mevcut Saat Hızları:

MCP_20MHZ, MCP_16MHZ, MCP_8MHZ

Modları ayarlayın:

mcp2515.setNormalMode();
mcp2515.setLoopbackMode();
mcp2515.setListenOnlyMode();

CAN Verici Kod Açıklaması (Arduino Nano)

Verici bölümünde, Arduino Nano, MCP2515 CAN modülü ile SPI pinleri aracılığıyla arayüz oluşturur ve DHT11, Sıcaklık ve Nem verilerini CAN bus’a gönderir.

Öncelikle gerekli kütüphaneler, SPI İletişimini kullanmak için SPI Kütüphanesi, CAN İletişimini kullanmak için MCP2515 Kütüphanesi ve Arduino ile DHT sensörünü kullanmak için DHT Kütüphanesi dahildir. Daha önce DHT11’i Arduino ile arayüzlemiştik.

#include <SPI.h>          
#include <mcp2515.h>      
#include <DHT.h> 

Artık Arduino Nano’nun A0’ına bağlı olan DHT11’in (OUT pini) pin adı tanımlanmıştır.

#define DHTPIN A0       

Ayrıca DHTTYPE, DHT11 olarak tanımlanır.

#define DHTTYPE DHT11

CAN mesaj biçimini depolamak için bir canMsg yapı veri türü oluşturulur.

struct can_frame canMsg;

SPI CS’nin bağlı olduğu pin numarasını ayarlayın (varsayılan olarak 10)

MCP2515 mcp2515(10);

Ayrıca, Arduino Nano ile DHT pinli DHT sınıfı için dht nesnesi ve DHT11 olarak DHT tipi başlatılır.

DHT dht(DHTPIN, DHTTYPE);     

void setup():

Aşağıdaki ifadeyi kullanarak SPI iletişimine başlayın

SPI.begin();               

Ardından DHT11 sensöründen sıcaklık ve nem değerlerini almaya başlamak için aşağıdaki ifadeyi kullanın.

dht.begin();               

Daha sonra MCP2515, aşağıdaki komut kullanılarak sıfırlanır.

mcp2515.reset();

MCP2515, saat olarak 500KBPS ve 8MHZ hıza ayarladık:

mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ); 

Ve MCP2525 normal moda ayarlanmıştır:

mcp2515.setNormalMode();

void loop()

Aşağıdaki ifade nem ve sıcaklık değerini alır ve h ve t tamsayı değişkeninde saklar.

int h = dht.readHumidity();       
int t = dht.readTemperature();    

Daha sonra CAN ID 0x036 (Seçime göre) ve DLC 8 olarak veriliyor ve h ve t datasını data[0] ve data[1]’e veriyoruz ve tüm datayı 0 ile bekletiyoruz.

canMsg.can_id  = 0x036;           
canMsg.can_dlc = 8;               
canMsg.data[0] = h;       //nem degeri [0]
canMsg.data[1] = t;   //sicaklik degeri [1]
canMsg.data[2] = 0x00;            //dinlendirme
canMsg.data[3] = 0x00;
canMsg.data[4] = 0x00;
canMsg.data[5] = 0x00;
canMsg.data[6] = 0x00;
canMsg.data[7] = 0x00;

CAN BUS’a mesaj göndermek için aşağıdaki ifadeyi kullanıyoruz.

mcp2515.sendMessage(&canMsg);     

Böylece sıcaklık ve nem verileri mesaj olarak CAN bus’a gönderilir.

CAN Alıcı Kod Açıklaması (Arduino Uno)

Alıcı bölümünde Arduino UNO, MCP2515 ve 16×2 LCD ekran ile arayüzlenmiştir. Burada Arduino UNO, CAN veri yolundan sıcaklık ve nemi alır ve alınan verileri LCD’de görüntüler.

Öncelikle gerekli kütüphaneler, SPI İletişimini kullanmak için SPI Kütüphanesi, CAN İletişimini kullanmak için MCP2515 Kütüphanesi ve Arduino ile 16×2 LCD kullanmak için LiquidCrsytal Kütüphanesi dahildir.

#include <SPI.h 
#include <mcp2515.h>          
#include <LiquidCrystal.h>  

Ardından Arduino UNO ile bağlantıda kullanılan LCD pinleri tanımlanır. Burada isterseniz I2C kullanabilirsiniz fakat kütüphaneyi I2C olarak değiştirip Wire kütüphanesini dahil etmeniz gerekir.

const int rs = 3, en = 4, d4 = 5, d5 = 6, d6 = 7, d7 = 8;  
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);  

CAN mesaj biçimini depolamak için bir yapı veri türü belirtilir:

struct can_frame canMsg; 

SPI CS’nin bağlı olduğu pin numarasını ayarlanır (varsayılan olarak 10)

MCP2515 mcp2515(10);                  

void setup()

LCD 16×2 moduna ayarlanır ve bir karşılama mesajı görüntülenir.

lcd.begin(16,2);                   
lcd.setCursor(0,0);                
lcd.print("devreyakan.com");
lcd.setCursor(0,1);
lcd.print("CAN ARDUINO");
delay(3000);
lcd.clear();

Aşağıdaki ifadeyi kullanarak SPI iletişimine başlatın.

SPI.begin();                         

Daha sonra MCP2515, aşağıdaki komut kullanılarak sıfırlanır.

mcp2515.reset();

MCP2515, saat olarak 500KBPS ve 8MHZ hıza ayarladık:

mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ); 

Ve MCP2525 normal moda ayarlanmıştır:

mcp2515.setNormalMode();

void loop()

CAN veriyolundan mesajı almak için aşağıdaki ifade kullanılır. Mesaj alınırsa if durumuna geçer:

if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)

if durumunda veriler canMsg’de alınır ve saklanır, nem değeri olan data[0] ve sıcaklık değeri olan data[1]. Her iki değer de bir x ve y tamsayısında saklanır.

int x = canMsg.data[0];         
int y = canMsg.data[1];

Değerler alındıktan sonra sıcaklık ve nem değerleri aşağıdaki ifade kullanılarak 16×2 LCD ekranda görüntülenir.

lcd.setCursor(0,0);          
lcd.print("Nem : ");     
lcd.print(x);
lcd.setCursor(0,1);
lcd.print("Sicaklik : ");
lcd.print(y);
delay(1000);
lcd.clear();

Donanım hazır olduğunda, CAN vericisi ve CAN alıcısı için programı (tam programlar aşağıda verilmiştir) ilgili Arduino kartlarına yükleyin. Güç verildiğinde, DHT11 tarafından okunan sıcaklık değerinin CAN iletişimi aracılığıyla başka bir Arduino’ya gönderilir.

Arduino Kodları

Verici Kodu
#include <SPI.h>
#include <mcp2515.h>
#include <DHT.h>

#define DHTPIN A0
#define DHTTYPE DHT11

struct can_frame canMsg;

MCP2515 mcp2515(10);
DHT dht(DHTPIN, DHTTYPE);

void setup()

{
  while (!Serial);
  Serial.begin(9600);

  SPI.begin();
  dht.begin();

  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();

}

void loop()

{
  int h = dht.readHumidity();
  int t = dht.readTemperature();

  canMsg.can_id  = 0x036;
  canMsg.can_dlc = 8;
  canMsg.data[0] = h;
  canMsg.data[1] = t;
  canMsg.data[2] = 0x00;
  canMsg.data[3] = 0x00;
  canMsg.data[4] = 0x00;
  canMsg.data[5] = 0x00;
  canMsg.data[6] = 0x00;
  canMsg.data[7] = 0x00;

  mcp2515.sendMessage(&canMsg);

  delay(1000);

}
Alıcı Kodu
#include <SPI.h>
#include <mcp2515.h>
#include <LiquidCrystal.h>

const int rs = 3, en = 4, d4 = 5, d5 = 6, d6 = 7, d7 = 8;

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

struct can_frame canMsg;

MCP2515 mcp2515(10);



void setup() {
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("devreyakan.com");
  lcd.setCursor(0, 1);
  lcd.print("CAN ARDUINO");
  delay(3000);

  lcd.clear();
  SPI.begin();
  Serial.begin(9600);


  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();

}

void loop()

{

  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
  {

    int x = canMsg.data[0];
    int y = canMsg.data[1];


    lcd.setCursor(0, 0);
    lcd.print("Nem : ");
    lcd.print(x);
    lcd.setCursor(0, 1);
    lcd.print("Sicaklik : ");
    lcd.print(y);

    delay(1000);
    lcd.clear();
  }
}