M1 MacBook Airの開封レビュー

この記事はM1Mac触ってみたの2日目のエントリです

前回に引き続き今回は開封してみます。

supernove.hatenadiary.jp

MacBook Airには3色ありますが僕はスペースグレーを選びました。

前は古いモデルを使い続けていた名残もあり、シルバーがいいかなと思ったのですが職場で貸与されたProのシルバーの見た目がイマイチなんですよね(逆にずっと使い続けたいと思わないからそれはそれでいいのかもw)。

で、先輩が使っているスペースグレーを見たらそっちのほうがかっこいいなと思ったので、スペースグレーにしました。

付属品は充電器とちょっとしたセットアップガイドとApple製品ではおなじみのAppleステッカーです。

色は本体のカラーに合わせたグレーですね。今までは白しかないと思ってました。

f:id:KMiura:20210430233025p:plain

そして付属の紙を見ると画面を開けると電源が開くようです。

起動の義

というわけでパソコンを開いて最初の起動です。

やっぱり最初の起動ってワクワクしますよね。

その後一通りセットアップを終えていよいよ使い始めます。

インタフェースの接続

M1のMacBookを使うにあたって一番気にしていたことが、USBハブの接続です。

普段仕事で使っているUSB-Cハブは問題なく使えているのですがそれがM1チップでも使えているのかが不安でした。

最初は無印のMacBook(Thundervoltポートが一つしかないやつ)で使っていたのですが、接続の調子が悪いことがちょいちょいあって不便でした。

ただ、仕事で使っているMacBook Proではモニター接続用で使っていますが接続不良がなくストレスなく使えています。

で、M1 MacBook Airではどうなのかと思ってYouTubeを眺めていたらこんな動画を見つけました。


www.youtube.com

Amazonで売ってる安いハブを使うとパソコン本体がぶっ壊れる危険があるということで不安でしたが、OSのアップデートで不具合が解消されているということで恐る恐る使ってみました。

そしたら、普通に使えていましたw。

USBハブに電源を接続すると壊れるということが動画でも言われているのですが、問題なく使えていました。

ついでにノベルティでもらったUSB-Aへの変換アダプタにUSB2.0のハブを接続してみましたがそれも問題なく使えました。

というわけで開封、動作レビューでした。

手持ちのアクセサリーが問題なく使えて無駄な出費がなくなったのは安心しました。

あとは、プライベートの開発環境を構築していくのみですね。

おまけ

普段MacでPCのパフォーマンスをチェックするときに「Run Cat」というアプリを使うのですが、これをM1 Macにインストールしたのですが普通に使えました。

これでCPU、メモリの使用状況を見やすくなりますね。

M1 MacBook Airがやってきた

この記事はM1Mac触ってみたの1日目のエントリです

今の会社に入社して一年が経過しますが、入社してから自腹でパソコンを買ってなかったことに気づきました。

3年ぐらい前にGPU付きのSurface Bookを買いましたが、おそらくそれが最後です。

型落ちで安くなってたとはいえ、学生が簡単に買えるようなパソコンじゃなかったのによく買えたなと我ながら感心してしまいますw。

そして、サブでMacBook Airも持っています。こっちは5年ぐらい前にヤフオクで中古で買いました。

これは大学入学したことから使っていたパソコンがあまりにも貧弱すぎて選んだやつです。

Surface Bookが来るまではこっちがメイン機として活躍しており、このパソコンにはかなり世話になりました。

ただ、2012年頃のモデルということもあり、流石に動作が遅くなってきたこととストレージが128GBで流石に限界が来ました。

なので、新しいMacBookを買うことにしました。

物色開始

というわけで栄のAppleStoreに行こうとしたですが、感染症対策で入店制限があり入ることができませんでした…

仕方なくその近くのヨドバシカメラへ行きました。

正直家電量販店にあまりいい印象がないのですが、ヨドバシはサービスの質がいいので安心感があります。

周り見回せば店員さんがいるので、声もかけやすいです。(同じところに長居すると声をかけてくるのでそこは要注意w)

選定ポイント

Apple製品の売り場を眺めていてかなり悩みましたが、ピッタリのモデルを選ぶための僕なりの選定ポイントをいくつか紹介します。

CPU

まずは肝心なCPUです。

一番最新のMacBookにはAppleシリコンと言われるApple独自のCPUを使われており、これは人によっていろいろ意見が分かれるところです。

僕もどちらかといえばAppleシリコンには否定的でした。

ただ、最近はAppleシリコンに対応したアプリもどんどん増えてきてリリース当初と比べたらだいぶ安定してきた気がします。

