衛星開発ゼミ 事前学習

WEEK 3

センサとの通信と
デバッグ

6軸 IMU「MPU6050」を AI のコードで動かし、AI が注意した2箇所(プルアップ・アドレス)をわざと間違えて、問題を特定するプロセスを身につける。

動かすAI と公式サンプルから始める
間違える注意書きの2箇所を踏み外す
特定する二分探索・観測(printf / オシロスコープ / ロジックアナライザ)・対照実験

0.1 前回の復習

今日使うのは I2C

  • 2本のバスに複数の相手。SDA(データ)と SCL(クロック)を全員で共有する。
  • アドレスで相手を選ぶ。応答は ACK(Acknowledge)で確認する。
  • バスの H はプルアップ抵抗が作る。オープンドレイン出力は L に引くことしかできない。
I2C のバス構成 — 2本の線に複数のデバイスがぶら下がる
I2C のバス構成(Week 2 の再掲)
Week3 センサとの通信とデバッグ02

0.2 今回の位置づけ

センサと通信=シリアル通信でセンサのレジスタを読み書き

Week 0電子工作の基礎
Week 1マイコンの原理・レジスタ
Week 2通信の規格
Week 3センサと波形観測
Week 4リアルタイムシステム
第1段階「要素技術と根拠のある設計」(Week 1〜4)— 今日はその3回目
  • 合宿にもそのまま通用する。模擬衛星の IMU(ICM-42688)が相手でも、今日の進め方は変わらない。
Week3 センサとの通信とデバッグ03

1

センサの中にも、番地の付いたレジスタが並んでいる

Week 1 の​​​「レジスタ=CPUと​​​周辺回路との​​​間の​​​掲示板」と​​​いう​​​モデルは、​​​
通信の​​​先に​​​ある​​​センサの​​​内部にも​​​そのまま​​​通用する。

マイコンの中
CPU(プログラム)
ポインタ経由
マイコン内のレジスタ番地に値を読み書き
ペリフェラル特別な周辺回路(GPIOやシリアル通信など)が動作する
センサの中
CPU(プログラム)
I2C/SPI 経由
センサ内のレジスタ番地に値を読み書き
測定回路専用のセンシング回路が測定結果をレジスタに書き込む
変わるのは経路だけ — 「番地に値を読み書きする」という形は同じ
Week3 センサとの通信とデバッグ04

1.1 シリアル通信の役割

通信の仕事は、センサのレジスタへ「番地」と「値」を運ぶこと

  • I2C の1回のやり取り=依頼と応答。「どの番地を」「読む/書く」の依頼を運び、応答を受け取る。
  • 模擬衛星も同じ。IMU(ICM-42688)のレジスタは I2C で、ADC(Analog-to-Digital Converter)の MCP3008 は SPI で読み書きする。
  • 運ばれているのは「番地と値」。経路が何であれ、この形は変わらない。
模擬衛星のシステム構成図
模擬衛星のシステム構成図。ICM-42688 は I2C、MCP3008 は SPI で Pico W とつながる
Week3 センサとの通信とデバッグ05

2

とりあえず動かす
 — 2つの​​​​​​​​​​方​​​法で​​​​​​​​​​「動く​​​​​​​​​​コード」を​​​​​​​​​​手に​​​​​​​​​​入れる

  • 題材は MPU60503軸ジャイロ+3軸加速度の6軸 IMU。資料とサンプルコードが豊富な定番。
  • 方法は2つ①:AI に書かせたコード。②:公式のサンプルコード。
  • 模擬衛星搭載品とは別の型番本番は ICM-42688 という別のセンサ。基本は同じ。
MPU6050 搭載モジュールの実写
今日の題材となる MPU6050 搭載モジュール
Week3 センサとの通信とデバッグ06

2.1 方法①:AI に書かせる

AI は、ほぼ動くコードと「注意書き」を返してくる

実際の会話:claude.ai/share/d543dcbd-ec47-445b-9d15-1811179875a6 (共有のため対話型の画面だが、開発時はエージェント型を使う)

AI との実際の会話のスクリーンショット(依頼と、返ってきたコード・注意書き)
依頼 「MPU6050をI2Cでpico sdkから
 動かすC言語のコードを書いて」
