「この席寒くない?」をなんとかしたい
オフィスって明らかに場所による温度差がありませんか?
この辺だけやたらと寒いとか。

じゃあ、本当なのかセンサーで調べてみよう!
ということで、今回は温度センサーつないだobnizを複数置くことで
「本当に温度差があるのか」
を検証し、更に、エアコンの向きを自動的に1つずつ変えて
「どの角度なら温度分布が少ないのか」
を自動的に計測するというのをやってみます。
どうやるのか
まずは温度センサーを各机に置きます。
使うのは手元にあったSH31など、いくつかの温度センサーとobnizです。
obniz(オブナイズって読む)はJavascriptからインターネット経由で使える電子回路です。
これならファームウェアを1こずつ用意しなくても手元で動かすjavascriptのプログラム1つから複数のobnizに接続して温度センサーの値をとって集計することができます。それもインターネット経由でできるので、ケーブルなどを気にしなくていいのがいいです。

これをそれぞれの机においてみます。

これで温度を測れそうですね。試しに測ってみます。ついでにheatmap.jsを使ってヒートマップ表示してみました。今回はHTMLにjavascriptを書いてブラウザで開くことで実行しています。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@1.5.1/obniz.js" crossorigin="anonymous"></script>
<script src="自分でビルドしたheatmap.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<h5 id="A"></h5>
<h5 id="B"></h5>
<h5 id="C"></h5>
<h5 id="result"></h5>
<div id="heatmap" style="width:400px;height:320px;"></div>
<script>
var obnizA = new Obniz("OBNIZその1");
var obnizB = new Obniz("OBNIZその2");
var obnizC = new Obniz("OBNIZその3");
var tempA, tempB, tempC;
var tempDiff;
var current_direction = 0;
obnizA.onconnect = async function () {
var sensor = obnizA.wired("SHT31", {vcc : 4, sda:3, scl:2, adr:1, gnd:0, addressmode:5});
obnizA.repeat(async () => {
var temp = await sensor.getTempWait();
temp -= 2;
$("#A").text(''+temp+'℃')
tempA = temp;
update()
})
}
obnizB.onconnect = async function () {
var sensor = obnizB.wired("ADT7410", {vcc:3, gnd:0, sda:1, scl:2, addressMode:8});
obnizB.repeat(async () => {
var temp = await sensor.getTempWait();
$("#B").text(''+temp+'℃')
tempB = temp;
update()
});
}
obnizC.onconnect = async function () {
var tempsens = obnizC.wired("MCP9701", { gnd:0 , output:1, vcc:2});
tempsens.onchange = function(temp){
temp -= 0.5;
$("#C").text(''+temp+'℃')
tempC = temp;
update()
};
}
var heatmap = h337.create({
container: document.querySelector('#heatmap'),
radius: 120
});
function update() {
var avg = (tempA + tempB + tempC)/3
tempDiff = Math.abs(tempA - avg) + Math.abs(tempA - avg) + Math.abs(tempA - avg);
$("#result").text('result = '+tempDiff+' ');
heatmap.setData({
max: 32,
min: 20,
data: [
{ x: 50, y: 100, value: tempA},
{ x: 200, y: 100, value: tempB},
{ x: 350, y: 100, value: tempC}
]
});
}
</script>
</body>
</html>
指で触ると触ったやつだけ熱くなってるのがわかります。(クリックで再生)
温度が取得できたところで、注目するのは温度の分散(σ^0.5)です。
これがあるのかないのか。あったら一番低いのはどこなのかを調べます。
エアコンを操作
あとは、エアコンの角度を1ステップずつ動かします。
obnizに赤外線LEDをつけます。
このオフィスのエアコンは富士通ですが、「風向」のコマンドが公開されていないので、
学習リモコンの要領で出ている赤外線を赤外線センサーでobniz経由で受け取って、保存してそのまま送信してみます。

このオフィスの「風向」はこれで変えられそうです。
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0]
計測開始!
赤外線の部分も含めた全体のプログラムです。
赤外線LEDはある1つのobnizに温度センサーと一緒につないであります。
こいつだけ1台2役ですね。
10分ごとにエアコンの角度を変えて、次に変える前に計測するということをしています。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@1.5.1/obniz.js" crossorigin="anonymous"></script>
<script src="自分でビルドしたheatmap.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<h5 id="A"></h5>
<h5 id="B"></h5>
<h5 id="C"></h5>
<h5 id="result"></h5>
<button id="change_wind">Change</button>
<div id="heatmap" style="width:400px;height:320px;"></div>
<script>
var obnizA = new Obniz("OBNIZその1");
var obnizB = new Obniz("OBNIZその2");
var obnizC = new Obniz("OBNIZその3");
var tempA, tempB, tempC;
var tempDiff;
var led;
var current_direction = 0;
obnizA.onconnect = async function () {
var sensor = obnizA.wired("SHT31", {vcc : 4, sda:3, scl:2, adr:1, gnd:0, addressmode:5});
obnizA.repeat(async () => {
var temp = await sensor.getTempWait();
temp -= 2;
$("#A").text(''+temp+'℃')
tempA = temp;
update()
})
}
obnizB.onconnect = async function () {
var sensor = obnizB.wired("ADT7410", {vcc:3, gnd:0, sda:1, scl:2, addressMode:8});
obnizB.repeat(async () => {
var temp = await sensor.getTempWait();
$("#B").text(''+temp+'℃')
tempB = temp;
update()
});
led = obnizB.wired('InfraredLED', {anode: 9, cathode: 11});
return; // 受信するときは外す。
var irsen = obnizB.wired('IRSensor', {vcc:8, gnd:11, output: 10});
irsen.start(function (arr) {
console.log(JSON.stringify(arr));
})
}
obnizC.onconnect = async function () {
var tempsens = obnizC.wired("MCP9701", { gnd:0 , output:1, vcc:2});
tempsens.onchange = function(temp){
temp -= 0.5;
$("#C").text(''+temp+'℃')
tempC = temp;
update()
};
}
var heatmap = h337.create({
container: document.querySelector('#heatmap'),
radius: 120
});
function update() {
var avg = (tempA + tempB + tempC)/3
tempDiff = Math.abs(tempA - avg) + Math.abs(tempA - avg) + Math.abs(tempA - avg);
$("#result").text('result = '+tempDiff+' ');
heatmap.setData({
max: 32,
min: 20,
data: [
{ x: 50, y: 100, value: tempA},
{ x: 200, y: 100, value: tempB},
{ x: 350, y: 100, value: tempC}
]
});
}
function update_wind_directino() {
current_direction++;
led.send([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0])
}
setInterval(()=>{
console.log(current_direction, tempDiff)
if (current_direction < 8) {
update_wind_directino();
} else {
console.log('DONE!')
}
}, 10 * 60 * 1000); //}, 10 * 1000); // for test
$("#change_wind").click(()=>{ // manual direction update
update_wind_direction();
})
</script>
</body>
</html>
結果
このようになりました。
最も大きな分散で1.6程度です。
センサーの誤差を悪い方に全部足しても1度に行かないので、1.6ということは本当に席ごとに温度の差があることになります。
そして最も温度差が少なかったのは角度4のときでした。
極値が2つ以上あったのはオフィスが小さく風が回り込んだりするからかなぁと思っています。

センサーも3つしか使ってなくて、狭いオフィスでしたが、自動最適化を試すことができました。
スタートボタンだけ押せば自動的に調べてくれるのはいいですね。
センサーを増やしたり場所を変えたり、あとは風向だけじゃなく風の強さを変えたりするとより面白い結果になりそうですね!
参考
obniz ( https://obniz.io/ )