2014年12月25日木曜日

TWE-Lite賞を受賞しました

 先月、こっそり応募した「みんなのラズパイコンテスト」で、しゃべる戸締まりチェッカーがTWE-Lite賞を受賞しました。ありがとうございます。
 事前に届いていたお知らせメールに全く気づかなくて、発表を見て受賞を知りました。
 

賞品は、TWE-Lite DIPその他の福袋という事でしたが、袋ではなく箱で届きました。

いざ、開封。
じゃーん!
 TWE-Lite DIPが4種類とUFL用アンテナ、新商品のパッチアンテナが揃っています。ToCoStickもうれしい。

 意外だったのが 、TWE-Lite SMDとハテナアンテナのセット。しかも、10個の大盤振る舞い。過去の作品はSMD版がメインだったので、ナイスな選定です。今まで手半田の空中配線でしたが、そろそろKiCADに挑戦して、基盤を作らないといけませんね。

 正直なところ、Pythonのスクリプトは少し書きましたが、Raspbery Piが無くてもシステムの大半は問題なく動くし、GPIOもカメラも使っていないので、ラズパイコンテストの応募作品としてはかなり微妙だったと思います。その代わり、TWE-Liteの工作は寝る間を惜しんで頑張りました。

 賞品が生かせるように、次の工作ネタを考えなくちゃ。

2014年12月23日火曜日

自転車発見器でジングルベル

 季節に合わせて、自転車発見器のメロディーをクリスマスソングに変えてみました。今週は、ジングルベルで自転車を探します。

オレオレTWE-Lite R基板でファーム書き換え



 このところお気に入りのTWE-Liteは、DIP/SMD取り混ぜて15個以上を使いました。秋月のFT231X USB-シリアル変換モジュールを持っていたので、専用ライターのTWE-Lite Rは持たず、書き込みにはこのモジュールを使っています。また、使用割合の高いSMDタイプはTWE-Lite Rのソケットに載らないため有り難味がほとんど無く、TWE-Lite Rを必要としない理由のひとつになっています。
 この方法は汎用性があって良いのですが、RESETとPRG(PWM3)をタクトスイッチにつないで操作するのが多少煩わしいです。

TWE-Lite Rの中核部分は設定変更したFT232Rらしく、「TWE-Lite Rメモ」に詳細が書いてありました。メモと回路図を参考に結線し、FT_PROGでEEPROMの設定を書き換えてみたら、TWE-Lite プログラマに「TWE-Liteのリセット」ボタンが現れ、無事にオレオレTWE-Lite Rが出来上がりました。これで、書き換え時のスイッチ操作が不要になります。


  TWE-Lite DIPの下端にある書き換え用端子は、RESET, RX, PRG, TX, GNDの5ピンが引き出されています。また、TWE-Liet Rには対向側の5個の端子が用意されているようです。ただ、実際に使ってみると、
  • 電源に太陽電池やCR2032を使う子機に対しては、書き換え時に外部から安定した電源を供給したい。
  • 無線タグアプリの子機でインタラクティブモードに入るために、M1をアサートしたい。
等の便利機能が欲しくなります。このため、自分で工作する場合は、RESETの隣にVccを、GNDの隣にM1を配置した7ピンをピンヘッダで出しておきます。すなわち、以下のようなピン配置になります。
  1. Vcc
  2. RESET
  3. UART RX
  4. PRG
  5. UART TX
  6. GND
  7. CFG(M1)
 この配置に合わせたピンソケットやTWE-Lite DIP用ソケット、PRG,RESETスイッチ、M1用ジャンパーピンを装備した、オレオレTWE-Lite R用の基板を作りました。結構便利です。






2014年12月22日月曜日

自転車ビーコン メロディー書き換えのデモ

 メロディー書き換えのできるファームウェアの作成と並行して、自転車ビーコンの2セット目を組み立てました。受信機はキャンドゥ(100円ショップ)の自転車用LEDフロントライトを電池ケースとして利用しながら改造、送信機はタカチのプラスチックケースCS75に収納しました。
 デモ動画では、サンプルアプリに入っていた「ちょうちょ」の他に、3曲を次々に書き換えています。
シリアルコマンドを拡張してMML転送用のコマンドパケットを定義し、ペイロードにMMLを載せて、画面外のPCに接続したTWE-Lite DIPから送信しています。受信側では、ペイロードのMMLをEEPROMに書き込んで、すぐに再生を開始します。スリープ中は受信機がコマンドを受信しないので、受信動作が連続するメロディー再生中に書き換えを行います。

2014年12月20日土曜日

自転車ビーコンの改良版ファームウェアを作成

 ブレッドボード上で組んだ試作回路であれこれいじって、改造版のファームウェアが完成しました。
  • 親機からの無線パケットに乗せてMMLのメロディーデータを更新
  • モードビット配線無しに、Device Idでmode3,mode4,mode7が指定可能
  • 子機間欠モードでチャンネル変更に対応(u32ChMaskの末尾をデフォルトchに使用)

マニュアルが無いので使う人はいないと思いますが、回路図とソースコードは公開してあります。
  https://github.com/true-nature/App_BicycleFinder

 無線経由のメロディー更新は、ぜひとも実現したかった機能です。これで、新曲が出てもすぐに対応できます。

2014年12月18日木曜日

自転車ビーコン改造中

 自作の自転車ビーコンは、受信機側の電池を最後に交換してから3箇月経ちました。まだ動いています。

 近日中に、2個目を製作する予定です。2個目の製作と同時に、ファームウェアも以下のように改造します。

間欠モードをDevice Idで指定可能にする

現在は、標準アプリの仕様を継承してモードビットM1,M2,M3の結線で間欠モードを指定しています。間欠10秒モードでは3本すべてをGNDに落とす必要があり、SMD版の製作が多少難しくなっています。
 親機または中継器の場合は、インタラクティブモードでDevice Idを121または122に設定すると、結線無しにモードを変更できますが、子機にはこのような仕様はありません。このモード変更は、ファームウェアを少し改造するだけで子機にも応用できるので、全てのモードをDevice Idで指定できるようにします。

インタラクティブモードで設定したチャンネルを反映させる

