次亜塩素酸水について

次亜塩素酸水を噴霧してコロナウイルス対策をしようという話が一時期頻繁にありました。NHKテレビなどで外出規制が解除された後に出入り口に閉鎖空間を設けて次亜塩素酸水を空間噴霧しているとして来客数を伸ばしている事業者が取り上げられたという話も聞きました。結論から言えば,次亜塩素酸の空間噴霧に効果はほとんどなく,かえって害をもたらす可能性があります。

次亜塩素酸水とは

次亜塩素酸水は,塩(NaCl)や塩酸(HCl)を水に入れて電気分解し,塩素イオン(Cl)の力で水を低pHにしている電解水です。最終的に食品に残らないことが条件ですが,次亜塩素酸水は随分以前に食品添加物として指定されています。(指定時の参考資料

食品工業での次亜塩素酸水の使われ方

次亜塩素酸水は,食品加工の現場では,加工中の材料や食品の表面に付着してる汚れを落としたり,微生物やウイルスを除菌する(要は微生物やウイルスを洗い流す)目的で使われています。成分表示上は殺菌料と書かれますが,水道水とあまりかわらない感覚で使い,殺菌を期待して使ったりはしません。

食品工業でいう殺菌

食品工業でいう殺菌は,商業的殺菌です。殺菌といっても,医療や微生物検査などで必要とされる滅菌(微生物やウイルスの完全死滅・除去)とは違い,すべての種類の微生物やウイルスがいない状態を作り出しているわけではありません。加圧加熱(いわゆるレトルト)殺菌や,加熱殺菌などの方法で,食中毒の原因となる微生物やウイルスを一定の割合で死滅・不活化させることいいます。殺菌の後,残っているかもしれない有害微生物が繁殖しない条件(例:酸素がない,pHが◎◎以下であるなど)の組み合わせのもとで保存・流通させることで,食中毒の発生を防ぎます。

食中毒の原因菌が繁殖しない条件を食品自らが備えているので,本格的な殺菌をしない場合もあります。例えばウスターソースやお酢,干物など,かなりpHが高い・低いものや,塩分濃度・糖度が高かったり乾燥してあって水分含量が低い—正確には自由水がほとんど含まれていない水分活性が低い—食品は,主な食中毒の原因となる微生物がこうした条件のもとでは繁殖しないので,大掛かりな殺菌はしません。

つくりたての次亜塩素酸水の力

次亜塩素酸水が今回の新型コロナウイルスを不活化させる力があるとの実験結果が報道されています。おそらく,つくりたての次亜塩素酸水を直接ウイルスにふりかけたりすれば,タンパク質でできたウイルスの外殻がこわれて不活化するのでしょう。たしかに,つくりたての次亜塩素酸水は,お酢などと同じく低pH,ですので,タンパク質を変性させる力はありそうです。できたての次亜塩素酸水は刺激臭があります。目や鼻・喉などの粘膜に付着すればかゆみや痛み,場合によっては炎症を起こす心配もあるでしょう。

余談ですが,かつて,同室で分析作業をしていた人が塩酸水溶液を加熱していて誤って沸騰させてしまい,白煙が立ち込めたところに出くわしたことがあります。消火しようと部屋に飛び込んだのですが,すぐ咳き込んで何もできませんでした。その場にいた別の人が口を布で覆って火を消し,事なきを得ましたが,苦い思い出です。

密封せずおいてある次亜塩素酸水なるもの

 

次亜塩素酸水の効力は,塩素イオンが生み出します。ところが,水中の塩素イオンは,密封していない環境では塩素としてすぐに揮発していきます。つまり,つくってすぐ密封せずにおいてある次亜塩素酸水なるものは,単なる水です。水にウイルスを不活化させる力はありません。ですので,よく除菌用などという名目でおいてあるプッシュポンプ式ボトルに入っている次亜塩素酸水という水は,ウイルスの除菌には役立ちません。

役立たないどころか,有害な場合もあります。というのは,塩素イオンが抜けた水は,微生物の繁殖の場となりえます。除菌するつもりで微生物を手や体にふりかけていたなんてこともありうるわけです。

霧状に空間噴霧される次亜塩素酸水

前述の通り,塩素イオンは容易に塩素となって揮発します。霧状にした次亜塩素酸水は表面積が増えますので,容器に詰めてある状態よりさらに速く,塩素イオンが抜けていきます。つまり,霧状に次亜塩素酸水を空間に噴霧してその霧がただよっているとしても,それは単なる水蒸気です。

一方,抜けた塩素は気体の塩素ガスになります。気体は自然に分散していきますが,ある程度閉鎖された空間なら,しばらくは残存しているでしょう。比重が2.49と重いので,足元をただよう感じです。また,塩素ガスは反応性の強い物質です。濃度の高い塩素ガスをウイルスに吹きかければ,これまたタンパク質が不活化するでしょう。気体の塩素分子がたまたまウイルスと出会えば不活化につながるかもしれません。床や地面に付着してるウイルスがいればですが,その出会いの確率は極めて低いです。なにしろ,もともと次亜塩素酸水に含まれていた有効塩素の量は,1kgあたり数十mg程度(つまり濃度でいうと数十ppm)ですから。

仮に次亜塩素酸水を狭い密封空間に噴霧して霧あるいは空間の塩素濃度が結構高い状態(プールで塩素臭が強い状態のようなもの)をつくれれば,その空間にいるウイルスの不活化にはつながるでしょう。塩素ガスの濃度が濃いということは,その空間での塩素ガスとウイルスの出会いの確率が高くなるからです。

ですが,その場合は塩素ガスによって人間に健康被害が出ます。人間にとって塩素ガスは猛毒のガスなのです。

現実としては,空間噴霧している場所は完全密封はしていないでしょうし,人の出入りによる空気の流れもあるでしょう。塩素自体は少量でもかなり特有の刺激臭がしますので,塩素臭さがないかぎり,塩素もその空間の外へ散っていると思って良いでしょう。散ってしまっているということは,その空間でウイルスの不活化に役立たないことになりますが。

また,湿度が高い空間は,雑菌が繁殖する場となります。かつて,24時間入れるお風呂が流行りましたが,レジオネラ菌という微生物が繁殖して健康被害をもたらす事故が頻発しました。水分は多くの微生物にとって,繁殖の材料となります。病原微生物が次亜塩素酸水を噴霧している空間に入り込めば,それが繁殖して人間に接触する確率が高くなるわけです。

いずれにせよ,次亜塩素酸の空間噴霧は意味がなく,かえって危険な場合もありうるということになります。

現実的な空間除菌の手段

現実的な空間除菌の方法もあるにはあります。除菌フィルターを使って清浄な空気で満たすいわゆるクリーンルーム,紫外線やオゾンを使う,あるいはその組み合わせです。

もっとも,紫外線やオゾンを使う方法は,塩素ガスの場合と同じく,その場に人が長くとどまることは危険です。食品工場ではライン稼働後の人がいない時間帯に行います。オゾンは気体として空間の隅々に行き渡るのですが,紫外線は影となった部分での殺菌はできません。

また,除菌フィルターによる方法は,設備に多額の投資が必要であり,除菌状態を得るまでの時間も長いので,大量生産する飲料の非加熱充填工程など限られた場所でしか使いません。

結語

空間噴霧や空間除菌を提唱している人たちは,ある程度有効塩素濃度が高い次亜塩素酸水によるウイルスの不活化効果をもって次亜塩素酸水が有効だと主張しています。つくりたて,あるいは密封状態からとりだした直後の次亜塩素酸水であればそのとおりですが,上述の通り,空間噴霧したり,密封式ではない容器に入れられた次亜塩素酸水にはあまり,あるいはまったく効果を期待できません。また,有効塩素濃度が低くなった次亜塩素酸水は雑菌が繁殖する場ともなる可能性があるため,かえってそれによる健康被害の危険もあることを忘れてはなりません。

工業経営論第2回 報告内容一覧

5月27日開催,2020年度前期工業経営論の第2回講義。例年はB/S, P/Lを紹介し,出資の概念や利益配分,金融機関の役割などを紹介し,講義の最後に下記のような問いかけをして発表してもらう。会社は誰のものかという問いに,所有という意味,大切にすべき人という意味など,問題そのものに多様な視点が含まれており,自分はこの視点でこう考えるが,他の人はこの視点で考えるのか,この視点だとこう考えるのか,などの気付きがあるとよい。

1)「会社は誰のものか」という問いに対して,回答とその根拠となる考え方を2組み答えなさい。
  <誰のものか   1>
  <なぜそういえるか1>
  <誰のものか   2>
  <なぜそういえるか2>
