M0rtercyc!e

バイクとプログラミング

閉め切った大学教室のCO2濃度は限界値を超えている!自作センサで計測してみた。

大学で眠くなったり集中できなかったりするのは、もしかしたらCO2濃度のせいかもしれません。

友人から誕生日祝いにRaspberry Pi Zero WHを頂いたので、有効活用するためにCO2センサを購入し実装してみました。

ジャンパケーブルが足りずピンヘッダに半田付けする図

CO2センサ自体はおなじみのMH-Z19を使っています。組み立て方法については下のサイトを参考にさせていただきました。

Raspberry Pi 3 で CO2濃度を測る – Qiita

もともとは自宅の部屋で使い換気の目安にすることでしたが、某まとめ記事を思い出し、せっかくなので大学で測定を行ってみることにしました。

初めて計測したのは中規模の広さで座席に対し70%程度の出席率の教室です。授業を続けていくうちに、若干の眠気を覚えました。

結果、一時間半の講義でしたが、なんと3800ppmもの値が出てしまいました。これは、屋外のCO2濃度である約400ppmの9.5倍です。

室内の二酸化炭素濃度は、高くなれば高くなるほど人体への影響が顕著になります。カリフォルニア大学バークレイ校のウィリアム・フィスク氏によれば、室内のCO2濃度が2,500ppmの場合、意思決定テストにおいて通常におけるスコアから最小6%、最大56%程度の減少がみられたと発表しています。[1]

また、学習環境について定めた学校環境衛生基準によれば、教室の喚起基準を以下のように定めています。[2]

換気 換気の基準として、二酸化炭素は、1500ppm 以下であることが望ましい。

このため、基準値である1,500ppmを優に超える3,800ppmの教室内環境は学習に適しているとは言えないでしょう。

さて、教授の勧めもあり、授業開始から授業終了までどのようにCO2濃度が変化するのかを確かめるため、統計を取れるようにして測定を行いました。今回は採取したデータの中から、高い値が出たものを紹介します。

技術的に特に難しいことはしていません。サーバ上にAPIを用意し、ラズパイが計測と同時にそこに値をPOSTします。授業終了時にDBをダウンロードし、matplotlibで解析・グラフ化をします。(本当はサーバサイドにフロントエンドを用意したかったのですが、タスクの関係上見送りました。)

一枚目は、中規模の教室で測定をしたときのグラフです。出席率は、座席に対し50%程度で余裕のあるものでしたが、教室は窓やドアを閉め切っており、授業開始時は特に何も感じなかったものの、終盤では眠気を感じました。

結果は以下のように、 開始時1,600ppm、終了時3600ppmという値が出ました。

閉め切っている中規模の教室 59%の出席率

二枚目は、同じく閉め切っている中規模の教室で、出席率は座席に対し80%程度の教室です。ぱっと見でも、教室の広さに対し生徒数が多いように感じました。教室に入った瞬間から空気に違和感を覚えましたが、授業中には息苦しさを覚え、終盤には寝ている生徒も多数観察できました。

蓋を開けてみると、初回測定から2,600ppmと高い値が出ています。授業終盤にはなんとMH-Z19の測定限界である5000ppmを超える値がでていました。

閉め切っている中規模の教室 80%の出席率

このように、教室を閉め切ることにより講義室内のCO2濃度は上昇を続けていくのがわかります。人により影響度合いは異なりますが、CO2濃度が低いことがいいことには変わりありません。私は眠気を感じる程度でしたが、頭痛や気持ち悪さを感じると訴えた友人もいました。

しかしながら、CO2濃度は窓が一枚開いているだけでもだいぶ減少します。また、換気設備が整っている教室では、1,000ppm前後の快適な環境が維持されています。そのような設備がなくとも、授業一時間半の間に数分の換気を挟むだけでも有効な対策といえるでしょう。

CO2を減らし、換気を増やして快適な学習環境を維持しましょう。

参考文献

