はじめに

モノづくりの現場において、さまざまな面でデジタル化が進んできました。精密機器や洋服のデザインは紙から CAD(コンピュータ支援設計: Computer-Aided Design)へ、建築業であれば CAD から BIM(建物情報モデル: Building Information Modeling)、実験やテストにおいても、現物ベースのテストからシミュレータの活用など、新規データの作成から、過去データの活用まで、さまざまな形でデジタルデータが活用されています。

ただし、ソフトウェアの側から見ると、必ずしも入力される一次情報が全てデジタル由来というわけではなく、カメラやマイク、さらには人間の五感では捉えきれない情報がセンサーを通じて入力されているのも、一方では事実です。

ソフトウェアテストという観点からは、そういった非デジタルに由来する入力のテストをどう扱うか、単体レベルではスタブやドライバ、モックでソフトウェア的に代替しつつも、システムレベルでは実機テスト、実環境テストを適用したい場合があります。従来、「ハードウェア」のカテゴリで扱われていた製品であっても、ソフトウェアのバージョンアップによって、新たな機能が加わる(テスラの車がまさにそうですね)、つまり、ハードウェアであっても powered by software な時代に、CI/CD はどういった貢献ができるのか。CircleCI ランナー や Arm ベースの Machine Executor など、組み込みソフトウェア開発への CI/CD の適用について、ご紹介していきます。

取り上げる内容

具体的な話に移りましょう。今回のターゲットデバイスは、Raspberry Pi(ラズベリーパイ、ラズパイ)です。Raspberry Pi にSeeed 社Grove システムが提供するさまざまなセンサーやアクチュエータ、出力デバイスを(はんだ付けすることなく)つなげて、ハードウェアとソフトウェアの開発、およびテストをしていきます。

全4回で、次のような内容をご紹介します。

  1. Raspberry Pi 上での CircleCI ランナーの設定
  2. Raspberry Pi 上での GrovePI+ 実行環境の設定(本ブログ)
  3. CircleCI ランナーを使ったセンサー使用ソフトウェアのテスト
  4. Arm ベースの Machine Executor を使ったソフトウェアのビルド

なお、本ブログの記述時(2021 年 4 月現在)、CircleCI ランナーに関わる 1, 3 をご自身で実際に試すには、CircleCI の Scale プランをご契約いただく必要があります。一方、Arm ベースの Machine Executor に関わる 4 をご自身でお試しいただくには、こちらのアクセス申請フォームよりお申し込みをいただく必要があります(Free プランを含む全てのプランで利用可能です)。

Grove システムとは

センサーやディスプレイ、各種アクチュエータを備えたハードウェア、およびソフトウェアの組み込み作業をする際に、プロトタイプ開発フェーズやアイデア出しのフェーズでの作業を考えてみましょう。さまざまな部品を繋げて、どういった機能やサービスが提供できるのかを、試作・評価する際に、プリント基板をエッチングしたり、部品をはんだ付けしたりというのはこのフェーズでは非効率です。

この非効率を解消するために、ブレッドボード上に部品を配置し、ジャンパワイヤを抜き差しして回路を作りながら進めることで、ソルダーレス(はんだ付け不要にする)というアプローチがあります。

一方、単にソルダーレスにするだけでなく、関連するソフトウェア開発の効率も上げようとするのが Grove のアプローチです。Grove では部品はそれぞれ独立したモジュールになっています(赤枠内は後ほど使用するTemperature & Humidity Sensor Pro)。

2021-04-08-masahiko-grove-modules

モジュールとボードをつなぐ4 ピンケーブル、およびソケットは標準化されているので、ボードとモジュールを繋げることで回路を作ることができます。

また、モジュールにはそれぞれ、サンプルプログラムが用意されているので、例えば、今回使用する温度・湿度を計測するための Temperature & Humidity Sensor Pro を Raspberry Pi から使用するのであれば、Python 版C++言語版などさまざまな言語での使用例を参照することが可能です。

