途中まで作業をしてしまってから気付いたけど、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 パーティションテーブルすること

をつくった。

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

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

  1. トップ
  2. ham
  3. モールスコードを再生できるだけのページ
  1. トップ
  2. モールス
  3. モールスコードを再生できるだけのページ

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();

	}

}
  1. トップ
  2. tech
  3. Scala で JOGL (OpenGL)

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

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

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

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

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

  1. トップ
  2. ham
  3. 勉強

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

しかし、調べてみると、まさに「導体と絶縁体の中間」という説明がそのままイメージとして理解できた。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

  1. トップ
  2. ham
  3. 無線局運用規則の読み方

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

電波法施行規則 第二条

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

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

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

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

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

こう考えたうえで

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

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

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

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

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

  1. トップ
  2. ham
  3. 法規:特性周波数・割当周波数・基準周波数

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
  1. トップ
  2. tech
  3. Mac で simavr + avr-gdb を使い AVR プログラムを PC 上でデバッグする
  1. トップ
  2. avr
  3. Mac で simavr + avr-gdb を使い AVR プログラムを PC 上でデバッグする
  1. トップ
  2. arduino
  3. Mac で simavr + avr-gdb を使い AVR プログラムを PC 上でデバッグする

まず何を作ろうという感じだけど、エレキーならはじめて作るマイコンの教材としては、LEDチカチカレベルで簡単だし、なおかつ実用性があるので、ちょうどいい。自分で作れれば何かしら挙動を変えたいときも技術力の許す限りは自由にできるのでやってみてる。

検索するといろいろ作っている人がいるけど、結構難しい感じまで作りこまれたのが多くてつらい。しかし この作例 はプログラムも外付け部品もかなりシンプルだったのでとても参考にした。特にプログラム部分は、割込みを使って非常に少ないコードで基本機能が完全に実装されていて、実装の気が楽になった。

設計の指針

  • いわゆるエレキーの基本機能
    • 長短点メモリー
    • インヒビット
    • スクイズキー
  • スピードコントロールできること
  • 1.2V電池2本で長いこと動くこと
  • サイドトーンを発音できて、単体でも練習用として使えること

最初の実装

最初の実装は全部で80行ほど。スピードコントロールなどもなくて、動作だけ動くかやってみた感じ。この時点ではブザーを鳴らす部分とかもないので、LED をチカチカさせていた

ブザーを鳴らす

一番お手軽なのは電圧かけるだけで鳴るやつを使うことだろうけど、手元にあるのは普通に圧電スピーカーだし、鳴る周波数変えれたら嬉しいので PWM を使って出力することにした。

16bit タイマーでやったんだけど、動作を理解するまでがまず意味不明で大変だったのと、動作を理解しても、比較値やトップ値に対応する実際の変数名がわからなくてひたすら仕様を読んだりした。しかしまだちゃんと理解しているという感じになってない…… 一応鳴るようにはなったし、ピポッって鳴らしたりもできるのでとりあえず良い。

出力

出力はリグと繋ぐ部分。事前に計ったところ、リグのキーイング端子は 5V がかかっていて、スイッチオンのときは 1mA 未満しか流れない。なのでほんと適当にスイッチすればよさそう。

  • トランジスタスイッチング
    • 安い・簡単・消費電力多め
  • FETスイッチング
    • 消費電力少なめ・少々高い・回路電圧からして使えるFETを探すのがめんどう
  • フォトカプラ
    • まだ試してない
トランジスタスイッチ

最初に試した。手元の 2SC1815Y のベースに5.6kΩ程度つけてエミッタ接地でスイッチングさせた。動作としては問題なくうまくいく。

FETスイッチ

エンハンスメント型でゲート電圧2.4V付近で十分電流が流せればなんでもいいはずだけど (ほんとうかな)、定番のスイッチ用 FET というのがよくわからない 、とにかく売ってるやつで適していそうなやつを探した…… CPAN からモジュール探すより難しい。

データシートを見た感じ、2SK2232 のほうが低い電圧でもかなりの電流 (3Aぐらい) が流せるようになるみたいだけど、だいぶ高い。2N7000 は 2.4V 程度だと数十mAしか流せない。

今回の用途だと、まずDS間に大量に電流が流れることがないので 2N7000 で駆動してもよさそうだけど、よくわからない。試した感じではうまくいった。

スピードコントロール

とりあえず手元にある ATTiny2313 には ADC がないので、お手軽にボリューム使ってスピードコントロールするみたいのはできない。コンデンサの充電時間を利用してADCぽいことをするというのをやってる人もいるけど、だいぶ面倒そうだし、そこまでするなら普通に ADC 内蔵のチップを買ったほうがいいな、という気分。ATmega168 というのも手元にあるけど、今回の用途ではオーバースペックすぎて使う気が起きない。

しかし、よくよく考えてもみると、そこまで執拗にボリュームというインターフェイスを使いたいわけではなくて、むしろデジタル的に 15wpm 〜 30wpm 程度を 1wpm 単位で切り替えられたほうが、相手に「QRQ25wpm」とか言われたときに対応しやすいのではないか? と思ったので、プッシュスイッチ × 2 を up/down スイッチとしてスピードコントロールをすることにした。

ただ、この方法だと、何らかの方法を別途用意しないと、現在設定している速度がいくつなのかわからなくなる。

  • up/down 同時押しか何かで現在の設定をサイドトーンに出力
    • 簡単で良さそうだけど急いでるときはだるい
  • up/down 同時押しか何かで一定時間 2桁の7セグを駆動
    • IO使いまくる
  • I2C 液晶をつける
    • TINY だと面倒

と考えた結果、ボタン長押しでサイドトーン側に現在の設定を鳴らすことにした。

ボタンの同時押し

up/down ボタンだけでできるだけ多くの操作を割り当てたい。具体的には

  • 上記の通り、ボタン長押しで速度を発音
  • ボタン同時長押しでエレキーとしての機能を切るモード (調整のときとかに必要)

