#はじめに
MaixduinoというESP32とK210を積んだ素晴らしいボードがあったので、ESP32にObniz OSを入れてみようと思った。K210で推論した結果をObniz Cloudを介してネットにデータを吐き出せれば、できることが相当広がりそうとおもったのが動機。
#注意
まず、ここから先の内容はすべて自己責任のもとで行うこと。何かしらの理由で多重課金が発生したりボードなどの破損があっても筆者は一切の責任を負いません。
また、obniz-cli os:flash-createコマンドを実行たびにObniz IDが発行されるため、コマンド実行ごとに150円/月の課金が発生します。 そのため、再インストール時にはobniz-cli os:createを使うこと。
(ちなみに、インストール後の翌月にOSインストール後のデバイスをネットに繋げなければ課金は発生しないはず。)
#環境
- Window10 pro(x64, BootcampにてMacbook proにインストールした)
- node.js 14.15.0 LTS (npm用にインストール)
- Arduino IDE 1.8.13
- Obnizのアカウント(クレカ登録済み)
- Maixduino
- USB typeCケーブル
#Obniz OSをインストールする
まず、Obniz公式Githubの手順に沿ってObniz-cliをインストールする。
まず、MaixduinoとPCをUSBケーブルでつなぐ。obniz-cli os:portsなどでポートを確認すると、ここで2つのCOMポートが認識されるようになっているはず。このポートの一つがK210用、もう一つがESP32用。
筆者の環境では数字の大きい方がESP32用のポートだった。
まず、Obnizクラウドにサインインして、後述のコマンドを実行できるようにする。
obniz-cli signin
次に、コマンドプロンプトないしターミナルで以下のコマンドを入れてObniz OSをインストールする。新規にObniz OSをインストールする際にはここで課金が発生する。
(初めてObnizをインストールする、あるいは新しくObniz IDを発行するときのコマンド)
obniz-cli os:flash-create -p COMなんとか --description "Maixduino"
もしObniz IDを取得した後であったり、Obniz OSの再インストールをする場合はこのコマンドを実行する。
obniz-cli os:erase
#この後ポートを指定する
obniz-cli os:flash -p COMなんとか
最後にESP32の再起動を促されるが、MaixduinoのリセットボタンがESP32につながっていないようなので、USBを抜いてObniz-cliもCtrl+Cで中止して抜ける。
その後にteratermなどでObnizインストール時のCOMポートにアクセスし、Wifiなどの設定を行う。ボーレートは115200でOK。
最後に"Connected Cloud"ならびに"Online"の文字列が出力されたらブラウザからObniz Consoleにアクセスし、赤丸部分が"Active"かつ"Online"になっていればObniz OSのインストールは完了。
#K210と通信・・・しかし!
こちらの顔検出に関する記事を参考に、顔検出▶結果をUARTで送る▶Obniz Cloudに届けるいう流れを作ってみる。
推論に使ったモデルはsipeedのファイル置き場にある"face_model_at_0x300000.kfpkg"を使用した。顔検出に使ったプログラムは下記。推論した結果はjson形式で表現し、文字列として送る。
import sensor
import image
import lcd
from fpioa_manager import fm
from machine import UART
from board import board_info
import KPU as kpu
import json
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
fm.register (6, fm.fpioa.UART1_RX)
fm.register (7, fm.fpioa.UART1_TX)
uart = UART (UART.UART1, 115200, 8, None, 1, timeout=1000, read_buf_len = 4096)
task = kpu.load(0x300000) # you need put model(face.kfpkg) in flash at address 0x300000
# task = kpu.load("/sd/face.kmodel")
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
while(True):
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
for i in code:
uart.write(json.dumps(i)+'\n')
a = img.draw_rectangle(i.rect())
a = lcd.display(img)
a = kpu.deinit(task)
uart.deinit()
del uart
また、Obniz Consoleで新たなリポジトリを作って下記のプログラムを動かす。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://obniz.io/js/jquery-3.4.2.min.js"></script>
<script src="https://unpkg.com/obniz@1.16.1/obniz.js" crossorigin="anonymous"></script>
</head>
<body>
<div id="obniz-debug"></div>
<h1>obniz instant html</h1>
<button id="on">ON</button>
<button id="off">OFF</button>
<div id="print"></div>
<script>
var obniz = new Obniz("");
obniz.onconnect = async function(){
var uart = obniz.getFreeUart();
uart.start({tx: 1, rx: 3, baud:115200 });
uart.onreceive = function(data, text) {
console.log(text.charCodeAt(0));
}
uart.send([0,1]);
}
</script>
</body>
</html>
さて実行サンプルに則ってUARTにて文字列をやり取りしようとすると、GetIOに存在しないピンが〜という旨のエラーが出力されてしまう。また、推論結果の受信に関する処理はマイコンボード上で完結させてしまったほうが後々が楽というのもあり、後述のObniz pluginでUARTの受信処理を書くことにする。
#Obniz pluginでUARTを受け取る
まず、こちらのチュートリアルに則ってArduinoでObnizを使えるようにする。
#include <obniz.h>
#include <string.h>
void onCommand(uint8_t* data, uint16_t length){
Serial.printf("%s",data);
}
bool isOnline = false;
void onEvent(os_event_t event, uint8_t* data, uint16_t length) {
switch (event) {
case PLUGIN_EVENT_NETWORK_CLOUD_CONNECTED:
Serial.println("cloud Connected");
isOnline = true;
break;
case PLUGIN_EVENT_NETWORK_CLOUD_DISCONNECTED:
Serial.println("cloud Disconnected");
isOnline = false;
break;
case PLUGIN_EVENT_NETWORK_HARDWARE_CONNECTED:
case PLUGIN_EVENT_NETWORK_HARDWARE_DISCONNECTED:
case PLUGIN_EVENT_NETWORK_WIFI_SCANNING:
case PLUGIN_EVENT_NETWORK_WIFI_NOTFOUND:
case PLUGIN_EVENT_NETWORK_WIFI_CONNECTING:
case PLUGIN_EVENT_NETWORK_WIFI_SOFTAP_CONNECTED:
case PLUGIN_EVENT_NETWORK_WIFI_FAIL:
case PLUGIN_EVENT_FAIL:
case PLUGIN_EVENT_OTA_START:
case PLUGIN_EVENT_OTA_END:
case PLUGIN_EVENT_OTA_ERROR:
case PLUGIN_EVENT_INITIALIZED:
break;
}
}
void setup() {
Serial.begin(115200);
obniz.commandReceive(onCommand);
obniz.onEvent(onEvent);
obniz.start(NULL);//NULL = obnizOS serial not used for log
while(!obniz.getId());
Serial.printf("obnizID : %s\n",obniz.getId());
Serial.printf("obnizOS : %s\n",obniz.getOsVersion());
}
uint8_t val[1024];
int i = 0;
void loop() {
if(isOnline){
if (Serial.available() > 0){
val[i]= (uint8_t)Serial.read();
if(val[i]==0 || val[i]==10){
obniz.commandSend(val,i);
i = 0;
}else{
i++;
}
}
}
}
このコードではSerial(UART0)から受信した値をobniz.commandSendにてプラグイン経由で送る。
このコードをArduino IDEにてコンパイル&実行する。
環境によっては、esptool.pyが存在しない旨のエラーを吐くかもしれないが、その際にはArduinoインストール時のArduino(Arduino15)フォルダからobnizフォルダを探し、その中からesptool.pyを検索した後にエラーで催促されたフォルダにesptool.pyをコピーすればコンパイル&実行でできるはず。
#console.logから通信確認
再びObniz Cloudでリポジトリを作成し、下記のプログラムを実行する。
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
/>
<link rel="stylesheet" href="/css/starter-sample.css" />
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script
src="https://unpkg.com/obniz@3.9.0/obniz.js"
crossorigin="anonymous"
></script>
</head>
<body>
<div id="obniz-debug"></div>
<div id="print"></div>
<script>
var obniz = new Obniz("");
obniz.onconnect = async function(){
obniz.plugin.onreceive = data => {
console.log((new TextDecoder).decode(Uint8Array.from(data)));
};
}
</script>
</body>
</html>
こんな感じにconsole画面に顔検出データが出てくればビンゴ。
#おわりに
- MaixduinoにObniz OSを入れただけでK210とのUART通信ができなかった。
- Obniz pluginを使ってK210とのUART通信ができた。
- Obniz Pluginを介してObniz Cloudまで推論結果を送ることができた。