Spresense Header CodeSpresense Header Code

Spresense - エッジコンピューティングを低消費電力で

Spresense で乾電池でも動く本格的なエッジコンピューティングを体験してみませんか?

Spresense Arduino Library の使い方

この章では、Spresense Arduino Library の入手から、LEDを光らせる簡単なアプリケーションの開発まで習得することができます。 

Arduino では、アプリケーションプログラムをスケッチと呼びます。

1. Spresense Arduino Library のインストールの仕方

1.1. サポートしているプラットフォーム

Spresense Arduino Library は以下のプラットフォームで動作を確認しています。

  • Windows 8.1/10

  • 64bit版 Linux Ubuntu 16.04

  • Mac OSX 10.12 Sierra

32bit版 Linux には対応していません。

1.2. 事前準備

Arduino IDE バージョンは、1.8.x 以降を使用してください。
Windows 10 環境では、上記 URL より v10.1.3 をダウンロードしてお使いください。 最新ドライバ (v10.1.4) を使用した場合、ターミナル起動直後の送信データが欠落する等の問題が発生することがあります。
  • 64bit版 Linux Ubuntu 16.04 ではシリアルポートをArduino IDEで利用できるように次の設定をします。

    1. Ubuntuのユーザを dialout のグループに追加します。

      $ sudo adduser <user-name> dialout
    2. Ubuntuを再起動します。

    3. Spresense ボードのUSBを接続し直したら完了です。

接続し直すことでこの設定が反映されます。
この設定を行わない場合Arduinoで作成したソフトウェアをSpresense ボードにアップロードできません。

1.3. Spresense Arduino board package のインストール

Spresense Arduino board package のインストールの仕方について記述しています。

この方法以外にも git clone やダウンロードしたパッケージをマニュアルでインストールする方法もあります。
  1. Arduino IDEを起動します。

  2. 環境設定を開きます。

    arduino borad manager preference ja
    図 1. Arduino IDE環境設定
  3. 追加のボードマネージャのURLに下記URLを入力し OK をクリックします。

    https://github.com/sonydevworld/spresense-arduino-compatible/releases/download/generic/package_spresense_index.json
    arduino borad manager add json url ja
    図 2. ボードマネージャ jsonファイル指定
  4. ツールボードボードマネージャ を選択してボードマネージャを開きます。

    tutorial arduino open boardmanager ja
    図 3. ボードマネージャの開き方
  5. Spresense を検索し インストール をクリックすればインストールは完了します。

    インストール中約 150MB のダウンロードを行いますので、パケット定額サービスなどの環境でインストールを行いください。
    パッケージ検索にてエラーが発生する場合は ファイル > 環境設定 > ネットワーク でプロキシの設定をご確認ください。
    tutorial arduino boardmanager spresense install ja
    図 4. Spresenseを検索&インストール
    ボードマネージャでは表示されるパッケージを一度クリックしないとインストールボタンは現れません。

2. Spresense Arduino Library のプログラミング環境の設定

2.1. USBシリアルポートの確認

事前準備を参照の上USBドライバをインストール後、USBケーブルをSpresenseメインボードに接続してください。

下の画像のように青いLEDが点灯されていればPCと接続されています。

spresense musb connect
図 5. Connection to the Spresense main board USB connector with power LED on

プラットフォーム毎のUSBポートの確認方法は下記をご確認ください。

2.1.1. Windows上でのUSBシリアルドライバの確認

  1. デバイスマネージャー を開きます。

  2. Silicon Labs CP210x USB to UART Bridge のCOMポートの番号を確認します。

    tutorial arduino windows device manager find port
    図 6. デバイスマネージャーでCOMポートを確認

    この例の場合 COM9 に接続されていることになります。

    Spresense メインボードは Silicon Labs CP210x USB to UART Bridge としてデバイスマネージャに表示されます。

2.1.2. Ubuntu 64bit上でのUSBシリアルドライバの確認

Spresense ボードが接続されているCOMポートを探し出します。

  1. ターミナルを開きます。

  2. ターミナル上で次のコマンドを入力してください。

    $ dmesg | grep "cp21.*attached"
    [12220.625979] usb 1-1: cp210x converter now attached to ttyUSB0

    この例の場合 ttyUSB0 に接続されていることになります。

2.1.3. Mac OSX上でのUSBシリアルドライバの確認

