2013年 10月 11日

半導体の基礎 N型、P型

半導体って「導体と絶縁体の中間」って説明されるけど、実感としてよくわからなかった。自分の中では導体か絶縁体しかなくて、半導体は特別なイメージがあった。

しかし、調べてみると、まさに「導体と絶縁体の中間」という説明がそのままイメージとして理解できた。2種類の半導体 (N型、P型) について理解するのがてっとりばやかった。なぜ今までこれを理解しようと思わなかったのか、恥ずかしい。普通に Wikipedia に載っている画像がわかりやすかった。

導体は自由に動ける電子がたくさんある物質、絶縁体は逆に自由に動ける電子が殆どない物質、半導体はその中間。

N型 (Negative)

http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:N-doped_Si.svg

電子が多少余っている半導体。電子の電荷はマイナスなので、電子が多いと全体としては負、すなわちネガティブになる。

P型 (Positive)

http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:P-doped_Si.svg
電子が足りていない半導体。電子がない分、相対的に正、すなわちポジティブになる。この穴のことを正孔といい、電流と同じ方向に移動する。

PN接合ダイオード

P型とN型を接合すると、片方には電子が余り、片方には電子が足りていない状態になる。
接合部付近では、電子と正孔が結合してしまうので、何もない部分ができる。これが空乏層。

ここで、P型側に+、N型側に-の電圧をかける (順方向) と、ダイオード内に正孔・電子が供給され、空乏層が狭くなり、電流が流れはじめる。

逆に、P型側に-、N型側に+の電圧をかける (逆方向) と、ダイオード内の正孔・電子が減少し、空乏層が電圧に応じて増え、電流は流れない。

無線局運用規則の読み方

アマチュア局は、第8章とそこから示されている第4章だけ読めばいい。ぼーっとしていて、ほかの章をうかつに読むと微妙に違う規則があって紛らわしいので、読みかたに注意する必要がある。

http://www.tele.soumu.go.jp/search/area/all_index.htm

法規:特性周波数・割当周波数・基準周波数

ひととおり法規をやってみると、この3つがどうしても意味不明だった。

電波法施行規則 第二条

五十六  「割当周波数」とは、無線局に割り当てられた周波数帯の中央の周波数をいう。
五十七  「特性周波数」とは、与えられた発射において容易に識別し、かつ、測定することのできる周波数をいう。
五十八  「基準周波数」とは、割当周波数に対して、固定し、かつ、特定した位置にある周波数をいう。この場合において、この周波数の割当周波数に対する偏位は、特性周波数が発射によつて占有する周波数帯の中央の周波数に対してもつ偏位と同一の絶対値及び同一の符号をもつものとする。
五十九  「周波数の許容偏差」とは、発射によつて占有する周波数帯の中央の周波数の割当周波数からの許容することができる最大の偏差又は発射の特性周波数の基準周波数からの許容することができる最大の偏差をいい、百万分率又はヘルツで表わす。
|

http://law.e-gov.go.jp/htmldata/S25/S25F30901000014.html

割当周波数、特性周波数はなんとなくわかるような気がするけど、基準周波数の説明が意味不明すぎる。そのうえで、「周波数の許容偏差」を読むと、全く意味がわからない。

ググってみたり、よく理解に努めようとして要約すると以下のようになるようだ。

  • 特性周波数 → 外部から測定できる周波数 (実際出てる電波の周波数)
  • 割当周波数 → 免許状に書かれているやつ。アマチュアの場合帯域が広いのでイメージしずらい。許可された帯域の中央の周波数
  • 基準周波数 → 無線機に表示されている周波数

こう考えたうえで

五十九 「周波数の許容偏差」とは、発射によつて占有する周波数帯の中央の周波数の割当周波数からの許容することができる最大の偏差又は発射の特性周波数の基準周波数からの許容することができる最大の偏差をいい、百万分率又はヘルツで表わす。

は言葉のイメージさえ掴めれば、あとよく読めば実用上(?)十分に理解できるレベルになる

  • 発射した電波と割当周波数とを比べた値 (発射した電波が占有する周波数帯の中央の周波数、割当周波数)
  • 外部から観測できる周波数と無線機が表示している周波数を比べた値 (特性周波数、基準周波数)

が、一定の許容範囲にあること。現実と理想を比べてる。搬送波ありの信号で考えたら言葉さえわかれば言ってることは難しくない。