2)上記のふたつの考え方のうち自分の考え方に近い方について,自分の考え方に遠い方に比べてより重要だと考える根拠を説明しなさい。
  <結論> 自分なりの考え
  <根拠> なぜそういえるのか
  <例証> 根拠を支える上で参考にできる事例

今年も,課題としては同じ問いかけをした。また,受講に際して気になる会社の決算書を入手してそれを見ながらの受講を指示した。

集まった課題レポートと,講師のコメントを一覧にしたものはこちら。

レポート一覧20200527

課題報告を眺めてみると,90分という講義時間の制約がないせいか,例年の口頭発表に比べて踏み込んだ内容を踏み込んだ表現で報告する学生が多い。ただし,ネット情報のコピペで済ませる学生もいるのだろうとも思うー自分が学生ならそうしていた。例年なら,発表者と対話して,発表者やそれを聞いている受講者の考えを深めてもらうのだが,今年度はそれができないところがもどかしいところ。

工業経営論2020年度講義開始

新型コロナ感染症の影響で遅れていた大同大学での今年度の工業経営論の講義が先週5月20日に始まった。結局すべてオンライン講義となり,資料をあらかじめ提示して受講生が報告書を提出というスタイルが基本形。

第1回の講義は例年,ガイダンスと,日本のものづくりをとりまく現況を考えてもらったり,そのうえで自分がどうすべきかを考えてもらう。今年は,質問票の代わりに毎回課題を出してもらうことにして,第1回は以下のような課題とした。

