工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

SPRESENSEでマルチコアを使用したプログラムを試しに作る

概要

SPRESENSEでマルチコアを使用したプログラムの実装を試し、動作を確認した。




背景と目的

ある目的で、SPRESENSEでマルチコアを使用したプログラムの実装をする必要が出た。そこで、まずは簡単なサンプルをもとに自分なりに理解しながら、実装し動作を確認してみる。



詳細

0. 参考資料

1. 作成するプログラムの概要

  • Arduino IDE
  • SPRESENSE Arduino SDK
  • SPRESENSE Arduino SDKのサンプルにある Examples > MultiCore MP > Message > MessageHelloスケッチを参考
  • サブコア1からメッセージとして以下の構造体データを引き渡す

実践的なデータとして、構造体をやり取りできたほうが良いので、MessageHelloを基にした。

struct MyPacket {
  volatile int status; /* 0:ready, 1:busy, 互いに書き込みをするためvolatile */
  char message[MSGLEN];
};

2. メインコアのプログラム

ポイントをまとめると、

  • setupにて、MP.begin(N)としてSubCoreNの起動を行う
  • MP.RecvTimeoutで受信モード設定
  • loopにて、MyPacket型構造体のポインタを定義し、MP.Recvで受けとる
  • 受け取ったら、statusを0にし、受け取り完了=> ready状態をSubCore1に伝える
#include <MP.h>

#define MSGLEN      64
#define MY_MSGID    10

struct MyPacket {
  volatile int status; /* 0:ready, 1:busy, 互いに書き込みをするためvolatile */
  char message[MSGLEN];
};

void setup() {

  Serial.begin(115200);
  while (!Serial);

  // サブコアの起動
  int ret = MP.begin(1);
  if (ret < 0) {
    printf("MP.begin(%d) error = %d\n", 1, ret);
  }

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

  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);
}

void loop() {
  int8_t   msgid;
  MyPacket *packet; // サブコア側のMyPacketのポインタを受け取る

  // サブコアからメッセージを受け取る
  if (MP.Recv(&msgid, &packet, 1) > 0) {
    printf("id=%d, message=%s\n", msgid, packet->message);
    packet->status = 0; // status -> ready
  }
}

3. サブコア1のプログラム

  • 各種マクロ定義とMyPacket構造体は同様に参照する必要があるのでメインコアと同様に定義
  • setupで、MP.begin()でメインコアに起動完了を伝える。なお、後述の書き込み対象Coreを設定しないと、MP.begin()はコンパイルエラーになる。※beginの引数が必要と怒られてしまう。
  • loopで、char配列messageに文字列データを格納し、MP.Sendにてメインコアに送信
#include <MP.h>

#define MSGLEN      64
#define MY_MSGID    10

struct MyPacket {
  volatile int status; /* 0:ready, 1:busy, 互いに書き込みをするためvolatile */
  char message[MSGLEN];
};

MyPacket packet; // やり取りしたい対象のデータ, グローバルで宣言

void setup() {
  memset(&packet, 0, sizeof(packet));
  MP.begin(); // Tools > CoreでSubCoreを選ぶと、引数なしのbeginがコンパイルエラーにならなくなる
}

void loop() {

  static int count = 0;

  // メインコアでpacket.status -> readyに書き換えられたら実行する
  if (packet.status == 0) {
    // メッセージ作成
    packet.status = 1; // status -> busy
    snprintf(packet.message, MSGLEN, "[%s] Hello %d", "Sub1", count++);

    // メインコアにメッセージ送信
    int ret = MP.Send(MY_MSGID, &packet);
    if (ret < 0) {
      printf("MP.Send error = %d\n", ret);
    }
  }

  delay(500);
}

4. 書き込み

メインコアは、通常通り書き込みすればよい。 サブコアは、IDEツールバーからTools > Coreで、SubCore1を選択。

5. 動作確認

以下のように、シリアルターミナルにメインコア側で受け取ったメッセージが出力された。

というわけで、無事動作確認OK。