コード(だいたい動く) i2c_init、gpio_pull_up、mpu6050_reset、読み出しループ…
注意書き①プルアップ抵抗を確認
注意書き②アドレスは AD0 で変わる
(0x68/0x69)
Week3 センサとの通信とデバッグ07

2.2 方法②:公式サンプル

pico-examples にも MPU6050 のサンプルがある

mpu6050_reset();                                     // 起こして
while (1) {
    mpu6050_read_raw(acceleration, gyro, &temp);     // 読んで
    printf("Acc. X = %d, ...", acceleration[0]);     // 表示する
}

Raspberry Pi 公式サンプル集 pico-examples の i2c/mpu6050_i2c(概要):github.com/raspberrypi/pico-examples/tree/master/i2c/mpu6050_i2c

  • 骨格は3つだけ。「リセットして、読み続けて、表示する」。AI のコードもほぼ同じ構造になる。
  • 今回は方法①で進める。サンプルは複数種(Pico・Pico W・Pico 2・Pico 2 W)で動くように少し複雑なので、分かりやすいAIのコードの方で
Week3 センサとの通信とデバッグ08

2.3 動かす

一発で​動いた

  • コードは1行も変えていないビルドして書き込むだけ。
  • 数値が流れ、傾けると反応する
    シリアルモニタに計測値が流れ続ける。
ブレッドボード上の Pico と MPU6050 の実機配線
実機の配線 — Pico と MPU6050 をブレッドボードで接続
AI のコードを動かしたシリアルモニタの出力画面(正常に動作)
AI のコードを動かしたシリアルモニタの出力(正常に動作)
Week3 センサとの通信とデバッグ09

2.4 手元で​​​​​​​​再現入する​​​​​​​​:Wokwi

シミュレータでも実行可能

  • ブラウザだけで配線と実行Pico と MPU6050 を Wokwi 上で接続して動かせる。
  • ジャイロの値をスライダーで動かせる出力の変化を手元で確かめられる。
Wokwi で Pico と MPU6050 を接続したシミュレーション画面
Wokwi で Pico と MPU6050 を接続したシミュレーション画面:wokwi.com/projects/469939527447668737
Week3 センサとの通信とデバッグ10

3

とりあえず動いた。
では、注意された箇所を間違えていたら?

全て​​​一発で​​​動作させられるとは​​​限らない。​​​
AIも​​​人間も、​​​やってみて​​​動かなかったら​​​修正する、​​と​​​いう​​​プロセスを​​​踏む。

一発で動いたが…AI の注意書き2つは未回収のまま
実験① プルアップを間違える
実験② アドレスを間違える

3.1 準備①:疑う場所

疑う場所は、理解した経路の上に並んでいる

コード設定・引数
HALHardware Abstraction Layer
ペリフェラルI2C コントローラ
ピン機能の割り当て
配線・プルアップ電気の層
センサ中のレジスタ
この経路が、そのまま故障時に「疑う場所の一覧」になる — Week 2 で深掘りした理由の答え
  • 経路を知らないと、「動かない」は1個の大きな謎のまま。
  • 経路を知っていれば、疑う場所を具体化できる。
Week3 センサとの通信とデバッグ12

3.2 準備②:二分探索

中点で割って、候補を半分に減らす

線形探索 — 端から1個ずつ潰す

候補 1
候補 2
候補 3
候補 4
候補 5(原因)
候補 6

端から​​​1​個ずつ順に​​​調べる​​​ — 原因​に​​​届くまで、​​​候補の​​​数だけ​時間が​​​かかる

二分探索 — 中点で「そこまでは正しいか」を判定する

候補 1
候補 2
候補 3
中点で1回判定
候補 4
候補 5(原因)
候補 6
…前半分はまとめて除外
  • 二分探索に必要なのは2つ経路の順序を知っていること(対象の仕組みを知っていること)。中点で「分ける」手段があること。
  • 当てずっぽうとの違いは「計画」「どことどこを切り分けるか」を決めてから、手を動かす。
Week3 センサとの通信とデバッグ13

3.3 準備③:分ける手段

分割点に注目する「測定」、ノードに注目する「対照実験」

