0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spresence に Jetson(ubuntu)を使って遠隔開発に挑戦

0
Last updated at Posted at 2026-02-23

2025年の単なる夜にキャンペーンで Spresence mini bot を買ってしばらくした後、
定期テストなどが終わってようやく

その後、自宅を少しの間を離れる事に...

このままでは Spresence mini bot 開発が止まってしまう💦

そこで、
以前 cuda 用に買ったjetson orin nano を起動し Spresence に接続して家に放置する。
jetson はVPNに参加させてSSH接続できる体制を整えて jetsonから SpresenceSDK を使い使用することにした。

本ブログの目標は
クライアントPC → TailscaleVPN → Jetson orin nano → Spresence
の体制構築を目指したもの。


1. Jetson > Spresence体制構築

まずは Spresence の mini bot を送られてきた動画(今回はURLは貼らない, 購入後メールの返信でもらえる)を元に組み立てる。

そして、Spresense Arduino スタートガイドをもとに組み立てる。

この時、
1.3. USB ドライバのインストールApple Silicon Mac では不要だった
USBドライバのインストールは Apple Silicon Mac では必ずうまくいかない模様。

ArduinoIDE
→ Spresense Arduino board package のインストール
→ USBシリアルポートの接続
→ Spresense ブートローダーのインストール
まで完了すればSpresense Arduino スタートガイド同様に完了すれば Spresence の PC(ArduinoIDE) → Spresence の開発体制は十分。

本題

次に、Spresenceメインボード を Jetson に繋げる。

Spresenceメインボードの青色LEDが光れば進める

IMG_8903.JPG

jetsonにSSH接続してUSB接続を確認

ls /dev/ttyUSB*

出力例:

/dev/ttyUSB0

これで接続できている。

Spresence かの確認は

lsusb

出力例

Bus 002 Device 003: ID 1d5c:5001 Fresco Logic USB3.0 Hub
Bus 002 Device 002: ID 0bda:0489 Realtek Semiconductor Corp. 4-Port USB 3.0 Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 13d3:3549 IMC Networks Bluetooth Radio
Bus 001 Device 012: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
Bus 001 Device 002: ID 0bda:5489 Realtek Semiconductor Corp. 4-Port USB 2.0 Hub
Bus 001 Device 006: ID 1d5c:5100 Fresco Logic PD3.0 USBillboard 
Bus 001 Device 004: ID 1d5c:5011 Fresco Logic USB2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

その内

Bus 001 Device 012: ID 10c4:ea60 Silicon Labs CP210x UART Bridge

これがあればOK
こういったコマンドは grep を使って

lsusb | grep -i cp210

結果が

Bus 001 Device 012: ID 10c4:ea60 Silicon Labs CP210x UART Bridge

と実行して見つけるのがスマートで見やすい

これで Jetson から Spresence に対してコマンドの実行などが可能になってくる。

2. Jetson の Tailscale VPN への参加

Tailscaleとは?

WireGuardベースのゼロコンフィグVPN です。
技術的特徴

  • プロトコル:WireGuard
  • NAT越え(UDP hole punching)
  • エンドツーエンド暗号化
  • 中央サーバーは「制御面のみ」
  • データ通信は原則P2P
    軽量高速で設定が簡単でサーバー構築などが不要なこともあり、ITエンジニアが多く使っている。

無料でデバイスが100台まで接続可能。モバイル利用可能。

Tailscaleをクライアントで準備

まずは

ここからアカウントを作る、またはログインする。
クライアントPCのブラウザから自身のアカウントのTailscale環境を見られるようにする。

JetsonにTailscaleを設定,参加

jetsonにTailscaleをインストール Jetson(Ubuntu想定)で実行:

curl -fsSL https://tailscale.com/install.sh | sh

その後

sudo tailscale up