そしてMacBookに使われているM1チップは8コアでインテルよりも処理能力が高そうということを期待してAppleシリコンのCPUを選びました。

Apple製CPUということもあってか明らかにインテルのCPUより安くてコスパ良さそうなんですよね。

ちなみにグラフィックのコア数についてはゲームをするわけではないので特にこだわりません。

メモリ

メモリは8GBにします。今まで使っていたMacBook Airが4GBですがそこまでストレスなく使えていて16GBもいらない気がしたので、現行モデルで買える最低のメモリ数で選びました。

ストレージ

ストレージは512GBにしました。環境構築をあれこれしていると256GBなんてあっという間に使ってしまうので避けました。

かと言って1TBはなくてもいい気がするので間とって512GBという感じです。

キー配列

家電量販店の店頭においてあるラップトップのキー配列って大抵JIS配列ですが、最近はUS配列を使うことが多いです。

個人的にはUS配列のほうがプログラムを書くときに効率的なので、今後買うパソコンは絶対にUS配列にしたいというのは譲れない条件です。

その他インターフェース

MacBook ProにはTouch Barがついていますが、MacBook Airにはなくて物理のファンクションキーがついています。

仕事で使っているパソコンにはTouch Barがついていますが、ぶっちゃけ使っててあまり恩恵を受けたわけでもないので別になくてもいいかなと思ってます。

あと、CPUを冷却するファンがMacBook Proにしかついていないです。

負荷の大きい作業をするときにはないと困るかなと思いましたが、あくまでサブ機なのでそんな高負荷な作業をすることを想定していないので、これもなくていいかなと思ってます。

結果

以上の選定ポイントを考えて、選んだのがM1のMacBook Airです。色はスペースグレイです。

他の人のYouTubeやブログを見ても割とMacBook Airは結構人気ありますね。

それにThunderboltのポートがProもAirも2つしかないのでなおさらProを買うメリットをあまり感じません。

それでいざ購入と思ったのですが、さっきも書いたように店頭にはJIS配列のものしかなかったので、US配列のモデルを買えるか聞いたら東京の倉庫には在庫があるそうです。

USキーのラップトップを買うのは初めてなのでわかりませんでしたが普通USキー配列だとお取り寄せで1週間以上はかかるイメージがありましたが、自社で在庫があるのは助かります!

到着まで最短3日で配送料はタダ、これなら連休にじっくり触れることを楽しみにしながら注文して届くのを楽しみに待ちました。

到着

そして今日、無事に手元に届きました!

長くなったので今回はここまで。レビューは次回書こうと思います!

ライブコーディングに挑戦してみた

先日LINE Developer Communityのイベント「LIVE CODING SHOW」でライブコーディングに挑戦しました。

linedevelopercommunity.connpass.com

今までハンズオンやライブデモをやることはありましたが、ライブコーディングは未知の領域でした。

何が起こるか分からないこの感覚を久々に味わってみたいと思い、挑戦してみました。

リハーサル

ライブコーディングの生配信はあまりイメージが無かったので、じっくりリハーサルをするところからはじめました。

用意した機材

基本構成

ライブコーディングの配信に用意した機材として以下のものです。

  • 手元のキーボードが映すカメラ
  • 斜めからの顔のアップを映すカメラ
  • 声とキーボードのタイピング音が拾えるマイク

つまりカメラ2台と外付けマイクを用意しました。

カメラは2台ともLogicoolのC920nを使いました(1台しかなかったので1台は貸してもらいました)

そして、マイクはマランツのUSBコンデンサーマイクを用意しました。スタンドとセット買えるのでそれっぽい雰囲気になりますw。

もちろん音声は申し分ありません。

これらを合わせたセッティングがこんな感じです。

f:id:KMiura:20210401000034p:plain

それっぽいですねw。顔を写すカメラは三脚を使っていて、手元を写すカメラはモニターの上に乗せて最大限下向きになるように調節しました。

スマホのキャプチャ

あとは作ったLINE botスマホ上で動かすデモをするためにスマホの画面をキャプチャするために、Chrome Castを使いました。

これはGoogle Homeが最初に発売された時におまけでついてもので、つい最近まで封を開けていませんでした。

しかしオンラインイベントとかでスマホの画面を使ってデモを見せる機会が増えたのをきっかけに出番が増えるようになりました。

画面を映したいスマホGoogle Homeアプリをインストールしておき、Chrome Castと接続をしてミラーリングを行うとHDMIで画面を出力できるようになります。

あとはUSB接続できるHDMIキャプチャ(中国の通販で手に入るやすいやつ)にChrome Castを接続してパソコン上でスマホ画面を出力するための機材のセッティングは完了です。

