ESP32-WROOM-SOLO でトラブった件

TL;DR

WROOM-SOLOチップを使う場合、とりあえず動かすには PlatformIO で ESP-IDF を選択して sdkconfig.h を次のように変更する必要がある。

  • 「#define CONFIG_FREERTOS_UNICORE 1」の行を追加
  • 「#define」行のうち「_CPU1」を含むもの、および「_PINNED_TO_CORE_0」を含むものを削除

※間違えて「_PINNED_TO_CORE 0」(CORE と 0 の間が「_」でなく半角スペース)を消さないよう注意

長文版

前回書いてからだいぶ経ったなぁと思いつつ最終更新日を見たら一年も経過していて愕然とした新年最初の月(の終わり)でございます。

久々に電子工作のネタを思い付いたので bluetooth LE の使えるワンチップマイコンの ESP32-WROOM を購入したのですが、カタログを見ながら毎度のごとく下手な考えで「ちょっと安価なシングルコア版かぁ、こっちが買いだな。」とやって要らぬ苦労をしたという話です。

くだんの ESP32-WROOM チップ自体は有名なので、変種の -SOLO についての情報もある『だろう』と思って調べもせずに購入してしまったのです。それがこれから始まる苦難の道への第一歩であるとも知らずに…

問題が発覚したのは注文の翌々日、商品が届いたその日でした。
一緒に頼んだブレッドボード用のブレイクアウト基板に WROOM-SOLO をハンダづけし、arduino-IDE でサンプルスケッチの Blink (いわゆる L チカ)を書き込んで走らせたその時、シリアルモニタに驚愕すべき文字列が表われたのです!

原文

E (98) cpu_start: Running on single core chip, but application is built with dual core support.
E (99) cpu_start: Please enable CONFIG_FREERTOS_UNICORE option in menuconfig.
abort() was called at PC 0x4008274e on core 0

萌訳

べ、別に双頭人向けのマニュアルが読めないわけじゃないのよ!
でも、あんたがどうしても単頭人版も用意したいって言うなら、特別にそっちも読んであげてもいいわ!

