Spresense Header CodeSpresense Header Code

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

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

Spresense Arduino Library 開発ガイド

1. Spresense で Arduino スケッチを書いてみよう!

Spresense の Spresense Arduino Library をインストールすると、Arduino IDE のメニューの File → Examples → Spresense に、多くのサンプルスケッチがあります。Spresense Arduino Library のインストールについては、Spresense Arduino Library の使い方 を参照してください。

多くの Arduino スケッチをSpresenseで動かすことができますが、Arduino Uno と Spresense に、幾つかハードウェアの違いがあり、全てのスケッチをそのまま動かせるわけではありません。詳細については、Spresenseと Arduino Uno のハードウェの違いを参照してください。

1.1. Spresense Arduino Library でスケッチを書く際の注意事項について

Spresense は、Arduino互換APIをサポートしていますが、使用にあたり制限や違い、そして追加機能があります。この章ではそのような注意事項について記述しています。Arduino プログラミング言語仕様については、Arduino Language Reference を参照してください。

1.1.1. LED

Spresense メインボードには4つのビルトインLEDが搭載されています。これらはアプリケーションから自由に使うことができます。LEDのピン番号は LED0LED1LED2LED3 として定義されています。LED_BUILTIN の定義は、LED0 に割り当てられています。これらは通常のデジタル端子と同様に pinMode(LED番号, OUTPUT)digitalWrite(LED番号, HIGH/LOW) で操作できます。また、 ledOn(LED番号) もしくは ledOff(LED番号) という専用APIを使うこともできます。

1.1.2. EEPROM

Spresense は、EEPROM を内蔵していませんが、Flash メモリを使用して EEPROM をエミュレートしています。永続的なデータを扱いたい場合は、EEPROMライブラリ、もしくは Spresense拡張ボードのSDカードを使用することができます。

1.1.3. Serial

Spresense には二つのシリアルポート(UART)が備わっており、Serial 機能をサポートしています。メインボード上の USB ポートはデバッグシリアル専用で Serial と定義して使用できます。一方、DO0、DO1 端子のシリアルは、 Serial2 のインスタンス名で使用することができます。

1.1.4. pinMode()

pinMode(pin, mode)mode について、 INPUT, OUTPUT, INPUT_PULLUP の他に INPUT_PULLDOWN をサポートしています。I/O電圧に関して、メインボード側のデジタル端子は1.8Vですが、拡張ボードのデジタル端子は 3.3V もしくは 5V 出力(ジャンパJP1で選択)になるように設計されています。この電圧レベル変換は、レベルシフタとプルアップ抵抗で行っているため、拡張ボードのデジタル端子にはいくつかの制約があります。

  • 起動時は、拡張ボードの全てのデジタル端子がプルアップされ HIGH になります。pinMode()で、 INPUT_PULLDOWN を指定してもプルアップされるレベルの方が高いため、入力は HIGH になります。

  • ピンがインプットに設定されている場合、初期値は HIGH に設定されます。これはプルダウン抵抗を必要とする回路に影響を与えますので注意してください。

  • ピンの出力は、 digitalWrite() で設定されてはじめて、 HIGH もしくは、 LOW にセットされます。

レベルシフタやプルアップ抵抗の詳細については、Spresense拡張ボード回路図 を参照してください。

1.1.5. analogRead()

Spresense は A0 から A5 まで 6 つのアナログ入力専用ピンをもっています。これらのピンをデジタルピンとして使用することはできません。 analogRead() に指定するピンには、ピン番号の数字だけではなく A0A1A2A3A4A5 という定義を使用してください。

1.1.6. analogReference()

Spresense 拡張ボードのアナログ入力基準電圧は5V固定、メインボードのアナログ入力基準電圧は0.7V固定です。 analogReference() 関数はサポートされていません。

1.1.7. analogWrite()

analogWrite(pin, value) にて、約 490 Hz 周期の PWM 信号を出力します。指定する pin 番号が、3, 5, 6, 9 の場合は、ハードウェア機能により PWM 信号を出力します。それ以外の pin 番号を指定した場合は、タイマーを使用して信号を交互に High / Low 出力することでソフトウェア制御により PWM 信号を生成します。

  • pin 3, 5, 6, 9 : ハードウェア制御 PWM

  • 上記以外の pin : ソフトウェア制御 PWM

ハードウェア制御 PWM を使用する場合、3 番 pin と 9 番 pin は連動して PWM モードに切り替わります。analogWrite() 関数で指定した pin には PWM 信号が出力されますが、同時にもう一方の pin も PWM モードに切り替わるため Low 信号が出力されます。両方の pin に対して順番に analogWrite() を呼び出して、二つの pin を PWM として使用することは可能ですが、どちらか一方だけを GPIO として使用するような使い方はできません。また、5 番 pin と 6 番 pin の組み合わせに対しても同様の制約があります。

1.1.8. tone()

tone(pin, frequency [, duration]) は、タイマーを使用してソフトウェア制御により tone 信号を生成します。このときタイマーの分解能が 1 マイクロ秒なので、frequency の半周期が 1 マイクロ秒で割り切れない場合に周波数誤差が発生します。 設定可能な最大 frequency は約 166 kHz です。 tone() 関数は、attachTimerInterrupt() と同じタイマーリソースを使用するため、attachTimerInterrupt() と同時に使用することはできません。

1.1.9. F()

F() マクロはサポートされていません。F() マクロを使用してもコンパイルは可能ですが、通常の文字列データと同様に RAM 上に配置されます。(Fマクロの例: Serial.println(F("This string will be stored in flash memory")); )

1.1.10. PROGMEM

PROGMEM 機能はサポートされていません。 PROGMEM は空マクロとして定義されているため、使用箇所があってもコンパイルエラーにはなりません。

1.1.11. attachInterrupt()

ピンに対する割り込み番号は、attachInterrupt() 関数内で動的に割り当てられます。 digitalPinToInterrupt() は空マクロとして定義されており、 次のどちらの使い方も可能です。

API

attachInterrupt(digitalPinToInterrupt(pin), void (*isr)(void), mode);
attachInterrupt(pin, void (*isr)(void), mode);

Parameter

pin: D05 などのピン番号

isr: 割り込みが発生したときに呼ばれる関数。この関数は引数も戻り値もありません。

この関数は割り込みハンドラから呼ばれるため、呼び出し可能な API には制限があります。 例えば、この関数内から Analog I/O 関数を使用することはできません。

mode: 割り込みを発生させるトリガ

  • LOW: ピンの状態がLOWのとき

  • CHANGE: ピンの状態が変化したとき

  • RISING: ピンの状態がLOWからHIGHに変わったとき

  • FALLING: ピンの状態がHIGHからLOWに変わったとき

  • HIGH: ピンの状態がHIGHのとき

ピン番号の変化に対して、チャタリング防止用にRTC(32.768kHz) 3サイクル分のノイズフィルタをもっています。 そのため、急峻なパルス上の信号変化に対しては割り込みを取得できないことがあります。

1.1.12. attachTimerInterrupt()

タイマー割り込み機能をサポートしています。 この機能は、tone() と同じタイマーリソースを使用するため、tone() と同時に使用することはできません。 attachTimerInterrupt() 機能はシステム上で一つだけ動作します。既に使用中の状態で、 再び attachTimerInterrupt() を呼び出すとエラーになります。異なるハンドラや周期で再設定する際は、detachTimerInterrupt() を呼び出してリソースを解放した後に、再度、attachTimerInterrupt() を呼び出してください。

API

void attachTimerInterrupt(unsigned int (*isr)(void), unsigned int us);

Parameter

isr: タイマー割り込みが発生したときに呼ばれる関数。この関数は次のタイマー周期を戻り値として返します。

  • この関数が 0 を return したときは、タイマーが停止し、ワンショットタイマーとして使用できます。

  • 周期タイマーとして使用したいときは、attachTimerInterrupt() で指定した us 時間と等しい値を return で返してください。

  • その他、return で任意の値を返すことで、次のタイマー割り込みまでの時間を動的に変更することができます。

この関数は割り込みハンドラから呼ばれるため、呼び出し可能な API には制限があります。 例えば、この関数内から Analog I/O 関数を使用することはできません。

us: マイクロ秒

1.1.13. micros()

micros() は RTC (32.768kHz) サイクルでカウントしているため、分解能は約 30 マイクロ秒です。

1.2. メモリの使用状況レポートに関して

Spresense の特徴として、コンパイルされたスケッチは全てフラッシュメモリ内にインストールされ、 それが実行されるときに、コードや読み出し専用のデータを含めてすべて、フラッシュメモリからRAM 上に展開されて RAM 上で実行されます。

展開先の RAM サイズ容量は、 デフォルトの構成でアプリケーション SRAM 1.5 MB のうちの半分 768 キロバイト(= 786432 バイト) が割り当てられています。 このスケッチのプログラムサイズがこの RAM サイズ容量を超えてしまった場合は、コンパイルに失敗しエラーが発生します。

Arduino IDE上で、スケッチをコンパイルした後に以下のようなメモリ使用状況のレポートが出力されます。 このレポートにより、スケッチが消費するメモリサイズを確認することができます。

最大786432バイトのフラッシュメモリのうち、スケッチがxxxxxxバイト(xx%)を使っています。
最大786432バイトのRAMのうち、グローバル変数がxxxxxxバイト(xx%)を使っていて、ローカル変数でxxxxxxバイト使うことができます。

このレポートでは、本来とは異なる意味で用語が使用されているので次のように読み替えてください。

  • フラッシュメモリ: 展開先の RAM サイズ容量を表します

  • グローバル変数 :スケッチが静的に使用する RAM サイズを表します

  • ローカル変数:RAM サイズ容量からスケッチが静的に使用する RAM サイズを差し引いた、残りのRAMサイズを表します

スケッチプログラムが消費するメモリとして、静的に確保されるサイズの他に、動的に確保されるヒープ領域があります。 ローカル変数 で表される残りの RAM サイズは全てこのヒープ領域に割り当てられます。 そのためスケッチ作成時にはヒープ領域の使用分も考慮し、残りの RAM サイズを空けておく必要があります。 目安として、スケッチプログラムの使用サイズが全体の 75% を超えると スケッチが使用できるメモリが少なくなっています。動作が不安定になる可能性があります。 という警告が出力されますので、そのときはスケッチプログラムのコードサイズを削減するなど、プログラムを見直してください。

2. Spresense ハードウェア比較

この章では、Spresense の他のオープンプラットフォームである、Arduino Uno や Raspberry Pi model 3B と比較し、何が違うのかを明らかにします。

2.1. プロセッサとオペレーションシステム

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

Processor type

AVR

ARM M4F

ARM A53

Bits

8

32

64

Number of cores

1

6

4

Clock speed

16 MHz

156 MHz

1.2 GHz

Operating system

None

NuttX

Linux

Boot time

0

<1 second

~20 Seconds

Spresense は、 Arduino のボードと比較すると遥かにパワフルなプロセッサを備えています。これはより計算が必要とされるようなセンサーフュージョンアプリケーションに非常に有利です。しかし、それよりも遥かに高速なCPUを持つ Raspberry Pi には及びません。

Spresense による大きなアドバンテージはその起動速度にあります。 Raspberry Pi は高機能であるが故に起動に20秒はかかりますが、Spresense では1秒もかからずに起動することができます。

2.2. メモリシステム

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

RAM

0.002MB

1.5 MB

1000MB

FLASH

0.032MB

8 MB

None

SD Card

Shield

On-Board, optional

On-Board, essential

eMMC

None

Shield

None

EEPROM

0.001MB

Use Flash

Use microSD card

Arudino は小さなメモリのため、複雑なアプリケーションを構築することを難しくしています。一方、 Raspberry Pi は遥かに大きなメモリを有していますが、それはシステムとして micro SD カードを必要とします。

Spresense はちょうどその中間の位置にあります。プログラムをストアするフラッシュメモリ(ROM)は 8MB あり、またRAMは 1.5MB 有しています。また、micro SD カードもサポートしているため、音楽データや画像データをストアすることができます。

2.3. 電力供給

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

Voltage

5V or 6-20V

5V or LiPo(3.7V)

5V

Typical Operating Power

50 mW

100mW or low power modes

2400mW

Spresense のチップセットである CXD5602 と CXD5247 は、ウェアラブル製品向けに設計されているため、シングルセルのLiPoバッテリで駆動できるように設計されています。また充電機能もあります。しかし、Spresense では安全性の観点から使えるようになっていません。

電源供給は、Spresense メイン基板のUSBコネクタから行ってください。

Spresense は、省電力モードを活用すると非常に小さな電力でセンサー等のイベントを待ち受けることができます。これらは、 ArduinoRaspberry Pi にはない IoT向けセンシングプロセッサならではの機能です。Spresense SDK を使えば、省電力機能を効率的に使うことが可能になります。

2.4. オーディオ

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

Quality

Shield

High

Low

Microphones

Shield

up to 8 microphone

Stereo

Speakers

Shield

Stereo (BTL)

Stereo

CXD5602 と CXD5247 は、ハイクオリティのポータブルオーディオ機器としての機能を持つようにも設計されています。ハイレゾリューションのオーディオの再生とマルチ録音が可能になっています。

CXD5247 は高性能のA/Dコンバータを有しており、アナログなら4チャンネル、デジタルなら8チャンネルのマイク入力を扱うことが可能です。さらに、フルデジタルアンプも備えており、非常にクリアな音でスピーカーに直接出力できます。スピーカー出力はBTL(Balanced Transformer Less)のため、ダイナミックな音を提供することができます。

CXD5602 は専用のAudio DSPを備えており、ハイレゾリューション音源の再生や録音が可能になっています。

これらの機能は、 ArudinoRaspberry Pi を遥かに凌ぐ、Spresense ならではの大きな特長と言えるでしょう。

2.5. GNSS測位機能とリアルタイムクロック

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

GNSS

Shield

GPS & GLONASS

Shield

Time

Shield

RTC

Shield

Spresense は超低消費電力のGNSS受信機能を有しています。これは正確な位置を必要とするトラッキング端末やドローンには非常に重要な機能です。

また、GNSS信号から受信できる極めて正確な時刻でリアルタイムクロックを同期できるため、時刻が重要なデータロギングに向いています。また、時刻をトリガーとして同期しなければならないアプリケーション(例えば、360度映像システム)の制御にも使えます。

ArduinoRaspberry Pi ではそのような機能はシールドで実現しなければならず、低消費電力やローレイテンシーで実現することを非常に難しくしています。

2.6. デジタル端子

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

IO Pins

14

29 + 4 LED

27

IO voltage

5V

5V/3.3V/1.8V

3.3V

UART

1

2

2

SPI

1

1 (3.3/5V) +1 (1.8V)

1

I2C

1

1 (3.3/5V) +1 (1.8V/camera)

2

PWM

6

4

1

Spresense は、UART, I2C, SPI, PWM, I2S など非常に多様なデジタル端子を備えています。

Spresense メインボードのデジタル端子の基準電圧は1.8Vで、Spresense拡張ボードのデジタル端子の基準電圧は、3.3Vもしくは5Vに設定できます。これはメインボードの1.8V基準電圧を3.3Vもしくは5Vにレベルシフトしています。また、メインボードには、ビルトインの四つのLEDを備えています。

Spresense メインボートとSpresense拡張ボードは、100ピンのB2Bコネクタで接続されています、

2.7. A/Dコンバータ

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