現在は、子機間欠モードで使用するチャンネルは、ビルド時に指定したデフォルト値以外使用できません。この原因と思われる部分を見つけたので、対策してみます。

メロディデータを無線経由で変更可能にする

TWE-Liteには4kBのEEPROMがありますが、システムと設定値で少し使用しているだけで、ほとんどが未使用です。もったいないので、ここにMMLデータを置けるようにして、 ファームウェアを書き換えなくてもメロディーを変更できるようにします。

2014年11月10日月曜日

TWE-Liteで雨センサーを作ってみた

せっかく作った戸締まりチェッカー。これを雨センサーを組み合わせたら、窓の閉め忘れで室内びしょ濡れという事故が防げるんではないかと思い、雨センサーを自作しました。
 ニトムズの銅箔テープをカッターで切って、100円ショップのプラ版に1-2mmの間隔で貼り付ければ、センサー電極の完成です。このセンサーをTWE-Lite DIPのAI3とGNDの間に接続し、AI3(ADC2)を2.2MΩでVccにプルアップしました。
 屋外設置なので、電源はTWE-EH Solarと1Fの電気二重層コンデンサの組み合わせにしました。スタート時は充電量が0なのですが、まもなく雨が降るとの予報だったので、乾電池で電気二重層コンデンサを充電して、即運用開始です。

土曜日に製作して、日曜の未明から丸1日の電圧変化をモニターしました。左がそのグラフです。青は雨センサー、緑は電気二重層コンデンサーの電圧です。
 日曜の朝に小雨が降り始めると、すぐに電位が低下しました。この時は平面に放置していたのですが、雨粒がいつまでも留まると晴天時の回復が遅れるため、14時ころに手すり上の斜め設置に変更しました。設置変更の再に雨粒を拭いたので、一時的に電位が回復しています。
 この日曜日の天気は降ったりやんだりでしたが、21頃には雨が上がりました。しかし、雨センサーの電位は翌朝まで下がったままです。ヒーターを内蔵していないので、雨上がりの検出は苦手なようです。大容量の電源は無いし、雨上がりを検出する必要も無いので、この特性は改善する予定はありません。

 せっかく作った雨センサーですが、もうじき訪れる降雪期の事はまるで考えていません。雪の季節に窓を開け放つことは無いので、 寒い時期は片付けて、春になったら運用再開ということになると思います。

2014年11月1日土曜日

RoombaにTWE-Liteを運ばせてLQIを測ってみた

 TWE-LiteのLQI(電波通信品質)が距離の目安になるというので、実際にどの程度のものか実験してみました。

 TWE-Liteを載せたRoombaを4畳半の部屋で走らせて、部屋の四隅に置いた中継器および親機でLQIを1秒毎に測定し、距離感を円で描いて動画化してみました。



 上の図に、LQI値からざっくり推定した距離が円として描いてあります。距離が遠いほど大きな円になります。プロットの範囲は部屋を真上から見た形に相当し、各々の円の中心は対応する中継器の座標に配置してあります。カメラの映像とグラフの時刻が微妙に合っていないため、変化に時間差があるようです。
 LQIと近さの間には正の相関があるのは見て取れますが、いくつか問題があって、この実験では可もなく不可もないという結果になりました。
  • 子機と親機・中継器のアンテナ高さが揃っていないと、アンテナの垂直方向の指向性が合わないため、近くてもLQI値が小さくなる。
  • 測定した部屋が狭すぎるせいか、距離の変化に比較してLQIの変動が大きい。
複数の中継器を置いて相対的な遠近を知る用途なら使えるかもしれませんが、絶対的な距離を知るのは無理っぽい感じです。

2014年10月29日水曜日

戸締まりチェッカー ソーラーセル版子機の充電状態をモニターしてみた

 自家製戸締まりチェッカーのセンサー子機は、リチウム電池版とソーラーセル版の2種類を作りました。リチウム電池の方は興味深い動作は別にありませんが、太陽電池を使うのは初めてなので、どのくらい使い物になるか興味津々でした。

 センサー子機は、I/O状態を定期的に親機へ送信します。この情報には、電源電圧とTWE-EH Solarに接続した電気二重層キャパシタの電圧が含まれています。 これをデコードして、Raspberry Piのモニター用に使っていたmrtgでグラフ化してみました。

  過去1週間のグラフは、このようになりました。運用開始から1週間しか経っておらず、この間にも何度かメンテナンスをしているため、切れ間の多いグラフになってしまいました。
 青色がVcc、緑色がVC2(電気二重層キャパシタ)の電圧です。電気二重層キャパシタは、秋月で買った耐圧5Vの容量1Fです。
週間電圧グラフ
先週の水曜日から計測を開始しましたが、VC2の電圧はほとんど上昇せず、日没の度にシャットダウンしていました。この時の起床間隔は30秒でした。このペースでは、充電と消費が拮抗していたようです。昼間に充電されなくては困るので、金曜日に起床間隔を1分に延長したところ、生き返ったように充電されるようになりました。

 グラフのところどころで、緑色で示した電気二重層キャパシタの電圧が急落している箇所があります。この子機はFRISKのケースに収納していますが、 絶縁がいい加減だったために、ケース内で電極が接触して短絡する事故が発生していたようです。
  月曜の朝にケースを開けたときにもキャパシタを短絡させてしまったらしく、1V未満からのスタートになりました。この日は晴天でしたが、一日かけても2V程度までしか充電することができず、日没直後にTWE-Liteが落ちてしまいました。
 こうも短絡事故が頻発していては困るので、amazonで買ったカプトンテープでTWE-Lite SMDと電気二重層キャパシタを包む対策を火曜日の朝に施しました。この後は、短絡は発生していません。

 火曜日の一日分の電圧は、下のようになりました。起床後に雨戸代わりのシャッターを開けてから充電がスタートし、正午頃には満充電(約3.45V)になっています。10時頃にVccの電圧が急落していますが、これは、VC2が2.6Vの閾値を超えてVccに直結されたためです。その後は、VccとVC2がほぼ同じ電圧で推移しています。
 日中に充分に充電されたため、日没後も動作し続けました。
