2020年7月13日月曜日

Nginxを使って素の状態のブラウザで視聴可低遅延ライブストリーミングをしてみる(Nginx-http-flv-module)

コロナ禍で!
コロナ禍でライブ配信が注目されてますね。ええ。コロナ禍と言いたかっただけです。
ZOOMのようなビデオチャットや、Youtube Live ニコニコ生放送のような
1対多の生放送アプリまで、実際に集まって行う会議やイベント、
あるいは授業なんかもライブ配信で済ませている。そんな時代が一気に訪れました。
ここではWebRTCなどを使った双方向のビデオチャットではなく、いわゆる映像配信と言われる1対多のストリーミングサービスの話題が中心です。

そんな中、セキュリティの関係もあり自分でライブ配信プラットフォームを作れないかという相談が寄せられた人もいることでしょう。
これまでは、Adobe Media ServerやWowzaを動かしてそこにRTMPで打ち上げ、Flash Playerで視聴といったアプリケーションが一般的でしたが、ライセンス料をはじめ、非常にサーバーのコストがかかりました。
また、映像送信側では現役で使われているRTMPも、現在では視聴環境側のブラウザでは、
RTMPの受信に必須であるFlash Playerのサポートを打ち切られているなどすでに終わった技術になりつつあります。
RTMPで打ち上げるのはいいけどじゃあどうやって見るの?という話になるわけです。

いくつか方法があり、
サーバーでHTTP Live Streaming形式に変換し、HTTPプロトコルでのストリーミング視聴を可能にする
同じくMPEG-DASH形式にしてHTTPプロトコルでのストリーミング視聴を可能にする
主に使われているのはこの2種類です。

どちらも仕組みとしては、配信したい映像を、一定時間に区切ったTSファイルにして、TSファイルの構成を示したプレイリストと一緒にブラウザでダウンロード、プレイリストにしたがって再生、プレイリストを逐次更新してまた新しいTSファイルをダウンロードという形で、HTTP GETを繰り返ししていくことにより映像をつながった状態で見られる仕組みです。

RTMPで打ち上げた映像をそのままHLS形式に変換してくれる機能まで持ったのが、Nginx-RTMP-moduleです。
https://github.com/arut/nginx-rtmp-module
WebサーバーとしてはおなじみのNginxのモジュールで、設定をするとRTMPサーバーとして動作、HLSファイルの生成をONにしてWebサーバーでホストするとTSファイルとM3U8プレイリストを生成して、HLSの配信環境も作ることができます。
これはすでに試している方も多いと思います。
HLSはサポートしているブラウザも多く、スマホでもPCでも安定して視聴できます。
しかし、先に述べた仕組みなので、
TSファイルの長さ分、録画した動画ファイルを生成してからプレイリストに乗せて、ブラウザがダウンロード、再生ということでその分遅延が大きくなります。
このへんは調べるか、実際にやってみるとよく分かると思います。
僕が限界までチューニングした結果3秒くらいの遅延までは縮められましたが、回線が遅くなったりするとすぐ映像が途切れてしまうピーキーな感じになってしまいました。

毎回前置きが長いですが、そこでタイトルのNginx-http-flv-moduleの出番です。
https://github.com/winshining/nginx-http-flv-module
まずはサクッとインストールから。
WSLでUbuntuを使っています。

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev -y

git clone https://github.com/winshining/nginx-http-flv-module.git
wget http://nginx.org/download/nginx-1.19.1.tar.gz
tar -zxvf nginx-1.19.1.tar.gz
cd nginx-1.19.1/
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module \
--with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module \
--with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module \
--with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream \
--with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 \
-fdebug-prefix-map=/data/builder/debuild/nginx-1.19.0/debian/debuild-base/nginx-1.19.0=. -fstack-protector-strong -Wformat -Werror=format-security \
-Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' \
--add-module=./../nginx-http-flv-module

make
sudo make install

sudo vi /etc/nginx/nginx.conf