説明内容を実行するための前提条件

注意事項(おことわり)

今回使用する GrovePi+ の動作 OS は、Raspberry Pi 上であれば、

であり、そもそも、本ブログで使用している Ubuntu 20.10 (Arm64 版)が動作検証・サポートされているわけではありません。本ブログの内容は、筆者の調査を元に、読者が「何らかの組み込み環境やプラットフォームと CircleCI ランナーを連携して使用する」ための参考となる情報を提供することを意図しています。したがって、書かれている通りにやれば動作することを何ら保証するものではなく、Seeed 社や Dexter Industries 社にはお問合せいただかないようにお願いいたします。

動作環境の構築

OS に Ubuntu 20.10(64bit 版)をインストールした Raspberry Pi で Grove+が使えるように、まずは動作環境を構築します。

OS に Raspberry Pi OS(旧称: Raspbian)を使用している場合の動作環境構築方法は、GrovePi+の Wiki ページで説明されています。その説明に準じた形で、説明を進めていきます。

なお、ここからの作業は Raspberry Pi 上で行います。Raspberry Pi にディスプレイ、キーボード、マウス等を接続するか、Raspberry Pi に対して、SSH 接続、または VNC 接続や X サーバ接続した上で、以下の操作を行なっていきます。

1. ユーザの作成

Raspberry Pi OS では、デフォルトユーザとして pi が設定されるのですが(参照)、この後の作業においても、作業を行っているユーザが pi であることを前提にして記述されたスクリプトがあるので、(説明を容易にするために)ユーザ pi を設定し、以降の作業は pi でログインした状態で行うようにします。

sudo adduser piでユーザ pi を追加します。ユーザ pi に設定するパスワードを聞かれるので(New password:)、パスワードを設定します(Raspberry Pi OS でのユーザ pi に対するデフォルトパスワードである raspberry 以外のパスワードを設定することを推奨します)。その後の名前等の入力は Enter キーを押してデフォルト値を設定するか、適宜、値の設定を行ってください。

次に、sudo adduser pi sudoで、ユーザ pi がsudoの実行ができるように、sudoグループのメンバーに加えます。

メンバーに加えたら、一旦ログアウトし、ユーザ名 pi で再ログインします。

2. GrovePi for Python のインストール

ここからの作業は、ユーザ pi で行います。ホームディレクトリが /home/pi であることを確認して下さい(pwd)。

次に GrovePi for Python のインストール時に必要になるコマンドやモジュール群をインストールします。

$ sudo apt-get install --no-install-recommends -y git \
    g++-aarch64-linux-gnu avrdude \
    nodejs libi2c-dev i2c-tools \
    python3 python-is-python3 \
    python3-dev python-dev-is-python3 \
    python3-setuptools python3-pip \
    wxpython-tools \
    python3-smbus python3-serial python3-rpi.gpio \
    python3-numpy python3-scipy \
    libncurses5

次に、ホームディレクトリ(/home/pi)の下に Dexter ディレクトリを作成し、作成したディレクトリに移動します。

$ mkdir Dexter
$ cd Dexter

移動したら、GitHub 上のGrovePi リポジトリの内容をクローンします。

$ git clone https://github.com/DexterInd/GrovePi.git

クローンが完了すると、GrovePiディレクトリが作成されます。

次に、GrovePi/Scriptディレクトリに移動し、update_grovepi.shを実行します。

$ cd GrovePi/Script
$ bash update_grovepi.sh

途中、警告(warning)等が出力されるかと思いますが、最終的に終了していれば(今回は)良しとします。

3. サンプルプログラムの実行

それでは、インストールがうまくいっているかどうかを、センサーの値を読み取るような Python プログラムを実行して、確認してみることにします。

今回は、Temperature & Humidity Sensor Pro(DHT22)を使って、温度と湿度を検出します。

