はじめに
環境モニタリング用のLoRaデバイスをテストしていたとき、LCDに表示された湿度に違和感がありました。なんと、
湿度: 102.4 %RH
湿度が100%を超えることは結露など特殊な状況ではありえなくもないのですが、高湿度時に最大値として 102.4% が表示されるのは何かおかしい…。
今思えば、102.4%なんて明らかに2^10 = 1024 が絡んでるってわかるのですが、なぜか湿度の%だとそのことに暫く気がつきませんでした。
あるとき、ふと気になって、調べてみると、BME280センサーの補償演算から換算する際のスケーリングミスが原因だったことが分かりました。
この記事ではその内容と、正しい換算方法について解説します。
症状
- センサーで取得した湿度が 高湿度のとき "102.4 %RH" と表示される
- センサー値の上限として "1024" が使われている
- 表示形式は
float
ではなく、整数を10で割って表現(例:1024 → 102.4) - その他の値も、全体的に 実際より 2% ほど高く表示されていた (結果的に)
原因:Q22.10形式とスケーリングの誤解
BME280 の湿度出力は、Boschのドキュメントにある通り Q22.10形式(固定小数点)です。これはつまり:
湿度値 = 出力値 / 1024(単位:%RH)
したがって、出力値 47445
は次のように換算されます:
湿度 [%RH] = 47445 / 1024 ≒ 46.333 %RH
しかし、以下のように /100
をしていたコードでは:
uint16_t hum = raw_hum / 100; // 誤り
最大値 102400
→ 1024
→ "102.4 %"と表示されてしまうのです。
また、全体的に本来よりも約2%高い湿度が表示される結果となっていました。
この実装は、Bosch公式サイトで公開されている補正演算コードをそのまま使っている場合に起こりうる現象です。なぜなら、
- 気温や気圧の出力値は
/100
で正しく換算できる形式 - それに対して湿度だけが
/1024
という別のスケーリング係数を使う仕様
つまり、気温・気圧と同じ感覚で /1000
にしてしまうと湿度だけがズレる、という紛らわしさが原因のひとつでもあります。
気温と気圧は整数なのに、湿度だけが固定小数点だなんて・・・
修正方法:正しくは /1024
正しく換算するには /1024
でスケーリングする必要があります。
もし 0.1% 単位の整数値(例:562 = 56.2 %RH)として扱いたい場合は、
uint16_t hum10 = (raw_hum * 10) / 1024; // 小数1桁を保持
こうすれば、LCDなどへの整数出力もしやすくなります。
Before / After の比較
状態 | コード例 | 表示結果例 |
---|---|---|
❌ 誤実装 | hum = raw_hum / 100; |
最大で 102.4 %RH、高めに出る |
✅ 正実装 | hum = (raw_hum * 10) / 1024; |
最大で 100.0 %RH、実測値 |
学びと再発防止のためのチェックリスト
- センサーデータは 必ずデータシートの形式(整数/小数/固定小数点)を確認する
-
/100
や*0.01
のような "なんとなくそれっぽい係数" に注意! - 換算式の単位・ビット数・精度 を明示的にコメントに残す
- センサーからの生データを printf などで 必ず一度ログ表示する
おわりに
この換算ミス、組み込み開発では意外とあるあるな話です。ADCの値やセンサー出力をそのままスケーリングする際に、"見た目それっぽい" 値が出るという落とし穴に気づきにくいんですよね。
ただ、今回のような102.4%なんて数値は、組み込みソフトやってたら秒で気が付きそうなので、単に自分がアホだっただけというお話でした。
🎀「あなたの湿度表示が102.4%になっていたら、それはセンサーではなく ”コードが湿気ってる” かも…?」