復活して満充電
  翌日の水曜日は、下のようになりました。電圧は夜明けまで徐々に下がりましたが、3Vを切ることはありませんでした。日中の充電は、9時頃には満充電に達しています。
 もう安心です。このペースなら、暗闇の中でも満充電から丸1日以上は持ちそうです。








2014年10月18日土曜日

戸締まりチェッカーの『しゃべるリモート子機』も完成

そういえば、戸締まりチェッカーのUI部分となる「しゃべるリモート子機」は、一応できています。
最初にLCD用の穴の位置を間違えてしまい、穴を拡大→余分なスペースを穴埋め という無駄をこいてしまったため、かなり見栄えが悪くなっています。
 今は100円ショップの外付けスピーカーですが、いずれ薄型のスピーカーを買い足して内蔵する予定です。

戸締まりチェッカーの親機を製作

親機はペリフェラルを全く持たないので、ただ通電さえしていればいいのですが、いつまでもブレッドボードという訳にも行かないので、基板に載せてケースに収めました。

基板は、秋月のユニバーサル基板 Bタイプです。これを、100円ショップCanDoで買った木製のディスプレイBOX(小)に収納しました。

 同じデザインのディスプレイBOX(大)も売られていますが、この基板には小サイズがぴったりです。木製なので、ドリルで穴あけもカンタン。

 親機の電源は三端子レギュレータの予定でしたが、Raspberry Piでログを取ったりメール通知したりするため、変換基板経由でFT232RLを専属でつなぎました。ちなみに、このFT232RLは、「TWE-Lite R メモ」に書いてあった設定でTWE-Lite R化してあります。

戸締まりチェッカー リチウム電池版を製作

太陽電池版に続いて、コイン型リチウム電池CR2032を使うセンサー子機も作りました。

センサー子機のTWE-Liteは、ハテナアンテナタイプのSMD版を使っています。
センサー子機のために買ったSMD版がずらり
リチウム電池版は、電池ホルダーの厚さがネックになって、MINTIAのケースには入りません。自転車ビーコンのリモコンと同様に、タカチのCS-75ケースを使いました。
2個同時に組み立てました

このケースの場合、電池の裏に配置したTWE-Liteが基板とサッシ枠の間に挟まれる格好になるため、電波の飛びがMINTIAケースより悪くなります。このため、庭も無い狭い家であるにもかかわらず、1階の窓に貼ったセンサー子機からの電波を、2階の対角位置に置いた親機で受信できませんでした。 これでは困るので、子機の真上に当たる2階の部屋に中継器を置いたところ、1階の3箇所に置いた全ての子機の電波を受信できるようになりました。
  これで、センサー子機、親機、リモート子機、中継器と、TWE-ZEROアプリ「Samp_Monitor」の構成を網羅する格好の使用例となりました。

2014年10月17日金曜日

戸締まりチェッカーのセンサー子機(ソーラーモデル)を作成

TWE-EH Solarの紹介ページにあった例を参考に、一丁作ってみました。
一番分厚いパーツは電気二重層キャパシタでした。MINTIAのケースにぎりぎり入ります。
書き換えおよび設定用のピンヘッダが付いているため、スペースに余裕がありません。
 使用前に、電気二重層キャパシタを乾電池で2.7V位まで充電しましたが、早々と電池残量警告が出ました。明日は、親機をRaspberry Piにつないで電池残量をモニターして見ます。

ケースの中身。右端にリードスイッチ。
 

磁力線がリードスイッチを貫通する向きに磁石を取り付けます

ちょっと、はみ出してます。

2014年10月16日木曜日

自転車ビーコンのリモコンをリニューアル

TWE-Lite DIP-PCB をMINTIA BREEZEに入れてリモコンとして使ってきましたが、やっぱりちょっとでかくて格好悪いので、TWE-Lite SMDをタカチのプラスチックケース CS75&専用基板CSPB-75に載せました。
表面は電池、電気二重層キャパシタ(2×0.22F)、書き換え用ピンヘッダ

裏面はTWE-Lite SMD(ハテナアンテナ)とタクトスイッチ

FRISKより少し大きい位のコンパクトなケースです。

タクトスイッチが表に来ます。

新旧リモコンのサイズ比較
このケースは、戸締まりチェッカーのセンサー子機にも使う予定です。

2014年10月6日月曜日

「おしゃべりTWE-Liteで戸締りチェッカー」を作ります

 TWE-Liteを使った実用工作第2弾は、戸締りチェッカーです。無線タグアプリ(Samp_Monitor)をベースに、目的の動作となるように改造します。
 ソフトウェアは着々と実装が進みつつあります。ハードが出来上がるには、あと2-3週間くらいかかりそうです。

 Samp_Monitorの最小構成は、センサー子機(EndDevice_Input)と親機(Parent)です。親機は常時動作で子機からのセンサー情報を待ち受けます。したがって、ACアダプター等の常時供給可能な電源を用意しなくてはなりません。電池駆動では、単三電池で1週間も持ちません。
 通常、戸締りチェックを行うのは外出前の玄関ですが、我が家の玄関にはコンセントがありません。同じシステムを設置しようと考えている会社の事務所も、出入り口付近にはコンセントがありません。設計をする前から、これは困った問題でした。

 こんな用途を予想していたのか、 Samp_Monitorには、さらに進んだ使い方が用意されていました。それが、MessagePoolによるリモート子機(EndDevice_Remote)への情報配布です。現在公開されているv1.3.3およびToCoNet SDKに含まれているv1.3.2のreadmeでは全く触れられていないのですが、2013年11月に配布された旧バージョンのSDKに含まれるv0.7.4では、センサー子機-親機-(中継器)-リモート子機という情報の流れが解説されています。
 センサー子機からの情報を収集した親機は、同報送信で情報を配布するMessagePoolを使って、定期的に中継器および子機に同じ情報を展開することができます。また、子機からのMessagePool 要求に応じてオンデマンドで配布を行うこともできます。この仕組みを利用し、コンセントの近くに常時動作の親機を、玄関に電池駆動のリモート子機を置くことにします。この構成なら、リモート子機は通常はスリープさせておいて、お出かけ前だけ動作させればいいので、電池交換を頻繁に行う必要はありません。

 状態表示の役割を担うリモート子機は、警告LEDとLCDに加え、「TWE-Liteではじめる カンタン電子工作」に載っていた AquesTalk pico LSI を使って、音声によるアナウンスを行います。

 センサー子機については、 Samp_MonitorのEndDevice_Inputが、ほぼそのまま使えます。改造ポイントは、スイッチによる起床に加えて定時送信を行うようにする位です。
 なお、現在公開されているSamp_Monitorでは、ドアタイマー(0x51)および磁気スイッチのモード(0xFE)で、外部プルアップが意図した通りに無効化されないバグがあります。このままでは、待ち受け時の電池持ちが1/10くらいに悪化するので要注意です。この問題は、判定タイミングを設定値読み込み後に移動することで解決します。


