2014年12月19日金曜日

エコキュートの制御 その2

変換コネクタを作ったので繋いでみました。
これは裏側から見た写真です。

こちらは表側

この状態で制御してみると、ちゃんと動作しました。
HA端子のon/offで「ふろ自動」ボタンが制御されます。
HA端子のステータスも「ふろ自動」ボタンのLEDに連動して読み出せます。


とりつけました。


最後にカバーを付けて完成です。
これで風呂の給湯制御が出来るようになりました。
でも、風呂の栓と蓋を自動で出来ないのでいまいちだなぁ。
せめて栓と蓋がされていることを確認出来るようにできないか考えています。
ちょっと難しそうですが。



2014年12月7日日曜日

LEDガーデンライト その4

作ってみました。
結局センサー部は上の隙間から引き出すことで、LEDライトの透明部分にXBeeを収めることにしました。
こんな感じです。

収めたところです。


これで一日太陽にあてて動作すればOKです。




2014年11月30日日曜日

LEDガーデンライト その3


ちょっと作り始めました。
ガーデンライトの回路のうち充電のパスだけ残して外します。
充電電池側に昇圧回路を繋いで出力を引き出します。



これで3.3Vが出来ました。
と、ここまで作ったところでXBeeをどこに配置するか悩んでいます。

1.電池と昇圧回路が入っている黒いケース側にいれる
2.LEDライトの透明な部分に入れる

のどちらかなのですが、1は外周が金属なのでZigBeeの電波が通らなそう。スペースに余裕が有るのに変なところに基板支持用の柱がでていてXBeeモジュールがうまく収まらない。柱を切ってしまえば収まりそうですが、スイッチが使えなくなってしまう。
2もサイズ的にXBeeのモジュールだけでギリギリ、センサーの回路のための基板が入らない。センサーの配線を通すために下に穴を開ける必要があり、構造的に湿気が上がってきて回路が錆びそう。
どちらも一度やってしまうと戻れないので最終的な収まりを考えてからやろうと思います。


とりあえず蓋してみました。


2014年11月14日金曜日

LEDガーデンライト その2


少し時間が空いてしまいました。

結局、CL0116はソーラーセル部分が発電中は充電電池に充電していて、昇圧回路の方は止まってしまうようです。うまく騙して昇圧回路を使えないか考えたのですが難しそうです。

ここはCL0116はソーラーセルから充電電池に充電するためのダイオードだと割りきって、昇圧回路は別途用意することにしました。




こんな回路です。
下の電極間の抵抗が小さくなるとAD1の電位が上がっていくので電圧がある程度以下なら乾燥状態と判断できます。
忙しくてまだ作ってませんが......

2014年10月26日日曜日

LEDガーデンライト

LEDガーデンライトを買ってきました。300円くらいでした。開けてみます。
さらに開けます。

回路を見てみると、なんか4端子のトランジスタのようなICで0116と書かれているものがあり、検索してみるとCL0116 LEDドライバICだそうで秋月で売ってました。回路も参考回路図の通りのようです。ネットで検索すると100均でも同じものが売っているようですね。昇圧回路を含んでいて直接電源も取れそうですが、夜にならないとLEDに給電されないようなので微妙です。やりたいことはソーラーセルから充電電池に昼間に充電しながら、3.3Vを24時間継続的に取り出し観葉植物の土の水分センサーの電源に使うことです。単純にドロップの小さいダイオードでソーラーセルから繋いで充電電池からDC-DCコンバータで昇圧したほうがいいかもしれません。100均で買ってくればソーラーセルと充電電池とケースが108円で買えることになりますね。











2014年10月17日金曜日

エコキュートの制御


観葉植物のセンサーをつくろうと思って部品までは集めましたが、まだLEDランプを買ってきていないので手を付けていません。

風呂の給湯を制御したいとの要望を何人かから聞いたのでちょっと調べてみました。

うちはオール電化でNational時代最後くらいのエコキュートです。



浴室内のコントローラはシールされているので、キッチン側のコントローラを開けてみました。


下側の引掛けを外すとこんな感じで、左端にコネクタが見えます。
取り付け用のマニュアルを見るとこれがHA端子のようです。
でも、通常のHA端子と形が違います。


外してみて、見てみるとpin pitchが2mmです。でも4pinなので多分HA端子の信号そのものかと思います。
とりあえず、左側2pinをピンセットでショートしてみると給湯開始しました。

コネクタ形状はJSTのPHシリーズのように見えます。

HA端子として動作していそうなので、変換コネクタを作って再チャレンジします。



2014年10月10日金曜日

色々とセンサー系を購入