パソコンの画面上に投影するときにはWindowsにデフォルトで入ってるカメラアプリでChrome Castを接続したキャプチャを選べば簡単に共有できます。

おそらく入力ソースはUSB VIDEOだと思います。

配信ソフト

配信はGoogle meetからのカメラ画像、画面共有をOBSで合成してYoutubeライブでやってました。

OBSの配信設定はLINE Developer Community事務局の方にやっていただいたので特にここで話すことはありませんw。

Google Meetの接続は当然ライブコーディングをしているパソコンで顔を映していますが、もう1台パソコンを用意して手元を写すようにしました。

なので先程のセッティングに追加でサブPCを用意して2台のPCでGoogle Meetに参加しました。

台座は以前イベントで手に入れたブラウンくんのぬいぐるみの箱がちょうど良かったので活用しましたw。

f:id:KMiura:20210402022945j:plain

また、OBSで顔だけ切り出せるようにするために、顔を映している映像にはグリーンバックの仮想背景をいれています。

これらを合成させた配信イメージがこうなりました。

f:id:KMiura:20210402024854p:plain

モノクロだとなんかかっこいいですよねw。

リハを終えて出てきた課題

さて、リハを終えていくつか課題が出てきました。

モニターの上のカメラからキーボード映しても角度的にキーボードと手元がきれいに映らない

モニターの上にカメラを載せているのは普段そこから顔を映すのにはちょうどいいのですが、手元を映すのには微妙なアングルです。

というわけでキーボードの真上から移せるスタンドを追加でいくつか用意してもらいました。

ブラウザの動作が重い

Google Meetはブラウザ上で動作しているせいかブラウザで検索するだけでも地味に動作が重かったです。

IoTLTで登壇するときもGoogle Meet使っていますが、そのときは仮想背景を使ってなくてブラウザの動作が重くならないのでおそらく背景の切り取り部分でかなり処理が持っていかれているのでしょう。

その割にはZoomより背景の切り取り精度が悪いですねw。

メインPCが配線地獄

これはもうしょうがないですねw。

普段キーボードとトラックボールが有線でそこにカメラ、キャプチャー、マイクを接続してメインPCのUSBが配線地獄でしたw。

パソコンには2つしかUSB端子が無いので、USBハブを2つ接続しました。

f:id:KMiura:20210402232409p:plainf:id:KMiura:20210402232455p:plainf:id:KMiura:20210402232536p:plain

本番

いざ本番、思ってたよりも視聴者数が少ない中でしたが逆に気は楽でしたw。

そして前回の課題を多少解消する形で機材配置を変えました。

f:id:KMiura:20210418020935p:plain

画面が見づらくなりましたが、顔は斜めから映してますし手元は前よりもキーボードが見やすくなったので、絵面的には良くなりました。

配線&機材地獄で世の中のYouTuberの人たちの配信の苦労を味わいましたw。

作業に関しては序盤はいつもの調子でできたのでよかったのですが、だんだん処理が重くなって待つ時間が長くなって結構焦りました。

ネットもそうだしCPUもかなり消費していて辛かったですね…

途中でWifiの接続を確認したらよりによって2.4GHz帯で接続していたことに気づきました。

いつも5GHz帯で接続してたのでどうりで遅かったわけです。

で、接続を変更したらネットワークの問題は解決しました。

でも結局全体の処理の重さの解決には繋がりませんでした。

3年以上使っていたPCなのでそろそろオンライン配信とかで耐えれるPCに買い替えた方がいいのかな…

とはいえ初の試みにしては結構楽しめましたし、見ていただいた方にも「トラブルがあっても動じなくてすごい!」と好評いただき一安心しましたw。

内心はトラブルで焦りましたが、いざ動画を見返すと割と普段の僕をそのまま映しているので変に気張ってないのは良かったかなと思いました(もちろん普段はここまでべらべら喋りながら仕事してるわけじゃないですよw)。

ぜひ次回も挑戦したいです!

編集された完全版

後日、ライブコーディングの様子をきれいに編集してもらい、いい感じにかっこいい動画に仕上がりましたw。

いいところで画面をアップしていたり当日にあった長く待たされたところは切ってもらえたので、かなり見やすいと思います。

(この動画がいいなと思ったら高評価お願いしますw)

www.youtube.com

おまけ

今回のライブコーディングではAzure Functionsを使って実装しましたが、こんな感じのbotを実装(したかった)という記事を以下で公開しているのこちらもよかったらぜひチェックお願いします。

zenn.dev

秋葉原のArduinoガチャで手に入れたArduino nano互換機を動かして詰まりまくった話

先日久々に秋葉原にでかけました。

