Digispark ATtiny85 起動までの5秒を取り除く

# 0. はじめに

**本家**?の[「Digispark USB Development Board」](http://digistump.com/products/1)は、いつからか現在も販売していない。
<img width="200" alt="Digispark USB Development Board" src="https://s3.amazonaws.com/digistump-resources/images/l/2520dcf84a0a3bf2257c2559d7a187db.jpg">

[Amazonで「digispark attiny85」を検索](https://www.amazon.co.jp/s?k=digispark+attiny85)すると、**互換品**?が多数ヒットする。1個当たりの価格は本家の$\frac{1}{3}$ほどで、日本に在庫を置いているのか注文して2日後には手元に届くショップもある。
以降、この製品を単に**ボード**と略す。

このボードはマウスやキーボードをお手軽にシミュレーションするには打って付けの製品である。しかし、このボードは、書き込んだプログラム（スケッチ）が動き出すまでに、5〜6秒のタイムラグがある。

[http://digistump.com/wiki/digispark/tutorials/connecting](http://digistump.com/wiki/digispark/tutorials/connecting#using_the_digispark_with_the_arduino_ide)から引用
> If you unplug the Digispark and plug it back in or attach it to another power source there will be a delay of 5 seconds before the code you programmed will run. This 5 second delay is the Digispark Pro checking to see if you are trying to program it.

このボードにとっては意図された仕様であるが、`setup()`にてキーボード`write`や`print`を実行したいときは、この5秒の待ちが無駄に長く邪魔である。

今回の記事は、この**5秒をとり除く**方法の説明である。
当**Qiita**をはじめ日本のサイトを多数検索したが、これを実現する方法を探し出せなかった。海外のサイトで見つけた方法で実現できたので、備忘録も兼ねてここにまとめておく。


# 1. 環境

執筆時点の当方の環境は以下の通り。

・PC : MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports)
・OS : macOS Big Sur version 11.2.3 (20D91)
・Arduino IDE : 1.8.13 for Mac OS X

記事の内容はWindowsでも同じはず。M1 Macで動作するかは不明である。

# 2. ブートローダを書き替える

解決策はズバリ、「**5秒待たないブートローダ**」に書き替える、である。

上記引用文書にあるように、「電源ONからの5秒間は新たなプログラム（スケッチ）を書き込むチャンスの時間」である。よって「書き込み前に一度USBポートから抜き、書き込み指示をしてから再びUSBポートに挿す」動作が必要なわけだ。

「**5秒待たないブートローダ**」にはこの書き込みチャンスは無い。代わりに、P0ポートをPull-Downすることで「プログラムの書き込みを待つ」仕様となる。
順を追って説明する。

## 2.1 書き込みコマンドと新ブートローダの入手

今回の解決策は、こちらの[動画](https://youtu.be/DXMHB1GCGEE)から得た内容であるが、動画で説明している入手先のリンクはすでに切れている。ネットを探し同等のダウンロード先を見つけた。

#### ・書き込みコマンドの入手先

MacOS : [https://github.com/micronucleus/micronucleus/tree/master/commandline/builds/x86_64-apple-darwin/](https://github.com/micronucleus/micronucleus/tree/master/commandline/builds/x86_64-apple-darwin/)micronucleus

Windows : [https://github.com/micronucleus/micronucleus/tree/master/commandline/builds/x86_64-mingw32/](https://github.com/micronucleus/micronucleus/tree/master/commandline/builds/x86_64-mingw32/)micronucleus.exe
多分、libusb0.dllも必要。

#### ・新ブートローダの入手先

こちら：[https://github.com/overfl0/NocInformatykaBoard/blob/master/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex](https://github.com/overfl0/NocInformatykaBoard/blob/master/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex)
（こちらが本家かも：https://github.com/micronucleus/micronucleus/tree/v1.11/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex）
当然だが、ボードに書き込むブートローダなので、Mac/Windowsの区別は無い。拡張子がhexだから中身はバイナリだと思ったがテキストだ。



## 2.2 新ブートローダを書き込む

書き込みコマンドと新ブートローダを同じディレクトリに保存する。ターミナルを開き、そのディレクトリにカレントを移動する。

書き込みコマンドの引数に新ブートローダを指定して実行するのだが、このとき、先にボードをUSBポートに挿してはダメだ。`micronucleus`コマンドを投入して「_Please plug in the device ..._」と出てきたら、USBポートに挿す合図である。

```shell:Terminal
$ ./micronucleus --run micronucleus-1.11-entry-jumper-pb0-upgrade.hex 
> Please plug in the device ... 
```

このタイミングでボードをUSBポートに挿す。すると「_Device is found!_」と出て書き込みが始まる。

```shell
> Device is found!
connecting: 33% complete
> Device has firmware version 1.11
> Available space for user applications: 6330 bytes
> Suggested sleep time between sending pages: 8ms
> Whole page count: 99  page size: 64
> Erase function sleep duration: 792ms
parsing: 50% complete
> Erasing the memory ...
erasing: 66% complete
> Starting to upload ...
writing: 83% complete
> Starting the user app ...
running: 100% complete
>> Micronucleus done. Thank you!
```

_Micronucleus done. Thank you!_ が出たら書き込み成功である。ボード上のプログラム（ステッチ）は初期化されたので、何も起きない。（プログラムが無いとLEDが早い点滅を繰り返すらしい）

~~Windowsの場合だと、引数の`--run`が不要かも？~~　/runが必要みたいだ。

```shell:cmd
> micronucleus.exe /run micronucleus-1.11-entry-jumper-pb0-upgrade.hex
```


# 3. ボードにプログラム（スケッチ）を書き込む

新しいブートローダは、**Arduino IDE**からスケッチを「マイコンボードに書き込む」ときの手順が、以下のように変更されている。
![IMG_6854.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/01535539-1099-2b97-19ea-bf4a58281f8c.png)

1. ボードの`P0`ポートをpull-downする（`P0`と`GND`をジャンパー線でつなぐ）
2. **Arduino IDE**のメニュー「マイコンボードに書き込む」か **⌘U**
3. `Please plug in the device ...`が出たら、ボードをUSBポートに挿す
4. `Micronucleus done. Thank you!`が出たら書き込み完了。USBポートから抜き、ジャンパー線も外す。

```test:ログ
Running Digispark Uploader...
Plug in device now... (will timeout in 60 seconds)
> Please plug in the device ... 
> Press CTRL+C to terminate the program.

> Device is found!
connecting: 16% complete
connecting: 22% complete
connecting: 28% complete
connecting: 33% complete
> Device has firmware version 1.11
> Available space for user applications: 6330 bytes
> Suggested sleep time between sending pages: 8ms
> Whole page count: 99  page size: 64
> Erase function sleep duration: 792ms
parsing: 50% complete
> Erasing the memory ...
erasing: 55% complete
erasing: 60% complete
erasing: 65% complete
> Starting to upload ...
writing: 70% complete
writing: 75% complete
writing: 80% complete
> Starting the user app ...
running: 100% complete
>> Micronucleus done. Thank you!
```

プログラムの書き込みが終わると、ボードがリセットされ書き込んだプログラムが起動される。このため、注意点としては、キーボード送出のプログラムを書いた時に、**Arduino IDE**上のカーソル位置にキーが送出され、プログラムコードを壊す可能性がある。自分は`/*    */`の間にカーソルを置き**⌘U**することで、キーが送出されても影響が少ないようにしている。（時々忘れてコードが壊される、そのときは**⌘Z**で戻している）

# 4. いざ起動

下の動画をご覧いただきたい。（↓クリックするとYouTubeで再生する）
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/f9323412-2cb5-bf7f-5001-22c0c884f877.gif">](https://www.youtube.com/embed/Jr6pqXpvGIo?rel=0&autoplay=1)
画面に映っている_ストップウォッチ_の時間を見ると、
　50.287　電源LEDが点灯
　50.687　pin#1のLED点灯
　52.547　最初の文字`T`が送出された
　53.247　最後の`Enter`が送出された
　53.837　pin#1のLED消灯 （1秒ディレイ後の）
であった。つまり、
・ボードに電源が入った0.4秒後に`setup()`が呼ばれた
・最初の`T`がタイプされるまでに0.9秒のタイムラグがある<font color=red>$^{注)}$</font>
・`T`〜`Enter`までの24文字のタイプに0.7秒を要した

<font color=red>**注）**</font>`DigiKeyboard.sendKeyStroke(0)`により、PCとの間でHIDキーボードのハンドシェイクが行われたものと想定する。

```c:確認プログラム
#include <DigiKeyboard.h>

void setup() {
  pinMode(1, OUTPUT);
  digitalWrite(1, true);
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.print("This board is started!");
  DigiKeyboard.sendKeyStroke(KEY_ENTER);
  DigiKeyboard.delay(1000);
  digitalWrite(1, false);
}

void loop() {
}
```
 
#### 体感的には1秒ぐらいでタイプを開始した感じで、すこぶる快適である。これで当初の目的を達成できた。

おまけ；動画で使用していた[電源スイッチ付きUSBアダプタ](https://www.amazon.co.jp/dp/B00IQO22B2/)は便利である。ボードをUSBポートから何度も抜き差しを行うので、このスイッチは重宝する。


# 終わりに

このボードの既ユーザ各位には周知の事実かもしれないが、これまで不便を感じていた方々の参考になれば幸いである。また、間違い等があればご指摘いただけるとありがたい。

**追伸；**
　マウスとキーボードを同時にシミュレーションするため、`DigiKeyboard`と`DigiMouse`両方のコードを書くとライブラリ重複エラーとなり上手くいかない。~~Report形式のデータを直接生成するしかないか？・・・あきらめ状態。~~ 2021.7.18変更
[Adafruit-Trinket-USB](https://github.com/adafruit/Adafruit-Trinket-USB)の**TrinketHidCombo**ライブラリを使用すると、マウスとキーボードを同時にシミュレーション出きることがわかった。これでDigispark ATtiny85の使い道が広がった。


以上


# 参考URL

http://digistump.com/wiki/digispark/tricks#get_rid_of_5_second_startup_delay

http://blameitonthegoose.com/remove-5-second-startup-delay-on-digispark/

https://digistump.com/board/index.php?topic=2928.0

https://www.youtube.com/watch?v=DXMHB1GCGEE

http://digistump.com/wiki/digispark/tutorials/connecting

http://shokai.org/blog/archives/8665

https://qiita.com/marc0468/items/8a4b1301416979ecba0e

https://qiita.com/Toramin10/items/291748d4a0c887dd8d7b

https://qiita.com/keitasumiya/items/ac228139f524bc6c8b4f

https://qiita.com/mt08/items/df4ed8c659b205d1fa1e

https://github.com/digistump/DigisparkArduinoIntegration/tree/master/libraries