sophiaの書

なんか書く

赤ちゃんみたいにかわいく哺乳瓶を吸う方法

おジャ魔女どれみのコラボカフェに行ってきた。そこでハナちゃんの哺乳瓶ミルクティーを注文した。

哺乳瓶の図

哺乳瓶の図

筆者が物心ついたころにはすでに哺乳瓶を卒業していたため、哺乳瓶の吸い方を完全に忘れてしまっていた。そのため最初は吸い方が分からず困り果てた。哺乳瓶を吸おうとして色々と試しながら考えたことをここに書き記したい。

哺乳瓶の特徴

ここでは一般的な哺乳瓶について論じる。

哺乳瓶の最大の特徴は瓶にはめてあるゴム製の突起である。この突起は中空になっており、柔らかくて変形しやすい。先端には小さな穴が開いていて、この穴から中に入っている飲み物を吸う。哺乳瓶を逆さにしただけでは中の飲み物が出てこないが、ゴム製の突起をつまむように変形させて先端の穴を広げると中の飲み物が少量だけ出てくる。速く飲みたい場合は吸引すればよい。しかし、吸いすぎると哺乳瓶内の圧力が下がってゴム製の突起がつぶれてしまい、飲み物の流路が狭くなってしまう。吸い過ぎには注意しなければならない。他にも、瓶を握力で握りつぶしたり、瓶の中身を手で温めて膨張させたりすれば飲む速さを速められる可能性があるが、現実的ではない。瓶は固くて変形しにくく、せっかくの冷たい飲み物がぬるくなってしまうためである。哺乳瓶を逆さにしないと中の飲み物が出てこないので、必ず逆さにしなければならない。逆さにした哺乳瓶を飲むためには顔を上に向ける必要がある。

逆さにしてもそのままでは中の飲み物が出てこない点、一度に少量しか出てこない点、強い吸引力がなくてもゴム製の突起を変形させれば中の飲みものが出てくる点は赤ちゃんにとってありがたい特徴なのであろう。

かわいく哺乳瓶を吸うためのコツ

ここでは飲み方について気づいたことを述べる。

特に工夫をせずに大人が哺乳瓶を吸うと、あたかもビールを一気飲みしているかのように見えてしまう。

 

哺乳瓶一気飲み

哺乳瓶一気飲み


哺乳瓶を吸うときも、ビールを一気飲みするときも、上を向きながら飲むからである。つまり大人が哺乳瓶を吸ったからといって必ずしも赤ちゃんらしさが生じるわけではない。

せっかく哺乳瓶を吸うからには赤ちゃんみたいにかわいらしく吸いたい。その願望をかなえるためには3つコツがある。

  1. 目を閉じる
  2. 哺乳瓶をわしづかみしない
  3. 口をモゴモゴさせる
目を閉じる

目を開けながら哺乳瓶を吸う我が友の姿を見て、筆者は恐怖を感じた。そこで、試しに目を閉じてもらい、その状態で哺乳瓶を吸ってもらうと、我が友が少しだけ赤ちゃんに近づいたような気がした。

目を閉じろ

目を閉じろ

目を開けながら飲む方法と目を閉じながら飲む方法の両方を試した結果、目を閉じた方が絶対によいと分かった。目の持つ威力はあまりにも強すぎるため、目を閉じて眼力を遮断しなければならない。目を閉じるだけで、哺乳瓶をくわえた大人の顔が和やかになる。

哺乳瓶をわしづかみしない

最初筆者たちは普段コップを持つときと同じように片手で哺乳瓶をつかみ、その持ち方のまま哺乳瓶を吸った。しかし、その姿はビールを一気飲みする姿とよく似てしまっていた。哺乳瓶の持ち方も工夫しなければ赤ちゃんらしくならないと気づいた。

赤ちゃんみたいになるためには、まず両手で哺乳瓶を持たなければならない。両手で哺乳瓶を持つときは肘を張らないようにしなければならない。加えて、指をそろえて可能な限り手を小さくしなければならない。

哺乳瓶の持ち方

哺乳瓶の持ち方

ただし、手をグーの形にしてしまうと、わざとらしくなって違和感が半端ないので避けなければならない。

本来赤ちゃんは哺乳瓶を自分で持たず、大人に持ってもらう。しかし、大人が哺乳瓶を吸うときは自分で持たざるをえない。可能な限り手の存在感を小さくしなければならない。

口をモゴモゴさせる

一度に少量しか中の飲み物が出てこないからといって、あせって吸引してはならない。哺乳瓶を吸引するためにはそれなりの力を必要とするので疲れてしまう。唇でゴム製の突起を変形させる動作を周期的に繰り返すだけで我慢しなければならない。この周期的な口元の動きが赤ちゃんらしさを醸し出す。

自分は赤ちゃんであると思い込め

自分は赤ちゃんであると思い込め

おジャ魔女どれみカフェ

もちろん哺乳瓶目当てでおジャ魔女どれみカフェに行ったわけであるが、他の食べ物もかわいらしく、良い思い出になった。おジャ魔女どれみのような対象年齢が低いアニメは、ところどころにギャグが散りばめられているため、見ていて単純に面白い。しかも絵がかわいらしいため、見ていると脳がほぐれる気がする。

今回の体験はとても楽しかったので大満足である。

わせ弁日記

早稲田大学の本キャン(早稲田キャンパス)のすぐ近くに「わせだの弁当」という弁当屋がある。通称「わせ弁」。安くて多いのが特徴の「わせ飯」のひとつである。あまりのコスパの高さにより、あの唐揚げは高田馬場の鳩肉なのではないかとささやかれるほどである。わせ弁には頻繁にお世話になっているのだが、いつも同じメニューばかりを注文しているので、全てのメニューを制覇しようと決心した。その記録をここに記す。

茄子カラ弁当

茄子カラ弁当 研究室の卓上にて撮影

茄子カラ弁当 研究室の卓上にて撮影

★★★★☆

ご飯の上に唐揚げ、茄子の炒め物、漬物が乗っていて、甘い醤油味?のたれがかかっている。良い。

今回は普通盛(350円)を購入した。

筆者はこの弁当が一番のお気に入りであるため、8割くらいの割合で茄子カラ弁当を注文している。

肉だけでなく野菜も入っていて健康的!!というのが我々研究室のメンバーの見解である。

この弁当を買った帰り道に裏道を見つけた。研究室とわせ弁の間の行き来がさらにしやすくなり、弁当進捗がはかどりそうである。

ギョーカラ弁当

ギョーカラ弁当 茶色い

ギョーカラ弁当 茶色い

★★★★☆

ご飯、揚げ餃子、きゃべつの千切り、唐揚げ、きんぴらごぼう(写真には写っていないが)、漬物、醤油、からしが入っている。

今回は普通盛(350円)を購入した。

全体的に茶色くて健康的である。

揚げ餃子を食べたのは小中学校の給食以来であるため懐かしさを感じる。

シューカラ弁当

シューカラ弁当 大きさ比較のために割りばしを置いてみた

シューカラ弁当 大きさ比較のために割りばしを置いてみた

★★★★☆

ご飯、千切りキャベツ、しゅーまい、きんぴらこぼう、唐揚げ、漬物、醤油、からしが入っている。

今回は普通盛(350円)を購入した。

この漬物はしば漬けという漬物であることを知った。

以上3種類がわせ弁のスリートップ(メニューの一番上に書いてある)であり、筆者も頻繁に食べるメニューである。いつも胃袋を満たしてもらっているので感謝しなければならない。

ちなみに筆者はおてもとに入っているつまようじを使ったことはない。

早稲田弁当

早稲田弁当 野菜が多め

早稲田弁当 野菜が多め

★★★★☆

ご飯、唐揚げ、オムレツ、揚げ餃子、茄子の炒め物、しば漬け、ポテトサラダ、千切りキャベツ、串カツ(肉と玉ねぎ)、醤油、ソースが入っている。

今回は普通盛(480円)を購入した。

惣菜の種類の多さのため、まるでわせ弁の総集編といった感じである。

茄子カラ、ギョーカラ、シューカラよりも値段が高く、野菜が多めである。どうやら健康のためにはそれなりの出費を覚悟しなければならないらしい。

大して運動してないのにカロリーの高そうなものばかり食べているため太りそうであるが、まだ大丈夫と自分に言い聞かせる。わせ弁のために運動を始めようかと思う。

研究室からわせ弁の店に向かう途中に別の弁当屋さんを2つも見つけた。わせ弁を食べ終わったらそっちの店の弁当も食べてみたい。

ドカ弁

ドカ弁 大きそう

ドカ弁 大きそう

★★★★☆

ご飯、のり、おかか、しば漬、きんぴらごぼう、メンチカツ、コロッケ、オムレツ、唐揚げ、ウィンナー、醤油、ソースが入っている。豪華なのり弁といった感じである。

今回は普通盛(450円)を購入した。

この透明なふたの容器は茄子カラ弁当の大盛りを注文したときに出てくるもの同じである。名前がドカだから大きめの容器に入っているのだろうか。

早稲田弁当との最大の違いは茄子の有無であろう。

ここで赤いウィンナーについて物申したい。赤いウィンナーが入っていると視覚的な華やかさが出るが、健康さは感じにくいのではなかろうか。特にこのウィンナーは赤い服を着ているかのようである(食べれば分かる)。赤かろうがそうでなかろうが、味はウィンナーである。赤いウィンナーの是非については検討の余地がある。

「わせ弁 歴史」で検索したら面白いことが分かった。わせ弁はもともとほっかほっか亭のチェーン店だったらしい。その他にも色々と面白いことが書いてあった。詳細は省くが、昔からこの近辺の人たちからよく利用されていたようだ。

さらに調べてみると早稲田大学わせ弁研究会なるTwitterアカウントの存在を確認した。わせ弁を学術的に研究する必要性を他の人たちも気づいているようだ。ツイートを見る限りではその研究会のメンバーは文学部の学生が中心らしい。彼らにはわせ弁を文学的に研究してもらうことにして、筆者の研究室ではわせ弁を工学的に研究するつもりである。

そういえばこのブログを書いているうちに筆者の食レポがうまくなっていくことを期待したい。

シーフードフライ弁当

シーフードフライ弁当 揚げ物が4種類もある

シーフードフライ弁当 揚げ物が4種類もある

★★★★☆

ご飯、おかか、のり、唐揚げ、しば漬け、千切りキャベツ、カニクリームコロッケ、エビフライ、白身魚のフライ、レモン!、ソース、タルタルソースが入っている。揚げ物が4種類もあり、存在感がある。

今回は普通盛(500円)を購入した。

並ばずに済むように12時前にわせ弁を訪れたのだが、すでに列ができていた。あまり並ばないために最適な時刻はいつ頃なのだろうか。それを知るために、まずは客数の増減をモデル化したい。客数の増え方を一次遅れ系に近似できると仮定したとき、開店時刻から立ち上がりまでの遅れ時間と時定数を知る必要がある。さらに、客数が減り始める時刻と時定数も知る必要がある。ここまで考えたものの、各種パラメータを丸一日かけて計測するほどの体力は筆者にはない。

一次遅れ系と仮定したときの客数分布図 手描きは格好悪いのでいつか差し替えたい

一次遅れ系と仮定したときの客数分布図 手描きは格好悪いのでいつか差し替えたい

いつのまにか揚げ物のしもべになっているので、揚げ物がおいしく感じられる。もちろんこの世にはもっとおいしい揚げ物が存在するが、これはこれでいい。カニクリームコロッケが謎であったけれど。

今回は会計時にくじをもらった。結果ははずれであった。

はずれくじ またチャレンジしたい

はずれくじ またチャレンジしたい

どういう条件のときにこのくじをもらえるのか、再現性はあるのか等について筆者は関心を持った。

レモンもおいしくいただいた。果肉はすっぱく、皮は少しだけ苦かった。

わせ弁を工学的に研究すると言ったけれど、その手法についてはまだ何も決まっていない。何の準備もしていない。この日記に書くべきネタが尽きてしまったときの切り札として使うかもしれない。

そろそろ気づいているかもしれないが、筆者には味がわからぬ。毎回弁当を五つ星で評価しているが適当である。いつも気まぐれに星をつけている。

ステーキ弁当

ステーキ弁当 揚げ物は入っていない

ステーキ弁当 揚げ物は入っていない

★★★☆☆

ご飯、ポテトサラダ、しば漬け、千切りキャベツ、ステーキ、オレンジ!が入っている。揚げ物が入っていないわせ弁を食べるのはこれが初めてである。注文する時に店員のおっちゃんから「10分くらいかかっちゃいますよ」と言われたが気にせず注文した。ステーキを焼くのに10分くらいかかるのであろう。

今回は普通盛(580円)を購入した。

前回もらったくじは今回もらえなかった。500円以上の弁当を購入したときにもらえるのかと予想を立てていたが、どうやら違ったようだ。どういう条件のときにくじをもらえるのかもう一度考え直す必要がある。

前回は客数と時刻の関係を一次遅れ系で近似できると仮定したが、縦軸が客数で横軸が時刻の正規分布に従うと仮定したほうがより自然である。ここでは昼時に限定して話を進めよう。平均μが12:30で標準偏差σが30分間とすると、12:00~13:00の1シグマ区間に約68%の客が来店し、11:30~13:30の2シグマ区間に約95%の客が来店していると計算できる。本当かどうかは知らない。

 f(x)=\dfrac{1}{\sqrt{2\pi}\sigma}\exp\left(-\dfrac{(x-\mu)^2}{2\sigma^2}\right)\tag{1}

x:時刻

f(x):時刻による客数の変化

\sigma:標準偏差 30分間

\mu:平均値 時間あたりの客数が最大となる時刻 12時30分

正規分布と仮定したときの来客数の時間分布図 よりよりモデルと考えられる

正規分布と仮定したときの来客数の時間分布図 よりよりモデルと考えられる

Foodieという食べ物をおいしそうに撮影するためのアプリを使ってみた。普通のカメラで撮った上のステーキ弁当の写真と見比べてみよう。

ステーキ弁当 Foodieで撮影

ステーキ弁当 Foodieで撮影

しば漬けが魅力的に写っている。

ちなみに普段筆者はよっぽど値段が高くやわらかい肉でない限り、ステーキではなくハンバーグを食べることにしている。

和風幕の内弁当

和風幕の内弁当 入れ物が大きい

和風幕の内弁当 入れ物が大きい

★★★★★

ご飯、ごま、梅干し、インゲン豆の天ぷら、たくあん、しば漬け、唐揚げ、シャケ、ゆで卵、きんぴらごぼう、甘い煮物、えびコロッケ、醤油が入っている。黄色と赤の漬物が華やかさを添えている。えびコロッケにはえびが入っていた。

