2017/2/6
百葉箱
最近は気象観測装置が性能向上して各地にくまなく設置されて天気予報などが正確になされるようになってきました。そのためかはわかりませんが,小中学校に設置されていた百葉箱が軽視されてきています。無くなっている学校もありますし,中身が入っていない学校も多くあります。
気象現象は私たち人間にとって(生物全体にも)とても大切なものです。インターネットで容易に近隣や全世界の観測結果を知ることができますが,自分で身近な気温や湿度,気圧を測定できると素敵だと思います。
表示装置
気圧,温湿度を表示するにはLCDキーパッドシールドを使います配線の必要がなく安定しています。
ブレッドボードで実験
Arduinoを手に入れてからセンサーや液晶,RTCなどを購入していろいろな実験をしてなんとか気圧,気温,湿度を測定し時間を計測できるようになりました。ブレッドボードはとても便利に使うことができました。容積が大きくなってしまいますがいろいろと手を加えることができました。
センサ
DHT11
MPL115A2
MPL115A2はI2C接続で使用します。
DHT11はOUTからアナログ出力で温度
基板組み立て
基板に組み立てるとかなり小さく作ることができます。小さくする必要はないのですがそうしてしまいます。各ディバイスにはICソケットを使用しています。
基板設計図
部品面とハンダ面です。データロガシールドを使う場合はDS3231は取り付けません。
基板ハンダ面
ハンダ面の実物です。手は震えるし,目が悪くなっているしでイモハンダになってしまっています。やり直しもあって見苦しい基板をお見せして済みません。右側のPINヘッダ6本と中央下部のPINヘッダ1本でArduinoと通信します。
時刻計測
時刻計測と気圧・温湿度データを記録するためのSDカードを搭載しているデータロガシールドを使うことにしました。
データロガーシールドの一部のフリーエリアや,プロトタイプシールドを使って気象観測用の回路をコンパクトに収めることもできますが,ディバイスによる温度上昇などを考えると離れたところに設置できるようにしました。
スケッチ
スケッチはさすがに長くなってしまいました。各部分はセンサやRTC,液晶の組み合わせなので難しいわけではありません。
テキストをコピーしてArduinoIDEにペーストしても動きません。インデント用にスペースが入っているので,全てのインデント用スペースを取り除けば,コンパイルできるようです。
A001_LCD_Keypad_SD_RTC_P_T_H_01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <Wire.h>//I2Cを使用
#include <LiquidCrystal.h>//LCDを使用
#include <DS3231.h>//RTCを使用
#include <DHT.h>//DTHを使用
#define MPL115A2 0x60//気圧計のI2Cアドレス
#define num 100//num回の平均をとる
#define DHTPIN A3//入力用のPIN
#define DHTTYPE DHT11//型名
LiquidCrystal lcd(8,9,4,5,6,7);//液晶作成
DS3231 RTC;//RTCを作る
DHT dht(DHTPIN, DHTTYPE);//dhtを作成
byte year, month, date, DoW, hour, minute, second,prevSecond;
float a0,b1,b2,c12;//気圧の係数のための変数
float Press,Temp;//気圧と気温の変数
void setup() {
Serial.begin(9600);//serial初期化
Wire.begin(); //wire初期化
lcd.begin(16, 2);
dht.begin();//dhtスタート
Coefficient();//補正係数取得
delay(3000);//3秒待ち
}
void loop() {
float p=0;//pは浮動小数
int h = dht.readHumidity();
int t = dht.readTemperature();
//時刻の取得
RTC.getTime(year, month, date, DoW, hour, minute, second);
if (prevSecond != second) {//以前の秒と違ったとき
//年表示
lcd.setCursor(0, 0); //年表示
lcd.print("20");
lcd.print(year);
lcd.print("y");
//日付表示
if(month<10){lcd.print(" ");}
lcd.print(month);
lcd.print("/");
if(date<10){lcd.print(" ");}
lcd.print(date);
//曜日の表示
lcd.setCursor(0, 1);
switch (DoW) {
case 1:lcd.print("Sn");break;
case 2:lcd.print("Mo");break;
case 3:lcd.print("Tu");break;
case 4:lcd.print("We");break;
case 5:lcd.print("Th");break;
case 6:lcd.print("Fr");break;
case 7:lcd.print("St");break;
default:lcd.print("??");break;
}
//時刻の表示
lcd.setCursor(2, 1);
if(hour<10){lcd.print(" ");}
lcd.print(hour);lcd.print(":");
if(minute<10){lcd.print("0");}
lcd.print(minute);lcd.print(":");
if(second<10){lcd.print("0");}
lcd.print(second);
prevSecond=second;//以前の秒を現在の秒に変更
//気圧の平均取得
for( int i=0;i<num;i++){
PressTemp();
p=p+int (Pressure());}//積算
if (isnan(h) || isnan(t)) {
return; }//h,tが数字でなければERROR帰還
Press=p/num;//平均
//気圧の表示
lcd.setCursor(11, 0);//キアツ
if(Press<1000){lcd.print(" ");}
lcd.print(int(Press));
lcd.print("h");//キアツ
//気温表示
lcd.setCursor(11, 1);//キオン
if(t<10){lcd.print(" ");}
lcd.print(t);
lcd.print("\xdf");//キオン
//湿度表示
lcd.setCursor(14, 1);//シツド
if(h<10){lcd.print(" ");}
lcd.print(h);
lcd.print("%");//シツド
}
}
//関数・補助部
int Coefficient(){//係数読み込み
unsigned int u,l;//ulは2BYTE数
Wire.beginTransmission(MPL115A2);
Wire.write(0x04);//04番地から読みます
if(Wire.endTransmission()!=0)return 5;//0でなければ失敗帰還
if(Wire.requestFrom(MPL115A2,8)!=8)return 5;//失敗なら帰還
//係数a0,b1,b2,c12を読み込む
//a0の読み込みと計算
u=Wire.read();l=Wire.read();
// a0 = (u << 5) + (l >> 3) + (l & 0x07) / 8.0 ;
a0=((u << 8) + l ) / 8.0 ;
if( u & 0x80 ) a0 -= 8192.0;
//b1の読み込みと計算
u=Wire.read();l=Wire.read();
//b1 = ( ( ( (u & 0x1F) * 0x100 ) + l ) / 8192.0 ) - 3 ;
b1 = ( ( u <<8) + l ) / 8192.0 ;
if( u & 0x80 ) b1 -= 8.0;
//b2の読み込みと計算
u=Wire.read();l=Wire.read();
//b2 = ( ( ( ( u - 0x80) << 8 ) + l ) / 16384.0 ) - 2 ;
b2 = ( (u << 8 ) + l ) / 16384.0 ;
if( u & 0x80 ) b2 -= 4.0;
//c12の読み込みと計算
u=Wire.read();l=Wire.read();
//c12 = ( ( ( h * 0x100 ) + l ) / 16777216.0 ) ;
c12 = ( ( u <<8) + l ) / 32768.0 ;
if( u & 0x80 ) c12 -= 2.0;
c12 /= 512.0;
return 0;
}
int PressTemp(){//気圧と気温を測定
unsigned int u,l;
Wire.beginTransmission(MPL115A2);
Wire.write(0x12);//気圧と気温のAD変換開始
Wire.write(0x01);
if(Wire.endTransmission()!=0)return 5;//失敗はERROR5
delay(3);//変換時間待ち
Wire.beginTransmission(MPL115A2);//
Wire.write(0x00);
if(Wire.endTransmission()!=0)return 5;//失敗はERROR5帰還
if(Wire.requestFrom(MPL115A2,4)!=4)return 5;//失敗はERR5帰還
//気圧
u=Wire.read();l=Wire.read();
Press=((u<<8)+l)/64.0;//=(u*256+l)/64.0;
//気温
u=Wire.read();l=Wire.read();
Temp=((u<<8)+l)/64.0;//=(u*256+l)/64.0;
return 0;
}
float Pressure(){//補正された気圧を求める式
float d;
d=a0 + (b1 + c12*Temp )*Press + b2*Temp;
return d * ( 650.0 / 1023.0 ) + 500.0 ;
}
スケッチの説明
宣言部では
1から4行目はインクルードファイルの読み込みです。I2C,液晶,RTC,温湿度計を使用するためです。気圧計はサブルーチンを使っていますのでインクルードファイルは必要としません。
6から9行目は数や型名を理解しやすい文字に決めています。
11から13行目はLCD,RTC,温湿度計の実体を作っています。
15から17行目は変数を宣言してスケッチ全体で使えるようにしています。
初期設定部では
シリアル通信,I2C,液晶,温湿度計を初期化して気圧用の係数を求めています。
繰り返し部では
29行目から31行目までで変数を確保してから気温と湿度を測定しています。
33行目で年月日時刻を取得して34行目で秒が更新されたか判断しています。更新された場合は36~39行目で年の表示,41~45行目までで日付を表示,47~57行目で曜日を表示,59行目から65行目で時刻を表示しています。66行目で現在時刻の秒を更新します。
68~89行目では気圧を求めて表示し,気温と湿度を表示します。
関数・補助部では
95~127行までで係数を読み込みます。
129~149行は気圧と気温の測定です。
151~156行は測定値から係数と気温を使った気圧の計算を行います。
牛乳パック百葉箱
牛乳パックで百葉箱らしきものを作ってみました。右は液晶表示です。
動作時間
単三乾電池2本で100均のUSB CHARGERで駆動すると3時間2分で電池切れになります。
表示用LEDを消灯すると6時間1分になります。
プログラム領域
プログラムカラフルクロックのPC制御時刻合わせを導入したところ,
スケッチに使用できるメモリが少なくなってきました。動作が不安定になる可能性が有ります。
と表示されました。あまり大きなプログラムはArduinoに適していないようです。朝までできていたデータロギングもできなくなってしまいました。
時計は時計,環境測定は別のCPUを使うべきなのかもしれません。