しかし、「発射によつて占有する周波数帯の中央の周波数」と「特性周波数」の違いがわかりにくい。AM (A3E) の場合はどちらも一緒になりそうだけど、単側波帯の場合は違いそう。USB の場合上にずれるのかな。調べてもよくわからなかった。

Mac で simavr + avr-gdb を使い AVR プログラムを PC 上でデバッグする

Mac の場合 AVR Studio を使えないので、いろいろ不便である。しかし一応開発環境がととのった。結構ググったけど、このようにして開発している人は少ないのか、はたまた情報発信しないのか、あまり gdb まで使ってやってる記事がなかった。

CrossPack-AVR のインストール

avr-gcc (AVR 用のクロスコンパイラー) や avrdude (書きこみツール) の Mac 向けにコンパイル済みパッケージ。配ってるのでインストールするだけでいい。

CrossPack for AVR を普通にダウンロードしてインストーラーからインストールするだけ。

普通 OS X の path_helper によって自動的に PATH が通るので、そのまま Terminal.app で avr-gcc が実行できるようになる。path_helper のパーミッションを落として使ってる場合自力で /usr/local/CrossPack-AVR/bin のパスを通す。

これさえ入れておけば実機開発はできる。

simavr の build

まずレポジトリを clone する。

$ git clone git://gitorious.org/simavr/simavr.git
$ cd simavr/simavr

simavr のビルドは CrossPack-AVR + Mac だと1発では通らない。以下のようにパスの指定が必要。あと、なんか変な状態になったりするので make clean と make を何回かやってみたほうがいいと思う。

make all V=1 AVR_ROOT=/usr/local/CrossPack-AVR AVR_INC=/usr/local/CrossPack-AVR/avr


これでシミュレーションまでできるようになった。

avr-project の Makefile 書き換え

CrossPack-AVR に avr-project というコマンドがついてくる。

$ avr-project Foo

とかやると Foo/firmware 以下に Makefile とかを作ってくれる。Foo.xcodeproj というのも作ってくれるけど、ハマりそうなので使ってない。

デバッグオプション付きでコンパイルするようにする。RELEASE=1 をつけない場合デバッグモード。最適化オプション -Os はどっちも付けてるんだけど、ちょっとどうすべきかわからない。デバッグ時 -Os をつけずに書きこむときだけ -Os をつけたらループが意図せず削除されたとき大変ハマりそうだなーと思う。いっそ -O0 のほうがいいのかもしれないけど……

ifeq ($(RELEASE),1)
COMPILE_OPT = -Os
else
COMPILE_OPT = -Os -g3 -gdwarf-2
endif

AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)  
COMPILE = avr-gcc -Wall $(COMPILE_OPT) -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)

でもってターゲットも足す

run:	all
	~/project/simavr/simavr/run_avr -g -mcu $(DEVICE) -freq $(CLOCK) main.hex &
	avr-gdb

さらに .gdbinit ファイルをつくる

file ./main.elf
target remote localhost:1234
load
break main
continue

make run をするとコンパイルされて、simavr をバックグランドで起動し、それにGDB接続する、とりあえず main 関数の最初で止まる (はず)。

自分は avr-project は使っていなくて、自作のテンプレート作成ツールを使っている AVR のテンプレート

実際のデバッグ

普通に GDB を使うだけだけどメモ

  • p foobar
    • 変数を表示
  • p/t PORTB
    • PORTB を2進数で表示
  • p set_bit(PINB, 1)
    • PINB の 1 bit 目を立てる (set_bit は自分で定義したもの)
    • 外部入出力をシミュレーションさせるのは結構骨が折れる感じなので、簡易的には、これで外部入力をシミュレーションできる
    • 外部入出力とかはもうさっさと書きこんでデバッグしたほうがトータルで早いと思う…

実機書き込み

書き込み装置は、ここで変にハマると自分には問題解決できる能力がないところなので、純正の AVR ISP Mark II を使った。

この場合 Makefile の PROGRAMMER は以下のようになる

PROGRAMMER = -c avrispmkII -P usb

DEVICE はチップ名にあわせる。ATTiny2313 なら、そのまま DEVICE = attiny2313 でいける。

