DHT20 温湿度測定器を使う(for Arduino)のPIC版です。
ハードの準備
PICはPIC24FJGB002。測定値表示用にAQM1248A(LCD)を使用しています。
- インターフェイスはI2Cなので SDA->RB9。SCL->RB8 は固定
- ポートの設定でRB,9にプルアップを適応しても良いのですが、プルアップの値が分からないので10kオームを外付けしています。
ソフトの準備
ADT7410 温度測定モジュール (for PIC)の時と同様I2Cに関してMCC作成のコードが動かなかったので必要な部分を自作しています。今回作成したプログラムは
- DHT20用のプログラム
- DHT20_PIC.c:本体
- DHT20_PIC.h:ヘッダー
- I2C関係のプログラム
- i2c1_PIC.c:本体
- i2c1_PIC.h:ヘッダー
- PIC24FJGB002はI2Cを2つ持っていますが今回はI2C1を使用しています。
- デモプログラム main.c:下記を行いLCDに表示します。
- ステータス・レジスタの表示
- 測定した温湿度の表示
DHT20.cの説明:作成した関数2つ。
DHT20.c
/*
* File: DHT20_PIC.c
*
* Created on December 29, 2021, 11:19 AM
*/
#include "xc.h"
#include "DHT20_PIC.h"
#include "i2c1_PIC.h"
uint8_t DHT20_chk()
{
uint8_t buf[1];
__delay_ms(10);
I2C_Start(DHT20_addr,0); // スタートコンディション
I2C_Send(0x71); // コマンド送信
I2C_Start(DHT20_addr,1); // リスタートコンディション
buf[0] = I2C_Receive(NOACK); // データの読み込み
I2C_Stop(); // ストップコンディション
return(buf[0]);
}
void DHT20_Get_Data(float * f_data)
{
uint8_t buf[10];
int i,ack;
long a;
I2C_Start(DHT20_addr,0); // スタートコンディション
I2C_Send(0xac); // control byte
I2C_Send(0x33); // data byte
I2C_Send(0x00); // data byte
I2C_Stop(); // ストップコンディション
__delay_ms(100);
I2C_Start(DHT20_addr,1); // リスタートコンディション
for (i = 0; i < 7 ; i++)
{
if (i == 6) ack = NOACK ;
else ack = ACK ;
buf[i] = I2C_Receive(ack); // データの読み込み
}
I2C_Stop(); // ストップコンディション
a = buf[1];
a <<= 8;
a |= buf[2];
a <<= 4;
a |= ((buf[3] >> 4) & 0x0f);
f_data[0] = a / 10485.76;
a = (buf[3] & 0xf);
a <<= 8;
a |= buf[4];
a <<= 8;
a |= buf[5];
f_data[1] = a / 5242.88 - 50;
}
- uint8_t DHT20_chk()
- DHT20にコマンド0x71を送って帰って来た値を戻します。
- マニュアルには状態変数と有りましたが前回理解出来なかったところです。
- void DHT20_Get_Data(float * f_data)
- 引数は、float型のポインターです。
- ポインターの先に測定データ(温湿度)を保存するのでFloat型で2つ必要です。
main.cの説明:
main.cy
/**
Section: Included Files
*/
#include "mcc_generated_files/system.h"
#include "AQM1248A_PIC.h"
#include "i2c1_PIC.h"
#include "ADT7410_PIC.h"
/*
Main application
*/
int main(void)
{
float h_data[3];
// initialize the device
uint8_t d_buf[5];
char c_buf[30];
int a;
SYSTEM_Initialize();
InitI2C_Master();
Init_LCD();
while (1)
{
LCD_CLS(0);
for(a = 0; a < 20; a ++) c_buf[a] = 0;
sprintf(c_buf,"State:%X", DHT20_chk());
LCD_Print_Str(0,0,c_buf,1);
__delay_ms(50);
DHT20_Get_Data(h_data);
for(a = 0; a < 20; a ++) c_buf[a] = 0;
sprintf(c_buf,"T:%0.1f'C", h_data[1]);
LCD_Print_Str(0,10,c_buf,1);
for(a = 0; a < 20; a ++) c_buf[a] = 0;
sprintf(c_buf,"H:%0.1f", h_data[0]);
c_buf[strlen(c_buf)] = '%';
LCD_Print_Str(0,20,c_buf,1);
__delay_ms(1000);
}
return 1;
}
- 28,29行:ステータス・レジスタの読み込みと表示
- 32行:測定データの読み込み
- 35行:温度データの表示
- 39行:湿度データの表示
プログラムの実行
デモプログラムを実行するとLCDに下記の様に表示されます。
左が最初の1回目、右はそれ以降です。両者共にステータスと温度、湿度が表示されています。ただステータスは最初の1回のみ、0x18。それ以降は、0x1Cを返します。マニュアルは0x18以外はレジスタの設定をして下さい的は文面でしたが、0x1Cでもちゃんと測定している様です。
今回使用したファイルをここに保存します。