今回は普通盛(530円)を購入した。

今までわせ弁を「工学的に研究する」と言ってきたが、結果が分かりきっていることに対しては研究という言葉を用いないため、これからは「工学的に考察する」という言葉を用いることにする。

さて、今回はわせ弁の名が早稲田大学の学生に広まる様子について考察していこう。わせ弁のことを知らない学生がわせ弁のことを知るためには何らかの障壁を乗り越えなければならない。例えばわせ弁について話している学生に偶然会うことなどである。人数が多い集団内でわせ弁について知らない学生があるきっかけによってわせ弁について知るようになる様子は、活性化状態を経て変化を起こす化学反応のようである。よって化学反応の反応速度式と同じような形の式を立ててみて、わせ弁情報伝播について解析することにする。

今回解析対象とする母集団を選ぶ際にいくつか仮定をする。早稲田大学に入学する人数と卒業する人数は同数である。全員が4年間で卒業する。わせ弁情報の伝達は各学年の間だけで行われる。以上のように仮定すると、母集団を各学年とし、解析期間は4年間とすることができる。ここで流体力学でよく使われる考え方である、流れとともに移動する検査体積を使用する。つまり、学生が学年を1つ上がるのと同時に、注目する学年を1つ上げるのである。すると4年間同じ学生たちに注目し続けることができる。補足しておくと、大学全体で見た時に、人数の多さのために、この仮定に反する事例は無視できるほど少ないと考えられる。ただし、大学院に関しては考慮しないことにする。

nをわせ弁のことを知らない学生の人数、Nをある学年の人数(N\gt\gt1)tを時間、k, \alphaを正の定数とすると次のように立式できる。ただし母集団の中でわせ弁のことを知らない学生の割合\frac{n}{N}を実数とみなした。

-\dfrac{d}{dt}\dfrac{n}{N}=k\left(\dfrac{n}{N}\right)^{\alpha}\tag{2}

左辺はわせ弁のことを知らない学生の割合が減少する速さであり、右辺の括弧の中身はわせ弁のことを知らない学生の割合である。

簡単のために\frac{n}{N}を実数xで置き換え、\alpha=1とすると

-\dfrac{dx}{dt}=kx\tag{2}

時間t=0のとき人数n=N-n_0とすると(つまり最初はn_0人だけわせ弁のことを知っている)0 \leq n \leq N-n_0だから0 \leq x \leq 1-\frac{n_0}{N}である。この変数分離形の微分方程式を初期条件t=0のときx=1-\frac{n_0}{N}の下で解く。まずx\neq 0のとき

-\dfrac{dx}{x}=kdt\tag{3}

C積分定数とすると

\log |x|=-kt+C\tag{4}

x=Ce^{-kt}\tag{5}

x=0のときはC=0とすればよいから式(5)が微分方程式の一般解である。

初期条件より

C=1-\dfrac{n_0}{N}\tag{6}

であるから

x=\left(1-\dfrac{n_0}{N}\right)e^{-kt}\tag{7}

x=\frac{n}{N}であったから

n=(N-n_0)e^{-kt}\tag{8}

よってわせ弁のことを知らない学生は指数関数的に減少することがわかる。

情報伝播速度は開始直後は遅く、あるときを境に急激に速くなり、最終的には飽和して速度0に収束すると筆者は経験的に予想していた。今回の解析結果は情報伝播開始直後には適用できないが、ある程度時間が経って情報伝達速度が速くなったあとの挙動には適用できると推測できる。今回は\alpha=1としたが、\alphaの値は実験により求めるべきものである。よって、今回の\alphaの値が妥当かどうか調べる必要がある。

スタミナ弁当

スタミナ弁当 Foodieで写真を撮るのはやめた

スタミナ弁当 Foodieで写真を撮るのはやめた

★★★★☆

ご飯、肉団子、牛肉と野菜の炒め物、唐揚げ、コロッケ、ソース、キャベツの千切り、しば漬けが入っている。そろそろ唐揚げに飽きてきたので、星5つにはしなかった。牛肉は固めなのであごを鍛えることができる。味に関しては個人的には割と高評価なのだが、この評価はわせ弁のメニュー同士の比較によって行われており、他の食べ物と比較しているわけではないので注意。なぜならば最近筆者はわせ弁ばかりを食べているからである。世の中には舌の肥えた貴族(のような人たち)がいて辛口評価をしがちだが、筆者にはうまいとまずいの2通りしか分からないため正確な評価などできようはずがなく、うまいとだけ感じるのである。

今回は普通盛(500円)を購入した。

画像加工アプリを使って弁当の写真を撮るとおいしそうに写せるのだが、なんだか嘘くさくて腹が立つ。よって今後はFoodieを使わないことにする。他の画像加工アプリは遊びで使ってみるかもしれないが。

いつか「食道を流れる唐揚げ流体の定常流れ」や「静止している唐揚げに水平方法に箸で撃力を加えた後の挙動」、「わせ弁を買ってから研究室に到着するまでにかかる数分間に弁当の温度が何度くらい低下するか」、「弁当容器のたわみ」について扱ってみたいが、ブログを書くことに疲れてしまったのでそのような負担の大きい題材を扱うことは当分ない。楽がしたいのである。スタミナ弁当を食べたくらいではブログ用のスタミナは付かない。

スポーツ弁当

スポーツ弁当 キャベツが2箇所

スポーツ弁当 キャベツが2箇所

★★★★☆

ご飯、ごま、梅干し、キャベツの千切り、メンチカツ、ソース、しば漬け、たくあん、焼肉、唐揚げが入っている。嬉しいことにキャベツの千切りが写真の左上と右下の2箇所に入っており、野菜が多めでスポーツマンの体調に対する配慮がなされている。茶色の占める割合が比較的小さいため視覚的においしそうである。そして弁当容器が横長で体積が大きめである。

今回は普通盛(500円)を購入した。

よいスポーツをするためには食べ物に気を配らなければならないので、スポーツ弁当のカロリーを計算することにする。先行事例として広告研究会による次のサイト[1]がある。

カロリー算出のためにカロリーSlismというサイト[2]を使用した。重さを量るためにデジタルスケールを使用した。(DS2005 株式会社アスカ 最大計量2kg 最小計量1g)

調査結果を以下に示す。

  • メンチカツ78gが1個で約150kcal
  • 唐揚げ3個が108gで314kcal
  • ご飯247gで415kcal
  • 梅干し1gで約1kcal
  • ソース5gで6kcal
  • キャベツ42gで10kcal
  • 沢庵14gで4kcal
  • しば漬け25gで8kcal
  • 焼肉99g(カロリー計算では牛肉のそぼろ99gで代用)で213kcal

合計すると1121kcalであった。

参考までに日本医師会のサイト[3]を参照して18~29歳の男女が1日に必要とするカロリーを示す。ただし我々研究室のメンバーは椅子に座って1日を過ごすため、身体活動レベルはレベル1(生活の大部分が座位で、静的な活動が中心の場合)とする。計算の結果、男性は2280kcal/日で女性は1665kcal/日である。

したがって運動をしない男性にとっては1121/2280=約49%、運動をしない女性にとっては1121/1665=約67%のカロリーをスポーツ弁当から摂取できる。1食だけで1日に必要なカロリーのうち大体5割くらいを摂取できるため、スポーツ弁当は高カロリーといえる。

カロリー計算をしている間にスポーツ弁当はすっかり冷めてしまった。しかし腹ペコだったためにおいしくいただいた。完食である。何かスポーツがやりたくなった。

[1]http://waseda-ad.com/wasead/foods/wasfes-waseben/#i-4

[2]https://calorie.slism.jp/

[3]https://www.med.or.jp/forest/health/eat/01.html

唐揚焼肉弁当

唐揚焼肉弁当 割りばしをうまく割れなかった

唐揚焼肉弁当 割りばしをうまく割れなかった

★★★★☆

ご飯、オムレツ、しば漬け、唐揚げ、焼肉、キャベツの千切りが入っている。

今回は普通盛(500円)を購入した。

そろそろ食レポに力を入れ始めたいので、筆者の食レポを披露したい。

「うん!おいしい。唐揚げと焼肉の組み合わせが斬新ですね。唐揚げ好きにはたまらないです。焼肉は固めの肉が好みな人にお薦めです。オムレツはやわらかくてふわふわですよ。しば漬けがよいアクセントになっています。ご飯はほかほかで噛むと甘みが出ます。そして影は薄いですが重要なのはキャベツです。キャベツによって弁当にメリハリが出ます。」

適当に形容詞を並べるだけでそれなりの食レポはできそうである。

少し調べてみると、客観性があって何がお薦めでどんな人が好きそうかをきちんと述べている食レポが良い食レポらしい。主観的においしいと言っても他の人の参考にならないからだ。

筆者の食レポ能力の伸びに期待したい。

ここで焼肉思い出話をしたい。以前友達と焼肉屋に行ってひたすら肉を食っている最中に筆者は肉に飽きてきた。そろそろ野菜も食べたいと友達に言ったら、焼肉屋は肉を食べる場所であり野菜が食べたければ焼き野菜屋に行くべきとその友達は言った。この場を借りてその友達に異議あり!と言いたい。焼肉屋で肉のみを食べる人は、研究室で研究しかしない人に相当する。1日のほとんどを研究して過ごしている人であっても、ときには体を動かして血の巡りを良くし、食事に気を配って脳に栄養と酸素を十分に供給しなければならない。適度な気分転換は研究活動を活気づけるのである。焼肉屋の肉問題についても全く同様である。少しの野菜があるおかげでますます肉をおいしく食べられる。つまりメリハリが大事と言いたいのである。

ホッケの塩焼弁当

ホッケの塩焼弁当 この容器だと高級感がある

ホッケの塩焼弁当 この容器だと高級感がある

★★★☆☆

ご飯、ごま、梅干し、たくあん、しば漬け、ひじき、きんぴらごぼう大根おろし、ホッケ、醤油が入っている。わせ弁ではない普通の弁当のにおいがする。ホッケは油っ気が少なかった。薄味なため、醤油と大根おろしの助けを借りた。唐揚げはさくさくしていて大変良かった。唐揚げは弁当容器の個室の1つに隔離されており、他のおかずから水分を吸い取らなかったためだと思われる。

今回は普通盛(500円)を購入した。

近年Instagramに投稿するためだけに食べ物を注文し、写真だけ撮って食べずに立ち去る人が少なからずおり、たびたび問題になっている。

Instagram使用者がこの問題を認識し、相互監視により自然にInstagramのための食わず逃げがなくなるのがよい。

筆者はちゃんと食べていることを示すために食後の写真を撮った。

完食である

完食である

Foodieのおかげで食後の様子を美しく撮影できた。今まで見た写真の中で一番インスタばえしそうである。

メンチ焼肉弁当

メンチ焼肉弁当 唐揚げがない

メンチ焼肉弁当 唐揚げがない

★★★★☆

ご飯、メンチカツ、ソース、焼肉、キャベツの千切り、オムレツ、しば漬けが入っている。焼肉を食べた感想は以前述べた通りである。

今回は普通盛(500円)を注文した。

研究室の先輩が別の弁当を食べているときに割り箸が折れてしまったので、そのことについて考察したい。割り箸が折れる直前の状況は次のようであった。割り箸で挟んでいるのは唐揚げである。

事故直前の絵

事故直前の絵


抽象化すると次のようになる。

割り箸と荷重

割り箸と荷重

下の割り箸には上の割り箸からの荷重に加えて唐揚げの自重も加わるため、下の割り箸にはより大きな荷重がかかる。そのせいか、折れたのは下の割り箸であった。実際には他の外力が下の割り箸にかかったからであると考えられるが、その外力も唐揚げからの接触力であるとみなして議論をすすめる。ただし、ここでは重力の影響は無視できるほど小さいとする。さらに、実験の結果、下の割り箸が折れるときには中指からの荷重がかかっていなかったと考えられるため、次の図のように単純化できる。

割り箸のはり曲げ問題化

割り箸のはり曲げ問題化

力のつり合いより

P_{唐揚}+P_{人差し指}=P_{親指}\tag{9}

モーメントのつり合いより

P_{親指}l_{1}=P_{人差し指}(l_{1}+l_{2})\tag{10}

よって

P_{親指}=\dfrac{l_{1}+l_{2}}{l_{2}}P_{唐揚}\tag{11}

P_{人差し指}=\dfrac{l_{1}}{l_{2}}P_{唐揚}\tag{12}

左端の図心を原点とし右方向にx軸、上方向にy軸をとる。

0 \leq x \lt l_{1}のとき位置xの断面における曲げモーメントM(x)

M(x)=P_{唐揚}x\tag{13}

l_{1} \leq x \leq l_{1}+l_{2}のとき

M(x)=P_{唐揚}x-P_{親指}(x-l_{1})\tag{14}

よってx=l_{1}つまり親指の位置でモーメントが最大となる。割り箸が等方性で脆性破壊を起こすまでフックの法則に従うとする。さらに一様断面のはりとみなせるとする。そしてせん断力による影響は小さいとする。結論だけ言うと親指の位置の表面で応力が最大となる。はりの高さと断面二次モーメントをそれぞれh, Iとすると

\sigma_{max}=\dfrac{M(l_{1})}{I}\dfrac{h}{2}=\dfrac{P_{唐揚}l_{1}h}{2I}\tag{15}

割り箸は脆性材料であり、最大主応力説によって破壊するものとすると、この最大応力\sigma_{max}が許容最大応力に達したとき破壊を起こす。

先輩は握力が強すぎて、割り箸が壊れるほどの荷重P_{唐揚}をかけてしまったのである。

中華弁当

中華弁当 チリソースは赤い。赤いと中華。

中華弁当 チリソースは赤い。赤いと中華。

★★★★☆

ご飯、ごま、梅干し、キャベツの千切り、揚げ餃子、春巻き、たくあん、しば漬け、唐揚げ、チリソース、醤油、からし、しゅうまい、肉団子、ザーサイが入っている。チリソースの赤さのために中華っぽさが醸し出されている。それから甘くて酸味がある。個人的にはもっと辛さが欲しい。全体として、おかずの種類が多くてありがたい。

今回は普通盛(480円)を注文した。

これまでわせ弁日記に莫大な時間を注いできたが、本業の研究をはじめとする諸々がおろそかになっているため、しばらく差し控えさせていただく。具体的には、わせ弁日記を書くための時間を30分間に制限することにする。

揚げ餃子を食べるとのどが渇く。近くのスーパーで買ったジャスミン茶をがぶ飲みしてのどの渇きを癒した。

生姜焼弁当

生姜焼弁当 割り箸をきれいに割れた

生姜焼弁当 割り箸をきれいに割れた

★★★★★