そこの東京ラジオデパートというところがありまして、そこにはArduino nano互換機やArduinoで使えるセンサー、モジュールなどが出てくるArduinoガチャというのがあります。(ラジオデパートの2階に設置されていますがたまに設置されていないこともあります)

今まで何度かやっているのですが、今回は1発でArduino nano互換機を出してしまいましたw。

互換機を出せたのはいいのですが、今後何かのネタに使えそうなセンサーを求めてさらに2回ガチャをやって期待通り(?)見たこともないセンサーたちを引きました。(このセンサーについてはまた今度書こうと思います)

ガチャで引いた割にはあたりかなと思いましたが、おそらく中国から大量に仕入れたパーツを手に入れたことを考えると1回300円でもと取れているかどうか微妙ですね。

Amazonで調べてみたら画像と一致したものが見つかりました。価格は500円近くしてるので、もとは十分取れてますね。(ちゃんと動けば)

前置きはこのぐらいにして、今回はこのArduinoガチャで手に入れたArduino nano互換機を動かしてみた話です。

ここまで書くと「どうせLチカのプログラム書いて終わりなんだろ?」って思った人もいるかもしれません。

いやいや、動かすまで地味に大変だったんですよw

というわけで開封から見ていきましょう。

開封の儀

早速カプセルあけて中身を確認しました。

中身はガチャらしく商品名の書かれた簡素な紙とArduino nano互換機ボードにピンヘッダだけです。

当然ピンヘッダは実装して無いですがついているだけ良心的ですね。

Arduino nano generic

はんだ付けしてみた

とりあえずピンヘッダをはんだ付けしてみました。

その時に気づいたのですがなんとUSB端子が見事に潰れてました…

これが1つ目の詰まりポイントです。

f:id:KMiura:20210412005048p:plain

ボードはカプセルに入れたまま持って帰ってきたので、これはシンプルに初期不良ですね。

検品ちゃんとやったのかな…?

動かす前から不安ですが、格安の互換機なので気にしてはいけません!

とりあえずUSB接続できないと何も始まらないのでマイナスドライバを使って潰れてるところを無理やりこじ開けてなんとかUSB接続できました。

ブートローダを書き込む

とりあえずLチカのプログラムを書き込もうとしたのですが、シリアルポートでボードを認識しませんでした…

f:id:KMiura:20210412013258p:plain

これだとファームウェアの書き込みができないので、ブートローダーを書き込むことにしました。

やり方は以下の公式ドキュメントにある手順にそってやると簡単にできます。

https://www.arduino.cc/en/Tutorial/BuiltInExamples/ArduinoISP

まずは、ブートローダを書き込むために別のArduinoボードにファイル→スケッチ例→11.Arduino ISP→Arduino ISPファームウェアを書き込みます。

今回は手元にあった純正品のArduino UNOにファームウェアを書き込みました。

f:id:KMiura:20210412014612p:plain

ブートローダが書き込めれば互換機でも大丈夫だと思います。

続いて配線です。Arduino UNOと互換機とは図の通りに配線すれば問題ありません。(図は公式チュートリアルのやつから拝借)

f:id:KMiura:20210412015216p:plain

実際に配線するとこんな感じです。ブレットボードとセットなので撮影がしやすかったです。

f:id:KMiura:20210412015658p:plain

あとは、ツール→書き込み装置→Arduino as ISPを選択してブートローダを書き込むをクリックして書き込みます。

f:id:KMiura:20210412020254p:plain

ドライバのインストール

さてブートローダを書き込んだのでこれでファームウェアを書き込めばいいと思ったのですが、さっきと同じようにシリアルポートを認識せず全然解決しませんでした…

f:id:KMiura:20210412024216p:plain

調べてみたらどうやらこの互換機に使われているシリアル変換チップにはCH340が使われていて別途ドライバのインストールが必要みたいです。

ドライバは以下の南京沁恒微电子股份有限公司のサイトからダウンロードできます。

www.wch-ic.com

サイトにアクセスしたら最新のドライバのインストーラをダウンロードします。

f:id:KMiura:20210412030555p:plain

ダウンロードしたらインストーラを起動して、Installをクリックします。

f:id:KMiura:20210412031132p:plain

インストールを終えたらデバイスマネージャー上でシリアルポートが認識されていれば、ドライバのインストールができています。

f:id:KMiura:20210412031525p:plain

ここまでやって無事にArduino nano互換機でLチカができました。

まとめ

今回は秋葉原のガチャで手に入れたArduino nano互換機を動かしてみました。

とても安いですが、調べないとわからないことだらけで地味に苦戦しました。

