ソフトウェアシリアルを使ってマイコンのデバッグを考える

# ソフトウェアシリアルを使ったマイコンのデバッグ
ATtiny85単体を使うことがあった。マイコン単体利用なので、Arduinoなどのボードように直接PCに接続し、シリアルコンソールにログ表示（デバッグ）をすることができない。ここでは、ATtiny85とArduinoを接続し、Arduino経由でPCにログ表示する方法を記載。

## ソフトウェアシリアル
ソフトウェアシリアルを使って、ATtiny85とArduinoとを接続する。要は、GPIO上でシリアル通信を実現するもの。[ここ](https://www.arduino.cc/en/Reference/SoftwareSerial)など、ソフトウェアシリアルについては多数の情報が見つかる。

## ATtiny85開発環境
話はそれるかもしれないが、ATtiny85の開発環境も本記事に記述。

### データシート
[ここ](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf)で見つかる。ピンアサインは次のとおり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/a6197e11-9923-67c5-b63b-c53054e4ea9e.png)

### USBasp
Arduino IDEを使って、ATtiny85へのプログラムの書き込みが可能である。書き込み装置として、USBaspを使う。[ここ](https://ht-deko.com/arduino/usbasp.html)に、書き込みのための配線やコネクタのピン配置について記載あり。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/7004ed20-f395-8187-d4d8-fd2ebe8c9819.jpeg", width=60%>
ブレッドボードの真ん中にあるものがATtiny85。

### プログラムの書き込み
Arduino IDEでは、「書込装置を使って書き込む」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/02f6137c-3ddd-f453-db1f-d7199ea107f9.png)

## ループバックでテスト
まずは、ループバックで確認。
　　PC - Arduino - ATtiny85
と接続し、PCのコンソールから入力した文字が、ATtiny85からPCへ戻ることを実施。 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/64cd7856-e73b-12b5-77a1-06f4009d2cea.jpeg", width=70%>

Arduino側コードはこちら（美しくないコードであるが勘弁）。

```c++:ArduinoSoftwareSerial.ino
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  mySerial.begin(4800);
  Serial.println("Setup is done.");
}

void loop()
{
  if (Serial.available()) {
    String data = Serial.readStringUntil('\n');
    for (int i = 0; i < data.length(); i++) {
      mySerial.write(data.charAt(i));
    }
  }
  if (mySerial.available()) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
    Serial.write(mySerial.read());
    digitalWrite(LED_BUILTIN, LOW);
    delay(400);
  }
}
```

ATtiny85側コードはこちら。

```c++:ATtiny85SoftwareSerial.ino
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 4); // RX, TX

#define LED 0

void setup()
{
  pinMode(LED, OUTPUT);
  mySerial.begin(4800);
}

void loop()
{
  if (mySerial.available()) {
    digitalWrite(LED, HIGH);
    delay(300);
    mySerial.write(mySerial.read());
    digitalWrite(LED, LOW);
    delay(200);
  }
}
```

ポイントは以下。
- SoftwareSerial mySerial(): ソフトシリアルの宣言
- Arduinoのピン10とATtiny85のピン4、Arduinoのピン11とATtiny85のピン3とを接続
なお、通信されていることを視覚化するため、LEDを用いている。

### ATtiny85のクロック
標準の8MHzではソフトウェアシリアルがうまく動作しなかっため（文字化け）、1MHzを用いた。Arduino IDEのボード選択後のオプションメニューで選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/69b93c6e-3b3d-4998-7755-70af971a69ca.png)
デバッグ時には1MHzを、通常は8MHz、、とするのも手であろう。

### ソフトシリアル通信速度
あまりに速度が大きいと、文字化けしてしまった。例えば、9600bpsの時の結果は、次のようなもの。
![9600.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/ce170fc4-2a1f-79b3-618b-fc56856db683.png)
「123」と入力したが、「1.3」とループバックしている。ここでは、4800bpsを選択している。
![4800bps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/c80722bb-ee4c-afd7-9195-2f3c50f2aba2.png)

## ログ表示（本題）
PC - Arduino - ATtiny85
と接続する。Arduino側コードは次のようなもの。

```c++:ArduinoSoftwareSerial-r1.ino
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

void setup()
{
  Serial.begin(9600);
  mySerial.begin(4800);
  Serial.println("Setup is done.");
}

void loop()
{
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
}
```

ATtiny85から受けたデータをシリアルコンソール（PC）に送る。ATtiny85側のサンプルコードは次のようなもの。

```c++:ATtiny85SoftwareSerial-r1.ino
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 4); // RX, TX

void setup()
{
  mySerial.begin(4800);
}

void loop()
{
  char buf[16];
  static uint32_t num = 0;

  sprintf(buf, "Debug %d\n", num++);
  for (int i = 0; i < strlen(buf); i++) {  
    mySerial.write(buf[i]);
  }
  delay(1000);
}
```

1秒毎にデバッグメッセージをArduinoに送るサンプル。PC側で次のような出力となる。
![Debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/aef3292d-88bf-af5c-29f7-44e0a307f240.png)

## 終わりに
UARTを持たないマイコンのデバッグに有効であろう。入力を考えなければ、GPIO１つですむ。