妻の携帯電話を安いものに替える

投稿日:

 先週の日曜日、妻の携帯電話を安SIMとともに新調した。今日(6日後の土曜の昼)に届いた。ASUSの「ZenFone 4 Max (ZC520KL)」だ。

 SIMは加入しているプロバイダ「OCN」がサービスしている「モバイルONE」だ。マツコ・デラックスが宣伝しているアレである。

 これまでにも娘二人の携帯電話はキャリア純正からMVNOの安SIMに移行してきており、経験済みの事ではある。

 妻と一緒にさっそくセットアップを始める。この際、妻は常に傍に居させなければならぬ。パスワードなどのセットアップがあるからだ。

 用意するものは、前の電話で使っていたLINEやGmail、プロバイダのpopメールその他のアカウント、申し込んでおいた「MNP予約番号」、クレジットカードの番号、その他一切である。

 それらを手元においておき、箱をあけ、中に入っている紙を読み、全部を書いてある通りに進めれば、なんてことなく移行は終わりである。

 あとは妻に携帯電話を渡し、「しかるべくイジり倒して研究せよ」と言っておけば終了、である。特に気を付けることもない。

 購入した「ZenFone 4 Max (ZC520KL)」だが、気を付けておきたいことがある。スペック表の「無線LAN」の欄を見ると、

無線LAN IEEE802.11b/g/n (周波数帯域:2.4GHz)

……とあることだ。つまり「a/ac」がない、ということで、要するに、

「5GHzのWiFiが使えない」

……ということである。私も私の妻もこれで特段不便を感じるわけではないが、Bluetoothやご近所の無線LANとの干渉が気になる向き、また、(もっぱ)ら5GHzのWiFiを利用しておられる向きなどは、この点を把握しておいた方が良いかもしれない。

売れる

投稿日:

 普段通勤電車に乗っていて、周りの人を落ち着いて眺めると、この5、6年がところ、たいていの人は携帯電話(スマホ)をいじっている。

 その前は大人のくせに任天堂に没頭している人が多かったが、いまやゲーム専用機を電車に持ち込んでいる大人はほとんどいない。皆携帯電話(スマホ)収斂(しゅうれん)した。

 悪趣味との謗りを御免(こうむ)って、人々の手許(てもと)を覗き込むと、字を読み書きしている人はほとんどいない。大体皆、色とりどりの画面でゲームをしている。最近はメールを書いている人もあまり見かけない。(もっぱ)らゲームであって、たまに字を書いているなと思ったら、LINEでスタンプを打ち合っている。

 してみると、もはや文字を書く人は儲からない。文字を読み書きする人は頑固なもので、デジタルに辟易して紙に回帰しているようだ。

 パソコンやゲーム専用機のゲームは数学で作られているが、携帯電話のゲームはまだまだ絵と論理で作られているように思う。使用できるマシンリソースが少ないからだろう。

 そうすると、まだまだ、絵を動かし、効果を派手にし、イベント毎に音を鳴らし、「当たり判定」なんていう地味な処理を書く人が食っていける理屈もあるように思う。(ただ)し、日本国内ではダメなのだろう。もはや中国も高価だ。食える場所は更に辺縁に広がっているのだろう。

引用の仕方とblockquote

投稿日:

 このブログはよく「引用」をしている。

 「引用」は著作権法第32条で認められており、れっきとした「法定コピペ」であるが、当然のことながら原文をコピペしておけばそれでいいというものではない。約束事が決まっているのだ。それは著作権法の条文にある「公正な慣行」にあたるもので、いろいろと作法がある。引用箇所がはっきりわかるようにカッコ書きや引用符などの約物(やくもの)(くく)ることや、出典、またそのページなどを明記すること、引用した分量に妥当性があることなどだ。争いごとにしたくなければ、それらをきちんと守ることだ。

 これまでにもこうした引用の作法を意識して守ってきたつもりなのだが、それに加えて、先日ふと学んだことがある。ウェブやブログについて書かれたサイトなどを見ていたところ、

「引用をするときは、ネットの場合、『blockquote』タグで括らないと、たとえば検索エンジンなどがその部分を引用と見なさず、他人が検索した時の要約文などに引用が引用として扱われずに転載されることなどにつながり、疑義を生じることになるから、引用箇所は見た目に判るようにする以外に、広義のセマンティックとして『blockquote』で括ることを励行すべきである」

……というような記事を見つけたのだ。

 これはなるほど、そのとおりだなあ、と思った。

 さっそくそのようにしようとしたのだが、ただ、WordPressのデフォルトのblockquoteのスタイルシートが気に入らない。あほのように大きい引用符、色・スタイル・ウェイトのどれをとっても読みづらい変なフォントなど、全部が嫌だ。

 そこで、「子テーマ」で「blockquote」を全部定義し直す。定義しなおしたこのブログの今の子テーマのスタイルシートが以下である。

blockquote {
	border: 2px solid #000000;
	color: #000000;
	font-size: 13px;
	font-size: 1rem;
	font-style: normal;
	line-height: 1.75;
	margin: 1em 0em 1em 2em !important;
	padding: 0.25em 1em 0.25em 1em !important;
}

 この時、少々コツがあった。マージンやパディング、ボーダーについて、後で読み込まれるスタイルがどうもあるようだ。ウェブは仕様として「後から読み込まれるスタイルが優先」ということがあるので、このままだと自分の思ったスタイルにならない。

 そこで、「!importantルール」というものを使う。上のスタイルシートの、下から2行分、プロパティの最後に「!important」という付け足しのあるのがそれである。こうすると、後から読み込まれる別のファイルのcssにかかわりなくこの設定になる。

 今までの「div」で見た目だけ整えていたやり方は下の通りだ。

 例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文

 これは、

<div style="margin-left:2em;border:solid 2px;padding:1em;"> 例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文</div>

……と、単に書いていただけだ。引用としての意味づけはしていない。

 これに対して、今回新しく定義したのが以下だ。

 例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文

<blockquote> 例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文例文</blockquote>

 見た目は全く変わらないが、これならブログ記事のソースもあっさりとして読みやすくなり、書きやすい。

 いずれにせよ、以前に書いた記事の「引用部分」を、できる限りこの「blockquote」で置き換えておかなければならない。

iPhone SE

投稿日:

 長女が高校に入学したとき、褒美にスマート・フォンを買い与えた。ガチガチにキャリアの純正回線で、結構高くついてきていた。

 長女はこのスマホを使いに使い倒したので、傷んでボロボロになってしまった。USBのコネクタなどもう「スカスカ」で、もはやPCに接続ができないどころか充電さえする(あた)わざる状況である。長女は充電ドックを使ってなんとかしのいでいる。

 そんな折、長女は先日19歳の誕生日を迎えた。「お父さん誕生プレゼントにスマホ新しくしてよ~」と言う。美大に通っているので、パソコンなども「Appleでないと話にならない」ほどの事らしく、学校のパソコンもほぼApple一色だそうな。

 そのせいで、「iPhone買って~」と言うのだった。

 うーん、高くつくなあ。

 機種変更だと、どうしたってキャリアのiPhoneを買わなければならず、ずいぶん高い。

 そこで、意を決し、長女の携帯電話は

  1.  本体はAppleストアでSIMフリーのiPhoneを直接買う。
  2.  キャリア(NTTドコモ)の回線は解約。
  3.  長女の回線はMVNOに変えてしまう。MNPで電話番号を移行。

 ……という、最近はやりの3点セットで買い替えることにした。

 MVNOはマツコデラックスの宣伝でおなじみ、「OCN モバイル ONE」を選ぶ。実は既に次女のスマホはそうしており、スピードや品質、商品の継続性もいいと思うからだ。

 iPhone SEを選び、Appleストアで注文した。同時に、「OCN モバイル ONE」も注文。音声回線付きで月々1600円ほどであり、今までの高額なキャリア回線が馬鹿々々しくなってしまう。

 これまでのように「壊れてしまいました」というようなときに、とりあえず近所のドコモショップへ持っていけば何とかなる、というふうにはいかなくなったが、しかし、そんなの、iPhoneであればAppleストアに送るなり持ち込むなりすればどうにかなる理屈だ。

 プッシュのキャリアメールが使えなくなるのはどうも不便なような気もするが、長女はLINEユーザで、特にそれで不便もないようだから、それでよし、となる。大学関係で使っているメールもGmailを主に使っており、まったく問題がない。

 私も同じようにMVNOに乗り換えて安くしたいが、それをやってしまうと、職場の連絡にLINEとかFBを使うことになってしまう。さすがにそういうわけにはいきかねる。キャリアのメールでないと具合が悪いのだ。それで、私は長女と同じようにはできない。