Amazonのレビューを見てると今回の作業を試してもうまくいかなかったというコメントもあるようなので、USB端子が潰れててもちゃんと動いたのでまだマシだったのかもしれませんねw。

これで次にArduinoガチャで互換機ゲットした時にはスムーズに作業が進むと思います。(いくつ手に入れれば気が済むのやらw)

MIT App Inventorとmicro:bitでBLE通信をやってみた

普段はサーバーエンジニアとして仕事をしていますが、プログラミングを勉強し始めたときにはサーバーサイドをやりたいという考えはなくて、スマホアプリをやってみたいと思って開発を始めていました。

ただ当時の僕にとってはやはり開発が難しくてあっという間に挫折しましたw。

あとは単純に作りたいものがなくて、モチベーションもなかったんですよね…

あれから4年経った今、職業柄ネイティブアプリのサーバーサイドを開発という形でスマホアプリの開発に携わるようになりました。

そこで改めて今回はネイティブアプリの開発の再入門をするべく、MIT App Inventorをやってみたいと思います。

とりあえずチュートリアルやってみた

公式のチュートリアルでは、ボタンを押したら予め用意した音源を再生するアプリや、入力した文字を読み上げるアプリが用意されており、どちらもチュートリアルどおりに簡単に試せました!

これらのチュートリアルは、以下のリンクで試すことができます。(上記ツイートのアプリはどちらもチュートリアルの内容からアレンジを入れたものです)

appinventor.mit.edu

BLEやってみたい!

とりあえずチュートリアルをいくつかやってみて思ったこととしては、めちゃめちゃ簡単にアプリを作ることができました!

何よりNoCodeでスマホのセンサー、アクチュエータも使えるので作れるアプリのバリエーションも豊富なのがいいですね。

その中にはどうやらBluetoothも使えるようになっており、さらに拡張機能を用意すればBLE通信もできるようです。

ということは、今までネイティブアプリでやってみたかったBLE通信ができるようになるってことですね。

それもノンコーディングで!

というわけで今回の本題である、App Inventorを使ったBLE通信を試してみたいと思います。

そしてせっかくなのでマイコン側もノンコーディングでBLE通信のプログラムをやってみたいと思ったので、micro:bitを使ってみたいと思います。(使用するmicro:bitはV2ではない旧モデルです)

拡張機能のインストール

App InventorでのIoTにまつわるドキュメントは以下のものが見つかりました。

iot.appinventor.mit.edu

そして、運良くmicro:bitを使ったドキュメントも見つかったのでこれを参考にやってみます。

http://iot.appinventor.mit.edu/assets/howtos/MIT_App_Inventor_Microbit_LED.pdf

まずは以下のページの上部にあるBLEの拡張機能のダウンロードします。

iot.appinventor.mit.edu

続いて以下のページの上部にあるmicro:bit拡張機能をダウンロードします。

iot.appinventor.mit.edu

App Inventorで新規のプロジェクトを作成し、Extensionをクリックし、Import extensionから先程インストールした拡張機能を読み込みます。

f:id:KMiura:20210308232421p:plain

アプリのレイアウト

必要な拡張機能を読み込んだところでアプリを作っていきましょう。

今回はBLEで接続したmicro:bitのLEDマトリックスをボタン操作で表示を切り替えるアプリを作っていきます。

f:id:KMiura:20210309213828p:plain

導入したコンポーネントとしてBLEデバイスの認識、デバイスの接続をするためのボタンを上部に配置しています。

ボタンを押したときのステータスをテキストで表示するようにしています。

また、認識したデバイス情報を一覧で出力できるようにリストビューを入れています。

また、ペアリングしたデバイスの操作をするためのボタンも用意しました。

あとは、今回導入した拡張機能の中のBluetoot LEMicrobit_Ledをそれぞれアプリビューに追加します。

この2つはアプリ上には表示されませんがアプリに必要な機能としてスマホ画面の下に表示されます。

また、Microbit_LedについてBLEデバイスとの紐付けを行います。

これによりmicro:bitをBLEで操作できるようになります。

アプリのプログラム

続いてアプリのプログラムを作成します。

プログラムの大枠は以下の画像のようになります。

f:id:KMiura:20210309221134p:plain

上記のプログラムの中にあるcall SmileFacecheckについては以下のブロックを組んだ上で呼び出すブロックになります。

このブロックはmicro:bitマトリックスLEDで描画する図を文字列で指定してそれをマイクロビットに送信するための配列に変換します。

f:id:KMiura:20210309221453p:plain

micro:bitのプログラム

micro:bitは以下のプログラムになります。

今回のアプリであれば最低限LEDサービスが定義出ていればOKです。

