NDIR非分散形赤外線吸収法(NDIR)の原理

いまさらながら、コロナ禍で活躍したCO2濃度測定器の信頼できる測定方法NDIRの原理を解説している堀場製作所さんのページを見かけたのでメモ。

https://www.horiba.com/jpn/company/about-horiba/readout/core-technology/ndir

埋め込みできなかったので、スクリーンショットですみません。やはり微弱信号の計測はチョッパアンプが有効ですよね。
さらに詳しい解説が堀場製作所さんの技報(かな?)としてぐぐる検索で引っかかったので、こちらもメモ。

https://static.horiba.com/fileadmin/Horiba/Company/About_HORIBA/Readout/JA/imported/R007-10-064_01.pdf

いやいや勉強になります。この技報、いつのものかと思ったら1993年なのですね。

紫金山・アトラス彗星タイムラプス

10月20日に撮影した紫金山・アトラス彗星、ポータブル赤道儀に載せてインターバル撮影をしていたのだけど、星が流れてしまった。
そこで、補正してみた。
まずは完成した動画。

もともと撮影した写真はかなり暗め(明るくすると光害で真っ白になってしまう)だった。
まずは16bitのTIFF画像(TIFF16)に変換して、代表的な1枚をImageMagickでマシにしてみる。

$ convert INPUT.TIF -level 15%,35% -gamma 0.5 OUTPUT.TIF

ということで、レベル補正とガンマ補正をかけてみた。

こんな感じになったので、位置を補正しながらすべての画像にレベル補正とガンマ補正をかけてみる。
位置補正は雛形のシェルスクリプトをGPTに書いてもらって、それを元にレベル補正とガンマ補正を組み込む。ついでに出力はJPGにするよう修正。

#!/bin/bash

# 処理するディレクトリのパス
input_dir="./TIFF16" # tiffファイルが置かれているディレクトリ
output_dir="./OUTDIR2" # 処理後のファイルを保存するディレクトリ

# 出力ディレクトリが存在しない場合は作成
mkdir -p "$output_dir"

# x, y座標のずらし量
shift_x=0
shift_y=0

delta_x="5.623" # 731/130
delta_y="5.723" # 744/130

