割込みタイマーによるカウンタを使った 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 消費電力を減らす

まず何を作ろうという感じだけど、エレキーならはじめて作るマイコンの教材としては、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 でエレキーをつくってる

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

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

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

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

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

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

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

  1. トップ
  2. ham
  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)

をつくった。

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

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

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

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

23wpm で文字+数字、数字だけ、文字だけ、をそれぞれ90%なんとかとったので24wpmでやりはじめてる。20wpmだと完全ランダムでだいたい90%前後がとれるようになったけど、普通文だとそれほどとれないので辛い。十分単語に慣れた人なら普通文のほうがとれるみたいだけど、単語に慣れていない場合、普通文のほうが短い符号の文字が多いので頭が追いつかない。

これが、実際に交信になると、テンパってしまって速度が遅くてもほぼ聴き覚えがある符号しかとれなくなる。599BK 式で、余計な符号がほぼ入らなければなんとか交信できる。CQ を出して、呼んでもらう場合、18〜20wpm なら2回コールしてもらえばとれる感じ…… CQ を出している局は 22〜30wpm あることが多いので4回〜6回聴かないと確定できない……

599BK で CQ を出している局を呼ぶか、自分で CQ を出して 599BK に付きあってもらうか、どっちもメリットデメリットがあってつらい。

CQ 出している局を呼ぶ場合

大抵、599BK でやっている局は JCC サービスなので、パイルになってることが多い。この場合、こちらからの電波が相手に十分届いているか、ある程度パイルが捌けるまでわからないので、非常に効率が悪い。

コールサイン、JCC などまで聴きとった状態で呼ぶので、ほぼ聴きとる必要がなくて気は楽だけど、何か想定外のことを打たれた場合、速度が早くて返せないので、その点で緊張する。

自分で CQ を出す場合

まず第一に、相手にメリットがほぼない (こちらのロケーションは政令指定都市なので別に珍しくもないし)。なおかつ、18wpm 程度で CQ を出すと、相手はラバースタンプ程度の長さを期待する (と思われる) ので、599BK で終わらせると偲びない。

ちょっとやった感じだと、相手の QTH が JCC/JCG で送られる場合、案外聴きとれるけど、それ以上に何か送られるとつらい。なのでだんだん申し分けない心持ちになってくる。

今後の予定

とにかく結構辛いんだけど、CQ 出している局を呼んで、自分のコールサインが呼ばれたとき結構嬉しいのがいい。電波届いたのも嬉しいし、「あっおれだ」っていうのが分かるのも嬉しい。

訓練は続けつつ、599BK であっても CQ を出すのに慣れるのがいいかなあとは思ってる…… けどほんとメンタルが弱すぎて聞きとれるものも聞きとれない。メンタルを強くする方法はわからないので、とにかく聞きまくって慣れるしかないかなと思う。それまで続けられるか心配。

  1. トップ
  2. ham
  3. 最近のモールス訓練
  1. トップ
  2. モールス
  3. 最近のモールス訓練

交信履歴をつけるツールにいろいろ機能をつけてる。

(というかそもそも記録するという一番大事な部分にバグがあって一部の交信が消えた感じがするけど、ようやく直ったような……)

コールサイン地域補完


コールサインのプリフィックスを入力した時点で、どのあたりの地域の人かわかるように。日本の局の場合エリアまで出すようにしてるので便利。慣れてる人は覚えているからこんなのいらなそう。

これは typeahead.js で実装してある。

JCC 補完

国内の場合、だいたいの人が JCC/JCG を送っているので、それを補完してどこかわかるようにした。JARL が提供してる .txt (クソフォーマット) をパースして JSON にしてる。取得時にソートしてインデックスを作ってるのでJS側はかなり簡単。

これは jQuery.textcomplete で実装してる。いろいろ補完できそうで夢が広がる。

  1. トップ
  2. tech
  3. ログ管理ツール
  1. トップ
  2. ham
  3. ログ管理ツール

CW 以外殆ど聞いてない。アパマンハムはやはり厳しいなあという感じ。聞こえてこないぶん、卑屈になる。

7MHz

深夜以外はだいたい聞こえる。

深夜はDXが聞こえるらしいんだけど、うちのような2m程度のアンテナの環境だと殆ど聞こえない。たまに韓国の局が聞こえてくるけど、あちらはかなりパワー入れてるみたいで、こちらから呼んでもとってくれない感じ (実際 JA の局が呼んでるけど、向こうは一切反応なし、というのを何度か見た)。

その他のDXは聞こえたことがない。

18MHz

太陽が昇ってる時間だとときどき DX が聞こえる。一方日本の局はあんまり聞こえない。バンド狭いのでちょくちょくコンディションが良さそうなときに聞いてるけど、あんまり聞こえてこない……

ビーコンも殆ど聞こえない。中国のビーコン100Wがかすかに聞こえたことがあるかな〜 程度。せめてビーコンがちゃんと聞こえるぐらいのアンテナを張りたい……

21MHz

クラスタを見てて 21MHz が多いな〜 と思ったら見る程度で、こっちも昼間たまに DX が聞こえてくる。けど基本殆ど聞こえない。結構バンド広くて、なおかつ慣習がいまいちよくわからないので、どのへんを聞いたらいいのかわからず。

