myApp = angular.module('myApp', [ 'myApp.filters', 'myApp.services' ]);

myApp.services = angular.module('myApp.services', []);
myApp.services.factory('loc', function () {
    return Location.parse(location.href);
});

myApp.filters = angular.module('myApp.filters', []);
myApp.filters.filter('page', function (loc) {
    return function (page) {
        return loc.params(angular.extend(loc.params(), { page : page })).href;
    };
});

services と filters のモジュールをわけて以上のようなのを実装した場合で、page filter をテストしたい場合、以下のようにするとエラーになる。

describe('filter', function () {
	beforeEach(module('myApp.filters'));

	describe('page', function () {
		it('should append page param', function () {
			inject(function (pageFilter) {
				expect(pageFilter(1)).toBe('foobar');
			});
		});
	});
});

//=> Error: [$injector:unpr] Unknown provider: locProvider <- loc <- pageFilter

loc の定義が別モジュールで、beforeEach で該当モジュールを読みこんでいないからだけど、そもそも DI で loc を注入してテストしたいところだと思う。

とりあえず以下のようにしたうまくいった。

describe('filter', function () {
	beforeEach(module('myApp.filters'));

	describe('page', function () {
		it('should append page param', function () {
			module(function ($provide) {
				$provide.factory('loc', function() {
					return Location.parse('http://localhost/foo');
				});
			});

			inject(function (pageFilter) {
				expect(pageFilter(1)).toBe('http://localhost/foo?page=1');
			});
		});
		it('should append page param', function () {
			module(function ($provide) {
				$provide.factory('loc', function() {
					return Location.parse('http://localhost/foo?foo=bar');
				});
			});
			inject(function (pageFilter) {
				expect(pageFilter(1)).toBe('http://localhost/foo?foo=bar&page=1');
			});
		});
	});
});

$provide でテスト用の loc factory を定義してやる。

  1. トップ
  2. tech
  3. AngularJS 依存を持つ filter のテスト

アナログ回路めちゃくちゃ難しい。考える要素が多すぎる。素子の誤差が結果にどの程度影響を及ぼすかを予測するためには、理論をしっかりわかってないと難しい。そしてそれがわかっていないと、結果誤差がなぜ発生しているかの原因をさぐることができない。設計範囲内の誤差なのか、あるいは何かしら他の要素 (寄生容量など物理現象) が関係しているのか、わかってこない。

あるいはそこまでやらなくても、カットアンドトライでなんとかできるケースは多いのかもしれない。どの程度まで机上で考えるのかというのがよくわからなくて難しい。シミュレータを活用したほうがいいのかもしれない。

DHT11 という比較的価格の安い(ただし精度はいまいちな)デジタル温湿度センサーがあるので読んでみた。1-wire ライクな (1-wireではない) プロトコルで、データシートを読みながら頑張って読む感じ。

  1. 18ms 以上バスをローにすることでデータ送信を行わせる
  2. 18ms のローを送信したあと、入力状態に変えて 50us ロー + 50us ハイを待つ (初期メッセージ)
  3. そのあと 40回 50us ロー + (28us or 70us ハイ) のセットが送られてくる。70us のほうが「1」のビット

だいたいすぐできるんだけど、waiting for slope up と書いてあるところのディレイを入れないと、バスがハイになる前に loop_until_bit_is_clear してしまって状態がズレてしまうので、立ちあがる時間を適当に待つ必要があった。

湿度・温度それぞれ16bitが送られてくるんだけど、下位8bitは、このモジュールの場合、どちらも全部0しか返ってこない。のでコードでは無視している。下位 8bit はAM2302とか精度が良いがコストが高いというモジュールがあって、そちらの場合使われるっぽい。

あと、送られてくるデータは前回測定時のデータなので、2回読み出しを行って2回目を採用しないと、正しいデータにならない。連続して読むなら関係ない。