# ディレクトリ内のすべてのTIFFファイルに対して処理を実行
for file in "$input_dir"/*.TIF ; do
# ファイル名だけを取得
filename=$(basename "$file" .TIF)

# convertコマンドを使って処理
convert "$file" -level 15%,35% -gamma 0.5 -roll -"$shift_x"+"$shift_y" "$output_dir/$filename.JPG"

shift_x=`bc <<< "$shift_x + $delta_x"`
shift_y=`bc <<< "$shift_y + $delta_y"`

echo "Processed: $file -> $output_dir/$filename.JPG $shift_x $shift_y"
done

echo "All files processed."

作成したファイルを連番に変換。

$ ls *.JPG | awk '{ printf "mv %s %04d.JPG\n",$0,NR}' | sh

切り出す領域を指定しながらffmpegで動画に変換、さらにサイズを1080×1080に縮小。

$ ffmpeg -r 15 -i %04d.JPG -r 15 -an -vf crop=2160:2160:2481:1611 -vcodec libx264 -pix_fmt yuv420p video1.mp4
$ ffmpeg -i video1.mp4 -vf scale=1080:-1 video2.mp4

出来上がったのが冒頭の動画。

DebianのカスタムLiveイメージを作ってみた

とある理由で、カスタムLiveイメージが作りたくなりました。
で、ぐぐって比較的最近の情報として検索できたのが、こちら。

https://tech.quickguard.jp/posts/debian-live-cd

まずは、こちらの内容に沿って、Liveイメージを作ってみます。

1.母艦環境の準備

まず、KVM上に母艦のDebian12をインストールします。なにも難しいところはありませんが、デフォルトのGUI環境に加えて、OpenSSH Serverをインストールしておきます。
加えて、/etc/group の sudo のエントリに自分のアカウントを加えて、再ログインして sudo が使えるようにしておきます。
そこへ、

$ sudo apt-get install live-build

でlive-buildパッケージをインストールしておきます。

2.早速、Liveイメージを作る

まずは何もカスタマイズせずにLiveイメージを作ってみます。

$ mkdir ./work
$ cd ./work/

初期化します。

$ lb config \
--distribution 'bookworm' \
--archive-areas 'main non-free non-free-firmware contrib' \
--bootappend-live 'boot=live components keyboard-layouts=jp'

参考にしたページでは quiet splash も付けていますが、splashはスプラッシュ・スクリーンを準備しないといけないこと、quietは起動過程が見えなくなることから外しています。

GRUBの設定ファイルを追加

$ mkdir ./config/bootloaders/grub-pc
$ {
cat /usr/share/live/build/bootloaders/grub-pc/config.cfg;

echo 'set timeout_style=menu';
echo 'set timeout=5';
} > ./config/bootloaders/grub-pc/config.cfg

ISOLINUXの設定ファイルを追加

$ mkdir ./config/bootloaders/isolinux
$ cat /usr/share/live/build/bootloaders/isolinux/isolinux.cfg \
| sed -E 's/^timeout 0/timeout 50/' \
> ./config/bootloaders/isolinux/isolinux.cfg

参考にしたページでは、OpenSSH Serverをインストールしたりしていますが、ここではまずビルドできることを確認するので飛ばします。

あとはビルドしてみます。

$ sudo lb build

完了したら、母艦から scp でISOイメージを引っこ抜きます。

$ scp username@debian12.local:~/work/*.iso .
username@debian12.local's password:
live-image-amd64.hybrid.iso 100% 615MB 532.8MB/s 00:01

引っこ抜いたISOイメージをKVMで別の仮想マシンを作って起動します。
起動すると、いかのような感じで自動ログインされた状態まで行きました。

とりあえず、最低限の確認はできました。

・・・が、GUIのLIVE環境は道のりが遠いかも・・・。

ダイソーのセンサーライト

ダイソーのセンサーライトを買ってきてバラしてみました。

パッケージングはこんな感じ。

パッケージのウラ面を見ると、定格消費電力0.9W、待機電力0.2Wだそうです。定格消費電力を0.9Wに抑えているのは、電気用品安全法の「特定電気用品以外の電気用品」の「エル・イー・ディー・電灯器具」の対象が「定格消費電力が1W以上のものに限り、防爆型のものを除く」だからでしょうか。

開封して外観をチェックしてみます。

銘板は直接印刷されていて、こんな感じ。(この分野は素人なのですが、ちょっとモヤる感じがします)

動作させてみました。(注:カメラのAEはONのままなので、LEDが点灯すると画像上は周囲が暗くなりますが、実際には部屋の照明は変化しておらず手をかざしているだけです)

単純にライトをON/OFFするだけではなく、暗さに応じて明るさが変わるようです。

早速開けてみました。白い部分は4辺が爪でとまっているので、小さなマイナスドライバーを差し込んでこじ開けると開きます。

F1のシルクのところに10Ωが実装されているのが目立ちますが、回路図を起こしてみました。

回路は入力のAC100Vをヒューズ・・・ではなく10Ωの抵抗を介してBD1のMB10Fという捺印のブリッジダイオード(おそらくこれ)で全波整流、200V1uFのコンデンサで平滑後、ハイサイド側に4つ直列のLEDがあってローサイド側をトランジスタQ1でスイッチングしています。このトランジスタのマーキングは1行目がR1N50、2行目が81018で正体不明ですが、おそらくNPNトランジスタでしょう。(追記:考えてみるとNPNトランジスタではなく、NchのMOSFETかもしれません)

LEDの電流制御はU1の(おそらく)陕西亚成微电子股份有限公司という会社のRM9003Bという電流制御ICで定電流制御しているようです(回路図上はFETのシンボルを使いました)。電流値はRs1の値で決まり、0.6V/Rs1 = 0.6V/82Ω = 7.3mAだと思います。C1で平滑された電圧の波形がわかりませんが、ピーク電圧140Vで充電されるとすると7.3mAの定電流で0Vまで放電にかかる時間は20msくらいだと思いますので、わりとリップルは大きめだと思います。消費電力は140V✕7.3mA=1022mWですが、リップルまで考えるともう少し小さめなのでしょう。(R3,R4経由の電流は35uA程度=4.9mW程度だと思います)

制御としては、D1のフォトトランジスタがON(すなわち明るい状態)では、R3,R4を通してきた電流はすべてフォトトランジスタを通ってしまうのでQ1のベース電流は流れず、フォトトランジスタがOFF(すなわち暗い状態)の時にはR3,R4,R2を通してQ1をONにするので、LEDが点灯するしくみだと思います。

さて、ヒューズF1が10ΩだとU1やC1がショートモードで故障した場合にちょっと怖そうです。F1がヒューズならヒューズが切れておしまいなのですが、10Ωになっているので、この10ΩかQ1あたりが燃えそうです。ヒューズはわりと高い部品なので抵抗で置き換えられればコストダウンに効果的なのですが、ちょっと気になります。

BulePillでスクリーンセーバーキラーを作る

昔BluePillで作った、スクリーンセーバーキラーが行方不明になってしまったので、環境構築から改めて作ってみます。

BluePillで作った理由は、ArduinoでUSBHIDのサンプルプログラムがあること、デバイス自身のUSBインタフェースなどを使わずにSTLINK V2を使ってArduino環境から書き込むことができるのでVID/PIDを書き換えても問題がないこと、手元にあったこと、などです。

今回の開発環境は新たにUbuntu 22.04をインストールして、その上でArduino環境でやってみます。NVME上の普段のLinuxMintのデスクトップ環境は維持したいので、以前調べた方法でリムーバブルにしてあるSSDドライブ上にインストールしています。

何度も

initcall_blacklist=nvme_init

と打つのはめんどくさいですが、なんとか頑張ってNVMEは認識させない状態でSATAのSSD上にインストールしました。

で、Arduinoをインストールしようと思ったら、AppImageで行けそうなことがわかったので、今回はAppImageでやってみます。

・・・が、ファイルに実行属性をつけても何も起きません。そこで、コマンドライン上で試してみたら、

$ ./arduino-ide_nightly-20240219_Linux_64bit.AppImage 
dlopen(): error loading libfuse.so.2

AppImages require FUSE to run.
You might still be able to extract the contents of this AppImage
if you run it with the --appimage-extract option.
See https://github.com/AppImage/AppImageKit/wiki/FUSE
for more information

ということで、FUSEが必要なようです。ぐぐってみると、Ubuntu 22.04の場合は、

$ sudo apt install libfuse2

でインストールしてやればOKなようで、その後はAppImageのArduinoが起動できました。

起動したら、File→PreferencesでLanguageを日本語に設定した後、追加のボードマネージャに

http://dan.drown.org/stm32duino/package_STM32duino_index.json

を設定します。

その後、ツール→ボード→ボードマネージャで、STM32を入れて検索して、STM32F1xx/GD32F1xx boardsのインストールをクリックします。

インストールしたら、ツール→ボード→STM32F1xx/GD32F1xx boards→Generic STM32F103C seriesを選択します。

CPU速度は48MHz、VariantはSTM32F103C8(20k RAM,64k Flash)、Upload methodはSTLinkに設定します。

PCとST-LINK V2、BluePillボードは以下のように接続します。

ST-LINK V2を認識させるために、/etc/udev/rules.d/49-stlinkv2.rules として以下の内容を作成します。

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \
MODE:="0666", \
SYMLINK+="stlinkv2_%n"

作成したら、

$ sudo udevadm control --reload-rules

として適用します。これでblinkなどの適当なサンプルプログラムを書き込んでみて動かしてみます。

問題なければ、ソースコードを作成します。ソースコードはスケッチ例の中のUSB Composite for STM32F1の下のjigglemouseをベースに作成しました。

#include <USBComposite.h>

#define LED LED_BUILTIN

USBHID HID;
HIDMouse Mouse(HID);

void setup(){
  pinMode(LED,OUTPUT);
  digitalWrite(LED,1);
  HID.begin(HID_MOUSE);
  delay(1000);
}

void loop(){
  static int v = 1;
  int r = random(60000,90000);
  #ifdef DBG
  Serial3.println(r);
  #endif
  digitalWrite(LED,LOW);
  delay(100);
  digitalWrite(LED,HIGH);
  Mouse.move(v,0);
  delay(r);
  v = -v;
}

BluePillをUSBマウスとして動作させますが、マウスを横方向に1単位移動させたらランダムに60〜90秒待って、次は反対方向に1単位移動させるという動作を繰り返すだけです。

ただ、これだとOS上はMapleとして認識されてしまいますので、 ~/.arduino15/packages/stm32duino/hardware/STM32F1/2022.9.26/libraries/USBComposite にある、usb_generic.c の冒頭の部分のベンダIDとプロダクトIDを書き換えます。

#define LEAFLABS_ID_VENDOR                0x1EAF
#define MAPLE_ID_PRODUCT 0x0024 // was 0x0024

これを、例えば

#define LEAFLABS_ID_VENDOR                0x04d9
#define MAPLE_ID_PRODUCT 0x1503 // was 0x0024

として、手元の謎の古いジャンクキーボードのものに偽装しました。また、同じファイルの先頭部分の

const char DEFAULT_PRODUCT[] = "Maple";
const char DEFAULT_MANUFACTURER[] = "LeafLabs";

const char DEFAULT_PRODUCT[] = "Mouse";
const char DEFAULT_MANUFACTURER[] = "Generic";

として、プロダクト名等を書き換えました。

こうすることで、例えばLinuxのdmesgでは接続時のログが

usb 5-2.4: new full-speed USB device number 8 using xhci_hcd
usb 5-2.4: New USB device found, idVendor=1eaf, idProduct=0024, bcdDevice= 2.00
usb 5-2.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 5-2.4: Product: Maple
usb 5-2.4: Manufacturer: LeafLabs
input: LeafLabs Maple as /devices/pci0000:00/0000:00:08.1/0000:05:00.4/usb5/5-2/5-2.4/5-2.4:1.0/0003:1EAF:0024.0005/input/input29
hid-generic 0003:1EAF:0024.0005: input,hidraw4: USB HID v1.10 Mouse [LeafLabs Maple] on usb-0000:05:00.4-2.4/input0
usb 5-2.4: reset full-speed USB device number 8 using xhci_hcd

から、

usb 5-2.4: new full-speed USB device number 16 using xhci_hcd
usb 5-2.4: New USB device found, idVendor=04d9, idProduct=1503, bcdDevice= 2.00
usb 5-2.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 5-2.4: Product: Mouse
usb 5-2.4: Manufacturer: Generic
input: Generic Mouse as /devices/pci0000:00/0000:00:08.1/0000:05:00.4/usb5/5-2/5-2.4/5-2.4:1.0/0003:04D9:1503.0009/input/input33
hid-generic 0003:04D9:1503.0009: input,hidraw4: USB HID v1.10 Mouse [Generic Mouse] on usb-0000:05:00.4-2.4/input0

という感じになりました。

LinuxMintでHEIFファイルを見る

最近、デジカメを新調してEOS R7を使い始めました。
そこで引っかかるようになってきたのが、画像の保存形式です。

HDRPQで保存すると確かにきれいなのですが、ファイル形式がHEIF(拡張子HIF)で保存されるので、PC上でファイルを探すのに苦労します。いまのところ、WindowsではキヤノンのDPP(Digital Photo Professional 4)でしか見れません。

そこでなんとかしていきたいと思います。

まず、HEIFのコーデックをインストールします。

$ sudo apt install heif-gdk-pixbuf
$ sudo apt install heif-thumbnailer

これだけではファイルマネージャ(的なツールのNemo 以下略)ではサムネイルが表示されませんので、MIMEの設定ファイルを編集します。

$ cd /usr/share/mime/packages
$ sudo cp heif.xml heif.xml.org

heif.xmlでは、拡張子HEICとHEIFしか記述されていないので、

<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="image/heif">
<comment>HEIF image</comment>
<comment xml:lang="de">HEIF-Bild</comment>
<glob pattern="*.heic"/>
<glob pattern="*.heif"/>
<glob pattern="*.hif"/>
<alias type="image/heic"/>
</mime-type>
</mime-info>

のように3つ目の拡張子を追加するために、 <glob pattern=”*.hif”/> の行を追加して保存します。保存したらデータベースを更新します。

$ sudo update-mime-database /usr/share/mime
$ sudo update-desktop-database /usr/share/applications

更新して、ファイルマネージャ再起動しても更新されなかったので、PC自体を再起動したらサムネイルが表示されるようになりました。
ただ、サムネイルの生成はかなり時間がかかってしまいます。そのうちCPUにデコード支援機能が入って使ってくれうようになればいいのですが・・・。

<追伸>
LinuxMintに標準で入っている画像ビューア(Eog)でも開けるようになりました。
ただ、いずれも色合いはJPGと比較するとだいぶ暗いです。

NanoPi NEO2のArmbianをアップグレード

NanoPi NEO2+NASキットにArmbianを入れて本来NASとして使うHDDをルートファイルシステムにして動かしています。といっても、大したものは動いていないのですが。

で、久々にリモートログインしてaptで更新をかけたら、

New release '22.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

という表示がでたので、記載どおりにアップグレードをかけると、すぐにsyslogが溢れてしまいます。
いろいろみていくと、syslogはzram0にマウントされていて、RAMDISK上に取られているようです。そのためにMicroSDへの書き込みが少なくて長期間の運用に耐えてくれるのかもしれませんが、ここではアップグレードの障害になっています。

しかし、このマシンのルートファイルシステムはHDD上なので、ログもHDDに取っても差し支えありません。そこで、/etc/default/armbian-ramlog の冒頭の

ENABLED=true

ENABLED=false

に変更して再起動すると、dfコマンドで見てもzramに取られなくなりました。この状態で、do-release-upgradeをかけると、先に進むようになりました。・・・・が、処理はきれいに最後まで走ったものの、再起動したら接続できず・・・でした。

ところで、こちらの記事をみると、Raspberry Piでもできそうな雰囲気です。(試していませんが)
その他、「zram syslog」でぐぐると、いろいろ情報はありそうです。

EzbookにインストールしてあるLinux Mintを再インストール

Webでの調べものやちょっとした調査を中心にサブマシンとして使っているJumper Ezbook Pro 3にインストールしているLinux Mint MATE Editionを19から21に入れ替えてみました。インストール用USBの作成や一般的な設定などは省略して肝の部分だけ記載します。
(内容を理解してやらないと既存のディスクの内容を飛ばしてしまうので要注意です)
インストール先はオンボードのeMMCです。プリインストールされていたWindowsは増設したM.2 SSDに移動してあります。(M.2 SSDの方が速いのと、容量的にもWindowsの方がたくさん欲しいので)

M.2 SSDに移動してあるWindows 10との共存

Windows 10と共存するため、インストール時にはLinuxからSSDが見えないようにしてeMMCにインストールさせます。具体的にはUSBメモリから起動する際にGRUBの画面でeを押して起動パラメータを編集、quiet splash のところに

libata.force=disable

を追加してからインストール環境を起動します。
起動したらディスクユーティリティでeMMCの中のFATとext2パーティションを削除してから普通にLinux Mint MATE Editionをインストールします。その際、インストーラに日本語を選ぶとキーボードの指定では日本語キーボードがデフォルトになっているのでEnglish(US)にしておきます。インストール完了後は通常通り再起動してeMMCから起動させます。

再起動後、/etc/default/grub の冒頭部分の追加コマンドラインの近辺を編集して、次回起動以降ではLinux MintにM.2 SSDを認識させないようにするのと、起動時にGRUBで選択した内容を次回のデフォルト選択にするようにします。こうすることで、今回のカーネルアップデートでGRUBエントリ作成時のみWindowsのloaderを認識させるのと、通常の使用時にWindowsUpdateで何度も起動する際に毎回Windowsを選択する手間を省きます。

#GRUB_DISABLE_SUBMENU=y
GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true
#GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="libata.force=disable"
GRUB_CMDLINE_LINUX=""

変更したらアップデートマネージャでアップデートをかけます。たいていの場合はこの中でカーネルの更新がかかるのでGRUBメニューが更新されてWindows loaderのエントリが追加されますが、カーネルの更新がない場合には、

$ sudo grub-mkconfig -o /boot/grub/grub.cfg

として手動でGRUBメニューの更新が必要です。

アップデートが完了したら再起動してWindows 10が起動できることと、Linux Mintが起動できることを確認します。
あとは一般的な言語設定などの変更を行えば概ね完了です。

英語キーボードで右ALTをIME ON/OFFに割り当てる

Jumper Ezbook Pro 3は英語キーボードなので全角半角キーがなくIMEの切り替えが面倒です。そこでMozcでは英語キーボードの右ALTをIME ON/OFFに割り当てるため、アプリケーション⇒設定⇒自動起動するアプリ でエントリを追加してxmodmapでキーマップを変更します。名前や説明は適当に入力し、コマンドの部分は

/user/bin/xmodmap -e "remove mod1 = Alt_R" -e "keycode 108 = Zenkaku_Hankaku Kanji"

とします。設定したらログインし直して有効に機能するかを確認します。

防湿ケースの湿度計をアップグレード

3Dプリンタ用のフィラメントやカメラ・レンズの保管にナカバヤシの湿度計付きドライボックス

(とこれの8L版)を使用しているのですが、この湿度計が怪しいのです。他の湿度計が50%程度を指示していてもこいつだけ70%とか80%とかの多湿の表示をしています。
そこで、このアナログな湿度計をデジタルに変更してみました。
交換するのは、以前秋月電子で買った温湿度計です。

何個か買ったのですが、すべてほぼ同じ値を指示していますし、BME280もほぼ同じ値を指していましたので、精度はそこそこあると思います。
これが付くようにブラケットをFusion360で適当に作ります。

出力してはめ込んで並べると、

こんな感じになりました。
そして、ケースに取り付けると、

こんな感じです。(これは8Lの方です)
ポリプロピレンのケースなのでやや見にくいですが、十分使い物になりそうです。

Windowsの「インターネット接続なし」の原因

よく起きる「インターネット接続なし」表示の原因です。
簡単にまとめると、

  1. dns.msftncsi.com の名前解決が正常にできない
  2. http://www.msftconnecttest.com/connecttest.txt から正しいテキストファイルが取得できない
    (IPv6の場合はhttp://ipv6.msftconnecttest.com/connecttest.txt

だそうです。
詳しくは、ネットワーク接続状態インジケーター (NCSI) の概要とトラブルシュートを参照。