下の画像のようにラズパイに繋がっているセンサの傾きによって、ブラウザに描画されているキューブの傾きも同じように反映されるよう、svelteとpython(flask)を利用して遊んでみました。
#目次
1.はじめに
2.処理の流れ
3.使用したライブラリ等の説明
4.環境説明
5.ネットワーク図
6.配線図
7.環境構築
8.コード
9.実行コマンド
10.終わりに(感想)
11.参考サイト
#1. はじめに
対象者:
この記事は、svelte初心者でIoT知識があり、Linuxをある程度触れる方を対象としています。
#2. 処理の流れ
1.macPC(svelte)がラズパイのセンサ数値を取得するためにラズパイにGETリクエスト
↓
2.ラズパイのセンサが取得したXYZ軸のデータを数値化
↓
3.ラズパイからmacPCに取得した数値をjson形式でレスポンス
↓
4.MacPCが取得したデータを元にブラウザにsvelthreeを使ってキューブ描画
↓
1に戻り、繰り返し
#3. 使用したライブラリ等の説明
・svelthree
three.jsのsvelte版
今回、キューブを描画する時に傾きXYZを3軸加速度センサの傾きXYZ軸の数値を同じにするように変更している、あとは公式のサンプルコードと同じ
https://svelthree.dev/examples#hello-cube
・flask
pythonの簡易版webフレームワーク
ラズパイに接続している3軸加速度センサの傾きを取得して、svelte側がfetchでラズパイ側にGETリクエストがきたらjsonで数値を返すようにREST APIを立てるために使用。
https://flask.palletsprojects.com/en/1.1.x/
・flask-cors
REST APIのやりとりの関係でCORSというものが必要らしく使用。
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
・3軸加速度センサの数値処理
こちらに関しては勉強不足のため下の記事のコードを利用されていただいております。
http://manabi.science/library/2017/02121501/#figure-1
・i2c
3軸加速度センサをラズパイのGPIOで繋いでやりとりするためのシリアル通信の方式
ラズパイのデフォルトの設定だと無効になっているので有効にしておく必要があります。
GUI操作またはターミナルによるコマンドで有効にできる。
https://www.indoorcorgielec.com/resources/raspberry-pi/raspberry-pi-i2c/
#4. 環境説明
使用部品:
・ラズパイ3
・3軸加速度センサー(型番GY-521)
・ジャンパー線 4本
・Macbook Air 2020上半期
↓Amazonリンク
KKHMF GY-521 MPU-6050 三軸加速度計 ジャイロスコープ 6DOF モジュール
https://www.amazon.co.jp/dp/B019664RAM
I-O DATA Raspberry Pi メインボード Bluetooth(R) Wi-Fi対応モデル Raspberry Pi 3 model B 安心の1年間ハードウェア保証 UD-RP3
https://www.amazon.co.jp/dp/B01NHEBAN5
ELEGOO 120pcs多色デュポンワイヤー、arduino用ワイヤ—ゲ—ジ28AWG オス-メス オス-オス メス –メス ブレッドボードジャンパーワイヤー
https://www.amazon.co.jp/dp/B06Y48V9DL
(GY-521)VCC - 5V (ラズパイ)
(GY-521)GND - GND (ラズパイ)
(GY-521)SCL - GPIO3 (SCL) (ラズパイ)
(GY-521)SDA - GPIO2 (SDA) (ラズパイ)
#7. 環境構築
↓ラズパイ側
$ sudo apt-get install i2c-tools python-smbus
$ pip install Flask==1.0.2
$ pip install Flask-Cors==3.0.9
↓MacPC側
$ npx degit sveltejs/template my-svelthree-app
$ cd my-svelthree-app
$ node scripts/setupTypeScript.js
$ npm install
$ npm install svelthree --save-dev
#8. コード
↓ラズパイ3コード
#!/usr/bin/python
# -*- coding: utf-8 -*-
import smbus
import time
import json
import math
from time import sleep # time module
from flask import Flask, request, Markup, abort, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
DEV_ADDR = 0x68 # device address
PWR_MGMT_1 = 0x6b # Power Management 1
ACCEL_XOUT = 0x3b # Axel X-axis
ACCEL_YOUT = 0x3d # Axel Y-axis
ACCEL_ZOUT = 0x3f # Axel Z-axis
TEMP_OUT = 0x41 # Temperature
GYRO_XOUT = 0x43 # Gyro X-axis
GYRO_YOUT = 0x45 # Gyro Y-axis
GYRO_ZOUT = 0x47 # Gyro Z-axis
bus = smbus.SMBus( 1 )
bus.write_byte_data( DEV_ADDR, PWR_MGMT_1, 0 )
# 1byte read
def read_byte( addr ):
return bus.read_byte_data( DEV_ADDR, addr )
# 2byte read
def read_word( addr ):
high = read_byte( addr )
low = read_byte( addr+1 )
return (high << 8) + low
# Sensor data read
def read_word_sensor( addr ):
val = read_word( addr )
if( val < 0x8000 ):
return val # positive value
else:
return val - 65536 # negative value
# Get Gyro data (raw value)
def get_gyro_data_lsb():
x = read_word_sensor( GYRO_XOUT )
y = read_word_sensor( GYRO_YOUT )
z = read_word_sensor( GYRO_ZOUT )
return [ x, y, z ]
# Get Gyro data (deg/s)
def get_gyro_data_deg():
x,y,z = get_gyro_data_lsb()
# Sensitivity = 131 LSB/(deg/s), @cf datasheet
x = x / 131.0
y = y / 131.0
z = z / 131.0
return [ x, y, z ]
# Get Axel data (raw value)
def get_accel_data_lsb():
x = read_word_sensor( ACCEL_XOUT )
y = read_word_sensor( ACCEL_YOUT )
z = read_word_sensor( ACCEL_ZOUT )
return [ x, y, z ]
# Get Axel data (G)
def get_accel_data_g():
x,y,z = get_accel_data_lsb()
# Sensitivity = 16384 LSB/G, @cf datasheet
x = x / 16384.0
y = y / 16384.0
z = z / 16384.0
return [x, y, z]
@app.route('/test', methods=['GET', 'POST'])
def test():
if request.method == 'GET':
temp = get_temp()
gyro_x,gyro_y,gyro_z = get_gyro_data_deg()
accel_x,accel_y,accel_z = get_accel_data_g()
d = {"gx": '%.3f' % gyro_x, "gy": '%.3f' % gyro_y , "gz":'%.3f' % gyro_z, "ax": '%.3f' % accel_x, "ay":'%.3f' % accel_y, "az":'%.3f' % accel_z}
return jsonify(d)
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=True)
↓MacPC側のコード
<script>
import {
Canvas,
Scene,
PerspectiveCamera,
DirectionalLight,
AmbientLight,
BoxBufferGeometry,
Mesh,
MeshStandardMaterial,
WebGLRenderer,
} from "svelthree";
let cubeGeometry = new BoxBufferGeometry(1, 1, 1);
let cubeMaterial = new MeshStandardMaterial();
let data_json = {"gx": 0, "gy":0 , "gz":0, "ax": 0, "ay":0, "az":0}
async function getfetch(){
let response = await fetch("http://{ラズパイ3のIPアドレス}:80/test");
data_json = await response.json();
console.log(data_json);
console.log("test");
getfetch();
}
</script>
<Canvas let:sti w={500} h={500}>
<Scene {sti} let:scene id="scene1" props={{ background: 0xedf2f7 }}>
<PerspectiveCamera {scene} id="cam1" pos={[0, 0, 3]} lookAt={[0, 0, 0]} />
<AmbientLight {scene} intensity={1.25} />
<DirectionalLight {scene} pos={[3, 3, 3]} />
<Mesh
{getfetch}
{scene}
geometry={cubeGeometry}
material={cubeMaterial}
mat={{ roughness: 0.5, metalness: 0.5, color: 0xff3e00 }}
pos={[0, 0, 0]}
rot={[data_json["ax"], data_json["ay"], data_json["az"]]}
scale={[1, 1, 1]} />
</Scene>
<WebGLRenderer
{sti}
sceneId="scene1"
camId="cam1"
config={{ antialias: true, alpha: true }} />
</Canvas>
<button on:click={getfetch}>取得</button>
<p>gx: {data_json["gx"]}</p>
<p>gy: {data_json["gy"]}</p>
<p>gz: {data_json["gz"]}</p>
<p>ax: {data_json["ax"]}</p>
<p>ay: {data_json["ay"]}</p>
<p>az: {data_json["az"]}</p>
#9. 実行コマンド
↓ラズパイ3側
$ python MPU6050.py
↓MacPC側
$ npm run dev
#10. おわりに(感想)
qiita記事初めて投稿してみました。
まだsvelte初心者で javascriptも初心者な私もsvelteは気軽にかけるのでとても楽しかったです。思い切ってIoTの要素も入れてみました。
#11. 参考サイト
http://manabi.science/library/2017/02121501/#figure-1