Channels

6

6

None

Bits

10

10

None

Fastest rate

~10 kHz

500 kSPS

None

Spresense 拡張ボードには、 Arduino と同じように6チャンネルのアナログ入力端子を備えています。しかし、 Arduino と異なり、アナログ入力端子をデジタル端子として使うことはできません。

また、A/Dコンバータの電圧レンジは5V固定です。SpresenseメインボードのA/Dコンバータ入力端子の電圧レンジは0.7Vなので、Spresense拡張ボードからの入力をノイズを抑えるために、抵抗分圧で電圧シフトしています。

したがって、接続されるデバイスの出力インピーダンスには十分注意を払ってください。

2.8. コネクティビティ

Feature

Arduino Uno

Spresense

Raspberry Pi 3B

USB

1 device

2 device

4 host

Camera

Shield

5M Pixel

8M Pixel

Video display

None

SPI up to 360x240 Pixel

HDMI, DSI

WiFi

Shield

Shield

802.11n

Bluetooth

Shield

Shield

4.1 Classic, Low Energy

Ethernet

Shield

Shield

10/100

Cellular

Shield

Shield

Shield

Spresense メインボードは、 Raspberry Pi と同じく専用のカメラインターフェースを用意しています。専用のカメラボードを使うことでHDの静止画を取得することができます。

3. ライブラリ

3.1. Audio ライブラリ

Spresense Audio ライブラリは、ハイレゾ音源含むオーディオデータの再生・録音を SD カードを使って行うことができます。シンプルなスケッチでハイレゾリューションオーディオの世界を体験することができます。

Spresense は、ADC と DAC (フルデジタルアンプ機能含む) を搭載しており、Audio ライブラリからこれらの機能を制御します。Spresense は 6つの CPU コアが搭載されており、オーディオの信号処理をアプリケーションプロセッサとは別のコア(以降、それらのコアをDSP と呼びます)で動作させることにより、非常に効率的かつ簡単な記述でオーディオのアプリケーションを構築することができます。

  • ハイレゾは、現時点では、192kHzのWAV(LPCM)のみサポートしています。

  • アプリケーションが求めるオーディオ機能に応じて、適切な DSP Codec バイナリを事前にインストールし、アプリケーションプログラムから DSP がインストールされている場所を指定する必要があります。詳細については後述します。

Audio ライブラリの主な特徴

  • Sound recorder

  • Audio player

  • Volume control

  • Balance (L/R Gain)

  • Beep generation

    • Beep音は、Arduino の tone() 関数と異なり、ヘッドホンに出力されますので注意してください。

この Audio ライブラリは input channel、output channel を選択できます。

Audio Input Channels
  • Analog microphone

  • Digital microphone

  • I2S

Audio Output Channel
  • Analog headphone

  • I2S

DSP codec は以下のフォーマットを扱うことができます。

  • MP3

MP3 ファイルは、ID3v2 TAG(特に画像データのような大きなメタデータ)がある場合、 デコーダがparseエラーになります。 MP3Tag などのツールで、タグ情報を削除してください。
  • WAV (PCM)

録音・再生時に、サンプリングレート、ビットレートを指定してください。例えば、MP3 codec は 32000, 44100, 48000 Hz をサポートしています。

詳細については、Audio Subsystem を参照してください。

3.1.1. Audio 動作環境

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

  • Spresense 拡張ボード

  • 録音用マイク

  • 再生用ヘッドホン

  • マイクロ SD カード

Spresense 拡張ボードは、マイク入力専用ピンと SD カードスロット、ヘッドホンジャックを備えています。ヘッドホンジャックは、3極 3.5mm ステレオジャックです。

ピン配置やオーディオ関連のコネクタに関する詳細については マイクの使用方法スピーカーの使用方法 を参照してください。

3.1.2. Audio スケッチのサンプル

Audio ライブラリを使ったサンプルスケッチは、Arduino IDE 上から ファイル → スケッチ例 → Spresense用のスケッチ例 Audio → application 以下にあります。Audio のサンプルスケッチを動かすときは、事前に DSP codec バイナリの準備が必要です。

録音用サンプル (recorder)

このサンプルでは、SD カードとマイクを使用します。

マイクの使用方法を参考に、拡張ボードにマイクを接続してください。

マイクに関するコンフィグレーションをし直したい場合は、MIC channel select map の設定を参照してください。
SDKのbuildとArduinoIDEへの組み込みに関しては、How to prepare Arduino environment を参照してください。

MP3エンコード用の DSP バイナリファイル MP3ENC 、 もしくは、WAV、PCMエンコード用の DSP バイナリファイル SRCDSP Codec バイナリのインストール を参照し、インストールしてください。

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

サンプルは、起動後に録音を開始し、一定時間で録音を停止します。録音したデータは "Sound.mp3" というファイル名で SD カードに保存されます。

記録する音声フォーマットは、 initRecorder の引数で切り替えることができます。

WAVファイルを記録する場合、音声記録実行前に、 writeWavHeader を呼び出し、WAVヘッダを作成する必要があります。
recorder_wav も参照してください。

ハイレゾ(192kHz)での記録を行う場合は、 setRecorderMode 実行前に、 setRenderingClockModeAS_CLKMODE_HIRES を指定して呼び出します。

MicのGainを設定したい場合は、 setRecorderMode の"input_gain"を設定してください。
デジタルは、0db~-78.5db
アナログは、21db~-78.5db
が設定できる範囲になります。

シリアルモニタにエラーメッセージが表示されている場合は、オーディオサブシステムのエラーについて を参照してください。

録音データを確認する場合は、SD カードを取り外して、PC 上で録音されたデータを確認してください。 また、後述する再生用サンプルでその録音データを再生することも可能です。

音声取得ができたとしても、SDカードの書き込み性能と動作しているアプリケーションなどの要因で、すべてのデータを書き込みことができない可能性があります。
現在の拡張ボードの場合、目安として、8ch/48kHz か、2ch/192kHzが限界になります。

また、SDカードのスピードクラスにも依存します。できるだけ転送速度の速いものをお使いください。

SDカードに書き込む際に必要なバッファのサイズは、デフォルトで、160kバイトになっています。このサイズは、ハイレゾのWAV音声の書き込みが可能なサイズになっており、48kHzのMP3ファイルなどを記録する場合は、メモリを不必要に使用します。
そのため、 setRecorderMode で、使用するバッファサイズを変更することができます。目安としては、ハイレゾのWAVファイルを記録する場合は、デフォルトの160kバイトを、48KHzのMP3ファイルを記録する場合は、8kバイトぐらいに設定することをお勧めします。

サイズに関しては、あくまで目安です。SDカードの性能、アプリケーションの処理量などに応じて、調整して使ってください。
バッファを小さくしすぎると、SDカードへの書き込み時にエラーが発生します。書き込みのオーバーフローが発生する場合は、バッファサイズを大きくしてください。

接続しているマイクがデジタルマイクであった場合は、 setRecorderMode の"is_digital"を"true"にしてください。

音楽再生用サンプル (player)

このサンプルでは、SD カードとヘッドホンを使用します。

拡張ボードにヘッドホンを接続してください。

再生したい MP3/WAV ファイル、もしくは、recorder サンプルスケッチで録音された MP3/WAV ファイルを "Sound.mp3" もしくは、"Sound.wav" というファイル名で SD カードのルートディレクトリに置いてください。

  • MP3 ファイルのサンプリングレートは 32000, 44100 または 48000 bps をサポートしています。

  • MP3 ファイルは、ID3v2 TAG(特に画像データのような大きなメタデータ)がある場合、デコーダがparseエラーになります。 MP3Tag などのツールで、タグ情報を削除してください。

MP3デコード用の DSP バイナリファイル MP3DEC 、もしくは、WAVデコード用の DSP バイナリファイル WAVDEC 、 を DSP Codec バイナリのインストール を参照しインストールしてください。

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

スケッチがアップロードされ実行されると、SD カードに置いた MP3/WAV ファイルがヘッドホンから再生されます。

ハイレゾ(192kHz)コンテンツの再生を行う場合は、 setPlayerMode 実行前に、 setRenderingClockModeAS_CLKMODE_HIRES を指定して呼び出します。

ハイレゾ、ノーマルレゾリューションを切り替える場合は、一度、 setReadyMode を呼び出し、Ready状態に遷移する必要があります。

出力デバイスをI2Sに切り替えたい場合は、 setPlayerMode での出力デバイスを AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT に切り替えてください。
I2Sの動作モードは、Slaveモード、I2Sフォーマットモード、48000Hz、Stereo のみ対応です。

SDカードから読み出す際に必要なバッファのサイズは、各プレイヤーごとにデフォルトで、160kバイトになっています。このサイズは、ハイレゾのWAV音声の読み出しが可能なサイズになっており、48kHzのMP3ファイルなどを再生する場合は、メモリを不必要に使用します。
そのため、 setPlayerMode で、使用するバッファサイズを変更することができます。目安としては、192kHzのハイレゾのWAVファイルを再生する場合は、デフォルトの160kバイトを、128kbps程度ののMP3ファイルを再生する場合は、24kバイトぐらいに設定することをお勧めします。

サイズに関しては、あくまで目安です。SDカードの性能、アプリケーションの処理量などに応じて、調整して使ってください。
バッファを小さくしすぎると、SDカードからの読み出し時にエラーが発生します。読み出しデータのアンダーフローが発生する場合は、バッファサイズを大きくしてください。

SPRESENSEからのオーディオ出力が拡張ボードのオーディオコネクタを用いたラインアウトの場合、CXD5247から出力されるAudioの信号のドライブ能力を setPlayerMode の"sp_drv"で、"AS_SP_DRV_MODE_LINEOUT"に設定してください。
CXD5247のアンプ出力をそのまま用いる、Speakerピンでの出力を行う場合は、"sp_drv"で、"AS_SP_DRV_MODE_4DRIVER"に設定してください。 初期値は、"AS_SP_DRV_MODE_LINEOUT"になっています。

シリアルモニタにエラーメッセージが表示されている場合は、オーディオサブシステムのエラーについて を参照してください。
Beep音サンプル (beep)

このサンプルは、ビープ音を鳴らす例になります。 ヘッドホンを使用します。

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

Beep音を発音するためには、setPlayerMode を呼び出し、音楽再生モードに変更する必要があります。

プレイリスト音楽再生用サンプル (play_playlist)

このサンプルは、プレイリスト (playlist) を使用して音楽を再生するためのサンプルスケッチです。

プレイリスト機能を使用するためには、PC 等で事前にプレイリストファイルを作成して SD カードにコピーしておく必要があります。 本サンプルスケッチが使用する SD カードのディレクトリ構成を以下に示します。