ブラウザ認証 URL が出ます。クリックしてクライアントPCのブラウザに自分のアカウントが表示されていればそのまま connect ボタンを押せば jetson はあなたのTailscale ネットワークに参加する。

Tailscale VPNに参加したjetsonに

systemctl status tailscaled

を実行し実際に参加しているか jetson 側から確認できる。
以下のように active (running) と緑色で出ていれば参加できている。

● tailscaled.service - Tailscale node agent
     Loaded: loaded (/lib/systemd/system/tailscaled.service; enabled)
     Active: active (running)
     Status: "Connected; user@example.com; 100.xxx.xxx.xxx"
   Main PID: 222840 (tailscaled)

jetsonの参加は

この Machines の画面にjetsonと同じ ubuntu などの項目が追加されていれば参加確認は完了

TailscaleはWireGuardベースのオーバーレイVPNのため、既存のローカルネットワーク構成を直接変更しません。
そのためJetsonのTailscale参加後も引き続き同じIPアドレスでSSH接続が可能です。
ただし、--accept-routesExit Node を利用するとルーティングテーブルが変更されるため、通信経路には注意が必要です。
従来のL2TP型VPNのようにデフォルトゲートウェイを強制的に変更する設計ではない点が、大きな違いです。


  • JetsonのTailscaleVPN参加
  • JetsonにSpresenceメインボードをUSB接続

この2つが完了すればあとは遠隔で jetson から操作する形で開発可能。

3. いざ、 Jetson 上に Spresense 開発環境を構築,操作する

Jetson (Ubuntu) に SSH でログインし、開発用ディレクトリを作成する。
そのディレクトリ配下に Spresense SDK をはじめとする関連リポジトリをクローンし、ビルドおよび書き込み環境を整備する。

まずは jetson に必要なパッケージをインストール

sudo apt update
sudo apt install -y \
    git \
    build-essential \
    bison \
    flex \
    libncurses5-dev \
    libusb-dev \
    minicom \
    python3 \
    python3-pip \
    gcc-arm-none-eabi

完了したらまず gcc コンパイラの有無を確認

arm-none-eabi-gcc --version

以下のような結果が出たら OK

arm-none-eabi-gcc (15:10.3-2021.07-4) 10.3.1 20210621 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Spresense SDK取得

git clone --recursive https://github.com/sonydevworld/spresense.git

--recursive オプションは必須(submodule取得)

ディレクトリ構造はこうなる:

workspace/
└── spresense
    ├── CONTRIBUTING.md
    ├── Dockerfile
    ├── LICENSE
    ├── NOTICE.txt
    ├── README.md
    ├── examples
    ├── externals
    ├── firmware
    ├── install-tools.sh
    ├── nuttx
    ├── sdk
    └── spresense_env.sh

開発環境用の環境変数を定義する

毎回パスを手入力するのは面倒なので、プロジェクトルートを基準に
環境変数をまとめた env.sh を作成する。

bash env.sh
#!/bin/bash

export JET2EX_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
export SPRESENSE_SDK=$JET2EX_ROOT/spresense
export MYAPPS=$JET2EX_ROOT/myapps
export APPDIR=$MYAPPS
  • JET2EX_ROOT : プロジェクトのルートディレクトリ
  • SPRESENSE_SDK : Spresense SDK の配置場所
  • MYAPPS : 自作アプリケーション用ディレクトリ(今後使用予定)
  • APPDIR : SDKビルド時に参照するアプリケーションディレクトリ

現時点では myapps ディレクトリに自作アプリは存在しないが、
将来的に追加する前提で構成だけ先に用意しておく。

workspaceディレクトリで

source env.sh

確認:

echo $SPRESENSE_SDK

正しくパスが表示されればOK。

ビルド前の前提事項

Spresense は組み込み向けボードのため、
Linuxのように「後からパッケージを追加する」ことはできない。

有効化した機能やアプリケーションのみが
ファームウェアにリンクされる。

