modalsoul’s blog

これは“失敗”と呼べるかもしれないが、ぼくは“学習体験”と呼びたい

M5StickC PlusとMH-Z19Bで二酸化炭素濃度を計測する

WFHだとオフィスと違い空間が狭く空調が効いていないので、どうしても二酸化炭素濃度が上昇しがち

CO₂センサーガジェットが色々リリースされているけれど、CO₂センサーモジュールとM5StickC PlusでCO₂センサーを作ってみた。

MH-Z19B

非分散型赤外線(NDIR)方式のCO₂センサー(ただし、これはMH-Z19Bのfake品らしい)

そこそこ安かったし、動作は問題なさそうなので気にしない

構成

M5StickC PlusとMH-Z19Bで計測し、Googleスプレッドシートに記録する。

実装

Googleスプレッドシート

M5StickC Plusからjsonを受け、受信した日時とppm値をスプレッドシートに追記していく。

function doPost(e) {
  var ss  = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('シート1');
  var PostData = JSON.parse(e.postData.contents);
  var date = new Date();
  var now = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');
  sheet.appendRow([now, PostData.co2]);
  return ContentService.createTextOutput('OK');
}

M5StickC Plus

配線

f:id:modal_soul:20210616220155j:plain

MH-Z19Bに付属したケーブルを切断しジャンパケーブルと接続している。

M5StickC Plus MH-Z19B
5V V+(緑)
GND V-(青)
G26 Rx(黒)
G0 Tx(黄)

ライブラリ

github.com

コード

計測は5分間隔。計測したCO₂濃度はM5StickC Plusのディスプレイにも表示する。1

#include <HTTPClient.h>
#include <M5StickCPlus.h>
#include <MHZ19_uart.h>
#include <WiFiMulti.h>

#define INTERVAL 300000
#define RX_PIN 0
#define TX_PIN 26

const char* ssid     = "<SSID>";
const char* password = "<PASSWORD>";
String url = "https://script.google.com/macros/s/****/exec";
MHZ19_uart myMHZ19;
WiFiMulti wifiMulti;

void setup() {
  M5.begin();
  myMHZ19.begin(TX_PIN, RX_PIN);
  myMHZ19.setAutoCalibration(true);
  wifiMulti.addAP(ssid, password);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setRotation(1);
}

void updateDisplay(int ppm) {
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10, 10);
  M5.Lcd.printf("CO2: %d ppm\n", ppm);  
}

void storePPM(int ppm) {
  if((wifiMulti.run() == WL_CONNECTED)) {
    HTTPClient http;  
    http.begin(url);
    http.addHeader("Content-Type", "Content-Type: application/json");
    int httpCode = http.POST("{\"co2\":\"" + String(ppm) + "\"}"); 
    if(httpCode <= 0) {
      M5.Lcd.printf("Store failed, error:%s\n", http.errorToString(httpCode).c_str());
    }
  }
}

void loop() {
    int ppm;
    ppm = myMHZ19.getPPM();
    updateDisplay(ppm);
    storePPM(ppm);
    delay(INTERVAL);
}

計測結果

f:id:modal_soul:20210618003950p:plain

絶対値の精度はいまいち不明だが、傾向は把握できたのでOK

自作PCビルドログ

ValheimのためにPCを組んだので、ビルドログを残しておく。

パーツリスト

種類 パーツ 価格
CPU AMD Ryzen 5 3600 ¥23,973
メモリ CORSAIR CMK32GX4M2E3200C16 ¥19,700
マザーボード GIGABYTE B550I AORUS PRO AX ¥19,164
グラフィックスカード MSI GeForce GTX 1080 SEA HAWK X ¥4,2400
SSD XPG SX8100 512GB ¥7,051
ケース Cooler Master MasterBox NR200 ¥6,636
電源 Corsair SF750 PLATINUM 750W ¥18,867
合計 ¥137,791

Valheimはローポリゲーでビッグパワーは必要としないので、性能よりもコストを重視。置き場所の問題で小型PCケース NR200を選んだ。 ケース以外のパーツはNR200で組んだ事例を参考にパーツを選んだ。

text.sanographix.net

価格高騰かつ品薄なグラフィックスカードだけはメルカリで中古パーツを購入。

GeForce GTX 1080 SEA HAWK XはCorsair Hydro H55を搭載した水冷・空冷のハイブリッドで、水冷部分がケースに収まるか心配だったが、結果としては何も問題なかった。

写真

  • マザーボードにCPU、CPUファン、メモリ、SSDを装着した状態。M.2のSSDマザーボード下部のカバー内に装着されている。 f:id:modal_soul:20210328193700j:plain

  • NR200のパネルと上部のフレームを外した状態。パネルは工具なし、フレームもプラスドライバー一本で外せるので楽。 f:id:modal_soul:20210328194817j:plain

  • マザーボードと電源、グラフィックボードを取付けた状態。水冷ラジエーター・ファンは手前のサイドパネルに固定した。 f:id:modal_soul:20210328211246j:plain

  • 上から見た状態。上部右手が電源ユニット、左手がマザーボード、下部がグラフィックカードの水冷ラジエーター・ファン f:id:modal_soul:20210328211306j:plain

  • 完成。問題なく一発起動。 f:id:modal_soul:20210328225635j:plain