int main(void) {
	logger_init(9600);
	setup_io();

	printf("initializing...\r\n");
	sei();
	printf("initialized\r\n");

	uint8_t i, j, us;
	int16_t humidity, temperature;
	uint8_t res[5];
	set_input(DDRD, PD7); clear_bit(PORTD, PD7);  // hi-z

	for (;;) {
		set_output(DDRD, PD7); clear_bit(PORTD, PD7);
		_delay_ms(20);
		set_input(DDRD, PD7); // hi-z

		// waiting for slope up
		_delay_us(5);

		// waiting for slave initial response
		loop_until_bit_is_clear(PIND, PD7);
		loop_until_bit_is_set(PIND, PD7);
		loop_until_bit_is_clear(PIND, PD7);

		for (i = 0; i < 5; i++) {
			for (j = 0; j < 8; j++) {
				us = 0;
				// 50us
				loop_until_bit_is_set(PIND, PD7);
				while (bit_is_set(PIND, PD7)) {
					us++;
					_delay_us(1);
				}

				res[i] <<= 1;
				if (us > 50) { // 0: <28us 1: <70us
					res[i] |= 1;
				}
			}
		}

		printf("%02x %02x %02x %02x %02x\r\n", res[0], res[1], res[2], res[3], res[4]);
		if (( (res[0] + res[1] + res[2] + res[3]) & 0xff) == res[4]) {
			humidity    = res[0];
			temperature = res[2];
			printf("%d%%RH %dC\r\n", humidity, temperature);
		} else {
			printf("invalid data\r\n");
		}

		_delay_ms(5000);
	}
}

信号全体

最初の長いロー部分が、AVR 側からのローで 18ms ある。その後、ちょっとハイになってるところは、センサー待ちの部分、そして 50us ロー・50us ハイに続いてデータが流れてくる。目で見てビット読める感じでたのしい。

立ちあがり時間

これは 18ms 待ちあとで AVR 側を入力に切り替えてハイインピーダンス状態にした直後の立ちあがり。立ちあがりにちょっとかかっていて、その後11usぐらい待ち時間がある。

参考

DHT22 というプロトコル互換デバイスについてのものがあったのでコードほぼそのままです。

DHT22を使った温度計・湿度計の製作 - henteko.org

  1. トップ
  2. tech
  3. DHT11 という温湿度センサーを読む

概要

連続信号をADCでサンプリングする場合、前段にローパスフィルタが必要だが、それをどう設計したらいいかわからない、という話。

ローパスフィルタの設計

ADC する場合、サンプリング周波数の2分の1 (ナイキスト周波数) 以上の周波数はローパスで完全に遮断する必要がある。さもなければ折り返し雑音が入り、これは後段では正常なデータと区別がつかないので対処しようがない。

ある周波数で「遮断」するというのは、その周波数において、分解能ないしノイズレベル未満まで減衰するということ。最大 1V の信号を 10bit ADC (1024段階)する場合、0.97mV 未満であれば分解能未満になる。この場合 20 * Math.log10(1024) = 60.2dB 減衰すれば、遮断したといえる。

そしてこの場合、サンプリング周波数が 10kHz であれば、5kHz 時点で 60.2dB 減衰させるようにフィルタを設計する。次に、どの程度まで完全に通過させるかでフィルタの性能 (次数) が決定する。当然通過帯域がナイキスト周波数に近ければ近いほどADCの性能を生かせるが、そのためには性能の良いフィルタが必要になる。

フィルタの特性にはいくつか種類がある。(同じぐらいの回路規模での比較)

  • バターワース特性
    • 通過帯域内はフラットだが、減衰傾度がゆるい
  • チェビシェフ特性
    • 減衰傾度はきついが、通過帯域内にリプルが発生する

ローパスフィルタの次数はそのまま減衰傾度になる。1次のバターワースフィルタは周波数が倍で出力が半減 (=-6dB/octave)。次数が高いほど減衰が強くなる (2次=-12dB/octave, 3次=-18dB/octave)。高い性能のフィルタが必要な場合は高次のフィルタ (部品点数の増加) が必要になる。

ADCの前段に入れる場合、できる限り急激な減衰が欲しくなるので、まずチェビシェフを検討することになる。そしてチェビシェフ特性の場合、リプルがどの程度発生するかというのも設計で考慮する必要がある。もしリプルが分解能ないしノイズレベル未満にできれば、それは問題にはならない。

10bitの場合リプルは 20 * Math.log10(1 / (1 - 1/1024.0)) = 0.0085dB 未満であれば完全に問題にならないが、リプルの大きさと減衰傾度はトレードオフの関係にある。

回路構成などによっては妥協する必要がある。妥協点は

  • 分解能
  • 通過帯域

そして、フィルタの実現方法として

  • パッシブ型
    • CR, LCR のみ
  • アクティブ型
    • オペアンプを使う

がある。パッシブ型は減衰のみしかできない。アクティブ型は同時に増幅もでき、特性を改善できる、という特徴があるらしい。あとどうも L を含む回路は好まれないらしく (誤差が多いから?) あまり使われないみたいだ。

わからないこと

  • 応答特性
  • 位相変化特性

フィルタ特性としてこれらもでてくるけどどのように影響していくるかわかってない。