つまり:

  • 使いたいアプリはビルド前に選択する
  • 無効な機能は実行時に追加できない
  • シェルコマンドもビルド構成次第

この前提を理解した上で、ビルドを行う。

念のため distclean

過去のビルド設定が残っていると不整合が起きることがあるため、
最初にクリーン状態に戻しておく

cd $SPRESENSE_SDK/sdk
make distclean

distclean は以下を削除する:

  • .config
  • 生成済みオブジェクト
  • 旧ビルド成果物

これにより完全に初期状態へ戻る。

その後に初期化

Spresense SDK では、用途ごとにビルド構成テンプレートが用意されている。
examples/xxx を指定することで、その機能を含む .config が生成される。

tools/config.py examples/hello

tools/config.pyの後に

  • examples/hello を入れれば Spresence の NSH (NuttShell) で Hello World が出せるようになる
  • examples/led → GPIO制御確認用
  • examples/usbmsc → USB Mass Storage 機能
  • examples/audio_player → オーディオ再生機能

私は今回 Sony の Spresence HDR カメラボード を買いメインボードに取り付けた。

IMG_8905.JPG

そのため、カメラ撮影を可能にするために

spresence/sdkディレクトリからターミナルで以下を実行する。

tools/config.py default device/camera examples/camera

ビルド

完了したら spresence/sdk でそのままビルドを実行

make -j$(nproc)
  • make → ビルド実行
  • -j → 並列実行オプション
  • $(nproc) → CPUコア数取得

注意点は、稀に

  • 依存関係の不整合

  • メモリ不足

  • 並列数が多すぎる

    で失敗することがある。その場合は

    make -j4
    

    のように固定値にする。

  • 組み込みでも通常は安全

  • 問題が出たら並列数を下げて対応

Spresenceに書き込み

./tools/flash.sh -c /dev/ttyUSB0 nuttx.spk

意味は:

  • -c /dev/ttyUSB0 → 書き込みに使用するシリアルポート指定 (ls /dev/ttyUSB*/dev/ttyUSB0 と出ていれば上記のコマンドをそのまま使える。)

  • nuttx.spk → ビルド生成されたファームウェアイメージ (spresense/sdk に nuttx.spk があるのか確認してください。)

実行結果は以下のとおり

