chinyuriのアイコン画像
chinyuri 2021年05月16日作成 (2021年05月16日更新)
製作品 製作品 閲覧数 831
chinyuri 2021年05月16日作成 (2021年05月16日更新) 製作品 製作品 閲覧数 831

obniz Board 1Yで部屋の温湿度をかわいく可視化する「まっちゃねこ温湿度計」をつくってみた

obniz Board 1Yで部屋の温湿度をかわいく可視化する「まっちゃねこ温湿度計」をつくってみた

はじめに

冬は超乾燥、夏は超暑い...。そんな部屋環境を快適に保ちたい!
ということで obniz Board 1Y と AE-BME280 を利用し、
部屋の温度湿度を可視化して環境改善を促す「温湿度計」をつくりました。

つくるにあたって、ただ数値を出すだけではつまらないのと、
快適な温度・湿度の値をいつもすぐ忘れてググる手間を省きたかったので
環境に応じてオリジナルキャラクター「まっちゃねこ」の状態が変わり、
まっちゃねこが快適に過ごせるよう積極的に自分の行動を促せるような作品にしました。

デモ動画

ここに動画が表示されます

まっちゃねこの状態変化について


まっちゃねこの状態変化は8通りあります。
からだと顔を分けた画像を作成し、その画像を状況に応じて HTML / CSS / JavaScript で組み合わせています。

設計図

部品

部品名 個数 URL・補足
obniz Board 1Y 1 https://akizukidenshi.com/catalog/g/gM-14930/
ジャンパワイヤ 6 https://akizukidenshi.com/catalog/g/gC-05371/
ブレッドボード 1 https://akizukidenshi.com/catalog/g/gP-00315/
AE-BME280 (温湿度・気圧センサモジュールキット) 1 https://akizukidenshi.com/catalog/g/gK-09421/
はんだごて 1 AE-BME280のはんだづけ用
はんだ 1 AE-BME280のはんだづけ用
type-Cのコネクタ 1 obniz Board 1Y の電源用
iPad 1 ブラウザ表示ができる端末ならなんでもOK

ツール

ツール名 用途
VSCode HTML / CSS / JavaScript の記述
PhotoShop まっちゃねこの素材作成
ロリポップサーバ 制作したサイトをアップロード。

制作手順

総制作時間は5時間くらいでした。

1. AE-BME280のはんだづけ

購入したものはピンヘッダがセンサと別々に入っているものだったため、
付属しているピンヘッダを写真のようにはんだづけします。

2. obniz と センサの接続

設計図通りにobniz Board 1Y、ジャンパワイヤ、ブレッドボード、AE-BME280を組み合わせます。
obniz公式のパーツライブラリを参考にしましたが、少し違うセンサだったようで、配線に少し手間取りました。

3. まっちゃねこの素材作成

8通りの状態変化を表現するため、PhotoShop でからだと顔を分けたデータを作成し png で書き出しました。

4. ソースコード作成

HTML

初めからimgタグで全てのpngを配置しています。
最初は快適ver.のみ配置して、JSで差し替えようと思っていましたが、
そうすると値更新時に毎回画像が点滅してしまったため、この方法にしました。

HTML

<html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://obniz.com/js/jquery-3.2.1.min.js"></script> <script src="https://unpkg.com/obniz@3.3.0/obniz.js"></script> <link rel="stylesheet" href="./css/screen.css" media="all"> </head> <body> <div id="wrapper"> <div class="matchanekoBox"> <div class="matchanekoBox__body"> <div id="tail" class="matchanekoBox__body__tail-imgBox"> <img src="./img/neko_tail.png"> </div> <div class="matchanekoBox__body__imgBox"> <img src="./img/neko_body.png"> </div> </div> <div class="matchanekoBox__face"> <div id="face_img" class="matchanekoBox__face__imgBox"> <img id="normal" class="view" src="./img/neko_1.png"> <img id="warm" src="./img/neko_0.png"> <img id="cold" src="./img/neko_2.png"> <img id="normal_dry_or_wet" src="./img/neko_5.png"> </div> <div id="effect_img" class="matchanekoBox__face__effect-imgBox"> <img id="dry" src="./img/neko_3.png"> <img id="wet" src="./img/neko_4.png"> </div> </div> </div> <ul class="valueUl"> <li class="valueUl__li"> <p class="txt">温度:</p> <p id="temperature_val" class="valuetxt">Loading...</p> </li> <li class="valueUl__li"> <p class="txt">湿度:</p> <p id="humidity_val" class="valuetxt">Loading...</p> </li> <li class="valueUl__li"> <p class="txt">気圧:</p> <p id="pressure_val" class="valuetxt">Loading...</p> </li> </ul> </div> </body> </html>

CSS

別々に書き出しているからだと顔が繋がるように調整します。
画像の表示・非表示は、表示したい画像にviewクラスをつけると opacity:1 で表示されるようにしています。
首をかしげたようなループアニメーションと、しっぽが揺れるループアニメーション(快適時のみ)も設定しました。生きている感が出て、かわいい...!

CSS