#追加
include /etc/nginx/streams-enabled/*;

sudo vi /etc/nginx/sites-available/vod

server {
    listen       80;
    server_name  vod.example.com;
    server_name  localhost;

    location /flv {
  flv_live on;
  chunked_transfer_encoding on;
  add_header 'Access-Control-Allow-Origin' '*';
  add_header 'Access-Control-Allow-Credentials' true;
 }
}

sudo mkdir /etc/nginx/streams-available
sudo mkdir /etc/nginx/streams-enabled

sudo vi /etc/nginx/streams-available/rtmp

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;
rtmp {
        out_queue               4096;
        out_cork                8;
        max_streams             8;
        timeout                 15s;
        drop_idle_publisher     15s;

        log_interval            5s;
        log_size                1m;

        server {
                listen 1935;
                server_name rtmp.example.com;
  server_name localhost;

                application rtmp {
                        live on;
                }
        }
}

sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/vod /etc/nginx/sites-enabled/vod
sudo ln -s /etc/nginx/streams-available/rtmp /etc/nginx/streams-enabled/rtmp
sudo /usr/sbin/nginx

こんな感じで設定したらOBSなどでRTMPの配信を受けられます。
そして、プレイヤーの画面を作っていきます。
プレイヤーにはbilibiliのflv.jsを使います。
から、flv.min.jsをダウンロードしてwwwrootに置きます。
同じくプレイヤーのHTMLを作ります。

sudo vi /var/www/html/player.html

<script src="flv.js"></script>
<video id="videoElement" muted autoplay controls></video>
<script>
    if (flvjs.isSupported()) {
        var videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            url: '/flv?port=1935&app=ingest&stream=stream01'
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();
        flvPlayer.play();
    }
</script>

これでhttp://localhost/player.htmlを見ると、
rtmp://localhost/rtmp/stream01宛にRTMPで送った映像が見られます。

仕組みとしては、 /etc/nginx/sites-available/vodに設定を書きましたが、
受け取ったRTMPストリームを、80番ポートで再配信しています。
これにより、RTMPストリーム(FLV)を直接HTTP GETできるようになっています。
Flash playerがないとRTMPを再生できないのは、ブラウザがrtmp://プロトコルをサポートしていないのが主な要因ですが、HTTPプロトコルでストリームが受信できるとなると話は別です。
flv.jsは、RTMP over HTTPのストリームをデコードしてHTML5プレイヤーで再生できます。
視聴中の通信イメージとしては、ずっと配信が続く限り無限に終わらない動画のダウンロードをしている感じです。
実際に試してみると、VPSサーバーに作った配信サーバーでも2秒くらいの遅延で配信ができました。




チャット付きのライブ配信や監視系など、遅延が大きすぎると問題なアプリケーションではとても威力を発揮しそうです。

今更ながらひだまりスケッチを最新巻まで一気読みした感想

Amazonが芳文社セールでKindleの芳文社単行本の一部が77円になっています。
https://amzn.to/2OeWBNvこの機会に、アニメを見てそれなりに好きだったひだまりスケッチを全巻買って、
週末一気に読んでいました。
最新巻だけ通常価格でしたが、一気読みして続きがあるのに読めないのは生殺し感があってそれもホイホイ買ってしまいました。思うつぼです。

ひだまりスケッチのこれまでのイメージ(アニメ1期を全部見ただけ)では、
ほぼほのぼの系のストーリーの中、天然だけどすごい頑張り屋さんのゆのっちがかわいくて応援したくなる感じだなぁくらいに思っていました。
実際1期分のストーリーではそんな感じなのですが、続きを読んで感想が変わりました。

内気で臆病なゆのっちは新しいことをするたびに不安がり、将来の目標もなかなか決まらず深く悩んでしまいます。そんなとき宮ちゃんはいつもコミカルに茶化しながら、さりげなくフォローしています。
これが読み進めていくごとにわかってきて、明るく破天荒ながら優しい宮ちゃんの魅力に引き込まれます。
卒業した沙英先輩の部屋へ行った宮ちゃん。いつも4人で集まりにぎやかだった部屋。
空っぽの部屋で一人、、
このシーンで、人に見せていないながらもやっぱり宮ちゃんはいろいろ考えていたんだろうなぁと確信しました。

他にも、いつもお金がなくお腹を空かせている苦学生の宮ちゃん。これ以上親を頼って大学進学していいのかという葛藤を抱えながら、実家に電話するシーンまで他の人には深く悩んでいる様子を見せませんでした。

10巻まで高校生活の2年半、局面ごとにはゆのっちと同じかそれ以上悩みや葛藤があったはずです。
もっと弱いところを見せてもいいのになと思いますが、もっとずっと弱いゆのっちを、持ち前の明るさで元気付けることで自分も元気をもらっていたのかなと思います。完璧なお姉さんです。

アニメを見た方もぜひ宮ちゃんに注目して単行本も読んでみてください。

2020年6月25日木曜日

やっぱりある程度自由であることが必要だよねって話

なぜか全然寝られなくて、
このブログ購読してる人とかいないはずなので、特に誰の迷惑にもならないかなと
いかにもめんどくさいやつだなってことを書きます。

コロナ禍の最中、テレワークが一気に流行りましたね。
これまで提案はされていても誰もしなかったものが、
右へ倣えで一気にみんながやり始めるというのはインパクトあったと思います。
テレワークでよく問題とされるのが、本当に仕事してるの?という管理の部分。
それが問題とされるたびに嫌な気分になります。
業務時間中はずっとWebカメラの映像が中継伝送されて、
中座して休憩したりするときはボタンを押すこと、
みたいなシステムもあるようです。

衆人環視の下でバリバリ作業を進めていいところ見せてやるぜ
という人もいるのかもしれないし、個人差がある話ではあると思うのですが、
僕自身は人に見られていると思うと(実際には見られていなくても)手が動かなくなってしまうので、
この環境下にいたら、ただでさえ低いパフォーマンスがガタ落ちだろうなと思います。
…というコメントをすると、本来したかった、管理しすぎるのは嫌だよねという話からそれてしまう…。

軌道修正をすると、管理する側からしたら毅然と、勤務中はビシっと100%頑張ってほしいという希望をするのは最もなのかなと思いますが、人間ですから、毎日それじゃ疲れてしまうと思います。
やはり個人差がある話だと思うのですが、僕は集中力がない人間なので、
何か余計なことをしながら本来やるべきことをやるくらいが一番能率が上がると思っています。
本来やるべきことのスレッドと、余計なことのスレッドを立ち上げると、シングルコアCPUなので
本余余本余本余本本余と脳内でスレッドを切り替えていき、10単位時間中に
「5 本来やるべきこと」ができるとします。
これが100%本来やるべきことしかしてはいけないとなると
本本………本…………と、同単位時間あたり
「3本来やるべきこと」になるくらいのイメージです。
「…」の間は何をしてるかというと、「何もしない」をしているか、「本」の進みがすごく遅い状態です。
これ、わかるって人いるんじゃないかと思うんですよ。
ずっと悩んでた問題が寝て起きたら解けるみたいなことあるじゃないですか。
この例ほど極端に集中を解かなくても、ある程度リラックスして、
自由に物事に取り組んだほうがパフォーマンスが上がるという人もそれなりにいると思うのです。

振り返ると、僕自身そういう環境ではそれなりに気に入られたりして、反対に、縛り上げられるような環境だとポンコツになっていたなと。
幼稚園小学校の頃は、子どもだから自由奔放です。

それが中学校に上がると、途端に管理社会が始まります。
学校生活に、生活指導という明示的なルールができました。
「中学生としての自覚を持った行動」
「中学生らしい服装」をはじめ
持ち物、登下校の方法など細則が多数。
10年以上前の話なので、25歳になって考えると、中学生としての自覚とかいうってワードで笑っちゃいますよね。そんなものねーよと。子供じゃん。ただ、当時強権的に、例外なく適用されるこのルールに怯えて生活していました。

すべてのルールに深い意味はなく、「中学生らしい生活態度」というパワーワードでごまかされています。
どの教員も強権的に、思春期の反抗精神の芽を摘むように抑圧してきます。
いやでもやらなきゃいけない。ルールだから。例外はない
という抑圧強権的な環境下で、本来やるべき学びに関してのモチベーションがなくなりました。
毎日学校へは通っていましたが、定期テストや高校入試の模試の結果なんかを見た両親に、本当にお前は学校で何をして来たんだと言われていたレベルで授業は右から左へ聞き流していました。
当時そこまで深く考えてはおらず、学校へ行って何もしないをしていただけなのですが、
意味もなく締め上げられていたストレスでそうなってしまった部分もあるのかなと、10年後にこうやって人のせいにしています。

結局、中学を卒業したあとは、僕が受験した年度、学校の統廃合があって枠が増えたりして、たまたま定員割れしてた工業高校に入りました。
もともと学科の専門分野に興味があったのもあります。今ではライフワークになっています。

高校はある程度自由だと聞いていたのでどんなもんかなと期待を胸に入学しました。
入学当初は、中学校と同じように生活指導の先生がいきなり、
高校はゆるいと思ってる生徒をシメるところから始まり、げんなりしました。
しかし、授業が始まってみると印象が変わりました。
強権的な指導をする先生もいますが、フレンドリーで寛容な先生もいたり、
そもそもルールに異を唱えるような先生までいる…。
ある程度自由にさせてくれる先生の授業はリラックスして取り組めるので頭に入りました。
また、地元の産業の人材育成を担う工業高校だったので、卒業後進路は就職の生徒が半数以上です。卒業後に即戦力!とまではいかなくとも、
実際の業務にどう関わってくるか、この学びがなんの役にやってくるのかということを、
専門科目の先生も、理科や社会、国語の先生も教えてくれました。
生活指導の方法も、近隣住民が困っていてクレームが入ったという、因果がわかりきったことや、学校全体のイメージ低下があると就職の口が狭まる可能性もあるといったリアルな理由をもとに指導していました。クロマティ高校になったらヤバい!というのは生徒間でも共有できていて、治安が保たれていたと思います。
人に迷惑をかけるような、よほどのことをしなければ問題ないわけですし、そりゃ当たり前だよなと納得できました。ルールのせいで、特にやりづらくなることはほとんどありませんでした。

ほとんど自分語りでしたが、自分の観測範囲と主観だけでいうと、
縛り上げすぎるとパフォーマンス落ちる人いるよねー
ルールは最低限がいいよねー
ルールには納得できる理由が必要だよねー
ということが言いたかったがための体験談でした。
中学校の生活は本当にトラウマというか、今でも理不尽さに恨んでいるのでたまに思い出すのです。
先生も忙しすぎて画一的にするしかないのはわかるんですけどね。僕には合わなかったというだけの話かもしれません。

2020年5月17日日曜日

Wio Terminalを使ってGPSなし・Wi-Fiだけで測位してみる(Google Geolocation API使用)


なんだかSeeed StudioのWio Terminalが話題ですね。
秋月やスイッチサイエンスでも取り扱いが始まりましたが、
即在庫切れになったりしているようで大人気みたいです。



会社で買ってもらったので、週末いろいろいじってみました。
内容としてはMicroChipのATSAMD51系MCUに、RealtekのRTL8720DNが乗っていて、
M5Stackのように画面やら何やらいろいろついてケースに入っている豪華マイコンボードです。
公式通販
https://jp.seeedstudio.com/Wio-Terminal-p-4509.html
公式Wiki
https://wiki.seeedstudio.com/jp/Wio-Terminal-Getting-Started/

RealtekのRTL8720DNは、先に出ているESP8266/ESP32とは違い、
5GHzのWi-Fiに対応した新しいWi-Fi搭載マイコンです。
これを早く使ってみたいという人も多かったはずで、
Wio Terminalの登場により、いち早く技適マーク付きの試せる環境が手に入りました。
どうやらメインマイコンのSAMDと、Wi-Fi用のRTL8720DNはSPIでつながっており、
このライブラリでArduino Wi-Fi API互換にラップしていますが、
実は内部ではATコマンドを叩いて通信しているようです。すごい!



さて、本題ですが、せっかくなので温めていたネタを、
この新しいボードで試してみようとやってみたのが今回のWi-Fiを使った測位です。

スマートフォンなんかではよくWi-Fiをオンにするとマップアプリの測位が早くなったり、
正確な位置が表示されやすくなったりするのはご存知な方も多いと思います。
これは、Googleのデータベースから、
飛んでいるWi-Fi APのMACアドレスと緯度経度を紐付けた情報が提供されているから
実現できています。
(Google以外にも、Apple他も同じことをしているのかもしれませんが、
よく知りません。)

あまり知られていませんが、Wi-Fi APの情報から現在位置を推定するAPIは公開されていて、スマートフォンに組み込みの機能以外からもアクセスできるようになっています。
今回はこれを使ってみようと思います。

先に準備を。
Google アカウントにログインして、APIコンソールを開きます。
https://console.developers.google.com/?hl=JA


 すでにプロジェクトがある場合もあると思いますが、
ここでははじめに新規プロジェクトを作っていきます。
Google APIsと書いてある文字の右側をクリックしてプロジェクトの選択画面を表示


新しいプロジェクトボタンをクリック


適当にわかりやすい名前をつけます。


こんな画面に飛ばされたら、APIとサービスを検索の検索窓に
Geolocationと入力




Geolocation APIが出てきたらクリック


有効にする。


左側にある認証情報をクリック


今回は使わないですが、OAuthの同意画面を作成


外部を選択。次の画面の写真はありませんが、
名前の場所だけ埋めればとりあえず使えます。
このへんからはセキュリティに関わってくるので、各自調べながらやってください。


OAuth認証画面が作成できたら、
認証情報のページで認証情報を作成→APIキーをクリック


APIキーが取得できたら準備完了です。

このレポジトリにWio Terminalに書き込むスケッチと、Node.jsスクリプトがあります。

git cloneしてArduino IDEで書き込んだら、SDカードを入れて起動するだけで、
30秒おきにスキャンした周囲のWi-Fi APの情報がSDカードに保存されていきます。

終わったら、PCにSDカード内のbssids.csvをコピーします。
↑のレポジトリに入っている、getloc.jsと同じディレクトリにコピーしてください。

Node.jsの実行環境がない場合は、適当にインストールしてください。
また、CSVパーサーライブラリのインストールが必要です。
適宜
npm install csv-parse
とかやってインストールしましょう。

get_loc.jsを開いて、YOUR_API_KEYの部分に先ほど取得したAPIキーを貼り付けて、
node getloc.js
すると、result.csvというファイル名で緯度経度に変換された結果が保存されます。

読み方ですが、1列目の数字はタイムスタンプ(起動時からのミリ秒)、
2列目に緯度、経度、誤差(m)と続く構造です。

めんどくさがって結果出力をKMLファイルとかにしてないわけですが、
世の中には便利なサイトがありまして、CSVを貼るとKMLにしてくれるサイトがあります。

ここに、CSVの中身を貼って、


こんな設定にしてあげるとあらかんたん、KMLファイルとして出力されます。
(ピンのタイトルがタイムスタンプになります)

Google Mapsのマイマップ機能やGoogle Earthにインポートすると結果が見られます。

こんな感じでわりとかんたんにWi-Fiだけを使った測位ができてしまいます。

Wio Terminalには3G/LTEのようなWWANがありませんが、
テザリングやモバイルルータを使うなどすれば
リアルタイムでの測位も可能と思います。
(その場合はモバイルルータのMACアドレスを除外するなど
ちょっと工夫が必要そうです。)





なお、Google Geolocation APIがなぜそれほど浸透していないのか、
理由はおそらく簡単で、料金だと思います。
↑の画像にも実はチラっと写っていますが、
利用料金なんと1000リクエストで5USDくらいだそうです。
この記事を読んで試す場合、さすがに無料枠内で試せると思いますが、
高頻度で24時間動かし続けたり、商用で何台もクライアントがいると
かなりの金額になりそうです…。

2020年3月3日火曜日

怪我をしたので松葉杖に取り付ける荷重管理デバイスを製作しました。

数年前に下書きを作って公開してない記事でした。令和になって初公開です。

膝の内側を怪我しました。前十字靭帯付着部裂離骨折という骨折のようです。
経緯についてはこちらの動画をどうぞ…

前十字靭帯の付け根にあたる膝の骨を剥離骨折する、
"前十字靭帯付着部裂離骨折"という怪我のようです。
骨にトンネルを開け、ワイヤを通し靭帯と結び、浮いた骨を元の位置に抑える手術をしました。
入院は一週間半、私は大学生で学期末の時期だったので
ちょっと成績的にまずくなったりしましたが、大学生活に疲れ精神的にも参っていた中、
一時の休みを得られてよかったとも感じています。
名医に出会えたので、術後の経過は良好で疼痛もなく順調でしたが、
骨が接合するまでには3ヶ月の時間を要するということで、術後2ヶ月は杖を欠かせませんでした。

術後の経過日数により、はじめの2週間は負傷側の足を地面につくことなく過ごすこと、
次の週は体重の1/3まで掛けてよい…など、徐々に負荷制限が緩和されていきました。
しかし、極度の運動音痴の私は、1/3荷重がこれくらいだと両足別々の体重計に乗せられて、
教えられたところで感覚を覚えられません。負傷側にも体重をかければ、
松葉杖を持つ手は楽なのですが、荷重制限を越えるとどうなるかわかったものではありません。
一方で、荷重を掛けず養生している負傷側はどんどん衰えていき、リハビリの先生には、
「寝たきりの老人並」と言われました。太ももが頬のように柔らかくなったのはショックでした。
荷重を掛けなければ筋肉を取り戻すことはできないのです。

そんなジレンマを抱えつつ、やはりこわいので余り荷重を掛けないようにしていたまま、
全体重の2/3荷重を負傷側に掛けていいと許可されました。
2/3荷重を掛けられると、松葉杖を両手に抱えずに1本で歩く、「片松葉」ができるようです。
以前と同じ荷重のままでは、手に掛かる荷重は両松葉のときの2倍になってしまいます。
右手がボロボロになりながら、ちゃんと2/3荷重を掛けられるようになろう。と考えました。

前置きが長くなりましたが、製作工程を…。

Wii fitというゲーム用コントローラーのバランスWiiボードをAmazonで買いました。
早速バラし…


松葉杖用の先端に取り付けました

テープ固定じゃ心もとないので、Amazonで杖の先のゴム石突部を買って加工しねじ止めしました。


測定値を正確にするために、校正用の機能と設備も用意。


で、ちょいちょいっとしきい値を設定してLEDが点くようにしてみました。

ESP32でBosch BME680の拡張ライブラリ Bsecを使う

少し前に、秋月でも気温・湿度・気圧に加え、MEMSガスセンサを搭載した、
Bosch BME680の取り扱いが始まりましたね。
サクっと4ピン出ていてすぐにI2Cで繋げられそうな感じになっています。
自分は去年しばらくストロベリーリナックスのBME680を使って
しばらく実験していたので、使い方について少しまとめてみます。

BME680は、公開されているデータシートやサンプルコードを使うと
・気温
・湿度
・気圧
・ガスセンサの抵抗値
が取得できるセンサーです。
ガスセンサの構造ですが、電気応用みたいな名前の科目で習った通りだとすると
金属をヒーターで温める→酸化して抵抗値が上がる
周辺の雰囲気に水素などがあると還元されて抵抗値が下がる
という原理で可燃性ガスの有無がわかるという原理だったと思います。
なのでセンサがしっかりと加熱されるまでしばらく新鮮な雰囲気下で動かして、
ベースラインの抵抗値を控えておいて、それより抵抗値が下回ったら
何かガスが出てるなという判断が可能です。

しかし、抵抗値が表示されても相対的な評価しかできないので、
何か単位がついた空気品質の指標が欲しいですよね。

そこでBosch謹製のBsecライブラリというものをご紹介します。
ボッシュのラボテストの結果、センサーから取得できる生データをもとに、
・推定CO2
・IAQ(屋内空気品質)
・推定呼気VOC
・湿度・気温補正値(ヒーターの影響を考慮した値)
を計算してくれるArduinoライブラリです。(RPi版もある)

最新版はGitHubにあります。早速cloneしましょう。

README.mdを読むとわかるのですが、インストールに一癖も二癖もあります。
なぜかというと、BoschはこのBsecライブラリのソースコードを公開していません。
特定環境向けに、コンパイル済みバイナリとヘッダーファイルという形で提供しています。
このコンパイル済みのライブラリを使うために、Arduino IDEに修正が必要です。

現時点で最新のインストール方法についてご説明します。

はじめに、Arduino IDE 1.8.11のポータブル版を用意します。
ここに過去バージョンの一覧があるので入手可能です。
Windows ZIP file for non admin installとあるリンクからZipファイルになったポータブル版をダウンロードして解凍しました。Macの場合は知りません。

解凍したら、できたフォルダにportableという名前のフォルダを作成します。
これですでに入っているArduino IDEとパスを共有しなくなります。
ライブラリやボードマネージャの設定などは入れなおしになります。

フォルダ内のexeからArduino IDEを起動します。
今回はESP32を使うので、ボードマネージャでESP32を使えるように設定し、(省略)
ライブラリをインクルードより、まずは普通にダウンロードした
Bsecライブラリをインポートします。
なお、ESP32ボードのパッケージはv1.0.4を使います。


Arduino 1.8.11のフォルダ\portable\packages\esp32\hardware\esp32\1.0.4
を開きます。



platform.txtを開き、
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.S.extra_flags=
compiler.cpp.extra_flags=
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=

あたりを

compiler.c.extra_flags=
compiler.c.elf.extra_flags=
#compiler.c.elf.extra_flags=-v
compiler.cpp.extra_flags=
compiler.S.extra_flags=
compiler.ar.extra_flags=
compiler.elf2hex.extra_flags=
compiler.libraries.ldflags=
とします。(コメントアウトが増えてるけど公式のやつそのままコピペなので)



さらに、
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" -Wl,--end-group  "-L{build.path}"

の行を

recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group {compiler.libraries.ldflags} -Wl,-EL -o "{build.path}/{build.project_name}.elf" -lm -lgcc

とします。
これでコンパイルが通るようになります。



そして、Arduino IDEを再起動後、スケッチ例→Bsec Software Library→basic
をコンパイルしてみましょう。I2C接続でセンサーデータを取得するサンプルです。
必要に応じて、LED_BUILTINを#define LED_BUILTIN 19のように置き換え
BME680_I2C_ADDR_PRIMARYを0x77(BME680_I2C_ADDR_PRIMARYは0x76)
としてあげると動くと思います。
ESP32の場合、Wire.beginの部分で
Wire.begin(21, 22);のようにピンを置き換えしてあげる必要があります。


成功するとこんな感じでセンサーデータが出てきます。
呼気VOCなんかは簡易アルコールチェッカーとして使えそうだったり、
気温測定の代わりに今流行っているCO2も推定値が出てきます。
また、空気品質もIAQという指標となる値が出てくるため評価しやすい値となっています。

春休みにBME680をいじってみてはいかがでしょうか。

2020年2月16日日曜日

ESP-IDF v4をWindowsのVS Codeで使いやすくしてみる(PlatformIOなし)

https://blog.nyancotech.online/2020/02/windowsesp32esp-idf.html
の続きです。
WindowsでESP-IDF v4環境の構築は上記ページをご覧ください。

まずは普通にインストールされたESP-IDF Command Promptを開きます。



Using Python in C:\Users\admin\AppData\Local\Programs\Python\Python37\
Python 3.7.3
Using Git in C:\Program Files\Git\cmd\
git version 2.25.0.windows.1
Setting IDF_PATH: C:\Users\admin\esp\esp-idf
この部分をメモっておきます。


VS CodeでESP-IDFディレクトリを、「フォルダを開く」から開いたあと、
左下の歯車ボタンから設定を開きます。


Workspaceタブを選択し、Terminal欄をクリック、Edit in settings.jsonをクリック


{
    "terminal.integrated.shellArgs.windows": [
        "cmd",
        "/k",
        "..\\.espressif\\idf_cmd_init.bat",
        "C:\\Users\\admin\\AppData\\Local\\Programs\\Python\\Python37\\",
        "C:\\Program Files\\Git\\cmd\\"
    ]
}
ここに上のJSONを環境に合わせて変更して入力後保存します。
..\\.espressif\\idf_cmd_init.bat

の行には、インストールした.espressifディレクトリ内の
idf_cmd_init.batへのパスを入力してください。
自分は

esp- .espressif
     L esp-idf
というディレクトリ構成にしているので
カレントディレクトリのesp-idfディレクトリから見ると
..\.espressifが.espressifの場所になってます。
Python37というのが書いてある行は、
初めにESP-IDF Command Promptで表示されていた
「Using Python in...」の右に書いてあるディレクトリを入力します。
Git\\cmdというのが書いてある行は、同じく
「Using Git in...」に書かれている行を入力します。

それぞれパスの区切り文字はエスケープ文字として認識されてしまうので、
\\と2つ続けて入力してください。




settings.jsonを保存して、Terminal->New Terminalでターミナルを開くと、
VS CodeからESP-IDF Command Promptが使用できます!
idf.py flash -p COM10とかやればこの画面のまま書き込みまでできます!


2020年2月15日土曜日

【令和最新版】WindowsにESP32開発環境ESP-IDFをインストールする

これまでESP32の開発環境はUnixシェル用のものしか用意されておらず、 Windowsではmsysを使って実行する方法が公式で紹介されていました。 そんな中、最近になって、Espressif純正の一括インストーラが出ていたので試してみました。
https://docs.espressif.com/projects/esp-idf/en/latest/get-started/windows-setup.html

ダウンロードしたexeファイルを開き、インストールしていきます。


必要なパッケージをインストールしてくれますが、Pythonやgitなど、
すでに入っているものがあればそれを選択することで
新しくインストールすることなく進むことができます。
よくできてますね


ESP-IDFのレポジトリをすでにダウンロードしてあれば
そのディレクトリを使うことができます。



ESP-IDFをダウンロードする場合はバージョンを選択できます。
使用するコンポーネントの互換性の問題などがなければ、
4.0を選んだほうが後々アップデートする手間を減らせるかもしれません。


ツールチェーンやPythonの仮想環境を保存する先を選択します。


一発でESP-IDF用のターミナルを開くショートカットを
スタートメニューやデスクトップに登録できます。


各種設定が完了するといよいよインストールです。


ESP-IDFレポジトリはとても大きいのでダウンロードに時間がかかります。



しばらくして、インストールができ…


ませんでした。

表示されたログを見ると、Python virtualenvに
--no-site-packeagesなんてオプションないよと言われています。


はてさてexeファイルの中身に入ってるんだろうしどうしたものかと調べていると、
修正版が出ていました。
下のほうに直リン貼ってる人がいます。




気を取り直してやり直し。


インストールできました。


Pythonのパッケージは専用の環境としてインストールされ、
PATHもシステム標準のものではなく専用のPATHが設定されるようです。
ほかの開発環境と競合せずに動いてありがたいですね。
早速esp-idf\examples\get-started\hello-worldディレクトリで
make menuconfig相当の"idf.py menuconfig"をしてみると…
なんかUnicodeDecodeErrorとか言われています…。


ちょっとぐぐったらこんなすばらしいコピペで動きそうな記事を発見

最近のUnicodeDecodeError

.espressif\python_env\idf4.0_py3.7_env\Lib\site-packages\sitecustomize.py
に上記記事のように
import builtins
__original = open
def __open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None):
    if 'b' not in mode and not encoding:
        encoding = 'utf-8'
    return __original(file, mode, buffering, encoding, errors, newline, closefd, opener)
builtins.open = __open

と記述したファイルを置き、標準のopen関数を上書きしてあげます。


すると…

うーんなんか周り文字化けてるけどとりあえず動いた!



このように、Espressif Systems様が提供してくださっている
Windows版インストーラにより、

簡単にWindowsでの開発環境が作れました!

(正直これでも今までよりは楽だと思います)

あとはメモですが
idf.py menuconfig
でmenuconfig
Serial flusher configでフラッシュの設定ができたりします。
idf.py makeでビルド
idf.py flash -p COMxxでCOMxxポートに接続されたESP32へ書き込み
idf.py monitor -p COMxxでシリアルモニタ(トレースバック付き)
monitor中に
Ctrl+T -> Ctrl+Shift+Fで再書き込み