前回、ラピロにXBee通信機能つきの Arduinoシールドを装備させました。せっかく無線通信できるのだから、遠隔地のセンサ情報の取得とか機器制御もやってみたくなるのが人情(?)というものです。
というわけで、ラピロの通信相手となるセンサステーションを作ろうと思います。
搭載したセンサ諸々はこんな感じです。
- 温度/湿度センサ(RHT03)
- 照度センサ(NaPiCa AMS302)
- 人感(動き)センサ(NaPiOn AMN14112)
- 開閉センサ(リードスイッチ)(MC-14AG)
- 圧電サウンダ(スピーカー)(PKM13EPPYH4000-A0)
それぞれ精度とかはあまり求めていなくて、「おおよその値がわかればいいから簡単に使えそうなのがいいな」という基準で選定しています。
とりあえずブレッドボード上に組んでみた結果がこちら。ブレッドボード大好き。

Arduino Fioの下はこんな感じ。

左上のソケットは、ゆくゆくはXBeeをスリープ動作させる可能性もあるので、引っ張っておきました。こちらによれば、Arduino FioのDTRとかいう端子が、XBeeのスリープ制御用の端子に繋がっているそうなので。
Arduinoのソースは、前回ラピロのシールド用に作成したものをベースに、I2C通信関係とマイク関係を除いて、温度/湿度センサの取得コードの変更、開閉センサの値取得コード追加、圧電スピーカーのテストコード追加、という形で作成しています。
ちょっと困ったのが、温度/湿度センサのRHT03。Arduinoを使った工作では比較的メジャーなようで、いろいろ情報はあるのですが、提供されているライブラリがArduino Unoベース(16MHz, 5V駆動)のためか、Arduino Fio(8MHz, 3.3V駆動)で最初うまく値が取れませんでした。どちらも0になる。
ライブラリはいくつか存在するようで、最終的に以下で提供されているライブラリを使うと、Arduino Fioでも動作しました。
また、こちらによれば、ライブラリのソースを一部書き換える必要があるようなのですが、とりあえずそのままでも動作しました。ただ、2000ミリ秒間隔で値を取得しにいっても、取得に失敗することがそこそこあるので、そのときは前回取得値で補完するようにしました。
ということで、現状のソースを載せておきます。
#include "DHT.h"
#include "pitches.h"
#define DHTTYPE DHT22 // DHT 22 (AM2302)
int TEMP_HUMID_PIN = 10;
int ILL_PIN = A7;
int DOOR_PIN = 4;
int MOTION_PIN = 12;
int SPEAKER_PIN = 13;
int XBEE_SLEEP_PIN = 3; // 0 … Enable XBEE / 1 … Disable XBEE
DHT dht;
float temp_avg = 0.0;
float humid_avg = 0.0;
float ill_avg = 0.0;
int motion_avg = 0;
int door = 0;
// すべてのセンサは、問い合わせ時点から過去1分間の出力値の平均値を返す。
// ただし、モーションセンサについては、平均値が0.2以上なら「人がいた」と判定して1、
// 0.2未満なら「人がいない」と判定して0を返す
const int SENSOR_LOG_NUM = 60;
float temp_log[SENSOR_LOG_NUM];
float humid_log[SENSOR_LOG_NUM];
float ill_log[SENSOR_LOG_NUM];
float motion_log[SENSOR_LOG_NUM];
int loop_count = 0;
void updateTemperatureAvg() {
float sum = 0.0;
for (int i = 0; i < SENSOR_LOG_NUM; i++) {
sum += temp_log[i];
}
temp_avg = sum / SENSOR_LOG_NUM;
}
void updateHumidityAvg() {
float sum = 0.0;
for (int i = 0; i < SENSOR_LOG_NUM; i++) {
sum += humid_log[i];
}
humid_avg = sum / SENSOR_LOG_NUM;
}
float getIlluminance() {
int AMS302_Value = analogRead(ILL_PIN);
float lx = AMS302_Value * (3300.0 / 1024.0) / 1000.0 / (0.26 / 100);
return lx;
}
void updateIlluminanceAvg() {
float sum = 0.0;
for (int i = 0; i < SENSOR_LOG_NUM; i++) {
sum += ill_log[i];
}
ill_avg = sum / SENSOR_LOG_NUM;
}
void updateMotionAvg() {
float sum = 0.0;
int flag = 0;
for (int i = 0; i < SENSOR_LOG_NUM; i++) {
sum += motion_log[i];
}
float avg = sum / SENSOR_LOG_NUM;
if (avg < 0.2) {
flag = 0;
} else {
flag = 1;
}
motion_avg = flag;
}
void get_coin() {
tone(SPEAKER_PIN, NOTE_B5, 100);
delay(100);
tone(SPEAKER_PIN, NOTE_E6, 850);
//delay(800);
delay(500);
noTone(SPEAKER_PIN);
}
void mario_1up() {
tone(SPEAKER_PIN, NOTE_E6, 125);
delay(130);
tone(SPEAKER_PIN, NOTE_G6, 125);
delay(130);
tone(SPEAKER_PIN, NOTE_E7, 125);
delay(130);
tone(SPEAKER_PIN, NOTE_C7, 125);
delay(130);
tone(SPEAKER_PIN, NOTE_D7, 125);
delay(130);
tone(SPEAKER_PIN, NOTE_G7, 125);
delay(125);
noTone(SPEAKER_PIN);
}
void fire_ball() {
tone(SPEAKER_PIN, NOTE_G4, 35);
delay(35);
tone(SPEAKER_PIN, NOTE_G5, 35);
delay(35);
tone(SPEAKER_PIN, NOTE_G6, 35);
delay(35);
noTone(SPEAKER_PIN);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(57600); // シリアル通信速度
pinMode(ILL_PIN, INPUT);
pinMode(MOTION_PIN, INPUT);
pinMode(DOOR_PIN, INPUT);
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(XBEE_SLEEP_PIN, OUTPUT);
for (int i = 0; i < SENSOR_LOG_NUM; i++) {
temp_log[i] = 0.0;
humid_log[i] = 0.0;
ill_log[i] = 0.0;
motion_log[i] = 0.0;
}
door = 0;
digitalWrite(SPEAKER_PIN, LOW);
digitalWrite(XBEE_SLEEP_PIN, LOW); // XBee Enable
dht.setup(TEMP_HUMID_PIN);
Serial.println("Ready.");
}
void loop() {
delay(2000);
if (loop_count == SENSOR_LOG_NUM) {
loop_count = 0;
}
temp_log[loop_count] = dht.getTemperature();
humid_log[loop_count] = dht.getHumidity();
ill_log[loop_count] = getIlluminance();
motion_log[loop_count] = (float)digitalRead(MOTION_PIN);
door = digitalRead(DOOR_PIN);
// Check if any reads failed and exit early (to try again).
if (isnan(temp_log[loop_count]) || isnan(humid_log[loop_count])) {
Serial.println("Failed to read from DHT sensor! Complement pre-measured value");
fire_ball();
if (loop_count > 0) {
temp_log[loop_count] = temp_log[loop_count - 1];
humid_log[loop_count] = humid_log[loop_count - 1];
} else {
temp_log[loop_count] = temp_log[SENSOR_LOG_NUM - 1];
humid_log[loop_count] = humid_log[SENSOR_LOG_NUM - 1];
}
}
Serial.print(temp_log[loop_count]);
Serial.print(" / ");
Serial.print(humid_log[loop_count]);
Serial.print(" / ");
Serial.print(ill_log[loop_count]);
Serial.print(" / ");
Serial.print(motion_log[loop_count]);
Serial.print(" / ");
Serial.println(door);
loop_count++;
}includeしている”pitches.h”は、Arduino IDEのサンプル”toneMelody”が使用しているものと同一です。複製して同じプロジェクト内に放り込んでやってください。
このソースでは、圧電スピーカーのテストとして、温度/湿度センサから値が取得できなったときに、なぜがマリオがファイアボールを投げる音が鳴るようになっています。。。いや、任天堂が好きなもんで。ちなみにこの音の部分のソースは、以下を参照させていただきました。
さて、次に個人的には難関の、XBeeの設定に入りたいと思います。省電力云々はまずは置いといて、とにかく通信できるようにしたいと思います。
コメント
コメント一覧 (2件)
[…] 今回は、前回作成したArduinoセンサステーションのセンシング情報を、XBeeを使って別のArduino(以前ラピロにシールドとして取り付けたもの)に飛ばします。ラピロ側のArduinoはさらにラピ […]
[…] これについては、「センサステーション」という形で一度作成しているので、必要な方はそちらも合わせてご参考にしてください。ここでは、今回の用途向けに微修正したソースコード […]