$psd_base_width: 2160; $base_width: 1920; body{ #wrapper { background-color: #ffffe0; transition: all 1s; &.warm { background-color: #ffa04a; } &.cold { background-color: #76d2cb; } .matchanekoBox { position: relative; &__body { position: relative; &__imgBox { position: relative; } &__tail-imgBox { position: absolute; width: calc(140 / #{$base_width} * 100vw); bottom: calc(200 / #{$base_width} * 100vw); right: calc(610 / #{$base_width} * 100vw); &.anim { animation: tailAnim 2s ease-in-out 0s infinite; transform-origin: left center; } } } &__face { position: absolute; width: calc(1379 / #{$psd_base_width} * 100vw); height: calc(881 / #{$psd_base_width} * 100vw); bottom: calc(380 / #{$base_width} * 100vw); right: 0; left: 0; margin: auto; animation: faceAnim 8s ease-in-out 0s infinite; transform-origin: center bottom; &__imgBox { position: relative; } &__effect-imgBox { position: absolute; top: 0; left: 0; width: 100%; } &__imgBox, &__effect-imgBox { img { opacity: 0; position: absolute; top: 0; &.view { opacity: 1; } } } } } .valueUl { position: absolute; top: calc(50 / #{$base_width} * 100vw); left: calc(50 / #{$base_width} * 100vw); &__li { display: flex; justify-content: flex-start; align-items: center; margin-top: calc(10 / #{$base_width} * 100vw); .txt { font-size: calc(16 / #{$base_width} * 100vw); } .valuetxt { font-size: calc(30 / #{$base_width} * 100vw); } &:nth-child(1) { margin-top: 0; } } } } // wrapper } // body @keyframes tailAnim { 0%{ transform: rotate(0deg); } 50%{ transform: rotate(8deg); } 100%{ transform: rotate(0deg); } } @keyframes faceAnim { 0%{ transform: rotate(0deg); } 50%{ transform: rotate(3deg); } 100%{ transform: rotate(0deg); } }

JavaScript

obniz関連のコードは obniz公式のパーツライブラリを参考にしました。
温度のif文と湿度のif文をそれぞれ書き、該当の状態のクラスを付け外しすることで
まっちゃねこの状態を変化させています。

JavaScript(※/bodyタグの直前に記載)

<script> // デバイスに接続 var obniz = new Obniz("XXXX-XXXX"); // obnizのID obniz.onconnect = async function () { // センサに接続 var bme280 = obniz.wired("BME280", {vio:0, vcore:1, gnd:2, csb:3, sdi: 4, sck: 5, sdo:6 }); await bme280.applyCalibration(); await bme280.setIIRStrength(1); setInterval(async function(){ val = await bme280.getAllWait(); // 値を表示 $("#temperature_val").text(val.temperature.toFixed(1) + "℃") $("#humidity_val").text(val.humidity.toFixed(1) + "%") $("#pressure_val").text(val.pressure.toFixed(1) + "hPa") // 温度によって、背景色とまっちゃねこの表情を変更 if (val.temperature.toFixed(1) >= 28) { //28度以上だと暑い判定 $("#wrapper").removeClass('cold'); $("#wrapper").addClass('warm'); $("#tail").removeClass('anim'); $("#normal").removeClass('view'); $("#cold").removeClass('view'); $("#warm").addClass('view'); } else if (val.temperature.toFixed(1) <= 15) { //15度以下だと寒い判定 $("#wrapper").removeClass('warm'); $("#wrapper").addClass('cold'); $("#tail").removeClass('anim'); $("#normal").removeClass('view'); $("#warm").removeClass('view'); $("#cold").addClass('view'); } else { // 27~16度は快適判定 $("#wrapper").removeClass('warm'); $("#wrapper").removeClass('cold'); $("#tail").addClass('anim'); $("#cold").removeClass('view'); $("#warm").removeClass('view'); $("#normal").addClass('view'); } // 湿度によって、乾燥 or じめじめ エフェクト追加 if (val.humidity.toFixed(1) >= 61) { //61%以上だとじめじめ判定 $("#dry").removeClass('view'); $("#wet").addClass('view'); $("#tail").removeClass('anim'); // 温度快適な表情であれば、表情を差し替え if ($("#normal").hasClass('view')) { $("#normal_dry_or_wet").addClass('view'); } } else if (val.humidity.toFixed(1) <= 39) { //39%以下だと乾燥判定 $("#wet").removeClass('view'); $("#dry").addClass('view'); $("#tail").removeClass('anim'); // 温度快適な表情であれば、表情を差し替え if ($("#normal").hasClass('view')) { $("#normal_dry_or_wet").addClass('view'); } } else { $("#wet").removeClass('view'); $("#dry").removeClass('view'); $("#tail").addClass('anim'); // 温度快適でも微妙な表情であれば、表情を差し替え if ($("#normal_dry_or_wet").hasClass('view')) { $("#normal_dry_or_wet").removeClass('view'); $("#normal").addClass('view'); } } }, 1000); } </script>

おわりに

ずっとつくってみたかった温湿度計を、まっちゃねこと組み合わせて作れたのが嬉しかったです。
コンテンツはWebサイトとして実装できたため、obnizとセンサさえ持ち歩いていれば会社、旅行先、展示会場など様々な場所でいつでも計測し環境改善できるようになったので活用していきたいです。

さらに作品を活用するために、気圧も組み合わせて偏頭痛を予測したり、環境改善した方が良い時にLINEでアラートを飛ばしたりするなどの機能を追加していきたいです。

最後までご覧くださりありがとうございました!

注意

※本投稿の文書・写真・キャラクターの絵柄などの著作権は ちにゅり に帰属しています。
※本投稿を参考にして制作してみることは問題ありませんが、第三者による、ちにゅりの許可を得ていないまっちゃねこの商用利用は禁止しています。

1
ログインしてコメントを投稿する