PICNIC(PIC Network Interface Controler)という、PICマイコンを使ったEthernetに繋がる制御カードのキットを買ってきて遊んでいる。秋葉原の秋月でキットは7,300円、完成品は12,800円。
最終的にはLAN経由で家電や照明、PC関係の電源ON/OFFや状態監視などをしてみたいが、取りあえずPICNIC付属の温度センサと、3個100円で買ってきたCDSを繋いで照度計(というほどのものではない)にしている。プラスティックのケースは秋月でおまけにくれた物。
パソコンの近くに置いてもつまらないので、無線LANのメディアコンバータに繋いで2Fに置いてみた。無線LANなので電源さえ確保できればどこへでも移動できる。
メディアコンバータとPICNIC イメージ図 以下がPICNIC本体の拡大写真。右上の外部インタフェースコネクタの端にCDSを付けてある。出力ポートの状態は右下の4つの赤い小さなLEDで確認できる。写真では全てLなので点灯していない。
PICNIC基板の拡大写真 PICNICはIPアドレスを持っており、制御用のパソコン等とPICNICとはhttpで通信する。Webブラウザから http://192.168.0.200 などとアクセスするとI/Oポートの状態が以下のように返ってくる。
RA0〜RA5がアナログ入力ポートで、RA5にはおまけで付いてくる温度センサが付いている。今回CDSはRA0に付けた。AD変換の精度は10ビット、つまり0〜1023の値が返ってくる。RB0〜RB3はデジタルの入力ポート、RB4〜RB7はデジタルの出力ポート。出力ポートは、H,Lボタンをクリックすることで状態を設定できる。
ボタンをクリックせずに設定したい場合には、http://192.168.0.200/modify.cgi?RB4=Hのようにアクセスすればよい。
PICNICが返すI/Oポートステータス 温度と照度を上の画面でみてもよいが、あまりに味気ないのでPerlとTkでGUIを作ってみた。スクリプト言語でこんなに簡単にGUIが作れるとは便利な世の中になりました。その昔、SunViewで苦労したことが懐かしい(望遠)。
左側は定期的な自動リフレッシュ、右はリフレッシュボタンを押したときにアクセスする画面。しかし、どちらも時々アクセスに失敗して応答が返ってこなくなることがある。無線LANを使っているからか? よく分からない。
LWP::Simpleで安易に作っているのがいけないのかも。この辺り課題です。また、Windows上のActivePerlで動かすとDOSコンソール(DOS窓)が開いてしまう。ここも何とかしたい。
温度・照度計1 温度・照度計2 ソースコードは以下です。見よう見まねで作ったのでおかしな所があるかもしれません。前半の2/3はTkの画面を作るための設定、実際にPICNICから状態を取り出して解析しているのは、後半のget行とifのマッチング行だけです。
#!/usr/local/bin/perl #--------------------------------------------------------------- # PICNIC温度・照度計 # 2004.11.23 nakamura #--------------------------------------------------------------- use LWP::Simple; use Tk; use Tk::ProgressBar; @color_tbl = ( 0, '#ff00d9', 1, '#ff00f3', 2, '#e900ff', 3, '#d400ff', 4, '#ae00ff', 5, '#9900ff', 6, '#8300ff', 7, '#5d00ff', 8, '#4800ff', 9, '#2800ff', 10, '#1200ff', 11, '#0008ff', 12, '#0028ff', 13, '#003eff', 14, '#0063ff', 15, '#0079ff', 16, '#008eff', 17, '#00b4ff', 18, '#00c9ff', 19, '#00eaff', 20, '#00fff8', 21, '#00ffe3', 22, '#00ffc3', 23, '#00ffa8', 24, '#00ff87', 25, '#00ff72', 26, '#00ff57', 27, '#00ff37', 28, '#00ff21', 29, '#03ff00', 30, '#19ff00', 31, '#2eff00', 32, '#54ff00', 33, '#6aff00', 34, '#8aff00', 35, '#9fff00', 36, '#baff00', 37, '#dbff00', 38, '#f0ff00', 39, '#ffe700', 40, '#ffd200', 41, '#ffbc00', 42, '#ff9700', 43, '#ff8100', 44, '#ff6100', 45, '#ff4600', 46, '#ff3000', 47, '#ff1000', 48, '#ff000a', 49, '#ff002a' ); @bright_tbl = ( 0, '#000000', 1, '#050500', 2, '#0a0a00', 3, '#0f0f00', 4, '#141400', 5, '#1a1a00', 6, '#1f1f00', 7, '#242400', 8, '#292900', 9, '#2f2f00', 10, '#343400', 11, '#393900', 12, '#3e3e00', 13, '#434300', 14, '#494900', 15, '#4e4e00', 16, '#535300', 17, '#585800', 18, '#5e5e00', 19, '#636300', 20, '#686800', 21, '#6d6d00', 22, '#727200', 23, '#787800', 24, '#7d7d00', 25, '#828200', 26, '#878700', 27, '#8d8d00', 28, '#929200', 29, '#979700', 30, '#9c9c00', 31, '#a1a100', 32, '#a7a700', 33, '#acac00', 34, '#b1b100', 35, '#b6b600', 36, '#bcbc00', 37, '#c1c100', 38, '#c6c600', 39, '#cbcb00', 40, '#d0d000', 41, '#d6d600', 42, '#dbdb00', 43, '#e0e000', 44, '#e5e500', 45, '#ebeb00', 46, '#f0f000', 47, '#f5f500', 48, '#fafa00', 49, '#ffff00' ); $mw = MainWindow->new(); $mw->Label( -textvariable => \$buffer0 )->pack(); $bar1 = $mw->ProgressBar( -borderwidth=>2, -blocks=>50, -gap=>0, -from=>0, -to=>49, -troughcolor=>'white',-colors=>\@color_tbl, -length=>106 )->pack(-padx=>5, -pady=>5); $mw->Label( -textvariable => \$buffer1 )->pack(); $bar2 = $mw->ProgressBar( -borderwidth=>2, -blocks=>50, -gap=>0, -from=>0, -to=>99, -troughcolor=>'white',-colors=>\@bright_tbl, -length=>106 )->pack(-padx=>5, -pady=>5 ); $mw->Label( -textvariable => \$buffer2 )->pack(); $mw->Button( -text => 'Refresh', -command => \&get_data )->pack( -pady=>5); #自動リフレッシュではココをコメント &get_data; MainLoop(); sub get_data { $data = get("http://192.168.0.200/"); $bright = 0; $temp = 0; if ($data =~ /RA0[^\d]+(\d+).*>(\d+) Celsius/) { $bright = $1; $temp = $2; } $bright = int( ((1023 - $bright) / 1023 ) * 100 ); $bar1->value($temp+10); $bar2->value($bright); $buffer1 = sprintf("Temperature:%d (C)",$temp); $buffer2 = sprintf("Brightness:%d (%%)",$bright); ($sec, $min, $hour, $mday, $mon, $year) = localtime(time()); $buffer0 = sprintf("%d.%d.%d %02d:%02d:%02d", $year+1900,$mon+1,$mday,$hour,$min,$sec); # $mw->after(5000,\&get_data); #自動リフレッシュではココのコメントを外す。 }LinuxマシンからMRTGを使って定期観測し、グラフ作成なども試してみたいが、我が家のネットワーク環境の都合でPICNICとLinuxマシンを同時に無線LANに繋げない(^_^) 直結すればいいのですが、そうするとWindowsマシンと繋がらないのでLinuxマシンにアクセスできないのだ。近々、TEPCO光が入るのでその時にネットワーク構成を再検討予定。
PICNICに関する情報はWebに結構あるので、"PICNIC 工作" などでググると見つかります。私も色々と参考にさせてもらいました。
なお、今回の照度計は電源電圧をCDSと抵抗で分圧しているだけのいい加減なものなので、部屋の明るさを相対的に見るだけのものです。絶対値を求めるものではありません。また、おまけで付いてくる温度計の精度も期待しないほうがよいです。
次はリレーを使って電源のON/OFFをトライしたいが、秋葉原まで部品を買いに行くのが億劫でなかなか進まない。(2004.11.28)