[1] Usha Satish, Mark J. Mendell, Krishnamurthy Shekhar, Toshifumi Hotchi, Douglas Sullivan, Siegfried Streufert, and William J. Fisk, 2012, Is CO2 an Indoor Pollutant? Direct Effects of Low-to-Moderate CO2Concentrations on Human Decision-Making Performance, Environmental Health Perspectives 120(12):1671–1677, PMID:23008272, https://doi.org/10.1289/ehp.1104789.
[2] 文部科学省(2018), 学校環境衛生管理マニュアル 「学校環境衛生基準」の理論と実践[平成30年度改訂版], http://www.mext.go.jp/component/a_menu/education/detail/__icsFiles/afieldfile/2018/07/31/1292465_01.pdf

ES Modulesではシビアな循環参照

タイトルの通りです。ES Modulesでどハマりしました。

DOMを所定の形式に変換して出力を行う処理を書いていましたが、その中で循環参照が生まれ二進も三進もいかなくなってしまったためメモを残します。

下記のようなファイル群を用意します。Chrome Version 74.0.3729.169で再現。

// script.js
import ModuleA from './ModuleA.js';

new ModuleA().createModuleB();
// ModuleA.js
import ModuleB from './ModuleB.js';

export default class ModuleA {
    createModuleB() {
        return new ModuleB();
    }
}
// ModuleB.js
import ModuleA from './ModuleA.js';

export default class ModuleB extends ModuleA {
}

上記のコードをHTMLから読み込むと下記のようなエラーが出ます。

ReferenceError: can't access lexical declaration `ModuleA' before initialization

まさか循環参照が悪さをしているとは知らず、直感的にはわかりにくいエラーで大変混乱しました。これは普段宣言していない変数を参照しようとすると出るエラーです。

これを解決するには、ModuleA.jsを読み込む前に、あらかじめModuleB.jsを読み込んでおく必要があります。

// script.js
import ModuleB from './ModuleB.js'; //  ここで読み込む
import ModuleA from './ModuleA.js';

new ModuleA().createModuleB();

これで問題なく読み込むことができました。

まだ理解が浅く、なぜこうなるのかを断言できないので詳しくは次回以降にメモできればいいかなと思います。

TypeScript Enumの値をオブジェクトのキーとして使う。

TLDR ブランケットを忘れるな

TypeScriptを使っているとオブジェクトのキーにEnumの値を使いたい時があります。まぁ当たり前なんですが、下のコードはコンパイルできません。

enum myStatus { int, act, typing }
const yourObject = {
myStatus.int : 5
}

TypeScript上でのEnumは要はオブジェクトなので、ちゃんとキーをブランケットで指定しないと怒られます。

enum myStatus { int, act, typing }
const yourObject = {
[myStatus.int] : 5
}


TypeScriptで動的インポート import() を使う。

自作ゲームのスキル計算の自由度を上げようと、JSONから単一クラスによるスキル情報定義に変更しました。JSONの場合、それ自体はただの文字列なので読み込むのは簡単だったのですが、TypeScriptの場合は動的インポートを使用する必要が出てきます。

動的インポートというのは、プログラムの実行時に関数やクラスをインポートすることを言います。TypeScriptやJavaScriptでは動的インポートを行なうためにimport()関数を利用します。

使い方は非常にシンプルです。import()関数は利用時にPromiseを返却します。

// ./modules/module1
export class Module1 {
constuctor() {
console.log('Hello');
}
}
// 読み込む側
import('./modules/module1')
.then((modData) => {
new modaData.Module1(); // => 'Hello'
})
.catch((error) => {
console.error(error);
});

Promiseなので、Async / Await関数でも利用することができます。

とりあえず以上です。

JavaFX CanvasでUndo/Redo

タイトルの通りです。大学の課題でJavaFXを使ったペインタを作成中です。

全体のソースはこちら。
kznrluk/4s-program-painter: ネットワークプログラミング応用演習 – 簡易ペインター

JavaFXのCanvasは他のCanvasと同じように、描写した内容を逐一保持しないため、Undo / Redoの処理には多少工夫が必要になります。

  • MOUSE_PRESSEDからMOUSE_RELEASEDまでの軌道を保持する。
  • Canvasの現時点の画像を取得して保持する。
  • Canvasのインスタンスをコピーする(実際にできるか不明)。

