2006/08/31(木)PCのコンデンサ置き換え修理

C3M266の修理

自分はメインとしてC3M266というマザーボードの、Socket370時代のマシンを使っています。たまに処理能力的に足りなくなるときは、Atholon XPなマシンを起動しますが、普通はこちら。大抵のことは用が足りますし、ファンも12cmファンが低速回転してるだけので実に静かです。

しかしこのマシン、夏に入ったあたりから様子がおかしくなりました。起動中に突然リセットがかかります。下手をすると、最終的に起動するまで5回ぐらいリセットがかかり5分とか待たされます。何事かと思って、ケースを開いてみるとマザーボードを見てみると案の定コンデンサが吹いてました

pc01.jpg
pc02.jpg
pc03.jpg

約30個載っているのですが、ほとんど全部壊滅状態。マシンを新調してもそれまでですが、物を大切に&省電力マシンがいいのでこのまま使い続けることにしました。ほぼ同時期に、家サーバとして使用しているC3マシンもコンデンサが飛んで不安定になっていたため、2マシン分のコンデンサを秋葉原に行ったついでに買い込みます。

秋葉原にて

……1万円也(汗) 絶対新しくした方が安いというつっこみはナシです。中途半端に直すのも難なので、どうせならとニチコンHNという高級品を物量投資してみました*1