やりたいことは色々あるのですが時間が取れずに進んでいません。
前からつくろうと思っていた観葉植物の水不足センサーを検討しようと思いスイッチサイエンスで部品を買ってみました。
センサー部分です。





こんなもの適当な金属棒2本でいいと思ったのですが、距離が変わると抵抗値が変化してしまうのと、金メッキされてないと電蝕が起こるので買ってみました。トランジスタ付いてるけど要るかなぁ?やってみて調整します。





1.2Vから3.3Vをつくる昇圧コンバータ


よくホームセンターで売っている屋外用のLEDランプを改造して、LEDを光らせる代わりにXBeeを動かすための電源です。多分安いランプだと充電電池が1本だと思うので昇圧が必要です。LEDランプは週末にでも買いに行ってこようと思います。

今のところの構想では太陽電池+充電電池の部分を活かしてXBeeの電源としADCにセンサーを付けて定期的に送信させるものをLEDランプのケースの中で作り込めないかと考えています。
センサーの制御自体は雨センサーと同じでよくてセンサー部の抵抗値を調整すればうまくいくのではないかな。

2014年10月3日金曜日

RaspberryPiのha1control daemonの更新

使わない機能を削除したり、新しい機能を追加したりしているうちにコードがかなり汚くなってきてしまいました。少しづつ掃除も兼ねて見なおしているのですが、なかなか進みません。
今年になってからの主な機能的な変更点は以下のとおりです。

・HA2module/RP-1 RIR基板のAVRマイコンFW updateに対応
 AVRマイコンのコードをbootとアプリケーションFWに分離して、アプリの方はXBee経由でupdate出来るようにしました。bootの方はAVR用の書き込み治具で直接書き換える必要がありますが、こちらはupdate時に使用されるだけなので書き換える必要は特にないと思います。ha1control daemonの起動時にconfig fileで指定したファイルのバージョンとHA2module/RP-1 RIR基板のAVRのFWバージョンを比較して新しいものがあればupdateされます。

・HA2module/RP-1 RIR基板の赤外線リモコン受信に対応
  AVRマイコンのFWに赤外線リモコン受信機能を追加して、受信したらコード化してha1control daemonに通知するようにしました。

・HA2moduleのAVR側のADCサポート
 これまでXBeeのADCを使ってきたのですが、電圧範囲が0~1.2Vで分圧しないと使えなかったりするものが多く0~3.3Vの方がいいなと思っていました。AVRマイコンの方のADCはリファレンス電圧を色々選べてHA2moduleでは3.3VにしているのでこちらのADCも使えるようにしてHoneywellのHIH-5030という湿度センサーをつなげるようにしました。

・LEDTape用のコマンド追加(ledコマンド)
 以前書いたLEDTapeを制御できるようにコマンドを追加しています。リモコンやスイッチのセンサーなどのイベントでLEDTapeを点灯させたり出来るようにしています。

・HA2module/RP-1 RIR基板の情報表示コマンド追加(devinfo)
 FW update対応したことで各デバイスのFWのバージョン情報や動作ステータス、機能情報などを見られるコマンドを追加しました。

・リモコン受信イベント対応
 AVRマイコンで赤外線リモコンを受信したらha1control daemonで何かコマンドを実行する機能を追加しました。適当なリモコンコードをに名前をつけて学習させてconfig fileでそのコード名で実行するコマンドを記述することで赤外線リモコン対応でない電動シャッターや玄関の電気錠などを赤外線リモコンで制御することが可能になります。RaspberryPi本体の赤外線受信機能では残念ながらこの機能は動きません。これは現状の赤外線受信機能のPCM受信部の実装がデバイスドライバではなくユーザー空間で実装したことで常に受信状態にしておくと負荷が大きいためです。デバイスドライバでDMACを使った実装に変更すれば出来そうですがHA2moduleがあるので後回しにしています。

・リモコンコードを学習リモコンに登録するために回数指定でリピートする機能追加
 リモコン受信イベントに追加する時に手持ちの赤外線リモコンだと他の機器が動いてしまうので都合が悪い場合、ha1control daemonで管理しているリモコンコードを適当にコピーして編集することで、他の機器が動かない独自のコードを作成できます。このコードを学習リモコンに登録することで色々使えるようになるのですが、学習リモコンは学習するリモコンコードを連続して受けることを想定しているようなので1回だけコードを送ると登録してくれません。そこでリモコンコードを回数指定して送ることが出来る機能を追加しました。

これらに付随してコマンドの構造を変更したりQueue管理のbugを修正したりという地味な部分に時間がかかってしまってます。
まだまだやりたいことが色々あるのですが現状リモコン受信その3と同じものですがここに置いてあります。

2014年9月26日金曜日

