照度計を基板にまとめてみました

しばらく前のS9706を使った照度センサを基板にまとめてみました。

結局、ケースは作らず、裸の基板のままで裏面にナット2段を挟んでもう1枚基板をつけて背面だけ保護することにしました。

センサは先の記事に加えて、S9705カラーセンサ(クロック同期シリアル出力)、手持ちのPH102フォトトランジスタを抵抗負荷で受けてA/D変換した物を追加して表示しています。

LCDは2行の小型のものに変更しています。1行目の左半分にS9706で取得した照度(lx)とその棒グラフ、1行目の右半分にPH102で取得した照度(lx)とその棒グラフ、2行めの1キャラクタ目に電池の電圧、その後にS9705で取得したRGBのそれぞれの照度(lx)を表示しています。電源は単4電池2本からHT7750Aで5Vを生成しています。

CPUは当初ATmega88としていたのですが、センサの数が増えるに従ってROM容量が収まらなくなり、ATmega168に変更しました。ソフトウェアはタイマ割り込みを使いたかったのでArduinoではなくAVR-GCCで作りました。表示にはChaNさんのキャラクタLCD制御モジュールを4bitモード時に下位側のポートを使うように改造して使わせていただきました。

作ってみてわかったのですが、理論値からはオーダーレベルでは合うものの、表示がバラバラになってしまいます。分光感度特性も異なる3種類のセンサなので、ある程度は当たり前のような気もしますが、これでは目安程度にしかなりません。やはり基準となる測定器がないとつらいですね。

玄箱debianバージョンアップ

古いノートPCにdebianを入れてUSB機器を監視しようとおもっていたのですが、そのノートPCがお亡くなりになってしまいました。2000年に購入したものですが、さすがに前半はモバイルのメインマシンとして酷使、後半はdebianで宅内サーバ、監視サーバとして酷使したので仕方がないでしょう。

で、監視サーバの代役として玄箱(無印)が余っているので、なんとかならないかと思いました。USBシリアルを使うためにはある程度カーネルバージョンが上がっていないといけないのですが、この玄箱、lennyにアップデートすると立ち上がらなかったので、Debianのバージョンはetchのままアップデートしていません。いまさらながら調べてみると、lennyはubootでなければならないようです。なので、その辺をやってつけて、アップデートをかけていくことにしました。

作業内容(後から書いたので、抜けや間違いがあるかもしれません)

1.すでにetchになっていたので、uboot化

注意深く /dev/mtdblock にファームウェアデータを流し込み

# cat u-boot-hd.flash.bin > /dev/mtdblock1

どのブロックかはカーネルによって変わる?ので、全部ダンプしてみてそれっぽいのを探した。

2.再起動せずにカーネル差し替え

ubootで起動できるカーネルをおいとかないと、立ち上がるわけがないので、先に用意しておく。

# cd /boot
# tar xvfz (置いてある場所のパス)/kernelimage-2.6.20-kuroBOX-uImage.tgz
# cd /lib/modules
# tar xvfz (置いてある場所のパス)/modules-2.6.20-kuroBOX.tgz

3.再起動

時間がかかるけど、たちあがる。
立ち上がったら再度 telnet で接続

4.lenny化実行

・/etc/apt/sources.list を修正
“etch” の部分を “lenny” に書き換え
・lenny化実行

#apt-get update
#apt-get safe-upgrade
#apt-get dist-upgrade

5.再起動

たちあがらねぇ・・・というか、立ち上がってるけどIPアドレスがわからない感じ
Linuxマシンで nmap をかけてもみつからない
nc.exe を使ってもつながらない

6.シリアルコンソール接続

最後の手段、シリアルコンソール接続とします。Webで調べるといろいろ情報は出てきますが、R76はシリアルの信号と直列に入っている保護用?の抵抗なので、115200bpsという速度を考え、適当に470オームとした。・・・が実際の接続の速度は 57600bps/8N81だった。