■第1回講義のアウトプット「これからのものづくり」
 講義資料や,ネット情報,新聞・雑誌情報などを参考に,以下の設問について調べたり考えたりした結果を簡潔にまとめ,メールで講師に送信してください。
1)これから,日本のものづくりはどうなっていくと思いますか?
  <結論> 自分なりの考え
  <根拠> なぜそうなっていくかといえる理由
  <例証> 根拠を支える上で参考にできる事例
2)上記1)を考える上で,について
  <疑問> 疑問を感じたこと,わからないこと  (感じたことでも可)
  <事実> 上記疑問について,自分が知っていること(反例等)
  <意見> 上記疑問について,自分はどう考えているか,予測しているか等

例年のごとく,コメントを入れた状態のまとめを今年も配布する。
報告一覧20200520

今年は例年と違い,学生から電子データで情報が送られてくるので,一覧を作成する時間や手間は少なくなった。しかし,それだけに質問の意図や背景,他の学生の記述内容や返信を調整しながらのコメントとしてじっくり考えたり後で修正したりといった時間を意図してとらないといけないなと感じた。今回分は時間切れで,少々そのあたりのバランスに欠けるコメントになってしまっている。

ScanSnapと8card

ScanSnapで8Card用に名刺を一気に読み込む仕組みがあるが,若干注意点が必要。

背景

名刺管理をクラウド化していたのだが,せっかく文書スキャナがありながら,スマホでちょこちょこと写真をとってデータを入力していた。年度末の書類をつくる際に便利だろうと,ここで一気に手元に残っていた名刺をスキャンすることにした。

環境
ハードウェア

  •  MacBook Air/Catalina
  •  ScanSnap iX500

両者はUSBおよびWiFiの両方でつながっている。

ソフトウェア

  • ScanSnap Home 1.6.0
  • Eight Scan beta 5.4.1

はまりどころ

  •  pdfファイル形式を選んではいけない。Eight Scan 側でファイルを認識できない模様。
  • 白紙削除を選んではいけない。次の名刺とデータがくっついてしまい,以下,オモテウラがずれる。
  • スキャン直後のScanSnapからEight scanまでの引き渡しプロセス(自動認識している?)でかなり時間がかかる(1枚あたり10秒くらい?)
  • 未送信名刺の整理で次の名刺にキーボード入力でとべない(Tabかカーソルキーでとべず,マウスで選ばなければいけない)
  • 同画面で画像のサイズが替えられないので,表裏や方向が判別しにくい。

香港の現状に思うこと

Why Civil Resistance Works 表紙

香港との接点

1987年から1988年にかけて,南京大学に語学留学していた冬休み,上海から船路で香港を訪ねた。鄧小平の南巡講話はすでにされていたが,経済発展の端緒についたばかり。翌年には天安門事件が起こるというタイミングである。19世紀末とあまり変わらないであろう生活スタイル,電力の節約で暗い中国大陸から,いきなりきらびやかな自由経済の旗手,東西混淆の香港にたどり着き,彼我の違いに目を見開きながら楽しんできた。

その後,就職して後も国際調達担当の業務で単独で新疆ウイグル自治区や山東省,河北省,江蘇省,福建省と訪れ,東京からの直行空路がふさがっているときは,啓徳空港からバスで市内を移動して境界を越える鉄道に乗り換えて広州へ往き,そこからまた空路で中国国内へと移動したこともある。また,食品会社を離れてからも,支援先の事業者さんや支援仲間と,あるいは単独で,視察や商談・出展・販売支援,観光にと随分足を運び,ときには密貿易の現場を覗きに行ったり,早朝の食品市場をめぐってみたり,いきあたりばったりでたどり着いた海岸で昼寝をしたりと,たびたび香港にはお世話になってきた。

スライドショーには JavaScript が必要です。

揺れる香港と過去の記憶

その香港が,今,揺れている。

一国二制度の形骸化を懸念しつつ,それでも独自の立ち位置にある香港は,海外旅行や食品輸出,海外展示会出展,商談の入門編として,手頃な場所であった。LCCが飛び始め,当初は大阪から発って深夜に到着するような強行軍をやってみたりしたが,ほどなく中部国際空港からも便利な時間帯に新たな路線が開設され,旅券とクレジットカード,スマホさえ持っていれば,当日思い立ってその日の夕方には香港などということもできるようになった。英語や中国語が通じ,社会秩序が安定しているという安心感があった。

