TT Lab
はじめる
学ぶ 学習パス コース

冷蔵庫が255°Cだと言い張る

冷蔵庫が255°Cだと言い張る

TT Labで続きを見る

一言でいうと

センサーが送ってきた2バイトは、まだ温度ではありません。バイト順・符号・単位を説明できて初めて、その数字を信じられます。

なぜ必要なのか

冷蔵庫が255°Cだと言い張ります。実際に過熱していると、すぐに断定することも、表示のバグだとして無視することもできません。今回の話は、合成した故障の状況です。まず、生のバイト、変換規約、出力単位を分けて再現します。誤った値がどの境界で生じたのかを探す練習であり、実際の冷蔵庫の制御・安全装置を設計する過程ではありません。

C言語の関数・ポインター・構造体の基礎を知ったうえで始めてください。関数は、結果を戻り値1つにすべて入れません。戻り値は成功かどうかで、温度は出力ポインターに書きます。失敗したときに以前の値が残っていても、今回の呼び出しが成功したわけではありません。呼び出し側は、ステータスコードと値を一緒に扱う必要があります。

どう動くのか

今回のTMP102の温度レジスターの変換は、上位バイトを先に受け取ります。通常モードは12ビット、拡張モードは13ビットの2の補数で、1カウントは0.0625°Cです。2バイト目のbit 0でモードを区別します。詳しいビット配置は、公式データシートの表6-8・6-9を確認してください。

ラボでは、浮動小数点の代わりに、マイクロ摂氏の整数を使います。1°Cは1,000,000、1カウントは62,500です。小数点を切り捨ててから単位を変えると、小さな負の値や分数の値が消えます。まずカウントを正確に求め、最後に単位を変えます。

通常モードの0x19 0x00は25°C、0xff 0xf0は-0.0625°Cです。0xffを符号なしの温度255としてそのまま表示するのは、バイトと物理量を混同した例です。12ビットの数で符号ビットが立っていたら、正の整数として読んだカウントから4096を引けば済みます。拡張モードでは、この幅が変わります。負の数の右シフトに頼らず、明示的に復元する理由は、C言語の実装による差を減らすためです。

予約ビットが立っている入力は、この課題ではSENSOR_FORMATで拒否し、出力はそのままにします。これは課題の有効入力ポリシーであり、すべてのセンサーに共通する一般規則ではありません。ヘッダーsensor.hの関数宣言とステータスの列挙型を、先に読んでください。main関数は検査ツールが提供するので、提出ファイルには2つの関数だけを実装します。

手で変換してみて、コードの仮説を立てる

次の表は、計測値ではなく、変換規約から作った計算例です。まず紙でカウントを求めてから、最後の列と比べてください。マイクロ摂氏の列は単位の付いた整数で、3桁区切りのカンマは省略しています。

2バイト モード 符号を復元したカウント マイクロ摂氏
0x19 0x00 通常 400 25000000
0x0a 0x10 通常 161 10062500
0xff 0x50 通常 -11 -687500
0xff 0xf0 通常 -1 -62500
0x4b 0x01 拡張 2400 150000000

3行目を解いてみましょう。バイトを結合した0xff50から下位4ビットを除くと0xff5、つまり4085です。この値は、12ビットの符号境界2048以上なので、4085−4096=−11です。これに62,500を掛けると−687,500、摂氏では−0.6875°Cになります。先頭のバイトだけを読んだり、摂氏の整数で先に割ったりすると、この小さな負の値が消えます。5行目は、下位のbit 0が1なので、3ビットを除かなければなりません。モードのビットだけを確認してシフト幅をそのままにすると、同じバイトを別の温度として解釈します。

Cでの符号の復元は、演算する型まで含めた約束です。シフトした非負のカウントは最大8191なので、int32_tに収まります。この範囲で、先に符号付きの変数に移してから4096または8192を引けば、負の数を明示的に作れます。逆に、unsignedのまま先に引くと、大きな正の数に戻ります。その結果を後でsignedに変える方法に頼らないでください。完成したカウントの絶対値は最大4096なので、62,500を掛けた結果もint32_tの範囲内です。途中の計算と最終的な保存の両方で範囲を確認する習慣が重要です。

次に、反例を作ります。表の0x0a 0x10を逆に読むと0x100aになり、今回の通常モードの予約ビットのポリシーにも反します。一方、0x00 0x00は、順序を逆にしても変わりません。したがって、「0が出た」というテストと、「順序が合っている」というテストは同じではありません。通常の入力を選んだ理由と、その入力では区別できない欠陥を、一緒に書いてください。

現場での姿

再現レポートには、画面の数字だけでなく、生のバイト・モード・出力単位を残します。バイト順が間違っているコードも、一部の値では偶然合います。0だけをテストすると、順序を入れ替えたコードと正しいコードが区別できません。そのため、正の数・0・小さな負の数・境界・予約ビットまで分けて見ます。

表現できる数と、物理的な動作範囲も違います。拡張エンコーディングで150°Cの計算が合っていても、実物のTMP102がその温度で動作することを保証するわけではありません。分解能が細かいことも、測定精度がそれだけ良いという意味ではありません。

続けて確認すること

すぐ続くクイズでは、計算の順序と反例を確認します。その後、失敗・時間の契約を読み、最後のモジュールの累積Cラボに進みます。ラボのステップ1–3でsensor_decodeを実装し、正の数の全範囲、負の数の全範囲、2つのモードとエラー入力を順に検査します。コンパイラーの警告も先に解決し、表のいくつかの値だけをハードコードしないでください。