トップ事象:通信が動かない
前半に原因(コード側)
コード・HAL
ペリフェラル・ピン
後半に原因(電気側)
配線・プルアップ
センサ
測定 — 分割点に注目 分割点で「ここまでは正しいか」を道具で直接観測し、どちら側か決める。紹介する道具:printf・デバッガ・オシロスコープ・ロジックアナライザ
対照実験 — ノードに注目 仮説を1つ持ち、分割されたノードを1箇所だけ変えて比べる。
直れば原因、直らなければ他に原因。
Week3 センサとの通信とデバッグ14

4

実験①:プルアップを間違えてみる

内蔵プルアップの​​​有効化を​​​コードから​​​外す​(外部プルアップは​​​外してある)。​​​
バスを​​​ H に​​​戻す部品が​​​1つも​​​無くなる。

gpio_pull_up(...); を外す仕込み:バスの H を作る部品がゼロに
ターミナルに何も出てこない症状:手元にあるのはこれだけ

4.1 最初の分割

読み出しの失敗か、通信の失敗か

仮説A 読み出しの失敗

通信は生きている。 加速度の設定やデータの扱いに失敗している。 → 疑うのはコードの設定・値の変換。

仮説B 通信そのものの失敗

通信自体が成立していない。 経路の根本が壊れている。 → 疑うのは配線・電気信号・アドレス。
この2つを、1回で分けられる観測は何か?
Week3 センサとの通信とデバッグ16

4.2 分割の道具を探す

MPU6050 の公式資料は2分冊 — 探し物は「レジスタ」

Product Specification

MPU6050 Product Specification の表紙

概要、電気的条件、ピン配置、通信方法が載っている。

Register Map and Descriptions

MPU6050 Register Map and Descriptions の表紙

レジスタの番地と各ビットの意味が載っている。今日開くのはこちら。

Week3 センサとの通信とデバッグ17

4.3 分割点

WHO_AM_I(0x75)は、読むと必ず 0x68 を返す

① 一覧表で当たりをつける

MPU6050 Register Map のレジスタ一覧表

頭から​​​読まず、​​​目次 → レジスタ一覧​表とたどる​​​(Week 1 と​​​同じ​​​読み方)。​​​
一覧の​​​末尾近くに​​​ WHO_AM_I​(0x75)。

② 該当ページで確かめる

MPU6050 Register Map の WHO_AM_I の記載箇所

読むと固定値 0x68 が返る「答えの分かっている読み出し」。期待どおりなら経路の生存が1回で確定する。

Week3 センサとの通信とデバッグ18

4.4 道具①:printf

中の値と進行を、文字で外に出す

// 最初にWHO_AM_Iレジスタを読み、センサと正しく通信できているか確認する
uint8_t whoami = mpu6050_read_whoami();
printf("WHO_AM_I = 0x%02X (expected 0x68)\n", whoami);
  • 組み込みでもよく使われる観測手段ソフトウェアの実行状況をログに出せば二分探索が進む。
  • printf の中身は実はかなり複雑マイコンにおける printf の経路は UART だったり USB だったりする。ソフトウェアでの"文字列"の扱いも難しい。
  • 発展:デバッガSWD(Serial Wire Debug)をつなぎ、実行を止めて中を覗く道具がある。今日は紹介まで。
Week3 センサとの通信とデバッグ19

4.5 観測結果

答えが返ってこない — 通信そのものが失敗している

  • ターミナルに何も出てこないWHO_AM_I の結果の行が届かない。これ自体が観測情報。
  • 「呼び出しから戻らない」と考えられるエラー値が返るだけが失敗ではない。
    来ない応答を待ち続けて止まっている。
  • 原因が絞り込めた「読み出しと設定の扱い」側ではなく、通信側に原因があることが分かる。
  • 「ここまでは動く」を示す。今回は省略するが、本来は printf() が動作することは単体で検証が必要。
    printf() の動作不良か、応答待ちで到達しないのか切り分けも必要。
mpu6050_read_whoami()読み出しの呼び出し
応答を待ち続けて戻らない1バイトの往復すら成立していない
printf(...)この行に到達しない — 何も表示されない
Week3 センサとの通信とデバッグ20

4.6 発展