Spresense ボードが接続されているCOMポートを探し出します。

  1. ターミナルを開きます。

  2. ターミナル上で次のコマンドを入力してください。

    $ ls /dev/{tty,cu}.*
    /dev/cu.SLAB_USBtoUART  /dev/tty.SLAB_USBtoUART

    この例の場合 cu.SLAB_USBtoUART に接続されていることになります。

2.2. Spresenseローダーのインストール

ボードを使う前に、ローダーをボードにインストールする必要があります。以下の手順にしたがって、ローダーをインストールしてください。

Spresense Arduino board package のインストールが完了していることが必要です。

Spresense ボードは出荷状態ではローダーはインストールされていません。
Spresense メインボードとPCが micro USB ケーブルで接続されていることが必要です。
  1. Arduino IDEを起動します。

  2. Spresense ボードを ツール > ボード> Spresense の順に選択します。

    tutorial arduino boardsmanager menu ja
    図 7. Spresense ボードの選択
  3. USBケーブルをSpresense メインボードUSBコネクタに接続し、 ツール > シリアルポート で、COMポートを選択します。

    Spresense ボードが接続されている COMポートを選択してください。

    接続されているCOMポートが分からない場合は、 USBシリアルポートの確認を参照してください。

    tutorial arduino select port ja
    図 8. Spresense ボードに接続されているCOMポートの選択
  4. ツール > 書き込み装置Spresense Firmware Updater を選択します。

    tutorial arduino select programmer ja
    図 9. Spresense Firmware Updater の選択
  5. ツール > ブートローダーを書き込む を選択します。これでブートローダーとバイナリライブラリがインストールされます。

    tutorial arduino tools menu do burn ja
    図 10. 'ブートローダーを書き込む' の選択
  6. End User License Agreement のダイアログ内にあるライセンス文を確認し、 I Accept the terms in the license agreement にチェックを付けたのち OK ボタンをクリックしてください。

    tutorial arduino eula dialog
    図 11. End User License Agreementのダイアログ
    Spresenseのローダーを利用するためにはEnd User License Agreementの同意が必要です。
    次回以降ボードマネージャの更新をしない限り再度表示されることはありません。
  7. 次のメッセージがArduino IDE(下記画像の赤枠)に表示されればインストール完了です。

    ブートローダの書き込みが完了しました。
    
    updater# Restarting the board ...
    reboot
    tutorial arduino fw update done ja
    図 12. インストール完了時に Arduino IDE に表示されるメッセージ

3. Spresense でLEDのスケッチ動かしてみる

以上でSpresense Arduino board package の準備が整いました。環境が正しくセットアップされたか確認するために、LEDサンプルスケッチを動かしてみます。

  1. 以下のLEDサンプルスケッチをArduino IDE にコピーしてください。

    void setup() {
        pinMode(LED0, OUTPUT);
        pinMode(LED1, OUTPUT);
        pinMode(LED2, OUTPUT);
        pinMode(LED3, OUTPUT);
    }
    
    void loop() {
        digitalWrite(LED0, HIGH);
        delay(100);
        digitalWrite(LED1, HIGH);
        delay(100);
        digitalWrite(LED2, HIGH);
        delay(100);
        digitalWrite(LED3, HIGH);
        delay(1000);
    
        digitalWrite(LED0, LOW);
        delay(100);
        digitalWrite(LED1, LOW);
        delay(100);
        digitalWrite(LED2, LOW);
        delay(100);
        digitalWrite(LED3, LOW);
        delay(1000);
    }
  2. Upload ボタンをクリックして、スケッチのコンパイルとアップロードを行ってください。

    tutorial arduino upload ja
    図 13. Upload のクリック
  3. スケッチのアップロード完了するまで待ちます。

    tutorial arduino sketch done uploading ja
    図 14. アップロードの正常完了時のメッセージ
  4. スケッチが動作するか確認します。正常にアップロードされていると、Spresenseボード上のLEDが点滅をします。

    スケッチのアップロードが完了すると自動でSpresenseボードがリセットされます。
  5. 以上で環境が正しくセットアップできました。

4. Spresense でStep Counter スケッチを動かしてみる

4.1. Sensingライブラリの動作環境

センシングしたい内容にあわせて、必要なセンサを繋いでください。

4.1.1. Step Counter 動作環境

Step Counter ライブラリを動作させるために事前に準備が必要なものを以下に示します。