2014年10月4日土曜日

自転車ビーコンを使ってみた

毎日、駐輪場で使っています。
一応、置いた時に列と番号を控えていますが、番号を確認しながら探すのは面倒なので、最近はメモを見ることなく、自転車発見器を利用しています。

2014年9月24日水曜日

自転車ビーコンの回路図

自転車ビーコンの回路図を、BSch3Vで描いてみました。

自転車ビーコン送信機
受信機はDIP版とSMD版があり、ピン番号が違います。現在使用しているのはSMD版です。

自転車ビーコン受信機(SMD版)

自転車ビーコン受信機(DIP版)
実物では、
  • ファームウェア書き換え用のピンヘッダまたはピンソケットを接続
  • モード設定ビット端子(M1,M2,M3)をピンヘッダ/ソケット化
 が追加されています。これらは動作時には不要なため、回路図では省略しています。モード設定ビット端子は、使用時はファーム書き換え用ピンソケットのGNDに接続し、書き換えおよび設定変更時には抜いています。

2014年9月23日火曜日

自転車ビーコンの使い勝手向上計画

 リモコン送信機のボタンが小さいため、受信機が反応するまで押し続けるのは、意外と不便な仕様です。ボタンの押しにくさのせいで受信間隔をあまり長くできず、電池持ちも思うように伸ばせませんでした。今週は、ここに改造のメスを入れてみました。

 当初の設計では、リモコン送信機を親機とし、タクトスイッチで電源をON/OFFしていました。押した間だけ電源が入り、動作中は連続送信を行います。
 これを、「チョイ押し」だけで手を離しても数秒間連続して送信を行うように改造しました。
  • 送信機をmode7(子機間欠10秒モード)とし、送信間隔を0秒としました。これで、タイマーによるWakeUpが無効となり、ボタンによる割り込みでのみWakeUpします。
  • 送信機がWakeUpしたら、mode4の送信間隔+100msの間、スリープせずにデータを32回/秒のペースで連続送信するようにしました。
  • 受信機側では、vReceiveIoData()にある親機子機の判定を無効化し、受信したデータを親機/子機の区別無く処理するようにしました。
  送信機のチョイ押しで自動的に送信を続けるので、子機の通信間隔が長くてもボタンを押すのが苦にならなくなりました。この改造に合わせて、
  • 2秒毎だった通信間隔を4秒に延長
  • ADCを行わない受信待ちだけのWakeUp時間を24msに延長
  • 連続送信の間隔を毎秒64回から32回に戻す
  • mode7のスリープ時にRAMを保持しない
という調整も行いました。これで、子機の電池は半年持つ見込みです。
 受信間隔が長いと親機の連続送信時間が延びて、親機の電池持ちは短くなりますが、スリープ時にRAMを保持しないことで待機時の消費電流を減らしました。1日1回の使用で、送信機の電池は7年以上持つ見込みです。

追記:
 この時は子機間で通信するために親子判定を無効化しましたが、子機からの宛先論理IDを親機(0x00)ではなく子機宛とし、この動作を想定するように受信時のID判定を改造するというのがToCoNet的にはまっとうな方法のようです。
  http://tocos-wireless.com/jp/products/TWE-ZERO/App_Twelite/overview.html

2014年9月22日月曜日

TWE-Lite子機間欠モードの受信動作で使えるチャンネル(2)

 子機間欠モードで受信動作をする場合、使えるチャンネルは18だけでしたが、正しくは、「ビルドの際にデフォルト値として設定したチャンネルだけ」でした。デフォルトのチャンネルを18以外にすると、そのチャンネルだけが使えるようになります。

2014年9月20日土曜日

自転車ビーコンの電池持ち問題に対する解決案

 自転車ビーコンの電池持ちが思ったより良くないので、改善を図ることにしました。

 電池が持たない最大の要因は、一回あたりのWakeUp時間が52msと長いせいだと考えられます。その大半が、IO状態の読み取りと送信待ちである事もわかりました。IO状態の読み取りは、電池残量を知る必要があるのでなくす訳には行かないのですが、頻度はある程度減らしてもいいはずです。

 IO状態の読み取りを60秒毎に1回のペースまで落とし、2秒に1回のWakeUp時間を減らしたところ、計測できる下限の4msになりました。これは、起きた直後にスリープするような感じです。しかし、ここまで短くしてしまうと、親機からのパケットを取りこぼしてばかりで、肝心のビーコンとしての動作が開始できなくなりました。
 タイミングのイメージとしては、 この図のようになります。青が子機のWakeUp時間、ピンクが親機のパケット送信時間を表しています。
  WakeUp部分を切り出しすと、下の図になります。1/32秒間隔で再送1回を伴う送信を行う場合、4msのWakeUp時間では親機のパケットの隙間に埋もれてしまい、すれ違いがちになります。
    
 WakeUp時間があまりに短いと、受信処理に支障が出ることが分かったので、スリープ前にウェイト入れてWakeUp時間を20msに延長してみました。
  かなりマシになりましたが、まだ時々取りこぼします。タイミングによっては、WakeUpが親機のパケットの隙間を縫ってしまうようです。
 ウエイトを長くしてWakeUp時間をたっぷり確保すれば確実に受信できますが、それでは電池持ちが改善されません。
 電池持ちのために受信間隔を長くするとWakeUpを長くしても電池は持ちますが、応答が悪くなってしまいます。 また、たまに取りこぼしたときのペナルティが大きくなってしまう問題もあります。

 この問題を解決するために、子機のWakeUp時間を20msにしたまま、親機のパケット送信ペースを毎秒64回に倍増することにしました。
  今度は、子機のWakeUp時間の間に、親機のパケットを確実に受信できるようになりました。
 パケット密度が高すぎて輻輳がちょっと心配になりますが、親機の電源は一日に2-3秒しかONにしませんので、この方法で行く事にします。