「読む」のシーケンスは、書くことから始まる

  • 1段目は WRITE。「これから読むのは 0x75 です」と番地を送る。
  • 電気信号を​​​見る
    ​​ — ソフトの​​​道具では、​​​ここから​​​先が​​​写らない
  • コードの並びの理由。i2c_write_blocking と i2c_read_blocking が並ぶのは、このため。
I2C レジスタ読み出しの2段のシーケンス
WHO_AM_I の番地 0x75 を WRITE してから、データ 0x68 を READ する2段のシーケンス
Week3 センサとの通信とデバッグ21

5

電気信号を​​​​​​見る​​​​​ — ソフトの​​​​​​道具では、​​​​​​ここから​​​​​​先が​​​​​​分からない

マイコンの中 — printf・デバッガで見える範囲
コード
HAL
ペリフェラル
観測の境界
マイコンの外 — ソフトからは見えない範囲
SDA・SCL の電気信号
配線・プルアップ
センサ
  • ソフト側の手がかりは「呼び出しから戻らない」だけ。コードにもログにも、SDA・SCL の上の信号は現れない。
  • 「はず」を確かめるには、信号を直接見るしかない。次の中点はマイコンの外 — 電気信号を測る道具を使う。計測器はキット外、今日はデモで見せる。
Week3 センサとの通信とデバッグ22

5.1 道具②:オシロスコープ

電圧の​​​変化を、​​​波形と​​​して​​​描画する

  • 見えるのは電圧の形波形の形、電圧レベル、立ち上がりのなまり。
  • デジタル信号の実体もアナログの電圧通信中なら、H と L を行き来する矩形波が見えるはず。
デモ機材の実写 — Pico と MPU6050、Analog Discovery 3 の接続
デモ機材の構成 — Pico と MPU6050 の間の SDA・SCL にプローブを当てる
Week3 センサとの通信とデバッグ23

5.2 観測

波形が全く立ち上がっていない

復習:オープンドレインとプルアップ(Week 2)

オープンドレイン出力とプルアップの回路

どの​​​部​​品も​​​線を​​​ L に​​​引く​​​ことしかできない。​​​
H に​​​戻す仕事は、​​​プルアップ抵抗だけが​​​担う。

実測:プルアップ無しの SDA・SCL

プルアップ無しのオシロスコープ波形(全く立ち上がらない)

立ち​上がりが​​​​​​​​​​​​無く、​​​​​​​​​​​​通信が​​​​​できていない。​​​​​​​​​​​​
「H を​​​​​​​​​​​​作る​​​​​​​​​​​​部品が​​​​​​​​​​​​無い」ことが​​​​​​​​​​​​波形に​​​​​​​​​​​​そのまま​​​​​​​​​​​​現れている。

Week3 センサとの通信とデバッグ24

5.3 対処

プルアップを​​​​戻すと​​​​波形が​​​​立つ 

ブレッドボード上に外部プルアップ抵抗 1kΩ を追加した様子
SDA・SCL に外部プルアップ 1kΩ を追加

無し

プルアップ無しの波形

全く​​​立ち​上がらない。​​​
通信は​​​成立しない。

内蔵のみ

内蔵プルアップのみの波形

動くが、​​​​​​​​​​​​立ち​上がりが​​​​​​​​​​​​遅く​​​​​​​​​​​​余裕が​​​​​​​​​​​​無い。​​​​​​​​
AIの​​​コードは​​​​​​​​​​​​この​​​​​​​​​​​​状態だった。

外部 1kΩ

外部プルアップ 1kΩ の波形

H へ​​​​​​​​​​​​引き上げる​​​​​​​​​​​​力が​​​​​​​​​​​​強い。​​​​​​​​​​​​
理想的な​クロック波形に​なった。

Week3 センサとの通信とデバッグ25

5.4 復旧

復旧した — ただし WHO_AM_I は 0x70、中身は MPU6500 だった

  • 通信は復旧固定値が返り、計測値も流れている。経路の生存確認としては成立。
  • 部品が偽物:WHO_AM_I = 0x70(期待は 0x68)0x70 は後継 MPU6500 の値。刻印は MPU-6050 でも、中身は別品種。Amazon のレビューにも同じ報告があった。
  • まとめ:デバッグの流れ症状 → 分割(WHO_AM_I・printf)→ 分割(波形) → 原因 → 復旧。
    中点を決めて、観測して、半分ずつ捨てた。