まずは、この温湿度センサを GrovePi+に取り付けます。プラグ&プレイで取り付けることはできないので、一旦、sudo shutdown -h nowで Raspberry Pi をシャットダウンします。シャットダウン後に電源が自動的にオフになったりはしないので、パイロットランプの点滅がしなくなったら、電源ケーブル(Type-C ケーブル)を抜くなどの方法で電源をオフにします。

次に、Raspberry Pi に GrovePi+を取り付けます。取り付け方法に関しては、Dexter Industries 社のこちらのページ(英文)を参考にして下さい。

Raspberry Pi に GrovePi+を取り付けたら、次に温湿度センサを4ピンケーブルを使って取り付けます。後ほど紹介するサンプルでは、D4 というコネクタ(デジタルポート)に取り付けをした前提でプログラムが書かれているのですが、筆者環境では、Raspberry Pi+GrovePi+をケースに収めている関係上、D4 が使用できないため、D3 と温湿度センサーを接続しています(下記写真参照)。

2021-04-08-masahiko-GrovePi

それでは、実際にサンプルプログラムを動かしてみましょう。Raspberry Pi にディスプレイ、キーボード、マウス等を接続するか、Raspberry Pi に対して、SSH 接続、または VNC 接続や X サーバ接続した上で、以下の操作を行なっていきます。引き続き ユーザー pi でログインして作業を続けていきます。

まず、Python のライブラリやサンプルプログラムが収められたディレクトリに移動します。

$ cd ~/Dexter/GrovePi/Software/Python

次に、サンプルプログラム grove_dht_pro.py を nano や vim 等のエディタを使って入力していきます(こちらのサンプルプログラムを一部改変して使用しています)。

import grovepi
import math
# Grove Temperature & Humidity Sensor Pro を デジタルポート D3 に接続します。
# このサンプルでは、白い色のセンサーを使用しています。
# SIG,NC,VCC,GND
sensor = 3  # センサーの接続先はデジタルポート 3

# temp_humidity_sensor_type
blue = 0    # 青色のセンサーを使用
white = 1   # 白色のセンサーを使用

while True:
    try:
        # 第1引数は接続ポート、第2引数はセンサー種別
        [temp,humidity] = grovepi.dht(sensor, white)
        if math.isnan(temp) == False and math.isnan(humidity) == False:
            print("temp = %.02fC humidity = %.02f%%"%(temp, humidity))

    except IOError:
        print ("Error")

ファイルを保存したら実行するのですが、普通に実行しようとすると、次のようにエラーになってしまいます。

$ python3 grove_dht_pro.py
wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: Permission denied.
  Aborting your program because if it can not access the GPIO
  hardware then it most certianly won't work
  Try running with sudo?

ハードウェア(/dev/mem または /dev/gpiomem)へのアクセス権限がないためにエラーになってしまいます。メッセージに書かれているように、sudoで管理者権限で実行すれば、問題なく実行されます。

$ sudo python3 grove_dht_pro.py
temp = 23.80C humidity = 40.20%
temp = 23.60C humidity = 40.90%
temp = 23.50C humidity = 40.80%
(Ctrl+C押下まで継続表示)

おわりに

今回のブログでは、Raspberry Pi の Ubuntu 環境上で GrovePi+経由で接続した温湿度センサーの情報を取得するような Python プログラムを実行することができました。

CircleCI ランナーでこういったプログラムを実行する際には、タスクエージェントにより ユーザ circleci の権限で実行されます。したがって、ハードウェアリソースにアクセスするようなプログラムは、そのままでは実行できない、ということになります。ユーザ circleci にパスワードなしで権利者に昇格させ、ハードウェアアクセスを含むプログラムを実行させる、という方法も考えられますが、適切な権限付与という意味では、ユーザ circleci に対して、(管理者権限に昇格しなくても)ハードウェアアクセスを許すような権限設定が望ましいと考えられます。詳しくは、次回のブログにて取り上げることにします。