[iot][arduino][breeding]Arduinoで水槽の温度管理
安価なマイコン基盤であるArduinoを使って、水槽の温度をクラウドサービスを利用してモニタリングし、さらに一定の温度から外れるとアラートをメールしてくれるシステムを作りました。
購入したのは、以下の機材
・Arduino Uno (のクローンの安物、1,000円程度)
・Ethernet Shield for Arduino Uno (のクローンの安物、1,500円程度)
・温度センサー DS18B20
・ブレッドボード
・金属皮膜抵抗器
・ジャンプワイヤキット

ブレッドボードにセンサーの三芯線とArduinoの5V電源、GRD、デジタル入力からのジャンパ線を刺し、サンプルのスケッチを参考に手直しを加えたら完成。
今のところ、室温と4つの水槽の水温(=5つの温度プローブ)を5分ごとに取得し、これをAT&Tのクラウドリソース、m2xにアップロードし、モニタリングしています(実際のサイト)。設定温度から上下1℃以上変動すると、Herokuに置いたアラートが作動してラボのメンバーにメールが通知されるようになっています。今のところ設置してから二か月以上、安定して動作しています。
スケッチは下記のもの。いろいろ試行錯誤した結果、MSTimer2を利用するのが最も安定しているようです。
#include <MsTimer2.h>
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define TEMPERATURE_PRECISION 12
#define ARDUINO_PLATFORM
#include "M2XStreamClient.h"
// MAC address for your Ethernet shield
byte mac[] = { NICのMACアドレス };
// Set the static IP address to use if the DHCP fails to assign
byte ip[] = { NICのIPアドレス };
byte dns_adress[] = { DNSアドレス };
byte gateway[] = { ゲートウェイアドレス };
byte subnet[] = { サブネットマスク };
char deviceId[] = "m2xのデバイスID"; // Device you want to push to
char m2xKey[] = "m2xのキー"; // Your M2X access key
char streamName1[] = { "temp01"};
char streamName2[] = { "temp02"};
char streamName3[] = { "temp03"};
char streamName4[] = { "temp04"};
char streamName5[] = { "temp05"};
const int temperaturePin = 0;
EthernetClient client;
M2XStreamClient m2xClient(&client, m2xKey);
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress temp0 = { DS18B20のデバイスアドレス
例 0x28, 0xFF, 0xB0, 0xA5, 0x8C, 0x16, 0x03, 0x54 };
DeviceAddress temp1 = { };
DeviceAddress temp2 = { };
DeviceAddress temp3 = { };
DeviceAddress temp4 = { };
void setup() {
sensors.begin();
sensors.setResolution(TEMPERATURE_PRECISION);
Serial.begin(9600);
Ethernet.begin(mac, ip, dns_adress, gateway, subnet);
//300000ms毎に記録
MsTimer2::set(300000, timerRecord);
MsTimer2::start();
//while (!Serial) {
// ; // wait for serial port to connect. Needed for Leonardo only
//}
}
void timerRecord() {
// Serial.println("Connected to Ethernet");
// printEthernetStatus();
float temp01, temp02, temp03, temp04, temp05;
sensors.requestTemperatures();
temp01 = sensors.getTempC(temp0);
temp02 = sensors.getTempC(temp1);
temp03 = sensors.getTempC(temp2);
temp04 = sensors.getTempC(temp3);
temp05 = sensors.getTempC(temp4);
// Serial.println(sensors.getTempC(temp0));
// Serial.println(sensors.getTempC(temp1));
// Serial.println(sensors.getTempC(temp2));
// Serial.println(sensors.getTempC(temp3));
// Serial.println(sensors.getTempC(temp4));
int response1 = m2xClient.updateStreamValue(deviceId, streamName1, temp01);
int response2 = m2xClient.updateStreamValue(deviceId, streamName2, temp02);
int response3 = m2xClient.updateStreamValue(deviceId, streamName3, temp03);
int response4 = m2xClient.updateStreamValue(deviceId, streamName4, temp04);
int response5 = m2xClient.updateStreamValue(deviceId, streamName5, temp05);
// Serial.print("M2x client response code: ");
// Serial.println(response);
delay(10000);
}
void printEthernetStatus() {
// print local IP
Serial.print("Local IP: ");
Serial.println(Ethernet.localIP());
// print subnet mask
Serial.print("Subnet Mask: ");
Serial.println(Ethernet.subnetMask());
// print gateway IP
Serial.print("Gateway IP: ");
Serial.println(Ethernet.gatewayIP());
// print dns IP
Serial.print("DNS IP: ");
Serial.println(Ethernet.dnsServerIP());
}
void loop(){}
2019/10/9 追記:
複数(当方の場合、5つ以上)のDS20B18のコードを延長して接続するとエラー値が頻発してしまうが、これはどうも延長したり複数繋ぐとDS20B18自体が抵抗となってしまい、通常の4K7の抵抗を入れると電圧が高くなりすぎる、あるいは電流が微弱になって読み取れなくなるらしい。その場合、抵抗を低いものに変えるとうまく行く(今回は2K2の抵抗に交換)。この現象はarduinoの個体差や配置する環境によっても異なるらしく、原因がわからずに1年ぐらいトラブルシュートに時間がかかってしまった。