復旧後のシリアルモニタ出力(WHO_AM_I = 0x70 と計測値)
復旧後の出力 — WHO_AM_I = 0x70 (expected 0x68)
Amazon の商品レビュー「中身が6500でした」
Amazon の商品レビューにも同じ報告
Week3 センサとの通信とデバッグ26

6

実験②:アドレスを間違えてみる

AI の​​​​注意書きの​​​​2つ目​「アドレスは​​​​ AD0 で​​​​変わる」を、​​​​誤った​​​​ハード設計を想定​​​​して​​​​試してみる。​​​

AD0 ピンを設計と違う側(H)に配線仕込み:誤ったハード設計を再現
波形の形は正常なのに、読めない予想される症状
気づく方法を2つ試す測定と、対照実験

6.1 アドレスとは何か

0x68 はレジスタではなく、センサを呼ぶ「アドレス」

マイコン0x68 宛に依頼を送る
I2C バス — 住所で相手を選ぶ
センサ MPU6050 — 住所:スレーブアドレス 0x68(AD0=L)/0x69(AD0=H)
WHO_AM_I部屋番号 0x75
設定レジスタ部屋番号 0x6B など
計測値レジスタ部屋番号 0x3B〜
  • I2Cバス内の住所と、センサ内の部屋番号の2階層スレーブアドレス(0x68)=建物の住所。
    レジスタの番地(0x75 など)=建物の中の部屋番号。
  • AD0 ピンでアドレスを変更できる同じセンサを1本のバスに2個つなぐための仕組み。
    配線が想定と違えば、センサのアドレスが整合しない。
MPU6050 搭載モジュールの実写
MPU6050 搭載モジュール — AD0 ピンの配線でアドレスが決まる
Week3 センサとの通信とデバッグ28

6.2 仕込み

AD0 を H にすると、センサのアドレスは 0x69 になる

  • 想定はハード側のミスAD0 の配線が設計と違っていた、という状況を再現する。
  • 症状はまた「何も出ない」0x68 を呼び続けるコードは、WHO_AM_I を読めなくなる。
  • ソフト側からは区別がつかないプルアップ無しのときと、見える症状はまったく同じ。
AD0 ピンを H に配線したことで応答アドレスが 0x69 になり、0x68 への呼びかけに応答が無い状況
AD0=H で応答アドレスは 0x69 に。0x68 への呼びかけには誰も応答しない
Week3 センサとの通信とデバッグ29

6.3 道具③:ロジックアナライザ

デジタル信号の意味を解読する装置

  • I2Cのシーケンス(Week 2 の復習)START の後にアドレス7ビット+読み書き1ビット。
    9クロック目に受け手が ACK、応答が無ければ NACK。
  • ロジアナのプロトコルデコード機能ビット列を意味の層に変換して文字で並べる。
  • オシロはアナログ、ロジアナはデジタル電圧の形(なまり)は見えない。H/L の列と意味だけを見る。
ACK の拡大波形
ACK の拡大 — 9クロック目で受け手が SDA を L に引く
ロジックアナライザの正常時のデコード画面
正常時のデコード — 0x68 WR に ACK、番地、Re-Start、0x68 RD に ACK。WRITE → READ の2段がそのまま現れている
Week3 センサとの通信とデバッグ30

6.4 測定で気づく

0x68 へ呼びかけて、NACK — そのアドレスには誰もいない

  • NACK=9クロック目で誰も SDA を L に引かなかった「0x68 へ呼びかけ→NACK」が確認できる。
  • 波形は正常=電気の層は健全クロックは見えていて、アドレスが間違っているからACKが来ない。
NACK の拡大波形
NACK の拡大 — 9クロック目で誰も SDA を引かない
AD0=H の実機に 0x68 で呼びかけたときのデコード画面
AD0=H の実機に 0x68 で呼びかけたデコード — WR も RD も NAK で Stop
Week3 センサとの通信とデバッグ31

6.5 対照実験で気づく

アドレスを1箇所だけ変えて、結果を比べる

コードA そのまま

#define MPU6050_ADDR 0x68

現状の再現。動かないことを確かめる基準の側。

コードB 1箇所だけ変える

#define MPU6050_ADDR 0x69