ubootの環境変数やsttyで速度は変えられるけど、カーネルは57600bpsでコンパイルされているようなので、実質57600bps以外の選択肢はない。

で、IPアドレスを調べてみたら、変わってない。
telnetでもつながる。なんだったんだろう?

7.squeeze化

・/etc/apt/sources.list を修正
“lenny” の部分を “squeeze” に書き換え
・squeeze化実行

#apt-get update
#apt-get safe-upgrade
#apt-get dist-upgrade

8.再起動

問題なく起動。

9.カーネルバージョンアップ

某所でsqueezeにバージョンアップしてもカーネルのバージョンは古いまま
(確かに 2.6.20 のまま)

# sudo apt-get install linux-image-2.6-powerpc

でカーネルバージョンアップとか書いてあったので試してみたが、ubootでロードするファイルとあってないのでロードされない。ubootを手動でコマンドを打ちながら起動してみたが、「linkstation用のカーネルじゃない」と蹴られる。どうしょうもない。

なので、

# cd /boot
# tar xvfz (置いてある場所のパス)/kernelimage-2.6.25.20-kuroBOX.tgz
# cd /lib/modules
# tar xvfz (置いてある場所のパス)/modules-2.6.25.20-kuroBOX.tgz

で 2.6.25.20 まではバージョンアップした。

10.電源落ちない対策

ここで、shutdownコマンドやrebootコマンドで最後の最後にフリーズする対策を見つけたので、追加。

/etc/init.d/haltのpathの行の後ろにecho -n “EEEE” > /dev/AVR00を追加

これでシャットダウン時に電源が切れるようになった・・・が、その後電源SWを押しても起動しない。結局一度プラグを抜かなきゃいけない。うーん。

<まとめ>
結局、カーネルのバージョンは 2.6.25 のまま。うーん。

照度計として動かしてみる

引き続き、秋月で売っている浜松ホトニクスのS9705という照度センサを使った照度計の製作です。

HT7750Aの負荷を下げるべく、省電力関係を調べて実装しました。

基本的には、Timer2でパワーセーブモードからの復帰が可能なので、Timer2の割込みで周期的に起こすことにして、通常はパワーセーブモード(スリープモード)に落としておくことにしました。これで5Vの消費電流は約15~16mAまで下がりました。本当はATmega88ではなくてATmega88Pを使えばいいのでしょうが、それでは手持ちの部品が減らないのでここまでにします。

また、Timer0とTimer1を使って、センサ出力の周波数をカウントする仕掛けを作りました。

で、適当にソフトウェアを作って動かしてみたのが上の写真です。左の数字が照度(ただし、この表示は飽和してます)、右がそのバーグラフです。

ソフトウェアを作るためにデータシートをあらためて眺めていて気がついたのですが、このセンサは1000lx程度までしか測定できません。で、この写真を取るために照明をあてたら飽和してしまいました。もともとはこの写真撮影用の光源に使っているクリップライトのランプを電球型蛍光灯からLEDランプに変えたら結構明るかったので、どのくらい差があるのか調べてみたかった、ということが発端で照度計を作り始めたので、ちょっとがっかりです。

そんな状態なので、単独の基板にするか、さらに、ケースに入れるかどうか迷ってます。ケースに入れるとなると、今回は光センサがありますので、透明なケースを使うとしても外に出してやらなければなりません。また、スイッチもどうやって外に出すかが課題です。ケースの加工って面倒くさいですからね。できれば、小型ボール盤、卓上フライス、卓上旋盤とそれを設置する場所が欲しいところです。(場所が一番課題ですね・・・)

ATmega88でLCDを動かす

秋月で売っている浜松ホトニクスのS9705という照度センサを使って、LED電球の明るさを測ってみたいと思っています。

このセンサは照度を周波数にリニアに変換して出力しますので、受け側では単純に周波数を測定して定数をかけてやれば照度計のできあがりです。