ご飯、豚肉の生姜焼き、キャベツの千切り、しば漬けが入っている。生姜焼きの汁がひたひたである。つまり「つゆだく」。焼肉と違って生姜焼きは咀嚼しやすい。結局、肉は細切れにすべきである。

今回は普通盛(480円)を購入した。

参考文献[4]の方法に従って割り箸を割ったらきれいに割れた。

[4]http://www.nhk.or.jp/suiensaa-blog/koremade/213928.html

そういえば、しば漬けは茄子の漬物らしい。よって、今回は茄子とキャベツ(どちらも淡色野菜)を摂取できた。

チンジャオロース弁当

チンジャオロース弁当

チンジャオロース弁当 qīng jiāo ròu sī

★★★★★

ご飯、しゅうまい、しば漬け、千切りキャベツ、チンジャオロースが入っている。すでに飽きている唐揚げが入っていないため、なおさらおいしく感じてしまっている可能性があるが、星5つである。やはり肉は細切れになっていたほうが食べやすい。

今回は普通盛(480円)を購入した。

筆者は授業で中国語を履修していたが、そのときは中国語を学ぶ意義を全く感じていなかった。しかし、授業のおかげで今、チンジャオロースを中国語読みすることができる。いつ何が何の役に立つか分からないものである。中国語の学習が活かされたことは今までなかったので、今回使えて嬉しさを感じる。店員さんの中に中国語を話せる人がいそうなので、中国語会話にも活かせる可能性がある。

食べ終わって片づけるときに弁当容器を傾けたら、チンジャオロースの残り汁が服にこぼれた。最悪である。

おふくろ弁当

おふくろ弁当 運んでいる間にひじきが偏ってしまった

おふくろ弁当 運んでいる間にひじきが偏ってしまった

★★★★☆

ご飯、おかか、のり、キャベツの千切り、ゆで卵、照り焼きチキン、しば漬け、たくあん、ポテトサラダ、きんぴらごぼう、ひじきが入っている。筆者にとって半熟ゆで卵と皮がパリパリなチキンが好みであるが、この弁当のゆで卵とチキンはそうではなく、残念であったが味はよかった。

今回は普通盛(480円)を注文した。

この弁当には横長の弁当容器が使用されている。このことから、おふくろ弁当の「おふくろ」は懐の広い人を想定したものであり、「懐の広い人が作った弁当」がテーマの弁当であると推測できる。それが本当かどうかを知るつもりはない。

今更だが、ポテトサラダを割り箸で食べるのは難しい。

チキン照焼弁当

チキン照焼弁当 テリヤキソースつき

チキン照焼弁当 テリヤキソースつき

★★★★☆

ご飯、きんぴらごぼう、しば漬け、ゆで卵、千切りキャベツ、チキン、テリヤキソースが入っている。これまでわせ弁に君臨していた唐揚げにチキンが取って代わったような感じである。テリヤキソースはみたらしのようであった。しかし色がみたらしより濃ゆく、甘さが少ない点で違いがある。チキンにはもとから醤油ベースの味付けがされているが、表面にツヤを出すためにテリヤキソースをかける。

今回は普通盛(480円)を購入した。

見方を変えるとチキン照焼弁当が人の顔に似ていることに気が付く。ゆで卵がゴーグル、チキンがマスク、千切りキャベツが髭、ご飯が白髪、その他がその他のようである。チキン照焼弁当はキャラ弁である可能性がある。

ビビンバ焼肉弁当

ビビンバ焼肉弁当 割り箸の紙袋が変わった

ビビンバ焼肉弁当 割り箸の紙袋が変わった

★★★★☆

ご飯、ナムル、しば漬け、ゆで卵が入っている。肉は噛めば噛むほど味が出てくる。その味はこれまでに食べてきた〇〇焼肉弁当に入っている焼肉の味と同じである。よく考えてみれば、火が通った厚切りの肉を食べる機会は滅多にないので(あったとしてもミディアム状態で食べてしまう)、筆者には肉の弾力に対する耐性がついていない可能性がある。ナムルはほんの少しであるが辛味があってよい。喜ばしいことに確認できただけでも、もやし、にんじん、緑色の細長い野菜、茶色の細長い茎のような野菜、きくらげ、唐辛子、ごまと調味料で構成されており、野菜が豊富である。

今回は普通盛(450円)を購入した。

研究室にある電子レンジを使ってわせ弁を温めてみた。

電子レンジで温め中 今はなきNationalの電子レンジ

電子レンジで温め中 今はなきNationalの電子レンジ

温め終わった直後は湯気が出ていたが、このブログに書く内容を考えているうちに冷めてしまった。

ゆで卵と肉にしっかり火を通してあるのは安全面に気を使った結果であると考えられる。よって弁当に半熟卵やミディアムの肉を求めてはいけないのかもしれない。

ベスカラ弁当

ベスカラ弁当 久しぶりの唐揚げ

ベスカラ弁当 久しぶりの唐揚げ

★★★★☆

ご飯、千切りキャベツ、しば漬け、唐揚げ、ベストサンド?、ソースが入っている。唐揚げが入っていない弁当が5回も続いたので、この弁当で唐揚げと再会できて満足である。

今回は普通盛(450円)を購入した。

この弁当を購入する前は、「ベスカラ」の意味について様々な憶測が研究室内でなされており、最も有力そうな説は「ベストな唐揚げ弁当」であった。ベスカラ弁当を購入して持ち帰り、ふたを開けてみると、そこには「ベス」らしき円盤状の揚げ物があった。ベスの構造を調べるために2つに切断した。その断面図を次に示す。

ベスの断面図

ベスの断面図

観察の結果、チーズを挟んだハムに衣を付けて揚げた食べ物であると判明した。

この弁当を購入する前に文献調査を行っていなかったので、食べ終わったあとにネットで調査を行った。すると「ベス」とは「ベストサンド」の略であることが分かった。ベストサンドの意味については分からなかった。

あらびきハンバーグ弁当(トマトソース)

あらびきハンバーグ弁当(トマトソース) おいしそうな匂いがした

あらびきハンバーグ弁当(トマトソース) おいしそうな匂いがした

★★★★★

ご飯、唐揚げ、しば漬け、きんぴらごぼう、ハンバーグが入っている。どちらかといえば、トマトソースではなくデミグラスソースの風味が強い気がする。ふたを開ける前からわせ弁らしからぬおいしそうな匂いが研究室内に漂い、皆の食欲を刺激した。ふたを開けてみると見るからにおいしそうであった。結局、なぜわざわざメニューでトマトソースの存在を強調しているのかは分からなかった。

今回は普通盛(450円)を購入した。

わせ弁周辺にはいくつもの弁当屋が存在しているが、わせ弁以外の弁当屋に関するブログは書きにくい。なぜならネタ性が薄いからである。なんらかのネタがないとブログにしにくい。

つまり「わせ弁以外はブログにならない」。これは大学でよく使われる決まり文句である「それは論文にならない」と非常によく似ている。ブログにおけるネタ性は論文における新規性に相当する。

古くからわせ弁に関する考察はなされていて、過去にはわせ弁のメニューを全部制覇した強者も存在する。しかし今もなお、わせ弁に対する興味は新たに湧き続ける。実際に現在も多くの人がわせ弁を食している。だからこそ今も、わせ弁に関する考察をする必要性があると考える。

本ブログは、わせ弁を工学的に考察している点で他のブログと異なると強調しておく。

工学は必ず役に立つことに対して用いなければならぬとの立場からすると、本ブログで行っている工学的考察は何の役にも立っていないため無駄である。しかし、そもそもこれはただのブログであるため、多少無益なことでも許されるのである。

唐揚(鶏)弁当

唐揚(鶏)弁当 ほぼ唐揚げ

唐揚(鶏)弁当 ほぼ唐揚げ

★★★☆☆

ご飯、唐揚げ、しば漬け、千切りキャベツが入っている。実にシンプル。唐揚げの多さに耐えられなかったので星3つである。(もちろん完食した。)

今回は普通盛(430円)を購入した。

唐揚げの味付けは醤油ベースで少し塩辛い。あと、衣の表面粗さ(機械製図の授業で習う概念)が小さいため、なおさら油っぽく見えてしまう。

もし長らく唐揚げを食べていなくて唐揚げをたくさん食べたい気持ちであったならば、この弁当をもっとおいしく食べられたのだろう。しかし、筆者は頻繁にわせ弁の唐揚げを食べていて若干飽きてしまっている。他の味付けの唐揚げが食べたい。

弁当名で鶏を強調している理由に関しては諸説あるが、ここで筆者が考える新説を提唱したい。裏メニューに唐揚(鳩)弁当があるとする説である。はたして真偽の程はいかに。

エビフライ弁当

エビフライ弁当 弁当っぽい

エビフライ弁当 弁当っぽい

★★★★★

ご飯、キャベツの千切り、しば漬け、きんぴらごぼう、レモン!、エビフライ、タルタルソース、からし、ソースが入っている。エビフライにつけるソースが3種類もあり、さらにレモンまであるため、2^4通りの味付けでエビフライを楽しめる。筆者の一番のお気に入りはレモンだけをエビフライにかけた場合である。わせ弁の最大の特徴である脂っこさを否定し、さわやかさを追求した。

今回は普通盛(430円)を購入した。

この弁当はエビフライを3本も食べられるので満足感がある。

MATLABをPCにインストールしたので簡単にグラフを作成できるようになった。ステーキ弁当を食べた日に載せた来客数の時間分布図は、MATLABで作成した正規分布のグラフにPowerPointで一部手を加えたものである。

チキン竜田弁当

チキン竜田弁当 肉が大きい

チキン竜田弁当 肉が大きい

★★★★★

ご飯、きんぴらごぼう、しば漬け、千切りキャベツ、チキン竜田が入っている。チキン竜田にかかっているたれは、酸味のあるみたらしのようであった。チキン照焼弁当のテリヤキソースと同時に食べ比べてみないと詳しいことは言えないが、同じような味のたれである。さすがにみたらしだんごに使われるみたらしとは酸味の点で異なっており、おかず用に開発されたものであると推測できる。

チキン竜田の表面とこれまでに食べてきた唐揚げの表面(他の弁当の写真を参照)を見比べてほしい。チキン竜田の表面はざらざらしている一方で唐揚げの表面はのっぺりしている。表面の様子によってギトギト感が大きく異なっている。筆者はチキン竜田の表面のほうが好みである。

今回は普通盛(400円)を購入した。

以前わせ弁でもらったくじの正体が分かったので報告する。「2019新宿区応援セール」のくじであった。そのキャンペーンに参加している店舗で6/1(土)~6/20(木)に500円以上の商品を購入した、またはサービスを利用した場合に、スピードくじ方式の抽選券を1枚もらえるキャンペーンであった。シーフードフライ弁当(500円)を購入したときにくじをもらえて、その翌日にステーキ弁当(580円)を購入したときにくじをもらえなかった理由は、その2日の間にわせ弁が保有していたくじが全部配布されたからであった。

ミノキムチ丼

ミノキムチ丼 容器が小さい

ミノキムチ丼 容器が小さい

★★★☆☆

ご飯、しば漬け、唐揚げ、ミノキムチが入っている。

今回は普通盛(400円)を購入した。

容器が茄子カラの普通盛と同じ大きさであり、小さめである。しばらくの間、大きめの弁当容器に入った弁当を連続して食べてきたので、この小ささに少し驚いた。

ミノキムチとは、キムチ味の牛の胃である。初めて食べる食材だったので星3にした。やはり唐揚げはしょっぱい気がする。

ミノキムチ弁当ではなくミノキムチ丼である理由が不明である。

店先の電光掲示板に表示されている値段と実際の値段が異なっているので、早めに修正したほうがいいのではないか。

もつ丼

もつ丼 引き続き小さめな容器

もつ丼 引き続き小さめな容器

★★★★☆

ごはん、もつ、しば漬け、ねぎが入っている。

今回は普通盛(400円)を購入した。

もつについて。煮込まれたもつの味のために、たれに使われている調味料が何なのかよく分からなかったが、おそらく味噌であろう。今までもつをあまり食べたことはなかったが、見た目に反してやわらかく、食べやすかった。適度な弾力があるために、口の中が面白いことになった。味やにおいのくせが強くなかったので安心して食べられた。

しば漬けについて。色が鮮やかすぎる。口の中が真っ赤になってしまいそうである。

ねぎについて。得体のしれないもつを食べ進める中でねぎに出会い、昔なじみの香りがすると安心感を感じた。あたかも暗闇の中、人里離れた長い山道を進み、人家から漏れ出す灯りを見つけたときのような安心感であった。ねぎは優れた香味野菜であるとの確信を深めた。

いつもは13:00過ぎにわせ弁を買いに行くが、本日は11:30頃にわせ弁に行った。するといつもよりご飯が熱々であった。筆者は軽い猫舌であるため、ご飯の熱さに驚いた。

ミノキムチ丼も、もつ丼も小さめの容器に入っていた(共に普通盛)。この小さめの容器の名前が「丼」なのではなかろうか。そうだとすると、同じく小さめの容器で提供される普通盛の茄子カラ弁当は、実は茄子カラ丼なのではないか。

塩チキン弁当

塩チキン弁当 肉が白っぽい

塩チキン弁当 肉が白っぽい

★★★★★

ご飯、きんぴらごぼう、しば漬け、レモン、千切りキャベツ、塩チキンが入っている。

今回は普通盛(400円)を購入した。

チキン照焼のチキンの表面は褐色だったが、塩チキンは白い。肉に下味をつけるときに使う調味料の種類より、色に違いがでるのであろう。チキン照焼には醤油、塩チキンには塩を使っている。さらに、肉には胡椒が程よく効いていて食べやすい。加えて、塩チキンにレモンは非常によく合う組み合わせであると感じた。

牛肉と違って鶏肉は柔らかくて食べやすい。

普通盛だと肉の量に対してご飯が少ない気がする。

筆者が普段過ごしている喜久井町キャンパスからわせ弁への行き方について述べる。わせ弁に通い始めた初期は下図で青い点線によって示した道を通ってわせ弁に行っていた。しかし、下図で緑の点線によって示した道を通ったほうが早く着くことに気が付いた。それ以来、緑の点線を通ってキャンパスとわせ弁の間を行き来している。

道順

道順

Googleマップのルート検索でも緑の点線で示した道のほうが50m短いと表示される。偶然かもしれないが、緑の点線で示した道を通ったほうが信号に引っかかりにくい上に、信号の待ち時間も少ない。

チキン南蛮弁当

チキン南蛮弁当 チキン南蛮の衣の厚さは約3mm

チキン南蛮弁当 チキン南蛮の衣の厚さは約3mm

★★★★★

