今回は温度・湿度センサです。以前作成した7セグメントディスプレイに温度と湿度を切り変えて表示する回路になっています。前回使用した温度センサとは違い、今回は校正済みの温湿度センサです。なので、電圧や抵抗をそれほど気にしなくても、正しい温度や湿度を取得することが可能です。PICと温湿度センサの通信はシリアル通信になっています。
回路図およびプログラムに関する各種詳細は、以下の記事を参考にしてください。
1.今回使用するPICについて
今回使用するPICは「PIC12F1822」です。
2.回路
2.1 電子回路図
2.2 電子回路の写真
2.3 回路説明
2.3.1 使用するパーツ一覧
パーツ名 | 使用数 |
---|---|
PIC12F1822 | 1 |
温湿度センサ(DHT11) | 1 |
タクトスイッチ(温度・湿度切り変え用) | 1 |
2.3.2 PICの配線
PICのピン | 接続 |
---|---|
VDD | 5[V]電源 |
RA0 | シリアル通信(TxD:送信) |
RA1 | -未使用- |
RA2 | 温湿度センサ(DHT11) |
RA3 | -未使用- |
RA4 | -未使用- |
RA5 | タクトスイッチ(温度・湿度切り変え用) |
VSS | グランド |
3. 温湿度センサの使い方
温湿度センサから温度と湿度を取得する方法を説明します。
3.1 接続
今回使用する温湿度センサ(DHT11)のシリアル通信ポートはオープンドレイン(ウィキペディア)となっています。なので、接続するPICのピンをプルアップに設定する必要があります。今回はPIC側はオープンドレインでなくても通信できるようにしています。プログラム方法は4章を参照してください。
3.2 通信方法
温湿度センサから温度と湿度を取得するための通信方法を説明します。
3.2.1 起動直後の待ち
温湿度センサは起動直後(電源投入後)、1秒間待たなくてはいけません。この待ち時間の間、どのような信号も送ってはいけないので注意してください。
3.2.2 PICから温湿度センサへの開始信号
温湿度センサ(DHT11)が取得した温度と湿度をPICに送信してもらうには、PICから送信信号を出さなくてはいけません。PICが送信する信号は以下の通りです。
- PICが、信号をハイからローにする
- PICが、ローの状態を18[ms]以上維持
- PICが、信号をローからハイにする
3.2.3 温湿度センサからPICへの開始信号
PICから開始信号を受け取った温湿度センサは、PICへデータの開始信号を送信します。温湿度センサが送信する開始信号は以下の通りです。
- 温湿度センサが、信号をハイからローにする
- 温湿度センサが、ローの状態を80[μs]維持
- 温湿度センサが、信号をローからハイにする
- 温湿度センサが、ハイの状態を80[μs]維持
- 温湿度センサが、データを送信開始
3.2.4 温湿度センサからPICに送られてくるビットデータについて
温湿度センサからPICへビットデータが送られてきます。データサイズは40ビットになります。0ビットと1ビットの判断方法を説明します。
<ビットデータが0の場合>
- 温湿度センサが、信号をハイからローにする
- 温湿度センサが、ローの状態を50[μs]維持
- 温湿度センサが、信号をローからハイにする
- 温湿度センサが、ハイの状態を26~28[μs]維持
<ビットデータが1の場合>
- 温湿度センサが、信号をハイからローにする
- 温湿度センサが、ローの状態を50[μs]維持
- 温湿度センサが、信号をローからハイにする
- 温湿度センサが、ハイの状態を70[μs]維持
ビットデータの0と1の違いは、信号がハイになっている時間です。0の場合は26~28[μs]、1の場合は70[μs]です。
3.2.5 温湿度センサからPICへの終了信号
温湿度センサはデータを全て送信すると、終了信号を送信します。温湿度センサから送信してくる終了信号は以下の通りです。
- 温湿度センサが、信号をハイからローにする
- 温湿度センサが、ローの状態を50[μs]維持
- 温湿度センサが、信号をローからハイにする
3.2.6 温湿度センサから送られてきたデータについて
温湿度センサからは40ビットのデータが送られてきます。その40ビットを8ビットずつ切り分けます。上位から湿度の整数、湿度の小数、温度の整数、温度の小数、パリティビットとなっています。以下に例を示します。
例:受信したデータが以下の場合
0011 0101 0000 0000 0001 1000 0000 0000 0100 1101
受信ビットデータ | 意味 |
---|---|
0011 0101 | 湿度の整数 |
0000 0000 | 湿度の少数(DHT11では0のみ) |
0001 1000 | 温度の整数 |
0000 0000 | 温度の小数(DHT11では0のみ) |
0100 1101 | パリティビット |
湿度は「0011 0101 0000 0000」から53%となります。
温度は「0001 1000 0000 0000」から24度となります。
パリティビットは8ビット単位の温度と湿度を加算した値となります。
0011 0101 + 0000 0000 + 0001 1000 + 0000 0000 = 0100 1101
4.プログラム
プログラムの基本的な部分は以下の記事を参考にしてください。
4.1 1ピンで双方向通信について
下記サイトの情報をもとに温湿度センサをオープンドレインのピンでなくても使用できるようにしています。
ポイントをまとめると以下の通りです。
- 温湿度センサからのデータを入力時:ポートを入力に設定
- ハイの信号を出力したい場合:ポートを入力に設定
- ローの信号を出力したい場合;ポートを出力に変えローを出力
4.2 プログラムの説明
プログラムを見ながら以下の説明を見てください。ソースコードは次の節にあるので、そちらを参照してください。
4.2.1 シリアル通信(送信処理)
void interrupt isr_ctrl( void ) { if( TXIF ) { if( uart_tx_cnt < TX_UART_SIZE ) { TXREG = uart_tx_msg[ uart_tx_cnt ]; uart_tx_cnt++; } else { TXIE = 0; } if( uart_tx_cnt >= TX_UART_SIZE ) { uart_tx_cnt = 0; TXIE = 0; } TXIF = 0; } }
4.2.2 PICの初期設定
OSCCON = 0b01110000 ; // 内部クロック8MHz OPTION_REG = 0b00000000 ;// 7bit目が0でプルアップ抵抗が有効 ANSELA = 0b00000000 ; // すべてデジタルI/Oに割当てる TRISA = 0b00101000 ; // RA3,5を入力にし、他は出力に設定 PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) WPUA = 0b00100100 ; // RA2,5にプルアップ抵抗に設定
PICの初期設定を行っています。ポイントを以下に示します。
- タクトスイッチにつながっているRA5を入力に設定
- 温湿度センサにつながっているRA2のプルアップ抵抗を設定(温湿度センサがオープンドレインの為)
- タクトスイッチにつながっているRA5のプルアップ抵抗を設定
4.2.3 シリアル通信に関する設定
TXSTA = 0x24; // 送信情報設定:非同期モード 8ビット・ノンパリティ RCSTA = 0x90; // 受信情報設定 BAUDCON = 0x08; // 16bit SPBRG = 0x40; // ボーレートを9600(高速モード)に設定 SPBRGH = 0x03; RXDTSEL = 0; TXCKSEL = 0; TXIE = 0; TXIF = 0; PEIE = 1; GIE = 1;
4.2.4 温湿度センサの起動待ち
__delay_ms(1000);
温湿度センサは起動後1秒間待たなくてはいけなので、そのための待ち時間です。
4.2.5 温湿度センサの開始信号を送信
// Low 出力 TRISA &= ~DHT11_IO; PORTA &= ~DHT11_IO; __delay_ms(20); // Hi 出力 TRISA |= DHT11_IO; // Low信号の確認開始を遅延する __delay_us(10);
温湿度センサに対して開始信号(3.2.2 PICから温湿度センサへの開始信号)を送信しています。
4.2.6 温湿度センサから送られてくる開始信号受信
// Lowになるまで待つ while( (PORTA & DHT11_IO) != 0 ) { // Hiの間処理無し } // Hi になるのを待つ while( (PORTA & DHT11_IO) == 0 ) { // Lowの間処理無し }
温湿度センサから送られてくる開始信号(3.2.3 温湿度センサからPICへの開始信号)を受信しています。
4.2.7 温湿度センサからデータ受信
for(i=0; i<5; i++) { b = 0; for(j=0; j<8; j++) { // Lowになるまで待つ while( (PORTA & DHT11_IO) != 0 ) { // Hiの間処理無し } // Hi になるのを待つ while( (PORTA & DHT11_IO) == 0 ) { // Lowの間処理無し } // 50usec wait __delay_us(50); // データをシフト b = b << 1; // IOがHiなら1をセット if( (PORTA & DHT11_IO) != 0 ) b |= 0x01; } // データをセット dht11_data[i] = b; } // データ転送完了待ち // Lowになるまで待つ while( (PORTA & DHT11_IO) != 0 ) { // Hiの間処理無し }
温湿度センサから送られてくるデータ(3.2.4 温湿度センサからPICに送られてくるビットデータについて)
を受信しています。
4.2.8 温度と湿度を7セグメントディスプレイに送信
for( i=0; i<500; i++ ) { if( (old_io!=SW_IO) && (SW_IO == 0) ) { if( dht11_mode == TEMPERATURE_MODE ) dht11_mode = HUMIDITY_MODE; else dht11_mode = TEMPERATURE_MODE; send = 1; } old_io = SW_IO; // 1sec毎に再表示 send_cnt++; if( send_cnt > 100 ) { send_cnt = 0; send = 1; } if( send != 0 ) { if( dht11_mode == TEMPERATURE_MODE ) work = dht11_data[2]; else work = dht11_data[0]; work1 = work%10; work /= 10; work2 = work; // 送信データ構築 uart_tx_msg[0] = 0x00; // 少数点位置の設定 uart_tx_msg[1] = 0x0f & 0x00; uart_tx_msg[2] = work2 << 4; uart_tx_msg[2] |= work1; uart_tx_cnt = 0; TXIE = 1; // 送信開始 send = 0; } __delay_ms(10); }
温湿度センサのデータを7セグメントディスプレイに送信している処理です。タクトスイッチを押すことで、送信する温度と湿度を切り替えるようにしています。
4.3 注意事項
本プログラムでは以下の異常処理を入れていません。必要に応じて追加して使用してください。
- PICと温湿度センサとの通信タイムアウト処理
- 温湿度センサから送られてくるデータのパリティチェック
- 割込みで時間がかかる処理を行うと温湿度センサからの信号を正しく受信できなくなる
- 温湿度センサと接続しているピンを、出力設定にしハイ信号を出力しない (ハイ信号を出力すると壊れる恐れがあります)
4.4 ソースコード
プログラムの全文を掲載します。
<注意>
ファイル名は必要に応じて変更し利用してください。
本サイトの注意事項を確認してください。
ソースコードや回路図などを使用する場合、上記注意とともに、自己責任でお願いします。
5.動作確認
起動すると数秒後に接続している7セグメントディスプレイに、温度が表示されます。タクトスイッチを押すと表示が湿度に変わります。
<更新履歴>
日付 | 内容 |
2015年7月13日 | 新規作成 |
2015年7月14日 | 3.2.6 温湿度センサから送られてきたデータについて データの説明の表の説明修正 「(DHT11では0のみ)」を追加 |
2016年10月6日 | フォーマット変更(内容の変更はなし) |