Arduinoでは周波数の測定はちょっと面倒そうなので、今回は手持ちのATmega88をそのまま使うことにしました。表示系はLCDを使いますが、照度しか表示しないので1行のLCDを使います。また、基本的には持ち歩いて使うことになりますので、電池駆動でなければなりません。電池は9Vではなく、単3/単4を1本にしたいと思いましたので、HT7750Aによる昇圧回路を組んであります。で、実験してみたところ、1本では昇圧してLCDを駆動できる5Vで20~30mAの電流を流すのは難しいようでしたので2本を前提にしています。

で、バラックでLCDのテストをするところまで組んでみたところ、こんな感じになりました。

LCDの表示にはChanさんが公開されているキャラクタLCD制御モジュールおよび組み込み用printfモジュールを使わせてもらうことにしました。この状態ですと、5Vの消費電流は内蔵8MHzオシレータ使用時で25mA程度でした。

Ubuntu11.04をインストール中

今、5月1日にリリースされたUbuntu11.04 Desktop 日本語 Remix CDを例によってUSBメモリにインストールしています。

最初はVMwareServer上でUSBメモリを認識させてインストールしようとしていたのですが、途中で止まってしまいます。それに、後で気づいたのですが、USBメモリが/dev/sda3とか/dev/sda4とかになってしまうので、ブートローダの書き込んだあと、修正が必要になってしまいます。

で、いまは、CD-ROMを実際に作成し、Core2Duoのマシンを使ってUSBメモリにインストール中です。HDDがSATA、CD-ROMがATA(パラレルATA)のマシンなので、USBメモリへのインストールは簡単です。

  1. BIOS設定メニューでSATAをDisableにする。
    (これができるマシンだと簡単なのです)
  2. CD-ROMから起動するようにBIOSを設定する。
  3. Ubuntu11.04 Desktop 日本語 Remix CDをCDROMにセットして起動
  4. ブートが始まったらUSBメモリを挿入
  5. しばらくするとライブCDとして動かすか、インストールするかを聞かれるので、インストールを選択
    (10.04ではインストール後に改めて実施だったのが改良されて楽になってます)
  6. インストール中にアップデートを参照するか、サードパーティ製のソフトをインストールするかを聞かれるので、両方ともチェックする
  7. 表示に沿って、ホスト名、ユーザー名、キーボード、タイムゾーンなどを設定する。
  8. 指示に従って再起動すると、Ubuntu11が起動します。

起動中はアクセスが遅いためか、やはり表示のない期間が長めです。ハングアップしたと思わないで、耐えることが必要です。

力技(fork)でブザーを鳴らす

コマンドラインからbeepコマンドでブザーを鳴らすことができたのですが、プログラムから鳴らす方法がわかりません。

しかたがないので、サブプロセスを生成して、そこから system() でブザーを鳴らすという力技で鳴らすことにしました。

先にサブプロセスが終了して何もしないでいると、サブプロセスがゾンビとして残ってしまいますので、次に鳴らす前に waitpid() で回収してます。これだと常にゾンビが1つ残ることになってしまいますので、もっといい方法があるのではないかと思うのですが、今回初めての fork() なのでこの辺で妥協します。

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h> 

pid_t child_pid = 0;
int child_sts;
int buzzer(void)
{
	/* ゾンビ回収 */
	if(child_pid > 0)waitpid(child_pid,&child_sts,WNOHANG);

	/* 子プロセス生成 */
	child_pid = fork();

	if(child_pid==-1) {
		/* fork()失敗 */
		printf("fork failed.\n");
	}
	else if(child_pid==0) {
		/* 子プロセス */
		system("/usr/bin/beep -f 2000 -l 20");
		_exit(0);
	} else {
		return(0);
	}
}

int main(void)
{
	int i;
	for(i=0;i<10;i++){
		buzzer();
		usleep(500000);
	}
}

よく見ると、要らないヘッダを include してたりしますが、メモなのでこのままということで。

linuxでbeep音を鳴らす

加速度センサを監視しているDebianマシンで加速度が大きいときにアラームをならしたいのでどうしたらbeep音がなるか調べてみました。
beep音を鳴らすにはパッケージの導入が必要なようで、