[BOX64] Box64 v0.4.1 3717266c3 built on Jan 12 2026 07:30:14
[BOX64] Running on Cortex-A78AE with 6 cores, pagesize: 4096
[BOX64] Will use time-based emulation for RDTSC, even if hardware counters are available
[BOX64] Will use software counter measured at 1.0 GHz emulating 2.0 GHz
[BOX64] Detected 48bits at least of address space
[BOX64] Counted 40 Env var
[BOX64] Library search path: 
[BOX64] Binary search path: ./:bin/:/home/maysak/.kiro-server/bin/ead477af76b5b4fc4d4bd12d33c849984a0d1d93/bin/remote-cli/:/home/maysak/.local/bin/:/usr/local/sbin/:/usr/local/bin/:/usr/sbin/:/usr/bin/:/sbin/:/bin/:/usr/games/:/usr/local/games/:/snap/bin/
[BOX64] Looking for /home/maysak/Documents/Jet2exSpresence/spresense/sdk/tools/linux/flash_writer
[BOX64] Running on Cortex-A78AE with 6 cores, pagesize: 4096
[BOX64] Will use time-based emulation for RDTSC, even if hardware counters are available
[BOX64] Will use software counter measured at 1.0 GHz emulating 2.0 GHz
[BOX64] argv[1]="-s"
[BOX64] argv[2]="-c"
[BOX64] argv[3]="/dev/ttyUSB0"
[BOX64] argv[4]="-d"
[BOX64] argv[5]="-b"
[BOX64] argv[6]="115200"
[BOX64] argv[7]="-n"
[BOX64] argv[8]="nuttx.spk"
[BOX64] Rename process to "flash_writer"
[BOX64] Using native(wrapped) libdl.so.2
[BOX64] Using native(wrapped) libz.so.1
[BOX64] Using native(wrapped) libc.so.6
[BOX64] Using native(wrapped) ld-linux-x86-64.so.2
[BOX64] Using native(wrapped) libpthread.so.0
[BOX64] Using native(wrapped) libutil.so.1
[BOX64] Using native(wrapped) librt.so.1
[BOX64] Using native(wrapped) libbsd.so.0
[BOX64] Box64 v0.4.1 3717266c3 built on Jan 12 2026 07:30:14
[BOX64] Running on Cortex-A78AE with 6 cores, pagesize: 4096
[BOX64] Will use time-based emulation for RDTSC, even if hardware counters are available
[BOX64] Will use software counter measured at 1.0 GHz emulating 2.0 GHz
[BOX64] Detected 48bits at least of address space
[BOX64] Counted 42 Env var
[BOX64] Library search path: 
[BOX64] Binary search path: ./:bin/:/home/maysak/.kiro-server/bin/ead477af76b5b4fc4d4bd12d33c849984a0d1d93/bin/remote-cli/:/home/maysak/.local/bin/:/usr/local/sbin/:/usr/local/bin/:/usr/sbin/:/usr/bin/:/sbin/:/bin/:/usr/games/:/usr/local/games/:/snap/bin/
[BOX64] Looking for /home/maysak/Documents/Jet2exSpresence/spresense/sdk/tools/linux/flash_writer
[BOX64] Running on Cortex-A78AE with 6 cores, pagesize: 4096
[BOX64] Will use time-based emulation for RDTSC, even if hardware counters are available
[BOX64] Will use software counter measured at 1.0 GHz emulating 2.0 GHz
[BOX64] argv[1]="-s"
[BOX64] argv[2]="-c"
[BOX64] argv[3]="/dev/ttyUSB0"
[BOX64] argv[4]="-d"
[BOX64] argv[5]="-b"
[BOX64] argv[6]="115200"
[BOX64] argv[7]="-n"
[BOX64] argv[8]="nuttx.spk"
[BOX64] Rename process to "flash_writer"
[BOX64] Using native(wrapped) libdl.so.2
[BOX64] Using native(wrapped) libz.so.1
[BOX64] Using native(wrapped) libc.so.6
[BOX64] Using native(wrapped) ld-linux-x86-64.so.2
[BOX64] Using native(wrapped) libpthread.so.0
[BOX64] Using native(wrapped) libutil.so.1
[BOX64] Using native(wrapped) librt.so.1
[BOX64] Using native(wrapped) libbsd.so.0
[BOX64] Using emulated /tmp/_MEI12xyoq/libpython3.5m.so.1.0
[BOX64] Using native(wrapped) libexpat.so.1
[BOX64] Using native(wrapped) libm.so.6
[BOX64] Using emulated /tmp/_MEI12xyoq/_ctypes.cpython-35m-x86_64-linux-gnu.so
[BOX64] Using emulated /tmp/_MEI12xyoq/_bz2.cpython-35m-x86_64-linux-gnu.so
[BOX64] Using native(wrapped) libbz2.so.1
[BOX64] Using emulated /tmp/_MEI12xyoq/_lzma.cpython-35m-x86_64-linux-gnu.so
[BOX64] Using native(wrapped) liblzma.so.5
[BOX64] Using emulated /tmp/_MEI12xyoq/termios.cpython-35m-x86_64-linux-gnu.so
>>> Install files ...
install -b 115200
Install nuttx.spk
|0%-----------------------------50%------------------------------100%|
######################################################################

232432 bytes loaded.
Package validation is OK.
Saving package to "nuttx"
updater# sync
updater# Restarting the board ...
reboot
  • nuttx.spk の転送成功
  • パッケージ整合性チェック成功
  • フラッシュ書き込み成功
  • 自動リブート実行