2014年9月18日木曜日

自転車ビーコンの電池持ち問題

 今日から自転車ビーコンの本番運用を開始しました。が、帰宅時に鳴らしたところ、早くも子機の電池警告サインが発動してしまいました。試作中に使用していた電池をそのまま使っているので、試運転で減ってはいたと思いますが、予想を上回る早さです。

 電池消費の要因は間欠受信のWakeUp時間が長いせいではと思い、vProcessEvCoreSlp()にデバッグログを追加して、状態遷移の間隔を測ってみました。すると、時刻の起点をWakeUpとした場合、
  • WakeUp 0ms
  • IO状態の確定 32ms
  • 送信完了,Sleep 48ms
  • 次のWakeUp 52ms
でした。時刻の刻みは4msです。1サイクルに52msもかかっています。

 動作中の消費電流は、Sleep時は2μA、WakeUp中は18.7mA、メロディ再生中は約21mAでした。Sleep時の電流は無視して、動作中をざっくり20mAとすると、2秒間隔の間欠モードで一日に消費する電流容量は、
(86400/2) * 0.052 * 0.02 = 44.9 [mA sec]
です。これに、1日あたり50秒のメロディ鳴動を追加すると、
44.9 + 50 * 0.021 = 46.0 [mA sec]
が、一日あたりの総消費電流容量になります。
 電源のニッケル水素電池の容量は750mAhです。満充電から1.2Vの電池警告までに容量の8割まで利用できるとすると、利用できる日数は、
0.8 * 0.75 * 3600 / 46 = 47 [日]
で、電池寿命は約1ヵ月半と予想されます。自分としては、ちょっと短いなと思います。

 子機は受信専用として使っていて、送信したデータは使っていないのですが、WakeUp中の動作時間のうち大半を、IO状態の読み取りと、読み取ったデータの送信が占めています。これはもったいない。ざっくり無効化したいところですが、IO状態の読み取りは電池残量を知るために必要なので、完全に消すと残量チェックができなくなります。ただ、WakeUpの度に毎回知る必要も無いので、もっと長いインターバルを置いて、例えば32回のWakeUpに対して1回計測するという動作にすれば、電池持ちは大きく改善できると思います。

2014年9月17日水曜日

TWE-Lite子機間欠モードの受信動作で使えるチャンネルは18だけ

 先日のエントリーで、TWE-Liteの子機間欠モードで受信を有効にしても、チャンネルによって機能しない場合があって大いに時間をロスした事を書きました。自転車ビーコンの製作が済んだので、改めて、11から26までの16個のチャンネルのうち、どれが使えるのかを調べてみました。その結果、18以外は全滅でした。親機から子機への通信が、連続モードでは動くのに、子機間欠モードにすると全く伝わらなくなります。子機から親機への送信結果は刻々と親機に表示されていたので、親機と子機でチャンネルが違っていたという落ちはありません。
 子機間欠モードで受信動作をさせる場合、使えるチャンネルは18だけです。したがって、チャンネルの住み分けでグループ化の区別をすることはできません。混信を防ぐには、アプリケーションIDの使い分けに頼ることになります。

2014年9月15日月曜日

メロディーと音で置き場所を知らせる自転車ビーコン完成

 この三連休で完成しました。左が子機、右が親機(コマンダーリモコン)です。


 LEDと圧電スピーカーを装備した子機は、100円ショップCanDoの自転車用LEDリアライトに、TWE-Lite(SMDタイプ)のハテナアンテナ型を格納しています。圧電スピーカーはサイズと音量の都合でケースの外に接着しています。
 親機のコマンダーリモコンは、MINTIA BREEZEのケースに、TEW-Lite(DIPタイプ)のPCBアンテナ型を格納しています。開閉できる蓋の中にタクトスイッチを仕込んで、押している間だけ電源が入り、毎秒32回の連続送信を行います。連続送信する親機はCR2032では賄えない電流を消費するため、電気二重層キャパシタを追加しています。
子機の中身

 TWE-Liteには、「超簡単!TWE標準アプリ」v1.7にToCoNet SDKに入っていたApp_MelodyのMML再生機能を流用し、さらに標準アプリでは無効化されていた子機間欠モードの受信動作を有効にしています。

  アンテナの設置条件は良くありませんが、メロディが聞き取れなくなる数十m先からでも反応しました。

 ソースコードは、githubで公開しています。

2014年9月14日日曜日

メロディーと光で置き場所を知らせる自転車ビーコン製作中

回路とソフトの試作ができました。
昨日は、使用するチャンネルを変えると、親子のチャンネルが揃っていても応答しないという落とし穴で一日無駄にしましたが、今日は快調です。自機または対抗機(親機)の電池残量が少なくなったときに、LEDの点滅周期を速くして警告する機能も付けました。



TWE--Lite子機間欠モードで受信が行えるチャンネル

 TWE-Liteのチャンネルをデフォルトの18から16に変えたら、子機間欠モードの受信動作が機能しなくなった。すべてのチャンネルを調べたわけではないが、どうも、使用するチャンネルによって、間欠モードの受信動作が動いたり動かなかったりするらしい。これに気がつくまで、ほぼ1日かかった。今のところ、16,18,19と3種類試してみて、成功したのは18だけ。

TWE-Liteの子機間欠モードで受信動作した場合の消費電流

 子機間欠モードの受信動作は、sToCoNet_AppContext.bRxOnIdle を有効にするまで成功しなかった。このフラグの説明には、
  • 無線回路アイドル時も受信回路を動作させます。
  • 受信時は常に受信電流を消費します。