ついでにデバイス側でペアリングしたことがわかるようにしてみました。

動作確認

実際に動作確認です。

BLEは機種依存があるので実機で確認する必要があります。

App InventorのコンパニオンアプリをAndroid端末にダウンロードしたらQRとかで読み込んで接続すれば確認できます。

アプリの動作は以下の動画のようになります。

Scanボタンで接続するデバイスを選択して接続できたら、ボタンが2種類表示されてLEDの表示が切り替わります。

まとめ

今回はApp Inventorでmicro:bitとBLE通信をやってみました。

ネイティブアプリを挫折してた人間でも簡単にアプリを作ることができて、しかもBLEまであっという間にできてしまうのは時代の進歩を感じますね(App Inventorはだいぶ前からあるっぽいですがw)。

何よりmicro:bit拡張機能でUUIDとかを考えずにBLE通信ができるのが便利で、アプリもハードもノンコーディングでシステム構築できてしまいました。

Grove Barometer SensorをRaspberry Piで動かしてみた

前回に引き続き積みモジュールネタです。

supernove.hatenadiary.jp

前回はCO2センサーを使いましたが、今回は気圧センサーを使ってみます。

このセンサーはi2cなので、Grove base hatであればi2cの端子に接続すれば大丈夫です。(写真の手前には別のモジュールをつなげています。)

f:id:KMiura:20210214024000p:plain

ところが、このモジュールのPythonサンプルはgrove.pyには無いので代わりに使えそうなサンプルコード探しから始まりました。

探してみるとスイッチサイエンスが公開しているbme280のサンプルがありました。

github.com

bme280とbmp280の違いとしては湿度を取れるか取れないかの違いで、GroveのBMP280のi2cアドレス(0x77)に修正すればこのサンプルはそのまま使えます。

ちなみにbmp280では湿度の測定ができないので、このサンプルを実行すると湿度だけ0になります。

サンプルコード

先程のBME280のサンプルをもとにGroveのBMP280向けにアレンジしたのが以下のコードになります。

smbus2のインストールが必要になりますが、Grove.pyをインストールしていれば別途インストールする必要はないと思います。                                                                                                                                        

# coding: utf-8

from smbus2 import SMBus
import time

bus_number  = 1
i2c_address = 0x77

bus = SMBus(bus_number)

digT = []
digP = []

t_fine = 0.0


def writeReg(reg_address, data):
    bus.write_byte_data(i2c_address,reg_address,data)


def get_calib_param():
    calib = []
    
    for i in range (0x88,0x88+24):
        calib.append(bus.read_byte_data(i2c_address,i))
    calib.append(bus.read_byte_data(i2c_address,0xA1))
    for i in range (0xE1,0xE1+7):
        calib.append(bus.read_byte_data(i2c_address,i))

    digT.append((calib[1] << 8) | calib[0])
    digT.append((calib[3] << 8) | calib[2])
    digT.append((calib[5] << 8) | calib[4])
    digP.append((calib[7] << 8) | calib[6])
    digP.append((calib[9] << 8) | calib[8])
    digP.append((calib[11]<< 8) | calib[10])
    digP.append((calib[13]<< 8) | calib[12])
    digP.append((calib[15]<< 8) | calib[14])
    digP.append((calib[17]<< 8) | calib[16])
    digP.append((calib[19]<< 8) | calib[18])
    digP.append((calib[21]<< 8) | calib[20])
    digP.append((calib[23]<< 8) | calib[22])

    for i in range(1,2):
        if digT[i] & 0x8000:
            digT[i] = (-digT[i] ^ 0xFFFF) + 1

    for i in range(1,8):
        if digP[i] & 0x8000:
            digP[i] = (-digP[i] ^ 0xFFFF) + 1


def readData():
    data = []
    for i in range (0xF7, 0xF7+8):
        data.append(bus.read_byte_data(i2c_address,i))
    pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
    temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
    hum_raw  = (data[6] << 8)  |  data[7]
    
    temp = compensate_T(temp_raw)
    pres = compensate_P(pres_raw)
        
    return temp, pres


def compensate_P(adc_P):
    global  t_fine
    pressure = 0.0
    
    v1 = (t_fine / 2.0) - 64000.0
    v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5]
    v2 = v2 + ((v1 * digP[4]) * 2.0)
    v2 = (v2 / 4.0) + (digP[3] * 65536.0)
    v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8)  + ((digP[1] * v1) / 2.0)) / 262144
    v1 = ((32768 + v1) * digP[0]) / 32768
    
    if v1 == 0:
        return 0
    pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125
    if pressure < 0x80000000:
        pressure = (pressure * 2.0) / v1
    else:
        pressure = (pressure / v1) * 2
    v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096
    v2 = ((pressure / 4.0) * digP[7]) / 8192.0
    pressure = pressure + ((v1 + v2 + digP[6]) / 16.0)  

    return pressure/100