Windows10 Proをインストール。起動も早いし、Valheimも一番リッチなグラフィック設定にしてもすいすい動く。

とても快適な環境に仕上がったと思う。

2段階認証を有効にした状態でKindle端末にアカウント登録をする方法

Kindle Oasisでアカウント登録に失敗した際のトラブルシューティングのメモ

症状

  • Kindleのセットアップ時、
    • Amazonアカウントを選択
    • ID/Password入力
    • 2段階認証のOTP入力
    • 最初に戻る

の繰り返しになる

サポートからの連絡

前提

サポートからの連絡を受ける前に、2段階認証の第1手段をSMSに変更

手順

  • Amazonアカウントの選択から2段階認証のOTP入力画面まで遷移
    • このとき、SMS宛にOTPが送信される
  • OTPを入力せずに、最初に戻る
  • Amazonアカウントの選択から、ID/Password入力画面を表示
  • Password入力欄に以下のフォーマットで入力
    • {password}{otpコード}

passwordとotpコードの間には何も含めない

2段階認証の方法をSMSにしたが、Authenticatorでも同様の方法で登録できるのかはわからない

M5StickC PlusからBLEでSwitchBotを操作する

M5StickC PlusからSwitchBotを操作したメモ

モノ

準備

操作対象のSwitchBotのDevice UUIDとService UUIDを確認する

今回はiPhoneアプリのBLE Scannerを使用

コード

BLEDeviceの特定

SwitchBotのアドバタイズをスキャンして、デバイスを特定する

ボタン操作の検知

M5.updateでボタンの読み取り状態を更新し、M5.BtnA.wasPressed()で押下を判定

コマンドの送信

setupでスキャンしたデバイスBLEClientを接続し、コマンドを送信

M5StickC Plusのシステム時刻/RTCのNTP同期と時刻の参照

M5StickCPlusでシステム時刻とRTPの管理と参照についてのメモ

参考

modalsoul.hatenablog.com

コード

WiFi接続

setup時にWiFiに接続し、NTPとの同期後に接続を解除

システム時刻をNTPと同期

configTime(JST, 0, ntpServer)でシステム時刻とNTPを同期

RTCの設定

getLocalTimeでローカル日時を取得する。

ローカル日時をRTC_TimeTypeDef/RTC_DateTypeDefを使いRTCの時刻と日時それぞれに適用

RTCから日時を取得

M5.Rtc.GetTime/GetDataで日時を取得

設定時と同じくRTC_TimeTypeDef/RTC_DateTypeDefを使用

動作確認

M5StickCPlusとBluetooth接続でシリアル通信

M5StickCPlusでシリアル通信した際のメモその2


前回はUSBを使った有線接続を使ったが、今回はBluetoothを使った無線接続でシリアル通信をする

modalsoul.hatenablog.com

ライブラリ

BluetoothSerial

github.com

コード

#include <M5StickCPlus.h>
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

void setup() {
  M5.begin();
  M5.Lcd.setTextFont(1);
  M5.Lcd.setCursor(0, 0, 2); 
  M5.Lcd.println("Serial sample.");
  SerialBT.begin("M5StickCPlusBT");
}

void loop() {
  if(SerialBT.available()) {
    String msg = SerialBT.readString();
    M5.Lcd.print("Received:" + msg);
    SerialBT.print(msg);
  }
}

SerialBluetoothSerialはほぼ同じIFなので、前回とコードはほぼ同じ

動作確認

  • BluetoothSerial.beginで指定したデバイスとペアリング
  • ArduinoIDEの「ツール」->「シリアル」から、接続したM5StickCPlusを選択
  • シリアルモニタを起動

あとは前回のシリアル通信と同じ手順でOK

M5StickCPlusとPCをUSB接続でシリアル通信

M5StickCPlusとMacでシリアル通信した際のメモ


出力先がM5StickCPlusの1.14 インチだけだと表示できる情報量も少なく、デバッグなどで面倒なので、手元のMacに情報を送る方法を探した

シリアル通信

M5StickCPlusには3系統のシリアルポートが存在し、USB-Cが1系統目のSerial

8ピンのG0/26がSerial1、GroveのG32/33がSerial2

Serial

www.arduino.cc

シリアル通信のインタフェースにSerialオブジェクトが提供されている

シリアルモニタ

Arduino IDEの、ツール -> シリアルモニタからシリアルモニタを起動

受信した内容の表示と、送信ができる

コード

#include <M5StickCPlus.h>

void setup() {
  M5.begin();
  M5.Lcd.setCursor(0, 0, 2); 
  M5.Lcd.println("Serial sample.");
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()) {
    String msg = Serial.readString();
    M5.Lcd.print("Received:" + msg);
    Serial.print(msg);
  }
}

シリアルモニタから送信したメッセージをM5StickCPlusのディスプレイに表示し、受け取った内容をそのままシリアル通信で送り返す