仮説「アドレスが違うのではないか」に対応する変更のみ。

結果を比べる — 直れば「アドレスの不一致」と確定。直らなければ「原因は他にある」と分かる。どちらに転んでも切り分けが進む
  • 確かめ終わったら、設計としての正解に合わせて確定する。今回はハード側の誤りの想定なので、配線を直してコードは 0x68 に戻す。「動いたからそのまま」とは違う。
Week3 センサとの通信とデバッグ32

7

整理:切り分けの手段は2系統 — 測定と、対照実験

測定 — 中点で実際に起きていることを、道具で直接見る
printfマイコンの中の値と進行
オシロスコープ電気信号の形(電圧・なまり)
ロジックアナライザ信号の意味(アドレス・ACK/NACK)
対照実験 — 道具が無くてもできる
1箇所変えて比べる仮説と計画が前提
どちらも目的は同じ — 二分探索の中点で、候補を半分に減らす
  • 順序は観測が先、修正は後。対照実験の変更も「直すための変更」ではなく「分けるための変更」。当てずっぽうで修正するわけではない。
Week3 センサとの通信とデバッグ33

7.1 切り分け表

症状から、壊れた層を逆引きする

症状(波形を見る) 壊れた層 次に疑う場所
波形が立ち上がらない・崩れている今日の実験①(プルアップ無し)
電気の層
配線・プルアップ・ショートソフトをいくらいじっても直らない
波形は正常なのに NACK(応答が無い)今日の実験②(AD0 違い)
意味の層
アドレス・設定・相手の状態電気の層は問題なしと確定できる
Week 2 の「電気の層/意味の層」の2階建てが、そのまま切り分けの軸になる — デバッグでもレイヤー(仕組みの層)の理解が必要
Week3 センサとの通信とデバッグ34

8

進め方の教訓:少し作っては、動かして確かめる

一気に全部作って、最後に確かめる

作る
作る
作る
作る
確認

動かなかったとき、疑う範囲は「全部」

少し作るごとに、動作確認して足場を築く

作る
確認 ✓
作る
確認 ✓
作る

疑う範囲は、常に「直前の一歩」だけ

  • 確認が通った地点は「ここまでは正しい」という足場。配線1本、設定1つ、機能1つ。単位を小さく刻む。
    壊れてから観測点を探すのが二分探索なら、作りながら観測点を残すのがこの進め方。
Week3 センサとの通信とデバッグ35

8.1 ただし AI は一気に作れる

「一つずつ」と「一気に」— 任せ幅は対象の素性で決める

定番部品今日の MPU6050。
情報が厚く、一発でも動きやすい。
← 一気に任せる小さく確かめながら進む →

どこに置くかは設計判断 — 対象の素性で決める「つまみ」

初物・自作基板合宿の実機。
外れたら絞り込みは自分の仕事。
  • 一気に任せて動けば最速。動かなければ、今日のように切り分ける。
  • 初物ほど、小さく確かめる価値が上がる。AI の当たる確率が下がるぶん、観測点を残しながら進む。
Week3 センサとの通信とデバッグ36

9

まとめ:特定の​​​​​プロセスと​​​​​「動く​​​​​≠適切な​​​​​設計」

  • 特定のプロセス中点を決め、測定(printf・オシロ・ロジアナ)か対照実験で半分に割る。
  • 確実に動く設計内蔵プルアップで動いてしまっても、実機は外部プルアップ。
  • 合宿への接続実機 TOP 基板の ICM-42688 も I2C。
模擬衛星 TOP 基板の ICM-42688 まわりの実回路
模擬衛星 TOP 基板の ICM-42688 まわり
右側に R5・R6=1kΩの外付けプルアップ
Week3 センサとの通信とデバッグ37

9.1 宿題

身近な機械のトラブルを、どう調べるか — 手順書を設計する

経路の分解例:スマホ → ルーター → 回線 → プロバイダ
分割点を決める中点をどこに置くか
観測か対照実験か設定画面で見る/別のスマホで比べる
次の一手結果ごとの分岐まで設計する
  • 題材は自由。Wi-Fi ルーターにつながらない、リモコンが効かない、自転車のライトが点かない、など。AI に聞くのは前提。
Week3 センサとの通信とデバッグ38