AVR ISP Mark II は 3x2 PINヘッダなので、このままだとブレッドボートで使えない。なので 1x6 PINヘッダに適当に変換してる。手元にあったピンヘッダがついてる余ってる平行ケーブルを使った。持ってるブレッドボートが狭くてつらい。

その他メモ

avr-gdb 上での _delay_ms() が非常に遅い。

これはいわゆるビジーループなので、動作周波数を下げることで早くデバッグすることができる。

make run CLOCK=10
2013年 10月 10日

勉強

アンテナの設計とか測定とかをしているうちに、もうちょっとちゃんと無線工学を学んでみようということで、いろいろやってる。

しかし、実際はじめてみると、そもそも中学生レベルの数学がぜんぜんできないことがわかったので、高校受験用中学生向けドリルを買ってきてやってみた。やってみると、解きかたが全くわからないというわけではなくて、うる覚えであったとしてもだいたい答えまでは導ける (あるいは単に考えて式をつくれる)。ただ、とにかくひどく計算ミスが多い。とにかく多い。分配法則を適用するとき文字を1つかけわすれるとか、符号を間違えるとか、本当にひどい。

原因を考えみると、数字の計算(だいたいは九九だけど、足し算・引き算も)に意識がいきすぎていて、ほかのことまで考えが及んでいない。つまり、九九がまともにできてない。大変、根本的な問題である。先日は計算中に 7 × 9 がパっと出てこなくてあせった。ひどいとしか言いようがない。

普段の生活だと、まず暗算に頼ることがない。第一に自分の計算能力を全く信用していないというのがあり、計算機が手元にないことがまずないので、2桁以上の数字の四則演算からして全部計算機に丸投げしてる。全く計算について考えないで生きてる。おかげでこのザマだと思う (小学校のとき体に沁みわたりまで九九をやらなかったのがそもそもだけど)。

教訓としては、九九は本当に大事なので100万回ぐらいやったほうがいいし、できないと人生が終わると全国のこどもたちに伝えたい。

2013年 10月 06日

Scala で JOGL (OpenGL)

Scala から JOGL (Java で OpenGL を使うやつ)

JOGL はどれをダウンロードしていいのかサッパリわからないが、jogamp-all-platforms.7z というのが全部入りっぽいのでこれをダウンロードする。このファイルのありかがそもそも見つけられないと思うけど、http://jogamp.org/deployment/jogamp-current/archive/ にある。ほんとどれをダウンロードしたらいいかサッパリわからないし、どこからこのページに辿りついたのかよくわからないけど、とにかくこのページから jogamp-all-platforms.7z をダウンロードすれば良い。jogamp って何?って感じだけどとにかくこれでいい。

ぐ〜ぐるで調べると、情報が古いのがたくさんでてくるのでつらい。これが公式?っぽいので、ここを見るのが良さそう。これまたこのページに辿りつくが難しい。

クラスパスには2つファイルを指定するだけでいい。これ以外はむしろ指定すると scala がぬるぽ出したりしてよくわからないことになる。横着して *.jar とかしてはいけない。

-classpath /path/to/jogamp-all-platforms/jar/gluegen-rt.jar:/path/to/jogamp-all-platforms/jar/jogl-all.jar

JOGL のチュートリアル にあるサンプルを移植すると以下のような感じになるっぽい。なんとなく awt ではなく newt を使うようにも変えてる。

チュートリアルだと animator.add() が余計でエラって動かない。あとなんかいろいろハマったけど忘れてしまった。とにかくこれで動く。

//#!scala -classpath /path/to/jogamp-all-platforms/jar/gluegen-rt.jar:/path/to/jogamp-all-platforms/jar/jogl-all.jar

import javax.media.opengl._
import com.jogamp.newt.event.WindowAdapter
import com.jogamp.newt.event.WindowEvent
import com.jogamp.newt.opengl.GLWindow
import com.jogamp.opengl.util.FPSAnimator