リモコン送信 RaspberryPi編

RaspberryPiの送信側はAVRと共通化出来そうな部分があまりないので、以前からあるFormatAEHA,FormatNEC,FormatSONYはそのままで変更せずにFormatOtherのみ最新のフォーマットに合わせて変更しました。CodeExpandOther()の部分になります。
最初にコードをheader部、PatternTable部、Code部に分けて処理しています。
Code部をビットパターンとそれ以外の処理に分けて、ビットパターンの場合1ビットずつ取り出して0/1High区間、Low区間の長さ、それ以外の場合はPatternTableからHigh区間、Low区間の長さを取り出しHigh区間の間は1CLK毎にHigh/Lowを繰り返し、Low区間の間はLowを繰り返します。
High区間のところをHigh/Lowを繰り返しているのは赤外線LED38KHzのサブキャリアに載せた形で出力されるようにするためです。(76KHzPCM audio I/Fから出力しているためHigh/Lowを繰り返すと38KHzの波形になる)
これらの処理をCode部が終わるまで繰り返しPCMBufferに書き出します。
他のフォーマットは以前のままなので変更なしです。
それぞれのフォーマットのコードをPCMのデータに変換したあと、PCMWrite()をリピート回数分繰り返しPCM audio I/Fからの出力で赤外線LEDをドライブします。


これらのコードはここにあります。

2014年9月19日金曜日

リモコン送信 AVRマイコン編

赤外線リモコンは30kHz~40kHz程度でduty1/2~1/3くらいの副搬送波にデータを載せて送信しています。リモコン受光部はこの副搬送波でフィルターしたデータを取り出して出力してきますが、フィルターは結構広い周波数を許容してくれます。またdutyはフィルターにはあまり関係無いので今回は発光強度を上げるためにも1/2で発光させるようにしています。
AVRでの赤外線出力は8bit TimerであるTIMER0を38kHzでPWM出力し、これをOnしている期間をHighのデータ期間、Offしている期間をLowの期間として使用します。

今回はFormatAEHA,FormatNEC,FormatSONY,FormatOtherの4パターンをそれぞれの処理ルーチンで実装していますが、基本的な動作はHigh・Lowの切り替えタイミングを順次Timer割り込みで処理していくことでリモコン信号を作っています。

例としてFormatOtherの場合を解説します。
IRSendコマンドを受けるとデータが揃うのを待ってIrOutput::Send()が呼び出されます。
この中でFormatの種類を判別してSendOther()に分岐します。
SendOther()ではHeader部分を解釈し内部シーケンス用の変数を初期化してSendOtherBody()を呼び出します。
SendOtherBody()ではデータ領域を1byteずつ順番に読みだして、ビットパターンとそれ以外のパターンに分けます。
ビットパターンの場合は後続するデータを1bitずつ読みだし値によってPattern0/Pattern1のHigh/Low期間のパターンを送出します。
それ以外のパターンの場合、パターン番号のパターンのHigh/Low期間のパターンを送出します。
これをデータの最後まで繰り返し、1セットのリモコンコードを送ります。

その後、リピート間隔分の時間を置いてリピート回数に応じて同じ処理を繰り返し、最後にコマンドの応答を返して終了します。

前回と同じものですがこれらを実装したHA2moduleのコードはここにあります。


2014年9月12日金曜日

リモコン受信 RaspberryPi編

AVRの方のFormatOtherを変更したので、RaspberryPiの方も変更をかけました。
以前はIRRemote.ccの中で処理を完結させていたのですが、赤外線リモコンを受信した後の解釈部分はAVRと共通化しました。
IrAnalyze.cc,IrDataBuffer.cc,IrPatternTable.ccをそのまま持ってきてIRRemote.ccの中でPCM audio I/Fからバッファに赤外線リモコンの生データを読み込んだ後、PulseRecord()の中でAVRのPinChange割込みの処理と等価になるように処理します。
その後はAVRの通常Threadと同じように各フォーマットの解析をしてCodeBufferにリモコンコードを生成しています。
以下詳細。

Record()が記録部分のメイン処理です。
この中のPCMRead()で赤外線リモコンデータを76kHzでPCMAudio I/Fを使ってサンプリングしています。その後、PulseRecord()の中で圧縮処理をしています。
ここまででFormatOtherのデータが生成されている状態になります。
次にFormatAEHA,FormatNEC,FormatSONYのそれぞれの解析をしてみてエラーが出るかどうかを確認しています。どれかでエラーが出なかった場合はそのフォーマット、3つともエラーの場合はFormatOtherとしてファイルに記録して終わります。