こちらもビーコンがあるけど聞こえてこない。

28MHz

聞こえたことがない。バンドが広いので探すのも大変。

どこを重視すべきか

まだわからない。7MHz は賑やかなので今でもそれなりに聞いてて楽しい。ただ、夜になると全く聞こえなくてつまらない。

18MHz, 21MHz は、うちのようなショボい設備でも DX のチャンスが多そうかもしれない。もっとずっと聞いててもいいかもしれないけど、基本何も聞こえてこないので面倒くさい。アンテナが7MHzに比べたら短いので、モノバンド短縮アンテナを作ってみたら今より良くなるかもしれないし、いずれやってみたい。

まだ聞いたことがないバンド、特にローバンドの1.9MHz, 3.5MHzも聞いてみたい。マイクロバートアンテナなら効率はともかく一応送信もできるのが作って設置できそう。3.5MHz は夜・冬に使えるバンドみたいなので、次 7MHz のアンテナと交換する形で作ってみる。

ベランダなのであんまりいっぱいアンテナを設置すると怪しすぎるので避けたい。4本程度が本当に限度だと思う。なのでマルチバンドホイップ (UHV-6) は大変便利に使ってるし、割と性能もいい感じで気に入ってる。

うちのベランダは本当に狭くて、横方向にも3mぐらいしかないので、ダイポールを上げるのはどんな手を使っても不可能。しばらくは長さに自由度があるマイクロバートアンテナをバンド別に何度も作ってみたい。

  1. トップ
  2. ham
  3. バンドごとの印象

ほんと明らかに何もかもに対して度胸というか自信が足りていなくて、どうしようもない。

というのをちょっと前に作ったけど日記に書いていなかった。

デモ (音アリじゃないとよくわからない):

デフォルトだと、信号がありそうなところを適当に追跡してデコードする。上のスペクトラムをクリックで、その周辺の周波数領域のデコードだけをするようになる。一度に1つのデコーダーだけが動く。

何もハッシュをつけない場合マイク入力からになる。あと Chrome でしか見てない。

Web Audio で信号処理

Web Audio を使って、マイク入力を信号処理しようと思うといくつか躓くところがあった。

  • サンプリング周波数を指定できない
  • AnalyserNode を任意のサンプリングタイミングで呼ぶことができない?
    • あとサンプリング周波数が指定できないので分解能に限界がある

モールスのデコードに高いサンプリング周波数は必要ない。しかしサンプリング周波数は Web Audio 側で固定になっているので、自力でダウンサンプリングしている。これは ScriptProcessorNode の onaudioprocess を使い、Float32Array にリングバッファ状に落としこんでる。なんかもっといい方法ありそうだけど、わからなかった。

まだ onaudioprocess の挙動が不安定で、データがこなくなったりすることがある。毎回 onaudioprocess に対してコールバックを代入しなおしたりいろいろやったけど、最近直ったような気がしないでもない。

FFT も AnalyserNode のを使うのではなく、このダウンサンプリングした信号に対し、JS レベルで実行してる。これは dsp.js を使ってる。

モールスデコード部

それなりに工夫して作った。最初のころ Description of RSCW's algorithms というのを見つけてよく読んでみたけどよくわからないことも多くて、僕でも実装できる程度に落としこんで結局以下のようになってる。

  • 適当にデコードしたい周波数を決める
    • 直近で信号強度が強い周波数
    • または手動 (スペクトラムをクリック)
  • その周波数に対し、2位相ロックインアンプ相当の処理をする
    • 本当に単純にその周波数の矩形波を90°ずらして合成してローパスフィルタにかけて、、というのをナイーブにやってる
  • 適当に閾値を決めて2値化する (むずかしい……)
    • ここまでで 0/1 になる
  • 0 の連続または 1 の連続のうち、最小の長さを見つける (モールスの符号単位)
  • 符号単位の2倍以上なら長点、そうでなければ短点として表から符号をデコードする

デモのようなホワイトノイズ + それなりの強さの信号でかつ、機械的に綺麗な符号なら、結構いい感じにデコードできるけど、実際の交信だと思ったより厳しい。

  • SN比がもっと悪い。フェージングで信号強度がよく変化する
  • 符号が綺麗なことが少ない

なので、なんらかの統計的な、機械学習のような要素を入れこんで (隠れマルコフモデルとか?) やりたいけど、そのような技術力がない。あと、別に全域常時 FFT して全チャンネル同時デコードとかも、ギジュツリョクがあればできるだろうけど、できてない。

  1. トップ
  2. tech
  3. HTML5 Web Audio でモールスを解読する
  1. トップ
  2. html5
  3. HTML5 Web Audio でモールスを解読する
  1. トップ
  2. audio
  3. HTML5 Web Audio でモールスを解読する
  1. トップ
  2. dsp
  3. HTML5 Web Audio でモールスを解読する
  1. トップ
  2. ham
  3. HTML5 Web Audio でモールスを解読する
  1. トップ
  2. モールス
  3. HTML5 Web Audio でモールスを解読する