# aptitude install beep

として、パッケージを導入します。さらに、/etc/group の audio グループにユーザが入っている必要があるようですが、自分のところでは初めから入っていました。
この状態でコマンドラインから、

$ beep -f 262 -l 500 -n -f 294 -l 500 -n -f 330 -l 500 -n -f 349 -l 500 -n -f 392 -l 500 -n -f 440 -l 500 -n -f 494 -l 500 -n -f 523 -l 500

と入力すると、「ドレミファソラシド」の音階を聞くことができました。
ただ、プログラムから鳴らす方法を調べなければなりません。
( system() でコマンドを呼ぶと、鳴り終わるまで動作がブロックされそうです・・・)

sshfsを試してみた

いろいろ実験していると、ホスト(サーバ)が乱立してきます。

そうなってくるとそのマシン上のファイル編集をどうしようかというのが段々面倒になってきます。高速なマシンであれば、FreeNXという手もあるのですが、データ収集用のマシンは古いノートPCなので性能的にも厳しいです。

で、ググっていたら、sshfsというものがあることがわかりました。これはホスト側でSSH Serverさえ動いていれば、ホスト側のファイルをローカルシステム側にユーザー権限でマウントできるというもので、非常に簡単・便利です。

以下、クライアント側(手元にある側)の設定方法です。

まず、Synapticパッケージマネージャでsshfsを検索すると、そのものずばりの「sshfs」パッケージがあるので、これをインストールします。

あとは、ホームディレクトリ内にマウントポイント(空のディレクトリ)を作ります。

準備ができたら、

% sshfs [-p ポート番号] [サーバ側のアカウント@]<サーバのホスト名>:[ディレクトリ] <マウントポイント>

でマウントできます。
同じユーザ名の場合、サーバ側のホームディレクトリを ~/mnt にマウントする場合は、

% sshfs [-p ポート番号] <サーバのホスト名>: <マウントポイント>

でOKです。アンマウント時は、

% fusermount -u <マウントポイント>

です。

これで手元のマシンのgeditなどでファイル編集ができるので楽ちんになります。

USB加速度計(KXM52版)

結局、KXP84は突然のノイズ(?)が入って使い物にならなかったので、KXM52-1050で改めてUSB接続のArduinoベースの加速度計を作りました。

今回はLCDがないのでより小さな基板とケースに入れています。ATMEGA328Pと加速度センサの電源はUSBシリアル変換モジュールからの3.3V出力を使っています。

写真に写っている一部の抵抗を除いて抵抗・コンデンサ・LEDはチップ部品を使って実装しています。ケースは100円ショップで売っていたポリプロピレンのカードケースを加工して納めました。

・・・が、このケースを固定する場所がなかったりします。どうしようかな・・。

KXP84+SCP1000

KXP84-2050は一応動くようになったのですが、稀におかしなデータを吐くので困っています。

連続でXYZの各データを読みつづけると、静止状態にも関わらず突然X方向に大きくずれた値を出力します。しかもYZは何事もなかったかの様に動作しつづけますし、その後X方向も元の値に戻ってしまいます。SPIでのデータ転送時のビット抜けかとも思いましたが、YZには影響がなかったり、ビット抜けパターンには合致しなかったりするので、ビット抜けではないようです。パスコンは写真の通り秋月モジュールなので0.1uFと4.7uFのセラミックコンデンサ(目視ではわかりませんけど)がついていますので、そうそう問題ではないはずです。

時々誤動作する加速度センサでは困りますので、KXM52-1050の方に切り替えようかと思っています。

一方、SCP1000の方ですが、こちらは上手くいっています。

5/1の深夜から5/2の午前中にかけての室内の温度変化です。窓を少し開けて寝ましたので、明け方に温度が下がっているのがわかります。

同様に気圧の変化です。約2サンプル/秒のものを強引にgnuplotでグラフ化しましたが、適切にサンプリングするようにすれば面白そうです。