def compensate_T(adc_T):
    global t_fine
    v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1]
    v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2]
    t_fine = v1 + v2
    temperature = t_fine / 5120.0
    return temperature


def setup():
    osrs_t = 1         #Temperature oversampling x 1
    osrs_p = 1         #Pressure oversampling x 1
    mode   = 3         #Normal mode
    t_sb   = 5         #Tstandby 1000ms
    filter = 0          #Filter off
    spi3w_en = 0           #3-wire SPI Disable

    ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode
    config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en

    writeReg(0xF4,ctrl_meas_reg)
    writeReg(0xF5,config_reg)


if __name__ == '__main__':
    setup()
    get_calib_param()
    while True:
        try:
            temp, pres = readData()
            print("Temp:{0:.1f}, Pressure:{1:.1f}hPa".format(temp, pres))
            time.sleep(1)
        except KeyboardInterrupt:
            break

実行すると、以下の用に温度、気圧が出力されます。

いい感じですね👍

Temp:27.2, Pressure:1021.6hPa
Temp:27.2, Pressure:1021.7hPa
Temp:27.2, Pressure:1021.6hPa
Temp:27.2, Pressure:1021.7hPa
Temp:27.2, Pressure:1021.6hPa
Temp:27.2, Pressure:1021.7hPa

これで台風来たときにはすぐにRaspberry Piを起動して気圧取れますね。

おまけ

今回はsmbus2だけを使って動かせるサンプルコードを紹介しましたが、実はbmp280にはPythonライブラリがあり、それを使えばさっきのサンプルコードもほんの数行書くだけで終わりますw。

ライブラリは例によって以下のpipコマンドでインストールします。

sudo pip3 install bmp280

あとは以下のサンプルコードでセンサーの値が取れます。

簡単ですねw。

import time
from bmp280 import BMP280
from smbus2 import SMBus

bus = SMBus(1)
bmp280 = BMP280(i2c_addr=0x77, i2c_dev=bus)

while True:
    temperature = bmp280.get_temperature()
    pressure = bmp280.get_pressure()
    print('{:05.2f}*C {:05.2f}hPa'.format(temperature, pressure))
    time.sleep(1)

ちなみに、前回はライブラリ側のバグがあり修正が必要でしたがこちらは普通に動かせますのでご安心をw

Grove VOC and eCO2 Gas SensorをRaspberry Piで使ってみた

GroveはSeeedが開発したハードウェアのコネクターのシステムです。

最近は多くのセンサーがGroveに対応するようになってGroveで大抵のセンサー測定は事足ります。

その昔、秋葉原で初めてGroveのきっとを見たときは「こんなの買ってもやれること限られるだろ?」と思って買おうと思わなかったんです。(当時はRaspberry PiでGroveが使えることを知りませんでした)

しかし、とあるハッカソンでGroveの心拍センサーを使ったときに「なんか使いやすいなこれ」と思ったんです。

心拍センサーなんてあんまり他で見たことありませんし、なんか扱いが面倒くさそうでしたけどGroveで使えるように設計されていてよくできてるなと感心しました。

それ以来、いろんなGroveのモジュールを買い集めては試すようになり、すっかりGroveの虜になりました。

特にRaspberry Piで使うときにはピンの番号をいちいち調べるのが面倒なのでGrove Base Hat を使ってGroveと連携すればRaspberry PiでGroveモジュールを使うのが簡単になります。

前置きが長くなりましたが、今じゃ気になったGroveモジュールを見つけては買っているとあんまり使う機会がなくそのまま積みモジュールが増えていくわけですw。

で、今回はその積みモジュールの一つである「Grove VOC and eCO2 Gas Sensor」を触ってみたいと思います。

ドキュメント

Seeedから出している大抵のGroveモジュールにはドキュメントが存在します。

もちろん、このモジュールにもドキュメントがあります。

それがこちら↓

wiki.seeedstudio.com

きほんはこれをベースにすすめていきます。

インストール

grove.py

今回は「Grove Base HAT for Raspberry Pi」を使うので、以下のコマンドでgrove.pyをインストールします。

curl -sL https://github.com/Seeed-Studio/grove.py/raw/master/install.sh | sudo bash -s -

ライブラリのインストール

このセンサーにはSGP-30が使われています。そしてこのセンサーを使うときには別途ライブラリーをインストールする必要があります。 ライブラリは以下のコマンドでライブラリをクローンします。

