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のコードはここにあります。