しかし、これは実際かなり大変で時間がかった。長押しはそんなに難しくないけど、同時押しはとにかくめんどうくさい。似たようなことをやってる人がいた ので、処理のしかたはほぼパクりつつ、PIND にしかスイッチがないので、PIND を一括で状態管理するような感じにした。

しかし、同時押しはどちらかが必ず先に押されるわけだし、通常の長押しと競合してしまったりする。頑張って判定する必要があった。

サイドトーンのオフ

リグに接続している間は当然サイドトーンを切りたい。しかし、スピードを発音したりするので、完全にスピーカーから何も鳴らさないというわけにはいかない。なので自由が効くソフトウェア側で処理するようにしたいと考えた。

しかしこれが曲者で、スイッチ付きジャックのスイッチ部分が信号ラインと一体でまずい。

説明するのが面倒だけど、リグ側からかかる電圧より、こちらの電圧のほうが低いので、ダイオードを1本入れて対処した。あやうい感じで、これでいいのかよくわからないけど、挙動的には望むものになった。

消費電力

何もしない状態だと 8MHz で動かして常時 2mA ぐらい流れる感じだったので、スリープモードとかを調べて実装してみた。

電源電圧 2.4V

  1. 何も対策しないと消費電力 約2mA、単3エネループ (1900mAh) 2本直列だと、950時間、約40日
  2. 毎ループアイドルにするようにする 0.82mA 同約96日
    1. キーの状態を見にいく割込みは生きているので、そのタイミングで毎回起きて、何もしてなかったらまた寝る
    2. 入力がない限り何もしないプログラムならお手軽に低消費電力にできる感じ
  3. 一定以上経つとパワーダウンする 54.9uA 同約1442日
    1. 10秒程度アイドル状態が続いたらパワーダウンモードに移行する
    2. キーの入力状態が変更されると、そこで割込みがかかって起きる
    3. 生きてるものが殆どなくなるので、さすがに制約が多く、ちょっと考えないとうまくいかない感じ

と、結構下げることができた。

動作周波数を1MHzまで下げることでさらに半分以下になったりするけど、while (--t) _delay_ms(1) のオーバーヘッドが無視できなくなるのか、符号のスピードがかなり遅くなってしまうので、やめてしまった。頑張ってオーバーヘッドをさっぴいて delay するようにするか、根本的に設計をみなおすかしないとだめそう。

最低動作電圧

現状

  • マイコン単体だと 1.5V 程度まで動く
  • 出力FETがオンする最低の電源電圧が 2.27V ぐらい。

電源はエネループを想定しているので、2.1V 程度まで動くと嬉しい。今だとちょっと高めで止まってしまう。FET のゲート抵抗をもっと低くしたらいいかもしれない。逆に、2.1V 程度になったら過放電を防ぐためにもちゃんと止まってほしい。むずかしい。

回路図

前述の通り、出力と、PB4(16pin) がダイオード経由で接続されてる。接続されているとき、リグからかかる電圧が PB4 にかからないようにという意図だけど、これでいいのかわからない。逆にこちらからリグ側へは制限されていなくてよくなさそう (プルアップされてるので電圧がかかってる)。接続されていない場合は接地される。もっといい方法がないか知りたいけど、手掛かりがない。

パドル側にはいずれもバリスタをつけてる。パドルは接点が露出したスイッチなので、静電気に気をつかわないとまずそうだなと思ってつけてるけど、これも自己判断なのでこれであっているかわからない。

  1. トップ
  2. tech
  3. AVR でエレキーをつくってる
  1. トップ
  2. avr
  3. AVR でエレキーをつくってる
  1. トップ
  2. arduino
  3. AVR でエレキーをつくってる

割込みタイマーによるカウンタを使った delay_ms に実装しなおしたら 1MHz で動かしても符号が著しく遅くなることがなくなった。

この状態で消費電流を測る

  • アイドル状態 0.38mA
  • パワーダウン状態 62uA
  • キーイング中 0.55mA

delay 中も sleep するようにしたのでキーイング中の消費がだいぶ減ってる。

常時キーイングしてても144日ぐらい持つ。普通ありえないので、1日あたり2時間キーイングとすると、771日でだいたい2年持つ計算 (実際は自然放電されるからもっと短いけど、十分長い)

さらに減らすにはどうしたらいいだろう。チップスペック的にはパワーダウンモードだと0.1uA未満しか流れないみたいだけど、現状の回路だと多少流れてる。プルアップしてるのがわるい?

スリープ前にピン設定を変える

リグとの接続を見る端子がプルアップしているのをスリープ時にオフにすればいいことがわかった。これで

  • アイドル状態 0.38mA
  • パワーダウン状態 10.8uA
  • キーイング中 0.55mA

これで1日2時間キーイングで1440日に…

アイドル中、キーイング中の消費電力はこれよりもっと減らせるだろうか……

ISP Programmer の罠

AVR ISP Mark II を繋いでいると、パワーダウンモードでも10uAほど流れるようだ…… なんとはずしただけで 0uA (測定限界未満) になってしまった。これで同条件で 1693日持つ計算になった。上のプルアップを一時的にやめるというのもやる必要がなかった。

  1. トップ
  2. tech
  3. AVR 消費電力を減らす
  1. トップ
  2. avr
  3. AVR 消費電力を減らす
  1. トップ
  2. arduino
  3. AVR 消費電力を減らす

ダイオードだけ入れて対処したのがどうもひっかかっていて、やはりまずい気がするので、やめた。リグ側から電圧がかかっていないとき、こちら側から電圧がかかってしまうのが気持ちわるい。

リグ側からかかっている電圧を使ってFETをスイッチし、接続されているときだけ、特定のプルアップしているピンをグラウンドに落とすような感じにした。スイッチを使わず、実際に接続されているかどうかを見れるようになったので、ジャックは挿しこまれているけど、リグの電源がついていない場合なんかには機能的にも前より便利になった。

素直にこうしとけばよかった。これでそんなにまずいことはない、と思う……