[Main] Used: 896 [KB] / Free: 640 [KB] (Largest: 640 [KB])
id=10, message=[Sub1] Hello 0
id=10, message=[Sub1] Hello 1
id=10, message=[Sub1] Hello 2
id=10, message=[Sub1] Hello 3
id=10, message=[Sub1] Hello 4
id=10, message=[Sub1] Hello 5
id=10, message=[Sub1] Hello 6
id=10, message=[Sub1] Hello 7
id=10, message=[Sub1] Hello 8
id=10, message=[Sub1] Hello 9



まとめと今後の課題

SPRESENSEで、マルチコアのプログラムの実装方法の基本が整理できた。実装予定のプログラムでは、より複雑なデータをやり取りする必要があるが、今回の経験を役立てて完成させたい。


SPRESENSEでデジタルマイクによる録音

概要

SPRESENSEにデジタルマイクを接続し、録音させてみた。




背景と目的

SPRESENSEを用いて、録音をしなければならなくなったため、とりあえず部品をそろえて録音できるところまで確かめる。



詳細

1. 使用部品

  • SPRESENSE メインボード

  • SPRESENSE LTE拡張ボード[LM1]

    • 別の用件でLTE拡張ボードが必要なので、今回これを使用する
  • SPH0641LU4H使用 超広帯域マイクモジュールキット

    • 秋月電子のキットで、SPRESENSEのハードウェアガイドで公式に使用が推奨されている品種SPH0641LU4Hが搭載されている。

akizukidenshi.com

2. 配線方法の確認

まず、SPRESENSE側のピン配置を確認。

SPRESENESE LTE拡張ボード[LM1]のハードウェアガイドにあるとおり、以下のように配線すればよい。今回は、2chのマイクをch0とch1として使用するつもりなのでD01列側の4つの端子を用いる。

※なお、D23側一番下の灰色のGNDは、回路図を見るとどう考えても1.8Vなので、実際にテスターを当てて測ってみたが1.8Vであった。したがって、ハードウェアガイド掲載のこの図は間違いなのでGNDと思って接続してはいけない。

※SPRESENESE LTE拡張ボード[LM1]のハードウェアガイドより引用

次に、マイクモジュールキット側だが、SPH0641LU4Hでは2chのデータをクロックの前半周期、後半周期に割り当てて1つのデータラインで送信できる仕様であり、キットの基板には選択用ランドがついている。そこで、

  • Lch: J2をショート=GNDに接続
  • Rch: J1をショート=VDDに接続

させる。

ということで、最終的な配線は、以下のようになる。M1がRch、M2がLchという対応となる。


3. LTE拡張基板のデジタルマイク入力への切り替え

SPRESENSE LTE拡張ボード[LM1]は、出荷状態ではデジタルマイク入力が使えない。そこで、ハードウェアガイドにある、アナログマイクからデジタルマイク入力への切り替え方法 を参考に切り替えを行う。

リンク先には

  • R22を取り外し、R26に0Ωをマウント(またはジャンパ線などでショートする)。
  • R16(D01チャンネル)とR17(D23チャンネル)に0Ωをマウント(またはジャンパ線などでショートする)。

という説明がさらっと書いてあるが、実は1005サイズのランドにはんだ付けでジャンパ配線を施さなければならない。作業対象となるランドは、密集していてなかなかやりづらく、特にR26をショートさせるのに手間取った。そこで、何かいい手がないか 回路図 でを調べてたところ、

R26をショートさせなくても、CN6の7番ピン(例の灰色GND)が実は1.8VなのでそこからMIC BIASAに接続すれば同じことができる

とわかったので、以下のように配線した。

なお、この作業中に、C15, C16と思われる0603サイズ?のコンデンサが取れてしまったが、R16, R17をショートさせると回路的には無くても同じなのでそのままにした。


4. ソフトウェア

ソースコードは、ひとまず録音さえできればよいので、サンプルコードを使用。

https://developer.sony.com/spresense/development-guides/arduino_tutorials_ja#_mp3_recorder

デジタルマイクを使用するため、一部コードを変更。0は録音ボリューム。16 * 1024はバッファーサイズ[bytes]、trueはis_digitalとあるのでデジタルマイク。

  theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC);

  ↓

  theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC, 0, 16 * 1024, true);


5. 動作確認

アプリケーションを書き込んで再生したところ、無事に録音された。PCでSDカード内に記録された録音ファイルの波形を表示させたところ。