PCMRead()の中では、76kHzのサンプリングクロックでPCM Audio Inputのポートに繋いだ赤外線受光部からの信号を記録し32bit毎にデータとして取り込んでいきます。
最初に何らかのデータが来るまで待って、データが来始めたところからサンプリングバッファに記録していきます。このルーチンの中では取り敢えずサンプリングバッファが一杯になるまで記録して戻ります。

PulseRecord()の中ではPCMRead()で記録したサンプリングデータの中の有効な部分をまず切り出します。
データの変化のある最初の部分から連続して100ms以上データがない状態になるまでの期間を有効なデータとしています。
その後、有効な区間を解析していきます。
有効期間を先頭から順番にデータの変化点の区間をHigh,LowのペアのデータとしてSearchPatternTable()、CalcAverage()で (AVRと共通なIrPatternTable.ccのルーチン)PatternTableに登録していきます。
パターンが全て登録し終わると最後のHigh区間のデータを登録しMakePatternConvTable()を呼び出し、登録されているパターンの上位2つのデータを0/1として選び、それ以外のデータを登録順に登録したパターンテーブルを作成します。

その後、再度有効な部分を順番に解析していきます。
データ区間のHigh/Low期間をパターンテーブルから検索し、0/1の場合はビットパターンとして記録、2番目以降の場合はそれ以外のパターンとしてパターン番号を記録していきます。
最後にCodeBufferの先頭部分にデータ長やフォーマットコード、データサイズ、パターンテーブルサイズを記録して戻ります。

以上がRaspberryPiでの赤外線リモコンの記録シーケンスになります。
これらのコードはここにあります。

2014年9月5日金曜日

リモコン受信 AVRマイコン編 その2

前回のTimeout割込みで最終bitの処理をして通常Threadをkickしたところからの続きです。

□通常Threadの処理
FIFOに64パルス分残っているのでこれの記録処理を行います。
次にデータのリピートを確認します。ここでは同じパターンが4回以上連続しているもの、2回、3回連続で丁度データが終わっているものをリピートしているとみなし1回分のデータに短縮します。
これは、HA2moduleで受信したコードをHA1ControlServerに転送し判別して何か動作させるためにコードが同じであることを比較しなくてはならず、リピートも回数の不一致を無視する必要があるので比較しやすいようにこのようなことをしています。最後にデータの先頭にHeaderを書き込み、これでFormatOtherとしてのデータが完成します。
フォーマットは上記の理由でそのままではないですがこちらの電子牛乳さんを参考にしています。
FormatOther
 code[0],code[1]    = length
 code[2]            = FormatOther 0xff
 code[3]            = DataSize
 code[4]            = RepeatCount/PatternTableSize
 code[5]-           = Data .....
    Data:
     0xxxxxxxx(続くbit patternのbit数-1) bit pattern + padding(byte align)
     1xxxxxxxx(PatternTableの番号) : 上位2つ以外のパターンを指定
 code[5+DataSize]-  = PatternTable
    PatternTable:
      [pattern 0] [pattern 1] ... [pattern N]
        [pattern x] : xx xx yy yy (4bytes) : xxxx=HiCLK / yyyy=LoCLK

その後Leader,Dataをチェックし、AEHAフォーマットなら以下のコードに置きまえます。
FormatAEHA
 code[0],code[1]    = length
 code[2]            = FormatAEHA 0x01
 code[3]            = TWIDTH
 code[4] -          = CustomerCode/Parity/Data0, Data1, Data2, ... DataN

NECフォーマットなら以下のコードに置きまえます。
FormatNEC
 code[0],code[1]    = length
 code[2]            = FormatNEC 0x02
 code[3]            = TWIDTH
 code[4] - code[7]  = CustomerCode, Data, ~Data

SONYフォーマットなら以下のコードに置き換えます。
FormatSONY
 code[0],code[1]    = length
 code[2]            = FormatSONY 0x03
 code[3]            = TWIDTH
 code[4]            = AddrLen (5/8/13)
 code[5]            = Data
 code[6],code[7]    = Address

どれでもなければOtherFormatのままXBeeのパケットとして送信します。

□データの記録結果
これで特に長いと評判のダイキンエアコンの電源ボタンをおした時のコードを記録してみると
00 49 ff 30 05 04 00 82 83 3f 11 da 27 00 c5 00
00 d7 84 83 3f 11 da 27 00 42 00 00 54 84 83 7f
11 da 27 00 00 38 32 00 a0 0f 00 06 60 00 01 c0
17 00 00 52 84 00 26 00 1e 00 25 00 61 00 27 07
bc 01 11 00 82 00 27 0a 9e
となりました。
FormatOtherで全体で0x0049=73バイト、データ0x30=48バイト、パターンテーブル5個
PatternTableは後半部分High/Lowの表記で
0026/001e
0025/0061
0027/07bc
0111/0082
0027/0a9e
の5つです。先頭から2つがbit = 0, bit = 1を表すパターンになります。

