Arduino Uno互換機でCAN送信機を作ってみた(4byte送信)

#初めに
今回は、CAN(Controller Area Network)通信の受信テストをするときに必要なCAN送信機をArduino Uno互換機で作ってみました。

私は、4byteの送信しか必要なかったので、4byteしか送信できません。

github:https://github.com/Yu-Tomo/CAN_test_sender

#概要
Arudino IDEからシリアルモニタを使ってCAN IDとデータを決めて送信します。
データの順番は、ビッグエンディアンです。

10進数入力と16進数入力に対応しています。

0x~~と書くと16進数になります。10進数はいつも通りです。
0sなどと書くとバグになります。テスト用なので悪しからず。

#使用するIC

使用するICはおなじみの、MCP2515とMCP2561です。

#回路
基本的な配線は、色々なサイトに記載されているため、割愛します。

#ソースコード

使用しているCANライブラリは、https://github.com/sandeepmistry/arduino-CAN から使わせてもらっています。


```C
#define CAN_CS 6
#define CAN_INT 2
```
ソースコードの上の部分を、お使いのマイコンに合わせて変更してください。

```C
#define CAN_CS 6
#define CAN_INT 2

#include <CAN.h>
#include <string.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
  Serial.println("CAN sender start!");
}
void loop() {
  uint16_t uiCan_id;
  int iByte;
  long lCan_data;
  unsigned char ucSend[4];
  uint8_t ucWork;
  
  while (1)
  {
    uiCan_id = 0;
    iByte = 0;
    lCan_data = -1;
    ucWork = 0;

    for (int i = 0; i < 4; i++)
    {
      ucSend[i] = 0;
    }
    
    Serial.println("Please input CAN_ID : ");
    uiCan_id = SerialInput();
    Serial.print("OK! Your inputing is (DEC) : ");
    Serial.print(uiCan_id);
    Serial.print(" (HEX) : 0x");
    Serial.println(uiCan_id, HEX);

    while (!((lCan_data >= 0 ) && (lCan_data <= 0x7FFFFFFF)))
    {
      Serial.println("Please input your sending data :");
      lCan_data = SerialInput();
    }

    Serial.print("OK! Your inputing is (DEC) : ");
    Serial.println(lCan_data);
    Serial.print("Your inputing is (HEX) : ");
    Serial.print("0x");
    Serial.println(lCan_data, HEX);

    for (int i = 3 ; i >= 0; i--)
    {
      ucWork = lCan_data >> 8 * (3-i);
      ucSend[i] = ucWork;
    }
    Serial.println("Big Endian");
    Serial.println("Sending packet ... ");
    CAN.beginPacket(uiCan_id);
    for (int i = 0; i < 4; i++)
    {
      CAN.write(ucSend[i]);
      Serial.print("0x");
      Serial.println(ucSend[i], HEX);
    }
    CAN.endPacket();
    Serial.println("done");
    delay(1000);
  }
}
long SerialInput(void)
{
  int iByte_cnt = 0;
  long work = 0;
  char ucData[256];
  char dec_hex = 1;         //0以外の時dec
  while (!Serial.available())
  {

  }
  delay(10);
  
  iByte_cnt = Serial.available();
  
  for (int i = 0; i < iByte_cnt; i++)
  {
    ucData[i] = Serial.read();
  }
  
  //改行コードがOSによって異なるため、有効文字の数を数える
  iByte_cnt = String_len(&ucData[0]);
  dec_hex = strncmp(ucData, "0x", 2);

  //入力がHEX
  if (dec_hex == 0)
  {
    Serial.println("HEX ");

    for (int i = 2; i < iByte_cnt; i++)
    {
      work <<= 4;
      if ((ucData[i] >= '0') && (ucData[i] <= '9'))
      {
        //'0'~'9'をHEXに変換
        work |= (ucData[i] - 0x30);
      }
      else if ((ucData[i] >= 'A') && (ucData[i] <= 'F'))
      {
        //'A'~'F'をHEXに変換
        work |= (ucData[i] - 0x37);
      }
      else if ((ucData[i] >= 'a') && (ucData[i] <= 'f'))
      {
        //'a'~'f'をHEXに変換
        work |= (ucData[i] - 0x57);
      }
      else
      {
        //異常終了
        return -1;
      }
    }
  }
  //入力がDEC
  else
  {
    Serial.println("DEC");
    for (int i = 0; i < iByte_cnt; i++)
    {
      work *= 10;
      work += (ucData[i] - 0x30);
    }
  }
  return work;
}
int String_len(char* str)
{
  int iCnt = 0;
  while ((*str >= 0x30 ) && (*str <= 0x7a))
  {
    str++;
    iCnt++;
  }
  return iCnt;
}
```

#使い方

CAN通信用ICを取り付けたArduino Unoにソースコードを書きこみます。
その後シリアルモニタを開きます。

![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485495/cb1a2061-0162-f7bb-fc2e-324e7c953b38.jpeg)
この画面になります。

![SharedScreenshot2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485495/412dda7c-c119-ba5d-9823-12fe009dcdb0.jpeg)

まず、CAN IDを決めます。今回は CAN IDを0x102とします。 
(16進数だったら、黄色の矢印のように0x---と入力します。2byteです。)
入力したらEnterで送信します。

![SharedScreenshot3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485495/62b3a871-3af4-4aff-444d-dfb134892d51.jpeg)

そうすると、入力した値の10進数と16進数を表示してきます。

この後は、先ほど入力したCAN IDで送りたいデータを入力します。4byteです。

![SharedScreenshot4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485495/b22a84e5-94af-19c2-8462-1468658b50a1.jpeg)

10進数を入力したいときはこのように入力します。

![SharedScreenshot5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485495/9950d50d-9189-db69-16ce-7e349a3e1afd.jpeg)

Enterで送信すると、入力したCAN IDでCANにデータを送信してくれます。
データはビッグエンディアンです。

while(1)で処理しているので、リセットボタンを押さずに続けて使えます。


#終わりに
手元にCANアナライザーがなかったので作りました。
製品には比べ物にならないですが、自分で使う分には十分です。