懸念していた点が解消されたので、ブレッドボートをやめてユニバーサル基板に実装した。

今まで、回路図からユニバーサル基板に落とすときはいきあたりばったりでやっていたけど、今回はプリント基板作成ツールを使って事前に実装を考えてみた。

いろいろ、プリント基板を作れるソフトウェアはあるんだけど、どれも微妙に使いづらくて難しい。自分だけの最高の部品ライブラリを作ってからじゃないと基板作成ができないとか、そういうアレがある……

今回はいくつか試した結果、Fritzing という OSS の、プリント基板ビューを使ってやってみた。ビューがいくつかあって楽しいソフトウェアなんだけど、やはりこれも回路図やブレッドボートビューを使う場合、ライブラリを作るあげるのが面倒くさい。ただ、配線を試行錯誤やる程度なら、別の部品を代用して使っても問題ない。

しかし配線を試行錯誤するのも結構つらくて、選択したくないものが選択されてしまうことがものすごく多い。そのためのロック機能がある、と思いきや、ロックをかけても選択できてしまうので意味がない。結果、一切あたり判定が存在しなくて動かすことができない部品とかが存在する (一度かぶっているのをとれば移動できるけど)。かなり辛い。

  1. トップ
  2. tech
  3. AVR エレキー、リグの接続を判定して内蔵ブザーを切り替え
  1. トップ
  2. avr
  3. AVR エレキー、リグの接続を判定して内蔵ブザーを切り替え
  1. トップ
  2. arduino
  3. AVR エレキー、リグの接続を判定して内蔵ブザーを切り替え

今まで kaise の SK-6201 というテスターを使っていたけど、中学生ぐらいから使っていて、電流計の表示にオフセットがあったり、測定レンジが狭かったりで不便だったのでこの際に新調した。

三和電気計器 SANWA デジタルマルチメータ バックライト搭載 CD771 - 三和電気計器

三和電気計器

4.0 / 5.0

電流のレンジが大幅に増えてすごく便利になった。ただ、前のテスターだと値に大きな変化があったときに音が鳴る機能があって気に入っていたんだけど、これにはなくて残念。

サンワは測定器メーカーとして有名なようです。

  1. トップ
  2. tech
  3. テスターを新調した

PC からモールス符号を発生させて無線機に入力するものが欲しいと思っていた。当然既にそういうのはあるんだけど、どうも気に入るのがないので、必要な機能だけ自分で実装する。

基本の要件としては

  • クロスプラットフォームであること
    • というか Mac で動くこと
  • USB バスパワーで動くこと

なので、簡単そうでいろいろ教材としても楽そう。

クロスプラットフォームで面倒なドライバを書かなくてすむ方法は HID デバイスとして作ることだと思うので、そのように作ることにした。また、USB 用の外部チップとか用意したくないので V-USB (AVR マイコン上で USB を処理できるライブラリ) を使うことにした。

いろいろやってなんとか2日ぐらいで最低限の機能の実装ができたのでいろいろメモしておく。

回路図とコード

コード: https://github.com/cho45/AVR-USB-CW


現状制作途中のものなので、実際使う際に必要なリレー部分とかは書いてない。

現状だとダイオード2本で約1.4V程度電圧降下させて 3.3V〜3.6V 程度を作りだす方法を使ってる。V-USB の Wikiに書いてある方法の1つ。

左下のはそのうち試してみたい回路で、AVR自体には5Vをそのまま供給して、信号ラインだけ 3.6V にツェナーダイオードで電圧降下させる。電源電圧を3.3V程度にしてしまうと、動作周波数が 12MHz 程度までしか保証されないので、16MHz や 20MHz で動かすならこちらのほうが安定しそう。

V-USB

まず examples/hid-{data,mouse} を動かして、ふむふむと思いながらやってみたけど、なかなかハマった…… HID デバイスを作ろうとするとデフォルトの usbconfig.h から結構書きかえないといけないんだけど、それを知っていないとだめなのでつらかった。

usbconfig-prototype.h から作るのではなく、example/hid-* のをコピってくるほうが確実に動くと思う。

まだコントロール転送しかできてない。少なくともインタラプト転送はやることになりそうだけどデバッグがだいぶ大変 (追記:インタラプト転送は Mac + libusb だとできなかった)。

あと、自分で設定している割込みの頻度が高すぎると STALL しやすい…… クロック周波数にしても、こういった処理にしても結構シビアなので気を使わざるを得ない……

HID のレポートデスクリプタ定義は、大本の仕様書がどこにあるのかわからないのでコピペと感で書いて試した。

V-USB を妨げない delay_ms

_delay_ms は定数しかスリープできないのと、ビジーループなのでその間割込み以外何も走らなくなってしまう。V-USB は usbPoll() を少なくとも50msecに一回は呼ばないといけないとかなので、これは使えない。

なので、まず割込みで時間を測るタイマー変数を作る。

必要な精度以上のタイマー(あまり短くないほうがいい)を用意 (この例だと1ms) して、グローバルな timer という変数をインクリメントするようにする。(F_CPU / 分周設定 / OCR0A) CTC のほうが自由に時間を設定できて楽

	/**
	 * timer interrupt
	 * CTC 16MHz / 64 / 250 = 1kHz = 1msec
	 */
	TCCR0A = 0b00000010;
	TCCR0B = 0b00000011;
	OCR0A  = 250;
	TIMSK0 = 0b00000010;
unsigned long timer;
ISR(TIMER0_OVF_vect) {
	timer += 100;
}

以下のようなマクロを用意して DURATION(msec) で、引数に与えた時間が timer 換算でいくつになるかを出す。浮動小数点演算を使った瞬間、出てくるバイナリサイズが長大になるのでそうならないようにしてる。

#define DURATION(msec) (unsigned int)(msec * 100)


delay_ms を実装する。_delay_ms におけるビジーループ部分が任意に書けるので、ここで usbPoll() をする。