最初にbit 0 x 5 + Stop





04 00 82 でbit 0(0026/001e) x 5 + Stop(0027/07bc)
 04は続く(4+1)bitがデータパターンであることを示しています。ここでは5bitとも0です。
 82は最上位bitが1なのでパターンテーブルの2番目を示しています。
少し空いてLeader+Data 64bit+Stop




83 3f 11 da 27 00 c5 00 00 d7 84 でLeader(0111/0082) + Data 64bit + Stop(0027/0a9e)
 83はパターンテーブル3番目
 3fは続く(0x3f + 1 = 64(10進数))bitがデータパターン
 84はパターンテーブル4番目を示しています。
少し空いてLeader+Data 64bit+Stop
83 3f 11 da 27 00 42 00 00 54 84 でLeader(0111/0082) + Data 64bit + Stop(0027/0a9e)
少し空いてLeader+Data 152bit+Stop
83 7f 11 da 27 00 00 38 32 00 a0 0f 00 06 60 00 01 c0 でLeader(0111/0082) + Data 128bit
 83はパターンテーブル3番目
 7fは続く(0x7f + 1 = 128)bitがデータパターン
17 00 00 52 84 でData 24bit + Stop(0027/0a9e)
 17は続く(0x17 + 1 = 24)bitがデータパターン
 (ここでデータパターンが2つに分かれているのは1つ目が最上位bitを0にした7bitで表せる最長の値0x7fまでのデータで一度区切っているためです。データパターン長を1引いた値で管理しているのは最長の0x7fの時に丁度16byteで収まる128bitにするためです。1引かずに表してしまうと1つ目が127bitで2つ目が25bitになってしまい1byteデータが伸びてしまいます。)
というフォーマットでした。
波形と見比べてみると合っていそうです。

これらを実装したHA2moduleのコードはここにあります。

2014年8月29日金曜日

リモコン受信 AVRマイコン編 その1

以前RaspberryPiでリモコン受信するやり方を書きましたが、今回はHA2module上のAVRマイコンでリモコン受信してコード化する方法について書きます。色々とあって長いので3回に分けて書きます。

赤外線リモコンのフォーマットは色々あって全てに対応するのは難しいですが、国内の一般的な赤外線リモコンはサブキャリアが38kHz前後で、AV機器は数十bit程度の長さが多いようです。エアコンの中にはかなり長く300bitを超えるものも存在しています。
赤外線受信モジュールはサブキャリアをフィルターしてパルスデータだけを出力してくれるので、GPIOで受けてパルスの変化のタイミングの間隔を見ていけばデコードできます。今回はAVRのPinChangeInterruptでTimerのCounter値を読んで前回の変化からの時間を記録するようにしました。
最初は自宅にある機器をメインに考えていたためAEHA,NEC,SONYのリモコンだけ対応すればよかったので、この割込みの処理の中でフォーマットの解釈もする実装にしていました。
ところが色々なリモコンを検討し始めたところ、このやり方ではダイキンやパナソニックのエアコンコードなどが対応出来ないため再度実装しなおしました。
新しい実装では、まずはじめにPinChange割込み処理中にHigh区間幅、Low区間幅のペアの頻度統計を取りながらコード化して記録します。
全体を記録し終えたところで押し続けることによる繰り返しパターンの判別をし、AEHA,NEC,SONYのフォーマットを解釈していずれかであればそのフォーマット、何れでもなければ記録したフォーマットをXBee経由で送るようにしています。
以下、実際の処理の詳細です。

□PinChange割込み中の処理
パルスをHigh区間、Low区間(実際の受光モジュールの出力は逆ですが、わかりやすいように無信号状態をLowとしています)をそれぞれ76kHzのカウント値で数えペアの値とします。このペアの値をPatternTableを検索し近い値があればそのPatternとして、なければ新規に登録して、そのPattern番号を求めます。
その番号を記録バッファに記録していくのですがそのまま番号を記録していくと4bit単位で記録していったとしても300bit越えのエアコンフォーマットだと余裕をみて196byte位必要になってしまいます。
普通のリモコンコードはデータを表すパターン2種類が0と1を表していて頻出するはずなのでこの2つを1bitの値として扱い、それ以外のパターンを特殊扱いすれば全体として短くすることが出来るはずです。ところがリモコンを受信し始めたタイミングではどのパターンがデータを表す2種類のパターンなのかは判りません。
そこで出現頻度を判断できるように先頭の64パルスを圧縮処理を遅らせるためにFIFOに登録しながら統計をとり、64パルス揃ったところで出現率の多いPatternを2つ選び、2つのうちHigh+Lowが小さい、等しい場合はHighが小さい方をパターン番号0、大きい方をパターン番号1とします。それ以外のパターンは出現順にパターン番号2から順番に登録します。普通のリモコンコードの場合、大体5〜6種類程度に収まります。
64パルス目以降はFIFOにパルス幅を登録しながらFIFOの先頭から順番に値を取り出します。
この時64パルス目のタイミングでそれまでのデータをまとめて処理してしまうと割込み中の処理が重すぎて取りこぼしが発生するので、FIFOでずらしたその割込みの64パルス前のパルスの処理だけを行うようにしています。
この説明だけでは判りにくいかと思いますが、あとで実際のエアコンのフォーマットを使って説明します。