ご飯、きんぴらごぼう、しば漬け、千切りキャベツ、レモン、チキン南蛮、タルタルソースが入っている。

今回は普通盛(400円)を購入した。

この弁当の特徴はなんといってもチキン南蛮の衣であろう。これまでに食べてきた唐揚げ(茶色)、チキン照焼(こげ茶色)、チキン竜田(白みがかった茶色)、塩チキン(白)のどれとも異なる見た目をしており、黄色である。色だけでなく、衣がどのチキンよりも厚く、およそ3mmであった。衣が湿気を吸ってしまっていたが味はよく、タルタルソースやレモンなしでも大丈夫である。これらのチキンの中では、チキン竜田とチキン南蛮が好みである。

本日は日曜日なのにも関わらず、わせ弁にはお客がたくさんいた。客数が少なそうな日曜日であっても朝から晩まで開店しているため、どうやりくりしているのか不思議である。

今回はわせ弁のビジネスモデルについて簡単に考察しよう。わせ弁はそのネタ性で集客し、その油で客をわせ弁中毒にし、リピーターを増やす。店先で弁当を販売するだけなので客の回転が速い。普通盛の値段は安くても、わせ弁に胃袋をつかまれた常連客は大盛りを注文するため追加料金を支払う。よって実質的な単価はそこまで低くない。極め付けはメニューの多さである。(筆者は毎日わせ弁に通っているのに全メニューを制覇するのは相当先のことになりそうである。)もしかすると本当に高田馬場で鳩を狩っているかもしれない。そうだとすると材料代を節約できる。

とりそぼろ弁当

とりそぼろ弁当 惣菜の密度が高い

とりそぼろ弁当 惣菜の密度が高い

★★★★★

ご飯、しば漬け、きんぴらごぼう、唐揚げ、インゲン豆の天ぷら、とりそぼろが入っている。

今回は普通盛(400円)を購入した。

唐揚げについて。久しぶりの唐揚げだったので、唐揚げの味が気にならなかった。

インゲン豆の天ぷらについて。やはり弁当には緑が必要である。千切りキャベツはどうしても水っぽくなってしまうが、天ぷらからは千切りキャベツほど水がしみだしてこないため良い。

とりそぼろについて。甘くて生姜が効いている。佃煮のような味である。

筆者は甘党なので星5つである。

以前に普通盛が小さめの容器で提供される弁当のことを「丼」と呼ぶのではないかと推測したが、例外を再び見つけた。今のところ茄子カラ弁当と、とりそぼろ弁当の2つが例外である。

わせ弁を研究室に持ち込むと室内がわせ弁の匂いで満たされ、湿気臭さがかき消される。このことから、わせ弁には抗臭効果があると言える。ただし、抗臭効果はわせ弁を食べ終わるまでしか続かないこと、消したい匂いの原因を根本解決しているわけではないことに注意しなければならない。

二段シャケ弁当

二段シャケ弁当 ご飯が二層構造である

二段シャケ弁当 ご飯が二層構造である

★★★★★

ご飯、おかか、のり、シャケ、ゆで卵、ちくわの天ぷら、醤油、しば漬け、きんぴらごぼうが入っている。

今回は普通盛(400円)を購入した。

弁当のご飯が二層構造になっていて、底から順に、ご飯、おかか、のり、ご飯、おかか、のりとなっている。その上に惣菜が乗っている。二段シャケ弁当は、のり弁の一種である。

この弁当は小さめの容器に入っている。以前、普通盛が小さめの容器で提供される弁当のことを丼と呼ぶのではないかと推測したが、さすがに例外が多すぎる。よってこの推測は正しくない。

今まで食べてきた弁当の中には初めて見る食材が入っているなどしたため、怪しみながら食べていた。一方で二段シャケ弁当はのり弁の一種であるためなじみ深く、怪しむ必要がなかった。

ドカ弁ものり弁の一種である。そちらの方の惣菜は揚げ物ばかりで全体的に茶色い。ドカ弁のほうがわせ弁らしい弁当である。

カキフライ弁当

カキフライ弁当 おそらく揚げたて

カキフライ弁当 おそらく揚げたて

★★★★★

ご飯、キャベツの千切り、きんぴらごぼう、レモン、しば漬け、カキフライ、ソース、からしが入っている。

今回は普通盛(400円)を購入した。

注文してから会計するまでに10分程度かかるので、その場で揚げているのだろう。

今回は冷めないうちに食べ終わった。

イカフライ弁当

イカフライ弁当 揚げたて

イカフライ弁当 揚げたて

★★★★★

ご飯、きんぴらごぼう、しば漬け、キャベツの千切り、イカフライ、ソースが入っている。

今回は普通盛(380円)を購入した。

ステーキ弁当、カキフライ弁当と同じく、注文してから弁当を受け取るまでに10分くらいかかる弁当のうちの一つである。これらの弁当は注文が入ってから調理されていると推測できる。

唐揚げと牛肉とホッケを除けばわせ弁の惣菜は基本的になんでもおいしい。よってこの弁当も星5つである。

わせ弁を食べると眠気に襲われる奇妙な現象が研究室内で観測された。筆者自身は何を食べても昼食後は眠くなる体質なので、わせ弁を食べたときと他の食べ物を食べたときの違いが分からない。しかし複数名がわせ弁を食べた後に眠くなると訴えたため、その原因について検討する必要が生じた。議論を進めていく中で睡眠薬混入説などが提案された。真偽の程は不明である。

話はそれるが、このように筆者はブログ作成に励んでいるが文章作成能力は伸び悩んでいる。その理由は極めて単純である。インプットがないからである。筆者は高校生になって以来書物をほとんど読んで来なかった。読むとしても参考書、SNS、データシート、試験問題くらいである。筆者が文章を書くときは、目標とすべき上手な文章がいかなる文章なのか知らずに書き散らしているだけなのである。これでは上達できない。

ミックス弁当

ミックス弁当 天候:雨 購入日時:2019.7.16, 13:26

ミックス弁当 天候:雨 購入日時:2019.7.16, 13:26

★★★★☆

ご飯、唐揚げ、しば漬け、のり、オムレツ、コロッケが入っている。

今回は普通盛(380円)を購入した。

やはり唐揚げの肉は固く、衣は平面的である。

これまでに食べてきたどの弁当にものりの下におかかが隠れていたが、この弁当にはなかった。代わりに醤油ベースのたれがご飯にかかっている。小さな変化であるが、気に入った。

日付:2019.7.16、天候:雨、購入時刻:13:26、実験時刻:13:52、実験場所、第2研究室

目的:わせ弁は冷めているとの噂を耳にしたので、わせ弁の温度を調べて噂の真偽を確かめたい。今回は実験装置の試験運用を行い、噂の検証に備えることにする。

実験装置:サーモカメラ XT2

実験方法:XT2でミックス弁当を撮影し、サーモカメラで噂の検証ができるかどうか検討する。

実験結果:ミックス弁当のRGB画像とサーモ画像を示す。

撮影状況図 RGB画像

撮影状況図 RGB画像

ミックス弁当 サーモ画像

ミックス弁当 サーモ画像

オムレツとソースの袋は40℃程度で、唐揚げとコロッケとしば漬けは30℃程度である。筆者の手の温度よりわせ弁の温度のほうが高い。

考察:今回は表面温度を赤外線から測定しただけであり、接触温度計で計測した温度を使って補正していない。そのため厳密な議論はできないが、大まかに次のことが言える。

食べてみると分かるが、ご飯が一番温かい。オムレツとソースはご飯からの熱で温められやすいが、唐揚げとコロッケとしば漬けはご飯から熱が伝わりにくいと推測される。

わせ弁はできたてほやほや熱々ではないにしても、体温よりは温かい。わせ弁は冷めているとの噂が立つ原因はわせ弁本体にあるのではなく、購入してから食べる場所まで持ち帰る間に冷えてしまうからだと予想できる。

厳密な温度を調べなくても噂を検証できるため、サーモカメラを用いてもよいと結論づける。

パワー弁当

パワー弁当 縦×横×高さ=208×268×37mm

パワー弁当 縦×横×高さ=208×268×37mm

★★★★★

ご飯、ごま、梅干し、唐揚げ、肉団子、キャベツの千切り、たくあん、しば漬け、コロッケ、ソース、オムレツ、ステーキが入っている。

今回は普通盛(750円)を購入した。

注文したら15分くらいかかるが大丈夫かと確認された。本日はパワー弁当を食べる予定だったので大丈夫と答えた。

とうとうパワー弁当を買ってしまった高揚感からか、購入してから研究室に戻るまでの間に弁当をぶんぶん振り回しながら歩いてしまい、ステーキのたれが漏れ出してしまった。ステーキが浸るほどたれが入っているため、弁当容器を傾けてはならない。

他の弁当より高価であり、迫力がある。

ステーキの焼き加減はウェルダンである。筆者はミディアムが好みであるが、衛生面を考えてしっかり火を通していると推測できるため、仕方がない。

唐揚げが容器からはみ出さんばかりに乗っかっている。

いつもは発砲スチロール製の熱が伝わりにくい容器だが、この容器は違う。研究室の冷たい机の上にパワー弁当を置くと、速やかに熱が弁当から机に移動してしまう。

この弁当を食べてパワー弁当は力であると確信した。

結言

筆者は工学の人間であるため、わせ弁の食レポをするにあたって批判的な立場で考えることを徹底した。その結果、わせ弁はつっこみどころが満載であった。到底一人の力では批判し切れるものではなかった。しかしながら隙の多さゆえに、わせ弁は多くの人から愛されているのであろう。わせ弁に関するブログの多さがわせ弁の人気さを物語っている。

これでわせ弁の黄色いメニューに載っている弁当は全て制覇したことになる。(テープで隠されているうなぎW(2枚)弁当はまだ注文していない。売っているのかどうかすら不明。)5月27日から7月17日に渡る52日間で34種類の弁当を食べたことになる。食べ過ぎである。

黄色いメニュー

黄色いメニュー

今後の展望

わせ弁のメニューは非常に多い。これまでに食べてきた弁当は全メニューのうちの一部でしかない。

白いメニュー

白いメニュー

黄色いメニューに表示されている34種類に加えて、白いメニューに表示されている弁当もある。こちらの弁当も食べる必要がある。全メニュー制覇への道のりは長い。

今後も文章作成能力を磨きつつ食レポに熱心に取り組み、わせ弁のイメージ向上に貢献していく所存である。

指先カイロ

(2020.7.27追記:世の中には塗るタイプのカイロや温感クリームというものがあるようです。指先カイロを考えたときは調査不足だったので知りませんでした。私が欲しかったのは前者であり、指先カイロではない気がします。)

寒い環境の中でも私は本のページをめくったりスマホを操作したりするのですが、指先が冷たすぎると指を思うように動かせません。細かい作業をするときは当然手袋をはずさないといけませんが、手袋をはずすとますます指先が冷たくなってしまいます。寒くても素手で指先を使った軽作業をしやすくできないかと考えて「指先カイロ」を作りました。

指先カイロ装着図

指先カイロ装着図

指を温める仕組み

  • 体の温かい部分から直接熱をもらう方法

息を手に吹きかけたり首などの温かい部分を触ったりして手を温めます。普段私はこの方法を一番よく使います。指を温めるためには一度作業を中断しなければなりません。

  • 血行をよくする方法

グーパーして指の血行をよくして温めます。この方法は私の指には無効でした。

  • 手首を温める方法

手首を温めることで指先までも温めようとします。この方法は私の指には無効でした。

  • あらかじめ温めて置いた物体から熱を伝える方法

温かい飲み物が入った入れ物を触るなどして指を温めます。もし小型軽量で熱容量が大きい物質があればかなりよい方法です。なぜなら使用後にその物体が冷たくなっても体温で温め直せば再び使えるからです。今回はそのような物質があるかどうかの調査は行いませんでした。

  • 摩擦熱による方法

手のひらをこすりあわせ、摩擦熱で手を温めます。指を温めるためには一度作業を中断しなければなりません。

  • ジュール熱による方法

火傷を防ぐために温度を制御する必要があり、電源や配線をどうするかという問題があります。さらに、複数回使用するなら洗濯をどうするかという問題があります。

  • 反応熱による方法

火傷を防ぐために高温になりすぎないように反応速度を調節する必要があります。そして環境にやさしい必要があります。

先行事例

  • 指のない手袋

作業はしやすいですが指先は冷たくなります。

  • 手首を温める方法

私の指は手首を温めたとしても冷たいままでした。

  • 電気で手袋を温める方法

手袋をしていたら作業が困難です。

  • 手袋の中に温かいものを挿入する方法

手袋をしていたら作業が困難です。

今回提案するカイロの特徴

私の指で試した結果、指に直接熱を供給しないかぎりは指が温まりませんでした。そして温めた部分だけ局所的に温かくなって、そうでない部分は冷たいままでした。温めるのを止めるとすぐに冷たくなりました。したがって熱源を直接指に取り付けて温め続けなければならないと分かりました。この実験結果と寒い中で指先を使った軽作業をしやすくするという目的とを考えあわせて以下に挙げる4点を満たすものを作ろうと考えました。

  • 指先を温める
  • 素手に装着して使う
  • 手作業の邪魔にならない
  • 少なくとも数分間は温かさが持続する

これらを実現するために自ら発熱する小さな熱源を第2指節の手の甲側に取り付ければよいと考えました。今回は熱源として酢酸ナトリウム三水和物の凝固熱を使用しました。酢酸ナトリウム三水和物を入れた小型容器をゴムバンドの輪っかで指に装着するだけで使えるので楽です。汚れるのはゴムバンドだけなので洗濯するなり交換するなりすれば繰り返し使用できます。

実際に使うとなれば安さも重要になってきますが、この方法なら安く作れます。

製作方法