一方で,銅鑼湾の書店主が行方不明になったり,愛国教育ー大陸では歴史・道徳教育的な位置づけーの延長として讒謗律のような法令が制定されるなど,耳目を集めるニュースが続いていた。

そして雨傘運動が起こり,民主派の立候補規制がかかるなど,揺れ動きが続いてきた。

今回,半年近くになる抗議活動が続いている。北京での騒動を,南京から戻ったばかりの頃,まだインターネットでニュースや動画が駆け巡るなどと思いもよらなかった頃,限られた情報を見つめていた。一介の学生としてやれることは限られていた。その頃の記憶につい意識が向き,暗い結末を迎える懸念が頭を離れない。

社会政治運動の成功率と香港の特殊な位置

ここに,20世紀100年間+アルファの期間の各種政治運動を分析した研究結果をまとめた本がある。

Book

・非暴力運動のほうが暴力行為中心の運動よりも成功率が2倍以上高い
・運動の参加率がピーク時で3.5%を超えると成功率が飛躍的に高まる

Why Civil Resistance Works 表紙
“Why Civil Resistance Works” Columbia University Press, SBN: 9780231527484

という研究成果が記載されている。香港の人口は約700万人。3.5%というと,約25万人だ。主催者発表では200万人を超える(警察発表でも30万人を越える)参加があったデモが複数回すでに起こっている。過去のデータから得られた知見からすれば,この運動は少なくとも香港域内では成功する確率が高いといえそうだ。

もっとも,香港は中国の一地域という位置づけである。大陸での香港情勢に関する情報流通はかなり統制がかかっており,関心も高くない。中国自体が変わるには,総人口12億人(未登録者も多いので13億人以上というのが実態だろうが)の3.5%という数字を使えば4,200万人以上が動くことが指標となる。年々変動しているが,香港への入境者人数は年間約4,000万人。大陸から7割として,年間2,800万人が香港を訪れていることになる。もちろん,生活費が安い大陸に住み,越境して勤務する人も多く,現時点では大陸から香港への観光を大幅に制限しているようなので,直接,香港の今を見聞きしている大陸の人達の人数は現時点ではかなり限られるだろう。それゆえ,上記の数に達して大陸側も変わるという可能性は,全く0とはおもわないし,一国二制度が維持される50年間の間に融合的な動きが起こってほしいとは思うが,今の所そこまでの広がりはない。また,運動もそうした目標を持っているとはいえず,今回の五大要求は表面的にはあくまで香港域内での政府の変化を要求している。もちろん,行政長官が北京の了承がなければ辞任もできないように,香港の統治・政策は中国共産党の意志が大いに関わるので,間接的には大陸政府の変化を狙っていることになるが,

ともかくも

自分は社会問題の専門家ではないし,中国語も北京語はともかく広東語は片言程度しか話せないので,もっぱら個人的関心,業務上の必要から香港に関心を持ち続け,時折訪問しているわけだが,馴染みがあり,また訪れたい場所といえば間違いなくその筆頭候補の一つである。また,中国が世界と協調して平和裏に,経済のみならず,政治や社会も発展してほしく,またその変化を見続けたい。アジアのみならず,世界の行く末を決める大きな要因の一つが,中国のありかたであり,その重要な因子として,香港,台湾や,中国国内の民族・人権・政治の変化は,目が離せないでいる。

評論的なものはさておき,上記の研究結果を知るにつけ,また,暴力は慎むべきという個人的に信条からしても,軸となる人達には非暴力という志向を持ってほしい。暴力装置の介入は,そこで生活している人々の大きな不幸を招くだけでなく,世界的な経済の大混乱や,人材の喪失に至る。これを防ぎつつ,理想とは行かないにしても一歩でもより望ましい社会をより少ない不幸で実現するには,知恵と理性と戦略とをもち,周囲の共感を引き起こせる行動をしなければならない。市民側からすれば,警察や社会インフラ機構は攻撃対象ではなく,説得対象ではないだろうか。また,行政側からすれば,市民活動を力づくで抑え込もうとするほど,運動が過激になり,みすみす外部からの介入を許すことになりかねない。攻撃による反作用を燃料に活動活力を維持することは,双方いずれにとっても安直で愚かな手法である。

希望を持ち続けたい。

重陽節の夕べに来し方を振り返りつつ

菊の花

MEMS(ECU)モニタ開発状況 GHCのバグ?環境整備の問題?

エンジンルームを乾燥中の Rover Mini 1.3i

インジェクション・ローバーミニの車載コンピュータのモニタリング,Macではstack環境下で順調に開発・運用していますが,ラズパイでの運用は未完。stackでのコンパイルがまだできないので,ghcで直接コンパイルをしてみたのですが…

現状把握:何が起こっているか

