読者です 読者をやめる 読者になる 読者になる

つくったブログ

ぼくがつくったもの。

温度計もどきをつくったよ。

温度計です。

http://instagram.com/p/rMQkBnLLh2/

 細かいことはあとで追記します。とりあえずコードだけ載せておきます。


必要なもの

  • 220Ω抵抗×8
  • 4桁7segLED(カソードコモン)(OSL40562-LB)

ダイナミック接続4桁高輝度青色7セグメントLED表示器 カソードコモン カソード共通接続: LED(発光ダイオード) 秋月電子通商 電子部品 ネット通販
250円くらいで売られています。

  • DHT11温湿度モジュール(Temperature and Humidity Sensor)[DFR0067]

DHT11温湿度モジュール(Temperature and Humidity Sensor): マイコン関連 秋月電子通商 電子部品 ネット通販
http://instagram.com/p/qn2xMJrLnQ/

精度は期待できませんが、安いです。520円。温度、湿度を1℃、1%刻みで計測できます。


コード

/*********************************************************************
        DHT11の簡易湿度計 for Arduino
                               Copyright (c) 2012-2014 Wataru KUNINO
*********************************************************************/
/*
参考:
DHT11:http://www.geocities.jp/bokunimowakaru/
7segLED:http://happy-arduino.blogspot.jp/2012/08/17_27.html
*/

#define DHTport			17			// DHT_DATAポート番号(ANALOG 3)
#define SD_CS			10			// SDカードCS端子(デフォルト=10)
#include <SD.h>
#include <MsTimer2.h>
const static byte DHTtype=	11;		// AM2302時はDHT=22にする
									// (#ifdefが使えないかった)
//---
const int BUTTON = 11;  // プッシュボタンが接続されているピン
const int led_1  = 9;  // 7segLED the one's place 
const int led_10 = 10;  // 7segLED the ten's place 
const int led_100  = 11;  
const int led_1000 = 12; 

int val = 0;            // 入力ピンの状態がこの変数(val)に記憶される
int old_val = 0;        // valの前の値を保存しておく変数
int state = 0;          // LEDの状態(0ならオフ、1ならオン)
int state_1=0;          // the one's digit 
int state_10 =0;        // the ten's digit
int state_100 =0;        
int state_1000 =0;   
float hum=0.0,temp=0.0;
	byte dht11_dat[5];
	byte dht11_check_sum;
	byte i;
	char Str[16];
//----

// DHTポートの初期化
void DHTInit(void) {
	pinMode(DHTport,INPUT);
	delay(250);
}

// DHT TSシーケンス
byte DHTTSSeq(void) {
	byte dht11_in;
	// start condition
	// 1. pull-down i/o pin from 18ms
	digitalWrite(DHTport, LOW);
	pinMode(DHTport,OUTPUT);
	delay(200);
	pinMode(DHTport,INPUT);
	delayMicroseconds(20+40);	// High 20us + Slave ACK 80us/2

	dht11_in = digitalRead(DHTport);	// 正常時 = LOW
	if(dht11_in){
		Serial.println("dht start condition 1 not met");
		return(1);
	}
	delayMicroseconds(80);
	dht11_in = digitalRead(DHTport);	// 正常時 = HIGH
	if(!dht11_in){
		Serial.println("dht start condition 2 not met");
		return(1);
	}
noInterrupts();
	while( digitalRead(DHTport) );		// LOW待ち
interrupts();
	return(0);
}

// DHTデータ受信
byte read_dht11_dat(){
	byte i = 0;
	byte result=0;
	for(i=0; i< 8; i++){
    noInterrupts();
		while( !digitalRead(DHTport) ); // High待ち
  interrupts();
		delayMicroseconds(49);			// 28us or 70us 
		if( digitalRead(DHTport) ){
			result |=(1<<(7-i));
 noInterrupts();
			while( digitalRead(DHTport) ); // wait '1' finish
 interrupts();
		}
	}
	return result;
}

// DHT ACK
void DHT_ACK(void) {
    noInterrupts();
	while( digitalRead(DHTport) );
  interrupts();
	delayMicroseconds(50);


}