今回提供のアルゴリズムは、Bosch社製BMI160に合わせてチューニングしていますが、ローム社製Sensor Add-Onボード SPRESENSE-SENSOR-EVK-701も使用可能です。

4.2. Sensingライブラリのスケッチサンプル

Step Counter (Sensing)ライブラリを使ったサンプルスケッチは、Arduino IDE 上から ファイル → スケッチ例 → Spresense用のスケッチ例 Sensing → application 以下にあります。

4.2.1. Step Counterライブラリのスケッチサンプル

ソニー製アルゴリズムは、v1.3.0以降、ブートローダの更新と共にインストールされます。最新版の ブートローダに更新してください。

Arduino IDE 上から ファイル → スケッチ例 → Spresense用のスケッチ例 Audio → application → step_counter を選択してサンプルスケッチを起動して実行してください。

起動後、サンプルには、

"-----------------------------------------------------------" +
"      tempo,     stride,      speed,       step,  move-type"

が、表示されていきます。

Step Counterライブラリの物理センサを変えてみる。

センサーボードをローム社製 SPRESENSE-SENSOR-EVK-701に変更する例を以下に示します。

  • KX122用のライブラリをインストール
    上記ホームページ、より、こちらからライブラリを 取得します。
    「Clone or download」→「Download ZIP」を選択し任意のフォルダーに保存します。
    ダウンロードしたファイルを任意のフォルダーに展開しておきます。
    Arduinoのメニューから、「スケッチ」→「ライブラリをインクルード」→「.ZIP形式のライブラリをインストール…​」を選択し展開しておいたフォルダーから「KX122」フォルダーを選択します。

  • サンプルスケッチの修正

#include <BMI160Gen.h>

#include <Wire.h>
#include <KX122.h>
KX122 kx122(KX122_DEVICE_ADDRESS_1F);

に変更し、初期化をしている、

BMI160.begin(BMI160GenClass::I2C_MODE, i2c_addr);

Wire.begin();
kx122.init();

に変更し、データを取得している

BMI160.readAccelerometerScaled(x, y, z);

kx122.get_val(acc);
/* accはfloat acc[3] */

に変更し、そのデータを論理センサーに渡している、

AccelSensor.write_data(x, y, z);

AccelSensor.write_data(acc[0], acc[1], acc[2]);

に変更することで、可能です。

kx122もライブラリでは、50Hzに設定されています。
Step Counterの独自論理センサを作ってみる。

現在提供している、ソニー製アルゴリズムのStep Counter(AESM) を使わずに、独自のStep Counterアルゴリズムを実装したい場合は、以下のように論理センサクライアントを作成します。

センサクライアントを継承した論理センサクラスを作成してください。

例えば、MyCounterClass をMyCounter.hに実装します。ヘッダファイルは必要に応じインクルードしてください。例えば、SensorClient.hは必要ですが、sensing/logical_sensor/step_counter.hはStepCounterの定義を使用したい場合のみ必要です。

また、例として、一般的に使われているコードの格納場所を下図に示します。

diag ee767dba3ab547a866a71ad95972601e
図 15. MyCounterコード格納場所の例

上記はWindows環境の例であり、Ubuntu環境であれば ~/Arduino , macOS環境であれば ~/Documents/Arduino となります。

class MyCounterClass : public SensorClient

この、 MyCounterClass

bool begin(int id,
           uint32_t subscriptions,
           int      rate,
           int      sample_watermark_num,
           int      size_per_sample));

int publish(FAR void* data,
            uint32_t  size_per_sample,
            uint32_t  freq,
            uint32_t  sample_watermark_num,
            uint32_t  timestamp);

int subscribe(sensor_command_data_mh_t& data);