また、ADC の場合で、特に例えば後段で FFT する場合、減衰傾度をゆるやかにしてデジタルでフィルタ特性にあわせたレベル補正をかけたり、という小手先テクニックも使えそうだけど、それがうまくいくかわかっていない。

  1. トップ
  2. tech
  3. ADC とローパスフィルタについてのメモ

これを試しにブレッドボードでやってみた。

  • 上側の「T型」がローパス、下側の「T型」がハイパスフィルタとして働き、ツインT型部分でバンドリジェクトフィルタを構成する?
  • 上側は位相が遅れ、下側は位相が進む
  • トランジスタのコレクタ側から負帰還させて発振させてる

定数決定がむずかしそう。いまいちよくわからない。

Wikipedia によると

R1 = R2, C2 = C3, R3 = R1 / x, C1 = C2 * x で x 倍以上増幅すれば発振器になるとのことらしい。このとき、周波数は以下の式

手元のやつでやって実際計ってみた。電源電圧は 3V ぐらい。電圧をあげると周波数もあがるっぽい…

R1=10k, C2=0.012u

C1 は 0.1u

R = 10e3; C = 0.012e-6; 1 / (2 * Math.PI * R * C )
//=> 1326.2911924324612

実際は 1650Hz ぐらいで発振してる。このぐらい誤差なのかがよくわからない。

R1=22k, C2=0.012u

C1 は 0.1u

R = 22e3; C = 0.012e-6; 1 / (2 * Math.PI * R * C )
//=> 602.859632923846

しかし発振せず。

R1=10k, C2=0.027u

R = 10e3; C = 0.027e-6; 1 / (2 * Math.PI * R * C )
//=> 589.4627521922049

786Hz

R1=10k, C2=0.1u

C1 も C2 も 0.1u

R = 10e3; C = 0.1e-6; 1 / (2 * Math.PI * R * C )
159.15494309189535

244Hz

この状態で C1 に 0.1u 並列でつないで 0.2u にすると、210Hz 付近に発振周波数がさがる。

  1. トップ
  2. tech
  3. ツインT型発振回路
  1. トップ
  2. ham
  3. ツインT型発振回路
  1. トップ
  2. 発振回路
  3. ツインT型発振回路

現状、あんまり効率的な開発手法みたいなことに興味が沸いていない。自分が楽できるように効率的にすることには興味があるけど、チーム的にこう進めたほうがいいみたいなことには興味がない。自分でいくらそれを考えても、どうも意味がないようだという感じだからだと思う。

Raspberry Pi を中心にやってみようとしているところ | avr | raspberrypi | ham - 氾濫原 を実現しようとケース加工して、ひとまず収めた。ただしもやもやと考えていた以下の機能を実現せず、基本機能に絞って実装した。

  • センサー類
    • 外に出すべきか悩んで結局やめた
  • 無線機の操作性改善的なこと
    • たとえば width を変えられるボタンをつけるとか

モデリング

どのぐらいの大きさのケースが必要か? というレベルから検討が必要だったので、Raspberry Pi 及び周辺回路のくみあがりをおおよそで SketchUp でモデリングして配置を検討した。

これはそこそこ意味があったと思う。組みあがった基板をちゃんと計ってフロントパネルの穴開け部分を事前に書いたりしてる。

回路全体を実装

一部ブレッドボードになっていた部分をユニバーサル基板に全ての機能を実装しなおした。一発で動かなかったけど回路図を間違えて作っていて、回路図を間違えていると実体配線図も自動的に間違えるので残念な感じの間違いになっていた……

ケース加工

モデリングしたデータを等倍印刷して、普通の紙用のスティック糊ではりつけて、穴開けをした。

フロント

ボタンとLEDあたりが一番位置決めがシビアでうまくいくか不安だったけど、モデリングして印刷作戦がうまくいってピッタリにできた。

四角の穴をあけるのも初めてだったので不安だったけどなんとかあけられた。



ぴったりサイズの線ではなく、1m ぐらい大きい枠線を書くべきだったのが反省点だった。しかし四角の穴あけるの大変すぎて二度とやりたくない感が強い。

バック

裏側は Raspberry Pi の USB 端子を出す穴 (Wi-Fi があるので外に出す必要がある) と、RS-232 コネクタを取り付ける穴、DC ジャックの穴が主で、Raspberry Pi の USB 端子の穴だけ、位置が決まっているので気をつける必要があった。結果的にはうまくいったけど、取り付け穴がぎりぎりの位置になってしまって作業しにくかった。

RS-232 コネクタは最終的に穴の形がわからなくなるので適当にあけた。

完成