材料

  • 酢酸ナトリウム無水物(Amazon
  • 水(水道水)
  • 醤油用の鯛型プラスチック容器(100均)
  • ゴムバンド(100均)
  • 小さいタッパー(100均)

熱源

今回は酢酸ナトリウム三水和物の過冷却現象を利用し、その凝固熱をカイロの熱源とします。

酢酸ナトリウム無水物82[g]と水54[g]の割合でペットボトルに入れ、湯煎にかけながら酢酸ナトリウム三水和物を作ります。酢酸ナトリウム三水和物を買ってもいいかもしれません。

最小目盛りが10[g]のはかりしか持っていなかったので重さはほぼ目分量で計りました。湯煎にかけると水が蒸発して減ってしまうので水は54[g]より少し多めに入れました。蒸留水を用意するのが面倒だったので水道水を使いました。

この作業は次のサイトを参考にして行いました。

http://www.onsenmaru.com/topics/T-150/T-177-jisakukairo-B.htm

カイロ本体

液体状態の酢酸ナトリウム三水和物を醤油用の鯛型プラスチック容器に入れて冷まします。ペットボトルに残った酢酸ナトリウム三水和物も冷まして衝撃を加え凝固させ、タッパーに入れておきます。

取り付け部

ゴムバンドを適当な長さに切ります。(私の指の場合9cmくらい。)ゴムバンドの両端がほつれないようにライターであぶります。ゴムバンドで輪を作り、縫い代1cmくらいで縫います。

使用方法

発熱開始

液体状態の酢酸ナトリウム三水和物入り鯛型プラスチック容器のふたを開け、酢酸ナトリウム三水和物の結晶をひとかけら入れると、そのかけらを起点として凝固が進行し、凝固熱が発生します。発熱が確認できたら容器のふたを閉めます。

装着

ゴムバンドの輪を手の指の第2指節にはめ、指の背とゴムバンドの隙間に、発熱している鯛型容器を挟みます。このページの一番上の写真(指先カイロ装着図)を参考にしてください。

再使用

凝固し終わって冷えたカイロを容器ごと湯煎にかけて中身を液体状態に戻し、冷まします。

湯煎の様子

湯煎の様子

以降同じことの繰り返しです。

苦労した点

酢酸ナトリウム無水物から酢酸ナトリウム三水和物をつくるのにかなり時間がかかるので大変でした。

酢酸ナトリウム無水物と水の分量が適当だったために水が多すぎたり少なすぎたりしました。そのせいか、一番最初に作った酢酸ナトリウム三水和物はなかなか凝固しなかったので困りました。

酢酸ナトリウム三水和物を入れる容器探しでだいぶ苦労しました。試行錯誤の末に見つけた醤油用の鯛型プラスチック容器は、その丸みのために指の背の曲面によく合うので、意外にも結構いい容器です。

酢酸ナトリウム三水和物を使ったカイロ自体はすでに製品化されています。既存のカイロは衝撃を加えることで発熱を開始させます。しかし今回作った酢酸ナトリウム三水和物入り鯛型容器にどんなに衝撃を加えても凝固が開始しなかったので別の方法を考えなけばなりませんでした。凝固はなんらかのきっかけがないと開始しないので、あらかじめ作っておいた酢酸ナトリウム三水和物の小さい結晶を容器に入れればよいのではないかと思いつき、試してみたらうまくいきました。手間がかかりますが、この方法が確実です。

左:凝固前、中:結晶入りタッパー、右:凝固後

左:凝固前、中:結晶入りタッパー、右:凝固後

改善点

酢酸ナトリウム三水和物を使えばカイロを家庭で作りやすいですし、再使用可能、軽量、制御不要、安全(酢酸ナトリウムは食品添加物なので口に入っても大丈夫ですし融点が58℃なので熱くなりすぎない)という利点があります。しかし発熱開始のための操作が面倒ですし、今回使った醤油用の鯛型プラスチック容器のように完全に密閉されていない容器だと酢酸ナトリウムの酸っぱいにおいがしますし、酢酸ナトリウム三水和物を温めて融かさなければ再使用できないので面倒という欠点があります。

「指先カイロ」をより使いやすいものとするためには発熱部分を変更する必要があります。私は市販のカイロのような鉄の酸化熱を利用した発熱部分がよいと考えています。ただし市販のカイロの大きさは手のひらサイズなので指先サイズの特注品である必要があります。カイロの入ったビニール袋を開けるだけで発熱が開始するので楽ですし、使い捨てなので楽ですし、無臭です。鉄粉自体は安全ではないですが市販のカイロのような入れ物に入っていれば安全です。市販のカイロは変形しやすいので鯛型容器よりも指にフィットしてより広範囲に指を温められます。

まとめ

カイロ会社が指先サイズのカイロも発売してくれればいいのに。

"楽器"としてのステッピングモーター入門

モーターを鳴らして演奏することが流行っているので自分でもやってみました。ついでにステッピングモーターについて理解を深めました。

はじめに

プログラムにC言語を使いました。

この記事はすでにステッピングモーターを回すことができる人向けです。

今回は2相ユニポーラのハイブリッドステッピングモーターを使いました。

2020.5.31追記 図がところどころ間違っていたので直しました。

ステッピングモーターについて

ステッピングモーターとは[1]「パルス信号によって回転角度・回転速度を正確に制御できるモーター」です。このパルス信号の周波数を変えると回転速度を変えられます。速く回転させると高い音が鳴り、遅く回転させると低い音が鳴ります。ということは、このモーターは周波数を調整すればドレミファソラシドの音を鳴らせて音楽を演奏できるモーターと言い換えることができます。

※[1], [2], ・・・は参考文献番号。以下同様。

駆動方式

2相ステッピングモーターには2つコイルが使われています。巻き方はモノファイラ巻きとバイファイラ巻きの2種類あります。[2]一つの極に一つのコイルを一方向に巻くのが「ユニファイラ巻き」で、一つの極に2本の線を重ねて巻くのが「バイファイラ巻き」です。

ユニファイラ巻きのステッピングモーターはバイポーラ駆動で動かします。一方でバイファイラ巻きのステッピングモーターはユニポーラ駆動で動かします。

今回使うステッピングモーターはユニポーラ駆動で動かすステッピングモーターです。

励磁方式

[3],[4]各相のコイルへ決まった順番で電流を流す方式を励磁方式といいます。

1相励磁

主にユニポーラモータで使用します。 1相ずつ励磁位相を進める方式で、フルステップ駆動ともいいます。 消費電力は少なくなりますが、振動が発生し易くなります。

1相励磁

1相励磁

1相励磁波形

1相励磁波形
2相励磁

バイポーラモータでのフルステップ駆動方式です。 2相ずつ励磁位相を進める方式です。 ユニポーラモータの1相励磁よりも、 出力トルクが大きくダンピング性に優れており、より滑らかに動作します。

2相励磁波形

2相励磁

2相励磁波形

2相励磁波形
1-2相励磁

1相励磁と2相励磁を交互に繰り返す方式で、ハーフステップ駆動ともいいます。 モータのステップ角分解能は、1相や2相励磁方式の半分になります。 2相励磁よりも更に滑らかに動作します。

1-2相励磁

1-2相励磁

1-2相励磁波形

1-2相励磁波形
マイクロステップ駆動

フルステップ、ハーフステップ駆動が、2つのコイル電流をON/OFFし一定角ずつ回転させるのに対し、 マイクロステップ駆動は、2つのコイル電流比率を階段状に変化させることで、 更に細かいステップ角で回転させることができます。

ステッピングモーター用モタドラ

今回はSLA7073MPRTというモタドラを使いました。マイコンでパルス波を出力し、回転方向(CW/CCW)と励磁方法を決めてモタドラに入力すると、モタドラからユニポーラ駆動のステッピングモーターを回すために必要な電気信号4つ( A相, Aバー相, B相, Bバー相)が出力されます。

音が鳴る原理

モタドラからの周期的なパルス電気信号が磁界の中にあるコイルを流れると、ステッピングモーターのローター(回転子。これには磁石が付いています。)とステータ(固定子。これにはコイルが付いています。)に周期的に力が働くので振動します。これがステッピングモーター音の原因と推測されます。

2019.9.3追記 推測しただけであって未検証です。

参考文献[5]によるとステッピングモーターをマイクロステップ駆動すると静音化できるようです。マイクロステップ駆動では単純なON/OFFのパルス波ではなく比較的滑らかな電気信号でモーターを駆動するから振動が抑えられたのでしょう。

2019.9.1追記 マイクロステップ駆動による静音化については自分で試しておりません。各自試してみてください。

2020.5.16追記 マイクロステップ駆動を試してみました。そして1-2相励磁のときとマイクロステップ駆動のときとでステッピングモーターが出す音を耳で確かめました。そのときモタドラへ入力するパルス信号の周波数は両方とも同じにしました。その結果、マイクロステップ駆動のときのほうが音が小さかったです。音の高さは両方とも同じでした。しかし、少し音が小さいだけでした。マイクロステップ駆動でも無音化できないようです。

ドレミファソラシド

ネットで調べればドレミファソラシドの周波数が調べられます。今回は参考文献[6]を使って必要な音階の周波数を求めました。

曲をプログラミングするためには

ステッピングモーターで演奏するために必要なのは音の高さと長さの2つです。だからプログラムにおける楽譜は音の高さとその長さを格納した配列で表せます。ステッピングモーターを駆動する電圧を音ごとに変更すれば音の大きさを調整できるかもしれませんが今回はやりませんでした。あと、音色は変更できません。

C言語に使える文字に「#」と「♭」は含まれていません。そこでドイツ音階を代わりに使いました。ドイツ音階なら全てアルファベットで書き表せるからです。

対応表

ファ

臨時記号

なし

C

ツェー

D

デー

E

エー

F

エフ

G

ゲー

A

アー

H

ハー

#

Cis

ツィス

Dis

ディス

Eis

エイス

Fis

フィス

Gis

ギス

Ais

アイス

His

ヒス

Ces

ツェス

Des

デス

Es

エス

Fes

フェス

Ges

ゲス

As

アス

B

ベー

ドはCではなくDO、ド#はCisではなくDO_SHARP、レはDではなくREとすれば少し読みやすいプログラムになったかもしれませんが、楽譜を全部手打ちしたため一音が短いほうが楽だったのでドイツ音階を採用しました。

パルス波(としてPWMを使います)の周期を変えることで色々な高さの音を鳴らします。

PWM周期レジスタに入れる値

鳴らしたい音階の周波数(これをf[Hz]とおきます)を元にして実際にPWM周期レジスタに入れる値を計算します。

\frac{タイマのクロック周波数}{f}\tag{1}

式(1)の「タイマのクロック周波数」の単位は[Hz]です。どのマイコンを使うかとクロックをどう設定するかとタイマをどう設定するかによってこの値は異なるので自分で調べましょう。

今回はSTM32F303K8T6マイコンをシステムクロック周波数64[MHz]に設定し、プリスケーラでタイマのクロック周波数を1[MHz]にして使いました。このマイコンにはFPU(浮動小数点演算装置)がついているので、遠慮なく小数を含む計算をマイコンで行います。

この計算は次のようにマクロを使って実現しました。2行目のマクロのXには音階の周波数(実数)が入ります。

#define CLK_FREQ 1000000
#define FREQ2PWMPERIOD(X) (int)(CLK_FREQ / (X))

マクロ

音の高さと長さをマクロで表します。音の高さには鳴らしたい音の周波数を、音の長さには実際に伸ばす時間[ms]を使います。

音階

音階マクロを例示します。ドレミファソラシとド♯レ♯ファ♯ソ♯ラ♯です。例えばレ♭はド♯と同じ音なのでマクロにする必要はありません。

5はオクターブの番号です。音が高いオクターブほど大きい数字を使います。どの数字を使うかは実際に鳴らして決めてください。

休符はRESTとしました。

ここでは1オクターブ分だけしか示していないので、必要があれば自分で補ってください。

音が低すぎても高すぎてもきれいにモーターが鳴りません。実際に鳴らしてどのオクターブならきれいに鳴るかを確かめてみてください。

#define C5 523.251//ド #define Cis5 554.365//ド#/レb #define D5 587.330//レ #define Dis5 622.254//レ#/ミb #define E5 659.255//ミ #define F5 698.456//ファ #define Fis5 739.989//ファ#/ソb #define G5 783.991//ソ #define Gis5 830.609//ソ#/ラb #define A5 880.000//ラ #define Ais5 932.328//ラ#/シb #define H5 987.767//シ #define REST 0

2020.4.2追記:Shift_JIS文字コードで表現された「ソ」の2バイト目は0x5Cであり、プログラムをコンパイルするときに「\」と認識されてしまいます。このように2バイト目が0x5Cである文字を駄目文字と呼ぶそうです。意図通りにコンパイルするためにはコメント「//ソ」を「//そ」に書き換えるなどの工夫が必要です。

長さ

長さマクロを示します。全音符と全休符の長さを表すlen1が1536[ms]である理由は3で割り切れる数字のほうがいいかと思ったからです。ちょうどいい長さであればいくつでもいいと思います。

#define LEN1 1536		//全音符と全休符の長さ。2^9*3[ms]
#define LEN2 LEN1 / 2		//二分音符と二分休符の長さ
#define LEN2d LEN1 / 4 * 3	//符点二分音符と符点二分休符の長さ
#define LEN4 LEN1 / 4		//四分音符と四分休符の長さ
#define LEN4d LEN1 / 8 * 3	//符点四分音符と符点四分休符の長さ
#define LEN3_4 LEN1 /2 / 3	//三連四分音符と三連四分休符の長さ
#define LEN8 LEN1 / 8		//八分音符と八分休符の長さ
#define LEN3_8 LEN1 / 4 / 3	//三連八分音符と三連八分休符の長さ
#define LEN8d LEN1 / 16 * 3	//符点八分音符と符点八分休符の長さ
#define LEN16 LEN1 / 16		//十六分音符と十六分休符の長さ

楽譜

例として「かえるの合唱」の楽譜について説明します。

音の高さと長さを別々の配列に格納しました。二元配列を使って一つの配列に音の高さと長さの両方を格納してもいいと思います。この2つを合わせて楽譜配列と呼びます。

frog_notesには音階マクロを格納します。この配列を音階配列と呼びます。

frog_lenには長さマクロを格納します。この配列を長さ配列と呼びます。

音階配列frog_notes[i]に格納した音を長さ配列frog_len[i]に格納した長さ分伸ばして演奏します。

ヘッダファイルfrog_notes.hに音階をまとめて記述し、ヘッダファイルfrog_len.hに音の長さをまとめて記述します。そして配列宣言時に配列の中に音と長さを格納します。

const float frog_notes[] = {
		#include "frog_notes.h"
};
const uint16_t frog_len[] = {
  		#include "frog_len.h"
};

音階配列の中身であるヘッダファイルfrog_notes.hには次のように書いて下さい。コメントの数字は小節番号を表しています。

C5	,	//1
D5	,
E5	,
F5	,
E5	,	//2
D5	,
C5	,
REST	,
E5	,	//3
F5	,
G5	,
A5	,
G5	,	//4
F5	,
E5	,
REST	,
C5	,	//5
C5	,
C5	,	//6
C5	,
C5	,	//7
C5	,
D5	,
D5	,
E5	,
E5	,
F5	,
F5	,
E5	,	//8
D5	,
C5	,

長さ配列の中身であるヘッダファイルfrog_len.hには次のように書いて下さい。

LEN4	,	//1
LEN4	,
LEN4	,
LEN4	,
LEN4	,	//2
LEN4	,
LEN4	,
LEN4	,
LEN4	,	//3
LEN4	,
LEN4	,
LEN4	,
LEN4	,	//4
LEN4	,
LEN4	,
LEN4	,
LEN2	,	//5
LEN2	,
LEN2	,	//6
LEN2	,
LEN8	,	//7
LEN8	,
LEN8	,
LEN8	,
LEN8	,
LEN8	,
LEN8	,
LEN8	,
LEN4	,	//8
LEN4	,
LEN2	,

実はステッピングモーター演奏で一番大変なのが楽譜を書く作業です。まず曲を聴きながら楽譜に書き起こし、プログラムに書き込みます。めちゃくちゃ面倒なので途中で何度も止めようかと思いましたが馬鹿力でやりきりました。だれか楽に演奏できるようにするための方法を知っていたら教えてほしいです。ちなみに私は「コンバットマーチ」と「ようこそジャパリパークへ」と「アンダー・ザ・シー」と「ゲゲゲの鬼太郎」と「エレクトリカルパレード」と「君をのせて(天空の城ラピュタ)」と「カエルの歌(二重奏)」をプログラムに書き込みました。しんどかったです。

耳コピした内容が間違ってないか確認するためにDOMINOというフリー作曲ソフトで音を確認しました。このようなソフトを使ってうまくやる方法がないか考え中です。

楽譜読み込み

楽譜配列をfor()文で読み込みます。ms_wait()はミリ秒待機する自作関数です。レジスタ構造体にHALライブラリを使っているので注意してください。今回は2個のステッピングモーターを同時に同じように鳴らします。TIM16によるPWM波で1個目のステッピングモーターを制御し、TIM17によるPWM波で2個目のステッピングモーターを制御します。

まず、音階配列に格納した周波数[Hz]からPWM波の周期を計算し、TIM16->ARRレジスタに代入します。タイマカウンタの比較一致値をPWM波の周期の半分とします。(必ずしもタイマカウンタの比較一致値をPWM波の周期の半分にする必要はありません。)そのあとに長さ配列に格納した伸ばす長さ[ms]分だけ待機します。最後にTIM16の2つのレジスタに0を代入して音を消し、少しだけ待機します。(今回は10[ms]待機しました。)こうすることで音と音が区切れて音楽が聴きとりやすくなります。TIM17についても同様です。以上の流れにより音を1音鳴らせます。次の音を鳴らしたいときは配列の添え字iをインクリメントして楽譜配列の次の音を読みに行きます。

ここで休符マクロRESTを0にした効果が現れます。場合分けしなくても休符のときはARRレジスタに0が代入されるので音を消せます。

for(i = 0; i < 31; i++) {
	TIM16->ARR = FREQ2PWMPERIOD(frog_notes[i]);
	TIM16->CCR1 = TIM16->ARR / 2;
	TIM17->ARR = TIM16->ARR;
	TIM17->CCR1 = TIM16->CCR1;
	ms_wait(frog_len[i]);
	TIM16->ARR = 0;
	TIM16->CCR1 = 0;
	TIM17->ARR = 0;
	TIM17->CCR1 = 0;
	ms_wait(10);
}

main関数

main関数はこんな感じになります。init()関数は各種初期化を行う自作関数です。

int main(void)
{
	init();
	GPIOB->ODR &= ~GPIO_ODR_7; // ステッピングモータ励磁ON
	uint8_t i;
	for(i = 0; i < 31; i++) {
		TIM16->ARR = FREQ2PWMPERIOD(frog_notes[i]);
		TIM16->CCR1 = TIM16->ARR / 2;
		TIM17->ARR = TIM16->ARR;
		TIM17->CCR1 = TIM16->CCR1;
		ms_wait(frog_len[i]);
		TIM16->ARR = 0;
		TIM16->CCR1 = 0;
		TIM17->ARR = 0;
		TIM17->CCR1 = 0;
		ms_wait(10);
	}
	GPIOB->ODR |= GPIO_ODR_7; // ステッピングモータ励磁OFF
	while(1);
	return 0;
}

プログラム全景

マイコンの初期設定についてはここでは説明しませんが、ソースコードを載せておきます。色々とコメントをつけておいたので参考にしてください。

2019.8.15追記:SW4STM32(開発環境)に最初からついてくるスタートアップファイル(?)を使うと、このコードをコンパイルできない可能性があります。参考にするだけにしてください。

2020.4.2追記:Shift_JIS文字コードで表現された「ソ」の2バイト目は0x5Cであり、プログラムをコンパイルするときに「\」と認識されてしまいます。このように2バイト目が0x5Cである文字を駄目文字と呼ぶそうです。意図通りにコンパイルするためにはコメント「//ソ」を「//そ」に書き換えるなどの工夫が必要です。

#include "stm32f3xx.h"

//音階[Hz]
#define C5 523.251//ド
#define Cis5 554.365//ド#/レb
#define D5 587.330//レ
#define Dis5 622.254//レ#/ミb
#define E5 659.255//ミ
#define F5 698.456//ファ
#define Fis5 739.989//ファ#/ソb
#define G5 783.991//ソ
#define Gis5 830.609//ソ#/ラb
#define A5 880.000//ラ
#define Ais5 932.328//ラ#/シb
#define H5 987.767//シ

//休符
#define REST 0

//伸ばす長さ[ms]
#define LEN1 1536		//全音符と全休符の長さ。2^9*3
#define LEN2 LEN1 / 2		//二分音符と二分休符の長さ
#define LEN2d LEN1 / 4 * 3	//符点二分音符と符点二分休符の長さ
#define LEN4 LEN1 / 4		//四分音符と四分休符の長さ
#define LEN4d LEN1 / 8 * 3	//符点四分音符と符点四分休符の長さ
#define LEN3_4 LEN1 /2 / 3	//三連四分音符と三連四分休符の長さ
#define LEN8 LEN1 / 8		//八分音符と八分休符の長さ
#define LEN3_8 LEN1 / 4 / 3	//三連八分音符と三連八分休符の長さ
#define LEN8d LEN1 / 16 * 3	//符点八分音符と符点八分休符の長さ
#define LEN16 LEN1 / 16		//十六分音符と十六分休符の長さ

//PWM周期計算
#define CLK_FREQ 1000000
#define FREQ2PWMPERIOD(X) (int)(CLK_FREQ / (X))

//音階配列
const float frog_notes[] = {
		#include "frog_notes.h"
};
//長さ配列
const uint16_t frog_len[] = {
  		#include "frog_len.h"
};

//関数宣言
void init(void);
void sysclk_init(uint8_t multiple);
void drive_init(void);
void ms_wait(uint32_t ms);

int main(void) {
	init();//マイコンの初期設定
	GPIOB->ODR &= ~GPIO_ODR_7; //ステッピングモータ励磁ON
	uint8_t i;//8ビット符号なし整数 for()文で使う
	for(i = 0; i < 31; i++) {//楽譜配列を読み込む
		TIM16->ARR = FREQ2PWMPERIOD(frog_notes[i]);//PWM波の周期
		TIM16->CCR1 = TIM16->ARR / 2;
		TIM17->ARR = TIM16->ARR;
		TIM17->CCR1 = TIM16->CCR1;
		ms_wait(frog_len[i]);//待機
		TIM16->ARR = 0;//消音
		TIM16->CCR1 = 0;//消音
		TIM17->ARR = 0;//消音
		TIM17->CCR1 = 0;//消音
		ms_wait(10);//待機
	}
	GPIOB->ODR |= GPIO_ODR_7; // ステッピングモータ励磁OFF
	while(1);
	return 0;
}

//ミリ秒待機するための関数
void ms_wait(uint32_t ms) {
	SysTick->LOAD = 8000 - 1;	// reset value for count-down timer
	SysTick->VAL = 0;			// initial value
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;	// count start

	uint32_t i;
	for(i = 0; i < ms; i++){
		while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) );
	}
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	// count stop
}