をMyCounter.cppに実装(オーバーライド)します。

  • begin() の実装 :

    MyCounterの初期設定を行います。publishされた加速度センサのデータを受け取るためのcallback関数の登録が必要です。callback関数からはMyCounterの subscribe() をコールしデータを渡します。

    記述例
    unsigned char mycounter_cb(sensor_command_data_mh_t &data)
    {
      return MyCounter.subscribe(data);
    }
    
    bool MyCounterClass::begin(int      id,
                               uint32_t subscriptions,
                               int      rate,
                               int      sample_watermark_num,
                               int      size_per_sample)
    {
      return SensorClient::begin(id,
                                 subscriptions,
                                 rate,
                                 sample_watermark_num,
                                 size_per_sample,
                                 mycounter_cb);
    }
  • subscribe() の実装 :

    加速度センサのデータをSubscribeし、独自のアルゴリズムで処理を行うことで、独自のStep Counterを作成することができます。

    今回、ライブラリが提供する AccelSensorClass を使う場合、送信されるデータは、50Hz、50サンプルで、下記記述例中の st_accel_axis のように並んでいるx,y,z軸のデータになります。 このデータを取り出すために、ベースクラス( SensorClient ) の Subscribe() を呼んでください。

    記述例
    int MyCounterClass::subscribe(sensor_command_data_mh_t& data)
    {
      struct st_accel_axis
      {
        float x;
        float y;
        float z;
      } *accel_axis;
    
      accel_axis = static_cast<accel_axis*>(SensorClient::subscribe(data));
      uint32_t  timestamp = data.time;
    
      SensorResultStepCounter output;
    
      /*
        独自のアルゴリズムを実装。
       outputに値を入れる。
       */
    
      publish(&output,
              sizeof(SensorResultStepCounter),
              1, /* 1Hz */
              1, /* 1sample */
             timestamp);
    }
    subscribeされたデータは、 sensor_command_data_mh_t になっています。このデータ構造は、こちらを参照してください。
  • publish() の実装 :

    publish() では、MyCounterで算出された値を発行することになります。 その読み出しアプリケーションクライアントのサンプルとして StepCounterReader が提供されており、それをそのまま使用する場合はpublishするデータ構造は、

    SensorResultStepCounter

    で送る必要があります。

    上記のように、 SensorResultStepCounter の型で渡される場合は、 publish() は、ベースクラス( SensorClient )をそのまま使用して問題ありません。

SensorResultStepCounter 型は、以下になります。

/*--------------------------------------------------------------------------*/
/**
 * @struct StepCounterStepInfo
 * @brief the structure of STEP_COUNTER results.
 */
typedef struct {

  float    tempo;     /**< Indicates tempo of walking / jogging calculated
                       *   from the input acceleration data.
                       *   The unit is [Hz].
                       */
  float    stride;    /**< Indicates stride calculated
                       *   from input acceleration data.
                       *   The unit is [cm].
                       */
  float    speed;     /**< Indicates speed of walking / jogging calculated
                       *   from the input acceleration data.
                       *   The unit is [m/s].
                       */
  float    distance;  /**< Indicates cumulative travel distance calculated
                       *   from the input acceleration data.
                       *   The unit is [m].
                       */
  uint32_t step;      /**< Indicates the number of steps calculated
                       *   from the input acceleration data.
                       * The unit is [step].
                       */
  StepCounterMovementType  movement_type; /**<
                                    * Indicates the walking type calculated
                                    * from the input acceleration data.
                                    */
  uint64_t          time_stamp;    /**< Indicates latest timestamp of the
                                    *   acceleration sensor data used.
                                    */
} StepCounterStepInfo;

/*--------------------------------------------------------------------------*/
/**
 * @struct SensorResultStepCounter
 * @brief the structure of sensor result on step counter commands.
 */
typedef struct
{
  SensorExecResult exec_result; /**< Execute resule.  */

  union
    {
      StepCounterStepInfo steps;        /**< Step count.         */
      SensorAssertionInfo assert_info;  /**< Assert information. */
    };
} SensorResultStepCounter;
自分の論理センサに合わせてデータを変えてみる。

当然、独自の論理センサに合わせて、結果となるセンサデータの方を変えたいこともあるかもしません。その場合は、

MyCounterで、publishする際の、データ型を変更し、

int MyCounterClass::subscribe(sensor_command_data_mh_t& data)
{
  ..()..

  MyStepCounterResult output;

  publish(&output,
          sizeof(MyStepCounterResult),
          1, /* 1Hz */
          1, /* 1sample */
          timestamp);
}

読み出す側のApplication( StepCountReaderClass )で、

subscribe()
{
  MyStepCounterResult* steps = reinterpret_cast<MyStepCounterResult*>(ApplicationSensorClass.subscribe(data));
}

と変換してください。

4.3. 新しい物理センサを作ってみる

[T.B.D]

5. Spresense Arduino マルチコア環境を動かしてみる

Arduino IDE を使ったマルチコアプログラミング開発環境について説明します。