img_4862 そういう風にして昨日注文したiPhone SEだが、もう今日届くという素早さだ。誕生日プレゼントにするにはどうにも味もそっけもない段ボール箱で届いたので、何か適当な包み紙は、と探すが、ない。ふと棚を見ると、昨年仕事でアメリカへ行った時の古新聞があったから、それで包んでやる。そしたら、表面に来たのが偶然iPhoneの新製品発売を報じるApple関係の記事で、ちょうどよい。

回帰分析の語源

投稿日:

 ニフティのギャグ満載ポータル「デイリーポータルZ」の、13年ほど前の記事によれば──って、13年前って言うと、インターネット界隈では老舗中の老舗だわな。だって、その頃、Facebookなんて影も形もなかったんだから──、「単に『エクセルでまとめる』に過ぎないことを、妙にビジネスっぽく言って韜晦(とうかい)すると、『回帰分析』という言葉になる」のだそうだが、まあ、そこまで回帰分析と言う手法をこき下ろすこともあるまい。

 で、あらためてこの「回帰分析」とは何かと言うと、これは、一般的には最小自乗法などを使って離散事象の傾向を数理化して把握し、今後の予測などに役立てると言うもので、経営科学の基本中の基本である。

 ところが、なぜこのメソッドに「回帰」──まわって、かえってくる──という言葉を当てるのか、誰に聞いてもわからない。最小自乗で近似式を作る、つまりこれが「仮説」であるが、この仮説を相関係数などで評価して「仮説検証」するのが、手っ取り早く言った「回帰分析」である。だが、このように説明したところで、何が「まわって、かえってくる」なのだか、よくわからない。

 そんな疑問を(くすぶ)らせつつ日々を送っていたのだが、ある日突然、この語源を知ることとなった。感ずるところが大きいので、ここに書き留めておきたい。

 左掲の本によれば、「回帰分析」の語源は罪深い。なんとなれば、それが優生学の分野から生まれたからである。

 この本によると、ダーウィン(C.R.Darwin, 1809-1882)の弟子ゴルトン(F.Galton, 1822-1911)は、優生学の分野に数学的手法を導入しようとした。それは、「子の背の高さは親の背の高さに関係があるはず」という着想によっていた。これは、直観的には正しく、長身の親に長身の子がある例、またその逆の例も、世間にはよく見かけることだからだ。ゴルトンは、これを数理的に整理しようとした。

 まずゴルトンは親子の身長のデータを幾千も集めた。そして、親の背の高さをx軸に、子の背の高さをy軸にとって散布図を描いた。

回帰の語源 ゴルトンは、背の高い親からは親と同じくらい背の高い子が生まれると考えた。また、逆に背の低い場合もそうだろう、と考えた。ところが、「平均」のため、背が高いはずである場合には「平均」のほう、すなわち背の低い方へ向かって値が「帰って」いき、また、背が低いはずである場合にも「平均」のほう、すなわち背の高い方へ向かって値が「帰って」いった。

 値がある傾向へ帰っていくことから、ゴルトンはこのグラフに引いた直線を「そこへ帰ってくる直線」ということで、「回帰直線 regression line」と名付けたのであった。

 これが、「回帰分析 regression analysis」という言葉の由来である。

 ここには、「この親にしてこの子あり」という遺伝学的、優生学的なものへの信仰にも近い思い込みが、数理的に、つまり自然によって、ひいては神仏によって(ただ)され、学者がそれに深い感動と畏敬を覚えた、という一つのドラマが見て取れる。

そうか、PHPでもモノにつながるな

投稿日:

raspi_index Raspberry Piは要するにLinuxマシンなので、ウェブサーバも選り取り見取りだ。単にウェブインターフェイスを備えたモノのプロトをするならArduinoのほうが手っ取り早いが、いかんせん、リッチなウェブ・コンテンツをArduino+ETHERNET SHIELD 2でサービスするのは難しく、不可能ではないにもせよ、ウェブ・コンテンツに写真を置くなどというのはほとんど無理であった。

 Raspberry Piはコンピュータ・パワーが大きいから、大きなウェブ・コンテンツも本体内に飲み込んでしまえる。

 そこで、である。Raspberry Piで遊ぶのに、なにも世間の教科書通りにPythonやRubyの作例を打ち込むだけが能ではない。CだってC++だって、PerlだってPHPだって動くはずである。SMTPもPOPもNTPも、なんだって動く。多分MySQLだのPostgreSQLだのも動くだろう。

 Apacheをインストールして動かしてみよう。それから、PHPでGPIOを突っついてみよう。これは、PHPでハードウェアを動かすことにつながる。無駄に贅沢なWebインターフェイスでLチカ、というのも面白い。

Apacheのインストールに先立ち、今動いているサービスを確かめよう

 まず、今起動しているモノを確認してみよう。RedHat系のLinux、Fedoraなどはこういう時に「chkconfig –list」などとするが、Raspberry Piに入っているのは「Raspbian」だ。RaspbianはDebian系のディストリビューションなので、chkconfigはない。

 私はUNIX育ちのオッサンで、SVR4.2の管理人を長年やっきた。Linuxに関してはフリー時代のRedHat(4~9ぐらいまで)、それ以降はずっとFedora Coreを使ってきたので、Debianは良く知らないのである。ま、これも機会だから、ちょっと体験してみようではないの。

 ネット情報によると「insserv」「update-rc.d」「sysv-rc-conf」「rcconf」「upstart」などがあるという。

# insserv -s
K:01:0 1 6:triggerhappy
K:07:0 6:umountfs
K:04:0 6:umountnfs.sh
K:02:0 6:sendsigs
K:01:0 6:plymouth
K:03:0 1 6:rsyslog
K:06:0 6 S:hwclock.sh
K:01:0 1 6:alsa-utils
K:06:0 6:networking
K:05:0 1 2 3 4 5 6 S:rpcbind
K:05:0 1 2 3 4 5 6 S:nfs-common
K:01:0 6:urandom
K:01:0 1 6:avahi-daemon
K:01:0 1 6:dhcpcd
K:01:0 1 6:cgroup-bin
K:08:0 6:umountroot
K:09:0:halt
K:09:6:reboot
K:01:0 1 6:fake-hwclock
K:01:0 1 2 6:lightdm
K:01:0 1 6:ifplugd
S:02:S:udev
S:03:S:keyboard-setup
S:15:S:console-setup
S:01:2 3 4 5:triggerhappy
S:08:S:mountall.sh
S:09:S:mountall-bootclean.sh
S:12:S:mountnfs.sh
S:13:S:mountnfs-bootclean.sh
S:04:2 3 4 5:plymouth
S:01:2 3 4 5:rsyslog
S:16:S:alsa-utils
S:11:S:networking
S:10:S:urandom
S:04:S:mountdevsubfs.sh
S:05:S:checkroot.sh
S:03:2 3 4 5:avahi-daemon
S:02:2 3 4 5:dbus
S:01:2 3 4 5:dhcpcd
S:01:2 3 4 5:cgroup-bin
S:01:S:mountkernfs.sh
S:01:S:fake-hwclock
S:03:3 4 5:lightdm
S:16:S:x11-common
S:14:S:kbd
S:01:2 3 4 5:ifplugd
S:02:1:single
S:01:1:killprocs
S:01:1 2 3 4 5:bootlogs
S:01:S:hostname.sh
S:01:1 2 3 4 5:motd
S:02:2 3 4 5:dphys-swapfile
S:04:2 3 4 5:rc.local
S:04:2 3 4 5:rmnologin
S:02:2 3 4 5:cron
S:02:2 3 4 5:rsync
S:02:2 3 4 5:ssh
S:02:2 3 4 5:ntp
S:01:2 3 4 5:sudo
S:16:S:raspi-config
S:10:S:udev-mtab
S:06:S:checkroot-bootclean.sh
S:16:S:bootmisc.sh
S:06:S:kmod
S:16:S:plymouth-log
S:07:S:checkfs.sh
S:06:S:mtab.sh
S:10:S:procps

 ほほー、なるほど、コレは多分、左から現状(StartかKillか)、起動順、起動すべきRun-Levelのリスト、サービス名、だろうなあ。はて、S、Kじゃないほうの、Run-Levelの「S」は、なんだろ、と調べると、「起動順で一番はじめ、かつ、どのRun-Levelでも共通で起動」ということのようである。

 で、