トラブルTips

R16, R17のショートがうまくいっていない、マイクの接続ができていないなど、ACP_MICAのラインにDAT信号が到達していない場合、以下のような録音波形となる。


まとめと今後の課題

SPRESENSEでデジタルマイクによる録音ができた。これを基に目的の製作を進めたい。


メインシェルフの製作 ~ デスク周りのリメイク(2) ~

概要

デスク周りのリメイクとして、メインシェルフの製作を行った。




背景と目的

前回、デスク周りのリメイクについて構想を整理した。今回は、手始めにメインシェルフの製作を行う。



詳細

1. 設計

使用用途としては、主にPC本体の収納と、以前製作したツールボックス、それと工作関係の資材を入れたボックスである。サイズはそれらが十分に入り現在使用中のアルミラックと大体同じ大きさになるようにした。 - 寸法は、幅1250mm、奥行300mm、高さ約1000mm。 - 棚板は25mmと十分な厚みをもつ木材として、木目を生かす。 - 側板は、30mm厚とするが、重量がかさむのでフレームを薄板で挟み込んだ中空構造とする。外観は、棚板の木目が目立つように、こちらは黒いコンクリート調のカッティングシートを貼る。


2. 材料調達

材料は、近所のホームセンターで購入し大きめの部材はカットサービスを利用。

棚板部分は、杉の無垢ボード910mm×1820mm×25mm。無垢ボードといいつついくつかの板材を接着した集成材的なものなので、反りが出づらいのがよい。板としては柔らかめで傷つきやすいことは注意が必要。

側板部分は、MDFで、フレームに12mm厚、フレームに貼り付ける薄板を2.5mm厚とした。安価で加工しやすい。ネジが効きにくくなりやすいのところだけ注意。カッティングシートは、以下のものを使用する。

https://www.amazon.co.jp/dp/B0DL4MP9VD?ref=ppx_yo2ov_dt_b_fed_asin_title


3. 部材加工、塗装

3.1 側板の組み立て、カッティングシート貼り付け

2.5mm厚 MDFの一方に、フレームとなる棒材(MDF12mmから切り出し)を貼り付ける。フレームが貼れたら、内部に吸音材を適量詰め、もう一方の薄板を張り付ける。フレームの一部がダクト状になっているのは、ヘルムホルツ共鳴器を形成するため。3種類のダクト長さにより、6畳間の縦横高さから計算される定在波周波数(の2倍)に合わせてある。書斎が比較的単純な直方体の部屋なので、定在波の影響が顕著に出ている。そのため、家具自身が定在波を吸音し影響を緩和できないか?と考えてこのような構造にした。

カッティングシートを貼った様子が以下。購入したカッティングシートのサイズ的に全体を覆うように貼ることが可能だったが、シワなくうまく貼れず結局各面それぞれの大きさにカットして貼った。

さらに、棚板受けとなる部材をネジ、ボンドを併用してつけた。

3.2 棚板の加工、塗装

棚板は、ホームセンターでカットしてもらったので、角を少し丸める程度の加工のみを行った。

塗装は、蜜蝋ワックスを用いた。これまで使用したことがなかった塗料だが、刷毛がいらず、木目がきっちり目立つ。杉の板目で節が目立つが逆に味があって悪くない。ただし、油性なので多少匂いが落ち着くのに時間がかかった印象だ。

以下の写真は、蜜蝋を塗ったもの(奥)と塗っていないものの比較。この写真だとあまり差が分からないが、目視ではもう少し差がある。

天板、底板についても、手前が塗った後、奥が塗る前の比較になる。もともとが赤身が強い部分のほうがより差が分かる。

すべて塗り終わった様子。この写真だとだいぶ深みのある色合いになっていい感じだ。


4. 組み立て、完成

組み立てにはネジ、ボンドを使用。ボンドはカッティングシート同士では接着できないので、気の部分が露出するように接着面のカッティングシートを一部切り欠いて接着した。棚板の木目と黒く落ち着いた側板のコントラストが効いており、設計イメージをそれなりに再現できていると思う。室内にうまくなじみそうだ。



まとめと今後の課題

メインシェルフの製作を行い、完成できた。次は、デスクトップシェルフの製作に取り掛かりたい。