使用している serialport パッケージ内の関数で引数の型として指定されている ByteString の参照先が Mac でstackを使ってコンパイル(stack 2.1.3) した場合と RaspberryPi で直接GHCでコンパイル(GHC 8.0.1 on Raspberian 4.14.79-V7+)した場合とで異なる。ラズパイ上ではなぜかbytestringのインターナルモジュール内の定義を参照し,呼び出し側は,モジュール内で明示的に指定した公開ライブラリを見にいっています。

具体的には,serialportパッケージのsend関数の第2引数の型が合いません。serialportの中では

> import qualified Data.ByteString.Char8 as B
>(中略)
> send :: SerialPort -> B.ByteString -> IO Int

と定義されています。一方,自作のモジュール内では,

> import qualified Data.ByteString.Char8 as BS
> (中略)
> send p $ BS.singleton (chr 0x0a)

みたいな感じで呼び出しています。

引数の型は合っているはず。Data.ByteString.Char8 (以下,「D.B.C」と省略)でのsingletonの定義は,

> singleton :: Char -> ByteString

です(尤も,D.B.C内のByteStringの定義は,後述の通り,Internalモジュールからインポートしていますが)。

実際,macOSでstack buildをした場合,問題なく通りますし,運用もできます。ところがraspberianで ghc でのコンパイルをすると,BS.ByteString は Data.ByteString.Internal で定義されているbytestring-0.10.8.1:Data.ByteString.Internal.ByteStringと合わないというわけで,型の不一致とされてしまいます。うーむ。

原因分析:何が原因か

serialportのソースをおっかけてみると,まずByteStringの定義は前述の通り,D.B.Cを参照しています。また,sendの第2引数は,途中でWord8に変換するため,B.unpackをかけており,その先のD.B.Cのほうでは,unpackは結局,内部関数のunpackAppendCharsLazyを束縛しています。

> unpackChars :: ByteString -> [Char]
> unpackChars bs = unpackAppendCharsLazy bs []
> (後略)

そこでunpackAppendCharsLazyを見ると,内部のByteStringの定義を用いて関数が定義

> unpackAppendCharsLazy :: ByteString -> [Char] -> [Char]
> unpackAppendCharsLazy (PS fp off len) cs
> (後略)

されています。

