HOME > 技術談話 > PIC microcontroller > 温湿度センサSHT11(試食) 

はじめに 温湿度センサ 回路図例 実験中 サンプルプログラム 動作例 温湿度センサの概要 汎用ライブラリ 
サンプルプログラムの構成 CRC演算 物理量変換 運用を考える 


■はじめに

 昨年のことですが、宝箱に眠っていた温湿度センサを利用して7セグメント表示方式の温湿度計を作りました。

 PICマイコン、シフトレジスタ、トランジスタアレイ、そして温湿度センサを組み合わせています。

 7セグメントLEDを利用し、左3桁で温度、右3桁で湿度を表示します(湿度は整数部のみ)。

 表向きにはスッキリ部品が並べられていますが、表示部に7セグメントLEDを利用しているために基板裏側は…裏面は手配線のワイヤが「みっしり」と(汗。

 配線面を基板で隠しているのは仕様です。

 温湿度センサには「 SHT11(Sensirion社製)」を利用しています。このセンサは動作電圧範囲が広く、誤差の少ない校正済みの測定結果をデジタル値で取得することができます。そして何よりも「相対湿度」を取得できるところがポイントです。

 相対湿度を測定する方法はいくつも有りますが、大抵の場合、多くの部品と微調整が必要になります。手段はともかく、最終的に
正しい値を示すか?がポイントになります。温度であれば安価なデジタル温度計と比較する方法が採れますが、湿度の場合は比較対象の選定が難しい。

 これらの課題を解決するためにSHT11を選択しました。値段は若干高いですが手間がかかりません。湿度センサ自体は数百円から存在しますが、実装と調整の手間を考えると数時間で相殺されます。相殺バランスは作成台数、部品単価に依りますが、手間のかからない便利なセンサであることは確かです。


 さて、今回のテーマでは紹介した温湿度計は…作成しません。 … 配線で心が折れそうです(本当)。
 (次回以降の課題とします。恐らく気圧センサでも使用したテキスト液晶パネルを利用する予感)

 温湿度計として作成されたプログラムはモジュール化されているものの、その場限り、環境依存の構成でした。C言語で記述されていても、ポートアクセスがソースプログラムに記述されていては移植も困難です。

 そこで、温湿度センサーをアクセスする部位をリメイクし、試食版として公開します。
 目標は
マイコンを問わないライブラリ」の構築です。

 センサ自体は何年も前に発表されたものですが…あまり気にしないことにします(汗

 相変わらず進捗は遅いかも…。そのような場合は「つぶやき」をチェックしてみてください。  
 途中経過やホームページの更新タイミングで何かしら独り言をつぶやいてます。

 注意事項 

 SHT11はSensirionn社の製品です。
 公開するサンプルプログラム、回路図は弊社独自の任意掲載でありメーカー未承認です。

 今時の表現としては「温湿度センサー」なのかな?「プリンター」、「モーター」とかと同じで。
 3文字以上の後ろにつく「ー」は書かない様に教えられた世代なので「温湿度センサ」になってますが御容赦。

 本ページでは以後、「相対湿度」を単に「湿度」と略します。

■温湿度センサ

 センサ単独の写真を撮り忘れたので上で紹介した写真を拡大しています。
 変換基板にはんだ付けされている小さなパッケージがセンサ本体です。

 センサの端子は1.27mm間隔です。そして見慣れたはずの「足」がありません。
 データシートによれば「LCC(リードレスチップキャリア)」という形状です。
 はんだ付けに工夫が必要ですが、表面に回り込まないようにすれば大丈夫です。

 ピン付きパッケージでSHT7xという種類も有りますが、お値段少し高くなります。

 この温湿度センサの入手先は以下になります。リンク切れの際はトップページから移動して下さい。
 ・ストロベリー・リナックス Sensirion 1チップ温度・湿度センサ[SHT-11] \2,200- (2010/08/03現在)
 今年3月から変換基板をサービスしています(過去に購入した私は貰えず orz)。
 SHT71も参考までにどうぞ。ただしピン間1.27mmです。となると、変換基板付きSHT11の方が便利かもしれません。

 データシートの入手先は以下になります。日本語資料、サンプルプログラムも有ります。
 ・SENSIRION AG スイス本社 「Humidity Sensors Download Center」の項に英文資料があります。
 ・センシリオン株式会社 日本法人 「カタログ・資料リスト」の項に英文と和文の資料があります。

■回路図例

 試食版では「PIC16F648A」を使用します。
 このPICマイコンには汎用入出力ポートが16個あり、DC3.0V以上、内蔵クロック4MHzで動作します。
 温湿度センサSHT11の試食にしては汎用入出力ポートが多いですが、プログラム容量
4Kワード確保できます。

 図面が縮小の関係で見難いですね。図面をクリックすると別ウィンドウで表示します。

 温湿度センサSHT11は回路図右側に配置しています。必要なのは電源と通信線2本です。
 ストロベリー・リナックスさんから変換基板を貰えた方、ピン配置がずれるので注意して下さい。

 温湿度センサへのアクセス状況は随時TXD端子からシリアル通信で出力しています。このTXD端子をRS232Cレベル変換することでパソコン等でモニタすることができます。

 試食版として「高分解能モード」と「低分解能モード」を用意しました。電源投入時に「RA5端子」を読み出して動作モードを決定します。なお運用中は切り替え不可です(プログラム都合)

 未使用端子が多いですが、基本は出力ポート設定でオープンとしています。
 この未使用端子の中でもRA0〜RA3、RA6、RA7は動作状況をモニタすることのできる端子として利用しています。

■実験中

 ブレッドボードで実験中。
 温湿度センサは温湿度計で動作しているモジュールを利用しています。

 左下、白のジャンパ線が高分解能モード、低分解能モードの切り替え用で利用します。
 運用中に切り替える事が無いのでVCC/GNDへの直結です。

 ブレッドボード下部に伸びる橙色、青色のラインはTXDになります。
 青色のラインの先には別に用意したRS232Cレベル変換基板に接続されています。

 電源電圧は DC3.3V を供給しています。 電圧は温度データに影響を与えるので注意して下さい。

■サンプルプログラム

 サンプルプログラムを公開します → ShtDemo010x.zip 
 サンプルプログラムを公開します → ShtDemo0101.zip 
 開発環境は MPLAB IDE V8.40 と HI-TECH C V9.70 を利用しています。 注意事項 

 
2010.11.16 Ver01.01 TX端子を入力設定にする件。見た目の変化はバージョン番号のみです。

 HI-TECH C v9.70 で作成されたプログラムを v9.81 以降のコンパイラで再コンパイルする際の注意点
  → 開発環境による修正 2011/03/09

 サンプルプログラムは本家サイトのデータシートとSampleCodeを参考にしていますが、SampleCodeで満足できなかったので作り直してフル機能を実装したイメージです。「マイコンを問わないライブラリの構成」を目指したので助長的な個所がありますが御容赦願います。

 プログラム容量が気になりますが、温湿度の物理量変換、文字列表示も含めた状態で、
 ・CRC演算無し … 3495word
 ・CRC演算有り … 3060word
です。
 サイズが大きい要因は開発環境がLite版であること、表示のためにデータを編集している点が挙げられます。

 ライブラリ本体の必要容量は、CRC演算有りで約1900word、CRC演算無しで約1500word位です。必要プログラム容量の多くを物理量変換に費やすので、高性能マイコンを利用すれば、よりコンパクトになります。なにせ今回利用したマイコンは8ビットの加減算を駆使して4バイト加減乗除を行っていますので。。

 今回は物理量演算式に従っていますが、別の方法を利用すると高速で変換することもできます(後述)。

 メイン処理では総てのコマンドを使用しています(ヒーター等の特殊な設定を除く)。
 測定タイムアウト監視以外は通信系のチェックを厳密に行っているのですが、過保護だったかもしれません(汗

■動作例

(1)高分解能モード

 RS232C変換基板を経由してパソコンのハイパーターミナルでj動作状況をモニタしました。測定間隔は2秒です。
 高分解能モード故、計測開始から計測終了までの時間が見えます。 … 要はゆっくり。ということ。

(2)低分解能モード

 動作モードを切り替えてのモニタ結果です。
 単語のイメージ通り分解能は低下しますが、高分解能モードに比べて高速に計測を行います。

■温湿度センサの概要

(1)データシート

 温湿度センサSHT11には日本語データシートがあるので詳細についてはデータシートを確認願います。
 データシートは以下より入手することができます。
 ・センシリオン株式会社 「カタログ・資料リスト」の項に英文と和文の資料。

 丁寧に記述されているので追加の解説は不要と思いますが、気になる箇所だけ追記します。

(2)基本性能

 温湿度センサの基本性能を下表にまとめます。

項目 説明
動作電圧 3.3V(2.4V〜5.5V)
供給電流 測定中:0.55mA〜1mA、休止中:0.3uA〜1.5uA、平均:2uA〜38uA
温度 測定範囲 -40℃〜+123.8℃、精度±0.4℃(SHT11の標準値、測定域で異なる)
分解能 高分解能モード:0.01℃、低分解能モード:0.04℃
データ長 高分解能モード:14bit、低分解能モード:12bit
湿度 測定範囲 0%〜100%、精度±3.0%(SHT11の標準値、測定域で異なる)
分解能 高分解能モード:0.05%、低分解能モード:0.4%
データ長 高分解能モード:12bit、低分解能モード:8bit
通信方式 デジタル2線式インタフェース(IIC風の半二重通信方式、1対1接続)

 温湿度センサ起動時は高分解能モードです。低分解能モードへの切り替えは専用のコマンドを利用します。
 温度、湿度で動作モードは共通です。温度が高分解能モードなら湿度も高分解能モードになります。

 接続のためのインタフェースは2本だけなのでPICマイコンを始めとし、多くのマイコンに簡単に接続できます。
 通信方式はIIC通信に似ていますが互換性はありません。他のIIC通信デバイスとの同時接続はできません。

 動作電圧が広く、そして必要ポート数が少ないので、マイコンの種類を問わず利用することができると思います。

(3)マイコンとの接続

 基本的にはDATA信号線、SCK信号線の計2本をマイコンのポートと接続すれば完了です。

 DATA信号線は双方向通信になります。
双方向通信では短絡(一方がHigh、他方がLow)厳禁です。
 DATA信号線はマイコン側のオープンドレイン形式ポートに接続することが理想です。ですが確保できない場合、オープンドレイン形式が定義されていない場合は、出力 L、入力モード(Hiz状態)で代用します。どちらの方法もDATA信号にプルアップ抵抗が必須です。これは出力 L 以外の状態に切り替えたときに信号線の状態を H とするためです。

 このDATA信号の扱いはIIC通信に似ていますが、実情は異なります。温湿度センサにはアドレスを示す情報が無いこと、測定完了をDATA信号で通知することから、マイコンに割りつけられたDATA信号は唯一の温湿度センサとだけ接続します。またマイコン側にIIC制御コントローラがあっても当該機能は利用できません。

 PIC16F648Aはオープンドレイン端子をサポートしますが、今回の実験では通常構成の出力ポートを後者の方法で制御します。

(4)DATA信号線の扱い

 データシートを見ると文章と図が絶妙(?)な表現をしていますが、基本的には、
 ・SCK信号が L でDATA信号を変更する。
 ・SCK信号が H で読み取る。
という動作の繰り返しになります。このルールはマイコン側、温湿度センサ側で共通の基本ルールです。

(4)−1 マイコンから温湿度センサへ

 SCK信号はマイコンに制御されるのでDATA信号の変化開始点はマイコン側の任意時点です。

(4)−2 温湿度センサからマイコンへ

 温湿度センサ側はSCK信号を制御できないのでDATA信号を変化させるタイミングが難しくなります。これはマイコン側の制御でSCK信号が H に移行するタイミングを予想できないからです。
 そこで温湿度センサはSCK信号の立下りエッジを基準にDATA信号線を変化させます。なお測定完了直後の最初の1ビットは例外です。SCK信号 L 期間中にがDATA信号が L に変化します。

 結果的にマイコン側の操作とセンサ側の操作が衝突する期間が発生します。ですが、前述のハードウェア構成ルールを踏襲していれば短絡状態は発生しません。ルールに従えばDATA信号線を「L」にした情報が優勢になります。

(5)SCK信号の動作周波数

 DATA信号の読み取りタイミングを制御するSCK信号の動作周波数の標準値は0.1MHzです。
 最大値は動作電圧により異なるので注意して下さい(3.3Vでは1MHz)。反対に最小値は0MHzです。

 今回の試食ではPICマイコンを4MHzで動作させています。この場合、1命令の基本処理時間は1usなので、SCK信号のオンとオフを交互に繰り返しても0.5MHzが限度です。実際の処理では付帯処理が加わるのでSCK信号の動作周波数は遅くなる一方です。反対に20MHzで動作させた場合は意識して遅延命令を加えた方が良いと思います。

(6)測定時間

 温度、湿度の測定は分解能に応じた待機時間が必要です。
 データシートに記載されている測定時間と実測時間は以下の通りです。

対象 分解能 仕様 実測
温度 14bits(高) 320ms 210.0ms
12bits(低) 80ms 60.8ms
湿度 12bits(高) 80ms 60.8ms
8bits(低) 20ms 14.4ms

 データシートは余裕をもった数字としても、実測でも同じ12bit長の測定時間が同じである事に少し驚きました。

 実測値は確かに早いのですが、タイムアウト処理を上位関数で作成する場合はデータシートに基づいて時間設定をした方が無難です。時と場合によりますがデータシートに基づく時間の1.5倍程度をタイムアウト時間に設定します。

 なお、読み出し操作の中でもステータスレジスタの読み出し操作は待機不要です。

■汎用ライブラリ

(1)ライブラリの構成

 温湿度センサSHT11ライブラリはミドルウェアの位置付けです。
 温湿度センサSHT11ライブラリはハードウェアドライバが提供するポートアクセスのための関数、もしくはマクロを利用して信号制御を行います。
 ハードウェアドライバを入れ替えれば他のPICマイコン、もしくはPICマイコン以外のマイコンで動作します。

 温湿度センサSHT11ライブラリは3つのファイルで構成されます。
 ユーザが行う作業は定義情報(DrvSht.u)を変更するだけです。プログラム(DrvSht.c)、公開情報(DrvSht.h)を編集する必要がありません。ユーザの作業でプログラムを触らない…このあたりは経験上の話ということで。

 アプリケーションを作成する場合は公開情報(DrvSht.h)をインクルードすればOKです。

ファイル名 修正 内容
DrvSht.c 不要 プログラム本体(コマンド制御、物理量変換、信号制御)
DrvSht.h 不要 関数のプロトタイプ宣言、定数宣言
DrvSht.u 必要 信号制御手法、遅延時間、診断有無を対象システムに合わせて宣言(カスタマイズ)

(2)関数の種類

関数名 処理内容 ステータス 温度測定 湿度測定
DrvShtInit 初期設定(装置起動直後に実行) 必須 必須 必須
DrvShtReset デバイスハードウェアリセット
DrvShtPutSts ステータスレジスタ書き込み
DrvShtGetSts ステータスレジスタ読み出し 推奨
DrvShtReqTmp 温度測定開始
DrvShtReqHum 湿度測定開始
DrvShtIsReady 測定経過取得
DrvShtGetMeas 測定結果取得
DrvShtCnvTmp 温度データの物理量変換(0.1単位) 任意
DrvShtCnvHum 湿度データの物理量変換(0.1単位) 任意
DrvShtDiagStatus 受信データの信頼性確認:ステータス
DrvShtDiagMeas 受信データの信頼性確認:温度、湿度

 基本的には作業対象に対して「必須」と「○」の部分の関数を実行すれば情報を得る事ができます。「△」の関数は障害発生時の復旧には欠かせません。運用使用等の条件によっては「必須」になる場合がります。

 温素測定を開始した場合は測定経過の取得〜測定結果の取得を一連の動作として行ってください。湿度測定時も同様です。温度測定と湿度測定を同時に行うことはできません。

 受信データの信頼性を確認する場合は、測定結果の取得に続いて呼び出しを行います。複数の測定結果に対して信頼性確認を行うことはできません。

 入出力パラメータや関数の詳細、戻り値の扱いについてはサンプルプログラムを参照願います。

 通信系のリセット手続き(接続リセット、通信開始)が関数として記述されていませんが、レジスタアクセス、測定開始関数の中で無条件に行われます。


 簡単な温度測定の例を以下に載せます。事前に初期設定が完了している場合を想定しています。
 通信エラー確認処理を含まないコードは非常にシンプルです。

(3)ユーザ定義ファイル

 温湿度センサSHT11ライブラリのプログラムは固定されたシンボル、関数名を利用せずにハードウェアアクセスを行います。これは仮の名前で処理を行っていることになるので、ユーザ定義ファイル(DrvSht.u)に実体を宣言することでコンパイル時に置き換えを行います。

 ユーザ定義ファイルで指定する実体の内容は以下の通りです。使用例はサンプルプログラムを参照願います。
シンボル 内容 説明
mShtSckH 関数 SCK信号をH
mShtSckL 関数 SCK信号をL
mShtDataH 関数 DATA信号をH(マイコンによっては入力モード切り替え兼用)
mShtGetData 関数 DATA信号をL
mShtSckWait 関数 SCK変化エッジ後に補てんする遅延時間(実力次第、省略可能)
mShtLibAddUW 関数 符号なし4バイト型加算
mShtLibMulUW 関数 符号なし4バイト型乗算
mShtLibDivUW 関数 符号なし4バイト型除算
SHT_VDD 定数 温湿度センサ動作電圧(mV)
SHT_CRC_DIAG 定数 CRC演算を行うか否かを指定(利用は任意)
mShtLibBitRev 関数 バイト内ビット列反転(CRC演算を利用する場合は必須
SHT_DEBUG 定数 シミュレーションデバッグ用(通常0)

 関数指定の箇所はハードウェアをアクセスする直接命令を指定することもできますが、情報の結合力が強くなるので、処理時間やスタックの問題が無いのであれば関数呼び出しにした方が何かと便利です。

 DATA信号は双方向通信で利用されます。制御の際は信号の衝突に注意して下さい。理想はオープンドレインタイプのポートを制御することですが、出力モードL,入力モードにより信号線を制御する方法も有ります。

 4バイト演算は物理量変換で参照されます。プログラム容量制限の厳しいマイコンでも演算ができるように外部の関数を参照しています。またアドレスをパラメータにすることで、関数呼び出し時のオーバーヘッドを最小にしています。

■サンプルプログラムの構成

 サンプルプログラムは温湿度センサSHT11ライブラリを繰り返し呼び出して測定と物理量変換を行います。
 複雑なことはしていませんが ライブラリの機能を総て利用、かつ異常系の処理を総て実施しているのでコーディングが助長的ですが、簡略化すると以下の流れになります。

 SCK信号はL、DATA信号は信号線レベルでHになるよう初期設定します。

 デバイスリセットにより温湿度センサSHT11はディフォルトの状態(高分解能モード、ヒータオフ)に戻ります。

 切り替え可能な分解能モード切り替え信号を電源投入時に読み出し、ステータスレジスタ設定を行います。設定後は読み出し、照合を行っています。

 一度の測定で1つの測定結果を得る事ができます。専用のコマンドを送信するとセンサ側はビジー状態に遷移します。このビジー状態は測定完了により解除されるので、このタイミングで測定結果を取得します。

 連続測定を行うことができますが、測定を短期間で繰り返すとセンサ自体の温度が上昇するので注意して下さい。

■CRC演算

(1)はじめに

 温湿度センサSHT11には通信データの信頼性を確保するためCRCを付与します。
 演算多項式は x8+x5+x4+1 で加算結果によるチェックサムよりも強力にエラーを検出することができます。
 (2010.09.19追記:日本語マニュアルの演算式は間違っています。英文マニュアルに合わせました)

 …

 CRCチェックの導入により処理速度、プログラム容量の面で不利ですが、CRC演算が成立することでデータの信頼性が向上する共に問題が発生した場合の原因の切り分けに役立ちます。

 汎用ライブラリでは定義情報(DrvSht.u)の指定によりCRCチェックの実行可否を指定することができます。
 お勧めできませんが処理速度、プログラム容量が厳しい場合はCRCチェックを行わない指定を選択します。

 
注意:汎用ライブラリではCRCチェックを行わない指定をしてもCRCデータは取得します(演算のみ省略)。

 CRC演算は汎用ライブラリ側で処理するものの、計算の仕方を覚えておくと何かと便利です。特にCRC演算を省略設定した場合は電卓片手に検算を行う必要があるので、演算の仕方を一通り確認しておくことを勧めます。

(2)演算手法

 以下のページでCRC演算の方法について日本語マニュアルを得る事ができます。丁寧に解説されています。
センシリオン株式会社 「カタログ・資料リスト」の項に英文と和文の資料。

 マニュアルでは「ビット方式」と「バイト方式」が紹介されています。資源の厳しいマイコン(PICマイコンは該当する?)では「ビット方式」を勧めていますが、今回作成した汎用ライブラリでは「バイト方式」を採用しています。

 アセンブラでビット操作命令駆使すれば確かに「ビット方式」が有利なのですが、C言語等の高級言語でプログラミングした場合は処理時間が長く、プログラム容量が大きくなる可能性が高いです。「バイト方式」では256通りのバイトテーブルを必要としますが、その演算手法は非常にシンプルです。バイトテーブルを作成するのは手間ですが、C言語等の高級言語との相性は良いと思います。

(3)演算対象

 CRCデータは「ステータスレジスタ読み出し」、「温度測定」、そして「相対湿度測定」のコマンド利用時に取得することができます。CRC受信の前にNOACKを指定した場合はCRCを受信できなくなるので注意して下さい。

 多くの場合、通信データのチェックサムは電文単位(送信、もしくは受信)で演算を行いますが温湿度センサSHT11ではマイコンからの送信データも含めてCRCデータを生成します。この時、ACK/NOACKの各ビットは演算に含めません。

 演算の対象範囲を以下に示します。

 演算の際に注意しなければならないのは「初期値」です。

 温湿度センサSHT11起動時の状態は 0x00 を適用できるのですが、ステータスレジスタの値を書き換えた場合は、書き換えた値を適用します。測定分解能で「低分解能モード」を設定した場合は要注意です。

 例えば、低分解能モードを設定する場合はステータスレジスタ書き込みでは 0x01 を指定します。するとCRC演算用の初期値は 0x80 になります。このルールを考慮しないとCRC演算は成り立たないので注意して下さい。

 可変の初期値を持つことは助長的です。制御する側は温湿度センサSHT11が現時点でどのような状態であるかを常に意識していなければなりません。ですが、この方法を採用することで温湿度センサSHT11だけが何らかの要因でディフォルト状態に戻ったか否かを区別することができます(測定結果の値だけでは区別がつかない)。

 なお、温湿度センサSHT11をディフォルト状態で使用している場合は初期値 0x00 のままなので区別はつきません。

(4)バイト演算変換表

 アプリケーションノートに掲載されているバイト演算で使用する変換表を16進数表記で置き換えました。
 表示にMSゴシックフォントを使用して等幅にしましたが、乱れる場合はサンプルプログラムを参照願います。

//.0 ...1 ...2 ...3 ....4 ...5 ...6 ...7 ....8 ...9 ...a ...b ....c ...d ...e ...f
0x00,0x31,0x62,0x53, 0xc4,0xf5,0xa6,0x97, 0xb9,0x88,0xdb,0xea, 0x7d,0x4c,0x1f,0x2e, // 00
0x43,0x72,0x21,0x10, 0x87,0xb6,0xe5,0xd4, 0xfa,0xcb,0x98,0xa9, 0x3e,0x0f,0x5c,0x6d, // 10
0x86,0xb7,0xe4,0xd5, 0x42,0x73,0x20,0x11, 0x3f,0x0e,0x5d,0x6c, 0xfb,0xca,0x99,0xa8, // 20
0xc5,0xf4,0xa7,0x96, 0x01,0x30,0x63,0x52, 0x7c,0x4d,0x1e,0x2f, 0xb8,0x89,0xda,0xeb, // 30

0x3d,0x0c,0x5f,0x6e, 0xf9,0xc8,0x9b,0xaa, 0x84,0xb5,0xe6,0xd7, 0x40,0x71,0x22,0x13, // 40
0x7e,0x4f,0x1c,0x2d, 0xba,0x8b,0xd8,0xe9, 0xc7,0xf6,0xa5,0x94, 0x03,0x32,0x61,0x50, // 50
0xbb,0x8a,0xd9,0xe8, 0x7f,0x4e,0x1d,0x2c, 0x02,0x33,0x60,0x51, 0xc6,0xf7,0xa4,0x95, // 60
0xf8,0xc9,0x9a,0xab, 0x3c,0x0d,0x5e,0x6f, 0x41,0x70,0x23,0x12, 0x85,0xb4,0xe7,0xd6, // 70

0x7a,0x4b,0x18,0x29, 0xbe,0x8f,0xdc,0xed, 0xc3,0xf2,0xa1,0x90, 0x07,0x36,0x65,0x54, // 80
0x39,0x08,0x5b,0x6a, 0xfd,0xcc,0x9f,0xae, 0x80,0xb1,0xe2,0xd3, 0x44,0x75,0x26,0x17, // 90
0xfc,0xcd,0x9e,0xaf, 0x38,0x09,0x5a,0x6b, 0x45,0x74,0x27,0x16, 0x81,0xb0,0xe3,0xd2, // a0
0xbf,0x8e,0xdd,0xec, 0x7b,0x4a,0x19,0x28, 0x06,0x37,0x64,0x55, 0xc2,0xf3,0xa0,0x91, // b0

0x47,0x76,0x25,0x14, 0x83,0xb2,0xe1,0xd0, 0xfe,0xcf,0x9c,0xad, 0x3a,0x0b,0x58,0x69, // c0
0x04,0x35,0x66,0x57, 0xc0,0xf1,0xa2,0x93, 0xbd,0x8c,0xdf,0xee, 0x79,0x48,0x1b,0x2a, // d0
0xc1,0xf0,0xa3,0x92, 0x05,0x34,0x67,0x56, 0x78,0x49,0x1a,0x2b, 0xbc,0x8d,0xde,0xef, // e0
0x82,0xb3,0xe0,0xd1, 0x46,0x77,0x24,0x15, 0x3b,0x0a,0x59,0x68, 0xff,0xce,0x9d,0xac, // f0


 なぜかアプリケーションノートは10進数表記なんですよね。16進数に慣れている人からすると見難いです。


 10進数表記を16進数表記に置き換える場合は手作業による変換ミスが怖いです。今回は専用ツールを作成するのではなく、10進数表記ままソースプログラムに張り付け、コンパイルを行って得られるリストファイルから16進数表記を抽出しました。

 そう言えば…。何年も前の知人の話ですが、ソースプログラムを紛失した(消去?)プロジェクトがありました。その時は電子媒体のリストファイルからソースプログラムを再構築したそうです。別のプロジェクトでは「電子媒体が存在しない」事件があり、印刷したリストを人海戦術で再入力したそうです。力技ですが復活できれば笑い話ですね。

(5)バイト演算例

 冒頭に掲載した「動作例」に通信データが含まれますが、このデータを使ってCRCデータの検算を試みます。

 バイト演算の演算方法は、
 ・演算中の値に通信データを排他的論理和し、得られた結果に対応する変換表の値を新たな演算データとする。
です。この演算をCRCの前のデータまで繰り返し、最後に演算データのビット位置を反転すれば照合値になります。


 まずは、高分解能モードでステータスレジスタ読み出しを行った場合を検証します。

演算中 通信データ 排他的論理和 変換表置換 その他
0x00 0x07 0x07 0x97 初期値は0x00
0x97 0x40 0xd7 0x93 演算終了。ビット位置反転で 0xc9


 続いて、低分解能モードで温度測定を行った場合を検証します。
 注意すべき点は初期値の状態。低分解能モードのステータスレジスタの値は 0x01 なのでこれを 0x80 にします

演算中 通信データ 排他的論理和 変換表置換 その他
0x80 0x03 0x83 0x29 初期値は0x80
0x29 0x06 0x2f 0xa8
0xa8 0xa0 0x08 0xb9 演算終了。ビット位置反転で 0x9d

 動作例では数値を大文字表示しています。90ではなく9D(0x9d)ですのでご注意を。書いてて間違えました(汗

■物理量変換

(1)はじめに

 温湿度センサSHT11では取得した温度、湿度の各データを専用の変換式で演算すると身近な値の形式(℃や%)に変換することができます。これを物理量変換と呼びます。

 物理量変換するときに使用する変換係数は温湿度センサSHT11の出荷ロット(製品バージョン)により異なりますが、データシートによれば相互に利用できる旨が記述されています。

 なお、
汎用ライブラリでは古い物理量変換式(V3)を利用しています。これは係数の値に関係します。

 湿度の測定結果は 25℃ を大きく外れる場合、温度補償を行わなければなりませんが、今回作成した汎用ライブラリでは演算を省略しています。必要な場合は別途外部プログラムで作成する必要があります。

(2)物理量変換の前に

 いきなりの算数で恐縮ですが、物理量変換で用いる変換式には以下の式が用いられることが多いです。
 いわゆる二次関数「風」ですが、違いは c=0 の場合があります。

  
y = a + bx + cx2  … cx2 を使用しない場合は c=0 が適用される。この場合グラフは直線です。

 各要素が変化した場合のグラフの変化具合を以下に載せます(簡単なグラフ…絵ですが御容赦)。

 左のグラフ、変換係数 b は分解能を示すことになります。
 中のグラフ、変換係数 a はマイナス値に適用されることが多いです(測定データが符号なしの場合)。
 右のグラフ、変換係数 c は微調整に用います。曲線を描画しますが変化量は意外と大きいです。

 デジタル値で計測できるセンサであれば y=a+bx を理想としますが、温湿度センサSHT11の場合は微妙に変換係数を指定しないと値を求める事ができません。温度の様にマイナス値がでる場合は仕方ありませんが、湿度の場合は物理量変換式をフルに活用して確度を高めています。

(3)物理量変換係数

 物理量変換で利用する変換係数は以下の通りです。
値についてはデータシートで再確認願います
 なお、湿度の温度補償の演算、華氏(F)については今回未使用なので除外します。

 まず温度データの物理量変換式です。微妙に係数が変化しています。

  T = d1 + d2 * SOT … SOTは測定された温度データです。直線グラフになります。

係数 因子 V3 V4 備考
d1 VDD=5.0V -40.00 -40.1  センサ電源電圧により基準位置が変わります。
 電圧差による変動は1Vあたり0.25℃以下です。
 計算式を変えると0.1℃程度の差が生じます。
VDD=4.0V -39.75 -39.8
VDD=3.5V -39.66 -39.7
VDD=3.0V -39.60 -39.6
VDD=2.5V -39.23 -39.4
d2 高分解能(14bits) 0.01 0.01  係数がそのまま分解能に対応します。
低分解能(12bits) 004 0.04

 続いて湿度データの物理量変換式です。これもまた係数が変化しています。

  RHlinear = c1 + c2 * SORH + c3 * SORH2 … SORHは測定された湿度データです。直線グラフではありません。

係数 因子 V3 V4 備考
c1 高分解能(12bits) -4.0000 -2.0468  見慣れないと迷いますが…。
 1.5E+3 = 1.5 * 10 * 10 * 10 = 1500
 1.5E-3 = 1.5 * 1/10 * 1/10 * 1/10 = 0.0015

 -2.8000E-6 = -0.0000028 です。
c2 0.0405 0.0367
c3 -2.8000E-6 -1.5955E-6
c1 低分解能(8bits) -4.0000 -2.0468
c2 0.6480 0.5872
c3 -7.2000E-4 -4.0845E-4

 測定データは有限の数です。測定対象、分解能に応じて最小値、最大値が決まります(算術数値的な範囲)。

対象 因子 最小値 最大値 備考
温度 高分解能(14bits) 0 16383  0x0000〜0x3FFF
低分解能(12bits) 0 4095  0x0000〜0x0FFF
湿度 高分解能(12bits) 0 4095  0x0000〜0x0FFF
低分解能(8bits) 0 255  0x0000〜0x00FF

(4)物理量変換式の実装

 前述の変換係数を見ると一目瞭然、基本は実数演算です。実数演算式でプログラミングしても良いのですが…。

 汎用ライブラリでは実数演算を整数演算に置き換えて演算を行っています。求める値は小数点以下第2位を四捨五入し、小数点以下第1位まで求めています。関数を利用する際はビットの重みづけに注意して下さい。

 参考までに、整数演算を利用することで約1Kワード程度のプログラム容量を節約できました(PICマイコンの場合)。
 整数演算手順については…。根が深いので汎用ライブラリ内にコメントを参照願います。

 汎用ライブラリでは古い物理量変換式(V3)を利用しています。これは変換係数の仮数部の有効桁数に起因しますしています。整数演算を行う際に桁あふれが起きない条件を考えると古い物理量変換式(V3)が有利なのです。


 補足:プログラム容量が厳しいマイコンへの実装(チラシの裏の裏?)

 物理量変換のためにプログラム容量を必要とする演算が必要です。高性能なマイコンであればマイコンが備える乗除算を利用できますが、ローコストマイコンでは乗除算を加減算で実現します。1バイト加減算しかないマイコンでは大変です。シフトに置き換える?これもまた大変な場合が多いです。

 今回の物理量変換する場合、温度データは2バイト演算、湿度データは4バイト演算が必要です。双方の演算が存在する状態において温度データは比較的高速に演算できますが…。ここが注意点。高速でも、たまにしか呼び出さなくても、一度でも利用するのであればプログラム容量に反映されてしまいます。

 そんな時は湿度データで利用する4バイト演算を関数化して共用します。要は温度データも4バイト演算にしてしまうことです。欲を言えばパラメータの取り扱いも最適化。値として渡すのではなくポインタで渡す。ももちろん演算速度は犠牲になります。

 プログラム作成時、高速化を目標とするのは理想ですが、プログラム容量がパンクしたら成果はゼロです。そこで速度を犠牲にする。それも作業を遠回りすることでプログラム容量の削減を図ります。

 汎用プログラムでは古い物理量変換式(V3)を整数演算で処理しています。最終的に得られる結果は小数点以下第1位まで…。力を入れている割には最終結果は無難なところに落ち着いています。幸か不幸か(計算づくですが)演算途中では値の切り捨てや丸めこみはありません。演算式に忠実で正統派っぽい動作をしています(笑

 もし実数演算で乗り切るのなら…。そうですね、今回のケースでは単精度演算を利用すると桁落ちが発生すると思います。精度を求めるなら倍精度演算をお勧めします。

 少しだけ朗報。本ページ後半でプログラム容量削減の方策を検討します(少々お待ちを)。

(5)温度データ用の物理量変換を考える

 温度データの物理量変換について考えます。

 新旧物理量変換式を比較すると傾きが同じで基準点が異なるだけで、双方共に綺麗な直線グラフを描きます
 傾きは同一なので任意の測定データから得られる値の差は同一であり、かつ0.1℃位です。

 小数点以下第1位を四捨五入して小数点以下第1位までを表示する様な使い方であれば、新旧物理量変換式の違いはそれほど気にする必要はないと思いますが、最終判断は「用途」でしょうか。

 さて、センサ電源電圧ごとに設けられた基準点に相当する d1 の値をグラフにしてみました(X=0 の温度に相当)。

 横軸がセンサ電源電圧、縦軸が d1 になります。残念ながら電圧に対する直線性はない様です。
 古い物理量変換式(V3)の3.0V時の係数には無理がある?心の目で保管すると 0.1℃くらい上の様な気もします。

 昨今の電子機器としては3.3Vという電圧を利用する機会が多いのではないでしょうか?ですがデータシートを確認しても3,3Vに対応する係数は定義されていません。その割には温湿度センサSHT11の製品出荷時のテストは3.3Vを利用しています。これは非常に残念です。

 サンプルプログラムは 3.3V が指定されても動作するように細工していますが、係数としての定義が無いので近似値を利用しています。ここで指定する値は単に「ズレ」として現れるだけです。その違いも 0.1℃程度の範囲なので、単に温度を見る用途であれば近似値の利用でも問題は無いと思います。

(6)湿度データ用の物理量変換を考える

 湿度データの物理量変換について考えます。

 新旧物理量変換式をグラフで表現しました。横軸は測定値、左軸は湿度、右軸は差分(V3-V4)です。

 まずは高分解能モード。あまり違いは見られませんが、V4の方が直線に近いです。

 続いて低分解能モード。似たり寄ったりでした。

 どちらの分解能も新しい物理量変換式(V4)を利用すると、より直線に近い結果が得られます。

 さて。どうなんでしょう? 客観的な湿度「これが相対湿度50%である」という環境を測定しないと、どちらの物理量変換式が優れているのか判明しません。この辺りはメーカーさんの校正結果を信用するしかないですね。

 …

 無難なのは高分解能モードでの測定結果を演算することでしょうか?どっちつかずで恐縮です orz
 けどけど、古い物理量変換式(V3)でもいい感じで結果を得られます(と、自己フォロー)。

(7)おまけ

 そう言えば1つ気になることがあります。
 物理量変換式の中で「c3 * SORH2」って演算の中でどれくらい貢献するんでしょうか?

 気になったのでグラフを描画してみました。まずは高分解能モード。値が2000で湿度65%位になります。

 続いて低分解能モード。

 想像以上の「ヒネリ」が加わります。
 新旧物理量変換式で「ヒネリ」に差がありますが「c2 * SORH」の演算が加わるので最終結果は大差ないです。

■運用を考える

(1)はじめに

 温湿度センサSHT11は非常に高性能なセンサーですが、実運用ではいくつかの検討しておきたい事項があります。
 本章では運用における留意事項とその対策「案」について考えてみます。

(2)測定分解能のまとめ

 測定分解能の指定により測定可能な最少単位、測定時間が変わります。

測定モード 測定対象 ビット長 測定分解能 測定時間
高分解能 温度 14bits 0.01℃ 320ms
湿度 12bits 0.05%RH 80ms
低分解能 温度 12bits 0.04℃ 80ms
湿度 8bits 0.40%RH 20ms

 上表における測定時間はデータシートに記載されている値ですが個体により前後する場合があります。
 測定時間にはコマンド送信、測定データ受信のための時間は含まれていません。

(3)測定分解能の選択

 装置の動作仕様、マイコンの性能に応じて測定分解能を選択します。

 例えば温度表示が1℃単位のシステムで高分解能モードを使用するのは宝の持ち腐れです。ですが、温度情報を保持して後日分析するのであれば高分解能モードが有利です。つまり測定データの最終的に行き着く先を基準に測定分解能を選択します。必要とする分解能の2倍以上の測定分解能を選択することが理想です(better)。

 悩ましいのは、温度は高分解能モード、湿度は低分解能モードという組み合わせです。
 混在利用は可能ですが、測定前にステータスレジスタの再設定を行う必要があり少々面倒です。

 大は小を兼ねる。いい言葉です。センサの機能をフルに使えますが、この辺りは利用するマイコンの性能と相談して下さい。少なくとも情報量が増える事により演算量や記憶域のサイズが増えます。

(4)待ち時間の対応

 測定分解能モードに関わらず、測定開始から終了までに時間を要します。

 待ち時間が数十μsの場合は他の処理を行うよりも「その場」で待機していた方が効率が良いです。ですが測定時間に 20ms〜320ms 要するので「その場」で待機する方法はあまりにも非効率的です。

 1つの選択肢として待ち時間を少なくするために測定分解能を落とす。これも1つの選択肢ですが、それでも大きな時間です。そこで測定待ちの間に他の処理をサービスする様な処理構成を考えます。

 マルチタスクOSを搭載していれば処理の優先度次第で待ち時間を利用することができますが、ローコストマイコンでは資源不足のために採用は厳しいです。その様な場合は「状態遷移」という方法を利用してみてはどうでしょう?

 例えば、湿度測定という関数を作成し、状態に応じて処理内容を遷移します。

 湿度測定という機能を1つの関数に閉じ込めます。

 状態により行うべき処理を限定し、条件が満たなければ次の状態に遷移せず、処理を抜けるように細工します。

 待機 … 条件付き遷移
 測定開始条件を確認し、条件が満たされた場合のみ状態を「開始」へ切り替えます。

 開始 … 無条件遷移
 センサに測定開始コマンドを送信して状態を「確認」へ切り替えます。

 確認 … 条件付き遷移
 センサの状態を確認し、測定完了を認識した場合のみ状態を「取得」へ切り替えます。

 取得 … 無条件遷移
 センサから測定データを取得し、物理量変換を施します。状態は「待機」へ切り替えます。

 状態により処理時間がばらつくので他の処理との兼ね合いを確認するのをお忘れなく。

(5)異常系の確認

 コマンド送信時のACK認識、CRCデータの確認は行う方がベターです。処理時間やプログラム容量の関係で確認を行わないケースも有りますが、基本方針として確認をすることを前提でプログラムを設計して下さい。

 ぜひとも確認したいのは低分解能モードにおけるCRCデータです。

 マイコンからセンサに対して低分解能モードを設定し運用を行うと仮定します。この運用中に何らかの要因でセンサ側が再起動した場合はディフォルト状態である高分解能モードに切り替わります。この状態が発生した以後も運用を継続した場合、マイコンは測定データ単独の情報からモードの切り替わりを判断することが困難なのです。

 この問題を回避するためにセンサ側はCRCデータの演算初期値にステータスレジスタの値を引用しています。マイコン側が低分解能モードであることを前提にCRCデータを確認すればセンサ側の再起動を確認することができます。

 理想を言えば測定時間も確認対象です。利用可能な信頼性確認手段はできる限り利用することが望ましいです。

(6)測定間隔

 データシートによれば例えば12bit精度の測定ならば最高でも毎秒1回の測定にするよう記載されています。

 なるべく短周期で測定結果を得たいと思う気持ちはわかりますが、ここはぐっとこらえましょう。

 今回掲載したサンプルプログラムでは温度、湿度を連続して測定した後、2秒待機するようにしています(物理量変換や通信時間が必要なので、実際には延長方向)。ですが温度と湿度の関係をみると測定間隔は短いです。温度と湿度を別物と考えた構成でしたが、実際にシステムを構築する際は温度と湿度の測定間隔も空けた方が無難です。

 ただ…1秒周期が2秒周期になったからといって情報の激しい変化はないと思いますよ。実際。

(8)物理量変換プログラム容量の削減

 物理量変換で実数演算を利用するため、どのマイコンを利用しても比較的大きなプログラム領域が必要になります。

 今回のサンプルプログラムではプログラム容量が少ないPICマイコンを利用しましたが、実数演算を実装したらプログラム容量がパンク。ということもあります(実話)。マイコンによっては2バイト乗除算を備えた種類も有りますが、それでも実数演算は厳しいです。

 そんな時は実数演算を整数演算に置き換えることで演算に関わるプログラム領域を削減することができます。PICマイコンでの実験になりますが2Kワード要していた演算処理が1Kワード程度で済む場合がありました。

 難点は実数定数の値(演算上は整数に置き換えている値)を容易に変更できなくなる事です。特に仮数部の桁数が増えた場合は整数演算で最適化した部分のオーバーフローに注意が必要です。

 サンプルプログラムに実装した汎用ライブラリでは実数演算の整数化を行っていますが、古い物理量変換式(V3)を利用しています。これは仮数部の桁数に起因します。詳細については前述の「物理量変換」の項を参照願います。

(9)物理量変換の高速化

 物理量変換の実数演算を整数演算に置き換えたとしても多くの処理時間を必要とします。

 温湿度の更新周期は秒単位での作業と思いますが、物理量演算に処理時間を引っ張られる(他の処理がサービスされなくなる)事も考えられます。特にスイッチのチャタリング除去等の定期的に行う処理を併用した場合は死活問題(おおげさですが)です。

 物理量変換を高速に行う…。逆の発想ですが処理時間に対する対策を行わず、むしろ処理時間を延ばします。

 具体的には演算処理を分割して呼び出します。例えば処理時間を要する4バイト演算が5件あれば処理を5つに分けます。そして他の処理のサービス具合を見ながら時間をかけ、処理を順番に呼び出して最終的な結果を得ます。この方法により見かけ上の負荷を軽減することができます。


 サンプルプログラムに実装した汎用ライブラリは物理量演算を一括で行う方法だけでなく、分割する方法も用意しています。処理時間が気になる場合は分割された関数を利用してみてはいかがでしょう?


 もう1つの高速化の方法は演算結果を事前に予測することです。
 難しく書いてしまいましたが、測定データは有限の種類を持ちます。予め表計算ソフトを利用して演算結果を求め、その値を初期化済み配列(定数配列、プログラム領域に配置されるデータ)に埋め込みます。そして測定データをキーとして唯一の測定結果をダイレクトに参照します。これ以上は無いという位に高速に結果を求める事ができます。


 個々の要素構成は同一である必要はありますが、値の扱い(小数点以下第1位まで等)については任意です。

 固定長データの連続になるので、小数点以下の情報が多いほどプログラム容量を多く消費します。

 左図では湿度を例にしました。実運用では高分解能、低分解能のどちらか一方の初期化済み配列で十分です。

 ただし…

 この方法は非常に高速ですが、初期化済み配列のためにプログラム容量を多く必要とするので、プログラム容量に余裕がある場合に利用して…

 諦めるのは早いです。

 例えばの話です。非常に複雑な演算を必要とする湿度データですが、表示上は整数部しか使わない事の方が多いと思います。すると 0%〜100% の101通りしか情報を必要としません。ここがポイントです。

 表計算ソフトで予め演算結果を求めるのは前述の話と同じですが、湿度の一の位の変化点に対する測定データを初期化済み配列に準備します。都合101個の要素が用意されると思います。後は測定データが何番目の要素に対応するか順番に検索すれば最大101回の検索で演算済みの湿度を得る事ができます。


 個々の要素構成は測定データのビット数に依存します。

 左図では湿度を例にしました。高分解能モードであれば個々の要素は16bit、低分解能モードであれば8bitで十分です。

 湿度の測定データを #0 の要素と逐次比較して、何番目の要素の範囲に含まれるかを順番に検索します。最終的に得られた要素番号が湿度の値になります。

 ただしこの方法。小数点以下第1位まで必要な場合、要素数は一気に10倍になるのでご注意を。

(X)まとめ

 価格の安い湿度センサは、周辺部品の扱いや制御、そして校正作業が非常に大変です。

 今回使用した温湿度センサSHT11は校正済みのデジタル値を簡単に得る事が出来るので非常に便利です。何万台も量産する機器に使用する場合は部品コストがネックになりますが、個人で利用する場合、少量生産する場合は多少価格が高くても校正作業が不要な分、メリットがコストを上回ります。

 ピン数の少ないPICマイコンでも十分に制御できるので(プログラム容量に注意)、単体で動作させるだけでなく、別の温度測定装置、湿度測定装置の比較用の補助装置としても利用できると思います。
あくまでも補助です。

 冒頭で温湿度計を作った際の写真を載せましたが、1台作っておくと何かと便利です。

(Y)おまけ

 やっと思い出しました。湿度計の校正方法。

 飽和した塩化ナトリウム(いわゆる食塩)溶液を密閉空間に閉じ込めておくと空間の湿度は75%になります。他の成分の飽和溶液でも同様の事(湿度は異なる)ができるのですが、塩化ナトリウムの場合は温度に対する依存度が少ないようです。この方法、葉巻やワイン保管庫に取り付ける湿度計の調整に使われることがあり、調整キットも販売されています(最初なんで校正できるのか不思議でした)。

 JISでも定義された方法なので「飽和塩法」をググると幸せになります。
 今回の温湿度センサSHT11は調整不要ですが、頭の隅入れておくと後で役立つかもしれません。

 この方法は湿度が安定するまで24時間位は覚悟して下さい。まぁ、放置ですけどね(汗


Copyright 2010,2011 PaletteSoft LLC. All rights reserved. 利用条件 | HOME | サイトマップ | お問合せ