と書かれている。これだけ読むと、スリープさせても受信回路が起きていて電流を消費しまくるように受け取れる。受信動作中のTWE-Liteの消費電流は約17mAなので、こんなんでは間欠モードの受信動作は使えないと思えるが、やってみたら、実はそうではなかった。
 テスターで図ったところ、bRxOnIdleをTRUEに変えても、スリープ中に大きな電流を消費することは無かった。ブレッドボード上に回路を組んだ状態での実測値は1.9μAと、とても小さかった。どうやら、bRxOnIdleを有効にしても常時動作をするわけではなく、結局、スリープが解除されている間しか受信は行わないようだ。これは、スリープ中に親機からパケットを送っても反応しない事実とも矛盾しない。

2014年9月10日水曜日

子機間欠モードで待ち受ける自転車ビーコン

 TOCOS TWE-Liteで動作する、自転車ビーコンアプリケーションのソースコードをgithubに置きました。親機/子機のどちらでも機能します。
    https://github.com/true-nature/App_BicycleFinder

 アピールポイントは、ズバリ「子機間欠モードでの受信動作」です。検索しても実装例が見つけられなかったので、TWE-Liteの応用例としては珍しいのでないかと思います。
 心配される電池持ちは、自転車に取り付ける実物ができてから計測します。

2014年9月9日火曜日

TWE-Liteで子機を間欠モードにした場合の親機側の設定

 子機間欠モードで受信をする場合は、親機側の動作も変更しないと実用にならない。連続動作モードで連続なのは受信の方で、送信動作はスイッチやタイマーなどのイベントを契機に発信する間欠的動作だからだ。スイッチを押すなどの操作した場合、または、約1秒周期でIO状態が送信されるが、これでは、子機の間欠受信に滅多にミートしないので、送信間隔を短くする必要がある。
 現行のApp_Tweiteであれば、オプションビットの設定で毎秒32回の連続送信が設定できる。ところが、何故かApp_Melodyにはオプションビットの機能が無い。しょうがないので、親機にApp_Tweliteを、子機には改造したApp_Melodyを書き込んで、親機のApplication IDを子機と揃えることで対応した。

TWE-Liteで子機間欠受信を有効にする方法

最初は無理かと思ったけど、だんだんわかってきた気がする。
「超簡単!TWE標準アプリ」を子機間欠モードで受信に対応させるには、若干のソース変更が必要。

無線回路アイドル時に受信回路を有効化する


 cbAppColdStart()で子機間欠モードの場合に
sToCoNet_AppContext.bRxOnIdle = FALSE;
としている部分を、
sToCoNet_AppContext.bRxOnIdle = TRUE;
に変える。

 SDKマニュアル中のbRxOnIdle の説明には「受信時は常に受信電流を消費します。」という恐ろしいことが書いてあるが、テスターで測った感じだと、間欠動作の場合はbRxOnIdle =TRUE にしてもスリープ時に17mAも電流を消費するようなことは無い。デジタルテスターの20mAレンジでは、スリープ時の電流消費は0mAとしか表示されず、連続動作に比べたら誤差の範囲。スリープ解除のタイミングだけ、連続動作並みに消費電流が増える。

受信イベントのコールバック関数で受信処理をスキップさせない