液晶の表示内容は考え中で、ソフトウェア側は (だいたいできてはいるけど) ちょいちょいいい感じにする。

  1. トップ
  2. tech
  3. ケース加工してハードウェア部分をフィックス
  1. トップ
  2. ham
  3. ケース加工してハードウェア部分をフィックス

アルゴリズムを原理から実装するみたいなのが相変らずできないわけだけど、そうでないものなら比較的すぐに実装を書けるようになってはきているので、普段の生活でちょっとしたハックみたいなのはコストパフォーマンスが非常に高く、やっていて面白い。

なんとなく以下らへんのスキルを Lv 7/10 ぐらい (Lv5 でギリギリ実用、みたいな) まで上げれたら上から下までできます!!って言えそうだけど、だいぶ遠く感じる。書いたレベルは現状の甘めの自己評価です。スキルポイントが足りてないんで、スキルシミュレーターとかが欲しいですね。

  • ウェブのフロントエンド (JS, HTML, CSS)
    • Lv7
  • ウェブのサーバーサイド (Ruby, Perl, JS)
    • Lv7
  • サーバーミドルウェア (httpd, memcached etc...)
    • Lv5
  • ネットワーク (ルーティングとか、ネットワーク冗長性とか)
    • Lv3
  • OS (マルチタスクとかメモリ管理とか)
    • Lv2
  • ハードウェアドライバ (OS 上で USB のドライバを自力で書くとか)
    • Lv2
  • ハードウェア組み込み (OS なしでハードウェアIOを叩くとか)
    • Lv2
  • 電子回路 (特にデジタル回路・デジタル回路実装に必要なアナログ回路の知識)
    • Lv2

ネットワークとかミドルウェアあたりは、会社にいると専門の人がいるから自分でほぼやることはなくて、あんまりスキルあがっていかない。それと独学だと解決すべき大きな問題が発生しないので、スキル上げしにくい。パーティプレイ必須はぼっちプレイヤーにはつらい。

ハードウェア以下の低いレイヤーは、全く仕事の役には立たないけどモチベーションは比較的高く、解決したいちょうどいい問題が結構ころがっているのでソロプレイでもスキル上げしやすい感じがする。ただ、一定以上からパーティプレイ必須で、ソロだと決して上がらなそう。

ウェブよりのレイヤーはソロプレイでスキル上げしやすい。わからないことは結局ソース見たら解決するし、バグってるの見つけたら pull-req する、みたいなのでレベルが上がっていく。

なので、ソロで上げれる限界的には Lv10, Lv10, Lv7, Lv5, Lv6, Lv5, Lv5, Lv6, Lv7 みたいな感じになりそう。

土曜日午後から頭痛がひどくなり寝た。翌日日曜日も頭痛がひどく、体温を計ると37度台後半でずっと寝てた。月曜日もまだ微熱で頭痛で会社休んで寝てた。

  1. トップ
  2. 体調不良
  3. 風邪

電子部品の足の間隔とかは 0.1inch == 100mil で作られている。ユニバーサル基板のピッチが 0.1inch == 100mil。mil は1000分の1 inch

  1. トップ
  2. tech
  3. mil

Raspberry Pi を中心にやってみようとしているところ | avr | raspberrypi | ham - 氾濫原 について、まず電源をつくった。

手元にサンハヤトのICB-90という基板がたくさんあるので、これに実装した。

とりあえずこれで Raspberry Pi を動かしてみたけど、スイッチング部分はちょっとあたたかいぐらいだった。

Eagle で配置を検討したら Print を Mirror とUpside down にチェックをいれて行うと裏面から見た感じがつくれるので配線が楽だった。あとなんか単位 (inch, mm) を切り替えながらやっていたらグリッドからずれることがあって困ったけど、これは Cmd を押しながら移動を行うことでグリッドにフィットするようだった。

  1. トップ
  2. tech
  3. 12V, 5V, 3.3V 電源
  1. トップ
  2. ham
  3. 12V, 5V, 3.3V 電源

机の横に棚が欲しかったけど、ちょうどいいのがないので作った。

机の横に防湿庫を置いていて、その上のスペースがあいている感じだったので、

  • 机の高さにあわせるため、防湿庫に1段作る
  • その上に載るように棚をつくる

という感じでやった。どちらも 1x8材 で作った。

高さをあわせる用のやつは 1x8 6 feet のものを自分でノコギリで切って作った。だいぶヘタクソな感じだけど、寸法的にはちょうどのものが作れた。事前に設計図的なのを書かず、場当たり的に作ってしまった

その上にのっける棚は 1x8 12feet の板から全部の板をとったけど、こちらはホームセンターでカットしてもらった。一旦 SketchUp でモデリングしてから、必要なサイズを事前に計算したので比較的スムーズに発注・組み立てができた。