Arduino マルチコア環境では、MultiCore MP ライブラリを使用します。 アプリケーション CPU には、全部で 6 個のコアがあり、1 個の MainCore と 5 個の SubCore で構成されています。 通常のシングルコアアプリケーションでは、ユーザーは MainCore のみを使ってプログラミングします。 一方、ここで説明するマルチコア環境を用いることで、ユーザーは SubCore を含むすべてのコアに対して 任意のアプリケーションプログラムを書いて実行させることができるようになります。

MainCore

MainCore は電源投入時に必ず起動されます。

SubCore(s)

SubCore は MainCore からの制御によって起動されます。全部で 5 個の SubCore があります。

本チュートリアルでは、MultiCore MP ライブラリに付属の 2 種類の Example を動かします。

マルチコア Boot サンプル

4 個の SubCore を起動し、マルチコアを使って L チカを行います。
このサンプルを動作させることで、SubCore を起動するための手順を理解することができます。

マルチコア MessageHello サンプル

MainCore と SubCore 間でメッセージのやり取りを行います。
このサンプルを動作させることで、MainCore と SubCore との通信方法について理解することができます。

5.1. マルチコア Boot サンプルを動かしてみる

主な手順としては、

  1. Arduino IDE を使用してスケッチを開く

  2. コアを選択する

  3. コンパイル&アップロードする

これを動作させたいコアの数だけ繰り返します。

以下の手順にしたがって実行してみてください。

  • デスクトップから Arduino IDE を起動します
    (デスクトップにアイコンが無い場合はスタートメニュー等から起動してください)

    arduino multicore desktop
    マルチコアプログラミングで、複数の Arduino IDE ウィンドウを起動する際に注意事項があります。
    Arduino IDE のメニューから File → New (ファイル → 新規作成) でウィンドウを新規作成した場合、例えば、一つのウィンドウで Core 選択のメニューを切り替えると、その設定が連動して全てのウィンドウに反映されてしまいます。
    これを回避する方法として、Core ごとに複数の Arduino IDE ウィンドウを開くときは、毎回デスクトップ上のアイコンから Arduino IDE を起動してください。そうすることで、Core 選択などのメニュー設定が連動することなくウィンドウごとに独立して設定できるようになります。
  • MainCore プログラミング

    • Arduino IDE メニューから File → Examples → Examples for Spresense → MultiCore MP → Boot → Main (ファイル → スケッチ例 → Spresense用のスケッチ例 → MultiCore MP → Boot → Main) スケッチを開きます

      arduino multicore boot0
      arduino multicore boot1 main
    • Main.ino スケッチの解説

      MP.begin(subid) により、引数 subid で指定した SubCore を起動します。
      ここでは、SubCore1 ~ SubCore4 の計 4 個の SubCore を起動しています。

      arduino multicore boot4 main
    • Arduino IDE メニューから Tools → Core → MainCore (ツール → Core → MainCore) を選択します

      arduino multicore boot2 main

      下のステータスバーで MainCore が選択されていることを確認できます

      arduino multicore boot3 main
      Arduino IDE 1.8.9 ではメニューを切り替えたときに
      ステータスバーが正しく表示されないという不具合があります
    • Upload ボタンを押して、Compile & Upload を行います

      arduino multicore boot5 main
      複数ウィンドウから複数コアのプログラムを同時に Upload することはできません。
      Upload 動作が同時に実行されないようにコアごとに順番に行ってください。
    • Compile 結果のログに使用メモリサイズが表示されます

      MainCore は常に 768 KByte のメモリを使用します。

      arduino multicore boot6 main

      正常に Upload が完了すれば、MainCore プログラミングは完了です

      • 試しに SubCore プログラムがまだ存在しない状態でシリアルモニタを起動してみます。
        SubCore が存在しないので、MP.begin(1~4) の呼び出しがエラーで返ってきていることが分かります。

        arduino multicore boot7 serial err

        シリアルモニタを開いている状態だと、他のウィンドウからの Upload が正しく行えないことがあります。
        この確認を終えたら、シリアルモニタを閉じてください。