void delay_ms(unsigned int t) {
	unsigned long end;
        cli();
	timer = 0;
        end = timer + DURATION(t);
        sei();
	while (timer <= end) {
		wdt_reset();
		usbPoll();
	}
}

これでナイーブに delay_ms() を使ったコードでも可読性と効率をそこそこ両立できそう。しかし、なんかもっといい感じにコード書けそう。。普通どうやるものなのかよくわからない。

I2C 液晶

デバッグするとき、何かしら文字を表示できるインターフェイスがないとつらいため導入。シリアルポートに出力してデバッグするのがたぶん一番楽なんだと思うけど、レベル変換が必要で手元にあるものではできなかった。


I2C を使うにあたって、原理を理解していないのと、なおかつそれを AVR で実現する方法がわからないのと、さらには「デファクトスタンダード」な通信プロトコルも存じあげないため、全ての箇所でハマりにハマった。チップは ATmega168P なのでそこまで細かい原理を知っていて実装できる必要はないけど、だいぶハマった。

やり終わってみれば、別に難しくはないんだけど、どこに問題の原因があるのかが、見える現象が少なすぎて大変だった。面倒でもいちいちLEDチカチカさせて動作確認をすべき。

以下に I2C 液晶 (アドレス 0x7c) を操作するコード。何をするにせよ、とにかくデータシートをよく読んで理解するのが大変に重要だと実感した。

#include <string.h>

#define START 0x08   
#define ReSTART 0x10   
#define MT_SLA_ACK 0x18   
#define MT_DATA_ACK 0x28   
   
#define MR_SLA_ACK 0x40   
#define MR_DATA_ACK 0x50   
#define MR_DATA_NACK 0x58   
   
#define SLA_W 0xA0   
#define SLA_R 0xA1   
#define ADDRESS 0x00   
#define DATA 0x55   

void Error () {
//	unsigned i = 0;
//	for (i = 0; i < 3; i++) {
//		set_bit(PINB, 0);
//		_delay_ms(500);
//		clear_bit(PINB, 0);
//		_delay_ms(500);
//	}
//	clear_bit(PINB, 0);
}

void i2c_start () {
	// start
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
	while (!(TWCR & (1<<TWINT)));
	if ((TWSR & 0xF8) != START) return Error();   
}