□Timeout割込み
PinChange割込みのたびにTimerに100msのTimeoutを登録、更新します。
最後のPinChange割込みから100ms経つとTimeout割込みが入り、最終ビットパターンの処理を行い、通常Threadに処理を渡します。

長くなってきたので、一旦ここで切ります。
次回は通常Threadで後処理をするところからです。

2014年8月21日木曜日

子供用のスイッチボックス

1歳の息子が壁の電気のスイッチに興味をもって、頻繁にスイッチを押すために抱っこをせがむので子供用にスイッチボックスを作りました。 



よく、自治体の子育て施設とかに行くと壁にスイッチを沢山つけたものとか設置してあるので、子供は興味を持つものなのですね。
押してもなにも反応しないとすぐ飽きられてしまうので、中にモジュールをいれて単1電池で電源を取るようにしました。
これをコントロールサーバーとXBee経由で接続しLEDテープをランダムな色で光らせるようにしました。
中身はこんな感じです。


XBeeを間欠モードで動かすことで消費電力を抑えているので多分半年ほどは電池交換なしで行けるかと思います。
投げられても電池が外れないように固定して、新聞紙で間を埋めてガムテープで箱を閉じてます。
一見、ただ段ボール箱にスイッチを付けただけでどこにも繋がってないように見えるのに実際にスイッチとして動くのが面白いかと思ったのですが1歳の子供には理解できないですね。


2014年8月17日日曜日

LEDTape

PHILIPSのHueのライトリボンをみて作ってみようと思い部品を探してみました。
スイッチサイエンスにフルカラーシリアルLEDがあったので試しに購入。簡単に点くかと思ったら意外とタイミングが厳しく、8MHz動作のAVRの場合割り込み禁止してアセンブラでクロック数を数えながら無駄なく書かないとうまく点きませんでした。
写真は明るいキッチンカウンターの上でとっていますが、LEDが強すぎてLED以外の部分が真っ暗になってしまってうまく撮れなかったので見た目に合わせて色補正かけています。実際に見るとかなり眩しいです。



このLEDは1m60個のフルカラーLEDで、今回は半分に切って50cm30個で使っています。
本当は1灯ずつフルカラーで色を指定できるのですが、実際に使うとなると全体を同じ色で光らせれば十分なのでLEDの個数とR,G,Bを指定してPORTC4につないだシリアルLED を光らせる関数を作りました。
この関数を呼ぶと30us x LEDの個数分割り込み禁止になります。
1m品の場合60個なので1.8msの間blockされます。UARTでフロー制御していない場合、AVRはFIFOが1段しかないので4800bps以下に設定しないと通信を取りこぼします。
HA2moduleで接続しているので、XBeeを4800bpsで接続してコントロールサーバー経由で制御するようにしています。