続いて SubCore のプログラミングを行います。

  • SubCore プログラミング

    • Arduino IDE メニューから File → Examples → Examples for Spresense → MultiCore MP → Boot → Sub1 (ファイル → スケッチ例 → Spresense用のスケッチ例 → MultiCore MP → Boot → Sub1) スケッチを開きます

      arduino multicore boot0
      arduino multicore boot1 sub1
    • Sub1.ino スケッチの解説

      setup() で MP.begin() を呼び出して、MainCore に起動完了を通知します。
      loop() では MPLog() によるログ表示と LED0 の点滅制御を行っています。

      arduino multicore boot4 sub1
    • Arduino IDE メニューから Tools → Core → SubCore 1 (ツール → Core → SubCore 1) を選択します

      arduino multicore boot2 sub1

      下のステータスバーで SubCore 1 が選択されていることを確認できます

      arduino multicore boot3 sub1
      Arduino IDE 1.8.9 ではメニューを切り替えたときに
      ステータスバーが正しく表示されないという不具合があります
    • Upload ボタンを押して、Compile & Upload を行います

      arduino multicore boot5 sub1
      複数ウィンドウから複数コアのプログラムを同時に Upload することはできません。
      Upload 動作が同時に実行されないようにコアごとに順番に行ってください。
    • Compile 結果のログに使用メモリサイズが表示されます

      ここで使用する SubCore サンプルスケッチは 128 KByte のメモリを使用することが分かります。
      このサイズは、ユーザープログラムに依存して増減します。

      arduino multicore boot6 sub1

      正常に Upload が完了すれば、SubCore 1 のプログラミングは終了です

  • SubCore 2, 3, 4 についても同様の手順で、Compile & Upload を行ってください

    • Sub2 スケッチを開き、SubCore 2 を選択して、Compile & Upload

    • Sub3 スケッチを開き、SubCore 3 を選択して、Compile & Upload

    • Sub4 スケッチを開き、SubCore 4 を選択して、Compile & Upload

  • 動作確認

    • Spresense メイン基板上の 4 個の緑 LED が点滅します

    • シリアルモニタを開くと、各コアからのログ出力が表示されます

      arduino multicore boot7 serial
  • まとめ

    • 簡単なサンプルスケッチを使って SubCore の起動方法について解説しました。
      既存のスケッチをマルチコア環境に移植するときは MP.begin() の呼び出しを追加してください。

    • Arduino IDE の Compile & Upload 方法など、基本的な使い方はマルチコア環境でも特に変わりはありません。 主な差分は、Tools → Core (ツール → Core) でコア選択のメニューが追加されていることです。

5.2. マルチコア MessageHello サンプルを動かしてみる

主な手順は、マルチコア Boot サンプルと同じです。
このサンプルでは、MainCore と SubCore(s) で共通のスケッチを使用します。

  1. Arduino IDE を使用してスケッチを開く(一度だけ)

  2. コアを選択する

  3. コンパイル&アップロードする

これを動作させたいコアの数だけ繰り返します。 このサンプルでは、全て (計 5 個) の SubCore を動かします。

以下の手順にしたがって実行してみてください。

  • デスクトップから Arduino IDE を起動します
    (デスクトップにアイコンが無い場合はスタートメニューから起動してください)

    arduino multicore desktop
    マルチコアプログラミングで、複数の Arduino IDE ウィンドウを起動する際に注意事項があります。
    Arduino IDE のメニューから File → New (ファイル → 新規作成) でウィンドウを新規作成した場合、例えば、一つのウィンドウで Core 選択のメニューを切り替えると、その設定が連動して全てのウィンドウに反映されてしまいます。
    これを回避する方法として、Core ごとに複数の Arduino IDE ウィンドウを開くときは、毎回デスクトップ上のアイコンから Arduino IDE を起動してください。そうすることで、Core 選択などのメニュー設定が連動することなくウィンドウごとに独立して設定できるようになります。
  • MainCore プログラミング

    • Arduino IDE メニューから File → Examples → MultiCore MP → Messsage → MessageHello (ファイル → スケッチ例 → Spresense用のスケッチ例 → MultiCore MP → Message → MessageHello) スケッチを開きます

      arduino multicore boot0
      arduino multicore hello1
    • MessageHello.ino スケッチの解説

      スケッチ内で #ifdef SUBCORE ~ #else ~ #endif を使って、MainCore, SubCore の実装を切り替えています。

      • MainCore ソースコードについて

        setup() で MP.begin(subid) により、5 つの SubCore を起動しています。
        setup() の最後に MP.RecvTimeout(MP_RECV_POLLING) により受信をポーリングモードに設定しています。
        このモードにすると MP.Recv() を呼び出したときに受信待ちに入らずポーリング動作を行います。
        loop() では、MP.Recv() で各 SubCore から packet のアドレスを受信し、packet 内の message を printf() 出力しています。

        arduino multicore hello4 main
      • SubCore のソースコードについて

        setup() で MP.begin() を呼び出して、MainCore に起動完了を通知します。
        loop() では、packet に "Hello" message を格納し、そのアドレスを MP.Send() で MainCore へ送信しています。

        arduino multicore hello4 sub
    • Arduino IDE メニューから Tools → Core → MainCore (ツール → Core → MainCore) を選択します

      arduino multicore hello2 main

      下のステータスバーで MainCore が選択されていることを確認できます

      arduino multicore boot3 main
      Arduino IDE 1.8.9 ではメニューを切り替えたときに
      ステータスバーが正しく表示されないという不具合があります
    • Upload ボタンを押して、Compile & Upload を行います

      arduino multicore hello5 main
      複数ウィンドウから複数コアのプログラムを同時に Upload することはできません。
      Upload 動作が同時に実行されないようにコアごとに順番に行ってください。
    • Compile 結果のログに使用メモリサイズが表示されます

      MainCore は常に 768 KByte のメモリを使用します

      arduino multicore boot6 main

      正常に Upload が完了していれば、MainCore プログラミングは終了です。