組み立てはコーススレッドをぶちコムだけなので、と思っていたけどトルク強すぎて板が割れたり結構大変だった。サイズをぴったりにはならないので鉋か荒いヤスリが必要だなーとか、店頭で良く見てから買わないとかなり反った材料を買ってしまうなーとか、気付きはいろいろあった。

あとは 120 -> 240 でやすりをかけて、ニスをひたすら塗るだけだけど、どう考えてもこの一連の作業が一番辛い。ただ手を抜くと悲しい感じではあるのでわりと頑張った。

一連の作業を行うと翌日激しい筋肉痛になる。金で解決できるなら金で解決するほうが安いというこのご時世ではありますが、たまに DIY をやると、いろいろ気付くことや思うことがあるし、物理的に形あるものを作るのも、ヘタクソではありつつも愛着が沸いておもしろいものであります。




  1. トップ
  2. ham
  3. 週末 DIY

ディスクユーティリティを使って FAT でフォーマッットをすると、フォーマットしようとしているディスクが2G未満だと自動的に FAT16 になってしまうようだ。

世の中にはFAT32だけをサポートするという変わったシステムもあるので、そのような環境において 2GB 未満のメディアを使おうとすると、これは困る。しかし以下のように diskutil コマンドからならば普通にフォーマットをかけられる。

$ diskutil list
# /dev/disk2 とか、フォーマットしたいディスクをよくよく確認する
$ diskutil partitionDisk /dev/{{disk}} 1 MBRFormat "MS-DOS FAT32" SD 100%
  1. トップ
  2. tech
  3. Mac で強制的に FAT32 でフォーマットする

OWON デジタルオシロスコープSDS7102 超薄型 1Gsサンプリング100MHzFFT機能付カラーポータブルフルセット【国内正規品】 - OWON

OWON

5.0 / 5.0

OWON SDS7102 というのを買った。OWON は中国の測定器メーカーで、かなり安いオシロスコープを出しているけど、ググったりしてみると割と評判が良く、英語圏でも使ってみたりハックしたりしている記事がヒットする。

オシロスコープの選定基準は主に

  • 帯域
  • サンプリングレート
  • チャンネル数

があるけど、買ったモデルは、帯域 100MHz、サンプリングレート1G samples/sec、2ch のもので、中堅クラスぐらいのもの。帯域が100MHz でも、矩形波にすると25MHz程度までしか観測できないので、マイコンプログラミング程度でもこれぐらいのスペックが必要になり、なかなか厳しいものがある。デジタル回路を見る場合2chは必要…

これ以上のスペックものは正直高すぎて手が出ない。購入価格は正規代理店経由のもので 52000円ぐらい。円安になりつつあって一時期より値段があがっていたけど、消費税もあがると買うことにした。

所感

今までオシロスコープを所持したことがないので、他のオシロスコープとの比較はできない。

届いてあけた感想としては「画面がでかい!」「奥行がない!」という感じだった。ちょうどいい大きさ。

使いこなせるかな、思っていたけど、予想よりは全然操作が簡単で、すぐトリガをかけて単発現象を観測したりはできるようになった。

見えないものが見えるようになるというのはすごくテンションがあがる。可能性が一気に広がったように感じる。

よくないところ

現時点では完全に使いこなせているとは言えないので、あまり思いつかないけど、

  • USB host 側として、FAT32 しかファイルシステムをサポートしてない
  • USB slave 側として、Mac につなげるとなぜか Mac がフリーズする
  • 電源ケーブルが硬く、ソケットが左向きについているので、結構邪魔
  • 電源ケーブルの接続がなんか心もとない

というのがあった。LAN ポートもついていて、こっちの連携はすぐにうまくいった。

  1. トップ
  2. tech
  3. オシロスコープを買った
  1. トップ
  2. ham
  3. オシロスコープを買った

普通にルーターと接続してアドレスとかを設定すると、設定したポートで listen するようになってるのでコマンドを送るだけ。

なので自分で Ruby で実装を書いてみた。bmp を得られるけど、png で欲しいので ImageMagick で変換までしている。

プロトコルフォーマットはググると出てくる。ただ、bin なフォーマットは仕様書とだいぶ違っていて、結構めんどうくさい。

というのがあって、解析したコードがあったりする。けど、とりあえず必要ないし、そこまで実装してない。

  1. トップ
  2. tech
  3. SDS7102 のスクリーンショットを LAN からとる
  1. トップ
  2. ham
  3. SDS7102 のスクリーンショットを LAN からとる