void SetLED(unsigned char count, unsigned char r, unsigned char g, unsigned char b) {

  asm volatile(
               "  in __tmp_reg__,__SREG__ \n" // interrupt block 30us x count
               "  cli                     \n"
               "  in r6, %[port]          \n"
               "  or r6, %[tmp]           \n"
               "  mov r5, r6              \n"
               "  eor r5, %[tmp]          \n"
               "  mov r2, %[byteg]        \n"
               "loop:                     \n"
               "  ldi %[tmp], 8           \n" // 1
               "loopg:                    \n"
               "  out %[port], r5         \n" // 1
               "  nop                     \n" // 1
               "  sbrs r2, 7              \n" // 1 - 2
               "  out %[port], r6         \n" // 1
               "  lsl r2                  \n" // 1
               "  mov r3, %[byter]        \n" // 1
               "  dec %[tmp]              \n" // 1
               "  out %[port], r6         \n" // 1
               "  brne loopg              \n" // 2
               "                          \n"
               "  ldi %[tmp], 8           \n" // 1
               "loopr:                    \n"
               "  out %[port], r5         \n" // 1
               "  nop                     \n" // 1
               "  sbrs r3, 7              \n" // 1 - 2
               "  out %[port], r6         \n" // 1
               "  lsl r3                  \n" // 1
               "  mov r4 , %[byteb]       \n" // 1
               "  dec %[tmp]              \n" // 1
               "  out %[port], r6         \n" // 1
               "  brne loopr              \n" // 2
               "                          \n"
               "  ldi %[tmp], 8           \n" // 1
               "loopb:                    \n"
               "  out %[port], r5         \n" // 1
               "  nop                     \n" // 1
               "  sbrs r4, 7              \n" // 1 - 2
               "  out %[port], r6         \n" // 1
               "  lsl r4                  \n" // 1
               "  mov r2, %[byteg]        \n" // 1
               "  dec %[tmp]              \n" // 1
               "  out %[port], r6         \n" // 1
               "  brne loopb              \n" // 2
               "  dec %[count]            \n" // 1
               "  brne loop               \n" // 2
               "  out __SREG__,__tmp_reg__\n"
               : 
               : [count] "r" (count),
                 [byter]  "r" (r),
                 [byteg]  "r" (g),
                 [byteb]  "r" (b),
                 [tmp]    "r" ((1 << PORTC4)),
                 [port]   "I" (_SFR_IO_ADDR(PORTC))
               : "r0", "r2", "r3", "r4", "r5", "r6");
}

2014年8月9日土曜日

bootの書き込みツール(AVR USB-ISP)



HA2モジュールは大きさの関係で特殊なコネクタを使用していますが、コネクタを変換すれば3.3V対応のAVR用のwriterを使用できます。
AtmelのAVR ISP mkIIが一番無難ですが、嵩張るのでaitendo AVR-USBasp-Bを改造して(5V->3.3V)使用していました。最近もう1つ必要で購入しようとしたら在庫切れで買えなくなっていたので、同じくaitendoのUSB-ASPの方を買って改造しました。




このUSB-ASPはFWが公開されておらずそのままではMacで使えないので、こちらのページ

を参考にFWを書き換え、B面に3端子レギュレータを載せて5VとVCCをつないでいるパターンをカットして3.3Vに変更しています。小型でなかなか便利なので最近の愛用品です。


2014年7月31日木曜日

XBeeSetup

XBeeのFW書き換えや各種設定をするのにX-CTUやmoltosenso Network Managerを使用するのが普通のやり方なのですが、terminalから設定ファイルを読み込むコマンドの形で使いたかったのでFW更新して設定するプログラムを作りました。
FWはDigi Internationalのページからダウンロードしてきて下さい。
 XBee / XBee-Pro ZB (S2) Modulesを選択、次のページでFirmware Updatesを開いてXBee / XBee-PRO ZB firmware ver. 2xA7を選ぶと82001817_G.zipがダウンロードされるので展開し、82001817_G/ebl_files/のXB24-ZB_21A7.eblからXB24-ZB_29A7.eblをXBeeSetupのdirectoryにコピーします。

configファイルの記述方法はsample.confを参考にしてもらえばわかると思いますが、
書き込むfirmwareのversion(XBeeの動作モード毎にfirmwareが違う。例えばCoordinator APIで使う場合は21A7)をfirmware:の行に記述
setup:以降の行はXBeeに送るATコマンドを記述します。
./XBeeSetup -c sample.conf -d /dev/cu.usbserial (serialのdeviceファイルは環境に合わせて下さい)
を実行するとFWのverisonを確認し、必要ならupdateして設定を書き込みます。
setupの最後にWRを書いておくことでXBeeの不揮発性メモリに設定が記録されます。

ソースコードはここにあります。

2014年7月25日金曜日

HA2module

HA2bootから起動されるHA-2/FC、RP-1/RIR用のプログラムです。
基本的なXBeeとの通信機能の他、赤外線リモコンの送信、受信、HA端子の制御、監視、接点スイッチの制御と監視、ADCの監視などの機能を実装してあります。
赤外線リモコンの送受信は今のところNEC,SONY,家製協フォーマットのみ対応です。
赤外線リモコン受信、HA端子、接点スイッチの監視はイベントが発生するとホスト宛に通知が出るようにしています。
プログラムの構成はScheduler,Timer,XBee,Queue,Usartでシステムとしてのスケジュール管理とXBee経由の通信管理を行い、それ以外の物が各種コマンド実行とそれに付随するデバイスドライバになっています。
このプログラムはXBeeからのコマンドでそれぞれの機能が動作するだけの物なので単独では役に立ちません。
ホスト側のControlDaemonとの組み合わせで機能するようになっています。
ソースコードはこちらにあります。
makeするとha2module.haファイルが出来上がります。