//初期設定関数
void init(void) {
	sysclk_init(16);//システムクロックを64[MHz]に設定
	drive_init();//ステッピングモーター制御のための初期設定
}

//システムクロック設定関数
void sysclk_init(uint8_t multiple) { // max clock = 64MHz
	if( multiple <= 0 || multiple > 16 ) {
		return;
	}
	RCC->CFGR |= RCC_CFGR_PLLSRC_HSI_DIV2; // PLL <== HSI/2 = 4MHz
	RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // APB1 = PLL / 2 = 32MHz
	//RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2 = PLL / 2 = 32MHz
	RCC->CFGR |= ( (multiple - 1) << RCC_CFGR_PLLMUL_Pos);
	FLASH->ACR |= FLASH_ACR_LATENCY_1; // flash access latency for 48 < HCLK <= 72. This statement must be placed immediately after PLL multiplication.
	RCC->CR |= RCC_CR_PLLON;
	while(!(RCC->CR & RCC_CR_PLLRDY)); // wait until PLL is ready
	RCC->CFGR |= RCC_CFGR_SW_PLL; // PLL as system clock
	while( (RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL ); // wait until PLL clock supply starts
}

//ステッピングモーター制御のためのタイマ設定
void drive_init(void) {
	//====モータードライバ関係のGPIO設定====
	RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // IO portB clock enable

	GPIOB->MODER &= ~GPIO_MODER_MODER7_Msk; // initialize PB7 function
	GPIOB->MODER &= ~GPIO_MODER_MODER6_Msk; // initialize PB6 function
	GPIOB->MODER &= ~GPIO_MODER_MODER3_Msk; // initialize PB3 function

	GPIOB->MODER |= (GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODER7_Pos); // set PB7 as GPIO for output
	GPIOB->MODER |= (GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODER6_Pos); // set PB6 as GPIO for output
	GPIOB->MODER |= (GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODER3_Pos); // set PB3 as GPIO for output

	GPIOB->ODR |= GPIO_ODR_7;	//ステッピングモータ励磁OFF

	GPIOB->ODR |= GPIO_ODR_3;	//モータの回転方向を設定
	GPIOB->ODR |= GPIO_ODR_6;	//モータの回転方向を設定

	//====PWM出力に使うタイマの設定====
	/*--------------------------------------------------------------------
		TIM16 : 16ビットタイマ。左モータの制御に使う。出力はTIM16_CH1(PB4)
	--------------------------------------------------------------------*/
	RCC->APB2ENR |= RCC_APB2ENR_TIM16EN; // Clock supply enable

	TIM16->CR1 = TIM_CR1_CEN;			//タイマ有効
	TIM16->CR2 = 0;
	TIM16->DIER = TIM_DIER_UIE;			//タイマ更新割り込みを有効に
	TIM16->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE;	//PWMモード1
	TIM16->CCER = TIM_CCER_CC1E;		//TIM16_CH1出力をアクティブHighに
	TIM16->BDTR = TIM_BDTR_MOE;			//PWM出力を有効に

	TIM16->CNT = 0;					//タイマカウンタ値を0にリセット
	TIM16->PSC = 63;				//タイマのクロック周波数をシステムクロック/64=1MHzに設定

	TIM16->EGR = TIM_EGR_UG;			//タイマ設定を反映させるためにタイマ更新イベントを起こす

	RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // IO portB clock enable

	// PB4 を Alternative Function に設定する
	GPIOB->MODER &= ~(1 << 8);
	GPIOB->MODER |= 1 << 9;
	// PB4 を AF1 に設定する
	GPIOB->AFR[0] |= (GPIO_AF1_TIM16 << GPIO_AFRL_AFRL4_Pos);

	/*--------------------------------------------------------------------
		TIM17 : 16ビットタイマ。右モータの制御に使う。出力はTIM17_CH1(PB5)
	--------------------------------------------------------------------*/
	RCC->APB2ENR |= RCC_APB2ENR_TIM17EN; // Clock supply enable

	TIM17->CR1 = TIM_CR1_CEN;			//タイマ有効
	TIM17->CR2 = 0;
	TIM17->DIER = TIM_DIER_UIE;			//タイマ更新割り込みを有効に
	TIM17->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE;	//PWMモード1
	TIM17->CCER = TIM_CCER_CC1E;		//TIM16_CH1出力をアクティブHighに
	TIM17->BDTR = TIM_BDTR_MOE;			//PWM出力を有効に

	TIM17->CNT = 0;					//タイマカウンタ値を0にリセット
	TIM17->PSC = 63;				//タイマのクロック周波数をシステムクロック/64=1MHzに設定

	TIM17->EGR = TIM_EGR_UG;			//タイマ設定を反映させるためにタイマ更新イベントを起こす

	RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // IO portB clock enable

	// PB5 を Alternative Function に設定する
	GPIOB->MODER &= ~(1 << 10);
	GPIOB->MODER |= 1 << 11;
	// PB5 を AF10 に設定する
	GPIOB->AFR[0] |= (GPIO_AF10_TIM17 << GPIO_AFRL_AFRL5_Pos);
}

発展

ステッピングモーターを2個別々に鳴らして二重奏しましょう。2個のモーターで同じ音を鳴らしていた先ほどよりも複雑になります。楽譜配列がモーター1用音階配列、モーター2用音階配列、待機時間配列、モーター1用処理配列、モーター2用処理配列の5つ必要だからです。

モーター1, 2が鳴っている(鳴)または鳴ってない(静)状態の組み合わせは(1, 2)=(静, 静), (鳴, 静), (静, 鳴), (鳴, 鳴)の4通りあります。ある状態がどれくらいの長さ続くかを格納した配列が待機時間配列です。この待機時間とはモーター1と2のどちらかで状態(鳴/静)が変化してから次に変化が起こるまでの時間です。ある状態から次の状態に移るときどういう命令をしてやればよいかを格納してある配列がモーター1, 2用処理配列です。ここで言っている処理とはある状態の始まりに行われる命令と終わりに行われる命令の組のことです。(始, 終)=(鳴らす, 消す), (鳴らす, そのまま), (そのまま, そのまま), (そのまま, 消す)の4通りあります。

これらを扱う関数を作ってください。この関数の名前を二重奏関数と呼ぶことにします。二重奏関数が呼び出されるとまずモーター1, 2用処理配列を見てモーター1, 2に別々の命令をします。待機時間分待機したらモーター1, 2に別々の命令をします。そして二重奏関数を抜けます。二重奏関数を実行している間は上記の4通りの状態のうちどれか一つにいることになります。そして再び二重奏関数を呼び出します。この繰り返しによって二重奏を実現します。

大変ですね。だからこの項目は発展にしたのです。一応状態遷移を示しておきます。この図は左から始まって時間が進み、右で終わる図です。各列が各状態を表し、時間が経過して次の列に移るたびに二重奏関数が呼び出されます。

二重奏状態遷移図

二重奏 状態遷移図

豆知識

ステッピングモーターを励磁させなくても小さな音が鳴ります。マイコンから出力されるパルス波の音だと思います。

2相励磁で音を鳴らしてみると1-2相励磁のときと比べて1オクターブ高い音が鳴りました。前のほうで示した励磁波形の図を見てください。1-2相励磁のパルス波の周期は2相励磁のパルス波の周期の2倍です。つまり2相励磁のパルス波の周波数は1-2相励磁のパルス波の周波数の2倍です。周波数が2倍になると、音が1オクターブ高くなるので2相励磁のときは1-2相励磁のときより1オクターブ高い音が鳴ります。

参考文献

[1]ステッピングモーターの概要 - ステッピングモーターとは|製品情報 |オリエンタルモーター株式会社、2019年2月7日閲覧

[2]ユニポーラ駆動とバイポーラ駆動、2019年2月7日閲覧

[3]ステッピングモータの駆動運転 - indexPro、2019年2月7日閲覧

[4]モータを廻す、2019年2月7日閲覧

[5]気圧計のバグつぶしと、ステッピングモーターの静音化: がた老AVR研究所、2019年2月7日閲覧

[6]音階と周波数の対応表、2019年2月7日閲覧

回せば文字が浮かび上がる!マウス型LEDライト

振ると文字が浮かび上がるLEDライト、ステッパマウス、高速回転。これらが頭の中で結びついたとき、「ステキなもの」ができました。このブログはその製作記録です。

はじめに

ステッパマウスをその場で高速回転させられる前提で話を進めます。

あと必要な技術はLチカだけです。

LEDを縦に5個並べてステッパマウスに取り付け、ステッパマウスを高速回転させながらLEDをちょうどいいタイミングで点滅させ、「HELLO WORLD ! 」という文字列を表示させます。

LED文字列予想図

LED文字列予想図

文字表示原理

LEDを5個使って文字を表示させる原理を、例として「H」を取り上げることで説明します。

以下では5個のLEDを上から順にLED1, LED2, LED3, LED4, LED5という番号で呼ぶことにします。また、文字を構成する点(LEDのパルス発光によるもの)をドットと呼ぶことにします。

次に示す原理説明図を見てください。これは各LEDが担当するドットの位置と発光タイミングを表しています。赤マルはドットでありLEDのパルス発光を表し、何もないマスはLEDが光ってないことを表しています。LEDxの行はLEDxが担当します(x=1,2,3,4,5)。ステッパマウスが左回転しているときにLED計5個を1列目、2列目、3列目、4列目、5列目の順にパルス発光させると、残像効果で人の目にはHと表示されているように見えます。

原理説明図

原理説明図

用意したもの

材料

ステッパマウス 1個

マイコン(とマイコンを使うために必要な電子部品たち) 1セット

片面ユニバーサル基板(穴数36×27) 2枚

スペーサー 数個

LED(5mm砲弾型、今回は赤色) 5個

保護抵抗1kΩ 5個

空中配線用の導線(ポリウレタン銅線または被覆線。場合によってはすずメッキ線)

アングル(TAMIYAのユニバーサルプレートLの付属品) 1個

養生テープ 少し

黒いビニールテープ 少し

熱収縮チューブ 少し

M3ボルト(ねじ部の長さは6mm以上) 3個

M3ナット 3個

道具

基板を切るために必要なもの(糸鋸など)

φ3.2の穴を開けるために必要なもの(ドリルビットと手回しドリル)

はんだ付けに必要なもの(はんだごてとはんだ)

ニッパー

工作

作業の流れ

LEDを縦に5個並べる基板(以降LED基板と呼びます。)の加工

LED5個を光らせるためのマイコンのための基板(以降第2基板と呼びます。(第1基板は元からマウスに付いている基板のことです。))の加工

LED基板と第2基板を固定するためのアングルの加工

第2基板にマイコンと書き込み回路と電源回路をはんだ付け

LED基板にLEDと抵抗をはんだ付け

LED基板と第2基板を固定

第2基板とLED基板を空中配線

余計な光を遮断

マウスに設置

作業の説明

LED基板加工

まず、LED基板を加工しました。穴数27×8の大きさで片面ユニバーサル基板を糸鋸で切り取ってφ3.2の穴を2つ開けました。穴の位置はランドの面がこちら側を向くようにして基板が縦長になるように見たとき、右下の穴から数えて上に5個目で左に2個目の穴と、右下の穴から数えて上に5個目で左に6個目の穴です。φ3.2のドリルビットを使って基板に元から開いている穴を広げました。この加工が終わると下図のようになります。

LED基板加工図

LED基板加工図
第2基板加工

次に第2基板を加工しました。第2基板が必要となった理由は、私のマウスに元から付いているマイコンだけだとピンが足りなかったので新たにマイコンを追加しなければならず、そのためのスペースが第1基板上にはなかったからです。第2基板をマウスに取り付けるために必要な加工をし、さらにφ3.2の穴を1つ開けました。この穴はLED基板と接続するためのものなので位置はどこでもいいですが、マウス本来の機能(迷路探索)の邪魔にならない位置にしました。(下図ではLED基板取り付け用の穴を開けただけの第2基板の様子を示します。)

第2基板加工図

第2基板加工図
アングル製作

次にLED基板と第2基板を固定するためのアングルを作りました。

TAMIYAのユニバーサルプレートLの付属品

TAMIYAのユニバーサルプレートLの付属品

TAMIYAのユニバーサルプレートLの付属品をニッパーで必要な大きさに小さく切り取りました。このアングルを使ってLED基板と第2基板を直交させた状態で互いに固定します。私はこんな感じに切り取りました。

アングル

アングル
第2基板はんだ付け

次に第2基板にマイコンと書き込み回路と電源回路をはんだ付けしました。第2基板上の電源スイッチとリセットボタンと書き込みピンを第2基板の端に配置し、その位置に対応する第1基板の一部を切り取りました。こうすることによって、あとで第1基板と第2基板を重ねてマウスに設置したときに第2基板を操作しやすくなります。下図は第2基板をマウスに取り付けたあとの写真で、上側の基板が第1基板、下側の基板が第2基板です。

第2基板操作部

第2基板操作部

もう1つ工夫した点は第1基板と第2基板のGNDと+3.3V電源を電気的に接続したところです。ピンソケットとピンヘッダを使いました。下図のように、第1基板の下側のピンソケットと第2基板の上側のピンヘッダが第1基板と第2基板を重ねたときにはまるような位置にはんだ付けしました。今回は7ピン分はんだ付けしましたが使っているのはGNDと+3.3V電源用の2ピンだけです。残りの5ピンは少なくとも今のところは使ってません。

基板間電気的接続

基板間電気的接続
LED基板回路

次にLED基板にLEDと抵抗をはんだ付けしました。以下に回路図と配線図を示します。回路図内のPIN1~PIN5はそれぞれマイコンの汎用入出力ピンを表しています。配線図内のLED基板の向きは上述したLED基板加工図とは反対で、ランドがある面がむこう側を向いていることに注意してください。

回路図

回路図

配線図

配線図
第2基板とLED基板の固定

次にLED基板と第2基板をアングルによって固定しました。ボルトとナットで固定すると下図のようになります。(このCAD画像では簡単のためにLEDなどの電子部品は省略してあります。)

LED基板と第2基板の固定

LED基板と第2基板の固定
第2基板とLED基板の電気的接続

次に第2基板上のマイコンのピンとLED基板上のLEDのアノードを空中配線し、さらに第2基板のGNDとLED基板のGNDを空中配線しました。実際に空中配線したところを撮った写真を示します。左がLED基板で右が第2基板です。銅色のポリウレタン銅線が第2基板からLEDのアノードにつながっていて、銀色のすずメッキ線が第2基板からLED基板のGNDにつながっているのが見えると思います。

空中配線図

空中配線図
遮光

次に不要な発光部分を隠しました。LEDの光で文字を表示させるわけですから、余計な光があっては困るからです。黒いビニールテープは使いやすいくて遮光性能が高いですが、ベトベトするのでそのまま使ったらマウスもベトベトしてしまいます。そこでマウスに養生テープを貼って、その上から黒いビニールテープを貼りました。LED基板の背面(LEDがない側)を黒いビニールテープで遮光しました。マウスに元から付いているLEDも邪魔なので隠しますが、完全に隠してしまったらマウスとして使うことができなくなってしまいます。そこで熱収縮チューブを使って遮光しました。こうすれば熱収縮チューブの開口部だけから光が漏れるので、マウス横方向からは光が見えないけれど上からみれば光が見えるという状況を作り出せます。その他の不要な発光部も隠しました。

黒いビニールテープで遮光

黒いビニールテープで遮光

LEDを熱収縮チューブで遮光

LEDを熱収縮チューブで遮光
第2基板をマウスに設置

最後に第2基板をマウスに取り付けました。これでハードは完成です。スペーサーを使って第1基板の下に重ねて設置しました。マウスの全体像を示します。写真右側の縦に長い基板がLED基板です。

回転LED文字列マウス

回転LED文字列マウス

プログラム

これから第2基板のマイコンに書き込むプログラムの説明をしていきます。第1基板用のプログラムの説明は省略します。C言語を使います。

待機マクロ

ここではLEDの発光時間待機と消灯時間待機をfor文の空ループで実現します。今回第2基板用に使ったマイコンはLPC1114FN28/102(偶然持ってたから)であり、その動作周波数は48[MHz]らしい(適当)です。ということは4800000を何倍かした回数だけループを回せば1秒間待機できます。試しに24000000回ループを回したら10秒間待機できました。つまり2クロックで1ループですね。私はまだ機械語を話せないのでなぜ2クロックなのかは分かりませんが、その理由を知らなくても今回のプログラムは書けました。

さて、この考え方を使って望みの時間待機するためのマクロを作ります。ループ回数は試行錯誤して決めました。このマクロについてはあとで説明します。

#define DOT_WIDTH_WAIT for(uint32_t i = 0; i < 2400; i++) // wait 1[ms]
#define INTERVAL_ADJUSTMENT for(uint32_t i = 0; i < 33600; i++) // wait 14[ms]
#define LETTER_SPACING_WAIT for(uint32_t i = 0; i < 24000; i++) // wait 10[ms]
#define SPACE_WIDTH_WAIT for(uint32_t i = 0; i < 204000; i++) // wait 85[ms]
#define EXCLAMATION_MARK_WAIT for(uint32_t i = 0; i < 120000; i++) // wait 50[ms]

LED点灯消灯関数

文字列を表示するためにはLED5個を別々に点灯・消灯できなければなりません。「HELLO WORLD !」という文字列を表示するためには次の15個の関数が必要です。これらをまとめてLED点灯消灯関数と呼ぶことにします。

void led00000();
void led00001();
void led00010();
void led00100();
void led00110();
void led01001();
void led01100();
void led01110();
void led10001();
void led10100();
void led10110();
void led10101();
void led11000();
void led11101();
void led11111();

例としてLEDを全部消灯させる関数led00000()と、LED5だけ点灯させる関数led00001()と、LED4だけ点灯させる関数led00010()について説明します。関数名に数字(0または1)が5個ありますが、それぞれ別のLEDを表しています。一番左の数字はLED1、左から2番目の数字はLED2、(略)という順に対応しています。数字の1は点灯、0は消灯を表します。

void led00000(){
	led1(OFF);
	led2(OFF);
	led3(OFF);
	led4(OFF);
	led5(OFF);
	DOT_WIDTH_WAIT;
}

void led00001() {
	led1(OFF);
	led2(OFF);
	led3(OFF);
	led4(OFF);
	led5(ON);
	DOT_WIDTH_WAIT;
	led00000();
}
void led00010() {
	led1(OFF);
	led2(OFF);
	led3(OFF);
	led4(ON);
	led5(OFF);
	DOT_WIDTH_WAIT;
	led00000();
}

一度光らせたあとに必ず全消灯しています。ledx()関数はLEDxを点灯・消灯する自作関数です(x=1,2,3,4,5)。

LED文字関数

次にLED点灯消灯関数を使って文字を表示させる関数を作りました。'H', 'E', 'L', 'O', 'W', 'D', '!'を表示する関数が必要です。これらをLED文字関数と呼ぶことにします。

void led_char_H() {
	led11111();
	led00100();
	led00100();
	led00100();
	led11111();
}
void led_char_E() {
	led11111();
	led10101();
	led10101();
	led10101();
	led10001();
}
void led_char_L() {
	led11111();
	led00001();
	led00001();
	led00001();
	led00001();
}
void led_char_O() {
	led01110();
	led10001();
	led10001();
	led10001();
	led01110();
}
void led_char_W() {
	led11000();
	led00110();
	led00001();
	led00010();
	led01100();
	led00010();
	led00001();
	led00110();
	led11000();
}
void led_char_R() {
	led11111();
	led10100();
	led10110();
	led10101();
	led01001();
}
void led_char_D() {
	led11111();
	led10001();
	led10001();
	led10001();
	led01110();
}
void led_char_exclamation_mark() {
	led11101();
}

LED文字列関数

次にLED文字関数を使って文字列を表示させる関数を作りました。この関数をLED文字列関数と呼ぶことにします。文字と文字の間に隙間がないと読みづらいのでスペースを挟みます(LETTER_SPACING_WAIT)。文字列のあとにもスペースをつけます(SPACE_WIDTH_WAIT)。文字列"HELLO"と"WORLD"の長さをそろえるためにもスペースをつけます(INTERVAL_ADJUSTMENT)。びっくりマーク'!'専用のスペースも使います(EXCLAMATION_MARK_WAIT)。

void led_str_HELLO() {
	led_char_H();
	LETTER_SPACING_WAIT;
	led_char_E();
	LETTER_SPACING_WAIT;
	led_char_L();
	LETTER_SPACING_WAIT;
	led_char_L();
	LETTER_SPACING_WAIT;
	led_char_O();
	INTERVAL_ADJUSTMENT;
	SPACE_WIDTH_WAIT;
}
void led_str_WORLD() {
	led_char_W();
	LETTER_SPACING_WAIT;
	led_char_O();
	LETTER_SPACING_WAIT;
	led_char_R();
	LETTER_SPACING_WAIT;
	led_char_L();
	LETTER_SPACING_WAIT;
	led_char_D();
	SPACE_WIDTH_WAIT;
}
void led_str_exclamation_marks() {
	led_char_exclamation_mark();
	EXCLAMATION_MARK_WAIT;
}

main()関数

main()関数を示します。init()関数のなかでLチカ用の初期設定を行います。次にマウスの回転が安定するまで待機します。そして文字列"HELLO"を表示します。少し待機したあとに文字列"WORLD"を表示します。少し待機したあとにびっくりマーク"! ! ! ! !"を表示し続けます。

int main(void) {

	init(); // setup for LEDs

	for(uint32_t i = 0; i < 12000000; i++); // wait 5[s]

	for(uint8_t i = 0; i < 20; i++) {
		led_str_HELLO();
	}

	for(uint32_t i = 0; i < 2400000; i++); // wait 1[s]

	for(uint8_t i = 0; i < 20; i++) {
		led_str_WORLD();
	}

	for(uint32_t i = 0; i < 2400000; i++); // wait 1[s]

	while(1) {
		led_str_exclamation_marks();
	}

	return 0 ;
}

調整

あと必要なのは根気だけです。2つのマイコン間で通信し合っていないため、自動でマウス回転速度とLED点滅間隔を調整することはできません。文字列が読み取れるようになるまでマウスの回転速度とLED点滅間隔を少しずつずらしながら地道に調整を繰り返すしか方法はありません。私はマウス回転速度を固定してLED点滅間隔を少しずつずらしていったのですが、始めのうちはLED点滅間隔が長すぎるのか短すぎるのかすら分からない状態でした。何度か試行錯誤を繰り返すうちにちょうどいいLED点滅間隔を見つけられました。

LED点滅間隔を調整するためには先ほど示した待機マクロを使います。待機マクロに使われているループ回数を少しずつ変更しながらちょうどいいループ回数を見つけました。ドットサイズを調節するためにはDOT_WIDTH_WAITを使います。INTERVAL_ADJUSTMENTはDOT_WIDTH_WAITの8倍の回数ループさせます(と、思いきや14倍がちょうどよかったです。意味不明。)。文字間隔LETTER_SPACING_WAITは自分が読みやすいと思う回数ループさせます。SPACE_WIDTH_WAITによって文字列が移動する速さを変えます。EXCLAMATION_MARK_WAITで'!'の数と移動する速さを変えます。

 当然ながら第1基板上のマイコン(マウス用)にはマウス用のプログラムを書きこみます。ただしその場高速回転プログラム付きですが。待機マクロを変更したら第2基板に書き込んで実験という動作を繰り返し、必要に応じてマウス回転速度を変更して第1基板に書き込んで実験しました。

動画

実際に動かしてみた様子を示します。この動画では右から左へ文字列"HELLO"が流れたあとに文字列"WORLD"が流れ、最後に"! ! ! ! ! !"と表示されます。

ラジペン代わりの平ヤットコ

お薦め工具を紹介します。

私は電子工作をするときにラジオペンチの代わりに平ヤットコを使っています。

平ヤットコ

平ヤットコ

平ヤットコは丸ヤットコとニッパーと合わせて手芸によく使われる道具です。見た目はラジオペンチに似ていますが、ラジオペンチと違って物をつかむ部分がギザギザしていないという特徴があります。

以前電子工作のためにラジオペンチを使っていたとき、ギザギザで電子部品などに傷が付いてしまうことに対して不満を抱いていました。何かもっといいラジオペンチがないか探しに東急ハンズを訪れ、偶然立ち寄った手芸コーナーで見つけたのがこの平ヤットコです。買ってみて、使ってみたら使いやすかったのでそれ以来ずっと使っています。ラジオペンチは物によりますが2000円くらいなのに対し、平ヤットコはだいたい500円くらいで買えてしまいます。安くて使いやすいので満足しています。

この平ヤットコには次のような利点があります。

  • 安い(約500円)
  • さびない
  • 先が細い
  • ちゃんとバネが付いてる
  • 物をつかむ部分がギザギザしてない

1年くらい前に買った物ですので今も(2019年2月25日現在)東急ハンズにあるのかネットで調べてみましたが、見つけられませんでした。今は取り扱ってないのかもしれません。

平ヤットコとは別に100均で売っているラジオペンチも使っていますが、先が太くてすぐさびます。電子工作に使えないわけではありませんがなんか微妙です。

2019.5.30追記

しばらく平ヤットコを使っていたらバネが取れやすくなってしまいました。

はずれたバネ

はずれたバネ

バネがはずれてなくなってしまうと困るので、糸で平ヤットコ本体に結びつけてみました。

糸でバネ紛失防止

糸でバネ紛失防止

バネを再び平ヤットコ本体にはめたら応急処置は完了です。

応急処置完了

応急処置完了


 

割り込み音楽

東京理科大MICEの方のクラシックマウスが走りながら曲を鳴らしているのを見て自分でもやってみたくなりました。演奏関連の処理のうち初期設定以外を全てタイマ割り込み関数内で行うことで実現しました。

注意

この記事はマイコンのクロック設定とPWM設定とタイマ割り込み設定ができる人向けです。だからそれらに関する説明はしません。

今回はSTM32F303C8T6という48ピンのマイコンを使って鳴らしました。他のマイコンのことは知りませんが基本的な考え方は同じだと思います。

プログラムにC言語とHALライブラリを使っています。

スピーカー

UGCT7525AN4というスピーカーを使いました。秋月電子で手に入り、表面実装でき、小さくてそこそこ大きい音が鳴るからです。しかし騒音が大きい場所では音がかき消されてしまうかもしれません。

表面実装用ダイナミックスピーカー UGCT7525AN4: パーツ一般 秋月電子通商-電子部品・ネット通販

データシートによるとこの図のように配線するといいみたいです。Vinをマイコンのピンにつなげます。今回はダイオードと抵抗とトランジスタは適当に買ったものを使いました。このダイオードはスピーカーに逆電圧がかからないようにするためにつけるみたいです。

スピーカ配線図

スピーカ配線図

プログラムの説明

音楽の教科書などに載っている楽譜には音の高さや長さ、テンポや強弱など、たくさん記号が書かれていますが、曲をプログラムする際には音の高さと長さ以外の情報を全て無視します。

PB9ピンからスピーカーに入力するパルス波が出力されます。

ここでは曲の例として「ド・レ・ミ・ファ・ソ・ラ・シ・休み」を繰り返すプログラムを示します。

楽譜

ドレミファソラシの音の周波数をネットなどで調べてマクロにします。このマクロの単位は[Hz]です。休符はRESTとし、適当な数字な数字を割り当てます。0にすると音の周波数と被らずに済みます。

#define DO 261.626
#define RE 293.665
#define MI 329.628
#define FA 349.228
#define SOL 391.995
#define LA 440.000
#define SI 493.883
#define REST 0

次に音の長さのマクロです。八分音符の長さをLEN8というマクロで表します。長さは適当に1000[ms]とします。

#define LEN8 1000 // 八分音符の長さ[ms]

楽譜を配列として表します。二元配列を使い、1行目に音の高さと休符、2行目に音の長さを格納します。

const float music[2][8] = {
		{DO, RE, MI, FA, SOL, LA, SI, REST},
		{LEN8, LEN8, LEN8, LEN8, LEN8, LEN8, LEN8, LEN8}
};

PWM

スピーカーに入力するパルス波をマイコンのPWM機能を使って生成します。今回はTIM17というクロックをPWM用に使います。CLK_FREQはタイマクロックの周波数という意味です。今回はタイマクロックの周波数を1[MHz]に設定するので1000000にします。パルス波の周期をタイマカウンタのカウント上限を指定することによって自由に変更するためにFREQ2PWMPERIOD(X)というマクロを使って音の周波数からカウント上限を計算します。このマクロで-1している理由は、タイマカウンタが0から数え始めるためそのままだと1カウント多くなってしまうからです。

#define CLK_FREQ 1000000
#define FREQ2PWMPERIOD(X) (int)(CLK_FREQ / (X) - 1)

タイマ割り込み

1[ms]ごとに関数を呼び出します。今回はTIM6というタイマを使い、TIM6_DAC1_IRQHandler()という関数をタイマ割り込みで呼び出します。この関数と、音の長さを1[ms]単位で計るsound_timerという変数と、楽譜配列のどの音符を鳴らしているかを示すnote_numという変数を使って演奏に必要な処理を行います。関数が呼び出されたとき、もし休符の最中でなければパルス波の周期を指定します。そしてその値のちょうど半分をコンペアマッチ用の値として使ってHIGHとLOWを反転させます。そうすると1周期の間のHIGHとLOWの時間は同じ長さになります。もし休符の最中であれば音が鳴らないようにします。関数が呼び出されたとき、もし指定した長さに音を鳴らし終わっていたらsound_timerを0にしてnote_numをインクリメントします。こうすることで次に関数が呼び出されたときに次の音を鳴らし始められます。関数が呼び出されたとき、もし楽譜配列の最後まで鳴らし終わっていたら再び楽譜配列の最初から鳴らし始めます。

uint16_t sound_timer = 0;
uint8_t note_num = 0;

void TIM6_DAC1_IRQHandler(void) {

	if( !(TIM6->SR & TIM_SR_UIF) ){
		return;
	}

	sound_timer++;
	if(music[0][note_num] != REST) {
		TIM17->ARR = FREQ2PWMPERIOD(music[0][note_num]);
		TIM17->CCR1 = TIM17->ARR / 2;
	}else{
		TIM17->CCR1 = 0;
	}
	if(sound_timer > music[1][note_num]) {
		sound_timer = 0;
		note_num++;
	}
	if(note_num == 8) {
		note_num = 0;
	}

	TIM6->SR &= ~TIM_SR_UIF;
}

 main関数

システムクロック設定とPWM設定とタイマ割り込み設定をして無限ループに入ります。演奏に必要な処理は全てタイマ割り込み関数内で行われるため、main関数が非常に簡潔になります。

int main(void) {
	init();
	while(1);
	return 0;
}

 

 

ソースコード

たとえ同じマイコンを使ったとしても開発環境が異なれば違うプログラムを書かなければいけないのでソースコードを丸ごと載せてもあまり参考にならないかもしれませんが一応載せておきます。コメントがぐちゃぐちゃと汚いですが、これは色々なブログなどからの寄せ集めだったり自分のメモだったりするからですね。PWMモード2を使っていますがこのコードだとモード1でも音は変わらないはずです。

2019.8.15追記 SW4STM32(開発環境)に最初からついてくるスタートアップファイル(?)を使うと、このコードをコンパイルできない可能性があります。参考にするだけにしてください。

#include "stm32f3xx.h"

#define DO 261.626
#define RE 293.665
#define MI 329.628
#define FA 349.228
#define SOL 391.995
#define LA 440.000
#define SI 493.883
#define REST 0

#define LEN8 1000 // 八分音符の長さ[ms]

#define CLK_FREQ 1000000
#define FREQ2PWMPERIOD(X) (int)(CLK_FREQ / (X)) - 1

const float music[2][8] = {
		{DO, RE, MI, FA, SOL, LA, SI, REST},
		{LEN8, LEN8, LEN8, LEN8, LEN8, LEN8, LEN8, LEN8}
};

uint16_t sound_timer = 0;
uint8_t note_num = 0;

void init();
void sysclk_init();
void speaker_pwm_init();
void interrupt_init();

void TIM6_DAC1_IRQHandler();

int main(void) {
	init();
	while(1);
	return 0;
}

void init() {
	sysclk_init();
	speaker_pwm_init();
	interrupt_init();
}

void sysclk_init() {
	RCC->CFGR |= RCC_CFGR_PLLSRC_HSI_DIV2; // PLL <== HSI/2 = 4MHz
	RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // APB1 = PLL / 2 = 32MHz
	//RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2 = PLL / 2 = 32MHz
	RCC->CFGR |= ( (16 - 1) << RCC_CFGR_PLLMUL_Pos); //sysclk = 64MHz
	FLASH->ACR |= FLASH_ACR_LATENCY_1; // flash access latency for 48 < HCLK <= 72. This statement must be placed immediately after PLL multiplication.
	RCC->CR |= RCC_CR_PLLON;
	while(!(RCC->CR & RCC_CR_PLLRDY)); // wait until PLL is ready
	RCC->CFGR |= RCC_CFGR_SW_PLL; // PLL as system clock
	while( (RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL ); // wait until PLL clock supply starts
	SystemCoreClockUpdate();
}

void speaker_pwm_init(void) {

	RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // IO portB clock enable

	// PB9 を Alternative Function に設定する
	GPIOB->MODER &= ~(1 << 18);
	GPIOB->MODER |= 1 << 19;
	// PB9 を AF1に設定する
	GPIOB->AFR[1] |= (GPIO_AF1_TIM17 << GPIO_AFRH_AFRH1_Pos);

	RCC->APB2ENR |= RCC_APB2ENR_TIM17EN; // Clock supply enable

	TIM17->CR1 = TIM_CR1_CEN;						//タイマ有効
	TIM17->CR2 = 0;
	TIM17->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 |
			TIM_CCMR1_OC1PE;	//PWMモード2,CH1
	TIM17->CCER = TIM_CCER_CC1E;		//TIM17_CH1出力有効
	TIM17->BDTR = TIM_BDTR_MOE;

	TIM17->CNT = 0;					//タイマカウンタ値を0にリセット
	TIM17->PSC = 64-1;					//タイマのクロック周波数をシステムクロック/64=1MHzに設定
	TIM17->ARR = 0;	//タイマカウンタの上限値。取り敢えず
	TIM17->CCR1 = 0;				//タイマカウンタの比較一致値
}

void interrupt_init(void) {

	RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // Clock supply enable
	TIM6->CR1 = TIM_CR1_CEN;		//タイマ有効
	TIM6->CR2 = 0;
	TIM6->DIER = TIM_DIER_UIE;		//タイマ更新割り込みを有効に
	TIM6->CNT = 0;					//タイマカウンタ値を0にリセット
	TIM6->PSC = 64-1;				//タイマのクロック周波数をシステムクロック/64=1MHzに設定
	TIM6->ARR = 1000-1;				//タイマカウンタの上限値。1000に設定。ゆえに1msごとに割り込み発生

	TIM6->EGR = TIM_EGR_UG;			//タイマ設定を反映させるためにタイマ更新イベントを起こす

	NVIC_EnableIRQ(TIM6_DAC1_IRQn);			//タイマ更新割り込みハンドラを有効に
	NVIC_SetPriority(TIM6_DAC1_IRQn, 1);	//タイマ更新割り込みの割り込み優先度を設定
}

void TIM6_DAC1_IRQHandler(void) {

	if( !(TIM6->SR & TIM_SR_UIF) ){
		return;
	}

	sound_timer++;
	if(music[0][note_num] != REST) {
		TIM17->ARR = FREQ2PWMPERIOD(music[0][note_num]);
		TIM17->CCR1 = TIM17->ARR / 2;
	}else{
		TIM17->CCR1 = 0;
	}
	if(sound_timer > music[1][note_num]) {
		sound_timer = 0;
		note_num++;
	}
	if(note_num == 8) {
		note_num = 0;
	}

	TIM6->SR &= ~TIM_SR_UIF;
}