Ubuntu 24 で Digispark ATTiny85 の DigiUSB を使う

Digispark という Arduino互換開発ボードがあります。親指サイズで、USBに直接刺せて、非常に便利です。そして安価 （互換品がAmazonやアリエクで500円ぐらいで買えます) です。

しかし、発売が10年以上？前のようで、最近のOS (Ubuntu24) で使うのに少々苦労しました。

## 物理的に認識しているか確認する

Digisparkが問題なく認識されている場合は、`lsusb` コマンドの結果に以下のような表示がされます。
差し込んでから10秒間ぐらいしか表示されませんが、そういう仕様です。`lsusb` にこの表示がされない場合、物理的に認識されてません。

```
$ lsusb
<snip>
Bus 002 Device 063: ID 16d0:0753 MCS Digistump DigiSpark
```

Digispark は どうやら、USB 3.0 以降と相性が悪いようです。最初、認識されなくて困りました。結局、USB 2.0のポートを使うか、「USB 3.0 + USB 2.0 ケーブル」の接続で、うまく認識させることが出来ました。

## Platform IO をセットアップする

マイコンにプログラムを書き込むために、Platform IO をセットアップします。
Ubuntu のパッケージでインストールした Platform IO は起動することが出来ませんでした。`apt` を使わずに、Github から最新バージョンを直接インストールしましょう。

```
$ curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -o get-platformio.py
$ python get-platformio.py
```

インストール後手順は、こちらの記事を参考に実施しました。

https://mickey-happygolucky.hatenablog.com/entry/2020/02/18/200140

## プログラムを書き込む

DigiUSB を使って、マイコンから文字列を出力します。
```
$ cat src/main.cpp
#include <Arduino.h>
#include <DigiUSB.h>

#define LED (1)

void setup() {
    pinMode(LED, OUTPUT);
    DigiUSB.begin();
    DigiUSB.refresh();
    DigiUSB.delay(10);
    DigiUSB.println("Booted digispark.");
}

void loop() {
    digitalWrite(LED, HIGH);
    delay(500);
    DigiUSB.refresh();
    if (DigiUSB.available()) {
      DigiUSB.delay(10);
      DigiUSB.println("hello");
    }
    digitalWrite(LED, LOW);
    delay(500);
}
```
`Please plug in the device` 〜の表示が出たら、Digispark を挿します。
```
$ pio run -t upload
Processing digispark-tiny (platform: atmelavr; board: digispark-tiny; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/digispark-tiny.html
PLATFORM: Atmel AVR (5.1.0) > Digispark USB
HARDWARE: ATTINY85 16MHz, 512B RAM, 5.87KB Flash
DEBUG: Current (simavr) External (simavr)
PACKAGES:
 - framework-arduino-avr-digistump @ 1.7.2
 - tool-micronucleus @ 1.250.210222 (2.50)
 - toolchain-atmelavr @ 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 24 compatible libraries
Scanning dependencies...
Dependency Graph
|-- DigisparkUSB
Building in release mode
Checking size .pio/build/digispark-tiny/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=======   ]  72.9% (used 373 bytes from 512 bytes)
Flash: [=====     ]  49.6% (used 2984 bytes from 6012 bytes)
Configuring upload protocol...
AVAILABLE: micronucleus
CURRENT: upload_protocol = micronucleus
Uploading .pio/build/digispark-tiny/firmware.hex
> Please plug in the device (will time out in 60 seconds) ...
```

## マイコンからの出力を取り出す

まず、以下のように `lsusb` コマンドの出力に HID デバイスが追加されているか確認しましょう。最初に 上記の `MCS Digistump〜` が表示されたのち、しばらく待つと出てきます
（認識されない場合、ソースコードの `refresh` や `delay` を増やすとうまくいく場合があるみたいです）
```
$ lsusb
<snip>
Bus 002 Device 059: ID 16c0:05df Van Ooijen Technische Informatica HID device except mice, keyboards, and joysticks
```

マイコンから送られてきたデータを読み取るための gem をインストールします。
```
$ sudo gem install digiusb
Successfully installed digiusb-1.0.5
Parsing documentation for digiusb-1.0.5
Done installing documentation for digiusb after 0 seconds
1 gem installed
```

しかし、この gem、そのままだとエラーがでます。
```
$ sudo digiterm
/var/lib/gems/3.2.0/gems/libusb-0.7.2/lib/libusb/dev_handle.rb:505:in `control_transfer': wrong number of arguments (given 1, expected 0; required keywords: bmRequestType, bRequest, wValue, wIndex) (ArgumentError)
	from /var/lib/gems/3.2.0/gems/digiusb-1.0.5/lib/digiusb.rb:169:in `control_transfer'
	from /var/lib/gems/3.2.0/gems/digiusb-1.0.5/lib/digiusb.rb:69:in `getc'
	from /var/lib/gems/3.2.0/gems/digiusb-1.0.5/bin/digiterm:44:in `block in <top (required)>'
	from /var/lib/gems/3.2.0/gems/digiusb-1.0.5/bin/digiterm:43:in `loop'
	from /var/lib/gems/3.2.0/gems/digiusb-1.0.5/bin/digiterm:43:in `<top (required)>'
	from /usr/local/bin/digiterm:25:in `load'
	from /usr/local/bin/digiterm:25:in `<main>'
```
この gem は Ruby 3 系に対応していないようで、以下のように少し手を加える必要がありました。
```
$ diff -u /var/lib/gems/3.2.0/gems/digiusb-1.0.5/lib/digiusb.rb /var/lib/gems/3.2.0/gems/digiusb-1.0.5/lib/digiusb.rb.new
--- /var/lib/gems/3.2.0/gems/digiusb-1.0.5/lib/digiusb.rb	2025-06-14 22:35:32.959842160 +0900
+++ /var/lib/gems/3.2.0/gems/digiusb-1.0.5/lib/digiusb.rb.new	2025-06-14 22:36:27.373242431 +0900
@@ -166,12 +166,12 @@
   end

   def control_transfer(opts = {}) #:nodoc:
-    io.control_transfer({
+    io.control_transfer(**{
       wIndex: 0,
       wValue: 0,
       bmRequestType: usb_request_type(opts),
       timeout: Timeout
-    }.merge opts)
+    }.merge(opts))
   rescue LIBUSB::ERROR_TIMEOUT, LIBUSB::ERROR_IO
     raise ErrorCrashed
   end
```

これで、`digiterm` コマンドでマイコンの出力がモニターできるはずです。
```
$ sudo digiterm
Looking for Digispark running DigiUSB...
Attached to <Digispark:?:@2.75>
Type control + c to exit

Booted digispark.
hello
hello
hello
```