git clone https://github.com/Seeed-Studio/Seeed_Python_SGP30.git
cd Seeed_Python_SGP30
sudo python3 setup.py install

サンプルコードの実行

サンプルコードは公式ドキュメントにある以下のコードを動かしてします。

import seeed_sgp30
from grove.i2c import Bus
 
sgp30 = seeed_sgp30.grove_sgp30(Bus())
while True:
  data = sgp30.read_measurements()
  co2_eq_ppm, tvoc_ppb = data.data
  print("\r  tVOC = {} ppb CO2eq = {}  ".format(
                               tvoc_ppb, co2_eq_ppm))

実行すると以下のエラーが出ました。

ImportError: cannot import name 'SMBusWrapper' from 'smbus2' (/usr/local/lib/python3.7/dist-packages/smbus2/__init__.py)

ドキュメント通りに実行してこんなことになることあるのか?と思うのですが、オープンソースってたまにそういうことありますねw。

で、さすがにこのまま終わるわけにはいかないので、なんとかすることにしました。

なんとかしてみた

このセンサーにはI2Cが使われており、seeed_sgp30の大元のライブラリであるsgp30にはsmbus2が使用されています。

そのときにSMBusWrapperを呼び出そうとしているようです。

とりあえずsmbus2でSMBusWrapperがメソッドとしてあるのか調べてみましたが、それらしき記述は見当たりませんでした。 (それはエラーになるな…)

github.com

そして、sgp30のライブラリのソースを確認してSMBusWrapperがどこで使われるのか確認したら以下のmain関数で使われていました。

def main():
    with SMBusWrapper(1) as bus:
        sgp=Sgp30(bus,baseline_filename=BASELINE_FILENAME+".TESTING")
        print("resetting all i2c devices")
        sgp.i2c_geral_call()
        print(sgp.read_features())
        print(sgp.read_serial())
        sgp.init_sgp()
        print(sgp.read_measurements())
    bus.close()

1箇所だけしか使われていなかったのでこれは修正はそこまで大変ではありませんね。 でもどう修正すればいいのか悩みつつもう一回smbus2のレポジトリのREADMEにあるサンプルコードを眺めてたら以下の記述を見つけました。

from smbus2 import SMBus

with SMBus(1) as bus:
    bus.pec = 1  # Enable PEC
    b = bus.read_byte_data(80, 0)
    print(b)

さっきのmain関数によく似ています。

なんだ、簡単に修正できるじゃないかw。

ライブラリの修正

というわけでRaspberry Piにインストールしたライブラリのソースを直に修正しちゃいます!

修正するのは、/usr/local/lib/python3.7/dist-packages/sgp30/sgp30.pyです。

まずは2行目のライブラリのインポートの記述を以下のように修正します。

from smbus2 import SMBus, i2c_msg

そして、118行目からのmain関数にあるwith構文を以下のように修正します。

修正点としては、SMBusWrapper(1)SMBus(1)にしました。

ついでにwith構文を使っているので関数の一番下にあるbus.close()を削除します。

def main():
    with SMBus(1) as bus:
        sgp=Sgp30(bus,baseline_filename=BASELINE_FILENAME+".TESTING")
        print("resetting all i2c devices")
        sgp.i2c_geral_call()
        print(sgp.read_features())
        print(sgp.read_serial())
        sgp.init_sgp()
        print(sgp.read_measurements())

もう一回動かしてみた

ライブラリを修正できたところでもう一回サンプルコードを動かしてみます。

するとセンサーの値がスムーズに取れました。

いい感じですね👍

  tVOC = 13 ppb CO2eq = 400
  tVOC = 8 ppb CO2eq = 401
  tVOC = 18 ppb CO2eq = 413
  tVOC = 11 ppb CO2eq = 408
  tVOC = 14 ppb CO2eq = 409
  tVOC = 8 ppb CO2eq = 413
  tVOC = 14 ppb CO2eq = 407
  tVOC = 9 ppb CO2eq = 407
  tVOC = 8 ppb CO2eq = 401
  tVOC = 6 ppb CO2eq = 403

センサーの値が変わらないときにはセンサーに軽く息を吹きかけるとセンサーの値が変化すると思います。

まとめ

今回はGrove VOC and eCO2 Gas SensorをRaspberry Piで動かしてみました。

ライブラリの問題でうまく動きませんでしたが、原因が単純で修正も簡単で拍子抜けしました。

ただ動かしてみたネタを書きたかったのに、図らずもエラー対処記録になってしまいましたがネタとしては程よい感じでしたw。

さて、修正をPRしないと…