Sphero BOLTのLEDマトリクスをRaspberry Pi 3B+にインストールしたPySpheroで制御する / How to control Sphero BOLT's LED matrix with PySphero installed on Raspberry Pi 3B+

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Qiitaに記事を載せました。<br><br>Sphero BOLTのLEDマトリクスをRaspberry Pi 3B+にインストールしたPySpheroで制御する / How to control Sphero BOLT&#39;s LED matrix with PySphero installed on Raspberry Pi 3B+<a href="https://t.co/ImIcCrGuJb">https://t.co/ImIcCrGuJb</a> <a href="https://t.co/o0B2He0vRA">pic.twitter.com/o0B2He0vRA</a></p>&mdash; ka’s (@pbjpkas) <a href="https://twitter.com/pbjpkas/status/1325471699534401536?ref_src=twsrc%5Etfw">November 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

##1. 用意するもの(What to prepare)
- Sphero BOLT([JP](https://sphero-edu.jp/teaching/bolt/)/[US](https://sphero.com/collections/for-home/products/sphero-bolt))
  - 筆者のSphero BOLTのファームウェアバージョンはNordic: 4.2.41, ST: 4.2.44です。
  - The firmware version of my Sphero BOLT is Nordic: 4.2.41, ST: 4.2.44.
- Raspberry Pi 3B+
- [Raspberry Pi OS](https://www.raspberrypi.org/downloads/raspberry-pi-os/)
  - OK : Raspbian GNU/Linux 10 (buster) (Python 3.7.3 included)
  - Does not work : Raspbian GNU/Linux 9.9 (stretch) (Python 3.5.3 included)

PySpheroはバージョンが3.6以上のPythonが必要です。筆者はRaspberry Pi OS (32-bit) with desktop and recommended software、Raspbian GNU/Linux 10 (buster)、August 2020を使用しています。
PySphero requires Python version 3.6 or higher to use it. The author is using Raspberry Pi OS (32-bit) with desktop and recommended software, Raspbian GNU/Linux 10 (buster), August 2020.

##2. 手順(Procedure)
###2.1 PySpheroのインストール(Install PySphero)
詳細は[こちら](https://github.com/EnotYoyo/pysphero)をご覧ください。
Click [here](https://github.com/EnotYoyo/pysphero) for details.

```sh
# Install the dependencies
$ sudo apt-get install libgtk2.0-dev
$ pip3 install bluepy

# To use gatt BT stack, install it manually
$ pip3 install gatt

# To use bled112 dongle, pygatt for BGAPI is supported
# To use pygatt BT stack, install it manually
$ pip3 install pygatt

# Install PySphero
$ pip3 install pysphero
```

筆者の環境では下記バージョンがインストールされました(2020/11/8)。
The following versions have been installed in the author's environment at November 8, 2020.

|Package      |Version
|-------------+-------
|libgtk2.0-dev|testing,now 2.24.32-3+rpt1 armhf
|bluepy       |1.3.0
|gatt         |0.2.7
|pygatt       |4.0.5
|pysphero     |0.0.12

###2.2 PySpheroの修正(Modify PySphero)
set_led_matrix_frame_rotation()のtarget_idを修正します。
Modify the target_id in set_led_matrix_frame_rotation().

```python:~/.local/lib/python3.x/site-packages/pysphero/device_api/user_io.py
    175     def set_led_matrix_frame_rotation(self, rotation: FrameRotation = FrameRotation.normal):
    176         self.request(
    177             command_id=UserIOCommand.set_led_matrix_frame_rotation,
    178             data=[rotation.value],
    179             target_id=0x12,      # <---- modify 0x11 to 0x12
    180         )
```

##3. Example
このプログラムは[police.py](https://github.com/EnotYoyo/pysphero/blob/master/examples/police.py)を参考にしています。
This program is based on [police.py](https://github.com/EnotYoyo/pysphero/blob/master/examples/police.py).

```sh
$ python3 led_matrix.py
```

```python:led_matrix.py
from time import sleep

from pysphero.core import Sphero
from pysphero.device_api.user_io import Color, FrameRotation


def main():
    mac_address = "aa:bb:cc:dd:ee:ff"  # <---- modify your Sphero BOLT's MAC Address
    with Sphero(mac_address=mac_address) as sphero:
        sphero.power.wake()

        sphero.user_io.set_led_matrix_one_color(color=Color(red=0xff,green=0x00,blue=0x00))
        sleep(0.5)
        sphero.user_io.set_led_matrix_one_color(color=Color(red=0x00,green=0xff,blue=0x00))
        sleep(0.5)
        sphero.user_io.set_led_matrix_one_color(color=Color(red=0x00,green=0x00,blue=0xff))
        sleep(0.5)
        sphero.user_io.set_led_matrix_one_color(color=Color(red=0xff,green=0xff,blue=0xff))
        sleep(0.5)
        sphero.user_io.set_led_matrix_one_color(color=Color(red=0x00,green=0x00,blue=0x00))
        sleep(0.5)

        sphero.user_io.set_led_matrix_single_character(symbol="a", color=Color(red=0xff,green=0xff,blue=0x00))
        sleep(0.5)
        sphero.user_io.set_led_matrix_single_character(symbol="b", color=Color(red=0x00,green=0xff,blue=0xff))
        sleep(0.5)
        sphero.user_io.set_led_matrix_single_character(symbol="c", color=Color(red=0xff,green=0x00,blue=0xff))
        sleep(0.5)

        sphero.user_io.set_led_matrix_frame_rotation(rotation=FrameRotation.normal)
        sphero.user_io.set_led_matrix_text_scrolling(string="<--", color=Color(red=0xff,green=0x00,blue=0x00), speed=0x10, repeat=False)
        sleep(1.5)
        sphero.user_io.set_led_matrix_frame_rotation(rotation=FrameRotation.degrees_180)
        sphero.user_io.set_led_matrix_text_scrolling(string="<--", color=Color(red=0x00,green=0xff,blue=0x00), speed=0x10, repeat=False)
        sleep(1.5)
        sphero.user_io.set_led_matrix_frame_rotation(rotation=FrameRotation.degrees_90)
        sphero.user_io.set_led_matrix_text_scrolling(string="<--", color=Color(red=0x00,green=0x00,blue=0xff), speed=0x10, repeat=False)
        sleep(1.5)
        sphero.user_io.set_led_matrix_frame_rotation(rotation=FrameRotation.degrees_270)
        sphero.user_io.set_led_matrix_text_scrolling(string="<--", color=Color(red=0xff,green=0xff,blue=0xff), speed=0x10, repeat=False)
        sleep(1.5)
        sphero.user_io.set_led_matrix_one_color(color=Color(red=0x00,green=0x00,blue=0x00))

        sphero.power.enter_soft_sleep()


if __name__ == "__main__":
    main()
```

##4. 付録(Appendix)
###4.1 既知の問題(Known Issue)
Raspberry Pi起動後の最初の実行時のみ、下記のエラーが発生します。
The following error occurs only on the first run after starting the Raspberry Pi.

```sh
pi@raspberrypi:~ $ python3 led_matrix.py
Traceback (most recent call last):
  File "led_matrix.py", line 49, in <module>
    main()
  File "led_matrix.py", line 10, in main
    with Sphero(mac_address=mac_address) as sphero:
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/core.py", line 49, in __enter__
    self._ble_adapter = self._ble_adapter_cls(self.mac_address)
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/bluetooth/gatt_adapter.py", line 39, in __init__
    ch_force_band = self._find_characteristic(SpheroCharacteristic.force_band.value)
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/bluetooth/gatt_adapter.py", line 56, in _find_characteristic
    raise PySpheroRuntimeError(f"Characteristic {characteristic} not found")
pysphero.exceptions.PySpheroRuntimeError: Characteristic 00020005-574f-4f20-5370-6865726f2121 not found
```

###4.2 target_idの修正について(About the modification of target_id)
以下のようなエラーが発生するためtarget_idを修正しています。
The target_id has been modified because the following error occurs.

```sh
pi@raspberrypi:~ $ python3 led_matrix.py
Traceback (most recent call last):
  File "led_matrix.py", line 49, in <module>
    main()
  File "led_matrix.py", line 31, in main
    sphero.user_io.set_led_matrix_frame_rotation(rotation=FrameRotation.normal)
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/device_api/user_io.py", line 179, in set_led_matrix_frame_rotation
    target_id=0x11,
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/device_api/device_api.py", line 38, in request
    timeout=timeout,
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/bluetooth/gatt_adapter.py", line 76, in write
    return self.packet_collector.get_response(packet, raise_api_error, timeout)
  File "/home/pi/.local/lib/python3.7/site-packages/pysphero/bluetooth/packet_collector.py", line 47, in get_response
    raise PySpheroApiError(response.api_error)
pysphero.exceptions.PySpheroApiError: Api reponse error: bad_command_id
```