はじめに
前回はカメラ・冷却ファン・スピーカーの接続とPiper TTSでの発話まで進めました。今回は、残りの部品(GC9A01丸型ディスプレイ・PCA9685サーボドライバ・SG90サーボ×2)を組み込んで、表情表示と首振り機構を作っていきます。最終的には「自作のパンチルト機構」から「100均のスマホホルダー」へ方針転換することになる、ちょっと遠回りした回です。
コードはGitHubで公開しています → Haradasn/baby-watcher
部品到着
GC9A01(丸型SPI液晶)、PCA9685(16ch PWMドライバ)、SG90マイクロサーボ×2が届きました。これで首振り+表情表示に必要な部品が揃いました。
配線図通りに一通り接続した状態がこちらです。Active Cooler・カメラ・GC9A01・PCA9685・SG90×2・スピーカーが見た目上はすべて繋がっていますが、この時点ではまだ何も動いていません。ここから、配線を一つずつ疑いながら潰していく地道な作業が始まります。
GC9A01のImportErrorにハマる
配線してすぐに動かしてみたところ、ImportErrorで落ちました。
from adafruit_rgb_display import gc9a01
adafruit-circuitpython-rgb-displayパッケージの中身を確認すると、実際のモジュール名はgc9a01a(クラス名もGC9A01A)で、gc9a01というモジュールは存在しませんでした。単純な綴り違いです。
さらにもう一つハマりどころがありました。このドライバはCS(チップセレクト)ピンをdigitalioで自前制御する作りになっているのですが、Raspberry Pi 5の/boot/firmware/config.txtでdtparam=spi=onとしていると、カーネル側のSPIドライバがCSピン(GPIO8/CE0)を専有してしまい、ドライバの手動制御と競合します。dtoverlay=spi0-0cs(CSピンをカーネルに渡さない設定)に変更して解決しました。
PCA9685のVCC配線を見落とす
配線図通りに繋いだつもりが、PCA9685が反応しませんでした。基板をよく見ると、PWM出力用の電源(V+)とは別に、ロジック用のVCCピンが独立してあることに気づきました。GC9A01のVCCで3.3Vのpin1を使用済みだったので、PCA9685のVCCはもう一方の3.3Vピン(pin17)に接続して解決しました。
サーボが動かない沼: USB-C PD充電器が原因だった
配線・コードともに合っているはずなのに、SG90サーボが一切動きませんでした。ここからしばらく迷走します。
最初に疑ったのは「PCA9685の電源入力(緑色のターミナルブロック)が壊れているのでは」という線でした。しかしここで試しに、Pi5本体のGPIOヘッダーにある5VピンからPCA9685に給電してみたところ、普通にサーボが動くことが判明。緑のターミナルブロック自体は壊れていませんでした。
では何が違うのか。切り分けていくと、USB-C PD(Power Delivery)対応の充電器 + 裸線タイプのUSB-Cケーブルの組み合わせが原因だとわかりました。PD対応の充電器は、CCピン経由できちんとネゴシエーションしないと5Vを出力しない仕様のものが多く、裸線ケーブル(CCピンのプルダウン抵抗が無い)だと充電器側が「何も繋がっていない」と判断して給電しないことがあります。
非PD(普通の)USB充電器、またはUSB-Aの電源に変えたところ、あっさり解決しました。POWER LEDが点灯し、サーボも問題なく動くようになりました。
見た目は「配線ミス」っぽいのに原因が電源アダプタの規格だった、というのは完全に盲点でした。
サーボでパンチルトを自作しようとする
ここからサーボ2個(パン・チルト)でカメラとディスプレイを振り向かせる機構を作ることにしました。最初は市販のパンチルトブラケットキットを検討し、Claude Codeのブラウザ操作機能(Claude in Chrome)にAmazonで候補を探してもらい、カートに入れるところまでやってもらいました。ただ配送が遅かったことと、プラ板で自作する方が安く・早く・自分のサイズに合わせられると考え、結局DIYすることにしました。
3D CADでの設計
平面図だけでは組み上がりのイメージが掴みにくかったので、Claude Code上でOpus(サブエージェント)と相談しながら3D CADモデルを作ってもらいました。最初はPythonのmatplotlibで描画していたのですが、ここで地味に厄介なバグに遭遇しました。
- 一番下にあるはずの土台が、一番手前(視点に近い側)に描画されてしまう
- 描画順を下から上に並べ替えても直らない
Opusエージェントに原因調査を依頼した結果、mplot3dのAxes3Dはデフォルトでcomputed_zorder=Trueになっており、これが自前の描画順を上書きしてしまうことが判明。computed_zorder=Falseを指定することで解決しました。matplotlibの3D描画は「正しいZバッファ」ではなく、パーツごとに1つの代表深度値で前後関係を決める簡易的な処理だと知らなかったので勉強になりました。
それでも立体感の表現には限界があったため、途中からthree.js(WebGL)ベースの描画に切り替えました。こちらは本物の深度バッファを持つので、パーツ同士の前後関係で悩むことがなくなりました。
設計を詰めていく過程では、何度もOpusに「パーツが互いにめり込んでいる」「補強材が宙に浮いている」「軸とプレートがズレている」といった修正を依頼しました。一つ直すと、また別の箇所で同じ種類のズレが見つかる、という繰り返しで、正直「AIに3D CADを任せれば一発でキレイに組み上がる」というようなものではありませんでした。Opus自身は座標計算が正しいはずだと報告してくるのですが、実際にスクリーンショットを目で見ると部品同士が貫通していたり、取り付け穴の位置がボディの中心からズレていたりと、座標の数値だけでは気づけない食い違いが何度も見つかりました。最終的には、角度を振った複数のスクリーンショットを目視するのに加えて、JavaScriptでパーツ同士のバウンディングボックスの接触判定を機械的に行わせる検証に切り替えてから、ようやく安定して不具合を洗い出せるようになりました。平面の図面と違って、立体の組み合わせの整合性を「コードと数値だけ」で正しく検証するのは、AIであっても一筋縄ではいかないのだと実感した部分です。
それでも最終的には、各パーツの正確な寸法・ネジ穴位置(SG90の実機datasheetに基づくφ2.2mm・穴間隔29.0mm)まで落とし込んだ型紙を作成するところまでは辿り着きました。
方針転換: 100均のスマホホルダーを使う
型紙まで用意したところで、改めて「これをプラ板から正確に切り出して、軸をズレなく組み立てる」という後工程の大変さを考え直しました。そこで思いついたのが、100円ショップのスマートフォンホルダーです。使ったのはダイソーのスマホホルダー(車内用)です。
車載用などに売っているクランプ+ボールジョイント式のホルダーは、ちょうど良いトルクと保持力を標準で備えています。プラ板を正確に切り出して軸を合わせる作業がまるごと不要になり、見た目も意外としっかりしています。土台はプラダン(プラスチック段ボール)で自作しました。
最初はカメラをクランプに固定し、ディスプレイだけをサーボで動かす構成にしていましたが、「カメラ自体が動かないと意味がない」ことに気づき、カメラとディスプレイを同じブラケットに乗せて、サーボの出力軸(ホーン)側に固定し直しました。さらに土台の中にもう1個サーボを埋め込んで、左右(パン)の回転も追加しています。
試行錯誤の過程で、カメラのリボンケーブルの取り回しの都合でカメラを上下反転させて取り付け直したり、サーボのホームポジション(正面の基準角度)がズレていたのを物理的に付け直したりと、細かい調整が何度も必要でした。このあたりは実機合わせの泥臭い作業そのもので、設計図だけでは分からない部分です。
まとめ・次回予告
今回は、GC9A01・PCA9685・SG90の配線トラブル(ドライバ名の誤り、VCC配線漏れ、USB-C PD充電器問題)を解決した後、パンチルト機構を自作しようとして3D CADで設計・型紙まで作ったものの、最終的には100均のスマホホルダーを使う方針に転換し、実際にカメラとディスプレイが物理的に動く状態まで組み上げました。
次回は、この構成で見つかったソフトウェア側の問題(カメラの画角が勝手にズームされていたバグ、動きを追い続ける追跡機能の実装、顔検出の導入、しゃべり方と表情表示のチューニング)についてまとめます → 次回: ソフトウェア仕上げ編
参考
- 本プロジェクトは個人のPoCであり、実際の乳児の安全監視を代替するものではありません
- 使用モデル: Claude Code / Sonnet系(ソフトウェア実装・デバッグ)、Claude Opus(3D CAD設計相談)