void i2c_stop () {
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

unsigned char i2c_write (unsigned char data) {
	TWDR = data;
	TWCR = (1<<TWINT) | (1<<TWEN);
	while (!(TWCR & (1<<TWINT)));

	switch (TWSR & 0xF8) {
		case MT_SLA_ACK:
		case MR_SLA_ACK:
		case MT_DATA_ACK:
			return 1;
		default:
			Error();
			return 0;
	}
}

void display_write_instruction (unsigned char address, unsigned char data) {
	i2c_start();
	i2c_write(address);
	i2c_write(0b10000000);
	i2c_write(data);
	i2c_stop();
	_delay_ms(1);
}

void display_write_data (char* string) {
	unsigned int i = 0;
	unsigned int len = strlen(string);

	display_write_instruction(0x7c, 0b00000001);

	i2c_start();
	i2c_write(0x7c);
	i2c_write(0b01000000); // Co=0 RS=1

	for (i = 0; i < len && i < 8; i++) {
		i2c_write(string[i]);
	}
	i2c_stop();

	_delay_ms(1);

	i2c_start();
	i2c_write(0x7c);
	i2c_write(0b10000000); // Co=1 RS=0
	i2c_write(0b11000000); // set ddram address to line 2
	i2c_write(0b01000000); // Co=0 RS=1
	for (; i < len && i < 16; i++) {
		i2c_write(string[i]);
	}
	i2c_stop();
}

void display_init () {
	TWBR = 0x24;
	TWSR = 0b00000001;
	TWCR = 1<<TWEN;

	display_write_instruction(0x7c, 0b00111000); // function set to 0 (default)
	display_write_instruction(0x7c, 0b00111001); // function set to 1 (extended)
	display_write_instruction(0x7c, 0b00010100); // internal osc frequency
	display_write_instruction(0x7c, 0b01110000); // contrast set
	display_write_instruction(0x7c, 0b01010110); // power/icon/contrast control
	display_write_instruction(0x7c, 0b01101100); // follower control
	_delay_ms(300);
	display_write_instruction(0x7c, 0b00111000); // function seto to 0
	display_write_instruction(0x7c, 0b00001101); // display on/off control
	display_write_instruction(0x7c, 0b00000001); // clear all

	_delay_ms(10);
}

ハマり

ハードウェアが絡むコーディングは、一度ハマると

  • 配線ミス
  • コーディングのミス

のどちらで発生しているかの見極めができないとかなりつらい…… 配線ミスはあってはならないので、最初の段階でよくよく確認しておかないとあとあとつらい。どんなに確認しても確認したりないぐらい確認する必要がある。あと配線後は必ずテスターをあてたほうがいい……

USB コネクタのピンの半田付けを適当にしすぎたせいで、試している最中に1本がはずれて通信できなくなるということがあった。こういうアホみたいなことでもコーディングミスを疑ったりすると時間を食ってしまう。

PORTB, PINB

出力を操作したいときは PORTB なのに、PINB と書いていてしばらく気付かなかった。この場合、微妙に出力されたりされなかったり、みたいな不安定な挙動になって、全く動かないわけでもないのでなかなかコーディングミスであることに気付けない。

Mac 環境で Ruby + libusb を使って HID デバイスを操作する

最初は feature レポートだけでごにょごにょしていたのでよかったけど、インタラプト転送をしようとしたところで、claim_interface が ERROR_ACCESS エラーを出して止まることがわかった。ググった感じだと、HID デバイスの場合、そのへんの処理を OS のドライバが握っているため、ユーザレベルだと直接扱えないらしい。

とりあえずどうしようもないっぽいので、feature レポートだけで情報をやりとりするように変えた。現状のプログラムだとそれでも問題がないっぽい。

  1. トップ
  2. tech
  3. AVR で USB 接続の PC キーヤーを作る
  1. トップ
  2. avr
  3. AVR で USB 接続の PC キーヤーを作る
  1. トップ
  2. arduino
  3. AVR で USB 接続の PC キーヤーを作る
  1. トップ
  2. ham
  3. AVR で USB 接続の PC キーヤーを作る
  1. トップ
  2. モールス
  3. AVR で USB 接続の PC キーヤーを作る

AVR は思ったより難しくなくて結構拍子抜けするぐらいだけど、今までやったことがない分野なので適度に難しい問題がたくさんころがっていてめちゃくちゃ楽しい。久しぶりに深夜3時ぐらいまでひたすらコーディングするとかしてしまった。

USB デバイスとか「作れない」という状態だとほんと全然アイデアが沸いてこないんだけど、やってみると結構「ああ、あれもできそう」「あれができたら楽しそう」みたいなのがでてきていい。

ウェブアプリのように誰かにすぐ使ってもらえるものを作るという感じではないのがもったいない感じだけど、なんか別に、自分そういうのなくてもいいなって感じなので良いです。

僕みたいな普段ウェブアプリみたいなかなりレイヤーが上のほうのことやってる人間でも、最近だとアセンブリとか全く書かなくてもよくていい。

ちょっと考えてみた感じ、何も持っていない状態からの AVR におけるとりあえずの開発に必要なのは以下あたりかなあと思った。

  • プログラムの一般的な知識 (ウェブとか関係なく普通の)
  • AVR ライター (純正 AVR ISP Mark II も別に高くないので純正のを買うのがよさそう)
  • ブレッドボード・ブレッドボード用のジャンパピン集
  • ピンヘッダ・オス・メス
  • ミノムシクリップコネクタ
  • レインボーフラットケーブル (裂いて使えるし、複数の線が纏められるし超便利)
  • マイコンチップ (ATTiny2312=150円ぐらい, ATmega168P=200円ぐらい)
  • 抵抗E12系一通り10本ずつぐらい
  • コンデンサE6系一通り10本ずつぐらい (デジタルだと100uF以下ぐらいでよさそう)
  • LED数個 (デバッグその他に必ず必要)
  • 電源
    • 安定化電源、なければ電池ケース (エネループなら4本直列=4.8V程度のもの)
    • あるいはUSBから5Vとってもいいかもしれないけど、ポリスイッチ(何度も使えるヒューズ)を入れたほうがいい
  • テスター (必須)

そんなに必要なものない気がしたけど、何もなしからだと結構ある。1万ぐらいあればぎりぎり集められるかな。

  1. トップ
  2. tech
  1. トップ
  2. avr
  1. トップ
  2. arduino

Kindle Paperwhite (第6世代) ―Wi-Fi - Amazon

Amazon

3.0 / 5.0

新しい Kindle Paperwhite を買った (予約してたのを忘れてて、きづいたらきた)

Kindle を所有するのははじめてなので (すこし他人のを触らせてもらったことはある) あんまり比較はできない。とりあえず、持った感じはよくて結構嬉しい感じ。表示の切替えはあんまり早くない (これでも早くなったらしいけど)

とりあえず手元にある PDF を入れみたり、既に購入済みのやつを読んでみたりした。PDF はそのままだとコントラストを最高にしないと読みにくい。

あとウェブページを送信する用に

をダウンロードしておいた。プリント先として表示されるようになって便利

持ち歩きで使うならカバーが必須な気がするなー と思っているけど、結構高いので買ってない。

Amazon Kindle Paperwhite用レザーカバー、オニックスブラック【Kindle Paperwhite(第5世代、第6世代、第7世代、マンガモデル)専用】 - Amazon

Amazon

3.0 / 5.0

普段仕事でもなんでも殆ど、筆記用具を使わないので、筆記用具とかもはやどうでもいいやって感じだったけれど、最近になって筆記で勉強しはじめたので、捗る筆記用具について思いを馳せた。

最初は普通に今まで持っていたゴミみたいなシャープペンシルを使っていた。しかし、最近何かのアレで万年筆 (LAMYというメーカーのやつ) をもらったので、せっかくだからと使ってみたら、すごく書きやすかった。気に入った点は大したことではないんだけど、

  • インクなのでシャープペンシルと比べて色が圧倒的に濃い
  • 筆圧かけずにすらすら書ける

あたりで、それからはずっと万年筆を使って勉強してる。書くのが楽しいので、問題を解くモチベーションに繋る。

しかし、いただいた万年筆は線がちょっと太めな感じだったので、細いのが欲しくなった。と、いうタイミングで、ちょうどよくパイロットのカクノ という子供向け1000円の万年筆が発売されたので、買ってみた。(アマゾンにまだなかったので普通に文具店で買った。今はあるみたい)

パイロット 万年筆カクノ F ライトグリーン FKA1SRLGF - パイロット(Pilot)

パイロット(Pilot)

3.0 / 5.0

買ったのは色はライトグリーンで、ペン先が F のもの。F のものが日本語筆記だとスタンダードっぽくて、ちょっと細めみたいだ。デザインはまぁ……悪くはないけどって感じだけど、使ってみた感じだと、先が細いぶんちょっとひっかかるかなというぐらいで十分良かったので、今はこっちをメインに使ってる。

と、いうのはいいんだけど、最初についてるインクが2週間経たないぐらいでなくなってしまって「えっ!」となった。実はインクがなくなるまで使えたら買おうと思っていたかっこいいインクがあったので、さっそく注文した。

パイロット 万年筆インキ iroshizuku INK-50-TY ツキヨ - PILOT

PILOT

5.0 / 5.0

↑ これ、どっかで見かけて、すごいかっこいいなー欲しいなーけど俺使わないなーと思っていたけど、案外インク使うことがわかったのでウキウキしながら買ってみた。

 -

4.0 / 5.0

インクを入れるコンバーターというのも買った。(カクノには最初インクカートリッジがついてるけど、コンバーターも普通に使えるようだ)

一回ペンを洗ってから入れかえた。初めて入れかえをやったので結構楽しい。実際書いてみると色がすごく自分に好みだったので大変満足した。嬉しい買いものだった。色はかなりたくさんあって、悩んだけど、これ (月夜) にしてよかった。少しだけ緑が入っている夜空の青。

ペンを変えたら、ペンを使いたくなるので、勉強のモチベーションがちょっとあがる。簡単にモチベーションが上がるようなことは全部やったらいいと思うし、コストの割には結構いい感じに上がるので、たいへんいいなと思った。

しかし、もうすこしいいのも欲しくなるのが困る

パイロット 万年筆 コクーン シルバー 細字 FCO-3SR-S-F - パイロット

パイロット

5.0 / 5.0


パイロット 万年筆 プレラ 色彩逢い 細字 透明ブラック FPRN350R-TBF - PILOT

PILOT

5.0 / 5.0


パイロット 万年筆 カスタム74 FKK-1MR-NCF 細字 透明 - PILOT

PILOT

5.0 / 5.0

カクノ以外は結構なお値段ですね!! カクノは使い捨てというわけではないし、コンバーターも使えるのでコストパフォーマンスは高そう。もうちょっとだけかっこいいのがあればなあ。

S (トトト) H (トトトト) 5 (トトトトト) の区別がつくように全然ならない。20wpm 程度でも結構間違える。全部とれない場合、ミスのほとんどがこれ。25wpm になると、1分間やっている中の 5 を全部 H、H を S と書く、あるいは逆、みたいにズレて聞きとったりする。クソすぎてイライラする。

S H 5 だけランダムで聞きとろうとすると、今度は全部聞きとれない。ランダムではなく SHE, HIS とかはパターンで覚えてるからある程度聞きとれるけど、ランダムだと全く意味わかんない。なので、比較して聞きとれるようにするということもできない。というか単体ならまず間違えないんだよ……

E (ト) と I (トト) と S (トトト) の区別は容易にできるけど、それ以上の短点は「いっぱい」としか認識されない。「ちょっと長いから5だろう」「5ほどじゃないからHかな」ぐらいの曖昧な感じ。本当にイライラする。

もう初めて3ヶ月ほど経つのにこのありさまなのでやる気なくす。あまりにもこれらを間違えるので 26wpm から 20wpm 程度までスピードを落としてゆっくりやってる。多少マシになったかもしれないけど。あいかわらず間違える。聞きとれない文字がいくつかあると、それらで考えてしまって止まるので、速度があげられない。一度聞きとれないと、その単語は完全に落とすので、そういう文字があってはならない。

次に J と 1 も、S H 5 ほどではないけど区別がつかない。こっちはコールサインの文脈でよく使うので比較的頭に長さのイメージができているけど、それでも間違える。どうすれば解決するのか全くわからない。3ヶ月やってダメなら一生ダメなんじゃないか。

以上の符号以外にも、2、3、7、Z、X はそれ以外に比べてよく間違える。

浮動小数点演算を使ったとき、-lm を付けないとバイナリサイズが巨大化する問題がある。-lm をつけない場合、デフォルトの (libgccの?) 浮動小数点関数がリンクされるけど、avr 用には高効率なものが libm に実装されている。libgcc だと 3k -> libm だと 1k ぐらいのインパクトがあるので必ず libm を使うようにしたい。

とはいえ、ちゃんと理解してないと libm にリンクされない……

結論からいうと以下じゃないとだめだった。

$(COMPILE) -o main.elf $(OBJECTS) -lm

以下のようだとうまくいかない。

$(COMPILE) -lm -o main.elf $(OBJECTS)
$(COMPILE) -o main.elf -lm $(OBJECTS)

というのも、リンカは、引数を順番に読みこんで、読み込み中のファイルに今までで未定義のシンボルがあったとき、それを解決する、という挙動をするらしい (なんとなく逆に、先に定義して解決していくもんだと思ってた)。

なので、先に -lm を指定しても、その時点では未定義のシンボルが何もないので何の意味もない。

gcc のオプションに -v (verbose) を渡すと、最終的に ld (collect2) に渡される引数がわかる。

うまくいく場合は main.o -lm -lgcc -lc -lgcc というふうになってる。main.o で使ってるシンボルが -lm で解決されて、あとまだ足りないのは -lgcc とかで解決される。-lgcc が2回出てくるのは、-lc が -lgcc を使ってるからかな。よくわかんない。

  1. トップ
  2. tech
  3. AVR 浮動小数点 (float) 演算
  1. トップ
  2. avr
  3. AVR 浮動小数点 (float) 演算
  1. トップ
  2. arduino
  3. AVR 浮動小数点 (float) 演算

割込みかけるように設定しているにも関わらず、それに対する処理を書いていないと、sei() を呼んだあと、割込みが発生するときに落ちてリセットがかかる。

sei() が呼ばれるまでは問題ないので、コメントアウトでデバッグしていると超ハマる。

  1. トップ
  2. tech
  3. AVR、なぜかリセットされまくるとき
  1. トップ
  2. avr
  3. AVR、なぜかリセットされまくるとき
  1. トップ
  2. arduino
  3. AVR、なぜかリセットされまくるとき

USB-シリアルポートアダプタ (RS-232C) は前に買っていたけど、RS-232C は正負 -12~+12 で1/0を表現うるので、マイコンのロジックレベル(0 or VCC)とは違っていて、そのままではマイコンと接続できない。

調べてみると、RS232トランシーバー (ドライバ) ICというのがあって、それを使えば簡単にレベル変換できることがわかった。有名なのは MAX232 というやつみたいだけど、ほぼ同じインターフェイス(ピンアサイン)でビットレートや電源電圧が違うやつがいろいろとあるみたいだ。

今回は ICL3232CPZ という 3.3V〜5V で動いて、なおかつ外付け部品が 0.1uF 5個だけというのを選んで作った。

繋いで以下のような、ボーレート 19200 で吐き出すコードを書いてみた (チップは ATTiny2313、レジスタ名がチップによって違うので、チップ変えるとそのままでは動かない)

#include <avr/io.h>
#include <string.h>
#include <util/delay.h>

#define clear_bit(v, bit) v &= ~(1 << bit)
#define set_bit(v, bit)   v |=  (1 << bit)

static inline void uart_putchar(char c) {
	loop_until_bit_is_set(UCSRA, UDRE);
	UDR = c;
}

static inline void uart_puts(char* string) {
	unsigned int len = strlen(string);
	unsigned int i;

	for (i = 0; i < len; i++) {
		uart_putchar(string[i]);
	}

	uart_putchar('\r');
	uart_putchar('\n');
}

void usart_init(unsigned short baudrate) {
	unsigned int d = ((F_CPU + (baudrate * 8L)) / (baudrate * 16L) - 1);
	UBRRL = d;
	UBRRH = d >> 8;

	UCSRB =
		(1<<RXCIE) | // RX Complete Interrupt Enable
		(1<<TXCIE) | // TX Complete Interrupt Enable
		(0<<UDRIE) | // USART Data Register Empty Interrupt Enable
		(1<<RXEN)  | // Receiver Enable
		(1<<TXEN)  | // Transmitter Enable
		(0<<UCSZ2) | // Character Size
		(0<<RXB8)  | // Receive Data Bit 8
		(0<<TXB8)  ; // Transmit Data Bit 8

	UCSRC =
		(0<<UMSEL)            | // USART Mode Select: 0=Asynchronous Operation, 1=Synchronous Operation
		(0<<UPM1)|(0<<UPM0)   | // Parity Mode
		(0<<USBS)             | // Stop Bit Select
		(1<<UCSZ1)|(1<<UCSZ0) | // Character Size (with UCSRB)
		(0<<UCPOL)            ; // Clock Polarity
}


static inline void setup_io () {
	usart_init(19200);
}

int main(void) {
	setup_io();


	for (;;) {
		uart_puts("Hello, World");
		_delay_ms(1000);
	}
}

PC 側では、この USB シリアルポートアダプタの場合、/dev/tty.usbserial-FTB3L9UG というようなファイルができるので、これを指定して GNU screen の window を1つ作ってる。変なことしてないのでボーレートを指定するだけでいける。

screen /dev/tty.usbserial-FTB3L9UG 19200

これで RX/TX があるチップならかなりデバッグが捗りそう。

  1. トップ
  2. tech
  3. AVR シリアルでPCと接続してデバッグ
  1. トップ
  2. avr
  3. AVR シリアルでPCと接続してデバッグ
  1. トップ
  2. arduino
  3. AVR シリアルでPCと接続してデバッグ

いろいろパーツを注文するついでに ATTiny13A というチップも買ってみた。

見ての通り8ピンしかないチップだけど、以下のような特徴がある

  • 1個50円と激安。
  • ADC がついてる
  • プログラムに使えるのは1KBしかない
  • SRAM が 64B だけある (のでCで書ける)
  • 外付け水晶を使うのは面倒 (使わないつもりで書いたほうが良い)
  • ISPを殺せば最大6ピンIOに使えるけど、基本5ピンしかIOに使えないと考えたほうがいい

かなり制約があって楽しい。サイズ的に浮動小数点は使えないので工夫する必要がある。メモリ(SRAM)も64Bしかないのでついうっかりするとオーバーしそう。でもCで開発できるのでいいバランス。

とりあえずエレキー作るのがいいかと思って作ってみた。

まとめを後日書きました ボタン電池で動く小型・低消費電力 AVR エレキー (50円 ワンチップマイコン ATTiny13A) | tech | avr | arduino - 氾濫原

ただ、ピン数が少ないせいで大きな問題がある。というのも、必然的に ISP で使うピンとアプリケーションのピンを共有することになるので、回路によっては、繋いだままの ISP というのができないっぽい。「SCK fail」とか「MOSI fail」とか出て意味不明だったけど、このせいみたいだ。うまくやらないと In-System Programming という感じでなくなる。なんか簡単ないい方法ないのかな。

ADC の端子がいくつかあるので、スイッチをたくさん繋いでいくというのは割とできそう。ただ出力はそうもいかない。ソフトウェアに使えるメモリ量も少ないので「ハードにないからソフトで実現」というのも難しいことが多そう。

それにしても「50円で買えるコンピュータ」というのはグっとくる。

  1. トップ
  2. tech
  3. ATTiny13A
  1. トップ
  2. avr
  3. ATTiny13A

使いはじめて2年ぐらい経ったところで、イヤーパッドの縫い目が割けてきしまったので、交換したくなった。とりあえず純正が高いので安いのを買ってみた。

Bose QuietComfort 15 対応交換用パッド◆QC15, QC2, AE2, AE2i 対応(univarcオリジナル) 安心安全保証付き U1355 -

3.0 / 5.0

さすがに本体とサイズが合わないということはなく、普通に使える感じ。ただ、純正と比べるとちょっと硬い。しばらく使ってみる。

Bose QuietComfort 15 Acoustic Noise Cancelling headphones ノイズキャンセリングヘッドホン QuietComfort15-S - BOSE(ボーズ)

BOSE(ボーズ)

5.0 / 5.0

やっぱりほぼ毎日使っていると痛んでくる。どのぐらい長く使えるかな。もうこれ無しの生活とか考えられないんだけど

IKEA で買ったピーラーの切れ味がよくなくて、うちで不評だったので以下を買った。知り合いの家にあって、便利だったので、検索してみたらすぐ見つかった。

スピードサラダ 19639 - 下村企販

下村企販

5.0 / 5.0

千切り機能とか使わねーだろと思ったけど、使ってみたら便利だった。刃物系はあんまり安いとよくないですね。

爪切りも少しだけ良いものを買ったほう確実に生活が向上していいです。

木屋 はがねの爪切り 大 BK-T02 - 瀬川 喜一郎

瀬川 喜一郎

3.0 / 5.0

↑ これほしい。

マイコンプログラミングとか、黙って Arduino やっとけハゲという感じではあるんだけど、Arduino の言語がどうも好きになれなくて使ってない。CっぽいけどCじゃない、でもC、みたいなのがなんとなく嫌だなと感じてる。それは置いておいても Arduino は素晴しいと思います。

Arduino も AVR を使っているし、結局 Arduino 頑張ろうとすると AVR のスペックを理解する必要があるので、じゃあ AVR でいいか、という感じになる (安いし)。

Arduino は、開発環境も含めたエコシステムが魅力で、そこがすごくいいと思うけど、自分みたいに CUI で vim で書いて Makefile でコンパイルして書きこんで gdb でデバッグするみたいのが好きな人間だと、少し魅力が薄れてしまうように思う。

IDE はあればあるで便利で良いんだけど、Makefile と gdb を使ってやっていれば、マイコンプログラミング以外のときにもその知識が生かせて嬉しいと思う (IDEの操作の知識はほかに生かせない)

  1. トップ
  2. tech
  1. トップ
  2. avr
  1. トップ
  2. arduino

まとめを後日書きました ボタン電池で動く小型・低消費電力 AVR エレキー (50円 ワンチップマイコン ATTiny13A) | tech | avr | arduino - 氾濫原

前に書いたのの続き。

せっかくメインのICが小さいので、できるだけ小さく作るならどうするのがいいだろう?と考えてる。

まず、乾電池1本で動いたらいいなと思ったので、1.4Vを3.3Vに昇圧する回路を組んで駆動させてみたら、昇圧回路がどうもうまくいかなくて、やたら電気食う感じだった。昇圧回路の調整を別途やれば乾電池1本でもいい感じになるかもしれないけど、実際ブレッドボードで組んでみたら結構体積も食う感じになってしまったので、そもそもこの方法を諦めた。

じゃあリチウムコイン電池を使うことを考えよう、と思った。リチウムコイン電池なら1個で3V出せる。ただ、あまり電流を流すことができなくて、標準で 0.2mA 程度に抑える必要がある。消費電力を減らす工夫はしてるつもりだけど、スピード調節をADCにしたのでボリュームに常に電流が流れるとか (10kΩなのでこれだけで0.3mA流れる)、もうちょっと頑張る必要がありそうだった。

まず、ADC は1秒ごとに行うようにコードを変えて、そもそも頻度を減らした。また、ボリュームに電圧をかけるのも、ADCが行われるときだけにした。これはピン1個を出力にして、VCC の代わりにそこに繋いでる。VCC とピンの出力電圧は厳密には違うので、ADCの精度は落ちるけど、そもそも安定してない電池駆動だし、相対値だけがとれればいいのでまぁいいかな、という気がする。

それでだいたいアイドル時に0.3mA程度まで下がった。しかしこれ以上思いつかないので、とりあえずクロックを下げてみて挙動に問題がないか試すことにした。ATTiny13A の場合、内蔵クロックは 9.6MHz, 4.8MHz, 128kHz とそれらを8分周したものが選べる。なので 4.8MHz を8分周した600kHzで動かしてみると、思ったより変なことにならなかった。これでアイドル中はほぼ0.2mA未満に。

じゃあ 128kHz だとどうだろう、ということでやってみたら、

 bad AVRISPmkII connection status: Unknown status 0x00

とかでるように…… たぶんクロックを下げすぎたせいで ISP の書きこみのクロックを読めてないのかな……

うーん困ったと思っていたら avrdude に転送スピードを下げるオプション (-B) があったので、-B 100 ぐらいにしてやったらいけた。しかし書きこみ速度がだいぶ遅い。

コードを全体的に書きなおさないと 128kHz でバグってて動かない感じだけど、軽く試した感じだと、アイドル中で0.09mAぐらい。キーイング中で0.19mA。パワーダウンは変わらず0.6uA程度。コーディングが面倒になった割にはそんなに減らない。ベースの消費が無視できないほどクロックの支配率が低くなってるせいかな。

仕様から

  • VCC=3V, f=128kHz
    • idle: 0.01mA
    • active: 0.04mA
    • power down: 0.00015mA
    • ADC: 0.225mA
    • Timer0: 0.002mA
    • pull-up: 0.08mA
  • キーイング中は pull-up + active + timer0 + FET GS接地抵抗(440k)電流 = 0.122mA が最低でも必ずかかる
  • アイドル中は idle + timer0 = 0.012mA
  • ADC中は active + ADC + timer0 = ボリューム電流 = 0.567mA
  • パワーダウン中はクロックに関係なく固定で 0.15uA
    • 比較すると実測値が結構高いけどなんでだろう
  • 瞬間最大電流
  • キー同時押し pull-up * 2 + active + timer0 + FET GS接地抵抗(440k)電流 + ADC
    • 0.7338mA

パワーダウン中の消費は AVR ISP Mark II と繋っていたからで、RESET をはずせば 0uA になった

  • パワーダウンモード 0.0uA未満
  • アイドル中 90uA -> 0.09mA
  • キーイング中 198uA -> 0.198mA with FET
  1. トップ
  2. avr
  3. ATTiny13A を使った小型エレキー
  1. トップ
  2. tech
  3. ATTiny13A を使った小型エレキー
  1. トップ
  2. arduino
  3. ATTiny13A を使った小型エレキー

「コレクタ接地ってボルテージフォロワ? エミッタフォロワー? あれ?」って思ったのでちゃんとしとく……

ボルテージフォロワは普通オペアンプに対して使うようだ。エミッタフォロワーはバイポーラトランジスタを使ったボルテージフォロワ、でいいのかな。

ボルテージフォロワは FET も同じようにドレイン接地 (ソースフォロワ) で作れる。

オペアンプをヴォルテージフォロワとして使う場合、中身 (バイポーラトランジスタやらFETやらの集合) のことを無視して考えると、中身がエミッタフォロワーだろうがソースフォロワだろうが、挙動としてはヴォルテージフォロワということっぽい。

  • ボルテージフォロワー
    • エミッタフォロワー
    • ソースフォロワー