編集履歴一覧に戻る
chinyuriのアイコン画像

chinyuri が 2021年05月16日22時28分03秒 に編集

初版

タイトルの変更

+

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

タグの変更

+

obnizBoard1Y

+

obnizIoTコンテスト

+

JavaScript

+

BME680

+

まっちゃねこ

メイン画像の変更

メイン画像が設定されました

本文の変更

+

# はじめに 冬は超乾燥、夏は超暑い...。そんな部屋環境を快適に保ちたい! ということで obniz Board 1Y と AE-BME280 を利用し、 部屋の温度湿度を可視化して環境改善を促す「温湿度計」をつくりました。 つくるにあたって、ただ数値を出すだけではつまらないのと、 快適な温度・湿度の値をいつもすぐ忘れてググる手間を省きたかったので 環境に応じてオリジナルキャラクター「まっちゃねこ」の状態が変わり、 まっちゃねこが快適に過ごせるよう積極的に自分の行動を促せるような作品にしました。 # デモ動画 @[youtube](https://www.youtube.com/watch?v=AkdGCrJzMJo) # まっちゃねこの状態変化について ![](https://camo.elchika.com/2035f6dd2f2f198f2d2527851858bf4fe8086137/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62616431663530642d646666622d343561612d393934382d3034633538386631316139312f35383566333162302d336337652d346434362d393036332d363164616364343961306131/) まっちゃねこの状態変化は8通りあります。 からだと顔を分けた画像を作成し、その画像を状況に応じて HTML / CSS / JavaScript で組み合わせています。 # 設計図 ![](https://camo.elchika.com/943116e24f206316b8df7588884902b9c1aa0752/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62616431663530642d646666622d343561612d393934382d3034633538386631316139312f32393634613439392d613535312d343865352d616263342d643733303339376236663131/) # 部品 | 部品名 | 個数 | 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のはんだづけ 購入したものはピンヘッダがセンサと別々に入っているものだったため、 付属しているピンヘッダを写真のようにはんだづけします。 ![](https://camo.elchika.com/d107fed2fcacdfcf0f8fae89a550614aecc24e2f/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62616431663530642d646666622d343561612d393934382d3034633538386631316139312f62646238393135342d323138362d346237392d623465312d613162616438363766383262/) ### 2. obniz と センサの接続 設計図通りにobniz Board 1Y、ジャンパワイヤ、ブレッドボード、AE-BME280を組み合わせます。 [obniz公式のパーツライブラリ](https://obniz.com/ja/sdk/parts/BME280/README.md)を参考にしましたが、少し違うセンサだったようで、配線に少し手間取りました。 ![](https://camo.elchika.com/c55e605920b0c4ce0dafd0ebeeb021c8fb1a756c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62616431663530642d646666622d343561612d393934382d3034633538386631316139312f63333835386433622d336634392d346463312d613232332d326437663865613032343166/) ### 3. まっちゃねこの素材作成 8通りの状態変化を表現するため、PhotoShop でからだと顔を分けたデータを作成し png で書き出しました。 ![](https://camo.elchika.com/4fc544f5ad237da605c380fd476ab15aafc46ae9/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62616431663530642d646666622d343561612d393934382d3034633538386631316139312f36386339613764652d353232342d343065652d613261362d643132363438376163626130/) ### 4. ソースコード作成 ##### HTML 初めからimgタグで全てのpngを配置しています。 最初は快適ver.のみ配置して、JSで差し替えようと思っていましたが、 そうすると値更新時に毎回画像が点滅してしまったため、この方法にしました。 ```VScode: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 で表示されるようにしています。 首をかしげたようなループアニメーションと、しっぽが揺れるループアニメーション(快適時のみ)も設定しました。生きている感が出て、かわいい...! ```VSCode: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公式のパーツライブラリ](https://obniz.com/ja/sdk/parts/BME280/README.md)を参考にしました。 温度のif文と湿度のif文をそれぞれ書き、該当の状態のクラスを付け外しすることで まっちゃねこの状態を変化させています。 ```VSCode: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でアラートを飛ばしたりするなどの機能を追加していきたいです。 最後までご覧くださりありがとうございました! # 注意 ※本投稿の文書・写真・キャラクターの絵柄などの著作権は ちにゅり に帰属しています。 ※本投稿を参考にして制作してみることは問題ありませんが、第三者による、ちにゅりの許可を得ていないまっちゃねこの商用利用は禁止しています。