「Wio Node」で半田付けなしの電子工作!温度計作りでIoTはじめの一歩
こんにちは、バックエンドエンジニアのちゃんとく(@tokutoku393)です。
今回は、難しいプログラミングや半田付けなしで簡単に試せる「Wio Node」を使って温度表示計を作ってみます!この記事は「WioNodeで始めよう!挫折しないIoT入門ハンズオン 」の資料にもなっています。
かなり長いですが、詳細な手順を載せていますので根気よく頑張りましょう!
Wio Nodeとは
今回使うWio Nodeは、中国のSeeed Studio社が開発したWi-Fiモジュール初期搭載のIoTデバイスです。
Grove規格のモジュールをそのまま挿せるコネクタを搭載していて、はんだづけなしで動かすことができます。モジュールのセットアップも公式のスマートフォンアプリから行うことができ、電子工作初心者でも簡単に試せます。
動かしてみる
早速Wio Nodeを動かしてみましょう。今回は、温度センサと7セグメントディスプレイを使って簡易温度計を作ってみます。
Wio Nodeに接続したモジュール同士は一見つながっているように見えますが、内部で連携する仕組みはありません。それぞれWi-Fiを使ってAPIからインプットやアウトプットを制御します。
以下の手順で作っていきます。
- Wio Nodeのセットアップ
- Wio Nodeにモジュールを接続する
- アプリからAPIを試す
- Node.jsでプログラムを書く
- 試してみる
用意するもの
- Wio Node -> 購入ページ
- Micro USBケーブル
- Grove 温度センサ(型番: SEEED-101020015)
- Grove 7セグメントディスプレイ(型番: SEEED-104030003)
類似のセンサがたくさんありますので、型番をよくご確認ください。(Wio Nodeに対応していない場合があります。)
筆者の環境
- MacBook Pro(Retina 13-inch、Early 2015)
- OS X El Capitan(v10.11.6)
- iOS10.31
- Node.js v7.9.0
- npm 4.5.0
Wio Nodeのセットアップ
まずはWio Nodeの初期設定から進めていきます。
Wio Nodeはモバイルバッテリ・PCなどからUSBケーブルで電源を供給しましょう。
開発用アプリのインストール
Wio Nodeの開発には、公式からリリースされている「Wio Link」というアプリ(Androidの場合は「Wio」)を利用します。執筆時はiOS版は1.5.2、Android版は2.3.6がリリースされています。今回はiOS版を使っての紹介です。
iOS: https://itunes.apple.com/jp/app/wio-link/id1054893491?mt=8
Android: https://play.google.com/store/apps/details?id=cc.seeed.iot.ap&hl=ja
アプリとWio Nodeの設定
アプリを開いたらまずはアカウントを作成しましょう。「SIGN UP」からメールアドレスとパスワードを設定し「Register」で登録します。ServerLocationはデフォルトのGlobalにしておきます。
GmailやFacebookのアカウントを使った登録もできますが、他サービスとの連携でうまくいかないことがあるので非推奨です。
アカウントが作成されたらAdd Your First Deviceをタップし、Wio Nodeを選択します。
Wi-Fi設定
続いてWi-Fi設定をします。手順が少しややこしいので注意してください。
まずは簡単にWio Nodeがインターネットに繋がる仕組みを整理してみます。 デバイスがインターネットに繋がるためには、インターネットに繋がる媒介(=アクセスポイント)が必要です。私たちは普段ルータやポケットWi-Fi(モバイルルータ)を媒介にしていますね。
Wio Nodeも同様に、インターネットに繋がるためにアクセスポイントが必要です。
Wio Nodeにアクセスポイントの情報を教える必要があるので、アドホックモードでWio Nodeとスマートフォンを同じ回線に繋いだ状態にします。
スマートフォンからWio Nodeにアクセスポイント情報を教えてあげると、その後はWio Node自身がアクセスポイントに繋がります。
接続手順が複雑になりますが、この仕組みを押さえておきましょう!
アクセスポイントやWAN/LANについてよくわからない方はドキュメントを参照してください。
Wi-Fi設定手順
まずは画面の指示にしたがってFuncボタン(写真親指側)を4秒以上長押しすると、青いランプがゆらゆらと光ります。
iOSのWi-Fi選択画面から、「Wio_XXXX」というSSIDを選択します。(Androidはアプリ内での選択です。)アドホックモードでWio Nodeとスマートフォンが繋がっている状態です。
アプリに戻ると、続いてWi-Fiの接続を促されます。ネットワークリストから、部屋や会場のWi-Fi(利用するWi-Fi)を選択してパスワードを入力しましょう。アクセスポイント情報を教えてあげた状態です。
Wio Nodeがインターネットに繋がり、登録が完了しました。デバイスに名前をつけておきます。(Android端末で認識がうまくいかない場合、機内モードにして試すと解消することがあるようです。)
アプリからでは失敗する場合は、こちらを参考にWio-Setupというツールを試してみてください。
以上でWio Nodeのセットアップは完了です。同じデバイスとアクセスポイントを使う場合は、以後起動するだけで接続されるようになります!
Wio Nodeにモジュールを接続する
アプリから、接続するモジュールを登録します。 「PORT0」(左側)をタップして、下の「OUTPUT」から「4-Digit Display」を選択しましょう。似たようなモジュールがたくさんありますので、よく確認してください。
続いて温度センサを登録します。「PORT1」(右側)をタップして、「INPUT」から「Temperature Sensor」を選択します。
アプリ画面を参考に、Wio Nodeにモジュールを接続します。 「PORT0」に7セグメントディスプレイ、「PORT1」に温度センサを接続しましょう。
接続できたら、アプリ画面下部の「Update Firmware」をタップしましょう。読み込みのあと、「View API」というAPIサンプルページが表示されるようになります。
Updateが失敗する場合はモジュールの接続が左右間違っていないか今一度確認してください。
アプリからAPIを試す
「View API」のページでは、手軽にモジュールを操作するAPIを試すことができます。正しく接続できているか、試してみましょう。 まずは7セグメントディスプレイの「display_point」というAPIを試してみます。説明部分には、「POSTメソッドで1を送ると”:“が表示される」とありますね。「Test Request」から1を送ってみます。
7セグメントディスプレイに”:“が表示されました。
続いて温度センサのAPIを試します。温度の取得には値は必要ないので、そのままGETメソッドでRequestします。
現在の温度が返ってきました。(かなり暑いですね(笑))
挙動が確認できたら、2つのモジュールを連携させるプログラムを書いていきましょう!
memo: GETメソッドとPOSTメソッド
HTTPリクエストにはいくつかのメソッド(送信方法)があります。GET、POSTの他にもPUTメソッド、DELETEメソッドなどがあり、最近主流の「RESTful API」という考え方では操作する内容によってメソッドを使い分けることになっています。
今回はメソッド名だけわかればプログラミング可能ですが、詳しく知りたい方は調べてみてください!
Node.jsでプログラムを書く
センサの値を取得して、室温をディスプレイに表示するプログラムを書いていきましょう。プログラムはAPIを叩ければよいので、今回はNode.jsで作成します。
プログラムの仕組みを理解するために、以下の手順で説明します。
- Node.jsのインストール
- プロジェクトの作成
- 温度情報を取得する
- 温度情報を表示したい文字列に変換する
- ディスプレイに温度を表示する
- 3秒ごとに更新する
memo: コマンドラインの使い方
Node.jsの実行やファイル操作はコマンドラインで行います。Macには「ターミナル」、Windowsには「コマンドプロンプト」というアプリケーションが最初から入っているので、立ち上げて使いましょう。
初めてコマンドを使う方は、「ターミナル コマンド」などで検索すると基本的な使い方がわかりますよ!
筆者はiTerm2というクライアントアプリにzshというシェルを入れています。(画面がちょっと違うくらいだと思ってください。)
1. Node.jsのインストール
まずはNode.jsのインストールから始めます。またasync/await
という機能を使っているので、v7.6.0以上が必要です。最新版をインストール済みの方は次項の「プロジェクトの作成」から始めてください。
Node.jsのインストールには、簡単にバージョン管理ができる「nvm」や「nodebrew」を使うのが便利です。nodebrewを使ったインストール方法は下記を参照してください。
インストールが完了したら、Node.jsが正しく動くか確認してみましょう。
コマンドラインでnode -v
を叩くとバージョンが出るようになったでしょうか?(v7.6.0以上ですよ!)
Node.jsの環境構築はとても簡単なので、ウェブ開発が初めての方にもオススメです!
memo: コーディング無しで動かしてみる
サクッと試したい方は、githubの完成プログラムをご覧ください。READMEの手順を進めるとコーディングなしで動かせます。
2. プロジェクトの作成
今回のWio Nodeのプログラムを置くプロジェクトを作成しましょう。
適当なディレクトリに移動します。(私は/Users/ユーザ名/workspace
という作業ディレクトリを用意しています。参考まで。)
mkdir ディレクトリ名
で新しいディレクトリを作成できます。wio_temperature
というディレクトリを作ってみました。
cd ディレクトリ名
で作成したディレクトリの下に移動します。
Node.jsでは「npm」でモジュールを管理できます。npm init -y
を実行しましょう。-y
オプションで名前等をデフォルト値で作成してくれます。
プロジェクト名やライブラリなどを管理する「package.json」が作成されました。
今回使用する「axios」ライブラリをインストールします。npm install axios --save
を実行しましょう。--save
オプションをつけることでpackage.jsonに記載されます。
axiosがインストールされ、package.jsonに追加されました。
続いてプログラムを記述するファイルを作成します。touch ファイル名
でファイルが作成されます。(Windowsの場合はコマンドがないのでフォルダから作成してください。)
app.jsというファイルを作成しました。(ls
コマンドでカレントディレクトリのファイルが見れます。Windowsはdir
。)
以上でプロジェクトの作成は完了です。ファイルにプログラムを書いていきましょう!
memo: ファイルの編集とエディタについて
コマンドラインからでもファイルの編集はできますが、インデントやコードの補完が効かず作業しづらいので、テキストエディタを使うのがオススメです。
下記記事ではVisual Studio Codeのインストール方法を紹介しています。
3. 温度情報を取得する
まずは温度を取得するプログラムを書いていきます。BASE_URL
はドメインが違う場合があるので、アプリから確認して自身のものに置き換えてください。
'use strict';
const axios = require('axios');
const TOKEN = process.argv[2] || '';
const BASE_PATH = `https://us.wio.seeed.io/v1/node`; // 自身のものをアプリで確認
/**
* 温度取得
*/
const getTemp = () => {
const ENDPOINT = `/GroveTempA0/temp`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${TOKEN}`;
axios.request({method: 'get', baseURL: BASE_URL})
.then((resp) => console.log(resp));
}
getTemp();
axiosに温度取得APIのURLとオプションを渡し、返ってきた値を出力しています。
const ACCESS_TOKEN = process.argv[2] || '';
の部分は、コマンドライン引数(実行時に渡す値)を取得しています。tokenなどの人に知られたくない値は、ファイルに直接書かないのがベターです。
それでは正しく動くか試してみましょう。node app.js <自分のtoken>
というコマンドで実行します。
ご自身のtokenはアプリのView API画面から確認してください。?access_token=
の後の文字列がtokenです。
温度センサの情報が返ってきたでしょうか?
1番下に温度情報がありますね。この情報を使ってディスプレイに表示する文字列を作っていきます。
エラーが出てしまった人は、「Node.js <エラーメッセージ>」で検索すると答えが見つかりやすいです。
4. 温度情報を表示したい文字列に変換する
取得した温度情報を、ディスプレイに表示する文字列に作り変えるfunctionを作りましょう。
/**
* 取得した温度情報を表示する文字列に変換
*
* @param {number} temp
* @return {string}
*/
const temp2digit = (temp) => {
let temp_str = `${temp}`;
temp_str = temp_str.replace('.', '');
if (temp_str.length >= 4) {
temp_str = temp_str.substr(0, tempstr.length-1);
}
return `${temp_str}C`;
}
temp2digit()の引数には、先ほど受け取った情報の温度部分だけを渡します。
数値を文字列に変換し、不要な’.‘を取り除き、3桁にして、温度計らしく’C’を付けて返します。
これを先ほど作ったgetTemp()と一緒に実行するようにしてみましょう。
'use strict';
const axios = require('axios');
const TOKEN = process.argv[2] || '';
const BASE_PATH = `https://us.wio.seeed.io/v1/node`; // 自身のものをアプリで確認
/**
* 温度取得
*/
const getTemp = () => {
const ENDPOINT = `/GroveTempA0/temp`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${TOKEN}`;
return axios.request({method: 'get', baseURL: BASE_URL}); // ここでは実行しない
}
/**
* 温度情報を文字列変換+Cを追加
* @param {number} temp
* @return {string}
*/
const temp2digit = (temp) =>{
let temp_str = `${temp}`;
temp_str = temp_str.replace('.','');
if(temp_str.length >= 4){
temp_str = temp_str.substr(0,temp_str.length-1);
}
return `${temp_str}C`;
}
async function main(){ // async/awaitを使う
const res = await getTemp();
const temp = res.data.temperature;
const text = temp2digit(temp);
console.log(text);
}
main();
ここではasync/awaitを使っています。awaitで指定したタスクの実行を待ってレスポンスを受け取り、asyncを付けたメソッドを一つのタスクとして処理するような機能です。Node.jsではv7.6.0から導入されました。
実行を待たせるため、getTemp()では、APIの結果ではなくメソッドを返すだけに変更します。
getTemp()で受け取ったobjectの子要素には.
でアクセスします。先ほどのレスポンスのdataの中のtemperatureが欲しいのでres.data.temperature
となります。
node app.js <自分のtoken>
で実行してみます。
温度計の文字列ができました!
次はいよいよこの文字列をディスプレイに表示させます。
5. ディスプレイに温度を表示する
取得した温度の値を使って、ディスプレイに表示するAPIを叩きます。温度の区切りを表すため、最初に試した’:‘を表示するAPIも使ってみましょう。
/**
* ディスプレイに値を表示
*
* @param {number} start_pos
* @param {strng} chars
*/
const fourDigit = (start_pos, chars) => {
const ENDPOINT = `/Grove4DigitUART0/display_digits/${start_pos}/${chars}`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'POST', baseURL: BASE_URL})
}
/**
* : を表示/非表示
* @param {number} display 0|1
*/
const fourDigitPoint = (display) => {
const ENDPOINT = `/Grove4DigitUART0/display_point/${display}`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'POST', baseURL: BASE_URL});
}
fourDigit()のstart_posにはディスプレイ表示の開始位置、charsには表示する文字を渡します。(詳しくはAPIの説明を読んでみてください)
fourDigitPoint()には表示するかどうかの0/1を渡すようになっています。
これまで作ったfunctionと繋げてみます。
'use strict';
const axios = require('axios');
const BASE_PATH = 'https://us.wio.seeed.io/v1/node'; // 自身のものをアプリで確認
const ACCESS_TOKEN = process.argv[2] || '';
/**
* 温度を取得
*/
const getTemp = () => {
const ENDPOINT = `/GroveTempA0/temp`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'GET', baseURL: BASE_URL});
}
/**
* 取得した温度情報を表示する文字列に変換
*
* @param {number} temp
* @return {string}
*/
const temp2digit = (temp) => {
let temp_str = `${temp}`;
temp_str = temp_str.replace('.', '');
if (temp_str.length >= 4) {
temp_str = temp_str.substr(0, tempstr.length-1);
}
return `${temp_str}C`;
}
/**
* ディスプレイに値を表示
*
* @param {number} start_pos
* @param {strng} chars
*/
const fourDigit = (start_pos, chars) => {
const ENDPOINT = `/Grove4DigitUART0/display_digits/${start_pos}/${chars}`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'POST', baseURL: BASE_URL});
}
/**
* : を表示/非表示
* @param {number} display 0|1
*/
const fourDigitPoint = (display) => {
const ENDPOINT = `/Grove4DigitUART0/display_point/${display}`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'POST', baseURL: BASE_URL});
}
async function main() => {
let res = getTemp();
const temp = res.data.temperature;
const text = temp2digit(temp);
console.log(text);
res = await fourDigit(0, text);
res = await fourDigitPoint(1);
}
main();
こちらも試してみましょう。node app.js <自分のtoken>
で実行です。
温度がディスプレイに表示されました!
6. 3秒ごとに更新する
今のままではコマンドを実行した時しか処理が走りません。3秒ごとに実行するようプログラムを変えてみます。
const INTERVAL = 3000;
/**
* 繰り返し実行する
*/
setInterval(() => {
main()
.catch((e) => {
if (e.response) console.log(e.response);
})
}, INTERVAL);
update()の実行部分をsetInterval()関数で繰り返すようにします。setInterval()の第二引数にミリ秒で数値を渡すと、その間隔ごとに実行されます。あとから変更しやすいよう、定数で宣言しておきましょう。
catch()はエラーが発生するとエラーレスポンスを受け取ります。
完成させたコードはこちら。
'use strict';
const axios = require('axios');
const BASE_PATH = 'https://us.wio.seeed.io/v1/node'; // 自身のものをアプリで確認
const ACCESS_TOKEN = process.argv[2] || '';
const INTERVAL = 3000;
/**
* 温度を取得
*
* @return {object}
*/
const getTemp = () => {
const ENDPOINT = `/GroveTempA0/temp`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'GET', baseURL: BASE_URL});
}
/**
* 取得した温度情報を表示する文字列に変換
*
* @param {number} temp
* @return {string}
*/
const tempToDigit = (temp) => {
let temp_str = `${temp}`;
temp_str = temp_str.replace('.', '');
if (temp_str.length >= 4) {
temp_str = temp_str.substr(0, temp_str.length-1);
}
return `${temp_str}C`;
}
/**
* ディスプレイに値を表示
*
* @param {number} start_pos
* @param {strng} chars
* @return {object}
*/
const fourDigit = (start_pos, chars) => {
const ENDPOINT = `/Grove4DigitUART0/display_digits/${start_pos}/${chars}`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'POST', baseURL: BASE_URL})
}
/**
* : を表示/非表示
* @param {number} display 0|1
* @return {object}
*/
const fourDigitPoint = (display) => {
const ENDPOINT = `/Grove4DigitUART0/display_point/${display}`;
const BASE_URL = `${BASE_PATH}${ENDPOINT}?access_token=${ACCESS_TOKEN}`;
return axios.request({method: 'POST', baseURL: BASE_URL});
}
/**
* メインの処理(同期)
*/
async function main() {
let res = await getTemp();
const temp = res.data.temperature;
const text = tempToDigit(temp);
console.log(text);
res = await fourDigit(0, text);
res = await fourDigitPoint(1);
}
/**
* 繰り返し実行する
*/
setInterval(() => {
main()
.catch((e) => {
if (e.response) console.log(e.response);
})
}, INTERVAL);
試してみる
完成コードを試してみます。ドキドキ。node app.js <自分のtoken>
で実行です。
現在の室温が表示されます。
3秒ごとに更新されるので、変化を試すため温度センサを手で温めてみます。
少し温度が上がりました。処理を止めたい場合はcontroll+c
で終了します。
これでプログラムは完成です!やったー!! お疲れ様でした!
補足: 完成の一歩先へ!
「簡単であっという間だった」というあなた!このガジェットを使ってできることはまだまだあります!
- 例1: Azure Web AppsなどのPaaSを使って常時稼働できるようにする
- 例2: 温度情報をAmbientなどのウェブサービスを使ってグラフ化してみる
- 例3: 一定の温度をトリガーにTwitterやSlackへ通知を送ってみる
上記はほんの一例です。Wio Node対応モジュールもたくさんありますので、ここまでの知見を使って試してみましょう!
まとめ
いかがだったでしょうか?簡単と言いつつ、コマンドでの作業やウェブ開発の経験がない人には詰まる部分が多かったかもしれません。でも、これでInternetとThingsの連携ができるようになりました!
IoTの世界には、まだまだたくさんの楽しいデバイスやアイディアが待っています。作っても使っても楽しい電子工作をやっていきましょう!
最後まで読んでくださりありがとうございました!