選択時点で軌道を保持して再描写する際にどれほどのコストがかかるのか不明だったため、Canvasの画像を取得する二番目を選びました。今考えてみると、画像で保持するのもそれはそれでコストがかかる気がしますが。

実装は比較的簡単です。履歴を保持するクラスを用意します。

JavaではArrayDequeという便利な配列があるので、それを使っています。

https://github.com/kznrluk/4s-program-painter/blob/master/src/Painter/Controller/ImageHistory.java

描写開始時に現在の描画内容を画像化して保存します。

this.canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
    WritableImage snapshot = new WritableImage(CANVAS_SIZE_X, CANVAS_SIZE_Y);
    this.canvas.snapshot(null, snapshot);
    this.history.add(snapshot);

    currentPen.mousePressed(event);
});

Undo / Redo時にスタックされている要素を取得し、キャンバスに描写します。

void undo() {
    WritableImage image = this.history.getLast(this.canvas.snapshot(null, null));
    GraphicsContext gtx = this.canvas.getGraphicsContext2D();
    gtx.drawImage(image, 0, 0);
}

void redo() {
    WritableImage image = this.history.redo(this.canvas.snapshot(null, null));
    GraphicsContext gtx = this.canvas.getGraphicsContext2D();
    gtx.drawImage(image, 0, 0);
}

描写終了時ではなく、描写開始時に履歴を作成することがポイントです。描写終了時に履歴を作成すると、Undoする場合に現在の描画内容が一度出現してしまいます。

そのうちしっかり書き直したいですが忘備録として。とりあえず以上です。

管理の続かないWordPressサイトを脱却するための工夫

タイトルの通りです。

私は以前からWordPressを使ったサイトをいくつか立ち上げ、運用したことがあります。このドメインでも、もともと`blog.anyfrog.net`というホストでブログを書いていました。

しかし、そのブログも含め基本的に運用が一年以上続きませんでした。

WordPressを自主運用すると、SaaSなどのサービスを使わない限り、物理的なサーバのヘルスケアから、仮想PC上ののOS, PHP, DB等の維持がもれなくくっついてきます。

数ヶ月経つと、”記事を書く気力はあるがバックエンドの維持管理が面倒くさい”状態となり、そのままサイトごとフェードアウトと言うことが数回、ありました。

そのため、維持管理の必要ないQiitaを気に入って使っていたのですが、先述の理由からまた個人ブログに戻ることにしました。そこで、同じ過ちを侵さぬようできるだけ管理の楽な方法でサイトを作ろうと考えました。

そのような場合、一般的にはWordPress.com等のホスティングやブログサービスを使うべきですが、独自ドメインの設定にお金がかかったり、カスタマイズが容易でなさそうなどの理由から結局自主運用のWordPressを使うことにしました。その中で選択したことをメモします。

まず、サーバサイドについて。今までは自宅サーバのWindows Server上で動いているHyper-V上のUbuntuに構築していましましたが、前述の通り物理サーバ+Windows Server+仮想Ubuntu+サーバソフトウェアの維持管理のコストが発生するため、VPSを利用することにしました。

選んだVPSはさくらVPSの1Gプラン。この点は単純にさくらインターネットに個人的な信用があるからです。石狩DCの無停電運用とか。さすがです。

一方で、このままだとOSとサーバソフトウェアの維持管理コストが発生するため、サーバ側のOSにも目を向けました。さくらVPSでは、KUSANAGIというWordPress専用仮想マシンが利用できるので、それを採用しました。

KUSANAGIについてはしばらく触ってからレビューをしようと思いますが、最適化がすでに済んでいるため非常に高速という点や、提供会社によりRPMパッケージ(ベースはCentOS)の提供が行われているためサーバソフトウェアの維持管理が楽、という点があります。

上の2つにより、だいぶ維持管理が楽になった気がします。

最後に、このブログを運用するにあたって一週間に一記事を投稿することを目標に設定したいと思います。ブログの利用を習慣づけることによって、アウトプットを活性化して、維持管理も含めたブログに対するモチベーションを高めることが目的です。

以上です。

Hello world!

WordPress へようこそ。これは最初の投稿です。編集もしくは削除してブログを始めてください !

Page 2 of 2

Powered by WordPress & Theme by Anders Norén