아두이노 Arduino

[아두이노] 1:1 캔통신 연결하기(Arduino, CAN Communication, Bus, MCP2515)

끄적끄적아무거나 2024. 1. 5. 08:38
반응형

 

목차

     

     

     

     

     

     

    [아두이노] 1:1 캔통신 연결하기: 준비


    이번 실습에서는 MCP2515 CAN 통신 트랜시버를 사용하여 아두이노 보드 간의 1대1 통신을 진행할 것입니다. MCP2515는 Controller Area Network (CAN) 프로토콜을 지원하는 트랜시버로, 자동차 및 산업용 기기에서 널리 사용되는 통신 방식입니다.

     

    먼저, 아두이노 프로그래밍을 위해 아래 웹사이트에서 MCP2515 라이브러리를 zip 파일로 다운로드 받습니다. 이 라이브러리는 아두이노와 MCP2515 모듈 간의 통신을 용이하게 해주며, 송수신 코드를 구현하는 데 필요한 함수들을 포함하고 있습니다.

    https://github.com/autowp/arduino-mcp2515

     

    실습에서는 두 아두이노 우노 보드를 사용합니다. 하나는 송신측으로, 다른 하나는 수신측으로 설정됩니다. 송신측에서는 수신측의 ID와 데이터 길이(DLC, Data Length Code) 값을 전송합니다. 이 정보는 CAN 프레임의 일부로, 수신측이 올바른 데이터를 수신하고 해석할 수 있도록 합니다.

     

    수신측 아두이노는 별도의 필터링 없이 CAN 버스 라인 상의 모든 데이터를 읽습니다. CAN 시스템에서 데이터는 프레임 형식으로 전송되며, 각 프레임에는 식별자(ID)와 데이터 필드가 포함됩니다.

     

     

    이 실습을 위해 필요한 재료는 다음과 같습니다.

     

    • 2개의 아두이노 우노 보드
    • 2개의 MCP2515 CAN 통신 모듈
    • 다수의 점퍼 케이블

     

     

    아두이노 보드와 MCP2515 모듈의 핀 연결은 아래와 같습니다.

     

    • D2 → INT (인터럽트)
    • D13 → SCK (시리얼 클록)
    • D12 → SO (시리얼 아웃)
    • D11 → SI (시리얼 인)
    • D10 → CS (칩 셀렉트)

     

    두 MCP2515 모듈은 서로 High(H) 핀은 High(H)끼리, Low(L) 핀은 Low(L)끼리 연결해야 합니다. 이 연결은 모듈 간의 통신을 가능하게 하며, 안정적인 데이터 전송을 보장합니다.

     

     

     

     

     

    [아두이노] 1:1 캔통신 연결하기: 실습

    1. 라이브러리를 ZIP 파일로 아두이노에 추가하면 아래와 같이 예제 파일이 만들어 집니다.

     

     

    2. 아두이노 보드 하나에는 CAN_write를 프로그램 하고 다른 하나는 CAN_read를 프로그램 합니다. 각 각의 코드는 아래와 같습니다.

     

    CAN_write 코드>>

    #include <SPI.h>
    #include <mcp2515.h>
    
    struct can_frame canMsg1;
    struct can_frame canMsg2;
    MCP2515 mcp2515(10);
    
    
    void setup() {
      canMsg1.can_id  = 0x0F6; //슬레이브1의 ID
      canMsg1.can_dlc = 8;
      canMsg1.data[0] = 0x8E;
      canMsg1.data[1] = 0x87;
      canMsg1.data[2] = 0x32;
      canMsg1.data[3] = 0xFA;
      canMsg1.data[4] = 0x26;
      canMsg1.data[5] = 0x8E;
      canMsg1.data[6] = 0xBE;
      canMsg1.data[7] = 0x86;
    
      canMsg2.can_id  = 0x036; //슬레이브2의 ID
      canMsg2.can_dlc = 8;
      canMsg2.data[0] = 0x0E;
      canMsg2.data[1] = 0x00;
      canMsg2.data[2] = 0x00;
      canMsg2.data[3] = 0x08;
      canMsg2.data[4] = 0x01;
      canMsg2.data[5] = 0x00;
      canMsg2.data[6] = 0x00;
      canMsg2.data[7] = 0xA0;
      
      while (!Serial);
      Serial.begin(115200);
      
      mcp2515.reset();
      mcp2515.setBitrate(CAN_125KBPS);
      mcp2515.setNormalMode();
      
      Serial.println("Example: Write to CAN");
    }
    
    void loop() {
      mcp2515.sendMessage(&canMsg1);
      mcp2515.sendMessage(&canMsg2);
    
      Serial.println("Messages sent");
      
      delay(500);
    }

    위 코드는 2개의 캔 메세지를 0.5초 단위로 전송합니다. 각 메세지는 8바이트 사이즈이고 ID는 코드를 참조하시면 됩니다.

    캔 속도는 125kbps로 설정되었습니다.

     

     

     

    CAN_read 코드>>

    #include <SPI.h>
    #include <mcp2515.h>
    
    struct can_frame canMsg;
    MCP2515 mcp2515(10);
    
    
    void setup() {
      Serial.begin(115200);
      
      mcp2515.reset();
      mcp2515.setBitrate(CAN_125KBPS);
      mcp2515.setNormalMode();
      
      Serial.println("------- CAN Read ----------");
      Serial.println("ID  DLC   DATA");
    }
    
    void loop() {
      if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
        Serial.print(canMsg.can_id, HEX); // print ID
        Serial.print(" "); 
        Serial.print(canMsg.can_dlc, HEX); // print DLC
        Serial.print(" ");
        
        for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
          Serial.print(canMsg.data[i],HEX);
          Serial.print(" ");
        }
    
        Serial.println();      
      }
    }

     

     

    3. 아래와 같이 수신측의 Serial Monitoring을 통해 정상적으로 캔 메세지를 출력함을 알 수 있습니다.

     

     

     

    반응형