object Sketch {
	def main (args: Array[String]) {
		val glp = GLProfile.getDefault
		val caps = new GLCapabilities(glp)

		val window = GLWindow.create(caps)
		window.setSize(300, 300)
		window.setVisible(true)
		window.setTitle("TEST")

		window.addWindowListener( new WindowAdapter() {
			override def windowDestroyNotify (e : WindowEvent) {
				exit(0)
			}
		})

		window.addGLEventListener( new GLEventListener () {
			var theta : Double = 0
			var s : Double = 0
			var c : Double = 0

			override def display (drawable : GLAutoDrawable) {
				println("display")
				update
				render(drawable)
			}

			override def dispose (drawable : GLAutoDrawable) {
				println("dispose")
			}

			override def init (drawable : GLAutoDrawable) {
				println("init")
			}

			override def reshape (drawable : GLAutoDrawable, x : Int, y : Int, w : Int, h : Int) {
				println("reshape")
			}

			def update () {
				theta = theta + 0.01
				s = Math.sin(theta)
				c = Math.sin(theta)
			}

			def render (drawable : GLAutoDrawable) {
				println("render")
				val gl = drawable.getGL().getGL2();

				gl.glClear(GL.GL_COLOR_BUFFER_BIT);

				gl.glBegin(GL.GL_TRIANGLES);
				gl.glColor3f(1, 0, 0);
				gl.glVertex2d(-c, -c);
				gl.glColor3f(0, 1, 0);
				gl.glVertex2d(0, c);
				gl.glColor3f(0, 0, 1);
				gl.glVertex2d(s, -s);
				gl.glEnd();
			}
		})

		val animator = new FPSAnimator(window, 60);
		animator.start();

	}

}
2013年 10月 05日

モールスコードを再生できるだけのページ

をつくった。

だいたい、符号って長点短点を可視化して見せてしまっていることが多いんだけど、あれはモールス学び初めの人には害でしかないので、そういったものが一切ない、すなわちそれぞれ音だけ聞けるページが欲しくて、作った。

20wpm 固定で鳴らしてる。Web Audio なので対応ブラウザならスムーズに鳴るし、スマートフォンでも問題なく鳴る。

2013年 10月 02日

バックアップの取り方を改良

途中まで作業をしてしまってから気付いたけど、ExFAT のディスクは TimeMachine のバックアップ対象にできないらしい。ひどい…… 以下の方法ではダメ

現状

2TB のディスクが2つ

  • 2TB
    • Backup (ExFAT)
  • 2TB
    • 1TB Backup2 (ExFAT)
    • 1TB Time Machine

Backup と Backup2 は基本的に同じもの (ミラーリング) しているつもりだけど、スクリプト以外でバックアップしたものは、めんどうくさくてちょっとずつずれてきてしまっている。これでは意味がない。

また、Backup ディスクは Windows からでも読み書きできるように ExFAT にしているのだけれど、これはジャーナリングができないせいか、USB から不意に外すと確実に fsck を要求されるのでだるい。2つ ExFAT のパーティションがあるだけで、fsck を2本走らせないといけない。アホだ。

なんとなく、Time Machine で外部ディスクもバックアップできないかな、と思ってググったら、それもできるということを知った。なのでバックアップ方法を変えることを考えた。

理想

  • 2TB
    • Time Machine
  • 2TB
    • Backup (ExFAT)

として、Time Machine のバックアップ対象に Backup (ExFAT) を含めるようにする。これで何も考えなくてもよくなりそう。Backup ディスクの取り扱いさえちゃんとすればよくなるので、今よりはだいぶマシだし、Time Machine に入れこむことで信頼性が上がる。

Time Machine ディスクが死ぬと悲しいけど、それはそもそもそういうものだし、最新の版については必ず2系統存在する感じなのでいいかな。

手順

しかし、現状で Backup2 + Time Machine というパーティションがあり、これを Time Machine パーティション1個にしくても、動かすことができない。別に1本ディスクがあればいいんだけど、あいにくないのでなんとかしないといけない。

  1. Time Machine を止める
  2. Time Machine パーティションのディスクイメージを Backup (ExFAT) に作成する
    • ExFAT なのでパーミッションとかが怪しい気がするのでディスクイメージ化してバックアップ
  3. Backup2 + Time Machine が入ってるディスクを Time Machine パーティション1個 にしてフォーマット
  4. Backup (ExFAT) にとった Time Machine.dmg から Time Machine パーティションを復元
  5. Time Machine の設定で「ディスクの選択…」で新しい Time Machine パーティションを指定
  6. Time Machine を有効化して今まで通りバックアックが効くか確認
  7. Backup (ExFAT) にとった Time Machine.dmg は消す
  8. Time Machine のバックアップ対象に Backup ディスクを追加する
  9. Time Machine フルバックをかける

備考

  • ディスクをフォーマットするときは GUID パーティションテーブルすること