InternalモジュールでのByteStringの定義は
> data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
> {-# UNPACK #-} !Int -- offset
> {-# UNPACK #-} !Int -- length
> deriving (Typeable)

となっています。これは外部公開していないモジュールのはずですから,ここを参照すべきではないでしょうし,D.B.Cのほうで,ちゃんとByteStringをエクスポートしています。

> module Data.ByteString.Char8 (
>
> -- * The @ByteString@ type
> ByteString, -- abstract, instances: Eq, Ord, Show, Read, Data, Typeable, Monoid
> (後略)

ですので,D.B.Cを指定したByteStringで型は一致するはずなのですが…

真因追求:本当の原因として考えられること

  • raspberian 上で整えた GHC の環境がおかしい? … 冒頭で述べたように,stackでの開発がラズパイ上ではできていません。cabal ライブラリのコンパイルをはじめて,大きなライブラリのコンパイルでメモリが不足して止まってしまう(一応,仮想メモリとして4GBを確保してあるのですが)。stackの環境構築がこのように中途半端になっているので,それがローカルなライブラリDBを構成するなどの悪さをしている?
  • 環境・構成に依存するGHCの挙動の違い? … GHC のバージョンや,Stackを使った場合と生で呼び出した場合のGHCに渡されるオプションや構成の違いが真因の可能性も。

考えられる対処

いずれにしても,検証するには環境を合わせることから始める必要がありそうです。そもそも stack ・ GHC 直接という違いもあり,macOS と raspberian とでは GHC のバージョンも違うため,そこらへんを合わせてみることが必要なのかもしれません。

思い切って,ラズパイ用は go言語で組み直してみる?手続き型言語の冗長さと,代数データ型やモナドが使えないなどの面倒さにつきあうのはためらいがありますが…。

蛇足

こんなデータを0.5秒おきにとっています。開発目的は,時々発生するECU気絶に由来すると思われるエンジン停止や回転数低下の原因を特定したいためと,IoTや関数型言語でのプログラミングの勉強。

下記画像では,右端の部分で時々横線が入っているように見える部分が,そこが,ECUのデータ読み出しができなかった瞬間です。左側の数値が羅列されている部分でいうと,文字列が並んでいる行です。

気が付かれる方もあるかもしれませんが,魚野の車はマニュアル車です。ですが,ECUが原因かという検証のため,修理業者さんが別の車のオートマ用ECUをつないでくれたために,オートマと表示しています。ECUが変わっても,瞬停や回転数落ちはまだ発生していますので,ECUそのものが原因ではないと思っています。

Rover Mini ECU(MEMS) Monitor CSV Data
Rover Mini ECU(MEMS) Monitor CSV Data

ECUモニタ開発状況

ローバーミニ,すでにクラッシックカーの領域に入りつつありますが,1992年以降に日本で新車として販売されたミニにはインジェクション方式が導入され,制御用のコンピュータECUも載せている。趣味として関数プログラミング言語 Haskell を使ってこの制御用コンピュータのデータをモニタリングしようとしてきましたが,少しづつ開発を進めています。ちなみに現在も引き続き車内にMacBookAirを持ち込んで,運転中に自動記録しつつ,車載モニターにライブデータを表示しています。

スライドショーには JavaScript が必要です。

開発の現況

全体としては安定してモニタリングできるようになり,プログラムの一部を改造しても他の部分に影響を出しにくくなりました(モジュラー化が進んだ。以前は各パーツが密接に絡み合っていたため,一部を改造するとしばらくコンパイルエラーのみならずロジックエラーを誘発していた。)。

Rover Mini ECU(MEMS) Monitor Screen Shot
2019年5月の Rover Mini ECU(MEMS) Monitor スクリーンショット

これは2019年5月にとったスクリーンショット。数値表示だけでは一瞥したときに全体像が把握できないなと,アスタリスクによる各データのリアルタイム棒グラフをつけたもの。

試作したRover Mini ECUモニタの画面
開発が進んだRover Mini ECUモニタのスクリーンショット

そしてこちらは過去データや他のデータとの相関を見たいと思い,縦棒グラフを並べるようになったバージョン。

2019年9月現在の画面

そして現在は複数のデータを同一のグラフに描画しています。一通り走った後,エンジンを停止した状態(エンジンを切っても10秒くらいはECUが動作しています。おそらく冷却液用の冷却ファンをしばらくまわすため)での画面キャプチャ。画面右側は,テキスト表示でむりやり表現した温度や回転数など各種センサー値の重ね合わせグラフ。テキスト表示なのは,ラズパイなど超小型コンピュータで動作させる際に簡単に実現できそうだからです(GUIはメモリや処理能力に要求される水準がTUIに比べて圧倒的に高いが,超小型コンピュータにそれを求めるのは酷ですものね)。

ループ処理や例外処理を見直し,エンジンの稼働状況やECUと繋がれた信号線の状態に影響を受けにくくなり,安定して稼働するようにしました。

こちらのログは岡崎から名古屋に帰る道すがら記録したものです。時々接続が切れて再接続しています(再接続に1秒近くかかっているのはあえて待ち時間を1000m秒入れているから)。路面の凸凹やアクセルオフ時の振動に連動(?)して接続が切れているので,コネクタかセンサ固定に何か問題がありそう。

Rover Mini ECU(MEMS) Monitor CSV Data
Rover Mini ECU(MEMS) Monitor CSV Data

得られた学び

前回の報告から進展したHaskellの学び,Haskell中級編といったところでしょうか。

モナドを作れるようになった

モナド,Haskell初心者のつまづきの石です。わかってしまえばなんてことはない概念ですが,RealWorldHaskellとかでゆっくりまなびつつ,試しにECUとのコミュニケーションモジュールで自作のモナドを作ってみました。裏で動く仕組みが理解できたため,ソースを見ても動作に検討がつくようになりましたし,liftとか融合とか,避けていた知識を身に着けたら,いろんなことがより簡素に表現できるようになりました。結局,ECUとのコミュニケーションモジュールは,出来合いの ReaderT を活用しています。ちなみに,モナドはRealWorldHaskellの記載内容から変わったところ(変わるところ)があるので,要注意。

Haskellでの例外処理を理解した

関数やIOモナド,スレッド間通信などがからむので,”Parallel and Concurrent Programming in Haskell”を電子書籍で購入して並行プログラミング関係だけ読み,初歩はマスターできました。このプロジェクトではマルチスレッド間の資源の取り合いはほとんどないので,できるだけ例外をマスクして,Eitherなどで把握・対処するようにしています。STMを利用したチャンネルで,スレッド間の通信をおこなうようにしました。

Haskell用TUIライブラリを使ってみた

Brickを使ってみました。GUIの基礎概念は知ってはいましたが,使ってみたのはほぼ初めて。プログラミングをよくやっていたのは学生時代で,まだGUIが一般的でない時代にPascalやModula II でPOSシステム,パソコン通信プログラム(端末エミュレータ)などを作っていました。まだオブジェクト指向という考えが広まる前で,インタフェースもGUI普及前。ユーザーとしては,まわりがワープロを使っている時代にMacintosh Plusで卒業論文を書いていたのでまさにエバンジェリストといった感じでしたが,イベント処理とか,GUIやオブジェクト指向でのクラスとかいった概念は,Smalltalkでちょっと触ったくらい。学び直しました。とはいえ,Brickのドキュメントを読むと一通り書いてあるので,それで済ませましたが。

グラフの作成

TextPlotというそのものズバリの名前の,テキスト文字によるグラフ作成ライブラリを使ってみました。ライブラリのソースを読んでみたのですが,仕組みとしては事前に考えていた内容そのものであったものの,その表現が関数プログラミングの利点を活用してすごく簡素に書かれていてびっくり。ただ,機能がシンプルで,随分前に進化が止まっているようなので,カラー化とか凡例表示とか,Vector化とか,いろいろ改造していきたい。

今後の計画

ラズパイでの稼働

本来はMacBookAirなどノートパソコンではなく,ラズパイなど超小型コンピュータで稼働させたいところですが,大型ライブラリBrickを使うために,ラズパイで直接コンパイルすることは難しそう。Docker と QEMU でクロスコンパイル環境を用意しましたが,stack を利用してのコンパイルはまだ完了していません。これをなんとかしたい。

グラフ表示の改善

表示要素が多いと,グラフの把握が難しくなります。カラー機能自体は既に使っていますが,TextPlot側が対応していないので,要改造。
また,凡例表示や,X軸時刻表示(今は単なる相対時系列番号)も課題。

終わりに向かって

ハードの監視というきわめてHaskell向きではない分野で手続き的な表現を多用していましたが,少しづつ関数プログラミングらしい表現を取り入れています(FunctorやAplicativeFunctorな演算子の導入とか)。抽象化が進むので,機能を増やしてもそれほどソースの行数が増えず,実行速度もあまり遅くならないことに感動。

OLYMPUS DIGITAL CAMERA

おかみフェスタ,近鉄百貨店四日市店で開催

先日,東京日本橋の #みえテラス で行われた #座・みえ #おかみフェスタ が,明日8/10(土),近鉄百貨店四日市店の #伊勢路テラス で開催されます。10:00から18:00まで。
http://okamifesta-mie.com/?page_id=118

スライドショーには JavaScript が必要です。

#おかみフェスタ は三重県の元気な女性事業者さんのあつまり。 ものすごい おかみを自称する元気なおかみの面々を見てみたいという方,お近くの方,ご興味のある方は明日はぜひ近百へ!

おかみ公式サイトの告知

今回の参加事業者さん一覧(順不同)

MEMSプロトコルのページ

MEMS Monitor作成の際に参考にしているMEMS のプロトコルが記載されているサイト内でのURLが変更されていた1。サイトのリニューアルにともなうものらしい。

新URL http://www.bearinghead.com/car_stuff/mems_interface/

MEMSとは

MEMSとは, Modular Engine Management System のことで,Roverグループが自社の車の車載制御システムとしてモトローラグループと開発し,1990年代に使用していたもの。魚野が1992年に新車で購入していまだに乗り続けているRover Mini Cooper 1.3iも搭載している。

MEMS Monitorの現状

関数型言語Haskellの学習を兼ねて作成していたMEMSデータの常時読み出し・表示プログラムは,概ね動作するようになった。実装済みの機能としては,1)ECUデータやエラーデータの読み出しと表示(概ね0.4秒サイクル),2)ECUのエラーリセットコマンドの発行,3)ECUコマンド(アクチュエータ操作)の発行の3つ(ただし,3)についてはすべてのコマンドを実装したわけではなく,動作確認のためいくつか実装したのみ)。