落雷

昨日の夕方、かなり強烈な落雷がありました。
家の中で色々リセットされてました。
対策を入れてあったので今回は壊れたモジュールは有りませんでした。
対策が有効だったということかと思います。

2014年7月17日木曜日

elf2ha

avr-gccで生成された.elfファイルをHA2bootで書き込める.haファイルに変換するためのツールです。
.haフォーマットは先頭16byteのヘッダーとプログラムの先頭からの連続領域のイメージからなる単純なフォーマットです。
ヘッダーの中身はBigEndianで
struct HeaderSt {
  longword Magic; // 'HAUP'の文字列
  word SetId; // moduleの種類を表す16bitの値
  word Version; // プログラムのバージョンを表す16bitの値
  word Addr; // 先頭アドレスだがリセットベクタがあるので必然的に0x0000
  word Size; // プログラムの先頭からのサイズ
  word Reserve;
  word CRC; // プログラムの先頭から終わりまでのCRC
};
です。

HA1Controlプログラムのconfigファイルでこの.haファイルを指定しておくと起動時に各moduleのバージョンチェックをして必要なら更新作業をします。
sudo make installすると/usr/local/binにelf2haが作られます。
HA2moduleのイメージを作るのに必要になります。

ソースコードはここにあります。

2014年7月11日金曜日

HA2boot

HA-2/FCモジュールのAVRのFWをFW更新用のbootプログラムと通常使用時に動く本体FWの2つに分離しました。
bootプログラムは一番最初にAVRのboot領域に書き込みツールで書き込みます。
本体FWはbootプログラムによってXBee経由でAVRのアプリケーション領域に書き込まれます。
通常動作時は本体FWが動作しており、bootに遷移するコマンドを受けるとbootプログラムにjumpします。
bootの書き込みツールは色々あるので別途書きます。
bootは起動するとボーレートを変えながらXBeeにバージョン問い合わせのパケットを投げて帰ってきたパケットを確認することでXBeeとAVR間のボーレートを認識します。
現在のコードでは2400bps, 4800bps, 9600bps, 19200bps, 38400bps, 76800bps, 250000bpsを確認しています。この値はAVRを8MHzで動かした場合に誤差が少なくてちゃんと通信が成立しそうな値を選択しています。
boot自体はアプリケーション領域の本体FWを受け取って書き込む機能に特化しているので、それに必要なコマンドが届くのを待ち続けコマンドが来たら実行するだけの単純なものですが実装して見ると意外と大きくなってしまいATMega328のboot領域ギリギリまで使用してしまいました。
コードをgithubに置きました。

2014年7月3日木曜日

HA-2/FCモジュールの回路修正

1年ほど使ってきて色々回路修正が入ってきたので修正内容をまとめました。

-落雷対策で問題になりそうな端子にバリスタを追加しました。
昨年落雷でモジュールが壊れてバリスタを入れる対策をしたことで、それ以降近所で一度落雷がありましたが壊れること無く動いています。このまま今年の夏も乗り切れれば大丈夫かとおもいます。
-外部端子のAD1,2をAVRのADCからも使えるようにしました。
温度センサーと雨センサーを読み取るのにXBeeのADCを使用してきましたが、XBeeのADCは1.2Vまでしか対応できません。他のセンサーをつなごうとすると3.3Vまでのものも多いためAVR側のADCも接続できるようにしました。
HA-2/FCモジュールはXBee側のADCをoffにして使用します。offになっていれば端子に3.3Vが掛かっても問題ありません。
-外部端子のGPIO1,2をAVRのGPIOからも使えるようにしました。
将来の拡張用としてAVRのGPIOも2本出せるようにしました。
-外部端子に赤外線出力が強弱2系統出していたのを片方赤外線入力に変更しました。
AEHA,NEC,SONYフォーマットの赤外線リモコンコードのみ受信可能です。
解釈後Header部(4byte)を含めて64byteまでのコードを受信できるはずです。(そんなに長いコードを吐くリモコンが手元にないので未確認です)
-XBeeからAVRをリセット出来るようにしました。
AVRのFW updateを出来るようにしたため、bugありのFWを送って同仕様も無くなった時の対策としてXBeeからAVRをリセット出来るようにしました。

修正後の回路図です。


2014年7月1日火曜日

SiriProxyその後

色々あって暫く更新をサボってました。
SiriProxyは当分無理そうなので、iOS8のHomeKitが出てきてから対応を考えようと思います。
更新サボってる間にもいろいろ変更していたので週一程度でぼちぼちと書いていきます。