No.21, No.20, No.19, No.18, No.17, No.16, No.15[7件]
Tweet ⌚ 2022年2月20日(日) 10:20:32 情報 <7955文字>
イワタニ CB-JCB ジュニアコンパクトバーナー
クレジットカードの使いすぎっていうか…ポイントがどっさり貯まっててそれが失効しそうってご連絡を頂いたんで慌ててポイント交換して イワタニ CB-JCB ジュニアコンパクトバーナー をげっちゅしました
ハードケース入りのコンパクトなやつ
このテのバーナーは 新富士バーナー の SOTO ST-300 ってのを永らく愛用しています セパレートなんで置き場所の自由度が高くてよかったんだけど…頑丈なバーナー部が災いしてなのか 600g というずっしり感のある重さがちょっとネックだったんですよね セパレートの自由度は利点である反面…セッティング/片付けがちょっと面倒なんもあって愛用してたと云いつつ使用頻度はそれほど高くありませんでした(汗
そんな訳なんで…半分以下の重量の CB-JCB には期待しちゃってます!(>_<)w
それでは早速セッティングしてみましょう まぁ脚をパタパタパタと広げて…ゴトクをパタパタパタパタと広げて CB 缶をブッ挿してねじって完成!って感じなんで説明する間もありませんが
せっかくガスバーナーを持ち出してきたのにカプ麺じゃ少々味気ないかな…って事なんで今回は袋麺を作っちゃう!
できたw おいしいwww この日は強烈な伊吹おろしが吹き荒れる天気で…まぁ物陰に隠れてはいたもののそれなりに風が巻き込んできてたけど問題なく使用できました
今回は丸型のコッヘルを使ったのですが…このゴトクの使い勝手がいいっていうかコッヘルの座りがよく安定感を感じました
段々にカットされているのでスッポリと納まる感じですかね
ざっくり測った感じでは 15cm のコッヘルまではズバピタに収まって使えるみたいです 逆に…長方形のコッヘルっていうかメスティンとかだとどんな使い勝手になるんだろ?って思ったりしていました
:
使い終わったらお片付けって事なんだけど…付属のハードケースに入れた際に数ミリ程度の隙間があって「ガタゴト」と揺れまくるんですよね 現実的な対策として軍手で包んだ後にハードケースに納めるといい感じになりますね
そう云いつつ…我が家では某Dイソーで買ってきた重ねられる箱に CB 缶と共に入れて使おうかと思ってます カバンやザックのなかでゴロゴロしがちな CB 缶をスマートに持ち歩けるようになると期待しています
あとオマケ的な話だけど…安っすい 遠赤ヒーターアタッチメント も持ち歩くようにしています これをゴトクにセットして燃焼開始すると…遠赤外線が発生して程よい暖房になるって感じらしいです まぁ確かに直火に手をかざしているより段違いに暖かいような気がします なんならこの上にコッヘルを載っけてお湯を沸かしたりとしても使えるようです
どうなんだろね よっぽどな時の非常用なのかなーってイメージですが…むっちゃ寒い真冬のキャンプツーリングなんかで威力を試せたらなぁって思います #アウトドア
Tweet ⌚ 2022年2月7日(月) 16:35:18 趣味 <1266文字>
Arduino の シリアル通信
Arduino VKLSVAN Pro Micro USB ATmega32U4 (※以下 Arduino と略す)で開発してる際のデバッグとかで「変数がどうなってるのか」を見たくなることはありませんか? 私はあります いやむしろ見ないとやってられません!!(>_<)wって感じなんだけど Arduino にはモニタ出力がありません
なんか LCD ディスプレイとやらを接続すれば文字なんかを表示させられるっぽいけど…接続とか面倒そうだし手が出ないなぁと思ってたけど何やら「シリアル通信」ってので PC と文字のやりとりができるらしいじゃん!? まじか!!
そんなシリアル通信は Arduino IDE から使えるようです
[メニュー] → [ツール] → [シリアルモニタ] と操作するか…
もしくはツールバーにある虫メガネみたいなアイコンを押下すると出てきます
出てきた「シリアルモニタ」はこんな感じです
我が家の環境では「改行コード = LFのみ」で「通信速度 = 9600bps」が初期設定となっていました
通信速度は Arduino 側で設定した速度とシリアルモニタで設定する速度は同じものにしておく必要がある…らしいんですが軽くイジってみた感じでは設定値に関係なく動作しているっぽい感じなんで気にする必要はないのかもしれません
改行コードは Linux 系が「LF」で Mac 系(の昔のやつ?)が「CR」で… Windows 系が「CR+LF」と聞いたことがあるので機種ごとに適切なものに変更しておいたほうがいいの?
ざっくり使ってみた感じでは… Arduino からシリアルモニタに送られてくる場合の改行コードは設定の影響を受けないっぽいです シリアルモニタから Arduino に送信する際に「送信ボタンを押した」もしくは「エンターキーを押した」時に改行コードをどのようにするかの設定となるようです なおここでの解説は改行コードを「LFのみ」に設定してあるものとします
:
それでは早速と言うか Arduino からシリアルモニタに文字を送信してみましょう シリアル通信を開始するには以下のように記述します
Serial.begin(speed) ってやつですね speed は BPS で… 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200 なんかがよく使われがちですがそれ以外の値も指定できるようです ここでの解説では「9600」を使用するとします
その後は Serial.print() や Serial.println() を使ってシリアルモニタに数値や文字列を送信できます Serial.print() は C で云うトコロの sprintf() を意識した作りとなってるようですが…書式を全て解説するのもアレなんでその辺は手を抜いてざっくりサンプルを載せておきます
----------
void setup() {
Serial.begin(9600); // シリアル通信を開始する
}
void loop() {
unsigned long time = millis() / 1000; // 動作時間を秒の単位で取得
String h = String(time / 3600); // 「時」を文字列にして取得
String m = String((time % 3600) / 60); // 「分」を文字列にして取得
String s = String(time % 60); // 「秒」を文字列にして取得
Serial.println(String(h + ":" + m + ":" + s)); // 整形して送信
delay(1000); // 1 秒待って繰り返し
}
----------
これは Arduino が動作開始してからの時間を延々と表示し続けるってものです 動作開始してからの時間をミリ秒で取得できる millis() 関数を使い…そこで得られた変数の値を人の目で確認しやすい(と思われる)「時:分:秒」に整形して表示しています こんな感じで変数の内容を確認できるんでデバッグなどでは大いに助かりますね!
:
シリアルモニタには Arduino に対して文字を送信する機能も備えられています それを Arduino 側から Serial.read() などを使って読み取るわけですが…基本的に「1文字づつ」送られてくる扱いになるようです
例えば「a10Z」と送信すれば「a」と「1」と「0」と「Z」に「設定した改行コード」が加えられて順番に送られてきます
あと文字は「文字コード」として送られてきます 「a」だと「97 (0x61)」となり「1」だと「49 (0x31)」となり「0」だと「48 (0x30)」となり「Z」だと「90 (0x5A)」で…最後に「改行コード(LF)」が「10 (0x0A)」って感じになります
デバッグ時に「ループ回数の変数をプログラム実行中に指定の値に変更したい」とかの場合だとシリアルモニタから送られてきた「文字」を「数値」に変換する必要があります
----------
void setup() {
Serial.begin(9600); // シリアル通信を開始する
}
void loop() {
if (Serial.available() > 0) // 文字(列)が送信されてきた?
{
byte data = (Serial.read()); // 送信されてきた文字を読み込む
if (data >= '0' && data <= '9') { // 文字は数字か?
data = data - '0'; // 文字コードを数値に変換
Serial.print("数字が入力された [" + String(data) + "]\n");
} else {
if (data == 10) { // 改行コードは表示に不都合があるんで
data = 0; // 何も表示しないようにしておく
}
Serial.print("数字以外 [" + String((char)data) + "]\n");
data = 0; // 数字以外は「0」と扱うことにする
}
for (int i=1; i <= data; i++){ // 送信された数値の数だけループしてみる
Serial.print(String(data) + " 回ループの " + String(i) + " 回目\n");
}
}
}
----------
シリアルモニタに適当な適当な文字(列)を入力して「送信」します
送信した文字に「数値」があればその数だけ for() のループ回数を変更します 「数値」以外の文字は処理しないようにしてあります
なお「1文字づつ」送られてくるってのが少々厄介で…「10以上の数値」を扱う場合にはひと工夫必要です どうしたらいいんだろう? 先に送られてきた数値を10倍してそこに新たに送られてきた数値を足すって流れになるのでしょうか ちょっと大掛かりになってくるっていうか面倒なんで今回はスルーしときますが概ねそんな流れになると思います(汗
そんなこんなな Arduino のシリアル通信なお話でした しょーみもっと早く知っとっけばよかった!って思いつつ書いてましたとさ(瀧汗 #Arduino
:
※ 追記 ※
「いやいや Arduino でも sprintf() って使えるじゃん?」ってタレコミを頂いんたんでよくよく調べたらありました(汗 参照している Arduino リファレンス にはその辺が載ってなかったんで…無いものとばっか思ってました
他にも数値かどうか?を判定する isDigit() や改行の判定に使ってたものを isPrintable() に置き換えられるようなものもありました
上で説明してる数値を変数に代入して云々…で書いてるものもこんな感じでできそうです
if (data >= '0' && data <= '9') { // 文字は数字か?
↓
if (isDigit(data)) { // 文字は数字か?
----
if (data == 10) { // 改行コードは表示に不都合があるんで
↓
if (!isPrintable(data)) { // 改行コード等は表示に不都合があるんで
いやはや勉強になりました! 興味本位でなんとなく始めた Arduino ってことでまだまだ知らないことだらけなんで…こうして知識が広がっていくのは楽しいです どもありがとございました!(>_<)w
Tweet ⌚ 2022年1月30日(日) 15:35:43 情報 <3825文字>
かつや・デミチキンカツ丼
かつや の期間限定! 濃厚デミグラスソースにチーズのコクがたまらない デミチキンカツ丼 を食べてきました
オーダーして…厨房から漂ってくるデミグラスソースの香りからして気分が盛り上がってきます そして丼を覆い隠さんばかりのチキンカツが 2 枚! そこに豚肉たっぷりなデミソースがかかっています!
最初はデミソースがかかってないサックリした部分のチキンカツから楽しみ…お次はデミソースがかかったしっとりした衣を楽しむ流れがイイネ!
たっぷり豚肉も食べ応えあってたまりません! もちろん刻みキャベツも入っているし飽きること無く最後まで楽しめます
いやむしろ具だくさんすぎてご飯とのペース配分が困難すぎますねw これは丼より…ちょっと奮発して定食にしたほうが余すとこなく味わえるのかなーって思いました
期間限定なのが惜しい逸品です! また近いうちに食べに行きたいです #外食記録
Tweet ⌚ 2022年1月16日(日) 10:10:03 日記 <404文字>
Windows の BAT ファイルで CGI しよう
ぺけぽんっていうか Windows XP の頃にあまりにも怒り心頭になって勢い Microsoft に三行半を叩きつけてからずっと Linux な生活の日々なんですが…まぁそうは云いつつ Windows も使える事をアピールしておかないとオファーが来ないんでって感じなんで今回は Windows 的な話題っていうか BAT ファイルを CGI にしちゃおう!って解説です(汗
つーか初っ端から言い訳を並べるっていうか…我が家の Windows 機は 2015 年くらいに発売された 2 万円くらいの 8 型 Windows 10 タブレットって事なんでものすっごい低スペックです リソースなんて OS を起動するだけで使い果たしちゃう感じなんで新たにアプリケーションとか入れる余裕が全くありません なんか Windows でも CGI を動かす時は Perl や Python なんかを導入してるようですが…そんなんが入る空きなんてこれっぽっちも無いんで「それじゃ今あるもので何とかするか」ってことで標準的に使える BAT ファイルを引っ張り出してきた感じですかね(泪
世間的には Windows の Web サーバは Apache や IIS がよく使われている感じ?らしいですが…もちろんその辺を入れる余裕がないんで軽量コンパクトな Web サーバとして有名だった AN HTTPD を microSD に入れて一時的なテスト環境をざっくり構築してみました ただ AN HTTPD はかなり前に開発が終了しちゃってるらしく正規のルートでは配布されていないらしい? まぁとりあえず anhttpd download なるキーワードでぐぐってみたらどうにかなったけどお約束っていうかこの辺は自己責任でお願いします
:
あーあと殆ど大半の方には関係のない話っていうか Windows の BAT ファイルを Linux で作ろうとすると色々と不都合が発生するようです…いや発生しました ごくシンプルにっていうか @echo off とだけ書いた BAT ファイルすら動かない致命的な不都合でありつつ原因に気付くまで結構かかりました orz
まずは改行コードです Windows 系列の改行コードは「CR+LF」なのに対して Linux 系列の多くは「LF」のみとなっていて…この改行コードの違いが問題になります ちなみに Mac OS では「CR」な改行コードを吐くものもあるとか??
Windows のみで開発していれば(ほぼ)気にする必要はないようですが…他の OS 上で書いた場合は改行コードの違いに要注意です
お次は文字コードです これもうっかりやらかしたっていうか Linux 上で何気に UTF-8 で書いた BAT ファイルを Windows に持ってきてテストしたらうまく動きませんでした
この文字コードの問題は改行コード以上に呪わしいっていうか…例えば Windows 標準の「メモ帳」を使用したとしてもバージョンの違いによりデフォルトの文字コードが Shift-JIS (ANSI) だったり UTF-8 だったりするので注意する必要があります
なお我が家の Microsoft Windows [Version 10.0.19042.1348] に付属のメモ帳ではデフォルト文字コードが UTF-8 だったようですが…いつの間にかメモ帳も進化したのか保存時に文字コードを選択できるようになってました ちなみに ANSI ってやつが Shift-JIS っぽいですね
つーかそもそもコマンドプロンプトで使用する文字コードが Shift-JIS (ANSI) だって保証がどこにも無いみたいです 我が家は(たぶん)何も設定していないので Shift-JIS (ANSI) になってましたが…これを他の文字コードに設定することも可能のようです
単に現在の文字コードを確認するだけなら「コマンドプロンプト」のタイトルバーを右クリックして「プロパティ」を参照するといいでしょう
もし他の文字コードに変更したい場合は chcp コマンドを使います 単に chcp とした場合には現在の設定値を表示します 変更したい場合は chcp 番号 という感じで番号を指定します 代表的なものだと「ANSI/OEM 日本語;日本語 (shift-jis) が 932」で「EUC 日本語が 51932」で「Unicode (UTF-8) が 65001」となるようです この辺の コードページ識別子の一覧 が公式(?)にあったんで参考になるかも? ちなみになんか面倒くさそうだったんで実際に変更して試してないんで今後は Shift-JIS (ANSI) で話を進めます(瀧汗
:
さて…その辺の注意事項もろもろを無事にクリアしたところで実際に BAT ファイルを CGI として動かしてみましょう
とりあえず AN HTTPD に CGI の設定をしましょう…っていうか特に何もしなくても動くっぽい?
我が家では拡張子「.bat」に対する「実行プログラム」を「空欄」もしくは「c:\windows\system32\cmd.exe /c」で動作しました テストする環境が無いんで IIS (Internet Information Services) 等では試せてないのですが…おそらくそっちも「.bat」に対する設定で「(空欄)」もしくは「c:\windows\system32\cmd.exe /c」を設定すれば動くのかなーって思ってます この辺はどなたか実際に試して教えて頂きたい感じですね ※ご連絡頂いたんで…本記事の最下部くらいに設定法などを転載してあります
そんな設定が済んだ所で…それじゃ実際に BAT ファイルを作って試してみましょう 以下のバッチファイルを適切な改行コードと文字コードで保存した後に Web サーバのドキュメントルート以下に配置してブラウザからアクセスしてみましょう
----- bat_cgi01.bat -----
@echo off
REM ブラウザに「Content-type:」を出力する(単純なTEXTファイル用)
echo Content-type: text/plain; charset=Shift_JIS
echo.
REM Windows のバージョンを表示 ※空行も表示されている
ver
REM 環境変数に設定されている CPU の種類を表示
echo %PROCESSOR_IDENTIFIER%
echo.
REM 現在日時を date と time コマンドで表示
echo. | date
echo. | time
echo.
REM 必要な所だけ抽出してみる
echo. | date | find "現在の日付"
echo. | time | find "現在の時刻"
echo.
REM 環境変数でも現在日時を取得できるっぽい??
echo %DATE%
echo %TIME%
echo.
REM 日付が設定されている変数から「年月日」を取得してログファイル的なファイル名を作ってみる
echo %DATE:~0,4%%DATE:~5,2%%DATE:~8,2%.log
----------
正しく動作すればこんな感じの内容がブラウザに表示されます
今回は単純なテキストを表示するのに適した「Content-type: text/plain; charset=Shift_JIS」で表示させてみました コマンドプロンプトを別の文字コードに設定している場合はここの「charset=」以降を適当なものに変更する必要があると思います
Linux の Web サーバだと実行属性がどうのこうのとかありますが Windows にはそんなものは無いので「.bat」の拡張子のものであればそれだけで動きます ちなみに大文字/小文字の区別も無いのでブラウザのアドレス欄で「BAT_CGI01.BAT」なんて大文字で指定しても動きます
※少なくことも我が家の AN HTTPD を使用した環境では動きました
※テストした環境が FAT32 ファイルシステムの microSD だったから大文字/小文字の区別がない? これが NTFS ファイルシステム上だと大文字/小文字を区別するの? どうなの??
さて…うまく動きましたか? 無事に動いたのなら次にいってみましょう
----- bat_cgi02.bat -----
@echo off
REM ブラウザに「Content-type:」を出力する(HTML出力用)
echo Content-type: text/html; charset=Shift_JIS
echo.
REM HTML なページとしてのお約束的なヘッダ部
echo ^<!doctype html^>
echo ^<html^>^<head^>^<title^>今日の運勢的な?^</title^>^</head^>^<body^>
echo 今日の運勢は…^<font color=red^>
REM コマンドの実行結果を変数に取り込む
for /f "usebackq delims=" %%A in (`echo. ^| time ^| find "現在の時刻"`) do set RAND=%%A
REM 「%RAND:~-1%」で変数の末尾 1 文字を取り出す
if %RAND:~-1% == 0 echo [%RAND:~-1%] ☆大吉☆
if %RAND:~-1% == 1 echo [%RAND:~-1%] 中吉
if %RAND:~-1% == 2 echo [%RAND:~-1%] 中吉
if %RAND:~-1% == 3 echo [%RAND:~-1%] 吉
if %RAND:~-1% == 4 echo [%RAND:~-1%] 吉
if %RAND:~-1% == 5 echo [%RAND:~-1%] 吉
if %RAND:~-1% == 6 echo [%RAND:~-1%] まぁまぁ
if %RAND:~-1% == 7 echo [%RAND:~-1%] 凶
if %RAND:~-1% == 8 echo [%RAND:~-1%] 凶
if %RAND:~-1% == 9 echo [%RAND:~-1%] 大凶(-_-;)
echo ^</font^>です^<br^>
REM HTML なページとしてのお約束的なフッタ部
echo ^</body^>^</html^>
----------
正しく動作すればこんな感じの内容がブラウザに表示されます 何度かロリードして試してみたってイメージでw
今回はホームページな表示をさせるために「Content-type: text/html; charset=Shift_JIS」を設定してみました これで文字装飾などの「タグ」が使えるようになるのですが…この「タグ」に使用する「<」と「>」はそのまま使うとファイルにリダイレクト/インリダイレクトするための記号として解釈されてうまく動かなくなるのでそれをエスケープするための記号「^」を使用しています コマンドの実行結果を変数に取り込むバッククオート内ではパイプに使用する記号「|」なんかも誤動作するんでエスケープする必要があります
そんなこの CGI はありがちな「おみくじ CGI」です 標準コマンドである time の出力の中から「現在の時刻」が含まれる行を変数に取り込み…その文字列の末尾(この場合 0〜9 になる)を取り出しその値に対して処理を振り分けています
ざっと見た感じ time は 1/100 秒の値まで表示している感じなんで…その値をざっくりした乱数値として使用しています ちなみに大まか作ってから気づいたのですが…バッチファイル内で乱数となる変数 %RANDOM% なんてのもあるようです これは 0~32767 の得られるようですね たぶん動作はこちらのほうが軽いと思います
さてさて…うまく動きましたか? 無事に動いたのなら次にいってみましょう
----- bat_cgi03.bat -----
@echo off
REM ブラウザに「Content-type:」を出力する(PNG画像用)
echo Content-type: image/png
echo.
goto MAIN
REM 時間を判定して画像を表示する用のサブルーチン
REM call :SUB <時間> <ファイル名>
REM <時間> は 0~23 で指定
REM <ファイル名> は表示させたい PNG 画像を指定
:SUB
echo. | time | find " %1:" > NUL
if %errorlevel% == 0 type %2
exit /b
REM サブルーチンを呼んだりするメイン的な処理
:MAIN
call :SUB 0 img_shinya.png
call :SUB 1 img_shinya.png
call :SUB 2 img_shinya.png
call :SUB 3 img_shinya.png
call :SUB 4 img_shinya.png
call :SUB 5 img_asa.png
call :SUB 6 img_asa.png
call :SUB 7 img_asa.png
call :SUB 8 img_asa.png
call :SUB 9 img_asa.png
call :SUB 10 img_hiru.png
call :SUB 11 img_hiru.png
call :SUB 12 img_hiru.png
call :SUB 13 img_hiru.png
call :SUB 14 img_hiru.png
call :SUB 15 img_hiru.png
call :SUB 16 img_hiru.png
call :SUB 17 img_hiru.png
call :SUB 18 img_yoru.png
call :SUB 19 img_yoru.png
call :SUB 20 img_yoru.png
call :SUB 21 img_yoru.png
call :SUB 22 img_yoru.png
call :SUB 23 img_yoru.png
----------
以下の画像を bat_cgi03.bat と同じフォルダ内に用意しておいてください
※画像は いらすとや さんから拝借しました いつもありがとございます
今度は少し変わり種っていうか…正しく動作すればこんな感じの内容がブラウザに表示されます(表示は時間帯によって変化します)
今回は HTTP ヘッダとして「Content-type: image/png」出力しています これは一体何なのかと云うと…ブラウザから見たこの CGI (bat_cgi03.bat) 自体が画像となっている事を意味しています
つまりブラウザから見れば「同じファイル名」なのに「アクセス毎に違う画像」を表示できることなんですね
※なお本来はテキストデータを扱う type コマンドでバイナリデータを標準出力に流しています ざっとテストした感じではうまく動いているっぽいけど…どうなんだろうね? なんか type コマンドの仕様に「EOF」が出現したら動作を終了する的なものがあるらしいんだけど…ねぇ?
※バイナリを扱える copy コマンドで出力先を CON にして試してもみたんだけど…こちらは明確に誤動作していました 確か CON デバイスは改行コードの置換などそんな動作を行うんだっけ? 何も変換とかの動作をしない…シンプルに全てのデータをそのまま標準出力に流してくれるものがあればいいのですが
話を元に戻して… CGI (bat_cgi03.bat) 自体が画像ファイルとして動作することのメリットを考えてみましょう
例えば迷惑系の HTML メールですかね その中の画像として他のサーバにある bat_cgi03.bat を呼ばれたとしましょう するとその他の場所にあるサーバ内ではアクセスログが記録されます それ即ち「メールが読まれたこと」を記録することになります
もちろんそれだけでは大きな脅威にならないかもだけど…そこには面白い使い方があるんですよ
ブラウザから見た bat_cgi03.bat は単なる画像ファイルだけど実際にはプログラム的な動作をしています そしてプログラムの動作には「引数」を与えることができます
先ほどの bat_cgi03.bat の呼び出しに対して bat_cgi03.bat?HOGEHOGE と云った感じで「引数」を与えて呼び出しそれを解釈できるようになります この引数の部分にメールを受信した人を特定する一意のデータ(この場合はHOGEHOGE)を付けておき…その一意のデータと送信したメールアドレスを紐づけておけば「誰がメールを読んだのか」を知ることができます
例として先ほどの bat_cgi03.bat の末尾にログを収集するものを付加してみましょう
----- bat_cgi04.bat -----
@echo off
REM ブラウザに「Content-type:」を出力する(PNG画像用)
echo Content-type: image/png
echo.
goto MAIN
REM 時間を判定して画像を表示する用のサブルーチン
REM call :SUB <時間> <ファイル名>
REM <時間> は 0~23 で指定
REM <ファイル名> は表示させたい PNG 画像を指定
:SUB
echo. | time | find " %1:" > NUL
if %errorlevel% == 0 type %2
exit /b
REM サブルーチンを呼んだりするメイン的な処理
:MAIN
call :SUB 0 img_shinya.png
call :SUB 1 img_shinya.png
call :SUB 2 img_shinya.png
call :SUB 3 img_shinya.png
call :SUB 4 img_shinya.png
call :SUB 5 img_asa.png
call :SUB 6 img_asa.png
call :SUB 7 img_asa.png
call :SUB 8 img_asa.png
call :SUB 9 img_asa.png
call :SUB 10 img_hiru.png
call :SUB 11 img_hiru.png
call :SUB 12 img_hiru.png
call :SUB 13 img_hiru.png
call :SUB 14 img_hiru.png
call :SUB 15 img_hiru.png
call :SUB 16 img_hiru.png
call :SUB 17 img_hiru.png
call :SUB 18 img_yoru.png
call :SUB 19 img_yoru.png
call :SUB 20 img_yoru.png
call :SUB 21 img_yoru.png
call :SUB 22 img_yoru.png
call :SUB 23 img_yoru.png
REM 最後にログを保存する
REM 例)[日 時],[引数],[相手ホスト名(相手IPアドレス)],[ブラウザ名]
echo [%DATE% %TIME%],[%QUERY_STRING%],[%REMOTE_HOST%(%REMOTE_ADDR%)],[%HTTP_USER_AGENT%] >> %date:~0,4%%date:~5,2%%date:~8,2%.log
----------
これで「アクセス日時」「引数」「相手ホスト名(相手IPアドレス)」「ブラウザ名」がログとして記録されるようになります
たったこれだけの仕組みで「単に HTML メールを見ただけ」なのにいろいろ収集できるんで…画像ファイルとして動作する CGI には大きな意義があると思います
※なお最近のメーラは「外部コンテンツを読み込まない」的なオプションがデフォルトでオフになっていると聞きます しかしその意味をよく判らないまま「便利さを求めて」読み込むような設定に変更してる人も多いと聞きます
※まぁもちろん外部コンテンツの全部が全部にそのような動作が仕掛けられている事は無いとは思いますが…そのような危険性があることを覚えておきたいですね
:
なんて感じで長々とお疲れさまでした 久しぶりのバッチファイルっていうか…思い返せば X68000 の Human68k の AUTOEXEC.BAT の頃以来ですかね(汗 なんか今回いろいろ調べてて「サブルーチンなんて使えてたっけ??」とか新しい発見があってよかったです
今回 Web サーバ以外は最初から用意されている(と思われる)標準的なコマンドをどうにか組み合わせて機能を実現してみました それ故にっていうか…久しぶりだったんでいろいろ無駄な部分とかもあるけどその辺はご了笑くださいませ
まぁしょーみ今さらバッチファイルを CGI に使おうなんて奇特な人も居ないだろうで全く問題ないだろうけどww
あと今回テストに使った Web サーバは一時的なものなので WAN に公開していません つーか使いたくないんで年に数回くらいしか電源を入れることがない代物なんでその辺はお察しください… #Windows #CGI
:
今回使用した bat_cgi*.bat と img*.png をひとまとめにした配布セットを用意しました
bat_cgi.zip
なおこれを使用した際に発生したあらゆる利益・不利益について当方は一切の責任を負いませんって定型文でよろしくお願いします
:
※ 追記 ※
今回は AN HTTPD のみでの動作テストだった訳ですが…有志のえらいひとが IIS (Internet Information Services) でのテストをしてくれて問題点と解決法をご連絡頂けたんでここに転載させていただきます
まずは IIS の設定から
「CGI」の設定で「起動ごとに新しいコンソールを使用する」を「True」にする
「ハンドラー マッピング」の設定で「マネージハンドラーの追加」をして
「要求パス」に「*.bat」を
「実行可能ファイル」に「c:\windows\system32\cmd.exe /c %s」を
「名前」には「判りやすそうな適当な名前」を設定します
あとは上の方で示してる BAT ファイルの内容的な問題っていうか…その BAT ファイルが参照/作成するファイルへのパスですかね
どうも IIS の場合だとカレントディレクトリが「BAT ファイルを実行した場所」ではなく「物理パス(ドキュメント ルート)」となるらしく…その辺を考慮してないと誤作動となるようなのでその辺を改良します まぁ基本的には BAT ファイルを実行した場所を示す変数である「%~dp0」を追加します
----- bat_cgi01.bat -----
REM 日付が設定されている変数から「年月日」を取得してログファイル的なファイル名を作ってみる
echo %DATE:~0,4%%DATE:~5,2%%DATE:~8,2%.log
↓
REM 日付が設定されている変数から「年月日」を取得してログファイル的なファイル名を作ってみる
echo %~dp0%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%.log
----------
----- bat_cgi03.bat -----
REM 時間を判定して画像を表示する用のサブルーチン
REM call :SUB <時間> <ファイル名>
REM <時間> は 0~23 で指定
REM <ファイル名> は表示させたい PNG 画像を指定
:SUB
echo. | time | find " %1:" > NUL
if %errorlevel% == 0 type %2
exit /b
↓
REM 時間を判定して画像を表示する用のサブルーチン
REM call :SUB <時間> <ファイル名>
REM <時間> は 0~23 で指定
REM <ファイル名> は表示させたい PNG 画像を指定
:SUB
echo. | time | find " %1:" > NUL
if %errorlevel% == 0 type %~dp0%2
exit /b
----------
----- bat_cgi04.bat -----
上記 bat_cgi03.bat のサブルーチン部と同じく if %errorlevel% == 0 type %~dp0%2 と直して…
REM 最後にログを保存する
REM 例)[日 時],[引数],[相手ホスト名(相手IPアドレス)],[ブラウザ名]
echo [%DATE% %TIME%],[%QUERY_STRING%],[%REMOTE_HOST%(%REMOTE_ADDR%)],[%HTTP_USER_AGENT%] >> %date:~0,4%%date:~5,2%%date:~8,2%.log
↓
REM 最後にログを保存する
REM 例)[日 時],[引数],[相手ホスト名(相手IPアドレス)],[ブラウザ名]
echo [%DATE% %TIME%],[%QUERY_STRING%],[%REMOTE_HOST%(%REMOTE_ADDR%)],[%HTTP_USER_AGENT%] >> %~dp0%date:~0,4%%date:~5,2%%date:~8,2%.log
----------
こんな感じに修正します これで正しく動くようになるようです
わざわざのご連絡ありがとございました!(>_<)w
Tweet ⌚ 2022年1月3日(月) 16:27:56 情報 <11014文字>
Arduino とマトリクスキーボード
以前にどうにかしてたっていうか「Arduino Leonardo (Pro Micro) でマルチメディアキーボードを作ろう!」の後ぐらいにいろいろ調べてたら…なんかマトリクス・キーボードっていうの? 少ないピン数で多くのスイッチを読み取れる方法があるらしい??ってのを見つけて気になってたんで勉強がてらその辺を試してみることにしました
そんなマトリクスってのを日本語的に云うと…碁盤の目みたいなものって感じになるっぽい? それをキーボード的に実装すると…例えば横方向にマイコンから何本かの出力線を這わせておいてそれと何本かの入力線をスイッチを介してあたかも碁盤の目のように配置したもの?ってなるらしい??
そんな感じで Arduino VKLSVAN Pro Micro USB ATmega32U4 (※以下 Arduino と略す)を使って実際に作ってみました ちなみに Pro Micro のピン配列図はこんな感じです つーかブレッドボード(?)が狭くて碁盤の目になってなくてアレですよね(汗
回路図的なものにするとこんな感じです つーか回路図なんて描いたことないんで正しくない図かもしれませんが…まぁ概念的な絵だと思って見てください(滝汗
ここでは Arduino の 6 番ピンと 7 番ピンを出力として使い 14 番ピンと 15 番ピンを入力として使います
そして 6 番ピンのみに信号を出力します その状態で A もしくは B のスイッチが押されればそれぞれ対応した 14 番ピンか 15 番ピンで信号を読み取ることができます それにより A もしくは B のスイッチが押されたかどうかを特定できます
※なんか PULLUP 回路の都合上っていうの?
※普段は HIGH にしてあって…「出力する」としたものを LOW にすることで動作する仕組みです ちょっとややこしいですね(-_-;)
引き続き今度は 7 番ピンにのみ信号を出力します その状態で C もしくは D のスイッチが押されればそれぞれ対応した 14 番ピンか 15 番ピンで信号を読み取ることができます それにより C もしくは D のスイッチが押されたかどうかを特定できます
この一連の動作を繰り返すことにより碁盤の目のように配置されたスイッチを特定していく…そんな構造のキーボードをマトリクスキーボードと呼ぶらしいです
それでは実際にスケッチを書いて動作を確認してみましょう
----------
#include "Keyboard.h"
void setup() {
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
digitalWrite(6, HIGH); // 6 番ピンを HIGH にしておく
digitalWrite(7, HIGH); // 7 番ピンを HIGH にしておく
Serial.begin(9600);
Keyboard.begin();
}
void loop() {
// -------------------------------- //
digitalWrite(6, LOW); // 6 番ピンを LOW にしてスキャン開始
if (digitalRead(14) == LOW) { // 14 番ピンは LOW になっている?
Serial.print("A\n"); // LOW なら A のスイッチが押されている
Keyboard.print("A\n");
}
if (digitalRead(15) == LOW) { // 15 番ピンは LOW になっている?
Serial.print("B\n"); // LOW なら B のスイッチが押されている
Keyboard.print("B\n");
}
digitalWrite(6, HIGH); // 6 番ピンを HIGH にしてスキャン終了
// -------------------------------- //
digitalWrite(7, LOW); // 7 番ピンを LOW にしてスキャン開始
if (digitalRead(14) == LOW) { // 14 番ピンは LOW になっている?
Serial.print("C\n"); // LOW なら C のスイッチが押されている
Keyboard.print("C\n");
}
if (digitalRead(15) == LOW) { // 15 番ピンは LOW になっている?
Serial.print("D\n"); // LOW なら D のスイッチが押されている
Keyboard.print("D\n");
}
digitalWrite(7, HIGH); // 7 番ピンを HIGH にしてスキャン終了
// -------------------------------- //
delay(100); // 適当に待って繰り返し
}
----------
シリアルモニタとテキストエディタを並べて動作テストしてみましょう スイッチに対応した文字が表示されれば成功です ちなみに今回はシリアルモニタとテキストエディタの両方に出力するようにしてますが…初期のテスト段階ではシリアルモニタだけを使ったほうがいいかもですね
:
さてそんな感じでマトリクス・キーボードの大まかな動作を理解できた気になったんで…ぼちぼちマルチメディアキーボード的なやつを作るか!って思いたいトコロなんだけどスイッチ類を買い揃えて配線したりとかとかしょーみ面倒くさいなぁと思ってたんですよね そう思いつつ某Aマゾンを眺めてたら気になるものを見つけました
Ren He 5個セット 16キー 4*4 マトリックス フィルム ボタン キーボード マトリックススイッチ キーパッド メンブレン式 マトリックスキーボード Arduinoに対応
かなり怪しげな感じだけど 5 個入りなのに 600 円でお釣りがきちゃうお値段に釣られてポチっちゃいました 初期不良でいくつか動かなかったとしても十分にお値打ちっポイネ!!
なんか適当なプチプチに包まれた荷姿で届くと思ってたのに…郵便受けをギリ通る厚みのプラケースに入れられて来ましたw やるじゃんww
ちなみにデータシートの類は入ってなかったんで自力で配線を解析する必要があったけど…まぁわりと素直な作りだったんで簡単に判明してよかったです そして Arduino と接続したピン番号とかも
実際に接続してみました まぁ毎度のごとく「接続例」って感じなんで…この辺は各人のお好みでどうにかしてもらえばいいかと思います
それでは早速スケッチを書いて動作を確認してみましょう
----------
const byte KEYOT[] = {4, 5, 6, 7}; // 出力ピンの設定
const byte KEYIN[] = {14, 15, 18, 19}; // 入力ピンの設定
const int WAIT = 100; // ちょっと待たせる
// 関数 keyscan() がキーの状態を読み取った値を入れておく配列
byte SW[sizeof(KEYOT)][sizeof(KEYIN)];
const byte ON = LOW; // LOW と HIGH を…
const byte OF = HIGH; // ON と OF の別名で定義しておく
void setup() {
for (byte i = 0; i < sizeof(KEYOT); i++) {
pinMode(KEYOT[i], OUTPUT); // 出力ピンのモード設定
digitalWrite(KEYOT[i], HIGH); // 出力ピンを HIGH に設定
}
for (byte i = 0; i < sizeof(KEYIN); i++) {
pinMode(KEYIN[i], INPUT_PULLUP); // 入力ピンを PULLUP モードに設定
}
Serial.begin(9600); // シリアル通信を開始
}
void loop() {
keyscan(); // キーの状態を読み取る
// -------------------------------- //
if (SW[0][0] == ON) { Serial.println("1"); }
if (SW[0][1] == ON) { Serial.println("2"); }
if (SW[0][2] == ON) { Serial.println("3"); }
if (SW[0][3] == ON) { Serial.println("A"); }
// -------------------------------- //
if (SW[1][0] == ON) { Serial.println("4"); }
if (SW[1][1] == ON) { Serial.println("5"); }
if (SW[1][2] == ON) { Serial.println("6"); }
if (SW[1][3] == ON) { Serial.println("B"); }
// -------------------------------- //
if (SW[2][0] == ON) { Serial.println("7"); }
if (SW[2][1] == ON) { Serial.println("8"); }
if (SW[2][2] == ON) { Serial.println("9"); }
if (SW[2][3] == ON) { Serial.println("C"); }
// -------------------------------- //
if (SW[3][0] == ON) { Serial.println("*"); }
if (SW[3][1] == ON) { Serial.println("0"); }
if (SW[3][2] == ON) { Serial.println("#"); }
if (SW[3][3] == ON) { Serial.println("D"); }
// -------------------------------- //
delay(WAIT);
}
void keyscan() { // キーの状態を読み取る関数
for (byte i = 0; i < sizeof(KEYOT); i++) {
digitalWrite(KEYOT[i], LOW); // 特定の出力ピンを LOW にする
for (byte j = 0; j < sizeof(KEYIN); j++) {
if (digitalRead(KEYIN[j]) == ON) { // 入力ピンの状態を読む
SW[i][j] = ON; // キーが押されている
} else {
SW[i][j] = OF; // キーは離されている
}
}
digitalWrite(KEYOT[i], HIGH); // LOW にした出力ピンを HIGH に戻す
}
}
----------
冒頭にある
const byte KEYOT[] = {4, 5, 6, 7}; // 出力ピンの設定
const byte KEYIN[] = {14, 15, 18, 19}; // 入力ピンの設定
const int WAIT = 100; // ちょっと待たせる
この辺と…あとは loop() 内を書き換えるだけでいいように書いてみました 使用するピン数が増減しても概ね追従できると思います
あーあと setup() で使用したい機能を開始させるような辺りの書き換えも必要ですかね
それと…話がややこしくなるとアレなんで今回はシリアル通信のみで動作チェックしています
キーの状態を読み取る keyscan() 関数ってのがありますが…グローバル変数を使っているので引数も返り値もありません
読み取った値は SW[][] って二次元配列にセットしています
あと PULLUP の特性っていうか普段が HIGH となっていて…スイッチが押されると LOW になるって辺りが何となく直感的にイメージしにくいように思えたんで
const byte ON = LOW; // LOW と HIGH を…
const byte OF = HIGH; // ON と OF の別名で定義しておく
って感じでスイッチが押されてる ON ってのとスイッチが離されてる OF って感じの別名で定義してあります
:
そして loop() 内で keyscan() を呼んでキーの状態を読み取っておいて…あとは個々の SW[][] の状態に応じてお好みの文字(列)を出力させるなり何なりをすればいいでしょう
将来的にっていうかもし「1」が押されてたらキーボードとして文字を出力して「#」が押されてたらマウスの右クリックを…って感じで様々な処理を行えるよう少しばかり長ったらしく書いてあります
この辺の「やること」の種類が決まりきっているのであれば
void loop() {
keyscan();
// -------------------------------- //
const char* str[] = {
"1\n", "2\n", "3\n", "A\n",
"4\n", "5\n", "6\n", "B\n",
"7\n", "8\n", "9\n", "C\n",
"*\n", "0\n", "#\n", "D\n",
};
for (byte i = 0; i < sizeof(KEYOT); i++) {
for (byte j = 0; j < sizeof(KEYIN); j++) {
if (SW[i][j] == ON) {
Serial.print(str[sizeof(KEYOT) * i + j]);
}
}
}
// -------------------------------- //
delay(WAIT);
}
こんなふうに for() で回すように書けばもうちょっとスッキリするかもしれんですね これはまぁ「やること」の内容によっていろいろ書き方があるよねって事で参考までに
:
あーあと後半の中華クソ安 16 キーボードでの実験ではテキストエディタへの文字出力を行っていないんですが…これを実際に行うと不具合が出るものがあります
キーボード上の「*」 なんですけどね シリアルモニタではちゃんと「*」が出力されているのに…テキストエディタ上では「(」になってしまいます
※別のスケッチでテストした際の画像です
これは #include "Keyboard.h" した際のキーボードレイアウトが KeyboardLayout_en_US になってて…まぁいわゆる US キーボードってやつですかね これが日本で一般的に使われている JIS キーボードとレイアウト(キーの配置)が違うから起こる現象のようです
アルファベットと数字に関しては問題ないのですが…記号はその多くが US と JIS とで配列が違うんで問題になります
先ほどの「*」を例にすると… US キーボードでは「*」が「8」のキーに割り当てられています
そのキーコードを JIS キーボードに当てはめると「8」のキーにあるのは「(」って事になるので正しく表示されないのです
困っちゃいますよね…そこそこ数が出回ってる(と思われる) JIS キーボードなんだで Keyboard.begin(KeyboardLayout_ja_JP); くらい通るようにしといてほしいのに!って思うんだけどそうはいきません(-_-;)
どうしたもんかなーって思いつつ調べてたら…何やら Keyboard.h を複製した後に JIS キーボード向けに書き換える手法を見つけました→ Arduino Leonardoで\記号を打つ:メガギガテラス:So-netブログ
実際に試してみたところ…これでバッチリ動作しました! まぁあくまで自己責任で!って感じになるんだけど…自作キーボードでいろいろしたい!って場合にはとても有用な情報だと思うんで参考にしてみてください
:
キーボード自作って話になると耳にするマトリクスキーボードってやつですね 今までは何となく漠然と聞き流していたんですが…今回はその辺に踏み込んでその原理をほんのり理解できた気になれてよかったです マイコン側のピン数を減らしつつ…より多くのキーを読み取るテクニックは今後も色々と使えそうなんで今後もより掘り下げた勉強をしていきたいなって思いました
あと…マトリクスキーボードの構造的な問題っていうか特定条件の複数キーの同時押しをした際に正常に動きません 今回の中華クソ安 16 キーボードを使った実験を例にとると…縦軸に配されたキー(例えば「1と4」とか「AとBとC」とか)を同時押しすると「どれも押されてない」って判定されます まぁなんか読みたいキーとは別のスイッチを介して HIGH が逆流してくる(?)ことにより誤動作するらしく…そんな逆流を防ぐためにダイオードを入れるって事らしいんですが今回は既成品でその辺をどうにもできかねる感じなんでそのままにしてあります(汗
まぁその辺を踏まえた上で…この中華クソ安 16 キーボードでマルチメディアキーボード的なものを作るとしますかね 程々に硬い板に貼り付けて配線の取りまとめをすればいいだけって感じの見栄えよりお手軽さ!って感じのアレですが(瀧汗
そんなこなんで今回も長々とお疲れさまでした! 安いのに遊び甲斐のある Arduino をもっと色々と使い倒していきタイネ!(>_<)w #Arduino