(ミニが修理が終わってもどってきたら,動作中の画面を撮影して掲載します)

実装計画中の機能

  • 重ね合わせグラフでの表示
  • 冷却液温度急上昇などの異常検出と警告表示
  • IoT用のSIMで走行中のデータを順次クラウドに送信

動作環境としてはmacOS(High Sierra, Catalina),Haskell(stack)を利用して検証しており,現在,Raspberry Pi(Paspberian)環境下でも動作させられるかの実験中。実験が成功すれば,ラズパイを車載し,モバイルバッテリーあるいは12V電源の変圧で走行時は常時データを表示・採取できるようにしたい。

読み出しているECUデータ

ただし,うちのECU(型式不明)は,駐車またはニュートラルの信号がエアコンオンオフの信号になっている。

    engineSpeed :: Int   -- Engine speed in RPM (16 bits)
  , coolantTemp :: Int   -- Coolant temperature in degrees C with +55 offset and 8-bit wrap
  , ambientTemp :: Int   -- Computed ambient temperature in degrees C with +55 offset and 8-bit wrap
  , intakeATemp :: Int   -- Intake air temperature in degrees C with +55 offset and 8-bit wrap
  , fuelTemp    :: Int   -- Fuel temperature in degrees C with +55 offset and 8-bit wrap. This is not supported on the Mini SPi, and always appears as 0xFF.
  , mapSensor   :: Int   -- MAP sensor value in kilopascals
  , battVoltage :: Float -- Battery voltage, 0.1V per LSB (e.g. 0x7B == 12.3V)
  , throttlePot :: Float -- Throttle pot voltage, 0.02V per LSB. WOT should probably be close to 0xFA or 5.0V.
  , idleSwitch  :: Bool  -- Idle switch. Bit 4 will be set if the throttle is closed, and it will be clear otherwise.
  , unknown0B   :: Word8 -- Unknown. Probably a bitfield. Observed as 0x24 with engine off, and 0x20 with engine running. A single sample during a fifteen minute test drive showed a value of 0x30.
  , pnClosed    :: Int   -- Park/neutral switch. Zero is closed, nonzero is open.
                         -- Fault codes. On the Mini SPi, only two bits in this location are checked:             
  , faultCode1  :: Bool  -- : Coolant temp sensor fault (Code 1)
  , faultCode2  :: Bool  -- : Inlet air temp sensor fault (Code 2)
  , faultCode10 :: Bool  -- : Fuel pump circuit fault (Code 10)
  , faultCode16 :: Bool  -- : Throttle pot circuit fault (Code 16)
  , unknown0F   :: Word8 -- Unknown
  , unknown10   :: Word8 -- Unknown
  , unknown11   :: Word8 -- Unknown
  , idleACMP    :: Int   -- Idle air control motor position. On the Mini SPi's A-series engine, 0 is closed, and 180 is wide open.
  , idleSpdDev  :: Int   -- Idle speed deviation (16 bits)
  , unknown15   :: Word8 -- Unknown
  , ignitionAd  :: Float   -- Ignition advance, 0.5 degrees per LSB with range of -24 deg (0x00) to 103.5 deg (0xFF)
  , coilTime    :: Float   -- Coil time, 0.002 milliseconds per LSB (16 bits)
  , unknown19   :: Word8  -- Unknown
  , unknown1A   :: Word8  -- Unknown
  , unknown1B   :: Word8  -- Unknown
  , lambda_voltage:: Int  -- This lambda value is a calculated value (if it is the same as the British emissions test).     And a value of, say, 1.05, suggests it is 5% too lean.   But, if your oxygen (and CO and HC) readings are all good, then it suggests your high lambda reading is because of a leak in the exhaust wgich pulls in fresh air (and oxygen).     You could try starting your car when it is cold and put your hand over the exhaust pipe and look underneath to see if water is leaking from any if the joints. 
  , closed_loop'  :: Int  -- 0 : Open Loop, others : Closed Loop  
  , fuel_trim'    :: Int  

  1. 著作者の表記が当該サイトにはないので,誰がメンテナンスしているかは不明。当初は某大学のサイトに掲載されていたので,その大学の卒業生が運営しているのではないかと推測。 

