解説が思いつきません。
タイトルと画像を見ればやりたいことがはっきりわかります。
今回のプロダクト
会話はVS Codeのターミナル上で実施することとしました。
実際の挙動については後述します。
かわいいですね。
環境・デバイス
obniz Board 1Y
マイコン内蔵RGBLED 8mm PL9823-F8
マイクロサーボ 9g SG-90
高精度IC温度センサ LM60BIZ
超音波距離センサー HC-SR04
Node.js v16.10.0
Visual Studio Code 1.60.2
挨拶
気温に応じて、最初の一声を変えてくれます。
機械なので、どうしても暑さには弱いみたいです。
かわいい。
今回は撮影のため、コードを書き換えて色を変えています。
実際は温度条件で色、セリフを変えています。
恥ずかしがり屋
恥ずかしがり屋なので、あまり近づきすぎると照れてしまいます。 かわいい。さよならのとき
別れ際には頭を撫でると、手を振ってバイバイしてくれます。 かわいい。サンプルコード
const Obniz = require('obniz');
const obniz = new Obniz('Obniz_ID');
obniz.onconnect = async () => {
obniz.display.clear();
// led
const rgbled = obniz.wired("WS2811", {gnd: 4, vcc: 5, din: 6});
//温度センサー
const tempsens = obniz.wired('LM60', { gnd: 7, output: 8, vcc: 9 });
const temp = await tempsens.getWait();
// 温度をコンソールに表示
console.log(temp);
// 赤: rgbled.rgb(255, 0, 0);
// 緑: rgbled.rgb(0, 255, 0);
// 青: rgbled.rgb(0, 0, 255);
if(temp < 15.0) {
rgbled.rgb(0, 0, 255);
console.log(`今日は寒いね。${temp}度しかないよ。`)
await obniz.wait(5000);
} else if(temp < 30.0) {
rgbled.rgb(0, 255, 0);
console.log(`今日は${temp}度。過ごしやすいね!`)
await obniz.wait(5000);
} else {
rgbled.rgb(255, 0, 0);
console.log(`${temp}度。暑いねー。熱中症にならないように家の中でだらだらしないと!`)
await obniz.wait(5000);
}
//距離センサー
var hcsr04 = obniz.wired("HC-SR04", {gnd:0, echo:1, trigger:2, vcc:3});
obniz.onloop = async function () {
hcsr04.measure(function( distance ){
//console.log("distance " + distance + " mm");
if (distance > 200) {
rgbled.rgb(0, 255, 0);
} else {
rgbled.rgb(255, 20, 50);
console.log('近いって/// 恥ずかしいじゃん///');
}
});
await new Promise((resolve) => { setTimeout(resolve, 3000) });
};
//サーボモーター
const servo = obniz.wired('ServoMotor', { signal: 11});
let degrees = 90.0;
// スイッチの反応を常時監視
// 「スイッチ状態が変化した瞬間に1回だけ実行される」
obniz.switch.onchange = async function (state) {
if (state === 'right') {
console.log('pushed');
degrees = 180.0;
servo.angle(degrees);
await obniz.wait(400);
degrees = 90.0;
servo.angle(degrees);
await obniz.wait(400);
degrees = 180.0;
servo.angle(degrees);
await obniz.wait(400);
degrees = 90.0;
servo.angle(degrees);
await obniz.wait(400);
}else {
// スイッチが押されていない状態
degrees = 90.0;
console.log('released');
}
}
}
距離センサーでLEDの色を変えるところは、setTimeoutでプログラムのみ停止、サーボモーターはawait obniz.wait(400)で止めてあげると、ちょうど良い挙動でした。
配線
必要に応じて参照ください。
今後の展望|LINEbotとの連携
現状では、こちらの声をobnizに届けることができておりませんので、LINE Messaging APIと連携し、L INE上で会話できるようにしたいと考えました。
現状実装できていないため、折り畳みとさせていただきますが、興味ある方はお読みいただければ幸いです。
サンプルコード
// ########################################
// obniz処理部分
// Obniz_ID:自分のobniz ID(XXXX-XXXX)
// ########################################
const Obniz = require('obniz');
const obniz = new Obniz('Obniz_ID');
// obnizと接続確立したとき
obniz.onconnect = async () => {
const rgbled = obniz.wired("WS2811", {gnd: 4, vcc: 5, din: 6}); // io0 is connected to anode, io1 is cathode
const getObnizTemp = async () => {
const tempsens = obniz.wired('LM60', { gnd: 7, output: 8, vcc: 9 });
const temp = await tempsens.getWait();
if(temp < 15.0) {
rgbled.rgb(0, 0, 255);
console.log(`今日は寒いね。${temp}度しかないよ。`)
await obniz.wait(5000);
} else if(temp < 20.0) {
rgbled.rgb(0, 255, 0);
console.log(`今日${temp}度。過ごしやすいね!`)
await obniz.wait(5000);
} else {
rgbled.rgb(255, 0, 0);
console.log(`${temp}度。暑いねー。熱中症にならないように家の中でだらだらしないと!`)
await obniz.wait(5000);
}
return temp;
}
}
// ########################################
// LINEBot イベント処理部分
// channelSecret:LINE Developers → チャネル基本設定 → チャネルシークレット
// channelAccessToken:LINE Developers → Messaging API設定 → チャネルアクセストークン(長期)
// ターミナルで `ngrok http 3000` 実行後、発行されたURLをWebhook URLとして設定するのを忘れずに
// 「検証」ボタンをクリックするとターミナルにエラーが出ますがここでは問題ありません(検証イベントのハンドリングをしていないため)
// ########################################
const config = {
channelSecret: 'channelSecret',
channelAccessToken: 'channelAccessToken'
};
const line = require('@line/bot-sdk');
const client = new line.Client(config);
// ExpressからMessaging APIイベントを渡されて処理するところ
const handleEvent = async (event) => {
// テキストメッセージ以外を受信したときは何も行わずresolveを返す
if (event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
}
// テキストメッセージを受信したとき
if (event.message.text === '温度教えて') {
// 待ってねというメッセージを「リプライ」で先に返す
await client.replyMessage(event.replyToken, {
type: 'text',
text: '.oO(ちょっと調べてきますねー。)'
});
// obnizの温度センサから値をとってくる(ブロッキング・時間のかかる処理で一旦ここで止まる)
const temp = await getObnizTemp();
// tempが取得できたらそれを含めたメッセージを「プッシュ」で送信する
client.pushMessage(event.source.userId, {
type: 'text',
text: '今の温度は' + temp + '度ですねー。',
});
} else {
// メッセージの中身が「温度教えて」以外だったとき
client.replyMessage(event.replyToken, {
type: 'text',
text: '「温度教えて」と話しかけてね!'
});
}
// resolveを返す
return Promise.resolve(null);
}
// ########################################
// Expressサーバー部分
// ########################################
const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();
// 「(サーバーURL)/webhook」にアクセス(LINEサーバーからのWebhook)があったとき
app.post('/webhook', line.middleware(config), (req, res) => {
// 受信したイベントをターミナルに表示
console.log(req.body.events);
// イベントをhandleEventに渡して1つずつ処理
Promise.all(
req.body.events.map(handleEvent)
).then(
result => res.json(result)
);
});
// PORT番号のポートでサーバーを開始
app.listen(PORT);
console.log('express runnning: PORT =', PORT);
本文中にありました、センサーでの温度取得+LED点灯に加えて、Line上で温度を尋ねると、そのデータを返してくれるように作成しておりましたが、実装できておりません。
温度を取得する関数として定義しているgetObnizTempが、obniz.onconnectの中でしか動かず、Line上で参照しようとしても参照できず、一方で、obniz.onconnectの外に出すと、データの取得はできるのですが、LEDの点灯などが実行されないというジレンマに陥っています。