「…ま、まあ CPU コア数が違うんだから、設定項目くらいあるか。うん、考えてみれば当然だよなぁ、ははは…」と呟きつつ、指示通りにシェルから make menuconfig を実行すると『make.exe”: *** No rule to make target `menuconfig’. Stop.』という非情なエラー表示が…

しかし、これはまだ序の口でした…

この直後に起こった闘いは、かの有名な「血と硝煙の七日間」として後世で語られるものとなったのです。

…が、紙幅の都合により、ここではダイジェストでお送りします。

  • arduino-IDE で別ボード名の設定を次々と試しては希望を砕かれ、失意のうちにマンハッタン隔離区画(通称 The division)にてマディソン野戦病院から医師を保護する作戦に召集
  • google 神の託宣を求めるも主流のデュアルコア派に関する情報しか得られず途方に暮れる中、リンカーン・トンネル検問所に追い詰められた部隊の救出に従事
  • データシートの解読を試みるも求めるものは見付からず、直後にマンハッタンの地下死体安置所から技師のポール・ローズを連れ出す作戦を遂行
  • PlatformIO 環境に変えてみても arduino 版は動かず、絶望にうめきながらハドソン難民キャンプからクリーナーズを排除
  • ESP-IDF 版では 4秒だけ動いてリセットが繰り返されるという怪奇現象に悩まされつつ、ブロードウェイの商業施設にて汚染源と推測されるドル札を調査
  • ようやく Linux 仮想マシン上にて動くバイナリが make できる事をつきとめ、 祝賀イベントと称してクリーナーズの火炎弾生産現場を襲撃
  • ついに Windows の PlatformIO での設定方法が判明した喜びでハイになった勢いで、タイムズスクエアの継電器をライカーズギャングから奪還

このときの携行火器はショットガンとサブマシンガン、 何度も半死半生になりながら仲間の援護射撃の下、イチかバチかの敵陣特攻を繰り返したと伝えられています。
…って話題が入れ替わってますね、はい。

というわけで、なんとかマトモに動く目処が付いたので忘れないうちに駄文記録を残しているところです。

オマケ:-SOLO 用設定のデフォルト化

新規プロジェクトで用意される sdkconfig.h の テンプレートを探したところ、grep して辿り着いた ~/.platformio/platforms/espressif32/builder/frameworks/espidf.py を見た限りでは espressif32/examples/*/src/sdkconfig.h を探して見付かったどれかをコピーしてくるようなので、次の手順で毎回の sdkconfig.h の変更を回避する事にしました。

  1. examples フォルダ内にあるサンプルを別フォルダに移動する
  2. サンプルの一つである espidf-blink フォルダ以下を examples にコピーして戻す
  3. 唯一のテンプレート候補である examples/espidf-blink/src/sdkconfig.h に次の変更を行う
    1. 次の一行を追加「#define CONFIG_FREERTOS_UNICORE 1」
    2. 以下のいずれかを含む行を削除
      1. 「_CPU1」
      2. 「_PINNED_TO_CORE_0」(CORE と 0 の間はアンダーバー記号)

ちなみにデュアルコア版 WROOM は変更後の設定でも(単一コアモードで)動きます。
※ESP32-WROOM 自体ではなく、変種の ESP32-WROVER-B で確認しました

Laravel で FixedMidashi を使う時

よくある話ですが、Web アプリでテーブルの上側(列ヘッダ)と左側(行ヘッダ)を固定したまま残りをスクロールしたい状況になりまして、検索して FixedMidashi JS ライブラリに辿り着きました。
これが非常によく出来ていて、使い方が簡単なのに見事に動作するという優れ物です。
心配していた bootstrap3 との併用も難無くクリアしてくれました。

しかしながら Laravel で動かすのに一点だけ手間取ってしまいました。
と言っても FixedMidashi 側に問題があったわけではなく、Laravel Mix でアセットコンパイルしたら動かなかったという話です。
最初試すのに public/js フォルダに置いた時には動いていたので、原因に辿り着くまで1時間くらい唸ってました。
最終的には mix.js や mix.scripts で処理するのではなく mix.copy を使って単純にコピーすることで解決しました。

いつも通り備忘録という名目でデータの海に一滴追加しておくことにします。

windows10で突然プリント枚数が増えた件

今回はトラブル報告です。

毎月 Excel で印刷している 1ページのデータがあるのですが、なぜか突然 4ページに分割されるようになりました。
プレビューでは今まで通り 1ページなのですが『印刷』ボタンを押すとダイアログに「1/4 ページ印刷中」となります。
そのファイルを別のパソコンで印刷すると大丈夫だったり、他のファイルだと問題無かったりと不思議な症状でした。

色々と試した結果、どうやら Windows10 のアップデートが原因のようで、バージョン 1709 ビルド 16299.125 で発生し、バージョン 1703 ビルド 15063.726 の方では起こりません。

症状は『ページ設定』においてパーセント指定で拡大縮小していると、その値が無視されるというものです。(Excel 2010 で確認しました)
改ページプレビュー表示で調整しても、印刷ボタンをクリックすると100%サイズで改ページされ、複数枚に分かれてしまいます。

対策としては『ページ設定』で『次のページ数に合わせて印刷』の方を使って設定することです。
こちらで縦・横の枚数を設定してやると、希望通りに印刷されました。

同じ症状に悩んでいる方のお役に立てば幸いです。(←ここに辿り着くのが一番の難関ですが)

いきなり slime が動かなくなった件

原因は不明ながら、slime が急にエラーで動かなくなってしまったので経過をメモ。
(思い出しながら書いているので、あやふやな部分あり)

検索したサイトを見ながら popwin の設定やら ac-slime のインストールやらをしていたら、ある時 M-x slime するとエラーするようになってしまった。
※正確には swank サーバへの接続待ちのままになった。表示通りに M-x slime-abort-connection するとキャンセルされて REPL には入れる。

その状態で (require 'asdf) (require 'alexandria) すると /usr/share/common-lisp/source/cl-asdf/build/asdf-TMP.lisp が FILE OPEN エラーになってデバッガに入ってしまった。
emacs を終了してコンソールから直接 sbcl で実行しても同じエラーになった。

~/.cache/common-lisp/ を削除してみたが直らず。
apt で slime と cl-asdf を再インストールしてもダメ。

以前に作成した以下のファイルを削除したら slime は起動するようになった。

;;;; ~/.config/common-lisp/source-registry.conf
(:source-registry
  (:tree "~/quicklisp/dists/")
  :INHERIT-CONFIGURATION)


require もエラーしなくなった… はず。ただ、相変らず (require 'alexandria) の返り値が nil だったのでダメかと思って作業を継続した。
この時点で最終結果と同じ状態に戻っていたのかもしれない。
(require 'asdf) の返り値が nil だったかは覚えていない。

その後、~/quicklisp/ も削除して slime から (load "/usr/share/cl-quicklisp/quicklisp.lisp") (quicklisp-quickstart:install) で再インストールしてみた。
ここで (ql:quickload 'alexandria) するとインストールが行われ、(alexandria:lastcar '(a b c)) が動作した。
そのまま更に (ql:add-to-init-file) を実行して設定ファイル(sbcl だったので ~/.sbclrc)に quicklisp の自動ロードを設定した。
一旦 emacs を再起動し、require するも返り値は nil のまま。
コンソールから sbcl でやっても同じく nil が返っていたが、何の気なしに alexandria:lastcar をやってみたら動作した。

ふと思い付いて .sbclrc の quicklisp 設定をコメントアウトしてから、コンソールで (require 'alexandria) したらエラーになった。
そのまま (load "~/quicklisp/setup.lisp") したところ alexandria:lastcar が動作した。

quicklisp 設定をコメントアウトしたままの状態で ~/.config/common-lisp/source-registry.conf をエラー前に戻してみた。
そうしたら (require 'alexandria) がエラーせずに nil を返し、alexandria:lastcar も動作するようになった。

元々は .sbclrc の quicklisp 設定はコメントアウトされていたので、結局エラー前と同じ設定に戻ったことになる。
経過から見るとキャッシュを壊していた確率が高いが、問題の原因は特定できず…
とりあえず動作するので、まあいいかと。

最終的にはコンソールでも slime でも以下のように動いている。
(行頭に「?>」があるのがプロンプトと入力内容で、次のプロンプトまでが出力)

?> (require 'asdf)
("ASDF" "asdf" "UIOP" "uiop")

?> (alexandria:lastcar '(a b c))
※以下のエラーが発生した
debugger invoked on a SB-INT:SIMPLE-READER-PACKAGE-ERROR in thread
#:
Package ALEXANDRIA does not exist.

Stream: #

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.

(SB-IMPL::READER-FIND-PACKAGE "ALEXANDRIA" #)

※ 0 でデバッガを終了してトップレベルに戻る

?> (require 'alexandria)
nil

?> (alexandria:lastcar '(a b c))
c

以上。

nodoka で右 Shift キーが効かなかった件

昨日に引き続きキーカスタマイズのネタです。

実は Windows で Emacs 似のキーバインドを使いたいために nodoka というユーティリティを使っているんです。
で、今まで気付いては忘れてた挙動に「右 Shift キーでは Shift されない」というのがありました。

今回よく調べてみたところ、nodoka を一時停止すると問題無く Shift されるので、設定が原因だろうと色々試しました。
調査とログのダイアログを駆使して探った結果、下のような設定で無事に動きました。


# 右 Shift のキー名を定義
def key E0RightShift E0RShift = E0-0x36
# 右 Shift を 左 Shift とみなす
def subst E0RShift = LShift
# 仮想キーの Shift が押されるように設定
keymap Global
mod shift += E0RShift
key *E0RShift = *LShift
# nodoka を使いたくないキーマップ(KeymapDefault)にも適用
keymap KeymapDefault
mod shift += E0RShift
key *E0RShift = *LShift

これはマニュアル(カスタマイズ詳細)中央あたりの次の部分を参考にしました。

なお、右シフトキーが使えないことは致命的なので、ホスト側の のどか設定ファイルでは、window RemoteDesktop /mstsc\.exe/ を記述し、ホスト側でのキー入れ替えは無いことにして、リモート側のどかの設定ファイルでは、下記のような設定をすると良いでしょう。

def key E0RightShift E0RShift = E0-0x36

mod shift += E0RShift

key *E0RShift = *LShift

カスタマイズまわりはハマると面倒ですね。

Putty 経由の Emacs で C-M-S-v が入らない件(未解決)

今回は Emacs です。
以前から使ってはいたのですが、ここを参考に設定しなおしてみようかと思いまして。

とりあえず Ubuntu Linux の仮想マシンを用意して Putty でログインして Emacs をいじっていました。
で、サンプルの通りにキーバインド「C-,」を割り当てて使ってみると動きません。
現在の割り当てを調べる「C-h c C-,」を使ったところ、どうも「C-,」が Linux に入っていないようでした。

この問題については最終的にこのサイトを参考にして解決できました。

該当ページ中から「xterm風定義」リンクを辿ると他のキー一覧もあります。
その中でカンマを示す「VKey188」の行ですが、以下(4番目が \033[27;6;60~)が正しいのではないかと思います。
VKey188=\054,<,\033[27;5;44~,\033[27;6;60~,\033\054,\033<,\033[27;13;44~,\033[27;14;60~

引き続いて「C-M-v」の別ウィンドウスクロールの逆方向版を「C-M-S-v」(Shift を追加する)に割り当てようとしましたが、こちらは解決できませんでした。
「C-,」と同様に「VKey…」を追加すればいいかと思って下のように色々試したのですがダメでした。

試した内容

  • VKey86=,,,,,,,\033[27;14;118~
  • VKey86=,,,,,,,\033[27;14;86~
  • VKey86=,,,,,,,\033[27;14;v~
  • VKey86=,,,,,,,\033[27;14;V~
  • VKey86=,,,,,,,\033[27;5;118~
  • VKey86=,,,,,,,\033[27;5;86~
  • VKey86=,,,,,,,\033[27;5;v~
  • VKey86=,,,,,,,\033[27;5;V~

カンマ区切りのキーコード出力部の内容は 「\033[27;≪修飾コード≫;≪キーコード≫~」だろうと思っています。
この中にある「27」は多分 Escape キーの VKey コードでしょう。

どれも思うようにいかなかったので、現在はエスケープシーケンスの規則を調査中です。
参考サイトに書いてある気もしますが、英語を読むのが面倒なので Try&Error で頑張ります。

参考サイト

ちなみに「C-,」問題は nadoka で「key C-Comma = &SendText("\e[27;5;44~")」でも解決できましたが、対象文字列を入れる時に一文字ずつ(少しだけ)ウェイトがかかって微妙な気分になるので止めました…

MySQL のテーブルコピーでやらかしてしまった件

はい、タイトル通り、今回はやらかしてしまった件です。
幸いにも被害は自分だけに留まったので大目玉をくらう前にコッソリ修正できましたが…

で、何をやったかというと、データごとテーブルのコピーを取るのに「CREATE TABLE test_t SELECT * FROM current_t」と叩いて test_t テーブルを作成したわけですよ。
それで、test_t テーブルをいろいろいじってから「RENAME TABLE current_t TO old_t, test_t TO current_t」として現行のテーブルと入れ替えました。
念の為にちょこっと動かしてみて、問題が無いようなのでそのまま利用することにしました。

悲劇はその後に起こったのです!

機能の追加を行った後で動作確認をしようと、テーブルに新規レコードを追加してからそのレコードを検索したところ… 見付からない…?
慌てて同じ条件で SQL コマンドを叩くと、ちゃんと居る…?
まさか幽霊かと思っても、この相手には見て確かめるための足はありません。
首を傾げながらレコードを消しては作り、消しては作り… 何度目かにふと思い立って SELECT * で全カラムを表示させてみました。
するとそこには… ああ、今思い出しても恐しい… プライマリキー値 0 (ゼロ)が居たのです!!

この時の動作は、レコードを探してそのプライマリキーを得るというものでした。その関数はエラー時に FALSE を返します。
ここで親切な PHP さんは、boolean の文脈では空文字列や数値の 0 (ゼロ)も FALSE だと判断してくださいます。
賢明な読者様にはもうお分かりでしょう。上の新規レコードが返すプライマリキー値 0 はエラー処理ルーチンの方へ入ってしまうのです。

まあ、ここまでは比較的よくある話とも言えます。
しかし、今回の真の敵はコイツであるはずが無いのです。何故ならそのカラムには AUTO_INCREMENT 属性が付けてあったのです。
つまり、新規レコードには自動的に新しい ID値が付与されるため、値 0 が設定される事実とは矛盾します。
この矛盾が今回の密室殺人の謎を解くカギになるはずだっ!(違)

と、ここまでが前置きです。
本題は「SHOW CREATE TABLE current_t」を実行した時に発見した驚愕の事実にあります。
コピー元(リネーム後の old_t)では「NOT NULL PRIMARY KEY AUTO_INCREMENT」となっていた部分が「NOT NULL DEFAULT ‘0’」に変わっているではありませんか。
確かにこれならプライマリキー値を指定しない新規レコードで、その値がデフォルトの 0 になるのは納得です。

実はテーブルのコピーを行う SQL 命令はもう一つあります。
こちらはテーブルの形だけコピーし、レコードは拾って来ない「CREATE TABLE new_t LIKE current_t」というものです。
この命令では、上で問題になった部分も元のまま「PRIMARY KEY AUTO_INCREMENT」で引っ張ってくれます。

以上から導き出される結論が「テーブルの全コピーを取るには CREATE TABLE LIKE で定義をコピーしてから INSERT INTO SELECT でレコードをコピーするという二段階で行うべし」というものです。
まあ、それ以前に作業した後にはちゃんと確認しろ(この場合は SHOW CREATE TABLE)という事なんですが…

ということで、今回の(イタい)レポートはこれで終わります。

phpMyAdminの環境保管領域が完全に設定されていない… エラー

おひさしぶりです。
不定期開催の今回のネタは phpMyAdmin on Ubuntu 14.04 LTS です。

とりあえずパッケージ入れてみたんですよ。
そしたら、ログインすると「phpMyAdmin 環境保管領域が完全に設定されていないため、いくつかの拡張機能が無効になっています。理由についてはこちらをご覧ください。」と表示されたわけです。
コマンドラインから見てみると、環境保管領域に使われる phpmyadmin データベースが無かったので CREATE TABLE して…ダメ。
中身を入れればいいのかと /usr/share/doc/phpmyadmin/examples/create_tables.sql.gz を流し込んでみても…ダメ。
権限の問題かと CREATE USER と GRANT を駆使しても…ダメ。

…結局、/etc/phpmyadmin/config.inc.php の中身で環境保管領域用のテーブル名を定義している部分で「_」(下線、アンダースコア)が一つ不足していたのが原因でした。
直接そのファイルを直すかわりに /etc/phpmyadmin/conf.d/env-storage.php を以下の内容で作りました。
ほとんどは /usr/share/doc/phpmyadmin/example/config.example.inc.php からコピーしたものです。


<?php // ここから

$i = 1; // インデックスを 1 に戻して(1-ベースなので最初が 1)
/* Storage database and tables */
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
$cfg['Servers'][$i]['tracking'] = 'pma__tracking';
$cfg['Servers'][$i]['designer_coords'] = 'pma__designer_coords';
$cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
/* Contrib / Swekey authentication */
// $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
?> // ここまで

それから、試行錯誤している時に /etc/phpmyadmin/config.inc.php を見ていたところ、設定ファイルは次のような順序で読み込まれるようでした。(後ろにある内容が優先)

  1. /var/lib/phpmyadmin/config.inc.php (phpMyAdmin/setup で変更されるファイル)
  2. /etc/phpmyadmin/config-db.php
  3. /etc/phpmyadmin/config.inc.php (今回の悪の元凶)
  4. /etc/phpmyadmin/conf.d/*.php (設定を追加した場所)

…以上で今回のレポートを終わります。