AM2322は,温度と湿度を測れるセンサです!
測定したデータはデジタル通信で出力されので,センサとマイコンを接続する必要があります.
この記事では,以下の悩みを解決します!
この記事にはYouTube動画バージョンがあります.
文字で読むより動画の方がわかりやすいと思うので,視聴できる環境がある人にはおすすめです!
全体回路
全体の構成として,AM2322とデジタル通信するためのマイコン,温度と湿度を表示するための7セグメントLEDがあります.
加えて,スイッチと圧電ブザーもつけておきました.
4桁の7セグメントLEDの使い方について詳しく知りたいからはこちらの記事を参考にしてください.
7セグメントLEDを光らせる方法5選!!完全攻略ガイド!主な部品名 | 使用数 |
---|---|
AM2322(温湿度センサ) | 1 |
PIC16F1827(マイコン) | 1 |
OSL40391-LG(7セグメントLED) | 1 |
タクトスイッチ | 1 |
圧電スピーカ | 1 |
AM2322センサの使い方
通信方式
データシートを読むと,このセンサは
- I2C通信
- 単線シリアル通信
の2つから選択してマイコンと通信するようです.
センサにはVDD,GND,SDA,SCL端子があり,
I2C通信を選択する場合はSCL端子をシリアルクロックとして使い,
単線シリアル通信として使う場合はGNDに接続します.
データシートの読み方は上記のYouTube動画で詳しく紹介しています.
接続
今回は単線シリアル通信で行うため,SCLはGNDに接続します.
また,マイコンの端子はオープンドレイン出力のものに接続します.
通信方法
1. 温湿度センサの起動待ち
電源を投入してからセンサが起動するまで,1秒以上待ちます.
このとき,センサとの信号線SDAはLowに落としておきます.
通信全体の順番は以下の図の通りです.
2. PICから温湿度センサへの開始信号
温湿度を取得するには,まずマイコンからセンサへ通信開始の合図を送ります.
開始信号を送る手順は以下の通りです.
- マイコンが,信号(SDA)をHighからLowにする
- マイコンが,Lowの状態を0.8〜20ms維持
- マイコンが,信号をLowからHighにする
3. 温湿度センサからPICマイコンへの開始信号
センサからマイコンへ,温湿度情報の送信を開始する合図を送ります.
送信開始信号を送る手順は以下の通りです.
- 温湿度センサが,信号(SDA)をHighからLowにする
- 温湿度センサが,Lowの状態を75〜85us維持
- 温湿度センサが,信号(SDA)をLowからHighにする
- 温湿度センサが,Highの状態を75〜85us維持
4. 温湿度情報
温湿度センサからPICへ温湿度情報が送られてきます.
データサイズは湿度16bit,温度16bit,チェックデジット8bitの合計40ビットになります.
0ビットと1ビ ットの判断方法を記述します.
○ビットデータが0のとき
データが0の場合,温湿度センサが以下のように信号SDAを変化させます.
- 温湿度センサが,信号(SDA)をHighからLowにする
- 温湿度センサが,Lowの状態を48〜55us維持
- 温湿度センサが,信号(SDA)をLowからHighにする
- 温湿度センサが,Highの状態を22〜30us維持
○ビットデータが1のとき
データが1の場合,温湿度センサが以下のように信号SDAを変化させます.
- 温湿度センサが,信号(SDA)をHighからLowにする
- 温湿度センサが,Lowの状態を48〜55us維持
- 温湿度センサが,信号(SDA)をLowからHighにする
- 温湿度センサが,Highの状態を68〜75us維持
温湿度センサから送られてきたデータについて
温湿度センサからは40ビットのデータが送られてきます.
送られてきたデータを,8bitずつに切り分けます.
湿度の上位8bit,湿度の下位8bit,温度の下位8bit,温度の上位8bit,チェックデジット8bitの合計40ビットになります.
湿度と温度は,2進数表記を10進数表記に直した後,その値を1/10します.
例)00000001 00011001 00000010 01001001 01100101
湿度は”00000001 00011001” →281(10進数)
1/10すると,28.1℃
温度は”00000010 01001001” →585(10進数)
1/10すると,58.5%
チェックデジットは,湿度の上位8bit,湿度の下位8bit,温度の下位8bit,温度の上位8bitの合計になります.
01100101 = 00000001 + 00011001 + 00000010 + 01001001
プログラム
PICマイコン16F1827でAM2322と通信するプログラムを以下に示します.
詳しい説明は上記のYouTube動画をご視聴ください!
// PIC16F1827 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define _XTAL_FREQ 8000000 //クロック動作周波数を8MHzとして__delay_msを使用する
//#define _XTAL_FREQ 32000000 //クロック動作周波数を8MHzとして__delay_msを使用する
#define DIG1 RA1
#define DIG2 RA0
#define DIG3 RA7
#define DIG4 RA6
#define colon RA3
#define SDA RA4
#define Speaker RA2
#define Switch RA5
unsigned short int temperature = 0;
unsigned short int humidity = 0;
Display7SEG(char num, unsigned short int dp);//引数はnum=(表示する数字・記号),dp=(デジマルポイントの有無(0or1)))
Display7SEG_4DIG(unsigned short int number, char option);//引数はnum=表示する数字,オプションoptionはc(°C),p(%),n(無し)
TemperatureAndHumiditySensor();
Beep(unsigned short int num);
int main() {
OSCCON = 0b01110100; //内部クロック8MHz
ANSELA = 0b00000000; //ポートAをデジタルI/Oピンとして使う
ANSELB = 0b00000000; //ポートBをデジタルI/Oピンとして使う
TRISA = 0b11111111; //ポートAを出力に設定
TRISB = 0b00000000; //ポートBを出力に設定
__delay_ms(1500);//温湿度センサが起動するのを待つ
Beep(300);//起動音
while (1) {
while(Switch == 0){
//スイッチが押されるまで待機
}
Beep(100);//スイッチが押されたことを確認
TemperatureAndHumiditySensor();//センサと通信
//温度を表示--------------------------
for(unsigned int i =0;i<500; i++){
Display7SEG_4DIG(temperature,'c');//°C
}
//温度を表示--------------------------
//湿度を表示--------------------------
Beep(100);//湿度表示開始音
for(unsigned int i =0;i<500; i++){
Display7SEG_4DIG(humidity, 'p');//%persent
}
//湿度を表示--------------------------
}
return 0;
}
Display7SEG_4DIG(unsigned short int number, char option) {
unsigned short int DIG[4];
unsigned short int temp;
temp = number;
DIG[3] = temp / 1000;
temp = number;
DIG[2] = (temp - 1000 * DIG[3]) / 100;
temp = number;
DIG[1] = (temp - 1000 * DIG[3] - 100 * DIG[2]) / 10;
temp = number;
DIG[0] = temp - 1000 * DIG[3] - 100 * DIG[2] - 10 * DIG[1];
TRISB = 0b00000000;
TRISA = 0b00000000;
DIG1 = 0;
DIG2 = 0;
DIG3 = 0;
DIG4 = 0;
colon = 0;
if(option == 'n'){
Display7SEG(DIG[0],0);
}else{
Display7SEG(option,0);
}
DIG1 = 1; //1桁目を表示
__delay_ms(1);
DIG1 = 0;
DIG2 = 0;
DIG3 = 0;
DIG4 = 0;
colon = 0;
Display7SEG(DIG[1],0);
DIG2 = 1; //2桁目を表示
__delay_ms(1);
DIG1 = 0;
DIG2 = 0;
DIG3 = 0;
DIG4 = 0;
colon = 0;
Display7SEG(DIG[2],1);
DIG3 = 1; //3桁目を表示
__delay_ms(1);
DIG1 = 0;
DIG2 = 0;
DIG3 = 0;
DIG4 = 0; //すべてのLEDを消灯
colon = 0;
Display7SEG(DIG[3],0);
DIG4 = 1; //4桁目を表示
__delay_ms(1);
DIG1 = 0;
DIG2 = 0;
DIG3 = 0;
DIG4 = 0; //すべてのLEDを消灯
colon = 0;
if(option != 'n'){
Display7SEG('d',0);
}
colon = 1; //コロン,°表示
__delay_ms(1);
DIG1 = 0;
DIG2 = 0;
DIG3 = 0;
DIG4 = 0;
colon = 0;
}
Display7SEG(char num, unsigned short int dp) {
unsigned short int dp_b;
if(dp == 1){
dp_b = 0b00001000;
}else{
dp_b = 0b00000000;
}
switch (num) {
case 0:
PORTB = 0b10110111 | dp_b;//0 正論理
//PORTB = 0b01001000; //0 負論理
break;
case 1:
PORTB = 0b00010100 | dp_b;//1
//PORTB = 0b11101011; //1
break;
case 2:
PORTB = 0b01110011 | dp_b;//2
//PORTB = 0b10001100; //2
break;
case 3:
PORTB = 0b01110110 | dp_b;//3
//PORTB = 0b10001001; //3
break;
case 4:
PORTB = 0b11010100 | dp_b;//4
//PORTB = 0b00101011; //4
break;
case 5:
PORTB = 0b11100110 | dp_b;//5
//PORTB = 0b00011001; //5
break;
case 6:
PORTB = 0b11100111 | dp_b;//6
//PORTB = 0b00011000; //6
break;
case 7:
PORTB = 0b00110100 | dp_b;//7
//PORTB = 0b11001011; //7
break;
case 8:
PORTB = 0b11110111 | dp_b;//8
//PORTB = 0b00001000; //8
break;
case 9:
PORTB = 0b11110110 | dp_b;//9
//PORTB = 0b00001001; //9
break;
case 'c':
PORTB = 0b10100011;//C
break;
case 'p':
PORTB = 0b01011001;
break;
case 'd':
PORTB = 0b00000100;
break;
}
}
TemperatureAndHumiditySensor(){
unsigned int data[40];
unsigned int c;
//picから温度センサーへ開始信号送信
TRISA = 0b00000000;
SDA = 0;
__delay_ms(25);
SDA = 1;
__delay_us(10);
//情報受信開始
TRISA = 0b11111111;
while(SDA != 0) //LOWになるまで待つ
{
}
while(SDA == 0) //Hiになるまで待つ
{
}
//温湿度情報受信開始
for(c=0 ; c <40 ; c++) {
while(SDA == 1) //LOWになるまで待つ(1の間はwhile文の中にいる)
{
}
while(SDA == 0) //Hiになるまで待つ (0の間はwhile文の中にいる)
{
}
__delay_us(40);
if(SDA == 1){
data[c] = 1;
}
else{
data[c] = 0;
}
}
//温度湿度の計算
humidity = 0*data[0] + 0*data[1] + 0*data[2] + 0*data[3] + 0*data[4] + 0*data[5] + 512*data[6] + 256*data[7] + 128*data[8] + 64*data[9] + 32*data[10] + 16*data[11] + 8*data[12] + 4*data[13] + 2*data[14] + data[15];
temperature = 0*data[16] + 0*data[17] +0*data[18] +0*data[19] +0*data[20] +0*data[21] +512*data[22] +256*data[23]+ 128*data[24]+ 64*data[25]+ 32*data[26] + 16*data[27] + 8*data[28] + 4*data[29] + 2*data[30] + data[31];
humidity = 10*humidity;
temperature = 10*temperature;
}
Beep(unsigned short int num){
TRISA = 0b11111011; //speakerを出力に設定
for(unsigned int s=0; s<num; s++){
Speaker = 1;
__delay_ms(0.75);
Speaker = 0;
__delay_ms(0.75);
}
}