void setup() {
  //1~8番ピン デジタル出力へセット
        for (int i=2; i<=8; i++){
        pinMode(i,OUTPUT);
  }
        pinMode(13,OUTPUT);
        pinMode(BUTTON, INPUT);  // BUTTONは入力に設定
        pinMode(led_10, OUTPUT); // 7segLED はoutput
        pinMode(led_1, OUTPUT);
        pinMode(led_100, OUTPUT); 
        pinMode(led_1000, OUTPUT);
        pinMode(DHTport,INPUT);
        Serial.begin(9600);	
        Serial.print("DHT");
        Serial.println(DHTtype,DEC);
        MsTimer2::set(50,led_start);
        MsTimer2::start();
}

// 7segLED---
//LEDレイアウトを定義
boolean Num_Array[11][8]={
        {1,1,1,0,1,0,1,1},{0,0,1,0,1,0,0,0},{1,0,1,1,0,0,1,1},{1,0,1,1,1,0,1,0},
        {0,1,1,1,1,0,0,0},{1,1,0,1,1,0,1,0},{1,1,0,1,1,0,1,1},{1,1,1,0,1,0,0,0},
        {1,1,1,1,1,0,1,1},{1,1,1,1,1,0,1,0},{0,0,0,0,1,0,0}
};
//LED表示関数を定義

void NumPrint(int Number){
        for (int w=1; w<=7; w++){
        digitalWrite(w+1,Num_Array[Number][w]);
        }
         digitalWrite(13,Num_Array[Number][0]);
}
//

void led_start(){
        state = (int)temp % 10000;
        state_1 = (state) % 10; 
        state_10 = state /10 % 10;
        state_100 = state /100 % 10;
        state_1000 = state /1000 % 10;
        digitalWrite(led_1000,1);
        digitalWrite(led_100,1);
        digitalWrite(led_10,1);
        digitalWrite(led_1,0);
        NumPrint(state_1);
        delay(3);
        digitalWrite(led_1000,1);
        digitalWrite(led_100,1);
        digitalWrite(led_10,0);
        digitalWrite(led_1,1);
        NumPrint(state_10);
        delay(3);
        digitalWrite(led_1000,1);
        digitalWrite(led_100,0);
        digitalWrite(led_10,1);
        digitalWrite(led_1,1);
        NumPrint(state_100);
        delay(3);
        digitalWrite(led_1000,0);
        digitalWrite(led_100,1);
        digitalWrite(led_10,1);
        digitalWrite(led_1,1);
        NumPrint(state_1000);           
        delay(3);  
        digitalWrite(led_1000,1);
}
// 7segLED---

void loop() {

	//DHTInit();
	DHTTSSeq();
	for (i=0; i<5; i++) dht11_dat[i] = read_dht11_dat();
	DHT_ACK();
	dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
	if(dht11_dat[4]!= dht11_check_sum){
		Serial.println("DHT11 checksum error");
	}
	/* 表示 */

        temp =  (float)dht11_dat[2];
	Serial.print("DHT TEMP = ");
	Serial.print( temp , 1 );
	Serial.print(" degC\n");

	hum =  (float)dht11_dat[0]; 
	Serial.print("DHT HUM  = ");
	Serial.print( hum , 1 );
	Serial.print(" %\n");
        delay(1000);
}
  • DHT11は8bit×5の40bitを出力します。温度は三個目の8bitを、湿度は始めの8bitを10進数に直して使います。
  • はじめから四つ目までの8bitの和が、最後の8bitと等しくならなかったら計測エラーです。

例:0011 0101/ 0000 0000/ 0001 1000/ 0000 0000 /0100 1101 のとき、
0011 0101+0000 0000+ 0001 1000+ 0000 0000 =0100 1101 なのでOK。

DHT11のデータシート
http://akizukidenshi.com/download/ds/aosong/DHT11.pdf

おわりに

 割り込みの間隔を短くすると、うまく計測できない。割り込み禁止/許可を入れてもだめだ。なんでかなー。

参考

Arduino温湿度測定ロガー・湿度センサーの比較 by ボクにもわかる地上デジタル


Making Things Talk ―Arduinoで作る「会話」するモノたち (Make:PROJECTS)

Making Things Talk ―Arduinoで作る「会話」するモノたち (Make:PROJECTS)