stackとraspberry pi

raspberry pi で stack buildできなかった問題,解決

Rover Mini の ECUデータ読み出しプログラムを動作させるためにRaspberryPiを用意したのだが,Haskellのコンパイルがstackを使ってはできなかった。stackが使えないと,ライブラリの準備とかが大変。

発生していた問題

stack buildすると,アセンブラが,この機械語はARMでは使えないとのたまうエラー発生。

/tmp/ghc2452_0/ghc_6.s:44:0: error:
Error: selected processor does not support `movt r7,:upper16:stg_bh_upd_frame_info' in ARM mode
|
44 | movt r7, :upper16:stg_bh_upd_frame_info
| ^

原因と対策

原因はコンパイル時にCPUアーキテクチャがGHCに伝わらないstackのバグ

対策は海外サイトのブログを参考に,GHCの設定ファイルにアーキテクチャ指示オプションの追加。以下は上記の参考サイトに書いてあるものだが,実際にはGHCの8.6.3がインストールされていたので,適宜8.0.1を8.6.3に読み替え。

$ vi ~/.stack/programs/arm-linux/ghc-8.0.1/lib/ghc-8.0.1/settings
...
("C compiler flags", " -marm -fno-stack-protector -mcpu=cortex-a7"),
...

あとがき

しかし,一昨日,車室内で冷却液の噴出をやらかしてくれたRover Miniはあえなく修理にまわすことに…。当面,ラズパイによるECUのモニタリングソフトの出番は先です。

あとがきその2

古いラズパイ上でHaskellを走らせたりWiFiドングルを使ったりしているのですが,いくつか注意点がありました(現在は解決済みのものもある):
– apt-get で入れられる stack のバージョンが古い。現在はRaspberianのもとになるディストリビューションが変更されたためか,関係者のご尽力により普通に入れられます(ただし,前述のGHCのコンパイルオプションが渡されないバグに注意)。
– 大型のライブラリをコンパイルしたり,インストール直後の何もコンパイルされていない状態から大量のライブラリをコンパイルすると,メモリとディスク上のスワップ領域を使い切ってOSごと固まってしまう模様。恒久的にスワップファイルのサイズを変える方法恒久的にスワップファイルのサイズを変える方法その2一時的にスワップファイルのサイズを変える方法
– WiFiドングルにはドライバが必要(ただし,ヤマダ電機で購入したElecomのドングル(型式:●●)は最新のOSだと初期設定でそのまま動きました)。

車内ヒーターから冷却液噴出した92年新車登録のRover Mini,ただいま乾燥中。