cbToCoNet_vRxEvent()に、子機間欠モードの受信処理を抑制するif文が存在する。これをコメントアウトする。
例えば、1秒間欠モードの受信を有効にするなら、 こんな感じ。
--- a/Master/Source/Master.c
+++ b/Master/Source/Master.c
@@ -989,7 +989,9 @@ void cbToCoNet_vRxEvent(tsRxDataApp *psRx) {
             psRx->u32SrcAddr, psRx->u32DstAddr);

     if (IS_APPCONF_ROLE_SILENT_MODE()
+#ifndef USE_RX_ON_SLP_1SEC
             || sAppData.u8Mode == E_IO_MODE_CHILD_SLP_1SEC
+#endif
             || sAppData.u8Mode == E_IO_MODE_CHILD_SLP_10SEC) {
         // SILENT, 1秒スリープ, 10秒スリープでは受信処理はしない。
         return;

 手元の改造ソースでは、vProcessEvCoreSlp()を変更して、状態遷移を数TICK遅らせてスリープまでの時間稼ぎをしているけど、これが必須か否かは未確認。まあ、受信したからには何か処理をするだろうから、必須でなくともイベント追加したりすると思う。

2014年9月8日月曜日

TWE-Liteの子機間欠モードでは受信できない?

駅前駐輪場で、自転車の置き場所をよく忘れる。
忘れても大丈夫なように、携帯のToDoメモに置き場所をメモるようにしているのだが、急いでいるとメモるのを忘れてしまう。先週も、メモを忘れた上に置き場所を憶えてなくて、5分くらい駐輪場をさまよった。

で、ふと思った。
これってもしかして、TWE-Lite使ったら、解決するんじゃね?

早速、家にあったTWE-Liteで試作を開始したのだが、どうもだめっぽい。
自転車に装着する予定の子機は、大半の時間は用無しなので、電池節約のため間欠モードでなくてはならない。さもないと、数日で電池がなくなってしまう。
 東京コスモス電機の説明では、
間欠1秒モードは休止状態(スリープモード)になり、1秒毎に送受信を行うモードです。休止状態では送受信は行わず内蔵タイマーだけを動作させ節電を行います。
休止中は親機からの信号を受けることができません。
 と書いてあって、休止が解除されたタイミングでは受信できそうに書いてある。ところが、超簡単!TWE標準アプリで子機を間欠1秒モードにしてみると、親機の操作にまったく反応しない。
 ソースを見てみると、間欠モードでは受信処理を抑止している事がわかった。受信処理のコールバック関数 cbToCoNet_vRxEvent() では、間欠モードでは素通りで戻るようになっている。
void cbToCoNet_vRxEvent(tsRxDataApp *psRx) {
    //uint8 *p = pRx->auData;

    DBGOUT(3, "Rx packet (cm:%02x, fr:%08x, to:%08x)"LB, psRx->u8Cmd,
            psRx->u32SrcAddr, psRx->u32DstAddr);

    if (IS_APPCONF_ROLE_SILENT_MODE()
            || sAppData.u8Mode == E_IO_MODE_CHILD_SLP_1SEC
            || sAppData.u8Mode == E_IO_MODE_CHILD_SLP_10SEC) {
        // SILENT, 1秒スリープ, 10秒スリープでは受信処理はしない。
        return;
    }
 試しに、間欠1秒モードでも受信処理へ進むようにif分の条件を変えてみたが、結果は変わらず。そもそも、このコールバックさえ呼ばれていなかった。道は険しそうだ。
とりあえず、TWE-Lite標準アプリの子機間欠モードは送信専用で、受信処理ができないらしい。

可能か否かはまだ不明だが、目標としているのは、こんなアプリ。
  • 音と光で知らせる自転車発見器にする予定なので、ベースにはApp_Melodyを使う。
  • 子機は間欠モード。数秒おきに動作する。
  • タイマーで起動したら、数msの間だけ受信動作する。
  • 親機の信号を受信したらメロディーを鳴らしてLEDを光らせる。
  • メロディーが鳴っている間はスリープしない。
  • 親機は連続動作。ただし、必要な時だけ電源を入れる。 

2014年8月12日火曜日

サーボモーターでNFCカードを上げ下げする

 STM32F0DISCOVERYでサーボモーターを制御して、割り箸に挟んだNFCカードを上げ下げするだけの装置を作ってみた。


 サーボを制御しているのは、Cortex-M0コアのSTM32F0DISCOVERY。デバッガが付いてて1000円。UARTをFT231XでUSBに変換して、PCから指令を出す。


 初めてのことだらけで、勉強になった。
  • STM32(というか、Cortex-M?)はタイマー1個でPWMが4ch賄えて便利。今回のサーボモーターのように、同一周期でパルス幅が違うだけのPWMが出し易い。
  • この規模でEEPROMがないのは盲点だった。調整値が保存できないのは痛い。
  • STM32Cubeはバグっぽいが、使えないほどではない。
  • 同一電源でサーボモーターが複数ある場合は、時間差を置いて順番に始動しないと、 サーボが不安定になって振動を繰り返す。
  • 3VのPWMでもサーボは制御できる。
  • 平滑回路のない粗末なACアダプターでは、サーボは安定して動かせない。
STM32を使った大人の自由研究は一旦終了。次のお題はTWE-Liteを使った工作。

2014年7月21日月曜日

STM32F3DISCOVERYでステッピングモーターとサーボモーターを動かす

ステッピングモーターに連結したレゴの歯車に、サーボモーターを無理やり付けてみた。コレで、刺身にタンポポを載せるような単調作業が楽になるかもしれない。

 最初はいい調子に動いたと思ったが、何度か動かしていると原点がずれていく。回転角が大きいときに、慣性に負けて脱調してしまうらしい。脱調しない速度に固定すると遅すぎるので、目標までの距離に応じて加減速させてみた。スピードと安定性のバランス が難しい。



秋月電子で買ったステッピングモーターを、LEGOで羽交い絞めにして固定している。負荷が軽いので、これで全く問題なし。サーボとLEGOは、輪ゴムで巻いただけ。

STM32F3DISCOVERYでステッピングモーターを動かす

STM32F3DISCOVERYでステッピングモーターを動かしてみた。
モータードライバはTIのDRV8830。I2Cインターフェースなので、MCUからの制御用配線は2本。ドライブ用ブレッドボードへの配線は、電源を入れても4本。

 モーターのステップ角は3.75°で、96step/rev。DRV8830は極性と同時に出力電圧を設定できるので、動作が滑らかになるのを期待して、極性を反転させる際に階段状に電圧を変化させてマイクロステップの真似事をしてみたが、スムーズになったようには見えない。




2014年7月15日火曜日

STM32CubeのUSBハンドラの中でosMessagePut()したら固まった

 Lチカできるようになったので、色気を出してOSのメッセージキューに手を出して見た。受信データの有無を知るために、グローバル変数のバッファデータ長をポーリングするのをやめて、USBの受信ハンドラの中でバッファ構造体をメッセージキュー経由で渡すことにした。んでもって、100%フリーズするバグの出来上がり。
 デバッガで追って見ると、優先度をチェックするconfigASSERT()でFAILして、無限ループの刑を受けているらしいことがわかった。ぐぐってみたら、ハンドラの中でFreeRTOSのシステムコールを呼ぶには、USBハンドラの優先度を下げないといけないらしい。
 ソースはココ→ マイコン徹底入門 割込み優先度の設定
STM32CubeMXのNVIC設定でUSBの優先度を下げて(priorityの数字を増やして)、一件落着。


STM32CubeMXをJava8(x64)で使うとコード生成でフリーズする

 STM32CubeMXのコード生成機能(Generate source code based on user settings)でソースコードを出力すると、100%の確立でフリーズするようになった。STM32CubeMXはJavaで動いているので、試しに64bit版のJava 8をアンインストールして32bit版を使うようにしたら、問題なく出力できるようになった。いつまで経っても信頼できないx64版Javaって悲しすぎ。

2014年7月13日日曜日

STM32F3DISCOVERY的なLチカ

 STM32F3DISCOVERYのVCP疎通確認用に作ったEchoBackが動いたので、F3DiscoveryらしいLチカを書いてみた。LD3~LD10が入力した文字コードの各ビットに対応する。

STM32CubeF3のUSB CDCミドルウェアがバグってる

STMicroelectronicsが用意したSTM32のUSB CDCミドルウェアが、少々バグってるらしい。
 PCからVCP(仮想COMポート)に送信した文字を、STM32F3DISCOVERYからエコーバックするだけのプログラムを書いたが、最初の1文字しかエコーバックされない。デバッガで調べると、2文字目以降でコールバック関数が呼ばれていないようだ。ぐぐってみたら、ズバリの現象を特定したスレがフォーラムに見つかった。
 USB middleware issue with CDC/VCP: only x packets receivable (HAL 1.1.0 and Host-Device_Lib 2.1.0)

 受信処理の中で、受信完了のコールバックを呼んでいないらしい。HeapSizeが小さすぎるという罠もあったらしいけど、これは試す前に書き換えた。

 VCPが通るようになったので、PCからコマンドを送る経路が確保する目処が立った。でも、リセットの度にUSB抜き差しして再接続は面倒。いずれFT232RLのUSB-UART変換に逃避してしまうかもしれない。

2014年7月8日火曜日

Keil 5.11aはST-LINK2の最新ファーム(V2.J21)に未対応

 STM32用のファームの雛形は、今年リリースされたSTM32CubeMXで用意することにした。クロックの選択やピンアサイン、タイマーの設定がGUIでできて、禁則もチェックしてくれる。
 開発環境は、コードサイズが32kBを越えないと踏んで、STM32CubeMXが対応しているKeil MDK-ARM Liteにした。が、ここに落とし穴があった。

 Keil  MDK-ARMと別にインストールしたST-LINK UtilityをSTM32F3DISCOVERYに初めて接続したとき、「ファームが古いからアップデートせい」と表示されたので言うとおりにしたのだが、これが罠。現在最新のKeil 5.11aは、ST-LINK2の最新ファームに対応していない事を後で知った。お陰で、ビルドしたファームウェアをダウンロードさせようと何度試しても、「USB communication error」で失敗する。これで一晩無駄にした。
 ぐぐって見つけた解決策は、 ファームウェアのダウングレードだった。
 "Keil 5.11 st-link usb communication error"
  http://www.keil.com/forum/58066/
 Keil 5.11aのインストール先にアップデータがあるので、これを使うとダウングレードが出来る。答えを見つけて3分で解決。

 今この時期だけに存在する旬なバグを踏んでしまった。天に見放されているのかもしれない。先が思いやられる。

初めてのSTM32F3DISCOVERY

マイコンでモーターを制御するために、STM32F3DISCOVERYその他一式を秋月電子で買ってみた。ファームウェアは、まだ1行も書いていない。


最終目標は、薄いカードをエアーポンプで吸引して動かす、卓上版リフティングマグネットもどき。ステッピングモーターで台座、サーボモーターでアームをを動かし、DCモーターで動く水槽用エアーポンプの吸引側を使ってカードを吸い付ける。
 ステッピングモーターのドライバとして選んだのは、DRV8830。I2Cで制御するので、配線数が少なくて済む。サーボモータはSTM32のPWMで直接制御。ポンプのDCモーターは、GPIOでモータードライバDRV8832に指令を出してON/OFFする。ドライバをDRV8830に統一しなかったのは、STM32の学習を兼ねるので、複数の方式を使いたかったから。

 STM32も、I2Cも、ステッピングモーターも、サーボモーターも、PWMも初めて使うものばかり。初物ばかりで、長い道のりになりそうだ。

2014年4月27日日曜日

Raspberry Piにshutdownスイッチ追加

 去年の暮れに、常時稼動させている家鯖をShuttle XS35からRaspberry Piに交替しました。Raspberry Piには電源スイッチがありません。通電すると即起動し、電源を切る前にはログインしてshutdownコマンドを実行します。電源OFFがちょっと面倒です。
 もっと手軽に電源を落とせるように、少々工作して、 GPIOとGNDの間に押しボタンスイッチを接続しました。プルアップしておいたGPIOのエッジ割り込みを監視し、GNDに落ちて5秒継続したらshutdownが走ります。参考になったのは、こちら↓。

 「Raspberry Pi にシャットダウンボタンをつける」
   http://d.hatena.ne.jp/penkoba/20130925/1380129824 

今は、このようなスクリプトでシャットダウンの指令を監視しています。
#!/usr/bin/env python2.7

import RPi.GPIO as GPIO
import time
import syslog
import os

# use GPIO 27 as shutdown button
WatchGpioNo = 27
LEDGpioNo = 4
SleepStepSec = 0.1

def KeepWatchForSeconds(seconds):
    GoFlag = True
    LEDState = False
    if seconds < 1:
        seconds = 1
    while seconds > 0:
        LEDState = not LEDState
        GPIO.output(LEDGpioNo, LEDState)
        time.sleep(SleepStepSec)
        seconds -= SleepStepSec
        if (GPIO.input(WatchGpioNo) == True):
            GoFlag = False
            break
    return GoFlag

def CallShutdown():
    syslog.syslog(syslog.LOG_NOTICE, "Going shutdown by GPIO.")
    os.system("/sbin/shutdown -h now 'Poweroff by GPIO'")

def SlowBlink(seconds):
    for i in range(int(seconds)):
        GPIO.output(LEDGpioNo, GPIO.LOW)
        time.sleep(0.5)
        GPIO.output(LEDGpioNo, GPIO.HIGH)
        time.sleep(0.5)
    GPIO.output(LEDGpioNo, GPIO.LOW)

if __name__ == '__main__':

    GPIO.setmode(GPIO.BCM)

    # GPIO 27 set up as input. It is pulled up to stop false signals
    GPIO.setup(WatchGpioNo, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    # GPIO 4 set up as output.
    GPIO.setup(LEDGpioNo, GPIO.OUT)

    try:
        SlowBlink(5)
        while True:
            GPIO.output(LEDGpioNo, GPIO.LOW)
            syslog.syslog(syslog.LOG_INFO, "Waiting for falling edge on port %d" % WatchGpioNo)
            GPIO.wait_for_edge(WatchGpioNo, GPIO.FALLING)
            syslog.syslog(syslog.LOG_INFO, "Falling edge detected.")
            if KeepWatchForSeconds(5):
                SlowBlink(5)
                CallShutdown()
                break
        GPIO.cleanup()           # clean up GPIO on normal exit
    except KeyboardInterrupt:
            GPIO.cleanup()       # clean up GPIO on CTRL+C exit


 単にスイッチを監視しているだけでは、スイッチを「ちょん」と押しただけでシャットダウンが走ります。自分の感覚としては、PC並みに数秒間押し続けてからシャットダウンしたほうが安心なので、ある程度の時間継続してスイッチが押されたことを見届けてからshutdownが走るようにしました。
 また、スイッチだけで表示が無いと、シャットダウンが受け付けられたか否かがしばらく待たないとわかりません。GPIO4にLEDを接続して、点滅動作で受付状況がわかるようにしました。

 試運転中の動画は、こちら。