続いて SubCore のプログラミングを行います

  • SubCore プログラミング

    • Arduino IDE メニューから Tools → Core → SubCore 1 (ツール → Core → SubCore 1) を選択します

      arduino multicore hello2 sub1

      下のステータスバーで SubCore 1 が選択されていることを確認できます

      arduino multicore boot3 sub1
      Arduino IDE 1.8.9 ではメニューを切り替えたときに
      ステータスバーが正しく表示されないという不具合があります
    • Upload ボタンを押して、Compile & Upload を行います

      arduino multicore hello5 main
      複数ウィンドウから複数コアのプログラムを同時に Upload することはできません。
      Upload は同時に実行されないようにコアごとに順番に行ってください。
    • Compile 結果のログに使用メモリサイズが表示されます

      ここで使用する SubCore サンプルスケッチは 128 KByte のメモリを使用することが分かります。
      このサイズは、ユーザープログラムに依存して増減します。

      arduino multicore boot6 sub1

      正常に Upload が完了していれば、SubCore 1 のプログラミングは終了です

  • SubCore 2, 3, 4, 5 についても同様の手順で、Compile & Upload を行ってください

    • SubCore 2 を選択して、Compile & Upload

    • SubCore 3 を選択して、Compile & Upload

    • SubCore 4 を選択して、Compile & Upload

    • SubCore 5 を選択して、Compile & Upload

  • 動作確認

    • シリアルモニタを開いてください

    • 各 SubCore が送信したメッセージを MainCore が受信し、シリアルモニタ上に表示されます

      arduino multicore hello7 serial
  • まとめ

    • サンプルスケッチを使って SubCore との通信方法について解説しました。

    • コア間でメモリが共有されているので、アドレスを渡してメッセージ通信を行うことができます。

    • コアごとにスケッチを分けずに共通のスケッチを使用したマルチコアプログラミングも可能です。

5.3. 特記事項

  • MultiCore MP ライブラリについて、詳しくは 開発ガイド を参照してください。

  • Spresense 基板上に既にアップロード済みの SubCore バイナリがあり、それらを一括して消去したい場合は、Spresenseローダーのインストール を行ってください。ローダのインストール時に、一旦、すべての SubCore バイナリを削除してからローダのインストールが始まります。

    arduino multicore remove subcore

    なお、MainCore から MP.begin() を呼び出さない限り、勝手に SubCore が動作することはありません。 そのため、古い SubCore がアップロードされたまま残っていても特に問題はありません。

  • マルチコアプログラミングで、Core ごとに複数の Arduino IDE ウィンドウを開くときは、毎回デスクトップ上のアイコンから Arduino IDE を起動してください。そうすることで、Core 選択などのメニュー設定がウィンドウごとに独立して設定できるようになります。

  • Arduino IDE での複数起動や Core を切り替える操作が煩雑ですが、arduino-builder や arduino-cli といったコマンドラインツールを使用することも可能です。また、Upload についても、直接 flash_writer ツールを使用すれば、各コアのバイナリを一回のコマンドで一括してロードすることも可能です。コマンドラインを用いた方法について後日ドキュメントに掲載する予定です。