楽しかったのが、某有名「海神無線」のとなりに某お店。HNを買おうとすると「これ(HN)は、見た目がゴールドだから素人さんはいいと騙されるけど、2000時間しか保たないからやめとけ。こっち(HE)の方は6000時間もつから在庫を入れ替えてるんだ。よその店は知らないけど、うちはちゃんと勉強してるんだ」と力説。いや、まあそりゃそうだけど、超低インピーダンス品(HN)と単なる低インピーダンス品(HE)をリプル除去でなく時間だけで比べるってどうよ……??って話しで(汗) まあおかげで在庫あるだけでしたが、安くHNが手に入ったからいいんですけどね(^^;;

足りない分は三栄電波でHZを購入しました。店頭にきちんとリプル電流が表示してあります。こういうのを勉強してると言うと思うんだけどなぁ。

載せ替え

さて部品を調達したところで、コンデンサの載せ替えです。グランド側のパターンはベタアースなので、40Wハンダごてを調達してきたのですが、イマイチ温度が上がらない*2。結局、ダイソー40Wの世話になりながらコンデンサをはずしていきます。さすがに30個以上あると疲れる疲れる。

broken_c.jpg

今度は付ける作業です。外す作業より若干楽かな……。ということで付け終わりました。ニチコン HN(or HZ)がこれだけ並ぶ姿は圧巻です! が、CPUがPentium3では、ほとんど意味はなし(苦笑)

new_pc01.jpg
new_pc02.jpg
new_pc03.jpg

というわけで電源on~。「おおーーー、普通にリセットかからず起動するよ(笑)」。というわけで修理完了でした。

粗悪コンデンサ三昧

しかし、過去こうやって何枚のマザーボートを修理したことか……。気になったので、今まで外したコンデンサを全部置いてみました。

broken_c2.jpg

こいつはちょっと多すぎませんか?(汗 誰かこのコンデンサ全部並列につないでアンプの電源にするといいよ(笑

*1 : 秋葉原など個人でPC用コンデンサを入手する場合、ほとんど値段代わらないのですよね……。個人的にはロットで買いたいのですが >ニチコン

*2 : goot シリーズ

2006/08/22(火)電流出力アンプの解析

この前の続き。広域特性をもちょっとフラット(おだやか)にしようということなのですが*1、いくつか方法を思いつくものの、いかんせん目安がない。というけとで、改造PCスピーカー用の解析をするために、今回の回路図に対して直接立式してみました。

v_o=A(v_i-v_s)
v_o=\frac{1}{c_1}\int_0^t idt  + R_Li+L\frac{di}{dt}+(i+i_f)R_s
v_o=(R_f+R_g)i_f + \frac{1}{c_2} \int_0^t i_fdt + (i+i_f)R_s
v_s=v_o-i_fR_f

を解いて、伝達関数H(s)=\frac{I(s)}{V_i(s)}を求めればいいのですが……。面倒になったので、今日はここまで(笑) これを見ている学生がきっと解いてくれるでしょう(ぉぃ

*1 : 考えようによっては十分フラット=電圧出力では絶対に実現できないフラットなのかもしれないけど

2006/08/18(金)電流帰還アンプ(電流出力アンプ)

電流出力アンプ

すごい昔頂いたけF社製PC用スピーカーを普段使っています。アンプの電源いれてもいいのですが、画面に対して左右においてないのでPCのときはPCスピーカー。

比較的素直な(ラジオ的な)音で嫌いではないし常用しているのですが*1、いかんせんかまぼこ(高域と低域がでない)*2。というわけで、中の基盤を丸々取り替えて電流出力アンプを作ってみました(通称「山本式電流帰還アンプ」)。

なかなか面白いです。PCスピーカーらしかぬ音がします。というわけで、今回は簡易報告メモ。アンプ(パワー)ICはTA8217P

  • 定位もしっかりして、高域もハッキリ出て見違えるようです。(若干出過ぎかも)
  • 試しにFE83EなBHスピーカーにつないでみたら、ラウドネスがかかりすぎたような変な音がして気持ち悪かった。中域の音がすっぽり抜けた感じ。
  • 電流駆動なので、スピーカーのインピーダンスが上昇する低域と高域のレベルがあがる傾向にある。この特性から考えると貧弱なかまぼこスピーカーユニット向きよって、FE83Eのようなまともな(ましてハイ上がりな)ユニットにつけると悲惨。
  • まともなユニットで使いたかったら、インピーダンス調整用に抵抗(8Ω~20Ω?)や抵抗+コンデンサ*3をスピーカーに並列に付けて、その電流も帰還抵抗に入れる必要があると思われるけど、Cut and Tryになることは間違えない上、電流出力アンプの特徴である素早い立ち上がり特性も若干失われそう……。*4

あと電源。ACアダプタから直接2200uFのコンデンサで平滑化してるのですが、オシロでみると20mV程度のリップル(商用電源周波数)が出てる……。10000uF~20000uFを付けるか、簡単でもいいから安定化した方がいいようです。どうもSNが悪いなぁーと思ったら(^^;;

使用中(追記)

ちょっと回路を対策する時間が取れないので、イコライザでハイをだだ下がりに補正して聞いてる(使用してる)のですが、すごいですねこれは。オーケストラが聴けます。音の定位といい、広がりといい、全体の鳴りっぷりといい、こんな安物PC用スピーカーでこれだけの音がでるなんてほんとに恐ろしいことこの上ないです。

ちなみに。ネットを検索していると、DFなる値(限定された条件の下で使える簡易式)を持ち出して、低域が制動されないとか言っている方がいますが、大嘘です。伝達関数を立ててシミュレーションを行えば、電流出力では入力波形に従って強烈にボイスコイル電流が制御されることがすぐに分かります。(←機械的な部分と電気的な部分を混同して記述していました)

さらに追記

電流駆動方式の場合、低域の機械的共振に対して(ほぼ)無力であることを確認しました*5。単純に電圧駆動、電流駆動のどちらが良いかと言われれば一長一短ですが、PC用スピーカーの改造法としては電流出力は十分魅力的だと思われます。細かい考察はこちらの記事

追記

電流駆動アンプの製作という記事を書きました。最新情報になりますご参照ください。とどのつまり、F特をフラットにしてあげれば、凡庸なスピーカーユニットは例え電流駆動しても凡庸な音がします。

*1 : 2wayのPCスピーカーの中には気持ち悪い音がするものが結構あるのです……

*2 : 手持ちアンプ+自作スピーカーと比べる方が悪いという説もあるけど(苦笑) あと、電源スイッチが電源のスイッチでははなく電源ランプスイッチという仕様が嫌になった<電気の無駄

*3 : Zobelネットワーク

*4 : 後日計算してみます

*5 : ただし、コメント欄で揚げられたサイトの考察は、理論的道筋として正しいとは思えませんのでご注意を

ナップサック問題をポケコンで解く

ナップサック問題は重いらしい

手元に舞い込んできたとある資料によると

ks.gif

この問題は,14個ある荷物を入れるか入れないかで考えるので 214 = 16,384 通りの組合せとなり,すべての組合せをコンピュータに計算させると最適な組合せ(解)を見つけるのに数十分もかかってしまいます。(中略)遺伝的アルゴリズムを用いると,わずか数秒で答を求めることができます

要するにGAの優位性を訴えているのですが、この程度の問題に、どうやったら数十分もかかるのか疑問で仕方ありません。というわけで実際に試してみました。

C言語で解いてみる

Pentium3@800MHzの、今となっては決して速くないCPUとgcc3.3を使いこの問題を総当たりで解いてみました。ソースファイルはこちら

nabe~$ gcc -O2 ks.c -o ks.o
nabe~$ time ./ks.o
Best pairing : 0(A) 1(B) 2(C) 4(E) 6(G) 7(H) 9(J)
Best value   : 530

real    0m0.005s
user    0m0.001s
sys     0m0.004s

プログラムの起動時間を入れても5ms、実際に問題を解いている時間だけみれば1msです。数秒をうたっているGAよりもはるかに速い結果です。困ったことになってしまいました。どうやら実験に使った環境が速すぎたようです。

JavaScriptで解いてみる

遅いマシンをすぐに用意できればよかったのですか、今更Pentium(初代)レベルのマシンやそれ以前のマシンを用意するのも大変です。マシンを遅くする代わりに処理系を遅くしてしまうことにしました。きっとコンパイルしてマシン語に変換されたのが問題だと思うので、処理が遅い言語としてインタプリタを使用することします。

ブウラザがあればどこでも動くJavaScriptによる実装です。

14個の荷物について計算します
最大重量 = 200
組み合わせ : A B C E G H J
最的値 = 530
計算時間 = 90 ms

実行マシンはCeleronの1GHzで、gccと比べても実行環境として100倍以上遅いのですが1秒を切ってしまいました。単純計算で100MHz程度のマシンをもってきても1秒程度で答えが出るようです。どうしましょう、数十分どころか、数秒と言われるGAよりも高速です

考えが甘かった。まだまだマシンが速すぎたようです。もっと決定的に遅いマシンならいいのですが、身近に、もっと遅くてプログラマブルのコンピューターがなかなか思い当たりません。ファミコン? 携帯? あーこれがありましたっ!

ナップザック問題をポケコンで解いてみる

pc-g815.jpg

まず簡単にスペックをおさらいしておきましょう。

型番SHARP PC-G815
CPUZ80相当 3.58MHz
メモリ(RAM)32KB

3.58MHzです! 今までより格段に遅いマシンです。最近のマシンと比較すれば1000分の1のクロックで「64ビットだー!」と世間が騒がしいこのご時世に8bit。単純計算で8分の1ですが、潜在的な能力差はその数倍にも昇ります。

これだけのマシンを持ってくれば誰も速いなんて文句を付けるような無粋な人間はいないと思いますが、念には念を入れて次の選択をしました。

プログラム言語BASIC

(パソコンと比べれば)劇遅なZ80の上で動くBASICインタプリタ。もはや文句はないでしょう。

さて実際にプログラムを打ち込むのですが、たった4行の狭い画面に打ち込むのが大変な上、BASICの文法が(CやPerlに慣れた今になっては)違和感ありまくりで一苦労でした。できあがったソースはこちら

きちんと正解が出るのか走らせてみましょう。多少緊張しつつ、RUNと入力します。

pc-g815_kekka.jpg

解けました、解けました。さて気になる時間は135秒!(手動計測) 2分15秒ですから、さすがに時間掛かってます。ですが、数十分どころか、数分にすらなりません! わざわざインタプリタでこれですから、普通にCで書いたとして一体どんなマシン持ってきたら数十分になるでしょう。誰か教えてっ!!

2006/08/09(水)Perlによるbase64エンコード/デコードの実装

エンコード

MIME::Base64(C実装)を使えば速いのですが、メールのタイトル程度でそこまでする必要はないし*1、かと言って日本で有名な某MIMEルーチンは、巨大変換テーブルという非効率な実装なので、自作した奴。

# テーブル
my $base64table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
# 変換処理
$subject =~ s/(\e\$[\@B].*?\e\([BJ])/ '=?ISO-2022-JP?B?' . &base64encode($1) . '?=' /eg;

sub base64encode {
	my $str = shift;
	my $table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
	my $ret;

	# 2 : 0000_0000 1111_1100
	# 4 : 0000_0011 1111_0000
	# 6 : 0000_1111 1100_0000
	my ($i, $j, $x, $y);
	for($i=$x=0, $j=2; $i<length($str); $i++) {
		$x    = ($x<<8) + ord(substr($str,$i,1));
		$ret .= substr($table, ($x>>$j) & 0x3f, 1);

		if ($j != 6) { $j+=2; next; }
		# j==6
		$ret .= substr($table, $x & 0x3f, 1);
		$j    = 2;
	}
	if ($j != 2)    { $ret .= substr($table, ($x<<(8-$j)) & 0x3f, 1); }
	if ($j == 4)    { $ret .= '=='; }
	elsif ($j == 6) { $ret .= '=';  }

	return $ret;
}

*1 : Perlは外部モジュールロードが速くない

デコード

# テーブル
my @base64ary = (
 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0,  0, 0, 0, 0,	# 0x00~0x1f
 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0,  0, 0, 0, 0,	# 0x10~0x1f
 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0,62,  0, 0, 0,63,	# 0x20~0x2f
52,53,54,55, 56,57,58,59,  60,61, 0, 0,  0, 0, 0, 0,	# 0x30~0x3f
 0, 0, 1, 2,  3, 4, 5, 6,   7, 8, 9,10, 11,12,13,14,	# 0x40~0x4f
15,16,17,18, 19,20,21,22,  23,24,25, 0,  0, 0, 0, 0,	# 0x50~0x5f
 0,26,27,28, 29,30,31,32,  33,34,35,36, 37,38,39,40,	# 0x60~0x6f
41,42,43,44, 45,46,47,48,  49,50,51, 0,  0, 0, 0, 0	# 0x70~0x7f
);
# デコード処理
$subject =~ s/=\?ISO-2022-JP\?B\?([A-Za-z0-9\+\/=]*)\?=/ &base64decode($1) /eg;

sub base64decode {
	my $str  = shift;

	my $ret;
	my $buf;
	my $f;
	if (substr($str, -1) eq  '=') { $f=1; }
	if (substr($str, -2) eq '==') { $f=2; }
	for(my $i=0; $i<length($str); $i+=4) {
		$buf  = ($buf<<6) + $base64ary[ ord(substr($str,$i  ,1)) ];
		$buf  = ($buf<<6) + $base64ary[ ord(substr($str,$i+1,1)) ];
		$buf  = ($buf<<6) + $base64ary[ ord(substr($str,$i+2,1)) ];
		$buf  = ($buf<<6) + $base64ary[ ord(substr($str,$i+3,1)) ];
		$ret .= chr(($buf & 0xff0000)>>16) . chr(($buf & 0xff00)>>8) . chr($buf & 0xff);

	}
	if ($f>0) { chop($ret); }
	if ($f>1) { chop($ret); }
	return $ret;
}

ライセンス

修正BSDで。