書き込みは 正常終了

Spresenseの NuttShell (NSH) でアプリの実行

JetsonからSpresense の NuttShell (NSH) へ、
ターミナルで以下を実行する。

sudo minicom -D /dev/ttyUSB0 -b 115200

成功すれば NuttShell へ

Welcome to minicom 2.8

OPTIONS: I18n 
Port /dev/ttyUSB0, 04:43:39

Press CTRL-A Z for help on special keys


NuttShell (NSH) NuttX-12.3.0
nsh> 

nsh>

hello

実行結果

nsh> hello
Hello, World!!

これで完了

NuttShellの抜け方は Ctrl + A を押してすぐに X を押すと Leave Minicom? と出るので Yes で Enter でjetsonのターミナルに戻る。

Spresenceからカメラ撮影

Spresence HDR カメラボードでのカメラ撮影実行は

カメラボードをメインボードに差す。
参考

事前に exFAT でフォーマットしたSDカードを IoT拡張ボード に差せば画像を撮影した後に保存できるようになる。

nsh> camera

で結果が

nsh> camera
nximage_listener: Connected
nximage_initialize: Screen resolution (320,240)
Take 10 pictures as RGB file in /mnt/sd0 after 5 seconds.
 After finishing taking pictures, this app will be finished after 10 seconds.
Expire time is pasted. GoTo next state.
Start capturing...
FILENAME:/mnt/sd0/VIDEO001.RGB
FILENAME:/mnt/sd0/VIDEO002.RGB
FILENAME:/mnt/sd0/VIDEO003.RGB
FILENAME:/mnt/sd0/VIDEO004.RGB
FILENAME:/mnt/sd0/VIDEO005.RGB
FILENAME:/mnt/sd0/VIDEO006.RGB
FILENAME:/mnt/sd0/VIDEO007.RGB
FILENAME:/mnt/sd0/VIDEO008.RGB
FILENAME:/mnt/sd0/VIDEO009.RGB
FILENAME:/mnt/sd0/VIDEO010.RGB
Finished capturing...
Expire time is pasted. GoTo next state.

普通にcameraだけだとRGB形式で10枚連続撮影なので

camera -jpg 1
  • -jpg jpg形式の指定
  • 1 連続1枚

結果が

nsh> camera -jpg 1
nximage_initialize: Screen resolution (320,240)
Take 1 pictures as JPEG file in /mnt/sd0 after 5 seconds.
 After finishing taking pictures, this app will be finished after 10 seconds.
Expire time is pasted. GoTo next state.
Start capturing...
FILENAME:/mnt/sd0/VIDEO004.JPG
Finished capturing...
Expire time is pasted. GoTo next state.

これで撮影されSDカードに保存される

今回はカメラ位置を何度か調整し jetson orin nano を撮影した。
取得された画像が
VIDEO004.JPG

jetson orin nano のシルエットがなんとなく取得できた。
でも近すぎたかな...


最初の記事はSpresenceを初めていじってみたといった内容。想定外に長くなりました。
カメラから取得,保存された画像をUSB接続経由でjetsonに送ることはできなかった。

SpresenceSDKはSONYから参考ガイドが出ている

これ全部理解できたら低レイヤーのお仕事ができるレベルだそうです...

遠隔開発のためにとんでも無く難しいことに手を出してしまった...(SpresenceSDKがスゴイのは確か)

てか普通に anydesk 使えるPCとか用意してに繋げばここまで難易度がこじれなかったかも...(まあ、すぐにはできないな〜)

今回の記事は物が少ない金欠学生が役立ててください🙇

目指すは Spresence mini bot で microROS を使って自宅内巡回ボットを作ること。
今後もSpresence開発は継続して参ります。
今回の記事の内容は ChatGPT をはじめとしたAIチャットアプリを利用し開発しました。

ここまで読んでいただき、ありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?