# insserv -s | egrep '(pache)|(ttp)'
#

 なんてことをやっても、全然何も出ないから、デフォルトのRaspbianではhttpらしきものやApacheらしきものは何も動いていない。

Apacheをインストール

 それでは、というわけで、

# apt-get -s install apache2
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の特別パッケージがインストールされます:
  apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1 libaprutil1
  libaprutil1-dbd-sqlite3 libaprutil1-ldap ssl-cert
提案パッケージ:
  apache2-doc apache2-suexec apache2-suexec-custom openssl-blacklist
以下のパッケージが新たにインストールされます:
  apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap ssl-cert
アップグレード: 0 個、新規インストール: 10 個、削除: 0 個、保留: 0 個。
Inst libapr1 (1.4.6-3+deb7u1 Raspbian:7.0/oldstable [armhf])
Inst libaprutil1 (1.4.1-3 Raspbian:7.0/oldstable [armhf])
Inst libaprutil1-dbd-sqlite3 (1.4.1-3 Raspbian:7.0/oldstable [armhf])
Inst libaprutil1-ldap (1.4.1-3 Raspbian:7.0/oldstable [armhf])
Inst apache2.2-bin (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Inst apache2-utils (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Inst apache2.2-common (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Inst apache2-mpm-worker (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Inst apache2 (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Inst ssl-cert (1.0.32 Raspbian:7.0/oldstable [all])
Conf libapr1 (1.4.6-3+deb7u1 Raspbian:7.0/oldstable [armhf])
Conf libaprutil1 (1.4.1-3 Raspbian:7.0/oldstable [armhf])
Conf libaprutil1-dbd-sqlite3 (1.4.1-3 Raspbian:7.0/oldstable [armhf])
Conf libaprutil1-ldap (1.4.1-3 Raspbian:7.0/oldstable [armhf])
Conf apache2.2-bin (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Conf apache2-utils (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Conf apache2.2-common (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Conf apache2-mpm-worker (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Conf apache2 (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Conf ssl-cert (1.0.32 Raspbian:7.0/oldstable [all])
#

 特に問題なさそうだな、というわけで……

# apt-get install apache2
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の特別パッケージがインストールされます:
  apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1 libaprutil1
  libaprutil1-dbd-sqlite3 libaprutil1-ldap ssl-cert
提案パッケージ:
  apache2-doc apache2-suexec apache2-suexec-custom openssl-blacklist
以下のパッケージが新たにインストールされます:
  apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap ssl-cert
アップグレード: 0 個、新規インストール: 10 個、削除: 0 個、保留: 0 個。
1,356 kB のアーカイブを取得する必要があります。
この操作後に追加で 4,585 kB のディスク容量が消費されます。
続行しますか [Y/n]? y
取得:1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libapr1 armhf 1.4.6-3+deb7u1 [90.9 kB]
取得:2 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libaprutil1 armhf 1.4.1-3 [77.1 kB]
取得:3 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libaprutil1-dbd-sqlite3 armhf 1.4.1-3 [17.2 kB]
取得:4 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libaprutil1-ldap armhf 1.4.1-3 [16.0 kB]
取得:5 http://mirrordirector.raspbian.org/raspbian/ wheezy/main apache2.2-bin armhf 2.2.22-13+deb7u6 [676 kB]
取得:6 http://mirrordirector.raspbian.org/raspbian/ wheezy/main apache2-utils armhf 2.2.22-13+deb7u6 [163 kB]
取得:7 http://mirrordirector.raspbian.org/raspbian/ wheezy/main apache2.2-common armhf 2.2.22-13+deb7u6 [292 kB]
取得:8 http://mirrordirector.raspbian.org/raspbian/ wheezy/main apache2-mpm-worker armhf 2.2.22-13+deb7u6 [2,238 B]
取得:9 http://mirrordirector.raspbian.org/raspbian/ wheezy/main apache2 armhf 2.2.22-13+deb7u6 [1,440 B]
取得:10 http://mirrordirector.raspbian.org/raspbian/ wheezy/main ssl-cert all 1.0.32 [19.5 kB]
1,356 kB を 4秒 で取得しました (281 kB/s)
パッケージを事前設定しています ...
以前に未選択のパッケージ libapr1 を選択しています。
(データベースを読み込んでいます ... 現在 78616 個のファイルとディレクトリがインストールされています。)
(.../libapr1_1.4.6-3+deb7u1_armhf.deb から) libapr1 を展開しています...
以前に未選択のパッケージ libaprutil1 を選択しています。
(.../libaprutil1_1.4.1-3_armhf.deb から) libaprutil1 を展開しています...
以前に未選択のパッケージ libaprutil1-dbd-sqlite3 を選択しています。
(.../libaprutil1-dbd-sqlite3_1.4.1-3_armhf.deb から) libaprutil1-dbd-sqlite3 を展開しています...
以前に未選択のパッケージ libaprutil1-ldap を選択しています。
(.../libaprutil1-ldap_1.4.1-3_armhf.deb から) libaprutil1-ldap を展開しています...
以前に未選択のパッケージ apache2.2-bin を選択しています。
(.../apache2.2-bin_2.2.22-13+deb7u6_armhf.deb から) apache2.2-bin を展開しています...
以前に未選択のパッケージ apache2-utils を選択しています。
(.../apache2-utils_2.2.22-13+deb7u6_armhf.deb から) apache2-utils を展開しています...
以前に未選択のパッケージ apache2.2-common を選択しています。
(.../apache2.2-common_2.2.22-13+deb7u6_armhf.deb から) apache2.2-common を展開しています...
以前に未選択のパッケージ apache2-mpm-worker を選択しています。
(.../apache2-mpm-worker_2.2.22-13+deb7u6_armhf.deb から) apache2-mpm-worker を展開していま す...
以前に未選択のパッケージ apache2 を選択しています。
(.../apache2_2.2.22-13+deb7u6_armhf.deb から) apache2 を展開しています...
以前に未選択のパッケージ ssl-cert を選択しています。
(.../ssl-cert_1.0.32_all.deb から) ssl-cert を展開しています...
man-db のトリガを処理しています ...
libapr1 (1.4.6-3+deb7u1) を設定しています ...
libaprutil1 (1.4.1-3) を設定しています ...
libaprutil1-dbd-sqlite3 (1.4.1-3) を設定しています ...
libaprutil1-ldap (1.4.1-3) を設定しています ...
apache2.2-bin (2.2.22-13+deb7u6) を設定しています ...
apache2-utils (2.2.22-13+deb7u6) を設定しています ...
apache2.2-common (2.2.22-13+deb7u6) を設定しています ...
Enabling site default.
Enabling module alias.
Enabling module autoindex.
Enabling module dir.
Enabling module env.
Enabling module mime.
Enabling module negotiation.
Enabling module setenvif.
Enabling module status.
Enabling module auth_basic.
Enabling module deflate.
Enabling module authz_default.
Enabling module authz_user.
Enabling module authz_groupfile.
Enabling module authn_file.
Enabling module authz_host.
Enabling module reqtimeout.
apache2-mpm-worker (2.2.22-13+deb7u6) を設定しています ...
[....] Starting web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
. ok
apache2 (2.2.22-13+deb7u6) を設定しています ...
ssl-cert (1.0.32) を設定しています ...
#

 なんてことなく終わる。

Apacheの起動状況を確かめる

 次に、

# insserv -s | egrep '(pache)|(ttp)'
K:01:0 1 6:apache2
S:02:2 3 4 5:apache2
#

……ぬぅ、StartなのかKillなのか、どっちやねん、というわけで、ブラウザにアドレスを入れてみると、

raspi-apache2start

……と、普通にApacheは動いている。KとS両方出るのは、起動順が01、02となっていることから、Run-Level 0、1、6ではどうあろうと強制終了し、改めて2、3、4、5では起動、ということであろうか。

 えーっと、自動起動のほうはこれでいいから、サービスの起動停止のテストは……、と。

# /etc/init.d/apache2 stop
[....] Stopping web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
[ ok waiting ..
root@satoraspi:~# /etc/init.d/apache2 start
[....] Starting web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
. ok
#

 ふむ、だいだい動いとる。

ドキュメントルートのindex.htmlを作る

 とりあえず、indexだけ、かっこよくしておこう。えーっと、ドキュメントルートはどこかいな、と。

# ls -Fla /etc/ | egrep '(http)|(apache)'
drwxr-xr-x   7 root root    4096  8月 30 09:01 apache2/
root@satoraspi:~# ls /etc/apache2
apache2.conf  envvars  mods-available  ports.conf       sites-enabled
conf.d        magic    mods-enabled    sites-available
# cd /etc/apache2
# grep 'DocumentRoot' */*
sites-available/default:        DocumentRoot /var/www
sites-available/default-ssl:    DocumentRoot /var/www
sites-enabled/000-default:      DocumentRoot /var/www

 ……と、いうわけで普通に「/var/www」の下じゃのう。普通のユーザに戻って、

toshio@satoraspi:~$ cd /var/www
toshio@satoraspi:/var/www$ ls -Fla
合計 12
drwxr-xr-x  2 root root 4096  8月 30 09:01 ./
drwxr-xr-x 12 root root 4096  8月 30 09:01 ../
-rw-r--r--  1 root root  177  8月 30 09:01 index.html
toshio@satoraspi:/var/www$ cat index.html
<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>toshio@satoraspi:/var/www$

 はあ、さっきブラウザに出てたヤツでんな、と。

 一応残しておいて……

toshio@satoraspi:/var/www$ sudo cp index.html .index.html.ORG
[sudo] password for toshio:
toshio@satoraspi:/var/www$ sudo chown toshio:pi index.html
toshio@satoraspi:/var/www$ ls -Fla
合計 16
drwxr-xr-x  2 root   root 4096  8月 30 09:37 ./
drwxr-xr-x 12 root   root 4096  8月 30 09:01 ../
-rw-r--r--  1 root   root  177  8月 30 09:37 .index.html.ORG
-rw-r--r--  1 toshio pi    177  8月 30 09:01 index.html
toshio@satoraspi:/var/www$cd ..
toshio@satoraspi:/var$sudo chown toshio:pi www
toshio@satoraspi:/var$cd www
toshio@satoraspi:/var/www$vi index.html

 んで、ばーっ、って、書くですよ。

<html>
 <head>
  <meta name="Editor" content="vim">
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <link rel="icon" href="favicon.ico" type="image/x-icon" />
  <link rel="Shortcut Icon" type="image/x-icon" href="favicon.ico" />
  <title>おっさん用Raspberry Pi 2 Model B</title>
  <meta http-equiv="Keyword" content="佐藤俊夫, 佐藤, 俊夫, SATOTOSHIO, SatoToshio, sato, toshio, Raspberry Pi, Raspberry Pi 2 Model B">
 </head>
 <body bgcolor="#888888">
  <basefont size=4">
  <center>
  <table>
  <tr>
  <td>
    <h1>おっさん用Raspberry Pi 2 Model B</h1>
    <hr>
    <center><img src="raspberry_pi.png"></center>
  </td>
  </tr>
  <tr>
  <td>
    とりあえずまだ何もない。
  </td>
  </tr>
 </table>
 </center>
 </body>
</html>

 んで、画像なんかをSCPでコピーして、まずはこんなindex.htmlですな。

raspi_index

 それにしても、こんな、5千円かそこらのシングルボードでapache2のウェブサービスができるなんて、隔世の感があるな。

同じようにして、PHPをインストール

 さておき、続いてPHPを入れよう。

toshio@satoraspi:/var/www$ cd
toshio@satoraspi:~$ su -
パスワード:
root@satoraspi:~# apt-cache search php5
dwoo - PHP5 template engine
libapache2-mod-php5 - server-side, HTML-embedded scripting language (Apache 2 module)
libapache2-mod-php5filter - server-side, HTML-embedded scripting language (apache 2 filter module)
libexpect-php5 - expect module for PHP 5
libgv-php5 - PHP5 bindings for graphviz
libkohana2-modules-php - lightweight PHP5 MVC framework (extension modules)
libkohana2-php - lightweight PHP5 MVC framework
libkohana3.1-core-php - PHP5 framework core classes
libkohana3.1-php - PHP5 framework metapackage
libkohana3.2-core-php - PHP5 framework core classes
libkohana3.2-php - PHP5 framework metapackage
libow-php5 - Dallas 1-wire support: PHP5 bindings
libphp-jpgraph - Object oriented graph library for php5
libphp-jpgraph-examples - Object oriented graph library for php5 (examples)
libphp5-embed - HTML-embedded scripting language (Embedded SAPI library)
php-doc - Documentation for PHP5
php-imlib - PHP Imlib2 Extension
php5 - server-side, HTML-embedded scripting language (metapackage)
php5-adodb - Extension optimising the ADOdb database abstraction library
php5-cgi - server-side, HTML-embedded scripting language (CGI binary)
php5-cli - command-line interpreter for the php5 scripting language
php5-common - Common files for packages built from the php5 source
php5-curl - CURL module for php5
php5-dbg - Debug symbols for PHP5
php5-dev - Files for PHP5 module development
php5-enchant - Enchant module for php5
php5-exactimage - fast image manipulation library (PHP bindings)
php5-ffmpeg - audio and video support via ffmpeg for php5
php5-fpm - server-side, HTML-embedded scripting language (FPM-CGI binary)
php5-gd - GD module for php5
php5-gdcm - Grassroots DICOM PHP5 bindings
php5-geoip - GeoIP module for php5
php5-gmp - GMP module for php5
php5-imagick - ImageMagick module for php5
php5-imap - IMAP module for php5
php5-interbase - interbase/firebird module for php5
php5-intl - internationalisation module for php5
php5-lasso - Library for Liberty Alliance and SAML protocols - PHP 5 bindings
php5-ldap - LDAP module for php5
php5-librdf - PHP5 language bindings for the Redland RDF library
php5-mapscript - php5-cgi module for MapServer
php5-mcrypt - MCrypt module for php5
php5-memcache - memcache extension module for PHP5
php5-memcached - memcached extension module for PHP5, uses libmemcached
php5-midgard2 - Midgard2 Content Repository - PHP5 language bindings and module
php5-ming - Ming module for php5
php5-mysql - MySQL module for php5
php5-mysqlnd - MySQL module for php5 (Native Driver)
php5-odbc - ODBC module for php5
php5-pgsql - PostgreSQL module for php5
php5-ps - ps module for PHP 5
php5-pspell - pspell module for php5
php5-radius - PECL radius module for PHP 5
php5-recode - recode module for php5
php5-remctl - PECL module for Kerberos-authenticated command execution
php5-rrd - rrd module for PHP 5
php5-sasl - Cyrus SASL extension for PHP 5
php5-snmp - SNMP module for php5
php5-sqlite - SQLite module for php5
php5-svn - PHP Bindings for the Subversion Revision control system
php5-sybase - Sybase / MS SQL Server module for php5
php5-tidy - tidy module for php5
php5-tokyo-tyrant - PHP interface to Tokyo Cabinet's network interface, Tokyo Tyrant
php5-vtkgdcm - Grassroots DICOM VTK PHP bindings
php5-xcache - Fast, stable PHP opcode cacher
php5-xdebug - Xdebug Module for PHP 5
php5-xmlrpc - XML-RPC module for php5
php5-xsl - XSL module for php5
phpunit - Unit testing suite for PHP5
root@satoraspi:~#

 はあ、いっぱい出たけど、要するにPHP5があるんだよな。うん、うん。

root@satoraspi:~# apt-get -s install php5
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の特別パッケージがインストールされます:
  apache2-mpm-prefork libapache2-mod-php5 libonig2 libqdbm14 lsof php5-cli php5-common
提案パッケージ:
  php-pear
以下のパッケージは「削除」されます:
  apache2-mpm-worker
以下のパッケージが新たにインストールされます:
  apache2-mpm-prefork libapache2-mod-php5 libonig2 libqdbm14 lsof php5 php5-cli
  php5-common
アップグレード: 0 個、新規インストール: 8 個、削除: 1 個、保留: 0 個。
Remv apache2-mpm-worker [2.2.22-13+deb7u6] [apache2:armhf ]
Inst apache2-mpm-prefork (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Conf apache2-mpm-prefork (2.2.22-13+deb7u6 Raspbian:7.0/oldstable [armhf])
Inst lsof (4.86+dfsg-1 Raspbian:7.0/oldstable [armhf])
Inst php5-common (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [armhf])
Inst libonig2 (5.9.1-1 Raspbian:7.0/oldstable [armhf])
Inst libqdbm14 (1.8.78-2 Raspbian:7.0/oldstable [armhf])
Inst libapache2-mod-php5 (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [armhf])
Inst php5 (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [all])
Inst php5-cli (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [armhf])
Conf lsof (4.86+dfsg-1 Raspbian:7.0/oldstable [armhf])
Conf php5-common (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [armhf])
Conf libonig2 (5.9.1-1 Raspbian:7.0/oldstable [armhf])
Conf libqdbm14 (1.8.78-2 Raspbian:7.0/oldstable [armhf])
Conf libapache2-mod-php5 (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [armhf])
Conf php5 (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [all])
Conf php5-cli (5.4.44-0+deb7u1 Raspbian:7.0/oldstable [armhf])
root@satoraspi:~#

 入れても大丈夫みたいだ。

root@satoraspi:~# apt-get  install php5
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の特別パッケージがインストールされます:
  apache2-mpm-prefork libapache2-mod-php5 libonig2 libqdbm14 lsof php5-cli php5-common
提案パッケージ:
  php-pear
以下のパッケージは「削除」されます:
  apache2-mpm-worker
以下のパッケージが新たにインストールされます:
  apache2-mpm-prefork libapache2-mod-php5 libonig2 libqdbm14 lsof php5 php5-cli
  php5-common
アップグレード: 0 個、新規インストール: 8 個、削除: 1 個、保留: 0 個。
6,142 kB のアーカイブを取得する必要があります。
この操作後に追加で 17.3 MB のディスク容量が消費されます。
続行しますか [Y/n]? y
取得:1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main apache2-mpm-prefork armhf 2.2.22-13+deb7u6 [2,342 B]
取得:2 http://mirrordirector.raspbian.org/raspbian/ wheezy/main lsof armhf 4.86+dfsg-1 [321 kB]
取得:3 http://mirrordirector.raspbian.org/raspbian/ wheezy/main php5-common armhf 5.4.44-0+deb7u1 [621 kB]
取得:4 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libonig2 armhf 5.9.1-1 [130 kB]
取得:5 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libqdbm14 armhf 1.8.78-2 [119 kB]
取得:6 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libapache2-mod-php5 armhf 5.4.44-0+deb7u1 [2,479 kB]
取得:7 http://mirrordirector.raspbian.org/raspbian/ wheezy/main php5 all 5.4.44-0+deb7u1 [1,024 B]
取得:8 http://mirrordirector.raspbian.org/raspbian/ wheezy/main php5-cli armhf 5.4.44-0+deb7u1 [2,469 kB]
6,142 kB を 6秒 で取得しました (1,016 kB/s)
dpkg: apache2-mpm-worker: 依存関係に問題があります。しかし要求に従い削除しています:
 apache2 は以下に依存 (depends) します: apache2-mpm-worker (= 2.2.22-13+deb7u6) | apache2-mpm-prefork (= 2.2.22-13+deb7u6) | apache2-mpm-event (= 2.2.22-13+deb7u6) | apache2-mpm-itk (= 2.2.22-13+deb7u6) ...しかし:
  パッケージ apache2-mpm-worker は削除されようとしています。
  パッケージ apache2-mpm-prefork はまだインストールされていません。
  パッケージ apache2-mpm-event はまだインストールされていません。
  パッケージ apache2-mpm-itk はまだインストールされていません。

(データベースを読み込んでいます ... 現在 79208 個のファイルとディレクトリがインストールされています。)
apache2-mpm-worker を削除しています ...
[....] Stopping web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
[ ok waiting ..
以前に未選択のパッケージ apache2-mpm-prefork を選択しています。
(データベースを読み込んでいます ... 現在 79203 個のファイルとディレクトリがインストールされています。)
(.../apache2-mpm-prefork_2.2.22-13+deb7u6_armhf.deb から) apache2-mpm-prefork を展開してい ます...
apache2-mpm-prefork (2.2.22-13+deb7u6) を設定しています ...
[....] Starting web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
. ok
以前に未選択のパッケージ lsof を選択しています。
(データベースを読み込んでいます ... 現在 79208 個のファイルとディレクトリがインストールされています。)
(.../lsof_4.86+dfsg-1_armhf.deb から) lsof を展開しています...
以前に未選択のパッケージ php5-common を選択しています。
(.../php5-common_5.4.44-0+deb7u1_armhf.deb から) php5-common を展開しています...
以前に未選択のパッケージ libonig2 を選択しています。
(.../libonig2_5.9.1-1_armhf.deb から) libonig2 を展開しています...
以前に未選択のパッケージ libqdbm14 を選択しています。
(.../libqdbm14_1.8.78-2_armhf.deb から) libqdbm14 を展開しています...
以前に未選択のパッケージ libapache2-mod-php5 を選択しています。
(.../libapache2-mod-php5_5.4.44-0+deb7u1_armhf.deb から) libapache2-mod-php5 を展開しています...
以前に未選択のパッケージ php5 を選択しています。
(.../php5_5.4.44-0+deb7u1_all.deb から) php5 を展開しています...
以前に未選択のパッケージ php5-cli を選択しています。
(.../php5-cli_5.4.44-0+deb7u1_armhf.deb から) php5-cli を展開しています...
man-db のトリガを処理しています ...
lsof (4.86+dfsg-1) を設定しています ...
php5-common (5.4.44-0+deb7u1) を設定しています ...

Creating config file /etc/php5/mods-available/pdo.ini with new version
libonig2 (5.9.1-1) を設定しています ...
libqdbm14 (1.8.78-2) を設定しています ...
libapache2-mod-php5 (5.4.44-0+deb7u1) を設定しています ...

Creating config file /etc/php5/apache2/php.ini with new version
[....] Restarting web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
 ... waiting apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
. ok
php5 (5.4.44-0+deb7u1) を設定しています ...
php5-cli (5.4.44-0+deb7u1) を設定しています ...

Creating config file /etc/php5/cli/php.ini with new version
update-alternatives: /usr/bin/php (php) を提供するために 自動モード で /usr/bin/php5 を使います
root@satoraspi:~#

……と、いうわけで、サクッと入る。

PHPの作動を確かめる

 それでは早速……。

root@satoraspi:/var/www# ログアウト
toshio@satoraspi:~$ cd /var/www
toshio@satoraspi:/var/www$ vi infotest.php

 で、中身はこじんまりとこう書いて……

<html>
<head></head>
<body>
<?phpinfo();?>
</body>
</html>

 早速ブラウザで見ると……

raspi-phpinfo

うん。動いちょる動いちょる。

さっそくPHPでLチカ

 さて、次に、phpからGPIOだな。マンネリだけどやっぱり「Lチカ」か。

「web2LED.php」

<html>
 <head>
  <meta name="Editor" content="vim">
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <link rel="icon" href="favicon.ico" type="image/x-icon" />
  <link rel="Shortcut Icon" type="image/x-icon" href="favicon.ico" />
  <title>PHPでLチカ</title>
  <meta http-equiv="Keyword" content="佐藤俊夫, 佐藤, 俊夫, SATOTOSHIO, SatoToshio, sato, toshio, Raspberry Pi, Raspberry Pi 2 Model B">
 </head>
 <body bgcolor="#888888">
<body>
  <center>
  <h1>PHPでLチカ</h1>
  <hr>
  <form method="POST">
  <input type="submit" name="on"  value="LED on"><br>
  <input type="submit" name="off" value="LED off">
  </form>
  </center>
<?
ini_set( 'display_errors', 1 );
file_put_contents('/sys/class/gpio/export', 17);
file_put_contents('/sys/class/gpio/gpio17/direction', 'out');
if(isset($_POST['on'])){
  file_put_contents('/sys/class/gpio/gpio17/value', 1);
  print("LED ON.");
}elseif(isset($_POST['off'])){
  file_put_contents('/sys/class/gpio/gpio17/value', 0);
  print("LED OFF.");
}
file_put_contents('/sys/class/gpio/unexport', 17);
?>
</body>
</html>

 ブレッドボードにLEDと330Ωの抵抗を直列につけて、17番ピンとアースにつなぐ。

IMG_3313

 で、こういうフォームになるのだが……

web2LED_permission_deny

 いや、そりゃまあ、動くわけないわな、GPIOはrootでなきゃ読み書きできんのだから。

GPIOのパーミションの調整

 えーっと、どうやったらいいかな、ということで、

  • 「sudoする」
  • 「GPIOのアクセス権をヌルくする」
  • 「PHPの実行ユーザを強くする」
  • 「何かをSUID」

……などと、いろいろあるが、どうも、どれもいまいち、ピンと来ないな……。

 まあ、GPIOのアクセスをヌルくする、これかなあ……。

toshio@satoraspi:~$ cd /sys/class
toshio@satoraspi:/sys/class$ su
パスワード:
root@satoraspi:/sys/class# chmod -R 777 gpio
root@satoraspi:/sys/class# ls -Flad gpio
drwxrwxrwx 2 root gpio 0  8月 30 13:20 gpio/
root@satoraspi:/sys/class#

 なんっか、もう、力いっぱい777丸出しですけどね(笑)。多分、700とか760でも大丈夫じゃないかなあ。試してないけど。

 で、まあ、これで、フォームをクリックするとLEDが点いたり消えたりする。

Raspberry Pi + Apache + PHP + SSRでAC100Vの家電製品を制御

 これをそのまま、いつぞやArduinoでやったSSR(ソリッド・ステート・リレー)につなぐと、家電製品のオン・オフなどができるわけだ。

SSRモジュール
IMG_3047

 では、やってみよう。

Raspberry Pi 2で扇風機のオン・オフ

 真ん中の黒い箱がSSRだ。Arduinoは5V、Raspberry Pi 2は3.3Vで電圧が違うが、このSSRは3Vから8Vまでの入力を受け付けるので、大丈夫なのである。

耽るLチカ

投稿日:

 LEDは半導体であるから、電球と違って、光り始める前は抵抗は無限大であり、電流は流れない。ところが電圧がVfを超えて光り始めたら最後、抵抗がなくなって電源をショートさせた状態でぶっ飛び、自分自身も壊れる。従って必ず抵抗を一緒にくっつけてやるのだ。

 その抵抗を選ぶのは簡単で、基本的に E = I\cdot R という、この式のみでよい。LEDを買ってくると、流すべき電流値(If)、光り始める電圧(Vf)がどこかに書いてあるから、それに従って計算する。すなわち、

R = \frac{V - Vf}{If}

ここに、

V 自分が用意する電源の電圧
Vf 買ってきたLEDのVf(順方向電圧)、つまり光り始める電圧
If 買ってきたLEDのIf(順方向電流)、つまり光らせるために必要な電流

 ただ、抵抗は入手可能な数値が決まっており、そのものピタリという抵抗値のものは売っていない。なので、計算した値と一番近い抵抗を選び、その抵抗値で再び電流を計算して、買ってきたLEDのIfを超えていないかどうかを確かめる。

 これが、簡単な計算ではあるけどいちいち面倒くさい。

 それでまあ、抵抗を選ぶのにこういうスプレッドシートを作る。

 それから、これを使ってみよう。

IMG_3181

 これは、「武蔵野電波のプロトタイパーズ第15回『TLC5940で16個のLEDを遊ぶ』」で取り上げられている「TLC5940NT」というICだ。千石電商本店2階、入って左側の、一番奥のほうの抽斗で売られている。武蔵野電波のページでは400~700円とされているが、千石電商の店頭売りでは390円である。

 Arduinoで使うには、GitHubにあるライブラリをダウンロードし、zipを展開して出てくる「tlc5940」というディレクトリをArduino IDEのインストールディレクトリの下にある「libraries」の中にコピーすればよい。

 スペックシートはコレだが、スペックシートを見るより、Arduinoにライブラリを入れると出てくるようになるサンプルスケッチの「BasicUse」を見た方が分かり易いと思う。こんな風にサンプルは書かれている。

/*
    Basic Pin setup:
    ------------                                  ---u----
    ARDUINO   13|-> SCLK (pin 25)           OUT1 |1     28| OUT channel 0
              12|                           OUT2 |2     27|-> GND (VPRG)
              11|-> SIN (pin 26)            OUT3 |3     26|-> SIN (pin 11)
              10|-> BLANK (pin 23)          OUT4 |4     25|-> SCLK (pin 13)
               9|-> XLAT (pin 24)             .  |5     24|-> XLAT (pin 9)
               8|                             .  |6     23|-> BLANK (pin 10)
               7|                             .  |7     22|-> GND
               6|                             .  |8     21|-> VCC (+5V)
               5|                             .  |9     20|-> 2K Resistor -> GND
               4|                             .  |10    19|-> +5V (DCPRG)
               3|-> GSCLK (pin 18)            .  |11    18|-> GSCLK (pin 3)
               2|                             .  |12    17|-> SOUT
               1|                             .  |13    16|-> XERR
               0|                           OUT14|14    15| OUT channel 15
    ------------                                  --------

    -  Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
         (cathode) in OUT(0-15).
    -  +5V from Arduino -> TLC pin 21 and 19     (VCC and DCPRG)
    -  GND from Arduino -> TLC pin 22 and 27     (GND and VPRG)
    -  digital 3        -> TLC pin 18            (GSCLK)
    -  digital 9        -> TLC pin 24            (XLAT)
    -  digital 10       -> TLC pin 23            (BLANK)
    -  digital 11       -> TLC pin 26            (SIN)
    -  digital 13       -> TLC pin 25            (SCLK)
    -  The 2K resistor between TLC pin 20 and GND will let ~20mA through each
       LED.  To be precise, it's I = 39.06 / R (in ohms).  This doesn't depend
       on the LED driving voltage.
    - (Optional): put a pull-up resistor (~10k) between +5V and BLANK so that
                  all the LEDs will turn off when the Arduino is reset.

    If you are daisy-chaining more than one TLC, connect the SOUT of the first
    TLC to the SIN of the next.  All the other pins should just be connected
    together:
        BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
        XLAT on Arduino  -> XLAT of TLC1  -> XLAT of TLC2  -> ...
    The one exception is that each TLC needs it's own resistor between pin 20
    and GND.

    This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
    Do not use analogWrite(...) on these pins.

    This sketch does the Knight Rider strobe across a line of LEDs.

    Alex Leone <acleone ~AT~ gmail.com>, 2009-02-03 */

#include "Tlc5940.h"

void setup()
{
  /* Call Tlc.init() to setup the tlc.
     You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
  Tlc.init();
}

/* This loop will create a Knight Rider-like effect if you have LEDs plugged
   into all the TLC outputs.  NUM_TLCS is defined in "tlc_config.h" in the
   library folder.  After editing tlc_config.h for your setup, delete the
   Tlc5940.o file to save the changes. */

void loop()
{
  int direction = 1;
  for (int channel = 0; channel < NUM_TLCS * 16; channel += direction) {

    /* Tlc.clear() sets all the grayscale values to zero, but does not send
       them to the TLCs.  To actually send the data, call Tlc.update() */
    Tlc.clear();

    /* Tlc.set(channel (0-15), value (0-4095)) sets the grayscale value for
       one channel (15 is OUT15 on the first TLC, if multiple TLCs are daisy-
       chained, then channel = 16 would be OUT0 of the second TLC, etc.).

       value goes from off (0) to always on (4095).

       Like Tlc.clear(), this function only sets up the data, Tlc.update()
       will send the data. */
    if (channel == 0) {
      direction = 1;
    } else {
      Tlc.set(channel - 1, 1000);
    }
    Tlc.set(channel, 4095);
    if (channel != NUM_TLCS * 16 - 1) {
      Tlc.set(channel + 1, 1000);
    } else {
      direction = -1;
    }

    /* Tlc.update() sends the data to the TLCs.  This is when the LEDs will
       actually change. */
    Tlc.update();

    delay(75);
  }

}

 この最初のほうのコメントにアスキー・アートで書かれている図を見て結線するとよい。こんな感じだ。

IMG_3185

 LEDは秋葉原・千石電商の隣の店、「akiba LEDピカリ館」で売っていた10個入り300円の白色LEDで、Vfが3.0V~3.4V、Ifが20mAとある。電源が5Vならば100Ωばかり抵抗を付けてやればいい理屈だが、全部点灯させるとArduinoがダメになってしまうから、さらに絞って10KΩつけてやる。

 コンパイルして動かすとこうなる。

 10kΩでもこれくらい明るい。

 このICを使うと、パルス幅変調の幅も、Arduinoが256段階であるのに比べ、4096段階と格段に細かくなる。

 アレンジを加えてみよう。昨日買ってきたポテンショメータを使う。アナログの4番ピンと5番ピンに50kΩのポテンショメータと10kΩの抵抗をつなぎ、それぞれを強さと速さにして、「尾を引いたみたいに」明るさ制御をする。

 ポテンショメータの回路はこうする。

IMG_3191

 図の「E1」をアナログ入力で読めばよい。ポテンショメータのつまみの位置は、次の計算でR2を求めれば明らかになる。

E_{0} = I_{0}\cdot(R_{1} + R_{2})
I_{0} = \frac{E_{0}}{R_{1} + R_{2}}…①
I_{0} = \frac{E_{1}}{R_{2}}…②
① = ②
\frac{E_{0}}{R_{1} + R_{2}} = \frac{E_{1}}{R_{2}}
E_{0}\cdot R_{2} = E_{1}\cdot R_{1} + E_{1}\cdot R_{2}
R_{2}(E_{0} - E_{1}) = E_{1}\cdot R_{1}
R_{2} = \frac{E_{1}\cdot R_{1}}{E_{0}-E_{1}}

 組み付けるとこうなる。

IMG_3187

 動かすとこんな感じ。

 スケッチはこんな感じ。

//
//  wPotentio2tlc5940.ino
//    ポテンショメータとTLC5940でLチカ
//    27.08.02(日)0900~
//    佐藤俊夫
//
#include "Tlc5940.h"
//
const float
  R1 = 10000.0,     //  ポテンショメータ前の抵抗10kΩ, 
  E0 = 5.0,         //  電源電圧5V, 
  MAXVR = 50000.0;  //  ポテンショメータの最大抵抗
const unsigned int   VR1 = 4, VR2 = 5;  //  ポテンショメータはアナログピンのA4・A5
const unsigned int MAX_LED = 15;  //  LEDは0~15の16個
//
void setup()
{
  Tlc.init();
  pinMode(VR1, INPUT);
  pinMode(VR2, INPUT);
}

void loop()
{
  float vr1 = 0.0, vr2 = 0.0, e11 = 0.0, e21 = 0.0;
  static unsigned int topLed = 0, tailLen = 10;
  e11 = analogRead(VR1) * (5.0 / 1024);
  e21 = analogRead(VR2) * (5.0 / 1024);
  vr1 = (e11 * R1) / (E0 - e11);  //  明るさ
  vr2 = (e21 * R1) / (E0 - e21);  //  速さ
  if(++topLed > MAX_LED + tailLen)  topLed = 0;
  Tlc.clear();
  int bright = constrain(fmap(vr1, 0.0, MAXVR, 0, 4095), 0, 4095);
  Tlc.set(topLed, bright);
  for(int i = topLed - 1; i >= 0; i--){
    bright -= (4096 / tailLen);
    if(bright < 0) bright = 0;
    Tlc.set(i, bright);
  }
  Tlc.update();
  unsigned int delayTime = constrain(fmap(vr2, 0.0, MAXVR, 100, 10), 10, 100);
  delay(delayTime);
}
//
float fmap(float x, float in_min, float in_max, float out_min, float out_max) {
  //  もともとの「map()」がlong int型でこの用途に合わないので、float型を定義
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

カメラで遊んでみる

投稿日:

 秋月電子のサイトを見ていると、小さなカメラがあり、Arduinoに付きそうな感じだ。

 3850円。Arduino自体が2800円かそこらなので、それに比べるとちょっと高いが、早速行って購入。

 だが、あまり情報は多くない。まず、メーカーのサイトを見ていくと、チュートリアルがあり、「とりあえずテストするには、電源をくれてやって、一番端のピンをテレビにつなぎゃあ絵が出る」みたいなザックリ感満載の解説が。それで、テレビにつなぐためのRCAジャックなども買う。

 チュートリアルはこれを読んでおけばだいたいいいようだ。

 ほどいてみるとこんな感じで、かなり小さい。

IMG_3112

 ピンのピッチが2mmで、ブレッドボードで扱いにくい。それで、普通の2.54mmのピンヘッダを出して、その根元をこんなふうにムリヤリ(笑)2mmピッチにせばめる。

IMG_3116

 こいつをカメラの基盤にえいやっ、とねじ込み、半田付けする。

IMG_3118

 なかなか小さいので、ルーペと老眼鏡を併用しつつ、ICなんか壊しちゃってもナンだから、20Wのぬるくて細い半田鏝でさっさとつける。

IMG_3117

 我ながらなかなかスピーディな仕事だなあ(笑)。

 で、メーカーのサイトには「5V」と書いてあるが、これは互換品の別の製品のためのチュートリアルのようで、買ってきたものの基盤をよく見ると「3.3V」と印刷されている。壊してはもったいないから、3.3Vで試す。3.3Vの電源代わりにArduinoの3.3Vピンを使う。

 基盤の印刷通り、3.3V、GND、それから右端のピンをRCAジャックのセンターに、RCAジャックのアースを同じくGNDに入れて、テレビの前に持っていく。

IMG_3119

 テレビにつなぐと、おお、確かに、値段なりのフザけた画質(笑)で、自分の顔が映る。

IMG_3121

 上下が逆だが、まあ、いいや。

 で、今度はArduinoで画像を撮影してみよう。

 チュートリアルにしたがってArduino用のライブラリをダウンロードし、これをArduinoのインストールフォルダの「libraries」に配置する。

 そうしておいてArduinoのIDEを起動すると、「ファイル」→「スケッチの例」の中に「Adafruit VC0706 Serial Camera Library」が現れるから、この中から「Snapshot」を選ぶ。これは静止画をjpegで撮影するスケッチのサンプルだ。

// This is a basic snapshot sketch using the VC0706 library.
// On start, the Arduino will find the camera and SD card and
// then snap a photo, saving it to the SD card.
// Public domain.

// If using an Arduino Mega (1280, 2560 or ADK) in conjunction
// with an SD card shield designed for conventional Arduinos
// (Uno, etc.), it's necessary to edit the library file:
//   libraries/SD/utility/Sd2Card.h
// Look for this line:
//   #define MEGA_SOFT_SPI 0
// change to:
//   #define MEGA_SOFT_SPI 1
// This is NOT required if using an SD card breakout interfaced
// directly to the SPI bus of the Mega (pins 50-53), or if using
// a non-Mega, Uno-style board.

#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>

// comment out this line if using Arduino V23 or earlier
#include <SoftwareSerial.h>         

// uncomment this line if using Arduino V23 or earlier
// #include <NewSoftSerial.h>       

// SD card chip select line varies among boards/shields:
// Adafruit SD shields and modules: pin 10
// Arduino Ethernet shield: pin 4
// Sparkfun SD shield: pin 8
// Arduino Mega w/hardware SPI: pin 53
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
#define chipSelect 10

// Pins for camera connection are configurable.
// With the Arduino Uno, etc., most pins can be used, except for
// those already in use for the SD card (10 through 13 plus
// chipSelect, if other than pin 10).
// With the Arduino Mega, the choices are a bit more involved:
// 1) You can still use SoftwareSerial and connect the camera to
//    a variety of pins...BUT the selection is limited.  The TX
//    pin from the camera (RX on the Arduino, and the first
//    argument to SoftwareSerial()) MUST be one of: 62, 63, 64,
//    65, 66, 67, 68, or 69.  If MEGA_SOFT_SPI is set (and using
//    a conventional Arduino SD shield), pins 50, 51, 52 and 53
//    are also available.  The RX pin from the camera (TX on
//    Arduino, second argument to SoftwareSerial()) can be any
//    pin, again excepting those used by the SD card.
// 2) You can use any of the additional three hardware UARTs on
//    the Mega board (labeled as RX1/TX1, RX2/TX2, RX3,TX3),
//    but must specifically use the two pins defined by that
//    UART; they are not configurable.  In this case, pass the
//    desired Serial object (rather than a SoftwareSerial
//    object) to the VC0706 constructor.

// Using SoftwareSerial (Arduino 1.0+) or NewSoftSerial (Arduino 0023 & prior):
#if ARDUINO >= 100
// On Uno: camera TX connected to pin 2, camera RX to pin 3:
SoftwareSerial cameraconnection = SoftwareSerial(2, 3);
// On Mega: camera TX connected to pin 69 (A15), camera RX to pin 3:
//SoftwareSerial cameraconnection = SoftwareSerial(69, 3);
#else
NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif

Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);

// Using hardware serial on Mega: camera TX conn. to RX1,
// camera RX to TX1, no SoftwareSerial object is required:
//Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);

void setup() {

  // When using hardware SPI, the SS pin MUST be set to an
  // output (even if not connected or used).  If left as a
  // floating input w/SPI on, this can cause lockuppage.
#if !defined(SOFTWARE_SPI)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  if(chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega
#else
  if(chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc.
#endif
#endif

  Serial.begin(9600);
  Serial.println("VC0706 Camera snapshot test");
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }  
  
  // Try to locate the camera
  if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

  // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 
  // Remember that bigger pictures take longer to transmit!
  
  cam.setImageSize(VC0706_640x480);        // biggest
  //cam.setImageSize(VC0706_320x240);        // medium
  //cam.setImageSize(VC0706_160x120);          // small

  // You can read the size back from the camera (optional, but maybe useful?)
  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");

  Serial.println("Snap in 3 secs...");
  delay(3000);

  if (! cam.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");
  
  // Create an image with the name IMAGExx.JPG
  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for (int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }
  
  // Open the file for writing
  File imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image (frame) taken  
  uint16_t jpglen = cam.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

  int32_t time = millis();
  pinMode(8, OUTPUT);
  // Read all the data up to # bytes!
  byte wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();

  time = millis() - time;
  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");
}

void loop() {
}

 で、これはSDカードに書き込むようになっている。

 私の手持ちの、ArduinoにSDカードをつなぐ手段は、先日から愛用中の「ETHERNET SHIELD 2」に搭載されているSDカードスロットだけだから、とりあえずこれを使う。

 手持ちのSDカードをETHERNET SHIELD 2に挿し、Adafruitのサイトのチュートリアルを参考に回路をブレッドボードに組む。

IMG_3122

 注意する点は2つだ。

  1.  サンプルスケッチをよく読むと、普通のSDカードは10番ピンを使うが、ETHERNET SHIELD 2を使う場合は4番ピンにつながる。なので、サンプルスケッチの中の「#define chipSelect 10」というところを「#define chipSelect 4」に書き換えなければならない。
  2.  メーカーサイトのチュートリアルでは、カメラに添付の10kΩの抵抗をTXの次に直列に二つ入れて、1本目と2本目の間からTXをとり、それをアースしているが、どうもこれだとうまく行かなかった。多分、このチュートリアルは給電が5Vだからだと思う。そこで、アースはそのままに、1本目の手前でTXをとるとうまくいった。
    IMG_3127

 そうやってArduinoをスタートさせると、写真が1枚だけ撮れる。

 下は、そうやって撮った私の顔である。

IMAGE02

 ……むっちゃむさくるしいなあw。

次に、ETHERNET SHIELD 2というやつを…

投稿日:

 次に、昨日FETやソレノイドと一緒に買っておいた「イーサネットシールド」というやつを試す。

 これを買ったのは、簡単なウェブインターフェイスで、例えばフォームのボタンをクリックするとデジカメのシャッターが落ちる、みたいなのをやりたかったからだ。千石電商で3240円だったが、多分、もっと安い互換品などもあるのだろう。

 ともかく、こんな箱に入っている、こういう形のブツである。

IMG_2880

 この方のサイトなどを勝手に参考にさせていただきつつ、いじくってみる。

 Arduinoに取り付けるとこのようになる。

IMG_2881

 で、ArduinoのIDEにサンプルプログラムが入っているから、それをタッチアップして目的を達する。

 注意しなければならないのは、私の買ったのは「ETHERNET SHIELD 2」という最新のもので、ネットで多く紹介されている「ETHERNET SHIELD R3」というものとは違うということだ。

 私の買った「ETHERNET SHIELD 2」は、最新のArduino IDE 1.7.3でないと、サンプルコードなども違い、扱えない。私が使っているIDEは1.6.4なので、アップグレードしなければならない。

 アップグレードしたIDEで、次のように「ファイル」→「スケッチの例」→「Ethernet2」とメニューを操作していくとサンプルコードが出てくる。

webServerSketchExample2

  • AdvancedChatServer
  • BarometricPressureWebServer
  • ChatServer
  • DhcpAddressPrinter
  • DhcpChatServer
  • TelnetClient
  • UdpNtpClient
  • UDPSendReceiveString
  • WebClient
  • WebClientRepeating
  • WebServer

……このように、けっこういろいろなものが入っている。今日は一番下の「WebServer」を選ぶ。

 このソースのMACアドレスとIPアドレスを、先達サイトを参考に現況に合わせて書き換える。MACアドレスはシールドの基板の裏にシールで貼ってある。
 
 出来上がったらそのへんにのたくっているカテ5のモジュラーをえいっとつっこみ、ブラウザにIPアドレスを入れれば、すぐにミニWebサーバとして動き出す。

ArduinoWebServerScreen

 これは、各アナログピンの現在の値を5秒毎にモニタしている。何かセンサをピンにつなげば、即、ネット温度計やネット照度計の出来上がりである。

 さて、次に、コイツで「POST」を受け取る段取りだ。コイツにアクセスして、フォームのボタンを押すと、ソレノイドが動く、という機構を作るためである。

 本当ならクライアントから来る文字列を標準入力で受ける段取りが必要だが、今日は簡略化して、ブラウザがPOSTを投げたら、内容はなんでもいいから、とりあえずソレノイドを動かす、というふうにする。

 そのソースコードはこんな感じだ。

//
//  WebServerでソレノイドを動かす。
//    佐藤俊夫
//    27.5.24(日)1352~
//

#include <SPI.h>
#include <Ethernet2.h>

const int FET = 9;
byte mac[] = {
  0x90, 0xA2, 0xDA, 0x0F, 0xF6, 0x74
};
IPAddress ip(192, 168, 1, 129);
EthernetServer server(80);

void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
  pinMode(FET, OUTPUT);
}

void loop() {
  String recvbuf;
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        recvbuf += c;
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<head></head>");
          client.println("<body>");
          client.println("<center><h3>Drive solenoid.</h3>");
          client.println("<hr>");
          client.println("<form method=\"POST\">");
          client.println("<input type=\"submit\" value=\"Do!\">");
          client.println("</form>");
          client.println("</center>");
          client.println("</body>");
          client.println("</html>");
        if (c == '\n' && currentLineIsBlank) {
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
          if(recvbuf.indexOf("POST") == 0){
            digitalWrite(FET, HIGH);
            delay(2000);
            digitalWrite(FET, LOW);            
          } 
          recvbuf = "";
        }
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

 次に、ちょっと仕掛けを作る。本当はカメラのシャッターを切りたいのだが、買ってきたソレノイドの力があんまりなくて、シャッターが切れない。それで、ガラスのコップをソレノイドで叩いて音を出す。

 ソレノイドは、午前中やったように、電流がちょいとばかり多く流れるので、FETでリレーしてやる。

 こんな仕掛けにする。

IMG_2885

 こんなフォームを作り、携帯電話にロードする。「Do!」というボタンをクリックすると、ソレノイドが動く。

form

 で、ガラスのコップにソレノイドの軸を近づけて……。

IMG_2886

 操作するとこんな風になる。


 

ついに俺をネットに接続することに成功した。

投稿日:

IMG_2803 さて、このようにArduinoで遊び、写真のような成果を得た。

 これが、Arduinoを使用して、私・佐藤俊夫をワイヤード(USB経由)でネットに接続し、常時私のおツムの具合をネットに公開するシステムの図である。

notice 全般構成を解説しよう。きわめて簡単だ。

 左側のブレッドボード、その更に左側にわずかに見える緑色の素子がサーミスタである。+5Vを印加、10kΩ抵抗と直列につないで接地し、抵抗とサーミスタの間から出力をとってArduinoのアナログ入力に入れてある。

 まことに疑問の余地もなく、シンプルである。

 Arduino側には、次のようなシンプルなソースが書かれている。

//
//  シリアルに体温を送る。
//    佐藤俊夫
//    27.05.05(火) 1730~
//
const int THERMISTOR = 0;  //  A0
//

void setup() {
  Serial.begin(9600);
}

void loop() {
  float v = 0;
  //
  v = analogRead(THERMISTOR);
  v = -9.663E-5 * v * v + 0.164 * v + 0.197;
  Serial.println(v, DEC);
}

 次に、これを手近のLinuxマシンにつなぐ。

# stty -F /dev/ttyACM0
speed 9600 baud; line = 0;
-brkint -imaxbel

 これでよい。

 あとは、crontabに次のように書き込み、crondを再起動すれば終わりである。

   */5  *   *   *    *   head -n 1 /dev/ttyACM0 | mail -s "Sato's Physical condition." foobar@hogehoge.ne.jp

 無論、上記の「foobar@hogehoge.ne.jp」というメールアドレスは、私のブログへのメール投稿アドレスにほかならず、こうすることによりTwitterとFacebookにパブリサイズ共有されるわけである。

 これで、私こと佐藤が、ついにインターネットに接続された!!