SD カードルートディレクトリ
|-- BIN/
|   |-- MP3DEC
|   `-- WAVDEC
|-- AUDIO/
|   |-- Sound1.mp3
|   |-- Sound2.mp3
|   |--   :
|   |-- Sound1.wav
|   |-- Sound2.wav
|   |--   :
`-- PLAYLIST/
    `-- TRACK_DB.CSV
  • BIN/ ディレクトリに、後述されるインストール方法にしたがって、MP3DEC や WAVDEC 等の DSP バイナリファイルをコピーしてください。

  • AUDIO/ ディレクトリに、プレイリストで再生する音楽コンテンツファイルをコピーしてください。

  • PLAYLIST/ ディレクトリに、プレイリストファイル ( TRACK_DB.CSV ) をコピーしてください。

プレイリストファイル TRACK_DB.CSV のフォーマットを以下に示します。 各ファイルの情報が行単位で書かれた CSV (comma-separated values) 形式のテキストファイルです。

[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
 :

音楽コンテンツのファイル名、アーティスト名、アルバム名や、コーデック情報(チャンネル数、ビット長、サンプリングレートHz)を記述してください。 TRACK_DB.CSV の例を以下に示します。

Sound1.mp3,Artist1,Album1,2,16,44100,mp3
Sound2.mp3,Artist1,Album1,2,16,44100,mp3
Sound1.wav,Artist2,Album2,2,16,48000,wav
Sound2.wav,Artist2,Album2,2,24,192000,wav

また、プレイリストファイルを作成するための簡単なスクリプトツール mkplaylist.py を提供しています。 こちら を右クリックしてファイルをダウンロードしてお使いください。 このスクリプトは ffmpeg-python を使用しているため、ffmpeg 及び ffmpeg-python をインストール済みの環境でご利用ください。

mkplaylist.py の使用方法を以下に示します。

$ python mkplaylist.py
usage: python mkplaylist.py dirname [dirname2] [dirname3] ...
usage: python mkplaylist.py -f filename

Generate an audio playlist file named as TRACK_DB.CSV

引数に音楽ファイルを含むディレクトリパスを指定して実行してください。 正常に実行を完了すると、TRACK_DB.CSV ファイルがカレントディレクトリに出力されます。 既に TRACK_DB.CSV ファイルが存在する場合はファイルの末尾に追加されます。

$ python mkplaylist.py MyMusic
  • 音楽コンテンツファイル名の拡張子は .mp3 もしくは .wav にしてください。

  • 日本語のような2バイトコードを含むファイル名はサポートされていません。ファイル名を ASCII コードの文字列に変更してください。

  • プレイリストファイルが CSV 形式で書かれているため、filename, artist, album 名に "," コンマを含む文字列を使用しないでください。

SD カードを基板に挿した状態で、 Arduino IDE 上から ファイル → スケッチ例 → Spresense用のスケッチ例 Audio → application → play_playlist を選択してサンプルスケッチを起動して実行してください。

起動するとシリアルモニタに次のようなメニューが表示されます。シリアルからのキー入力にしたがって各種の動作を行います。

=== MENU (input key ?) ==============
p: play  s: stop  +/-: volume up/down
l: list  n: next  b: back
r: repeat on/off  R: random on/off
a: auto play      m,h,?: menu
=====================================

また、EEPROM ライブラリを使用して、volume 値, random / repeat / auto play 等の設定情報を不揮発メモリに保存しています。 次回起動時に、前回プリセットされた情報をもとに動作するというサンプルアプリケーションになっています。

オリジナルのミュージックプレイヤーを作成する際に参考にしてください。

Audio Throughサンプル (through)

このサンプルは、I2Sから入力されたデジタル音声をアナログ出力に出力したり、マイク入力をI2Sに出力するなど、オーディオHWのパス設定を用いることで、省電力で、非常にレイテンシの少ない出力を実現します。
このアプリケーションは、SWでのAudio信号処理が必要でないため、DSP、すなわち、SDカードが不要です。
マイクを使用する場合は、マイクの使用方法を参考に、拡張ボードにマイクを接続してください。

マイクに関するコンフィグレーションをし直したい場合は、MIC channel select map の設定を参照してください。
SDKのbuildとArduinoIDEへの組み込みに関しては、How to prepare Arduino environment を参照してください。

例えば、I2Sから入力された音声をアナログ出力したい場合は、 setThroughMode の"input"を"I2sIn"に設定し、
"i2s_out"を"None"に、
"sp_out"を"true"に設定します。

Micから入力された音声をI2S出力したい場合は、 setThroughMode の"input"を"MicIn"に設定し、
"i2s_out"を"Mic"に、
"sp_out"を"false"に設定します。

MicのGainを設定したい場合は、 setThroughMode の"input_gain"を設定してください。
デジタルは、0db~-78.5db
アナログは、21db~-78.5db
が設定できる範囲になります。

SPRESENSEからのオーディオ出力が拡張ボードのオーディオコネクタを用いたラインアウトの場合、CXD5247から出力されるAudioの信号のドライブ能力を setThroughMode の"sp_drv"で、"AS_SP_DRV_MODE_LINEOUT"に設定してください。
CXD5247のアンプ出力をそのまま用いる、Speakerピンでの出力を行う場合は、"sp_drv"で、"AS_SP_DRV_MODE_4DRIVER"に設定してください。 初期値は、"AS_SP_DRV_MODE_LINEOUT"になっています。

そのほかの複合サンプル

通常サンプルの他に、幾つかの複合動作サンプルがあります。

  • dual_players
    2つの音楽再生を同時に行うサンプルです。

  • pcm_capture
    音声データをキャプチャするだけのサンプルです。信号解析などにお使いください。

  • rec_play
    音声を録音した後、その音声を再生するサンプルです。オーディオ動作を切り替えるためのサンプルになります。

  • Recorder_with_rendering
    音声を確認しながら録音するサンプルです。

  • Voice_effector
    入力音声を加工しながら出力するサンプルです。

3.1.3. DSP Codec バイナリのインストール

オーディオの再生・録音機能を動かす際に、適切な DSP バイナリファイルを下記の手順に従ってインストールしてください。

表 1. DSPの種類
DSPファイル名 DSP インストーラー 説明

MP3DEC

mp3_dec_installer

MP3 オーディオ再生で使用します

WAVDEC

wav_dec_installer

WAV (PCM) オーディオ再生で使用します

MP3ENC

mp3_enc_installer

MP3 オーディオ録音で使用します

SRC

src_installer

WAV(PCM) オーディオ録音で使用します

DSP バイナリのインストール先は、SD カード、もしくは、フラッシュを選択できます。インストール手順は、単純に PC を使って SD カードへファイルをコピーする方法と、DSP インストーラーと呼ばれるスケッチを用いた方法の二通りがあります。

DSP バイナリのインストール作業は、DSP ファイルの更新が無い限り、一回実行してインストール済みの状態であれば毎回作業する必要はありません。
  • SD カードへ DSP ファイルをコピーしてインストールする場合

    1. 上の表 にあるDSP ファイルを次の手順でインストールされているSpresense Arduino パッケージから取り出します。ご使用のPCのプラットフォーム毎に異なりますのでお使いのOSの手順をご参照ください。

      • Windowsの場合

        • 次のテキストをコピーして pickup_dsp.bat としてファイルを作成します。

          set SPRESENSE_DIR=%userprofile%\AppData\Local\Arduino15\packages\SPRESENSE\hardware\spresense
          set AUDIO_DSP_DIR=libraries\Audio\examples\dsp_installer
          
          for /f "usebackq tokens=*" %%i IN (`dir /B %SPRESENSE_DIR%`) DO @set BOARD_VERSION=%%i
          
          set DSP_OUT=dsp_ver%BOARD_VERSION%
          
          echo "DSP binary copy to %DSP_OUT%"
          
          mkdir %DSP_OUT%"
          
          copy %SPRESENSE_DIR%\%BOARD_VERSION%\%AUDIO_DSP_DIR%\mp3_dec_installer\MP3DEC %DSP_OUT%\
          copy %SPRESENSE_DIR%\%BOARD_VERSION%\%AUDIO_DSP_DIR%\mp3_enc_installer\MP3ENC %DSP_OUT%\
          copy %SPRESENSE_DIR%\%BOARD_VERSION%\%AUDIO_DSP_DIR%\src_installer\SRC %DSP_OUT%\
          copy %SPRESENSE_DIR%\%BOARD_VERSION%\%AUDIO_DSP_DIR%\wav_dec_installer\WAVDEC %DSP_OUT%\
        • pickup_dsp.bat をダブルクリックで実行するとDSPファイルが dsp_ver1.x.x にコピーされます。

      • Ubuntu/Macintoshの場合

        • 次のテキストをコピーして pickup_dsp.sh としてファイルを作成します。

          #! /bin/bash
          
          HOST=`uname`
          if [ "${HOST}" == "Linux" ]; then
                  ARDUINO_ROOT=~/.arduino15
          elif [ "${HOST}" == "Darwin" ]; then
                  ARDUINO_ROOT=~/Library/Arduino15
          else
                  echo "ERROR: Cannot detect your machine."
                  exit
          fi
          
          SPRESENSE_ROOT=${ARDUINO_ROOT}/packages/SPRESENSE/hardware/spresense
          AUDIO_DSP_PATH=libraries/Audio/examples/dsp_installer
          
          BOARD_VERSION=`ls ${SPRESENSE_ROOT}`
          
          DSP_OUT=dsp_ver${BOARD_VERSION}
          
          echo "DSP binary copy to `pwd`/${DSP_OUT}"
          
          mkdir -p ${DSP_OUT}
          cp -a ${SPRESENSE_ROOT}/${BOARD_VERSION}/${AUDIO_DSP_PATH}/mp3_dec_installer/MP3DEC ${DSP_OUT}/
          cp -a ${SPRESENSE_ROOT}/${BOARD_VERSION}/${AUDIO_DSP_PATH}/mp3_enc_installer/MP3ENC ${DSP_OUT}/
          cp -a ${SPRESENSE_ROOT}/${BOARD_VERSION}/${AUDIO_DSP_PATH}/src_installer/SRC ${DSP_OUT}/
          cp -a ${SPRESENSE_ROOT}/${BOARD_VERSION}/${AUDIO_DSP_PATH}/wav_dec_installer/WAVDEC ${DSP_OUT}/
        • pickup_dsp.sh を下記コマンドで実行するとDSPファイルが dsp_ver1.x.x にコピーされます。

          $ bash pickup_dsp.sh
    2. SD カードに BIN ディレクトリを作成し、そこに取り出したファイルをコピーしてください。

      arduino dsp copy ja
      図 1. DSPファイルのコピー

      オーディオの再生・録音のアプリケーションプログラムにおいて、DSP ファイルがインストールされた場所を initPlayer() 関数、または initRecorder() 関数の引数で指定する必要があります。SD カードへインストールした場合は、/mnt/sd0/BIN を指定してください。Example スケッチでは、/mnt/sd0/BIN が指定されています。

  • DSPインストーラー用いてインストールする場合

    DSP インストーラーは、Arduino IDE 上から ファイル → スケッチ例 → Spresense用のスケッチ例 Audio → dsp_installer 以下にあります。DSP バイナリごとにインストーラーが分かれているので、上の表に従って、DSP インストーラーを選んで起動してください。

    arduino dsp installer ja
    図 2. DSPインストーラーの起動

    コンパイル&書き込み(Upload)の実行が終わったら、シリアルモニタを起動してください。

    1. ボーレート 115200 bps を選択すると、下図に示すメッセージが表示されます。

    2. インストール先の番号を入力してください。 SD カードへインストールする場合は、Spresense 拡張ボード上の SD カードスロットへ FAT フォーマット済みの SD カードを挿入してください。

    3. 送信ボタンを押してください。

      arduino dsp installer monitor1 ja
      図 3. DSPインストール先の選択

      インストールが成功すれば下図に示すメッセージ表示されます。

      arduino dsp installer monitor2 ja
      図 4. DSPインストール実行

    オーディオの再生・録音のアプリケーションプログラムにおいて、DSP ファイルがインストールされた場所を initPlayer() 関数、または initRecorder() 関数の引数で指定する必要があります。SD カードへインストールした場合は、 /mnt/sd0/BIN を指定し、フラッシュへインストールした場合は、 /mnt/spif/BIN を指定してください。Example スケッチでは、SD カード /mnt/sd0/BIN が使用されています。

3.1.4. 詳細情報

さらなる情報については、以下のリンクを参照してください。

3.2. Camera ライブラリ

ここでは、Spresense のArduino IDE で利用可能なCameraライブラリについて説明します。

3.2.1. 概要

下記にCamera ライブラリの概略図を示します。

arduino camera overview
図 5. Camera Overview

Spresense Cameraには、2つのライブラリクラスが用意されています。 1つは、CameraClassのインスタンスである"theCamera"で、もう一つがCameraから取得した画像を操作するCamImageクラスです。

"theCamera"には大きく3つの機能が備わっています。

  • CameraのPreviewを取得するVideoStream機能

  • Cameraのパラメータを制御する機能

  • Cameraで高解像度なJPEG画像を写真として取得する機能

CamImageクラスは、theCameraから取得した画像イメージをユーザが操作するための関数です。 CamImageクラスの概要を以下の図に示します。

arduino camera camimage
図 6. CamImage Overview

CamImageクラスには、2つの機能が備わっています。

  • Cameraで撮影された画像の情報を取得する。

  • 取得した画像を変換する。

以下に、theCameraおよびCamImageが持つ、これら5つの機能について説明します。

3.2.2. CameraのPreviewを取得するVideoStream機能

通常カメラのファインダーには、Cameraに映るリアルタイムの画像が映っています。 ここでは、このリアルタイム画像(リアルタイム動画)をPreview画像と呼びます。 "theCamera"には、このPreview画像を毎フレーム取得する機能が備わっています。

Preview画像を取得するには、まず、begin()メソッド関数を用いて、Preview画像の画像フォーマットを決定します。 begin()メソッド関数の定義は以下のようになっています。

begin(
    int buff_num=1,
    CAM_VIDEO_FPS fps = CAM_VIDEO_FPS_30,
    int video_width   = CAM_IMGSIZE_QVGA_H,
    int video_height  = CAM_IMGSIZE_QVGA_V,
    CAM_IMAGE_PIX_FMT fmt=CAM_IMAGE_PIX_FMT_YUV422)

begin()に与えるパラメータはすべてPreview画像のパラメータを決定するものです。 それぞれ、theCamera内部で持つPreview用画像バッファの数とVideoのフレームレート(1秒間に何コマの画像を取得するか)、 画像の縦横サイズと画像データのピクセルフォーマットになります。 デフォルトではそれぞれ、内部画像バッファ数が1枚、フレームレートが30FPS(1秒間に30枚)、画像サイズがQVGA(320 x 240)、ピクセルフォーマットがYUV422となっています。 内部画像バッファの数は通常使用であればデフォルトの値をご使用ください。

内部画像バッファの数を増やす際の例としては、 取得した画像を色々と加工するなどの重たい処理をさせたい場合に、画像処理とCameraからの画像取得を並列化したい、という場合が考えられます。 そのような場合、内部画像バッファ数を2にすることで、その重たい処理をさせながら、その裏でCameraからの画像取得を平行して行うということが可能となり、結果的にフレームレートが改善する場合もあります。 ただし、QVGAでバッファのメモリを約150KB消費しますので、枚数を多く設定する場合はご注意ください。

現在、画像サイズはQVGAのみサポートしています。 QVGA以外の値を設定するとbegin()でエラーが発生します。 また、 Preview画像のピクセルフォーマットはYUV422のみサポートしています。

begin()メソッド関数は、theCameraを利用する際に最初に呼び出す必要のある関数です。 begin()メソッド関数が正常に終了したらstartStreaming()メソッド関数を使ってPreview画像を取得するためのコールバック関数を登録します。 コールバック関数の型は以下のようになります。

void camera_callback(CamImage img)

ユーザはこの型の関数を独自に実装して、startStreaming()メソッド関数を用いて登録します。 startStreaming()の第一引数に"true"を指定すると、Preview用のVideo画像の取得が開始され、画像が取得されるたびに登録されたコールバック関数が呼び出されます。 画像を取得する頻度は、begin()メソッド関数で指定した、フレームレートによって決定します。 ただし、ユーザが実装したコールバック関数が終了しない限り、次のフレームのコールバック関数が呼び出されることはありません。 Preview画像の取得を停止したい場合は、startStreaming()メソッド関数の第一引数をfalseにしてstartStreaming()メソッド関数を呼び出してください。

3.2.3. Cameraのパラメータを制御する機能

通常のCameraには、色味の調整や明るさなど、様々な設定が出来るようになっており、Spresense Cameraにも、いくつかの設定が出来るようになっています。

表 2. Camera Parameter Control method functions
Method name Description

setAutoWhiteBalance()

Cameraの自動ホワイトバランスの開始停止

setAutoISOSensitive()

Cameraの自動ISO感度の開始停止

setISOSensitivity()

マニュアルISO感度設定でのISO感度設定

setAutoWhiteBalanceMode()

自動ホワイトハウス時のモード設定

setColorEffect()

画像効果設定

これらの設定メソッド関数はbegin()メソッド関数をエラー無く呼び出した後であれば、任意のタイミングで呼び出すことが可能です。

3.2.4. Cameraで高解像度なJPEG画像を写真として取得する機能

Preview画像は低解像度な半面、動画としてフレームレートの頻度で画像を取得することが出来ます。 一方、写真としてデータを取得する場合、Spresense Cameraでは、高解像度なJPEG圧縮された画像を取得することが出来ます。

まず、theCameraに対して「フィルムをセットする」という処理を行います。 この処理を行うメソッド関数が、setStillPictureImageFormat()になります。 このメソッド関数を用いて、静止画(写真)用の画サイズやピクセルフォーマットを設定します。

setStillPictureImageFormat(int width, int height, CAM_IMAGE_PIX_FMT fmt = CAM_IMAGE_PIX_FMT_JPEG)

第一、第二引数で画像の縦横サイズを指定します。第三引数で画像のピクセルフォーマットを指定します。

現在、画像のピクセルフォーマットはJPEGのみサポートしています。

setStillPictureImageFormat()メソッド関数は、1度設定を行えば、パラメータの変更をしない限り、永続的に設定が有効になります。

画像の設定が終わったら、任意のタイミングで「シャッターを切る」という処理を行い、写真データを取得します。 そのためのメソッド関数がtakePicture()になります。 takePicture()は戻り値としてCamImageのインスタンスを返します。 写真撮影で何らかのエラーが発生した場合、空のCamImageを返します。 CamImageのインスタンスが空かどうかを判断するには、CamImageクラスのisAvailable()で確認することが出来ます。

3.2.5. Cameraで撮影された画像の情報を取得する。

startStreaming()でのコールバック及びtakePicture()の戻り値で得られるCamImageインスタンスは、取得した画像の情報が入っています。 CamImageクラスのメソッド関数を用いて、画像の情報を取得することが出来ます。

表 3. Methods to get Informations from CamImage
Method name Description

isAvailable()

取得したCamImageインスタンスが利用可能なものかどうかを確認する

getWidth()

画像の幅をピクセル単位で取得

getHeight()

画像の高さをピクセル単位で取得

getPixFormat()

画像のピクセルフォーマットを取得

getImgSize()

画像のデータのサイズをバイト単位で取得

getImgBuff()

画像データのバッファアドレスを取得

3.2.6. 取得した画像を変換する。

CamImageインスタンスには1つの画像変換メソッド関数が用意されています。

表 4. Methods to convert CamImage
Method name Description

convertPixFormat()

現状のピクセルフォーマットから別のピクセルフォーマットに画像を変換する

画像をディスプレイに出したいような場合、ディスプレイのピクセルフォーマットは通常、RGBフォーマットが用いられます。 特にPreview画像を取得した場合、取得した画像をディスプレイ表示したいケースは多いと思います。 このようなケースで、ピクセルフォーマットの変換を行う際などに、このメソッド関数を用いることが出来ます。

convertPixFormat()は自身データメモリ上でピクセルフォーマットが変換されるため、 現在のCamImageインスタンスが上書きされます。

現時点では以下の制約があります。

  • convertPixformat()は、YUV422からRGB、YUV422からGLAY、の2つのみ対応しています

3.2.7. サンプルコードによる解説

ここでは、実際に、Spresense Arduino Packageに含まれるCameraのサンプルコードを用いて、 Spresense Cameraの使い方を解説します。

サンプルコードは、Arduino IDEのメニューバーから開くことが出来ます。

「ファイル」⇒「スケッチ例」⇒「Spresenseのスケッチ例の中のCamera」⇒「camera」

/*
 *  camera.ino - One minute interval time-lapse Camera
 *  Copyright 2018 Sony Semiconductor Solutions Corporation
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  This is a test app for the camera library.
 *  This library can only be used on the Spresense with the FCBGA chip package.
 */

#include <SDHCI.h>
#include <stdio.h>  /* for sprintf */

#include <Camera.h>

#define BAUDRATE                (115200)

SDClass  theSD;
int take_picture_count = 0;


/**
 * Callback from Camera library when video frame is captured.
 */

void CamCB(CamImage img)
{

  /* Check the img instance is available or not. */

  if (img.isAvailable())
    {

      /* If you want RGB565 data, convert image data format to RGB565 */

      img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);

      /* You can use image data directly by using getImgSize() and getImgBuff().
       * for displaying image to a display, etc. */

      Serial.print("Image data size = ");
      Serial.print(img.getImgSize(), DEC);
      Serial.print(" , ");

      Serial.print("buff addr = ");
      Serial.print((unsigned long)img.getImgBuff(), HEX);
      Serial.println("");
    }
  else
    {
      Serial.print("Failed to get video stream image\n");
    }
}

/**
 * @brief Initialize camera
 */
void setup()
{

  /* Open serial communications and wait for port to open */

  Serial.begin(BAUDRATE);
  while (!Serial)
    {
      ; /* wait for serial port to connect. Needed for native USB port only */
    }


  /* begin() without parameters means that
   * number of buffers = 1, 30FPS, QVGA, YUV 4:2:2 format */

  Serial.println("Prepare camera");
  theCamera.begin();


  /* Start video stream.
   * If received video stream data from camera device,
   *  camera library call CamCB.
   */

  Serial.println("Start streaming");
  theCamera.startStreaming(true, CamCB);

  /* Auto white balance configuration */

  Serial.println("Set Auto white balance parameter");
  theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);

  /* Set parameters about still picture.
   * In the following case, QUADVGA and JPEG.
   */

  Serial.println("Start streaming");
  theCamera.setStillPictureImageFormat(
     CAM_IMGSIZE_QUADVGA_H,
     CAM_IMGSIZE_QUADVGA_V,
     CAM_IMAGE_PIX_FMT_JPG);
}

/**
 * @brief Take picture with format JPEG per second
 */

void loop()
{
  sleep(1); /* wait for one second to take still picture. */

  /* You can change the format of still picture at here also, if you want. */

  /* theCamera.setStillPictureImageFormat(
   *   CAM_IMGSIZE_HD_H,
   *   CAM_IMGSIZE_HD_V,
   *   CAM_IMAGE_PIX_FMT_JPG);
   */

  /* This sample code can take 100 pictures in every one second from starting. */

  if (take_picture_count < 100)
    {

      /* Take still picture.
      * Unlike video stream(startStreaming) , this API wait to receive image data
      *  from camera device.
      */

      Serial.println("call takePicture()");
      CamImage img = theCamera.takePicture();

      /* Check availability of the img instance. */
      /* If any error was occured, the img is not available. */

      if (img.isAvailable())
        {
          /* Create file name */

          char filename[16] = {0};
          sprintf(filename, "PICT%03d.JPG", take_picture_count);

          Serial.print("Save taken picture as ");
          Serial.print(filename);
          Serial.println("");

          /* Save to SD card as the finename */

          File myFile = theSD.open(filename, FILE_WRITE);
          myFile.write(img.getImgBuff(), img.getImgSize());
          myFile.close();
        }

      take_picture_count++;
    }
}

このサンプルは、Preview画像をQVGA、フレームレートを60FPSに設定し、60コマのデータを取得すると1枚JPEG写真を撮り、SDCardに保存する、 という動作をします。

ステップとしては、「初期設定」、「setup()」、「Previewコールバック」そして「loop()」の4つで動作しています。

それでは、これら4つについて詳しく見ていきましょう。

初期設定
/*
 *  camera.ino - One minute interval time-lapse Camera
 *  Copyright 2018 Sony Semiconductor Solutions Corporation
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  This is a test app for the camera library.
 *  This library can only be used on the Spresense with the FCBGA chip package.
 */

#include <SDHCI.h>
#include <stdio.h>  /* for sprintf */

#include <Camera.h>

#define BAUDRATE                (115200)

SDClass  theSD;
int take_picture_count = 0;

まず、Camera ライブラリを利用する場合、ヘッダファイル <Camera.h> をインクルードする必要があります。

#include <Camera.h>

このヘッダファイルをインクルードすることで、thCameraインスタンスを利用することが出来るようになります。

その後、コールバック関数とloop()関数で共通で使う変数を定義しています。

int take_picture_count = 0;

take_picture_countは、1秒おきにtakePicture()を呼ばれる度にカウントアップしていく変数で、この変数を用いて、 SDCardに書き出されるファイル名と作成するファイル数の上限を制御しています。 (このサンプルでは100枚の写真を撮ると写真撮影を終了するようになっています。)

Previewコールバック
/**
 * Callback from Camera library when video frame is captured.
 */

void CamCB(CamImage img)
{

  /* Check the img instance is available or not. */

  if (img.isAvailable())
    {

      /* If you want RGB565 data, convert image data format to RGB565 */

      img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);

      /* You can use image data directly by using getImgSize() and getImgBuff().
       * for displaying image to a display, etc. */

      Serial.print("Image data size = ");
      Serial.print(img.getImgSize(), DEC);
      Serial.print(" , ");

      Serial.print("buff addr = ");
      Serial.print((unsigned long)img.getImgBuff(), HEX);
      Serial.println("");
    }
  else
    {
      Serial.print("Failed to get video stream image\n");
    }
}

startStreaming()で登録される、カメラのPreviewが出力された際に呼び出される関数になります。 この関数内では、関数の引数として取得したCamImageのインスタンスが利用可能なものかどうかのチェックを行い、 その後、ピクセルフォーマットをRGB565に変換しています。 変換後、getImgSize()とgetImgBuff()で取得したデータサイズとメモリアドレスを表示しています。 一般的には、この段階で接続したディスプレイなどにイメージデータを出力して、 カメラのファインダービューを構築します。

setup()
/**
 * @brief Initialize camera
 */
void setup()
{

  /* Open serial communications and wait for port to open */

  Serial.begin(BAUDRATE);
  while (!Serial)
    {
      ; /* wait for serial port to connect. Needed for native USB port only */
    }


  /* begin() without parameters means that
   * number of buffers = 1, 30FPS, QVGA, YUV 4:2:2 format */

  Serial.println("Prepare camera");
  theCamera.begin();


  /* Start video stream.
   * If received video stream data from camera device,
   *  camera library call CamCB.
   */

  Serial.println("Start streaming");
  theCamera.startStreaming(true, CamCB);

  /* Auto white balance configuration */

  Serial.println("Set Auto white balance parameter");
  theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);

  /* Set parameters about still picture.
   * In the following case, QUADVGA and JPEG.
   */

  Serial.println("Start streaming");
  theCamera.setStillPictureImageFormat(
     CAM_IMGSIZE_QUADVGA_H,
     CAM_IMGSIZE_QUADVGA_V,
     CAM_IMAGE_PIX_FMT_JPG);
}

setup()では、初めにメッセージ表示用にSerialのセットアップを行い、続いてCameraのbegin()メソッド関数を呼び出しています。 Cameraのbegin()はデフォルトではフレームバッファメモリは1枚、フレームレートが30FPS、画サイズはQVGAになっています。 その後、startStreaming()でPreview用コールバック関数の設定とコールバックを有効にし、setAutoWhiteBalanceMode()で日中設定にしています。 最後に、setStillPictureImageFormat()で、QUAD VGAサイズの写真用の設定を行っています。

loop()
/**
 * @brief Take picture with format JPEG per second
 */

void loop()
{
  sleep(1); /* wait for one second to take still picture. */

  /* You can change the format of still picture at here also, if you want. */

  /* theCamera.setStillPictureImageFormat(
   *   CAM_IMGSIZE_HD_H,
   *   CAM_IMGSIZE_HD_V,
   *   CAM_IMAGE_PIX_FMT_JPG);
   */

  /* This sample code can take 100 pictures in every one second from starting. */

  if (take_picture_count < 100)
    {

      /* Take still picture.
      * Unlike video stream(startStreaming) , this API wait to receive image data
      *  from camera device.
      */

      Serial.println("call takePicture()");
      CamImage img = theCamera.takePicture();

      /* Check availability of the img instance. */
      /* If any error was occured, the img is not available. */

      if (img.isAvailable())
        {
          /* Create file name */

          char filename[16] = {0};
          sprintf(filename, "PICT%03d.JPG", take_picture_count);

          Serial.print("Save taken picture as ");
          Serial.print(filename);
          Serial.println("");

          /* Save to SD card as the finename */

          File myFile = theSD.open(filename, FILE_WRITE);
          myFile.write(img.getImgBuff(), img.getImgSize());
          myFile.close();
        }

      take_picture_count++;
    }
}

loop()関数では、まず、1秒ほどsleep()関数で待ちます。 1秒後、take_picture_count変数の値が100を超えていないかチェックし、超えていなければ写真撮影処理に入ります。 撮影する処理では、 takePicture()メソッド関数をコールし、写真撮影を行って、取得した写真をimg変数に代入します。 img変数が利用可能であることをisAvailable()関数で確認し、取得した画像をSDカードに保存します。 最後に、take_picture_countをインクリメント(1増やす)して、loop()関数を終了しています。

以上でサンプルを使った説明は終わりになります。

さあ、Spresense Cameraを使ってオリジナルカメラデバイスを作ってみましょう。

3.3. DNNRTライブラリ

DNN Runtimeライブラリは、Sonyが提供するNeural Network LibrariesまたはNeural Network Consoleで学習したモデルを使用して、Deep Neural Network (DNN) を用いた認識処理を行うことができます。

dnnrt overview ja

DNNRTライブラリには、コアとなる DNNRT と、データの入出力に使用する DNNVariable があります。

ここでは、0~9までの手書き文字を認識するためのサンプル(number_recognition.ino)を例に解説していきます。

3.3.1. 学習済みモデルの準備

Neural Network Console

学習済みモデルを作成するために、Neural Network Console (NNC)を使用します。こちらの、公式サイト からクラウド版の使用、またはWindows版インストーラがダウンロードできます。

学習
  1. クラウド版では、サンプルプロジェクトの image_recognition.MNIST.LeNet をベースに新しいプロジェクトを作成します。サンプルのプロジェクトを選択すると選択されたプロジェクトを元に新しいプロジェクトを作成します。新しいプロジェクトの名前を入力するダイアログボックスが表示されるので、好きな名前を入力してください。(ここでは、myproject とします)

    作成された myproject を選択すると編集画面が表示されます。

    edit
    図 7. 編集画面(クラウド版)

    Windows版では、LeNet.sdcproj を選択して使用します。

  2. ここでは、サンプルのネットワークモデルをそのまま使用して学習を行います。

    クラウド版では、編集画面の右上にある Run ボタンを押します。

    start
    図 8. 学習開始(クラウド版)

    Windows版では、Training の下にある三角ボタンを押します。

    start
    図 9. 学習開始(Windows版)
  3. ウィンドウ下部のコンソールに Training Completed が表示されれば学習は完了です。

    TRAINING
機械学習は非常に時間がかかります。
  1. 学習が完了したら学習結果を評価します。

    クラウド版では、学習画面の右上にある Run ボタンを押します。

    EVALUATE
    図 10. 評価開始(クラウド版)

    Windows版では、Evaluation の下にある三角ボタンを押します。

    EVALUATE
    図 11. 評価開始(Windows版)
  2. 評価が完了すると評価結果が表示されます。 x:image の列に表示されている画像と y:label の列に表示されている数字が一致しているはずです。DNNRTで使用するためにこの学習済みモデルをダウンロードします。

    クラウド版では、評価画面右上のドロップダウンリストから NNB (NNabla C Runtime file format) を選択し、下の Download Project を押します。

    DOWNLOAD

    Windows版では、ACTION メニューから、ExportNNB (NNabla C Runtime file format) を選択します。

    DOWNLOAD
  3. ダウンロードした学習済みモデル result.nnb (クラウド版)または model.nnb (Windows版)と認識させたい画像をSDカードの直下にコピーします。学習済みモデルは、network.nnb というファイル名に変更してください。このサンプルで対応している画像フォーマットはPGM (Portable Greyscale Map) のみです。PGMファイルを作れない場合は、こちらのサンプルPGM画像ファイルを使用してください。

以上で number_recognition.ino サンプルを動作させる準備は完了です。

3.3.2. 手書き文字認識サンプル

image_recognition.MNIST.LeNet および LeNet.sdcproj で作成された学習モデルは、28x28サイズの画像を1つ入力にとり、10個の配列を出力します。この10個の配列はインデックスが認識した数字を意味しており、配列の中にそれぞれの数字である確率が出力されます。例えば、配列の先頭(インデックス0)には、入力された画像が数字の「0」である確率が出力されます。

各数字の確率を表示する場合の例
DNNVariable output = dnnrt.outputVariable(0);

Serial.println(output[0]);   // 入力画像が「0」である確率
 ...
Serial.println(output[9]);   // 入力画像が「9」である確率

number_recognition.ino では、出力された確率の配列の中から一番大きい確率のインデックスを認識した数字として、その確率とともにシリアルに出力します。

入力させたい画像は、number_recognition.ino の以下の行で変更できます。

  File pgmfile("number4.pgm");

3.4. EEPROM ライブラリ

EEPROM は、電源を切っても内容が消去されない不揮発なデータを保持することができます。 Spresense では EEPROM が搭載されていないので、SPI-Flash メモリを用いて EEPROM をエミュレートしています。 このライブラリは、SPI-Flash によってエミュレートされた EEPROM に対して、書き込みと読み込みを可能にします。

EEPROM ライブラリの API 仕様については、Arduino EEPROM ライブラリ を参照してください。

EEPROM のサンプルコードは、Arduino IDE のメニューから ファイル → スケッチ例 → Spresense用のスケッチ例 EEPROM 以下に用意されています。 EEPROM ライブラリは、Arduino EEPROM ライブラリと互換性をもち Arduino 用のサンプルコードをそのまま動かすことができます。

EEPROM サイズは、EEPROM.h に定義されている E2END の値によって決められ、4000 バイトです。

Spresense ボードにおいて、アプリケーションからアクセスできる SPI-Flash の最大容量は 4MByte です。 この最大容量を超えない範囲で、E2END を変更することによって EEPROM のサイズをさらに増やすことも可能です。

3.5. eMMC ライブラリ

3.5.1. 概要

eMMC ライブラリは eMMC Add-on ボード (今後発売予定) の eMMC デバイスにアクセスするためのライブラリです。

eMMC ライブラリは、Arduino SD ライブラリ に類似した API 構成となっており、オブジェクト名を SD から eMMC へ置き換えることで、SD ライブラリと同じインターフェースを用いて eMMC デバイスへアクセスすることができます。

また、追加機能として、USB MSC (Mass Storage Class) 機能をサポートしています。 Spresense 拡張ボードにある USB と PC を接続し、beginUsbMsc() を呼び出すことで、PC から eMMC デバイス上のファイルに直接アクセスすることができます。

3.5.2. 機能

各種APIの詳細は、APIリファレンスマニュアル eMMC Library API を参照してください。

Function Description

eMMC.begin()

eMMC デバイスを初期化します。本 API を呼び出すことで eMMC デバイスが使用可能になります。

eMMC.beginUsbMsc()

USB MSC (Mass Storage Class) 機能を開始します。

eMMC.endUsbMsc()

USB MSC (Mass Storage Class) 機能を終了します。

eMMC.format()

eMMC デバイスをフォーマットします。デフォルト FAT32 ファイルシステムでフォーマットします。

eMMC.open()

ファイル名を指定して eMMC デバイス内のファイルをオープンします。
FILE_READ: 読み取り専用でファイルをオープンします (デフォルト)
FILE_WRITE: 読み書き可能でファイルをオープンします。ファイル位置は末尾を指します。
この関数は File オブジェクトを返します。ファイル操作については File ライブラリ を参照してください。

eMMC.exists()

eMMC デバイス内にファイルが存在するかどうかを確認します。

eMMC.mkdir()

eMMC デバイス内にディレクトリを作成します。

eMMC.rmdir()

eMMC デバイス内にディレクトリを削除します。

eMMC.remove()

eMMC デバイス内のファイルを削除します。

3.5.3. サンプル

eMMC ライブラリには、4 つのスケッチのサンプルが提供されています。

Example Description

format.ino

eMMC デバイスをフォーマットします。eMMC デバイスを初めて利用する際に一度だけ実行してください。

read_write.ino

eMMC デバイス上のファイルを読み書きするサンプルです。

UsbMsc.ino

USB MSC 機能のサンプルです。eMMC デバイスが PC 上のドライブとしてマウントされ、PC から eMMC デバイスに直接アクセスすることができます。

UsbMscAndFileOperation.ino

USB MSC 機能とファイル操作を組み合わせた複合アプリケーションです。eMMC デバイス内のファイルに対して、スケッチからのファイル操作と、USB MSC による PC からのファイル操作は、排他的に動作させる必要があります。このサンプルでは、アプリケーションプログラムからファイル一覧を取得・表示した後に、USB MSC 機能を有効にし、PC から eMMC デバイス内のファイルを操作できるようになります。USB MSC 機能を終了した後に、再びプログラム中からファイル一覧を取得・表示します。

3.6. File ライブラリ

3.6.1. 概要

File ライブラリは各種ストレージから共通に利用されるライブラリです。 File オブジェクトは、SDHCI, Flash, eMMC ライブラリから open() 関数によって生成されます。 本ライブラリは、オープンされた File オブジェクトに対してファイル操作を行う機能を提供します。

3.6.2. 機能

各種APIの詳細は、APIリファレンスマニュアル File Library API を参照してください。

File インスタンス名が myFile のとき、次のようにファイルをオープンします。

#include <SDHCI.h>
SDClass SD;
File myFile;

  myFile = SD.open("test.txt");

File オブジェクトに対して、次に示すような関数が提供されています。

Function Description

myFile.write()

ファイル位置からファイルにデータを書き込みます。

myFile.read()

ファイル位置からファイルのデータを読み出します。

myFile.peek()

ファイルから読み取り位置を進めずに 1 バイト読み出します。

myFile.available()

ファイルから読み出し可能なバイトがあるかを確認します。

myFile.flush()

ファイルに書き込んだデータがストレージに書き込まれることを保証します。

myFile.seek()

ファイル内のファイル位置を先頭から指定した位置に移動します。

myFile.position()

ファイル内の現在位置を取得します。

myFile.size()

ファイルのサイズを取得します。

myFile.close()

ファイルをクローズします。

myFile.bool()

ファイルやディレクトリが存在するかどうかを返します。

myFile.name()

ファイル名を取得します。

myFile.isDirectory()

ファイルがディレクトリなのかどうかを返します。

myFile.openNextFile()

ディレクトリ内の次のファイルをオープンします。

myFile.rewindDirectory()

ディレクトリ内の最初のファイルに戻します。

3.6.3. サンプル

File ライブラリには、以下のサンプルが提供されています。

Example Description

read_write.ino

ファイルを読み書きするサンプルです。

3.7. Flash ライブラリ

3.7.1. 概要

Flash ライブラリは Spresense メインボード上の Flash デバイスにアクセスするためのライブラリです。

Flash ライブラリは、Arduino SD ライブラリ に類似した API 構成となっており、オブジェクト名を SD から Flash へ置き換えることで、SD ライブラリと同じインターフェースを用いて Flash デバイスへアクセスすることができます。

3.7.2. 機能

各種APIの詳細は、APIリファレンスマニュアル Flash Library API を参照してください。

Function Description

Flash.begin()

ダミー関数です。常に true を返します。

Flash.format()

Flash デバイスをフォーマットします。

Flash.open()

ファイル名を指定して Flash デバイス内のファイルをオープンします。
FILE_READ: 読み取り専用でファイルをオープンします (デフォルト)
FILE_WRITE: 読み書き可能でファイルをオープンします。ファイル位置は末尾を指します。
この関数は File オブジェクトを返します。ファイル操作については File ライブラリ を参照してください。

Flash.exists()

Flash デバイス内にファイルが存在するかどうかを確認します。

Flash.mkdir()

Flash デバイス内にディレクトリを作成します。

Flash.rmdir()

Flash デバイス内にディレクトリを削除します。

Flash.remove()

Flash デバイス内のファイルを削除します。

3.7.3. サンプル

Flash ライブラリには、2 つのスケッチのサンプルが提供されています。

Example Description

format.ino

Flash デバイスをフォーマットします。Flash デバイスはフォーマット済みの状態で出荷されていますが、Flash 内のデータを削除したい等の目的で再フォーマットが必要な際に実行してください。フォーマットを実行すると、ブートローダやスケッチからロードしたプログラムを除くすべてのユーザー領域が削除されます。Flash に存在する EEPROM データも削除されます。
このスケッチはシリアルモニタを使用します。通信レート 115200 baud でシリアルモニタを開いてください。
シリアルモニタから y を入力することにより、フォーマットを開始します。
フォーマット中は 4 つの LED が点灯し、フォーマット完了後に LED は点滅します。
フォーマットには約 40 秒ほどの時間がかかります。フォーマット中は電源を切らないように注意してください。

read_write.ino

Flash デバイス上のファイルを読み書きするサンプルです。

3.8. GNSS ライブラリ

GNSS ライブラリは、Spresense の GNSS測位機能をコントロールし、位置情報を取得するためのライブラリです。Arduino のスケッチから簡単に使うことができます。

使用するにあたって、特別なハードウェアの設定は必要ありません。アンテナも Spresense メインボード上にマウントされていますので、見晴らしのよい屋外に出れば簡単に位置情報を得ることができます。ただし、起動時に衛星を捕捉するのに1〜2分かかりますので、アプリケーション設計時には留意してください。

本ライブラリを使用するにあたって、Spresense拡張ボードは必要ありません。メインボード単体で動作させることができます。

GNSS ライブラリには、2つのサンプルスケッチが提供されています。

  • gnss.ino は、GNSSで測位された情報を USBシリアルポートから出力する簡単なサンプルです。このサンプルでは位置情報を GNSS ライブラリ特有のフォーマットで出力されます。詳細については GNSS.h を参照してください。

  • gnss_tracker.ino は、少し複雑なサンプルです。このサンプルは、SDカードに位置情報を保存するので、Spresense拡張ボードが必要です。SDカードには、位置情報で一般的に使われている NMEA フォーマットで保存されますので、様々なアプリケーションから利用できます。

3.8.1. 詳細情報

さらに詳細の情報については、 Spresense SDK GNSS documentation を参照してください。

3.9. LowPower ライブラリ

LowPowerライブラリは、Spresenseがもつ省電力機能をサポートしています。

LowPowerライブラリは、主に以下の機能を提供しています。

  • Deep SleepCold Sleep など各種スリープ状態への遷移

    Deep Sleep

    最も消費電力が低いスリープモードです。CXD5247 PMIC (Power Management IC) のみ電源が入っており、CXD5602 は電源が OFF されます。

    Cold Sleep

    CXD5602 内で必要最小限の電源ドメインのみ ON されているスリープモードです。Deep Sleep に比べると消費電力は高くなりますが、GPIO の変化を起動要因のトリガとして、Cold Sleep 状態から起床することができます。

Sleep 中の消費電力に関して、拡張ボードに SD カードが挿入されていると SD カードの電源消費分により 約 5 mA ほど消費電流が増加します。
  • スリープ状態から起床したときの起動要因の取得

  • 起動要因の許可/禁止を設定する起動マスクの設定

  • 3 種類のクロックモードへの動的切り替え

    CLOCK_MODE_156MHz

    パフォーマンスが最も高いクロックモードです。起動時はこのクロックモードが選択されています。CPU は PLL を使用して 156MHz で動作します。

    CLOCK_MODE_32MHz

    システム全体のクロックを 32MHz に落として消費電力を削減します。このクロックモードが選択された場合、CXD5602 の Core 電圧は 0.7V で動作します。CPU は PLL を使用して 32MHz で動作します。

    CLOCK_MODE_8MHz

    システム全体のクロックを 8MHz に落とします。これは最も消費電力の少ないクロックモードです。Core 電圧は 0.7V で動作し、CPU は PLL を使用せずに内蔵発振器で動作します。PLL を使用しない場合、クロックモードをこのモードにして、さらに TCXO の電源を落とすことでさらに消費電力を削減することができます。

一般的に、クロックを下げれば下げるほど消費電力を削減することができますが、それに応じて動作パフォーマンスも低下します。 また、低クロックモードにおいて、すべてのハードウェア機能が動作するわけではありません。詳細については後述します。

各種APIの詳細は、APIリファレンスマニュアル LowPower Library API を参照してください。

3.9.1. クロックモードについて

clockMode() の引数に CLOCK_MODE_156MHz, CLOCK_MODE_32MHz, CLOCK_MODE_8MHz のいずれかを指定することにより アプリケーション CPU のクロック、及び、システム全体のクロックを動的に切り替えます。動作クロックを下げることにより、 消費電力を削減することができます。

参考までに 3 つのモードについてバッテリー端の消費電流を示します。 測定条件は、Spresense メインボードのみを使用し、電源はバッテリーコネクタから 3.7V を供給しています。 ソフトウェアは特に何も動作していないアイドル状態です。

lowpower current
図 12. Battery current measurement with LowPower
Clock Mode Battery current

CLOCK_MODE_156MHz

6.68 mA

CLOCK_MODE_32MHz

3.66 mA

CLOCK_MODE_8MHz

3.20 mA

CLOCK_MODE_8MHz + TCXO=PowerOff

1.16 mA

この測定結果は、メインボード上の電源 LED による電流消費分も含まれています。

ユーザーアプリケーションからのクロックモード制御とは別に、システム内部で自動的にクロックモードを切り替えることがあります。

  • USB MSC (Mass Storage) など USB 通信機能を使用している間、クロックモードは自動的に CLOCK_MODE_156MHz になります

  • GNSS 測位機能を使用している際は、クロックモードは自動的に CLOCK_MODE_156MHz もしくは CLOCK_MODE_32MHz になります

  • SD カードのマウント処理中は、自動的に CLOCK_MODE_156MHz へクロックアップしマウント後に以前の状態に戻ります。

そのため、必ずしもユーザーが指定したクロックモードに変更されるわけではないことに留意してください。 クロックモードが切り替わったかどうかを確認するために、現時点のクロックモードを getClockMode() 関数により取得することができます。

また、低クロックモードですべての機能が動作するわけではありません。制約事項を次に示します。

  • Audio 機能は、CLOCK_MODE_156MHz で動作させてください

  • Camera 機能は、CLOCK_MODE_156MHz もしくは CLOCK_MODE_32MHz で動作させてください

3.9.2. サンプル

LowPower ライブラリの基本的な使い方は、examples にあるサンプルスケッチをご覧ください。 サンプルスケッチは、Arduino IDE メニューの ファイル → スケッチ例 → Spresense 用のスケッチ例 LowPower から開くことができます。

Example Description

ExternalWakeup

GPIO外部ピンの状態変化によって、Cold Sleepから起床します

TimedWakeup

RTCアラームによって、Cold Sleepから起床します

TimedWakeupDeep

RTCアラームによって、Deep Sleepから起床します

Reboot

システムを再起動します

WatchdogReboot

ウォッチドッグタイマーによって、システムを再起動します

ClockChange

クロックモードについて 156MHz/32MHz/8MHz へ順番に切り替えます

3.10. MultiCore MP ライブラリ

3.10.1. 概要

MultiCore MP ライブラリ (以下、MP ライブラリ) は Arduino 環境でマルチコアプログラミングをサポートするためのライブラリです。デフォルトで起動される CPU コアを MainCore、そして MainCore から起動される CPU コアを SubCore と呼びます。SubCore 1 から SubCore 5 まで全部で 5 個の SubCore があります。

MainCore, SubCore 1~5 の選択は、Arduino IDE メニューの Tools → Core (ツール → Core)で選択します。それぞれのコアでプログラミングして、コアごとにコンパイルされたバイナリを Spresense 基板にロードして動かします。MP ライブラリを用いることで各コアのプログラムを協調して動作させることができるようになります。

3.10.2. 機能

MP ライブラリは、主に以下の機能を提供します。

  • SubCore の起動/終了制御

  • コア間通信機能

  • コア間排他制御機能

  • 共有メモリの獲得/解放

  • 排他機能付きログ出力機能

各種APIの詳細は、APIリファレンスマニュアル MP Library API を参照してください。

MPクラス

MP.h を include することで MP という名前のオブジェクトが生成されます。

#include <MP.h>

MP クラスが提供する関数一覧を以下に示します。 一部、MainCoreSubCore で機能が異なる関数や、 SubCore ではサポートされていない関数もあります(*: サポート, -: 非サポート)

Function Description MainCore SubCore

MP.begin()

マルチコアの起動に関する制御を行います。
(MainCore) 引数に指定した番号の SubCore を起動します。
(SubCore) 引数無しで呼び出し、MainCore へ起動完了を通知します。
詳細はSubCore 起動方法 を参照してください。

*

*

MP.end()

マルチコアの停止に関する制御を行います。
(MainCore) 引数に指定した番号の SubCore を停止します。
(SubCore) 特に何もしません。
詳細は、SubCore 終了方法 を参照してください。

*

*

MP.Send()

指定したコアへデータを送信します。
(MainCore) 引数に指定した番号の SubCore へデータを送信します。
(SubCore) 引数に指定した番号の SubCore へデータを送信します。番号を省略したときは MainCore へ送信します。
詳細は、コア間通信方法 を参照してください。

*

*

MP.Recv()

指定したコアからデータを受信します。
(MainCore) 引数に指定した番号の SubCore からデータを受信します。
(SubCore) 引数に指定した番号の SubCore からデータを受信します。番号を省略したときは MainCore から受信します。
詳細は、コア間通信方法 を参照してください。

*

*

MP.RecvTimeout()

Recv() 受信時のモードやタイムアウト値を設定します。
3 種類の待ちモードがあり、引数によって選択します。
詳細は、コア間通信方法 を参照してください。

*

*

MP.GetRecvTimeout()

RecvTimeout() で設定した値を取得します。

*

*

MP.Virt2Phys()

引数で指定された仮想アドレスを物理アドレスに変換します。物理アドレスマップはすべてのコアで共通です。一方、仮想アドレスは各コアごとに異なります。SubCore は仮想アドレス上で動作するため、異なるコアにアドレスを送信する場合は、この関数を用いて物理アドレスへ変換してください。
詳細は、アプリケーション用メモリ を参照してください。

*

*

MP.GetMemoryInfo()

アプリケーションメモリの空き状況を取得します。
usedMem: 使用メモリサイズ (Byte)
freeMem: 空きメモリサイズ (Byte)
largestFreeMem: 空きメモリの連続最大サイズ (Byte)
詳細は、アプリケーション用メモリ を参照してください。

*

*

MP.EnableConsole()

シリアルモニタ (Serial) からの入力を許可します。
Serial からの入力は、いずれか一つのコアで受け付けるようにしてください。 起動直後は、MainCore のみ許可されています。

*

*

MP.DisableConsole()

シリアルモニタ (Serial) からの入力を禁止します。
Serial 入力を特定の SubCore で受け付けるように変更したい場合は、MainCore から DisableConsole() を呼び出し、SubCore 側で EnableConsole() を呼び出してください。
使い方は、サンプルコードShell を参照してください。

*

*

MP.AllocSharedMemory()

共有メモリを確保し、先頭の物理アドレスを返します。共有メモリの確保と解放は 128 KByte 単位です。引数に指定したサイズから 128 Kbyte アライメントされたメモリを確保します。メモリ不足により確保できなかった場合は、NULL が返ります。
使い方は、サンプルコードSharedMemory を参照してください。

*

-

MP.FreeSharedMemory()

AllocSharedMemory() で確保したアドレスを渡して、共有メモリを解放します。

*

-

MPMutex クラス

マルチコア間で排他制御を行うための機能です。 MP_MUTEX_ID 番号(0~10) を引数に指定して、mutex オブジェクトを生成します。

#include <MPMutex.h>

MPMutex mutex(MP_MUTEX_ID0);

MPMutex が提供する関数を以下に示します。

Function Description MainCore SubCore

mutex.Trylock()

ロックを獲得します。獲得できた場合は 0, 失敗した場合は非 0 の値が返ります。
使い方は、サンプルコードMutex を参照してください。

*

*

mutex.Unlock()

Trylock() で獲得した mutex をアンロックで解放します。

*

*

MPLog() 関数

マルチコア環境でログ出力を行うための関数です。

Function Description MainCore SubCore

MPLog()

コア間で排他制御されたログ出力を行うための関数マクロです。引数は一般的な printf() と同じ書式を使うことができます。
(MainCore) ログの先頭に [Main] が表示されます。
(SubCore) ログの先頭に [Sub番号] が表示されます。
マルチコア環境でコアごとのログ出力を識別することが可能です。
ただし、割り込みハンドラ内から呼び出した場合はログが混在して出力されることがあります。

*

*

アプリケーション用メモリ

アプリケーション用の SRAM メモリは、全部で 1.5 MByte (= 1536 KByte) です。 ハードウェア内部では 128 KByte x 12 個のメモリタイルに分かれて構成されています。 各 CPU と SRAM との間は、メモリタイル単位でバスマトリックス状に接続されています。 あるタイルへアクセスする CPU が一つだった場合は、waitサイクル無しで SRAM を読み書きできます。 (これは CPU アーキテクチャでよく聞かれる Cache と同等のパフォーマンスを意味します)。 一方、同一メモリタイルへ複数の CPU からアクセスが発生した場合、 メモリへのアクセス速度が低下します。

このアクセス競合を防ぐために、基本的に SubCore を動かす際は、 専用のメモリタイルを確保して SubCore プログラムはそのメモリタイル上で動作します。

Arduino 環境における SRAM 1.5 MByte の内訳を次に示します。

diag 64935e6555171d8a58adc590aadf0c3c
図 13. アプリケーションSRAM

MainCore は先頭の 6 タイル (768 KByte) を固定的に使用します。 残りの 6 タイル (768 KByte) を SubCore やその他のライブラリ等で共有して使用します。

上の図では、SubCore1 に 256 KByte, SubCore2 に 128 Kbyte のメモリを割り当てた例です。 SubCore は、割り当てられた物理メモリを 0 番地から始まる仮想アドレスにマップして動作します。 CPU 間通信等で共通のアドレスを参照する必要があれば、MP.Virt2Phys() で物理アドレスへ変換してください。

また、MainCore 使用領域を除く後半 768 KByte の共有メモリは、SubCore 以外にも各種ライブラリから使用されることがあります。 各ライブラリ、及び、そのユースケースごとの使用メモリサイズを以下に示します。

Library UseCase Used Memory Size

Audio, Sensing

初期化時における各種バッファ用

256 KByte

Audio

MP3 再生時における MP3DEC デコーダのロード用

128 KByte

Audio

MP3 録音時における MP3ENC エンコーダのロード用

128 KByte

Audio

WAV 再生時における WAVDEC デコーダのロード用

256 KByte

Audio

WAV 録音時における SRC サンプリングレートコンバータのロード用 (ただしサンプリングレート 48kHz の場合を除く)

256 KByte

DNNRT

初期化時における dnnrt-mp のロード用

128 KByte

SubCore に必要なメモリサイズは、ユーザーアプリケーションに依存します。 スケッチをコンパイルした際に、コンパイル結果表示のウィンドウに以下のようなログが出力されます。この値が、その SubCore を動作させるのに必要なメモリサイズを表します。

arduino multicore boot6 sub1

アプリケーションの組み合わせによっては、メモリ不足で動作させることができないかもしれません。 MP.GetMemoryInfo() を使って、メモリの使用状況/空き状況を確認することができます。

サンプルコードを以下に示します。

{
  int usedMem, freeMem, largestFreeMem;

  MP.GetMemoryInfo(usedMem, freeMem, largestFreeMem);

  MPLog("Used:%4d [KB] / Free:%4d [KB] (Largest:%4d [KB])\n",
        usedMem / 1024, freeMem / 1024, largestFreeMem / 1024);
}
SubCore 起動方法

引数に起動したい SubCore 番号(1 ~ 5) を入れてMainCore から MP.begin(1~5) を呼び出します。 起動された SubCore 側では、同様に MP.begin() を引数無しで呼び出しすことで、起動完了通知を行います。

diag 98ff0312883d4ab0998aaacfacbdc1c3
SubCore 終了方法

引数に終了させたい SubCore 番号(1 ~ 5) を入れて MainCore から MP.end(1~5) を呼び出します。 指定された SubCore は動作を終了してシャットダウンします。

diag 916fbe6a6910c9b06b25096d29b61846
コア間通信方法

MP.Send(), MP.Recv() 関数を使用して任意のデータを送受信することができます。
受信の待ち方には 3 つのモードがあり、MP.RecvTimeout() によりモードを設定します。 デフォルトは、MP_RECV_BLOCKING が設定されています。

  • MP_RECV_BLOCKING (0): データを受信するまで永久に受信待ちに入るモードです。(デフォルト)

  • MP_RECV_POLLING (0xffffffff): データの受信をポーリングするモードです。Recv() を呼び出したときに受信データが無かった場合はすぐに抜けます。このモードでは受信待ちに入ることはありません。

  • 時間 (上記以外): 待ちのタイムアウト時間 (ミリ秒) を設定します。Recv() を呼び出したときに指定された時間だけ待ち、受信データが来ない場合はタイムアウトで抜けます。

diag c597a6eb173ba124e93c0d6c1b0c4e6c

MP.Send(), MP.Receive() の通信方式には、データを渡す方法とアドレスを渡す方法の 2 種類が用意されています。

  • データ送受信

    • 書式

      int MP.Send(int8_t msgid, uint32_t msgdata, int subid)
      int MP.Recv(int8_t *msgid, uint32_t *msgdata, int subid)

    • 引数

      msgid: ユーザ側で任意の Message ID (8 bit データ)を定義することができます。
      msgdata: ユーザー側で任意の Message Data (32 bit データ) を定義することができます。
      subid: メッセージをやり取りする SubCore 番号を指定します。省略した場合は、MainCore と通信します。

    • 戻り値

      成功した場合は 0、エラーの場合は 0 以外の値が返ってきます。

    • 説明

      Message ID, Message Data ともに、Send() で送信した ID と Data がそのまま Recv() 側で受信できます。

      Send() は非同期で送信が行われます。内部で 8 段の送信バッファをもっており、送信データをバッファに積んだ時点で Send() 関数はすぐに成功 0 を返します。もし、受信側のコアがデータを引き取る前にこの送信バッファがフル状態になると、Send() 関数は -EAGAIN(-11) のエラーを返します。
      一方、受信側も 8 段の受信バッファをもっています。Recv() が呼ばれずにこの受信バッファがフルになった場合、システムは異常状態であると判断してプログラムは assert します。この assert が発生した場合、受信側のコアが正しく動作していない、または、通信の負荷が高すぎるといった可能性が考えられます。

  • アドレス送受信

    • 書式

      int Send(int8_t msgid, void *msgaddr, int subid)
      int Recv(int8_t *msgid, void *msgaddr, int subid)

    • 引数

      msgid: ユーザ側で任意の Message ID (8 bit データ)を定義することができます。
      msgaddr: ユーザー側で任意の Message Address (ポインタ) を定義することができます。
      subid: メッセージをやり取りする SubCore 番号を指定します。省略した場合は、MainCore と通信します。

    • 戻り値

      成功した場合は 0、エラーの場合は 0 以外の値が返ってきます。

    • 説明

      Message ID, Message Address ともに、Send() で送信した ID と Address がそのまま Recv() 側で受信できます。 実際に通信したいデータは別のメモリにあって、そのデータのポインタアドレスのみを送信するようなケースで使用します。
      SubCore からアドレスを送信する場合に、仮想アドレスから物理アドレスへの変換が必要ですが、msgaddr については、 Send() 関数の内部でアドレス変換を行っています。もし、msgaddr ポインタの指し示す先にもアドレス情報があり、 コアを跨いでそのアドレスを参照する場合は、ユーザー側でアドレス変換を行ってください。
      Send() が非同期であることはデータ送受信のときと同様です。Send() 関数は、実際に相手がメッセージを受信したかどうかに 関係なく return で返ってきます。そのため、Send() した直後にポインタが指し示す先のデータを書き換えてしまうと、 受信側で受け取るデータについて保証ができなくなります。同期を取るための Acknowledge のような通信を別途 Send()/Recv() で実現するか、 もしくは、データパケットの中にデータを保証するためのフラグを追加する、といった工夫が必要になります。

Send()/Recv() 機能の具体的な使い方は、サンプルコードMessage を参照してください。

Message/MessageData

データ渡しについてのサンプルコード

Message/MessageHello

アドレス渡しについてのサンプルコード

SubCore から使用可能なライブラリ

Arduino 標準コアライブラリは SubCore からも使用可能です。

Spresense 特有のライブラリのいくつかは SubCore から使用することはできません。 もし組み込んだ場合にコンパイル時に以下のエラーメッセージが出力されます。

XXX library is NOT supported by SubCore.

SubCore から使用可能なライブラリを以下に示します。

Library MainCore SubCore Description

MP

*

*

RTC

*

*

Alarm 機能は SubCore では使用できません。

SPI

*

*

Servo

*

*

SoftwareSerial

*

*

Watchdog

*

*

Wire

*

*

Audio

*

-

Camera

*

-

DNNRT

*

-

GNSS

*

-

LowPower

*

-

Sensing

*

-

Storage (EEPROM, eMMC, File, Flash, SDHCI)

*

-

SubCore プログラミングTIPS
SubCore プログラムのヒープサイズを増やす方法

SubCore で必要なメモリサイズはコンパイル時に自動的に決定されますが、詳細なロジックを説明します。

.stack までのサイズはコンパイル時に静的に決定されますが、.heap のサイズはプログラムに依存します。 ヒープメモリとして最低 32 KByte 分が確保されており、 最終的にリンクする際に、全体のメモリを 128 KByte に アライメントされた上限までをヒープメモリとして割り当てます。

diag b04beb3f5ef99d3c277e407a3275d202
図 14. SubCore プログラムサイズ

上記のルールによって、最低 32 KByte 分のヒープ領域が確保されています。 ただし、ユーザープログラムによっては、ヒープ領域が不足するかもしれません。 ヒープ領域を拡張したい場合は、ユーザースケッチ上で次のように USER_HEAP_SIZE() マクロを使用することで そのサイズを拡張することができます。

USER_HEAP_SIZE(64 * 1024);

このように 64 KByte を指定すると、必ず 64 KByte 以上のヒープメモリが確保されます。

SubCore 番号を識別するためのコンパイルオプションについて

SubCore をビルドする際には、コンパイルオプションとして -DSUBCORE=コア番号が指定されています。 共通ソースコードを使用して、コアごとに ifdef によってコードを分けたい場合は以下を参考にしてください。

#if   (SUBCORE == 1)
// SubCore1 ビルド

#elif (SUBCORE == 2)
// SubCore2 ビルド

#elif (SUBCORE == 3)
// SubCore3 ビルド

#elif (SUBCORE == 4)
// SubCore4 ビルド

#elif (SUBCORE == 5)
// SubCore5 ビルド

#else
// MainCore ビルド

#endif

これを応用して、ユーザーのスケッチに以下のような記述を追加することで、 間違ったコアが選択されてビルドやアップロードしてしまうことを防止することができます。

  • MainCore のスケッチに、SubCore が指定されていた場合にビルドエラーにする

#ifdef SUBCORE
#error "Core selection is wrong!!"
#endif
  • SubCore のスケッチに、MainCore が指定されていた場合にビルドエラーにする

#ifndef SUBCORE
#error "Core selection is wrong!!"
#endif
  • SubCore1 のスケッチに、SubCore1 以外のコアが指定されていた場合にビルドエラーにする

#if (SUBCORE != 1)
#error "Core selection is wrong!!"
#endif
スケッチディレクトリ構成について

MainCore, SubCore とで共通のヘッダファイルを参照したい場合があると思います。
一つの案として、例えば、次のようなディレクトリ構成にすることによって、 共通の common.h ヘッダファイルを include することができます。

diag 66900e49037f717735e83d1d138ec99a

SubSketch.ino の中で、

#include "common.h"

MainSketch.ino の中で、

#include "SubSketch/common.h"

別案として、Arduino 環境の libraries ライブラリの置き場所に共通のヘッダファイルを置くという方法もあります。
libraries 配下にヘッダファイルがあればどのスケッチからも参照することが可能です。
libraries 以下にヘッダファイルを置くには Arduino IDE メニューの Sketch → Include Library → Add .ZIP Library…​ (スケッチ → ライブラリをインクルード → .ZIP形式のライブラリをインストール…​) からヘッダファイルを含むフォルダの場所を指定することによって libraries へ追加することができます。

3.10.3. サンプル

MP ライブラリの基本的な使い方は、examples にあるサンプルスケッチを参照してください。 サンプルスケッチは、Arduino IDE メニューの File → Examples → Examples for Spresense → MultiCore MP (ファイル → スケッチ例 → Spresense用のスケッチ例 → MultiCore MP)にあります。

Example Description

Boot

4 つのSubCore を起動するサンプルです。起動された SubCore はそれぞれ別の LED を制御し、マルチコアを使って L チカします。

Message/MessageData

MainCore と SubCore 間でデータの通信を行うサンプルです。

Message/MessageHello

MainCore と SubCore 間でアドレスの通信を行うサンプルです。

Mutex

ハードウェアセマフォ MPMutex の機能を用いて、MainCore, SubCore 間で排他制御を行います。

SharedMemory

MainCore から共有メモリを確保/解放するサンプルです。

Shell

MainCore から起動された SubCore 側でシェルを動作するサンプルです。

AudioFFT

SubCore を使った応用アプリケーションのサンプルです。MainCore で Audio ライブラリを使ってPCM 4chデータをキャプチャし SubCore へ渡します。SubCore はリアルタイムに FFT (Fast Fourier Transform) 解析をかけてピーク周波数を表示します。Arduino IDEのシリアルプロッタを使って時系列データとしてグラフ化して表示することができます。

3.11. RTC ライブラリ

RTC (Real-Time Clock) ライブラリは、Spresense の RTC 絶対時刻を管理します。 Spresense がもつ RTC ハードウェアは 初期値 0 からはじまる単調増加カウンタです。 RTC は UNIX 時刻で管理されるため、初期値 0 は 1970年1月1日午前0時0分0秒を表します。 Deep Sleep や Cold Sleep といったスリープ期間中も時刻を保持し続けることができます。 ただし、電源がオフされると、RTC カウンタはリセットされ初期値 0 に戻ります。

RTCライブラリを使用する場合は、初めに必ずRTC.begin()を呼び出してください。 電源が供給されてから、RTC XTALが安定して発振するまでに約2秒かかります。 RTC.begin() の中で、この発振安定待ちを行いますので、 RTC.begin() の呼び出しから戻ってきた後で、RTC 機能を安全に使用することができます。

RTC ライブラリは、以下の機能を提供しています。 各種 API の詳細は、API リファレンスマニュアル RTC Library API を参照してください。

  • RTC.setTime() 絶対時刻を設定

  • RTC.getTime() 絶対時刻を取得

  • RTC.attachAlarm() アラームハンドラを登録

  • RTC.detachAlarm() アラームハンドラを解除

  • RTC.setAlarm() アラーム時刻を設定

  • RTC.setAlarmSeconds() 指定時間(秒数)の相対時刻アラームを設定

  • RTC.cancelAlarm() アラーム設定をキャンセル

RTC ライブラリの基本的な使い方は、examples にあるサンプルスケッチをご覧ください。 サンプルスケッチは、Arduino IDE メニューの ファイル → スケッチ例 → Spresense 用のスケッチ例 RTC から開くことができます。

その他、RTC ライブラリとは別に #include <time.h> をインクルードすることで、 strftime() や clock_gettime(CLOCK_REALTIME, tp) のような POSIX 標準の API もサポートされています。

詳細はNuttX User’s Manualを参照してください。 なお、NuttX Configurationにて Local time 機能は無効化されているため、localtime() はサポートされておりません。

3.12. SDHCI ライブラリ

3.12.1. 概要

SDHCI ライブラリは Spresense 拡張ボードにある micro SD にアクセスするためのライブラリです。

SDHCI ライブラリは、Arduino SD ライブラリ に類似した API 構成となっており、SD ライブラリを用いた既存のスケッチから簡単に移植することができます。

SPI インターフェースを用いた SD ライブラリとは異なり、SD Host Controller Interface の専用ハードウェアを用いて、SD カードへアクセスするため、次のような特徴をもちます。

  • SD カードは専用端子で接続されるため、SPI 端子を必要としません。SPI 端子を他の用途で使用することができます。

  • SPI 通信と比べて非常に高速です。SDR25 転送モードまでサポートしています。

また、特徴的な機能として、USB MSC (Mass Storage Class) 機能を提供します。 Spresense 拡張ボードにある USB と PC を接続することで、PC から SD カード上のファイルに直接アクセスすることができます。

3.12.2. 機能

各種APIの詳細は、APIリファレンスマニュアル SD card Library API を参照してください。

SDHCI ライブラリ内では、SDClass のインスタンスを生成していないため、スケッチ内で次のように定義してください。

#include <SDHCI.h>
SDClass SD;
Function Description

SD.begin()

SD カードがマウントされているかどうかを確認します。この関数が true で返ってきてマウント済みであることを確認した後にその他の API を使用してください。
SD カードがマウントされていないときは最大で 2 秒間待ってから結果を返します。

SD.beginUsbMsc()

USB MSC (Mass Storage Class) 機能を開始します。

SD.endUsbMsc()

USB MSC (Mass Storage Class) 機能を終了します。

SD.format()

SD デバイスをフォーマットします。デフォルト FAT32 ファイルシステムでフォーマットします。

SD.open()

ファイル名を指定して SD デバイス内のファイルをオープンします。
FILE_READ: 読み取り専用でファイルをオープンします (デフォルト)
FILE_WRITE: 読み書き可能でファイルをオープンします。ファイル位置は末尾を指します。
この関数は File オブジェクトを返します。ファイル操作については File ライブラリ を参照してください。

SD.exists()

SD デバイス内にファイルが存在するかどうかを確認します。

SD.mkdir()

SD デバイス内にディレクトリを作成します。

SD.rmdir()

SD デバイス内にディレクトリを削除します。

SD.remove()

SD デバイス内のファイルを削除します。

3.12.3. サンプル

SDHCI ライブラリには、3 つのスケッチのサンプルが提供されています。 SD カードは、FAT32 でフォーマット済みの状態で使用してください。

Example Description

read_write.ino

SD カード上のファイルを読み書きするサンプルです。

UsbMsc.ino

USB MSC 機能のサンプルです。Spresense 拡張ボードの SD カードが PC 上のドライブとしてマウントされ、PC から SD カードに直接アクセスすることができます。

UsbMscAndFileOperation.ino

USB MSC 機能とファイル操作を組み合わせた複合アプリケーションです。SD カード内のファイルに対して、スケッチからのファイル操作と、USB MSC による PC からのファイル操作は、排他的に動作させる必要があります。このサンプルでは、アプリケーションプログラムからファイル一覧を取得・表示した後に、USB MSC 機能を有効にし、PC から SD カード内のファイルを操作できるようになります。USB MSC 機能を終了した後に、再びプログラム中からファイル一覧を取得・表示します。

3.13. Servo ライブラリ

Servo ライブラリは、Spresense に RCサーボを制御する機能を提供します。

Servo ライブラリは、Arduino で定義されているArduino Servo ライブラリ と同様に扱うことができます。

Spresense は4つの PWM をサポートしており、これらを使って RC サーボを制御することができます。

  • D06 PWM0

  • D05 PWM1

  • D09 PWM2

  • D03 PWM3

多くのサーボは 5V電源を要求し、また多くの電力を要求します。そのため、Spresense 拡張ボードから供給すると、モーターの回転に多くの電力を消費し、本体に電源が十分に供給されない可能性があります。そのため、モーターへの電源は外部電源で供給することを検討してください。

また、Spresense拡張ボードは、IOREFジャンパーで 3.3V もしくは 5V を選択できることも注意してください。ただ、多くのRCサーボは、3.3V も 5V も受け付けることができますが、仕様をよく確認する必要があります。

3.13.1. 制限

  • サーボ機能には PWM が必要です。したがって、Spresense の Servo ライブラリでコントロールできる RC サーボは最大4つになります。

3.14. Sensing ライブラリ

Spresense はLow Powerで常時Sensingを行う機能と、Edgeコンピューティングができるパフォーマンスを有しています。また、各種センサデータを組み合わせつつ信号処理・AI処理などを施すことによって、データ量の少ない抽象的なデータに変換することができます。この一連の処理をセンサ(論理センサと呼びます)として作成することができます。
Sensingライブラリは、このような論理センサを使用・作成するためのフレームワークを提供します。

論理センサは、Spresense の持つ特徴であるMulti Coreを利用し、別のコア(以降、それらのコアをDSP と呼びます)で信号・認識処理をさせることも可能です。

Sensing ライブラリの主な特徴
  • Publish-Subscribe Architectureに基づき、複数のSensorのフュージョンが実行・変更が容易です。

  • Arduinoが供給するエコシステムで作成されたセンサドライバを用いてセンシングしたデータを、作成された論理センサにpublishし、Arduinoのアプリケーションがsubscribeすることで、Spresense SDKと同様の機能がArduino上から使用できます。

Arduinoライブラリは、基本的には、Spresense SDKの有する機能・APIのArduino向けラッパライブラリになっています。
詳細情報に関しては、SDK側を参照してください。

3.14.1. アーキテクチャとデータフロー

まず、SpresenseでのSensor Frameworkを示します。

こちらに関してはSensor Fusion Frameworkを参照してください。

Sensor Framework(Publish/subscribe) Architecture
図 15. Sensing Library (Publish/subscribe) Architecture

次に、Arduino向けSensingライブラリのアーキテクチャを示します。

Sensor Framework(Publish/subscribe) Architecture
図 16. Sensing Library (Publish/subscribe) Architecture

Spresense SDK で提供しているSensor Framework部分を "Sensing" ライブラリとして提供することで、SDKと同等の機能を実現します。
Arduinoで開発する方は、センサのドライバ、センサを使用したアプリケーション、および、より抽象度の高い論理センサを自分で作成される方は、論理センサの信号処理部分を実装することで、高機能な論理センサを使ったアプリケーションを作成できます。

Sensing ライブラリのクラス
  • SensorManagerClass:
    SDK内部にある各センサクライアントを管理するクラス(Sensor Manager)のラッパクラスです。

  • SensorClient:
    各センサの要素であるSensorClientのベースクラス。ユーザは、直接このクラスを呼ぶことはありません。
    また、独自の論理センサを作成する場合は、このクラスを継承してください。

    • AccelSensorClass:
      加速度センサの物理センサクライアント、Arduinoでのセンサのドライバから取得したセンサデータをPublishすることで各センサクライアントが加速度データを利用できます。

    • ApplicationSensorClass:
      アプリケーションがセンサデータをsubsribeするためのセンサクライアントです。

      • StepCountReaderClass:
        アプリケーションの中で、ステップカウンタセンサのデータを読み出すためのセンサクライアントです。ApplicationSensorClassを継承して作成しています。

    • AesmClass:
      Spresense SDK が提供する歩数計アルゴリズム(AESM: Activity Engine and StepMeter) が実装されている論理センサクライアントです。 加速度センサを使用します。
      SDK提供の論理センサのため、Arduinoからのpublish/Subscribe処理は不要です。

3.14.2. 各クラスのAPIリファレンス

以下に、各クラスのAPIリファレンスを示します。

SensorManagerClass

以下、SensorManagerClassのAPIです。

begin
begin();
  • センサマネージャの起動を行います。フレームワークを使用する前に一度呼んでください。

end
end();
  • センサマネージャの停止を行います。フレームワークを使用を終了したら、一度呼んでください。

SensorClient

以下、SensorClientのAPIです。 このクラスは、各センサクライアントのベースクラスです。

begin
begin(int      id,
      uint32_t subscriptions        = 0,
      int      rate                 = 0,
      int      sample_watermark_num = 0,
      int      size_per_sample      = 0,
      sensor_data_mh_callback_t cb  =NULL):

センサクライアント生成時に一度だけ呼んでください。

  • int id
    センサクライアントのIDになります。

  • uint32_t subscriptions
    Subscribeしたいセンサを指定します。 ID番目のbitを1にすることで、そのIDのデータを読むことができます。

  • int rate
    入力するセンサデータのサンプリングレートを指定します。

  • int sample_watermark_num
    一回の処理でのサンプル数を指定します。

  • int size_per_sample
    1サンプルのサイズを指定します。

  • sensor_data_mh_callback_t cb
    センサデータがsubscribeされた時に呼ばれるcallbackを指定します。

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

センサクライアントで取得・生成されたセンサーデータをPublishするAPIです。

  • FAR void* data
    送信するセンサーデータのアドレスを指定します。

  • uint32_t size_per_sample
    サンプル単位でのサイズを指定します。

  • uint32_t freq
    センシングの周波数を指定します。

  • uint32_t sample_watermark_num
    センサデータのサンプル数を指定します。

  • uint32_t timestamp
    送信するセンサデータの最初のサンプルのタイムスタンプを指定します。

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

Memory管理エリアを独自に定義し、メモリを削減する際に呼び出します。現在は使用しません。

int publish(MemMgrLite::MemHandle& mh,
            uint32_t size_per_sample,
            uint32_t freq,
            uint32_t sample_watermark_num,
            uint32_t timestamp);

センサクライアントでのセンサデータの管理をMemoryUtilのMHandleを用いた場合に呼び出します。現在は、使用しません。

subscribe
int subscribe(sensor_command_data_mh_t& data);

SensorClientのSubscribeを呼びことで、センシングデータが格納されているアドレスを取得できます。 SubClassで、使用してください。

subscribeされるデータ型は、

sensor_command_data_mh_t

になります。これは、Spresense SDKで定義されています。

typedef struct
{
  sensor_command_header_t header;  /**< command header    */
  unsigned int self: 8;            /**< sender sensor ID  */
  unsigned int time: 24;           /**< time stamp        */
  unsigned int fs: 16;             /**< frequensy         */
  unsigned int size: 16;           /**< number of samples */
  MemMgrLite::MemHandle  mh;       /**< mem handle for send data */

  unsigned int get_self(void)
  {
    return self;
  }

} sensor_command_data_mh_t;

です。 timestamp情報など、必要に応じて取得してください。

AccelSensorClass

実際に加速度センシング用の物理センサクライアントもライブラリとして提供しています。SensorClientを 継承する形で作られています。

begin
bool begin(int id,
           int rate                 = 0,
           int sample_watermark_num = 0);

加速度センサクライアントの生成をします。

  • int id
    自分のセンサIDを指定します。SEN_accelID を指定してください。

  • int rate
    加速度センサのレートを指定します。 今回提供のStepCounter(AESM)の場合は、50Hzにしてください。   

  • int sample_watermark_num
    一回の転送サンプル数です。指定できる値は、50以下です。特に変更をする必要がなければ50を指定してください。

write_data
int write_data(float x,
               float y,
               float z);

実際に加速度データを書き込む関数です。 センサから取得したデータをGに換算して書き込んでください。 このインターフェースで1サンプルずつ書き込み、sample_watermark_num数だけ書き込まれると、Publishされます。

ApplicationSensorClass

アプリケーションセンサは、センサデータをアプリケーションに受け渡すためのセンサクライアントです。そのため、subscribeしか実装されません。

begin
bool begin(int id,
           uint32_t subscriptions,
           sensor_data_mh_callback_t cb);
  • int id
    自分のセンサIDを指定します。 SEN_app*ID(*:0~3) を指定してください。

  • uint32_t subscriptions
    Subscribeしたいセンサを指定します。 ここでは、ID番目のbitを1にすることで、そのIDのデータを読むことができます。

  • sensor_data_mh_callback_t cb
    センサデータがsubscribeされた時に呼ばれるcallbackを指定します。

subscribe
int subscribe(sensor_command_data_mh_t& data);

subscribeによって、所望のセンサ(物理センサ・論理センサ)のデータを取得できます。 アプリケーションに応じて、実装してください。

StepCountReaderClass

アプリケーションセンサの中で、StepCounterデータを読み出すために、用意したアプリケーションセンサクライアントです。

begin
bool begin(int      id,
           uint32_t subscriptions,
           sensor_data_mh_callback_t cb);
  • int id
    自分のセンサIDを指定します。 SEN_app0ID を指定してください。

  • uint32_t subscriptions
    Subscribeしたいセンサを指定します。 ここでは、StepCounterの論理センサを読み出しますので SUBSCRIPTION(SEN_stepcounterID) を指定してください。

  • sensor_data_mh_callback_t cb
    センサデータがsubscribeされた時に呼ばれるcallbackを指定します。

subscribe
int subscribe(sensor_command_data_mh_t& data);

subscribeによって、Step Counterの論理センサからのデータを取得することができます。

通知されるデータ構造は以下になります。

typedef struct
{
  SensorExecResult exec_result;

  union
    {
      StepCounterStepInfo steps;
      SensorAssertionInfo assert_info;
    };
} SensorResultStepCounter;

この中の StepCounterStepInfo steps; がセンサデータの実体です。

以下が、StepCounterセンサーデータです。

typedef struct {

  float    tempo;
  float    stride;
  float    speed;
  float    distance;
  uint32_t step;
  StepCounterMovementType  movement_type;
  uint64_t          time_stamp;

} StepCounterStepInfo;
AesmClass:

ソニーが独自に用意した、ステップカウンタライブラリを呼び出すためのセンサクライアントです。 本アルゴリズムは、Bosch社製BMI160をベースにチューニングされています。BMI160のセンシングデータを利用することを推奨しますが、加速度データとして、所望のサンプリングレートでデータが取得できれば、論理センサとして機能はします。

begin
bool begin(int      id,
           uint32_t subscriptions,
           int      input_rate,
           int      input_sample_watermark_num,
           int      input_size_per_sample);

* int id
自分のセンサIDを指定します。 SEN_stepcounterID を指定してください。

  • uint32_t subscriptions
    Subscribeしたいセンサを指定します。 ここでは、加速度センサのデータを使用しますので、 SEN_accelID を指定してください。  

  • int rate
    入力するセンサデータのサンプリングレートを指定します。今回のアルゴリズムは、50Hzをベースに作成されていますので、50にしてください。

  • int sample_watermark_num
    一回の処理でのサンプル数を指定します。 今回のアルゴリズムは、1秒単位での処理を行いますので、50にしてください。

  • int size_per_sample
    floatの値が、x、y、zの3軸分ありますので、12を指定してください。

set
int set(uint8_t walking_stride,
        uint8_t running_stride)

歩幅をセットする関数です。現在は使用できません。

3.14.3. サンプルスケッチについて

Step Counterサンプル

今回、Sensingに関しては、Sonyが提供するStepCounterを使用するサンプルを提供しています。

このサンプルでは、v1.3.0以降のブートローダへの更新が必要です。

Spresense SDKでの、Step Counter機能は、以下で構成されています。

こちらに関しては、Sensor Fusion Frameworkを参照してください。

Sensor Framework(Publish/subscribe) Architecture
図 17. Sensing Library (Publish/subscribe) Architecture

Arduino向け、Sensingライブラリのでは、以下の図に示す部分が、ライブラリとして提供されています。

Sensor Framework(Publish/subscribe) Architecture
図 18. Sensing Library (Publish/subscribe) Architecture

サンプルスケッチとしては、加速度センサを読みだしフレームワークに供給する部分と、生成されたStepCounterデータを読み出す部分の実装を行うことで、実現が可能です。

以下が、シーケンスになります。

diag da588cc9f42d18f4ff622ea14f3adfa2
図 19. 初期化シーケンス
diag 4b4aa04ad7bfb6a504afb76a05ad5c3a
図 20. 実行シーケンス

このように、実装することで、StepCounterデータが取得できます。

使い方の詳細に関しては、チュートリアルを参照してください。

3.15. Software Serial ライブラリ

Spresense Arduino Library は、2つのシリアルポートを有しています。USBコネクタのデバッグシリアルは、 Serial で、DO, D1 ピンは Serial2 に割り当てられています。

SoftwareSerial ライブラリは Spresense のデジタル端子をシリアル端子として使うことができるようになります。最大の転送レートは 250,000bps です。

SoftwareSerial ライブラリは Arduino の SoftwareSerial ライブラリと互換性があり、そのまま使うことができます。

3.15.1. 制限

  • 最大転送レートは、250,000bps

  • 使用できる GPIO ピンは (D0 - D28) です。 TX はどのピンでも使えますが、RX はいくつかの制限があります。TXは次のピンから 6 pins を選択できます: 0, 1, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28、その時 RX は次のピンから 6 pins を選択できます: 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 22.

3.16. SPI ライブラリ

Spresense SPI ライブラリは Spresense に各種 SPI インターフェースを備えたスレーブデバイスを接続するための標準インターフェースを提供します。 Spresense SPI ライブラリは、Arduino SPI ライブラリ と互換性をもち同様に使うことができます。

Spresense ボードは、メインボードと拡張ボードのそれぞれに独立した SPI インターフェースを有しています。

各SPIインターフェースの端子を以下に示します。

表 5. SPI インターフェース端子
SPI インスタンス名 コネクタ MOSI MISO SCK SS IO電圧

SPI (or SPI4)

拡張ボード

D11

D12

D13

D10

3.3V or 5V (JP1ジャンパーにより切替)

SPI5

メインボード

D16

D17

D23

D24

1.8V

SPI というインスタンス名を使用した場合、拡張ボード上の SPI インターフェースが使われます。 メインボード上の SPI インターフェースを使う場合は、例えば、SPI5.beginTransaction() のように、 インスタンス名を SPI5 に置き換えて使用してください。

3.16.1. 機能と制限

  • Spresense SPI ライブラリは 8bit ならびに 16bit データ長の転送をサポートしています

  • SPI SS は自動的に個々のトランザクションを開始するときに LOW に落ちます。トランザクションが終了すると HIGH になります。これは高速転送のときに非常に便利な機能です。もし、この機能が検討しているアプリケーションにそぐわない場合は、他のデジタル端子を SS に割り当てて、digitalWrite() 関数で HIGH/LOW 制御することを検討してください

  • 16 bit data は Little Endian で転送されます

  • 最大転送スピードについては、ハードウェアドキュメント SPIの使用方法 を参照してください。

  • SPI ライブラリのサンプルについては、Arduino IDE から ファイル → スケッチ例 → Spresense 用のスケッチ例 → SPI を参照してください。

3.17. Storage ライブラリ

3.17.1. 概要

Storage ライブラリは SDHCI, SPI-Flash, eMMC など各種ストレージライブラリのベースクラスです。 基本的にはデバイスごとの SDHCI, Flash, eMMC ライブラリ経由で使用されますが、 マウントディレクトリを含む絶対パス名を指定することにより、Storage ライブラリを直接使用することも可能です。

参考までに、各種ストレージとマウントディレクトリ名の関係を以下に示します。

Device Mount Path

SD card

/mnt/sd0

Flash

/mnt/spif

eMMC

/mnt/emmc

3.17.2. 機能

各種APIの詳細は、APIリファレンスマニュアル Storage Library API を参照してください。

Function Description

Storage.open()

マウントディレクトリを含むファイル名を指定して Storage デバイス内のファイルをオープンします。
FILE_READ: 読み取り専用でファイルをオープンします (デフォルト)
FILE_WRITE: 読み書き可能でファイルをオープンします。ファイル位置は末尾を指します。
この関数は File オブジェクトを返します。ファイル操作については File ライブラリ を参照してください。

Storage.exists()

Storage デバイス内にファイルが存在するかどうかを確認します。

Storage.mkdir()

Storage デバイス内にディレクトリを作成します。

Storage.rmdir()

Storage デバイス内にディレクトリを削除します。

Storage.remove()

Storage デバイス内のファイルを削除します。

3.17.3. サンプル

Storage ライブラリには、1 つのスケッチのサンプルが提供されています。

Example Description

read_write.ino

ファイルを読み書きするサンプルです。

3.18. Wire ライブラリ

Spresense Wire ライブラリは、Spresense で I2C / TWI デバイスと通信することができます。I2C は多くのセンサーデバイスで採用されている通信インターフェースです。

Spresense Wire ライブラリは、Arduino Wire ライブラリ と同じ様に使用することができます。

Spresense メインボード/拡張ボードのピン配置を以下に示します。IO電圧は、メインボードでは 1.8V、拡張ボードでは 3.3V もしくは 5.0Vになります。拡張ボードとメインボードで同じピンを使っていますので、使用の際は注意してください。

  • D15 I2C_SCL Clock line

  • D14 I2C_SDA Data line

注意:拡張ボードのピンの物理配置は Arudino Uno と同じですが、I2Cのピン番号の配置が異なります。したがって、Arduino Uno 向けのスケッチを流用する場合は変更が必要になります。

拡張ボードのIO電圧は IOREF ジャンパーによって変更することができます。I2C のIO電圧もIOREF ジャンパーによって変更されます。

メインボード上のピンソケットからも I2C を利用できますが、IOREF に関係なく、IO電圧は1.8V固定です。

I2C 通信には通常プルアップレジスタが必要ですが、拡張ボードとメインボードでは必要ありません。

  • Spresense 拡張ボードは、1kΩのプルアップ抵抗がついていますので追加のコンポーネントは不要です。

  • Spresense メインボードは、4.7kΩのプルアップ抵抗が内蔵されていますので追加のコンポーネントは不要です。

3.18.1. 機能と制限

通信速度は3種類定義されています。起動時に選択します。

  • #define TWI_FREQ_100KHZ (100000) // standard mode

  • #define TWI_FREQ_400KHZ (400000) // fast mode

  • #define TWI_FREQ_1MHZ (1000000) // fast mode plus

デフォルトの通信速度は 100kHz です。

ライブラリは、二つの I2C アドレス長をサポートしています。

  • #define TWI_ADDR_LEN_7_BIT (7)

  • #define TWI_ADDR_LEN_10_BIT (10)

デフォルトのアドレス長は、7 bit です。

オリジナルの Arduino Wire ライブラリと同じ様に、Spresense Wire ライブラリも 32 byte buffer です。したがって、デバイスとの通信データはその範囲内に収める必要があります。それを超えるデータを受信した場合、超過分のデータは捨てられます。

3.19. Watchdog ライブラリ

Spresense Watchdog ライブラリは Spresense の システム状態を監視し、異常時にHW リセットをするための Hardware watchdog 機能を提供します。

このライブラリによって以下の機能をアプリケーションから使う事ができます。

  • HW リセットを実行するまでの時間を設定する

  • リセットまでの時間を取得する

  • リセットまでの時間をリセットする

例えば”10秒以内に loop() を抜けなければならないのにそれを経過してしまったらリセットするようにしたい”場合に使うことができます。

3.19.1. 使い方

このライブラリは以下の手順で使うことができます。また、 WatchdogClass のインスタンス Watchdog を使います。

  1. Watchdog.begin() でWatchdogを初期化する

  2. Watchdog.start(time) で監視を開始する

    time にリセットするまでの時間(ms)をセットします。 その時間を経過するとHW リセットが発生します。 time は最大40秒を設定できます

  3. Watchdog.kick() でリセットまでの時間をリセットする

    プログラムが正常に動作している場合はそれを通知してリセット時間をリセットします。

  4. Watchdogで監視する必要がなくなったら Watchdog.stop() を実行する

    Watchdog.stop() 及び Watchdog.kick() せずに所定時間が経過すると、HWリセットが発生してしまいます。

必要に応じて、HWリセットが発生するまでの時間を Watchdog.timeleft() で確認してください。

diag 19f5857c5fd9a3e66f5543fac9881375
LowPower ライブラリ を利用してのクロックモードの切り替えを行った場合やSDカードの挿抜時は Watchdog のタイマーがリセットされます。

3.19.2. サンプル

このライブラリのサンプルスケッチは、Arduino IDE上で ファイル > スケッチ例 > Watchdog > Watchdog_bite にあります。

4. Spresense Arduino Library 付録

4.1. Spresense Arduino board package のマニュアルインストール

Spresense Arduino board package をマニュアルでインストールした場合、ボードマネージャを使ったインストールに失敗することがあります。その場合は Spresense Arduino board packageのインストールに失敗する を参照しインストールを実施してください。

4.1.1. Windows版 Spresense Arduino Library のインストール

このチュートリアルでは、WinZip を使用していますが、Windows エクスプローラーメニューの"すべて展開(T)"も同様に利用できます。
  1. Arduino IDE のインストールフォルダを開きます。

    %userprofile%/AppData/Local/Arduino15

  2. ダウンロードしたファイル (manual-install-spresense-arduino-windows-latest.zip) を %userprofile%/AppData/Local/Arduino15 へドラッグします。ZIP ファイルを右クリックでメニューを開き Extract > Extract to here を選択してその場に展開します。

    tutorial arduino extract into arduino15
    図 22. Arduino15フォルダーへ Spresense Arduino board package を展開

    これで、ボードパッケージはインストールされています。

4.1.2. Linux版 Spresense Arduino Library のインストール

このチュートリアルは、64bit版 Ubuntu であり、 manual-install-spresense-arduino-linux-latest.zip が ~/Downloads へダウンロードされていることが前提となっています。

  1. Arduino IDE をインストールします。

    Arduino IDE を起動します。

    Arduino IDE を終了します。

    この一連の操作によって、Spresense Arduino board package をインストールするためのフォルダが生成されます。 ~/.arduino15/ が存在していることを確認してください。

  2. ターミナルを開いて、 manual-install-spresense-arduino-linux-latest.zip がダウンロードされているフォルダへ移動してください。

    zipファイルを解凍し、 ~/.arduino15/ 以下へコピーします。

    $ cd ~/Downloads
    $ unzip manual-install-spresense-arduino-linux-latest.zip
    $ rm -rf ~/.arduino15/packages/SPRESENSE
    $ cp -rfv ~/Downloads/Arduino15/* ~/.arduino15/
    $ rm -rf ~/Downloads/Arduino15
  3. これでボードパッケージはインストールされました。

4.1.3. Mac OSX版 Spresense Arduino Library のインストール

このチュートリアルはオペレーティングシステムが Mac OSX であり、 manual-install-spresense-arduino-macosx-latest.zip が ~/Downloads へダウンロードされていることが前提となっています。

  1. Arduino IDE を Mac OSX へインストールします。

    Arduino IDE を起動します。

    Arduino IDE を終了します。

    この一連の操作によって、Spresense Arduino board package をインストールするためのフォルダが生成されます。 ~/Library/Arduino15 が存在していることを確認してください。

  2. ターミナルを開いて、 manual-install-spresense-arduino-macosx-latest.zip がダウンロードされているフォルダへ移動してください。

    ~/Library/Arduino15 を解凍します。

    $ cd ~/Downloads
    $ unzip manual-install-spresense-arduino-macosx-latest.zip -d ~/Library/Arduino15
  3. これでボードパッケージはインストールされました。