tag:blogger.com,1999:blog-796533763938009252024-02-20T15:11:14.523+09:00Programminblogプログラミングの話題ログ
TWE-Lite, MCU, Android, Java, C#, .NET Framework, Python, AutoItThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.comBlogger181125tag:blogger.com,1999:blog-79653376393800925.post-62632345304846442322021-05-15T10:01:00.001+09:002021-05-15T10:02:02.563+09:00Power Log Readerをアップデート<p> PCの電源イベントから出退勤時刻を推定するアプリに機能を追加しました。</p><p></p><ul style="text-align: left;"><li>記録の無い日をカレンダー上で選択できないようにしました</li><li>日毎の要約を丸め無しで表示できるようにしました</li></ul>インストーラはGitHubからダウンロードできます。<p></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"><a href="https://github.com/true-nature/PowerLogReader/releases">https://github.com/true-nature/PowerLogReader/releases</a><br /></p></blockquote>ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com1tag:blogger.com,1999:blog-79653376393800925.post-10986690433749498682021-02-11T12:57:00.001+09:002021-02-11T12:58:55.740+09:00Power Log Readerの多言語化<p> PCの電源イベントから出退勤時刻を推定するアプリを、英語に加えて日本語でも表示できるようにしました。GitHubで公開しています。</p><p><a href="https://github.com/true-nature/PowerLogReader/releases/">https://github.com/true-nature/PowerLogReader/releases/</a><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoR2LJP7unX899xdgrJwGTKKafM6JYN5zXxlEnYzcoPfBhxu_aBo3vBlohUVMcgUZPvgWcbWn6VA8x2KgAcejccVixCuuqEU2-wYJQFnCfwi6BtELNZvwKdDLbYTJL7MZ5Hjw14jMhKvE/s966/Screenshot_MainWindow.ja.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="393" data-original-width="966" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoR2LJP7unX899xdgrJwGTKKafM6JYN5zXxlEnYzcoPfBhxu_aBo3vBlohUVMcgUZPvgWcbWn6VA8x2KgAcejccVixCuuqEU2-wYJQFnCfwi6BtELNZvwKdDLbYTJL7MZ5Hjw14jMhKvE/w433-h176/Screenshot_MainWindow.ja.png" width="433" /></a></div><br /><p></p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxMrKq2g8EJH7zjCF_QqtPamw21E_eAQKGNQANVNzwZeqQo3os-nlycjQ4aZhYzPaHGqVrZxu6seH74SXcQ8g' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><br /><p><br /></p>ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-87340665327064647572021-01-02T01:46:00.001+09:002021-02-11T12:58:03.911+09:00在宅勤務者の勤怠時刻をイベントログから推定するアプリ<p> タイムレコーダーの無い在宅勤務環境で、PCの起動/シャットダウン時刻から出退勤時刻を推定するためのアプリ <a href="https://github.com/true-nature/PowerLogReader">Power Log Reader</a> を作りました。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr_wK23XApmSGDMDxQOZi0S7c50SdmU1_cCdbyfS34fI30xCmnycymCnVqXOVm6xJrFbFbu4pcePhEfd47WlqKvvugbyo9ngd3Rshp-Qig60wsX7pl2-uh7-hUEO8XfarRt4LoiqY6Isk/s966/Screenshot+2021-01-02+002449.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="393" data-original-width="966" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr_wK23XApmSGDMDxQOZi0S7c50SdmU1_cCdbyfS34fI30xCmnycymCnVqXOVm6xJrFbFbu4pcePhEfd47WlqKvvugbyo9ngd3Rshp-Qig60wsX7pl2-uh7-hUEO8XfarRt4LoiqY6Isk/w476-h193/Screenshot+2021-01-02+002449.png" width="476" /></a></div><br /><p> Windowsのイベントログの中からカレンダーで選択した日の記録を抽出し、PCの開始/終了に関する記録をピックアップして時刻と一緒に表示します。ノートPCでの利用も考えて、スリープ/復帰に関するイベントも抽出するようにしました。</p><p> 勤怠時刻の単位時間、丸め規則(四捨五入/切り上げ/切り捨て)、PCの起動/シャットダウンに要する時間を設定すると、日毎のサマリーに反映されます。日付の切り替わり時刻を0時以降にずらす事もできます。</p><p> アプリ製作のきっかけは、自己申告制の勤怠管理で記入忘れを補完するためでした。PCの動作記録を簡単に調べられたら、記憶に頼らずとも正確な時刻が推定できると考えて作ってみました。</p><p>ビルド済みのインストーラをリリースページに置いておきました。動作には .NET Framework 4.8 が必要です。</p><p><a href="https://github.com/true-nature/PowerLogReader/releases/tag/release_1.0.0">https://github.com/true-nature/PowerLogReader/releases/</a></p>ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-31911759847373434472018-10-14T08:08:00.002+09:002018-10-14T08:42:21.479+09:00TWELITE SDK on Docker 最近、仕事で非公開用のgitサーバとしてGitLabをインストールしたところ、おまけで付いてきたGitLab CIと、gitlab-runnerで動かすDockerがとても便利で気に入りました。<br />
Linux上でビルドできるなら大抵のものに応用できるはずなので、試しにTWELITE SDKのLinux版を組み込んだDockerイメージを作って、GitLab CIと組み合わせてみました。<br />
サンプルのプロジェクトを、GitLabで公開しています。<br />
<a href="https://gitlab.com/twelite/app_twelite">https://gitlab.com/twelite/app_twelite</a><br />
<br />
Dockerイメージを作るための<a href="https://gitlab.com/twelite/app_twelite/blob/master/docker/Dockerfile.bionic">Dockerfile</a>は以下のようにしました。<br />
<blockquote class="tr_bq">
<div class="blob-content" data-blob-id="f6d61a785035d836b2035d53071c213bdf96dff8">
<pre class="code highlight"><code><span class="line" id="LC1" lang="Dockerfile">FROM ubuntu:18.04</span>
<span class="line" id="LC2" lang="plaintext"></span>
<span class="line" id="LC3" lang="plaintext">RUN sed -i s://archive.ubuntu.com://jp.archive.ubuntu.com:g /etc/apt/sources.list</span>
<span class="line" id="LC4" lang="plaintext">RUN apt-get update</span>
<span class="line" id="LC5" lang="plaintext">RUN apt-get install -y make curl libc6-i386</span>
<span class="line" id="LC6" lang="plaintext">RUN curl -o MWSDK_Linux-i386_201805.tgz https://mono-wireless.com/download/SDK/MWSDK_201805/MWSDK_Linux-i386_201805.tgz</span>
<span class="line" id="LC7" lang="plaintext">RUN tar zxf MWSDK_Linux-i386_201805.tgz</span>
<span class="line" id="LC8" lang="plaintext">RUN rm -r MWSDK_Linux-i386_201805.tgz MWSDK/Wks_TWELITE</span></code></pre>
</div>
</blockquote>
基本は、Ubuntu 18.04にTWELITE SDKをcurlでダウンロードして展開しているだけです。一点重要なのが、libc6-i386をインストールしておくことです。TWELITE SDKに入っているコンパイラの実行ファイルは32bit Linux用なので、これが無いと64bit Linuxのmakeからコンパイラを起動できず、<br />
<blockquote class="tr_bq">
<pre class="build-trace" id="build-trace"><code class="bash js-build-output">make: /builds/ChipLib/SW4063V1416/../../Tools/ba-elf-ba2-r36379/bin/ba-elf-gcc: Command not found</code></pre>
</blockquote>
のようなファイルがあるのに「コマンドが無い」という不可解なメッセージが出ます。<br />
上記のDockerfileをビルドしたDockerイメージを、Docker Hubに用意しておきました。<br />
<a href="https://hub.docker.com/r/truenature/mwsdk/tags/">https://hub.docker.com/r/truenature/mwsdk/tags/</a><br />
<br />
GitLab CIの設定ファイル <span style="font-family: "courier new" , "courier" , monospace;"><a href="https://gitlab.com/twelite/app_twelite/blob/master/.gitlab-ci.yml">.gitlab-ci.yml</a></span> は、以下のようにしました。<br />
<blockquote class="tr_bq">
<div class="blob-content" data-blob-id="e782380d0def1586cdde2bbb19bcd90c5d5e139d">
<pre class="code highlight"><code><span class="line" id="LC1" lang="yaml"><span class="na">image</span><span class="pi">:</span> <span class="no">true</span><span class="s">nature/mwsdk:18.04_201805</span></span>
<span class="line" id="LC2" lang="yaml"></span>
<span class="line" id="LC3" lang="yaml"><span class="na">stages</span><span class="pi">:</span></span>
<span class="line" id="LC4" lang="yaml"> <span class="pi">-</span> <span class="s">build</span></span>
<span class="line" id="LC5" lang="yaml"></span>
<span class="line" id="LC6" lang="yaml"><span class="na">before_script</span><span class="pi">:</span></span>
<span class="line" id="LC7" lang="yaml"> <span class="pi">-</span> <span class="s">pwd</span></span>
<span class="line" id="LC8" lang="yaml"> <span class="pi">-</span> <span class="s">ln -s /MWSDK/* ../../</span></span>
<span class="line" id="LC9" lang="yaml"></span>
<span class="line" id="LC10" lang="yaml"><span class="na">blue</span><span class="pi">:</span></span>
<span class="line" id="LC11" lang="yaml"> <span class="na">stage</span><span class="pi">:</span> <span class="s">build</span></span>
<span class="line" id="LC12" lang="yaml"> <span class="na">script</span><span class="pi">:</span></span>
<span class="line" id="LC13" lang="yaml"> <span class="pi">-</span> <span class="s">cd Master/Build</span></span>
<span class="line" id="LC14" lang="yaml"> <span class="pi">-</span> <span class="s">make TWELITE=BLUE clean all</span></span>
<span class="line" id="LC15" lang="yaml"> <span class="na">artifacts</span><span class="pi">:</span></span>
<span class="line" id="LC16" lang="yaml"> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">$CI_JOB_NAME-$CI_COMMIT_REF_NAME"</span></span>
<span class="line" id="LC17" lang="yaml"> <span class="na">expire_in</span><span class="pi">:</span> <span class="s">2 weeks</span></span>
<span class="line" id="LC18" lang="yaml"> <span class="na">paths</span><span class="pi">:</span></span>
<span class="line" id="LC19" lang="yaml"> <span class="pi">-</span> <span class="s">Master/Build/*.bin</span></span></code></pre>
</div>
</blockquote>
ビルドしておいたDockerイメージを <span style="font-family: "courier new" , "courier" , monospace;"><span class="na">image</span><span class="pi">:</span> </span>で指定しています。<br />
<a href="https://mono-wireless.com/jp/products/TWE-APPS/index.html">TWELITE APPS</a>として公開されているサンプルアプリは、2階層上のディレクトリにTWELITE SDKのツール群が配置されていることを前提に<span style="font-family: "courier new" , "courier" , monospace;">Makefile</span>が用意されていますので、<span style="font-family: "courier new" , "courier" , monospace;">before_script</span>で最初にシンボリックリンクを用意しています。<br />
サンプルアプリにはテストコードが含まれていないため、<span style="font-family: "courier new" , "courier" , monospace;">stage</span>は<span style="font-family: "courier new" , "courier" , monospace;">build</span>だけです。サンプルアプリのトップにある<span style="font-family: "courier new" , "courier" , monospace;">Makefile</span>は下位のmakeにビルドを丸投げして失敗を無視する仕様のため、<span style="font-family: "courier new" , "courier" , monospace;">Master/Build</span>まで下りてmakeを行います。<br />
ビルドしたファームウェアバイナリは、artifactsでダウンロードできます。<br />
<br />
GitLab CI/CDを有効にしておくと、pushやマージリクエストが処理される毎にpipelineが実行されます。<br />
<a href="https://gitlab.com/twelite/app_twelite/pipelines">https://gitlab.com/twelite/app_twelite/pipelines</a><br />
GitLabにホストされたプロジェクトでshared runnerだけを使っているので、とても時間がかかっているように見えますが、ローカルにGitLabをインストールして専用のgitlab-runnerを登録しておくと、見ている間に(数十秒で)完了します。<br />
<br />
プライベートなGitLabでローカルにビルドしたDockerイメージを使う場合は、<br />
<br />
<ul>
<li>ローカルに命名、タグ付けしたイメージを <span style="font-family: "courier new" , "courier" , monospace;">image: </span>で指定する</li>
<li>gitlab-runnerの <span style="font-family: "courier new" , "courier" , monospace;"><a href="https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work">pull_policy</a> </span>に'never'または'if-not-present'を指定してDocker Hubからのpullを予防する</li>
</ul>
のような設定が必要です。ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-62159675330219721722018-05-06T21:24:00.000+09:002018-05-06T21:24:00.865+09:00Raspyberry Pi 3Bに小型ディスプレイを装着 今まで、Raspyberry Pi 3BのディスプレイとしてPC用ディスプレイを使っていましたが、もっと手軽に使いたいので、安くてコンパクトな<a href="https://www.amazon.co.jp/gp/product/B075K56C12/">Raspberry Pi 3B用HDMIモニタ</a>をamazonで買いました。解像度は低いですが、私の用途では問題にはなりません。また、Windows 10 IoT用のドライバが無いのでタッチスクリーンが機能しませんが、USBマウスを使えば大丈夫です。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/t9xipXSsOC8/0.jpg" src="https://www.youtube.com/embed/t9xipXSsOC8?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-19260040640956627542018-04-21T22:37:00.000+09:002018-04-21T22:37:32.470+09:00Windows 10 IOT Core + TWELITE Raspberry Pi 3Bで動いているWindows 10 IOT Core用にアプリを書き始めました。UWPアプリは初めてなうえに、XAMLも初心者の域を出ないので、なかなか捗りません。<br />
TWELITEでドアの開閉を検出して、予め登録したMACアドレスにWake On LANパケットを送出するのがアプリの主な機能です。同様の仕組みはPython/Raspbianで動作しているのですが、誰でもメンテナンスできるように、UWPアプリとして作り直すことにしました。<br />
<ul>
<li>シリアルポートに流れるTWELTIEの出力を読むバックグラウンドアプリ</li>
<li>設定およびログ表示のためのフォアグラウンドアプリ</li>
</ul>
という基本構成は固まりました。バックグラウンドとフォアグラウンドの間の通信ができるまでに試行錯誤を繰り返し、BackgroundTaskとAppServiceでやりたいことができるようになるまでかなり時間がかかりましたが、ようやく見通しが立ってきました。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgblGI4Oq611ScjlYKfJM7k5u_yVzgNPd1D9WTXtvADiQ27L77rOIw-zKZmoSDMOliKYQfM0xrnuRyGccBpPu1UsbTO5UYw4Lr0xlsWqW8Fbo2AVgP3-WVHhqo6-I5X-snxXBbtq9LVKs8/s1600/Screenshot_2018-04-21_22-10-08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgblGI4Oq611ScjlYKfJM7k5u_yVzgNPd1D9WTXtvADiQ27L77rOIw-zKZmoSDMOliKYQfM0xrnuRyGccBpPu1UsbTO5UYw4Lr0xlsWqW8Fbo2AVgP3-WVHhqo6-I5X-snxXBbtq9LVKs8/s320/Screenshot_2018-04-21_22-10-08.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7w3pgQO-j64T_tScAY27T26GdXqR4fnyX0Fnrv6CU6R3LPxPr0PJKwObhwGsZWF9VZdQGQxw97iVPgo8i_bYoErSptbzMJBqacaOhsSZM0Lx-2FTv6ho6Lc493wOgyx-pc_cQFYzFf8/s1600/Screenshot_2018-04-21_22-26-48.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7w3pgQO-j64T_tScAY27T26GdXqR4fnyX0Fnrv6CU6R3LPxPr0PJKwObhwGsZWF9VZdQGQxw97iVPgo8i_bYoErSptbzMJBqacaOhsSZM0Lx-2FTv6ho6Lc493wOgyx-pc_cQFYzFf8/s320/Screenshot_2018-04-21_22-26-48.jpg" width="320" /></a></div>
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-44247609822943038652017-03-07T07:44:00.001+09:002017-03-07T20:41:32.008+09:00TWE-LITE 2525Aの連続稼働が終了 TWE-LITE 2525Aの連続稼働が、電池切れにより3月6日の朝で終了しました。<a href="http://programminblog.blogspot.jp/2016/12/twe-lite-2525a.html">11月17日の夜から開始</a>して、およそ3カ月半、108日動き続けました。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcVtQCKDgPM-Did_sYZ-ti-l_7XlbSbqVA21gqX_7-KbO62FjQEXDQ3k3ItE8JTEf6sCrT8jm9u-03yybOs7nzZ6yWvn6HXUlQCCC4tXq61alU9GhSBc4kiMBX7mTcFNDjsIKislOJQRk/s1600/TWE-LITE-2525A-VBATT.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcVtQCKDgPM-Did_sYZ-ti-l_7XlbSbqVA21gqX_7-KbO62FjQEXDQ3k3ItE8JTEf6sCrT8jm9u-03yybOs7nzZ6yWvn6HXUlQCCC4tXq61alU9GhSBc4kiMBX7mTcFNDjsIKislOJQRk/s320/TWE-LITE-2525A-VBATT.png" width="320" /></a></div>
<br />
電池切れ間際の電源電圧は約2Vでした。グラフを見ると、2.2Vあたりから電圧低下が早くなっているように見えます。2.1Vから約1週間で終了しました。<br />
<br />
記録された送信回数は25,000以上でした。年末年始にログが取れなかった期間があるので、実際には26,000回を超えていたのではないかと思います。一回のドア開閉で2回の送信が行われるので、一日当たりドア開閉回数はおよそ120回という事になります。<br />
<br />
加速度センサーの消費電流を仮に40μAとすると、一日当たり0.96mAhが消費されます。使用したコイン電池の容量は210mAhですので、加速度センサーとTWE-Liteでだいたい半分ずつ消費していたようです。この計算だと、ドア開閉が多ければ電池切れはさらに早くなりますし、殆どドアを開けなければ半年くらいは持つかもしれません。<br />
<br />
使用した電池は、<a href="https://www.amazon.co.jp/dp/B002BAL0AG">amazonで買った中国製電池</a>です。星一つのレビュー評価が多いですが、普通に使えました。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvXDa7akjn9ZSsbvEuGCNkeIPbBMIap1VIo_ge1Q3yjwhmBnnb9uE5mHu6bJK5iCQ_I0bnxU76MAnQZrhFl0R57LJxqjqwg1bfBoLOcS-qO6w0d-Hw8jETHITZVK7OsCyE2kmEbplYqTo/s1600/DSC_0462.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvXDa7akjn9ZSsbvEuGCNkeIPbBMIap1VIo_ge1Q3yjwhmBnnb9uE5mHu6bJK5iCQ_I0bnxU76MAnQZrhFl0R57LJxqjqwg1bfBoLOcS-qO6w0d-Hw8jETHITZVK7OsCyE2kmEbplYqTo/s320/DSC_0462.JPG" width="320" /></a></div>
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-51938432521091183392017-02-05T23:16:00.004+09:002017-02-05T23:16:56.340+09:00PWMとLPFで疑似DA変換 TWE-Liteの<a href="http://mono-wireless.com/jp/products/TWE-APPS/App_Audio/index.html">オーディオアプリ</a>では、PWM出力をLPFに通すことで、デューティー比の変化を電圧に変換しています。Analog Discovery 2を買ったので、この様子を視覚的に確認してみました。<br />
<br />
LPFを通す前のPWM出力と、LPFとスピーカーアンプを通った後の音声出力にプローブをつないで、同時に波形を見てみました。<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEFeoAcUIbfiw5hT2JWDePLrnkJ6D8mV5XcBvchVxdzeWeVnY1UqRgaUUGWvtEUL29G1QuYmVXLa5m1W6qEspnrKJ1G5j7soiVr_SwNKTOUfpz4iQ0CEZ5ZeOUeMBfUF1RDPb3YWwzF0M/s1600/App_Audio_schematic.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEFeoAcUIbfiw5hT2JWDePLrnkJ6D8mV5XcBvchVxdzeWeVnY1UqRgaUUGWvtEUL29G1QuYmVXLa5m1W6qEspnrKJ1G5j7soiVr_SwNKTOUfpz4iQ0CEZ5ZeOUeMBfUF1RDPb3YWwzF0M/s320/App_Audio_schematic.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">プローブの接続箇所</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
波形は、このようになりました。上がPWM波形、下がスピーカー出力の波形です。この時は、テストトーン(正弦波?)を再生していました。<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixnuSKOr30XktL_yOyRc8407P5TTG6P71FqcUSyoYvdsDWd3kd05gkRZuSmZoe_FhjKxyWEohzS-awjXvdcC6te6ri2Enex2q154MLfY8mePhX2aasDqVvjg9UHObwmBdJG9gmbQEvuok/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2017-02-05+16.23.51.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixnuSKOr30XktL_yOyRc8407P5TTG6P71FqcUSyoYvdsDWd3kd05gkRZuSmZoe_FhjKxyWEohzS-awjXvdcC6te6ri2Enex2q154MLfY8mePhX2aasDqVvjg9UHObwmBdJG9gmbQEvuok/s320/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2017-02-05+16.23.51.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">電圧の山では高デューティー比</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZQNasglb5VWITyOZ8nHHu-AYv-3fF6NAyw-DWgU7iBVRq522sbeoFBH4LFWdEHsjzX1_7ABlCP6PcEk3Gk504sRU0agp3yyKtOakDJPea7II-NGQkqtgCZ19G8pAAJdaM_cdy100AGys/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2017-02-05+16.25.05.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZQNasglb5VWITyOZ8nHHu-AYv-3fF6NAyw-DWgU7iBVRq522sbeoFBH4LFWdEHsjzX1_7ABlCP6PcEk3Gk504sRU0agp3yyKtOakDJPea7II-NGQkqtgCZ19G8pAAJdaM_cdy100AGys/s320/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2017-02-05+16.25.05.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">電圧の谷では低デューティー比</td></tr>
</tbody></table>
<br />
PWMのデューティー比が高い箇所(約60%)ではスピーカー出力の電圧が高く、デューティー比が低い箇所(約40%)では電圧が低くなっています。<br />
一見しただけではわかりにくいのですが、Quick Measureでカーソル位置の値を見ると、簡単に理解できます。<br />
<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-41447620048825389382017-01-22T00:01:00.000+09:002017-01-22T00:01:03.007+09:00TWE-Liteで出力した赤外線リモコン信号の波形 今までオシロスコープ無しで開発してきましたが、やっぱりあると便利なので、場所を取らないUSBオシロスコープ <a href="https://reference.digilentinc.com/reference/instrumentation/analog-discovery-2/start">Analog Discovery 2</a> を秋月電子で買いました。<br />
<br />
とりあえず、TWE-Liteで作った赤外線リモコン信号の送受信機が正しく動いている事を確認しました。下のスクリーンキャプチャで、水色が赤外線受光モジュールの出力、黄色がTWE-Liteの赤外線リモコン信号出力です。同じタイミングで信号が出ていることが確認できました。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfNtw_IOES-AN5Td_9Jvm4BezY7ZWMhkLrJsCXEpVEHQj_ysGQmyklTsgRI3LCWaeJbeIKnhdqgdbTaiffAV11QVI7lNVR58i4rm8CMZVHjyYk5T7lKKbTDf90T23eliJhJvNwkL7HSHk/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2017-01-21+23.45.46.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfNtw_IOES-AN5Td_9Jvm4BezY7ZWMhkLrJsCXEpVEHQj_ysGQmyklTsgRI3LCWaeJbeIKnhdqgdbTaiffAV11QVI7lNVR58i4rm8CMZVHjyYk5T7lKKbTDf90T23eliJhJvNwkL7HSHk/s320/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2017-01-21+23.45.46.png" width="320" /></a></div>
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-58081583203385084422017-01-20T20:12:00.001+09:002017-01-20T20:12:25.618+09:00TWE-LITE 2525Aの連続稼働が2カ月を超えました <a href="http://programminblog.blogspot.jp/2016/12/twe-lite-2525a.html">11月中旬から動かし始めた</a>TWE-LITE 2525Aは、予想を超えて、まだ動き続けています。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXWA-DvQMSiP5LrJTHCx_DOjv1h7_qxSBMmrF8qc2uelx2x52PQmeYEUOeACXqedJU9z61fNE7gZ88DUKwHizgtHX06Bc9e0UMyEYs52qDLCaOi5YIytiO9wp-U_Uwbw9oyfycMs1hRho/s1600/TWE-LITE-2525A-VBATT.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXWA-DvQMSiP5LrJTHCx_DOjv1h7_qxSBMmrF8qc2uelx2x52PQmeYEUOeACXqedJU9z61fNE7gZ88DUKwHizgtHX06Bc9e0UMyEYs52qDLCaOi5YIytiO9wp-U_Uwbw9oyfycMs1hRho/s320/TWE-LITE-2525A-VBATT.png" width="320" /></a></div>
<br />
現在の電源電圧は、2.4V前後です。もう少し、頑張れそうです。ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-67246561083678331372017-01-14T18:03:00.000+09:002017-01-14T21:40:44.828+09:00TWE-LiteのInfra-Red Transmitter TWE-Liteには赤外線リモコン信号を送信するための機能が用意されているのですが、使用例を見たことが無いので、考え方をメモっておきます。<br />
<div>
<br /></div>
<div>
副搬送波の周期とデューティー比、データビットを構成する微小ビットの長さ等、タイマーの設定に関係するパラメータは、bAHI_InfraredEnable()で設定します。<br />
<div>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">bool_t bAHI_InfraredEnable(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">uint8 u8Prescale,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">uint16 u16Hi,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">uint16 u16Lo,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">uint16 u16BitPeriodInCarrierPeriods,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">bool_t bInvertOutput,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">bool_t bInterruptEnable);</span></blockquote>
</div>
<div>
<ul>
<li><b>u8Prescale</b> 赤外線送信で使うTIMER2の分周比を指定します。Users Guideの例では2(=1/4)を指定していますが、16MHzの16ビットタイマーのまま分周しなくても無理なく使えますので、0で良いと思います。</li>
<li><b>u16Hi </b>副搬送波1周期のうちの非アクティブ時間をタイマーのクロック数で指定します。</li>
<li><b>u16Lo </b>副搬送波の周期をタイマーのクロック数で指定します。</li>
<li><b>u16BitPeriodInCarrierPeriods </b>データビットを構成する微小ビットの長さを、副搬送波の周期(CarrierPeriod)で割った個数で指定します。</li>
<li><b>bInvertOutput </b>出力のHi/Loを反転する場合にTRUEを指定します。</li>
<li><b>bInterruptEnable </b>送信完了割り込みを発生させる場合にTRUEを指定します。</li>
</ul>
</div>
<div>
bAHI_InfraredEnable()で設定できる構造は微小ビットまでで、データビットの1/0やリーダーコード等は全て、u16BitPeriodInCarrierPeriodsで指定した個数の副搬送波を単位とする微小ビットの1/0の集まりとして表現します。例えば、下の図に示したNEC方式における'0'データビットは、微小ビットでは'10'という2ビットのデータで表現します。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjysmdlchs_tRUULKVV6KPvMz-5iv25hS0qcP61B53bbd8vjv5oGBUVkhBCVkt0J02So2W5f1lr6Pf0vx9hoWrRUzi06b8ZyoIxsb5LTNMQ9wOx2jn-lagRVe70L_JfnXaeM9pjRbqywtw/s1600/Sub-Carrier-and-DataBit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjysmdlchs_tRUULKVV6KPvMz-5iv25hS0qcP61B53bbd8vjv5oGBUVkhBCVkt0J02So2W5f1lr6Pf0vx9hoWrRUzi06b8ZyoIxsb5LTNMQ9wOx2jn-lagRVe70L_JfnXaeM9pjRbqywtw/s320/Sub-Carrier-and-DataBit.png" width="320" /></a></div>
<div>
<br /></div>
<div>
赤外線コマンドの送信は、bAHI_InfraredStart()で行います。</div>
<div>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">bool_t bAHI_InfraredStart(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">uint32 *pu32BufferAddress,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">uint16 u16TransmissionLengthInBits);</span></blockquote>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<ul>
<li><b>pu32BufferAddress </b>微小ビットの連続で表現したフレーム構造をビッグエンディアンで指定します。</li>
<li><b>u16TransmissionLengthInBits</b> pu32BufferAddressに含まれる有効な微小ビット数を指定します。</li>
</ul>
pu32BufferAddress の先頭はリーダーコードで始まります。NEC方式では、0xffff0000(の上位24ビット)になります。リーダーコードの後は、データビットの0/1をそれぞれ2進数の'10'および'1000'としてエンコードして、ストップビットの'1'を追加し、最後にフレーム間を'0'で埋めます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqaAii5COS-D2wbeKVj_jhw1KQ0HsA3BnG4ofG_jql3sC3fOFxCn9eY7vq2G1lmErW_vFaz5EN1_yqC5AWT1HTHfcS4ybf0qSl8LnUV6fpsFTngsC1H-HhpTz34u5N6MCs3rNwtfeQ1i0/s1600/Frame_NEC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqaAii5COS-D2wbeKVj_jhw1KQ0HsA3BnG4ofG_jql3sC3fOFxCn9eY7vq2G1lmErW_vFaz5EN1_yqC5AWT1HTHfcS4ybf0qSl8LnUV6fpsFTngsC1H-HhpTz34u5N6MCs3rNwtfeQ1i0/s320/Frame_NEC.png" width="320" /></a></div>
<div>
上の例は、我が家の日立製テレビの電源コマンドで、フォーマットはNEC方式、カスタマーコードは0x50,0xaf, コマンドデータは0x17です(リトルエンディアン)。これを、bAHI_InfraredStart()用にエンコードすると、パラメータは、</div>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">pu32BufferAddress = {0xffff00aa, 0x8a28888a, 0x28888a2a, 0xaa288880, 0x00000000, 0x00000000}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">u16TransmissionLengthInBits = 192</span></blockquote>
となります。<br />
2進数表現にすると、ON/OFFの様子が視覚的にわかります。<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;"> 11111111111111110000000010101010</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 10001010001010001000100010001010</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 00101000100010001000101000101010</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 10101010001010001000100010000000</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 00000000000000000000000000000000</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 00000000000000000000000000000000</span></blockquote>
<br />
複数のフレームを送信する場合は、<br />
<ul>
<li>pu32BufferAddress に複数のフレームをエンコードして一気に送信する。</li>
<li>vAHI_InfraredRegisterCallback()で送信完了ハンドラを指定し、ハンドラの中で次のフレーム送信を行う。</li>
</ul>
のいずれかの方法になると思います。送信完了ハンドラを使用する場合は、オーバーヘッドを考えてu16TransmissionLengthInBitsを若干減らしたほうが良いかもしれません。<br />
<br />
<h4>
参考資料</h4>
<div>
<ul>
<li><a href="http://www.nxp.com/documents/user_manual/JN-UG-3087.pdf">JN516x Integrated Peripherals API User Guide</a></li>
<li><a href="http://elm-chan.org/docs/ir_format.html">「赤外線リモコンの通信フォーマット」</a></li>
</ul>
</div>
</div>
ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-42503494006274098542017-01-14T01:45:00.001+09:002017-01-14T16:26:42.971+09:00TWE-Liteで赤外線リモコン信号を送信 赤外線リモコン信号の受信だけでなく、送信もできるようになりました。<br />
<br />
送信用のパーツを追加した回路図は、こちらです。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY0aCnebtMAXxKzpdgZR0JcF_a3DUji0QpiJKCZnzRsJhNfETpmYUeEPOCnu2dgMPT-trZxR8DCJi2QBMXz080v9hYsI7455r14_smgvM71_Nptpu4lSm05zYvqTMziwHscRkT_Z7gDBA/s1600/InfraRed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY0aCnebtMAXxKzpdgZR0JcF_a3DUji0QpiJKCZnzRsJhNfETpmYUeEPOCnu2dgMPT-trZxR8DCJi2QBMXz080v9hYsI7455r14_smgvM71_Nptpu4lSm05zYvqTMziwHscRkT_Z7gDBA/s320/InfraRed.png" width="320" /></a></div>
TWE-LiteのGPIOでは赤外線LEDを十分な明るさで点灯させることができないので、余っていたトランジスタを使いました。LEDの電流制限抵抗は、もっと小さくしたほうが良さそうです(50mA位は流したい)。<br />
<br />
赤外線リモコン信号を駆動するTIMER2は、標準アプリでは代替割り当てによってPWM2(or DO0)に割り当てられていますが、NPNトランジスタのベースと一緒に<a href="http://mono-wireless.com/jp/tech/Hardware_guide/Lite_pins_special.html">DO0をプルダウンしてしまうとプログラムモードに入れなくなる</a>ので、代替割り当てではなくデフォルトのピン割り当てのDO12(標準アプリではDI1)をTIMER2の出力として使っています。<br />
p-ch FETやPNPトランジスタならば、標準アプリと同様の代替割り当てで問題ありません。その場合は、TIMER2の出力極性を反転する必要があります。<br />
<br />
赤外線リモコン信号を送信する手順は、おおまかに以下のようになります。<br />
<ol>
<li>vAHI_TimerDisable(E_AHI_TIMER_2) でTIMER2を止めておく。</li>
<li>vAHI_InfraredRegisterCallback(cbToCoNet_vHwEvent) で送信完了ハンドラを指定する。</li>
<li>bAHI_InfraredEnable(0, 281, 421, 21, FALSE, TRUE) で副搬送波とエンコード単位波数を指定する。</li>
<li>送信したい赤外線コマンドのパターンをuint32のバッファにビッグエンディアンで設定する。</li>
<li>bAHI_InfraredStart(pu32BufferAddress,u16TransmissionLengthInBits) で赤外線コマンドを送信する。</li>
<li>送信完了割り込みが発生したら、次のフレームを送信するために4.または3.の手順に戻る。</li>
</ol>
上記のbAHI_InfraredEnable()で指定しているパラメータは、NEC方式または家電協方式の場合です。SONY方式では、副搬送波が40kHzになるように指定します。<br />
<br />
赤外線コマンドの1ビットは、bAHI_InfraredEnable()で指定したエンコード単位幅(u16BitPeriodInCarrierPeriods)を複数使って表現します。リーダーコードやフレーム間の無信号部分も同様にしてエンコードに含めるので、1個のコマンドに必要なバッファ長は75-235ビット位になります(長さはフォーマットに依存)。<br />
<br />
送信部分を実装したソースコードも、<a href="https://github.com/true-nature/App_InfraRed">github</a>で公開しています。<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-41947798794006441482017-01-11T23:11:00.004+09:002017-01-12T10:12:13.915+09:00TWE-Liteで赤外線リモコン信号をデコード 子供部屋の照明消し忘れが多いので、別室の照明を操作するリモコンをTWE-Liteで作ろうと思い立ちました。<br />
<br />
先ずは、リモコンから出ている赤外線信号を知る必要があります。オシロスコープがあれば波形を見て解読することができますが、残念ながら持っていませんので、TWE-Liteで赤外線信号を受信してデコードするプログラムを作りました。<br />
<h4>
回路図</h4>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1X8BAb86zRxBJC0LQMoTS2rQfDs2saMWl5RDI2BGVqXka69tXOcmjCgRn5UN1tFV03HHqbUTsm1nLXr0PCrOmn3jYj8maaMT9_24cej4RCkfcNJ1aPrrR7rUaeHL8pTLAPQ2q1FrZMEk/s1600/IrReceiver.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1X8BAb86zRxBJC0LQMoTS2rQfDs2saMWl5RDI2BGVqXka69tXOcmjCgRn5UN1tFV03HHqbUTsm1nLXr0PCrOmn3jYj8maaMT9_24cej4RCkfcNJ1aPrrR7rUaeHL8pTLAPQ2q1FrZMEk/s320/IrReceiver.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">赤外線リモコンデコーダ回路図</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<h4>
計測方法</h4>
赤外線リモコンの信号については、検索すれば山ほど出てくるので説明は省略します。デコードの方式はいろいろありますが、リーダーパルスの幅と、ビットパルスの立下り間隔で見ることにしました。<br />
赤外線受光モジュールからの出力をDI2とDI3に同時に接続し、立ち上がりと立下りの各々で発生する割り込みでエッジを検出します。割り込みハンドラの中で、プリスケーラを調整したTIMER2のカウンタ値を読んで記録します。<br />
<br />
<h4>
デコード方法</h4>
最初のパルスはリーダーコードなので、幅の違いからフォーマット(NEC/家電協/SONY)を判定します。フレームの間には長めの無信号期間があるので、信号が途絶えたらフレームをデコードします。リーダーコードに続いて、0/1をエンコードしたビットのパルスが続くので、短間隔を0、長間隔を1として判定し、フレーム全体をデコードします。<br />
<br />
<h4>
ファームウェア</h4>
赤外線リモコンデコーダーのファームウェアは、サンプルアプリのSamp_ContTxをベースにして作りました。<a href="https://github.com/true-nature/App_InfraRed">ソースコードはgithub</a>に置いてあります。TWE-Liteで動いていますが、親機も子機も無く単体で動作し、電波の送受信は行いません。<br />
<br />
リモコン信号を受光モジュールに送信して暫く待つと、デコード結果をUARTに表示して、受信待ちに戻るという動作を繰り返します。出力は下記のようになります。<br />
<blockquote class="tr_bq">
<span style="background-color: #f3f3f3;"><span style="font-size: x-small;"> <span style="font-family: "courier new" , "courier" , monospace;">1 2 3 4<br />cnt=4<br />type:SONY , bits:20, 88 b4 f0<br />type:SONY , bits:20, 88 b4 f0<br />type:SONY , bits:20, 88 b4 f0<br />type:SONY , bits:20, 88 b4 f0<br /> 1 2 3<br />cnt=3<br />type:AEHA , bits:40, 34 4a 90 14 84<br />type:AEHA , bits:40, 34 4a 90 14 84<br />type:AEHA , bits:40, 34 4a 90 14 84<br /> 1 2 3 4 5<br />cnt=5<br />type:NEC , bits:32, 6a 95 8e 71<br />type:NEC(R), bits:0,<br />type:NEC(R), bits:0,<br />type:NEC(R), bits:0,<br />type:NEC(R), bits:0,</span></span></span></blockquote>
<div>
<br /></div>
デコーダができたので、引き続き、赤外線信号の送信部分を作ろうと思います。TWE-LiteのMCU(JN5164)には赤外線リモコン信号を送信する機能があるので、タイマーやPWMの面倒な操作しなくても、パルスの周期とパターンを与えるだけで出力できるようです。<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh52Y6CeO1S9OeKcyxWq8CuG1eERUSi-IcsOGP8_tZsuL5ZYOM1AgrWMCpMOU0Ar1llBa17Y2iBTOskuUBCMGTpqbWkrOpvHvhUvDNsOwQrNqVOYd25TPBZAQ4VDsonVzGEu0gn2aLVJdU/s1600/DSC_0418.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh52Y6CeO1S9OeKcyxWq8CuG1eERUSi-IcsOGP8_tZsuL5ZYOM1AgrWMCpMOU0Ar1llBa17Y2iBTOskuUBCMGTpqbWkrOpvHvhUvDNsOwQrNqVOYd25TPBZAQ4VDsonVzGEu0gn2aLVJdU/s320/DSC_0418.JPG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">ブレッドボードでデバッグ中の赤外線リモコン受信機</td></tr>
</tbody></table>
<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-24456659092048430952016-12-19T21:18:00.003+09:002016-12-19T21:19:59.992+09:00TWE-LITE 2525Aの電池寿命を実測中 先月から、自宅リビングのドアにTWE-LITE 2525Aを貼り付けて、ドア開閉のパケットを記録しています。季節変化のせいか、平坦だった電源電圧が12月に入ってから急に低くなりました。一カ月余り経過した時点で、電源電圧は2.6Vを切っています。この様子だと、2カ月は持たないかなという感じです。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy15EdduuH8dWKdK-g8bzJbylPLZGXTz1SRuCBwC1vuBzkE_IfJToriQ1oZusYNPKn0j0gMfX5evYUdIdmnzB5uXSA8xh17zjzIHqrAZXhMQ6mXrOkm26Rm5wLZgh-VM69ZztGGrCgUwc/s1600/TWE-LITE_2525A_VBATT.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy15EdduuH8dWKdK-g8bzJbylPLZGXTz1SRuCBwC1vuBzkE_IfJToriQ1oZusYNPKn0j0gMfX5evYUdIdmnzB5uXSA8xh17zjzIHqrAZXhMQ6mXrOkm26Rm5wLZgh-VM69ZztGGrCgUwc/s320/TWE-LITE_2525A_VBATT.png" width="320" /></a></div>
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-40713395428801878392016-06-17T22:28:00.002+09:002016-06-17T22:28:27.479+09:00闇の中で怪しく光るTWE-Lite 我が家の戸締りチェッカーは、親機がRaspberry Piのある2階であるのに対し、子機は主に1階に設置してあります。子機の全てを親機だけでカバーできないので、親機の真下に当たる1階の部屋に、中継器を置いてあります。使わなくなったPHSの充電器を再利用し、三端子レギュレータで3.3Vの電源を供給しています。<br />
中継器としては電源つなぐだけでも事は足りるのですが、それだけでは動いている実感が無いので、PWMにLEDをつないで明滅させるようにしています。<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/blmpvJ23c9s/0.jpg" src="https://www.youtube.com/embed/blmpvJ23c9s?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
この中継器のソースも、<a href="https://github.com/true-nature/App_DoorChecker/commits/master/Router/Source/Router.c">github</a>で公開しています。<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-80130549886701423702016-06-08T08:12:00.002+09:002016-06-08T08:12:17.183+09:00トランシーバーの電池もち見積もり TWE-Liteで作ったトランシーバーの電池もちは、およそ3か月以上と見込んでいます。算出の基にした数値は、以下の通りです。<br />
<blockquote class="tr_bq">
<table style="border-collapse: collapse; height: 171px; width: 261px;">
<colgroup><col width="205"></col>
<col width="56"></col>
</colgroup><tbody>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">TWE-Lite Warm Sleep(uA)</td><td 00000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="2">2</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">TWE-Lite 待機起床時(mA)</td><td 0000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="17">17</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">起床間隔(sec)</td><td 00000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="1">1</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">起床時間(ms)</td><td 0000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="32">32</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">TWE-Lite 受信時(mA)</td><td 0000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="80">80</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">TWE-Lite 送信時(mA)</td><td 0000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="20">20</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">1通話あたり送信秒数</td><td 0000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="15">15</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">1通話あたり受信秒数</td><td 0000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="15">15</td>
</tr>
<tr height="19">
<td class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 153.75pt;" width="205" x:str="">通話回数/日</td><td 00000000000000="" class="et1" height="19" style="font-size: 12pt; height: 14.25pt; vertical-align: middle; width: 42pt;" width="56" x:num="5">5</td>
</tr>
</tbody></table>
</blockquote>
単3エネループの容量を2000mAhとすると、130日で電池が空になります。<br />
<br />
電池の消費割合を時間帯別に集計すると、下のグラフのようになります。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZvIF2WDSNqxvjCxkiSt8A5Tf1xJ4uvT-d6RHKzJb3QBEgYtbUWZym6nKFCGa4Y0DP43x-l6RNMt78rACujz-2prL9SuqDQD9zPff1HryWm_M7KcBBi0Fgua-2oTL3eq72sjMw9ZPTSmk/s1600/Transceiver_power_consumption.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZvIF2WDSNqxvjCxkiSt8A5Tf1xJ4uvT-d6RHKzJb3QBEgYtbUWZym6nKFCGa4Y0DP43x-l6RNMt78rACujz-2prL9SuqDQD9zPff1HryWm_M7KcBBi0Fgua-2oTL3eq72sjMw9ZPTSmk/s320/Transceiver_power_consumption.png" width="320" /></a></div>
<br />
スリープ中の消費は1%をはるかに下回り、1秒毎に32msの受信待ちを行う待機中起床時の消費が大半を占めています。<br />
起床間隔と起床時間の長さが電池もちを決定づける主なパラメータです。これらは、電池もちと応答性という相反する要求に直結しています。<br />
受信時はアンプでスピーカーを鳴らすため、消費電流が数十mA~100mA前後と非常に大きくなります。この部分の割合は、使用状況によって大きく変動します。<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-5256667067825421632016-06-06T22:43:00.000+09:002016-06-06T22:48:59.314+09:00トランシーバーの回路を再検討中トランシーバーの回路を見直しています。<br />
<div>
イヤホンでなくスピーカーからの出力を可能にしながら、マイクをコンパクトなMEMSマイクにしてオペアンプを省略し、電解コンデンサーを減らしたら、このようになりました。</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW_FgG0SFQjsUyyY0oHWZ29TjrUfpzx7xzlrRgBt7enb4Y28VyaQRxhv2wPn4ifnMXUmAiTo0SOL4RfInT20YrbNAPBkv897liJM8uiKpN8DpvKQJtqBH_jUP1hpjwdZiJqQV1cx9i3Ko/s1600/TransceiverSch.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="MEMSマイクとオーディオアンプを使ってオペアンプを省略した回路図" border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW_FgG0SFQjsUyyY0oHWZ29TjrUfpzx7xzlrRgBt7enb4Y28VyaQRxhv2wPn4ifnMXUmAiTo0SOL4RfInT20YrbNAPBkv897liJM8uiKpN8DpvKQJtqBH_jUP1hpjwdZiJqQV1cx9i3Ko/s320/TransceiverSch.png" title="周辺回路を見直したトランシーバー" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">トランシーバーの回路図</td></tr>
</tbody></table>
<div>
<br />
ブレッドボード上で組んでみた感じでは、出力は全く問題なし。オペアンプのLPFより低ノイズで聞き取りやすいです。</div>
<div>
マイクのゲインが、コンデンサーマイク+オペアンプに比べると、やや物足りない印象です。<br />
<br /></div>
ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-2594765646956337822016-06-05T01:04:00.002+09:002016-06-06T22:44:37.356+09:00TWE-Liteを使った電池ながもちトランシーバー完成 TWE-Liteを使ったトランシーバーの初号機セットが完成しました。<br />
今回のプラスチックケースは、タカチのLC115H-M2を使いました。<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifavmlGDb5CRKDBhNqnNIr6jVGRpTlfZflRj5ZaJyAsP3R-kFZPD4D0sOooV194Fqjadn3F8DxbVquxMCS2Q1j4fXKgsoVJg3_6m8ogU8JhZtXePKEYhZMTBByt9JVeK-_7mwpn-CoANU/s1600/DSC_0306.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifavmlGDb5CRKDBhNqnNIr6jVGRpTlfZflRj5ZaJyAsP3R-kFZPD4D0sOooV194Fqjadn3F8DxbVquxMCS2Q1j4fXKgsoVJg3_6m8ogU8JhZtXePKEYhZMTBByt9JVeK-_7mwpn-CoANU/s320/DSC_0306.JPG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">トランシーバーのセット</td></tr>
</tbody></table>
中はスッカスカです。<br />
適当なケースさえあれば、もっとコンパクトにできそうです。<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEXq1dl3f11Qcwz01TCyq-oeG-Q6Em_UO2xJnhGui4nzx3CgxGjGpxuiROAwIo67nOSPwqMWJ75ma0ehosii1iXHNX2MJ216gWbEfK6Y4r-ePH6LuKB_FyaKcNelXjOUoqboFdiHpPPUc/s1600/DSC_0304.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEXq1dl3f11Qcwz01TCyq-oeG-Q6Em_UO2xJnhGui4nzx3CgxGjGpxuiROAwIo67nOSPwqMWJ75ma0ehosii1iXHNX2MJ216gWbEfK6Y4r-ePH6LuKB_FyaKcNelXjOUoqboFdiHpPPUc/s320/DSC_0304.JPG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">裏ぶたを開けたところ</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ9mZCGMZjtcgT6YfiKfZ9jPA1Hx3MZZDPTWy_l0oLeMTQ26h0nwzvdfeHOoyXlzJyI_X3Jq1dqc8Ol9XVK-ypUZgGCKfYmDEZbQm06ViHGy4kQEueeuXO9jw4Kp2cxd_IBenSe4_urUs/s1600/DSC_0305.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ9mZCGMZjtcgT6YfiKfZ9jPA1Hx3MZZDPTWy_l0oLeMTQ26h0nwzvdfeHOoyXlzJyI_X3Jq1dqc8Ol9XVK-ypUZgGCKfYmDEZbQm06ViHGy4kQEueeuXO9jw4Kp2cxd_IBenSe4_urUs/s320/DSC_0305.JPG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">TWE-Liteは前面に実装しています</td></tr>
</tbody></table>
<br />
アプリケーションは、サンプルアプリのApp_Audioを間欠受信に改造したものを書き込んであります。設定が楽になるように、オートペアリングも実装しました。<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-47128890716040024972016-06-02T08:15:00.003+09:002016-06-02T08:15:59.950+09:00自転車ビーコン電池交換 今年もMaker Faire Tokyo 2016に出店応募しましたが落選しました(;_;)。<br />
<br />
2月中旬に入れた電池が一昨日から残量警告状態になったので、今朝交換しました。100円ショップのアルカリ乾電池で3か月半持ちました。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwkx6qsdfnWtMQGnfqEG7oi9ipytAqxuFXcI_MT8isCxrl4SIixq4YuO8Qchf_fMEMiPIJkHjbp4KDvZNSD7usoSw7C2oPHW-k3IXEW6R1pfviZwkv8Z1lXSX0NxKYFg4NK-djGa1Xc2o/s1600/DSC_0303.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwkx6qsdfnWtMQGnfqEG7oi9ipytAqxuFXcI_MT8isCxrl4SIixq4YuO8Qchf_fMEMiPIJkHjbp4KDvZNSD7usoSw7C2oPHW-k3IXEW6R1pfviZwkv8Z1lXSX0NxKYFg4NK-djGa1Xc2o/s320/DSC_0303.JPG" width="320" /></a></div>
応答性向上のため、スリープ間隔を2秒に短縮して使用しています。3か月以上持ったので、この設定をデフォルトにしようと思います。今使っている送受信機ペアは好調で、呼んでも応答がない空振り状態になった記憶がありません。百発百中で応答があります。<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com1tag:blogger.com,1999:blog-79653376393800925.post-61360239784272898522016-05-26T23:51:00.002+09:002016-05-26T23:51:37.759+09:00トランシーバー組み立て中通販に注文した部品がそろってきたので、1,2号機の組み立てを開始しました。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg70mlnHE_t6KtcyjjSS_sU7h3M46mPoUiM6xhAmQ_5ynppouZjoL1J8Yv-IvId-eTicCEczQhm7br_7KnrYxPRdHHMipVwHrvkEBVgujuq-7E0T-PClr2c3IZ5hxjbUEsKTsoKiV4vvTM/s1600/DSC_0300.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg70mlnHE_t6KtcyjjSS_sU7h3M46mPoUiM6xhAmQ_5ynppouZjoL1J8Yv-IvId-eTicCEczQhm7br_7KnrYxPRdHHMipVwHrvkEBVgujuq-7E0T-PClr2c3IZ5hxjbUEsKTsoKiV4vvTM/s320/DSC_0300.JPG" width="320" /></a></div>
コネクタ部品がないので完成には至っていませんが、ファームウェアを書いて電源とスピーカーを接続したら、ちゃんと音が鳴りました。強いエコーがかかっていて、カラオケのスピーカーで話しているような音が出ます。<br />
ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-75112539124897017552016-05-08T21:53:00.000+09:002016-05-08T21:53:39.102+09:00トランシーバーの基板を発注 トランシーバーの基板をElecrowに発注しました。<br />
<br />
こちらは、表面の3Dイメージ。大きな黒丸はスピーカー。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmO3V1j8XDRjo_Pv4u-BACJcM11WpkGYGcP6YK5P64U1Y-5VsfTyB3p_J4Wbhv643u88R8S9xsUPBjUz1Cxr1LlgzZFmHTWe9nQyTPlcRxm3TNWyT_aWCBrI-CcPUbCNN9Tz-qXRqBbDg/s1600/TransceiverFront.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmO3V1j8XDRjo_Pv4u-BACJcM11WpkGYGcP6YK5P64U1Y-5VsfTyB3p_J4Wbhv643u88R8S9xsUPBjUz1Cxr1LlgzZFmHTWe9nQyTPlcRxm3TNWyT_aWCBrI-CcPUbCNN9Tz-qXRqBbDg/s320/TransceiverFront.png" width="320" /></a></div>
<br />
こちらは、裏面の3Dイメージ。ケースはタカチのLC115H-M2です。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNfTPMzmLNST5nrTn3FuM1bZ0_dnSM3pUWEz4Hlr4FA8WUiyTS1oktUiCZFcfLxHot8eP0AjOrqYyXmhDlQVHpBH_YPFuzbwc0wkAQltOohi2AnpF6x3_ZuCo-sFUViRrCCe127urZDKs/s1600/TransceiverBack.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNfTPMzmLNST5nrTn3FuM1bZ0_dnSM3pUWEz4Hlr4FA8WUiyTS1oktUiCZFcfLxHot8eP0AjOrqYyXmhDlQVHpBH_YPFuzbwc0wkAQltOohi2AnpF6x3_ZuCo-sFUViRrCCe127urZDKs/s320/TransceiverBack.png" width="320" /></a></div>
基板が届くまでに、部品を用意しなくては。ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-70607826139281173762016-05-08T09:53:00.001+09:002016-05-08T09:54:44.928+09:00TWE-Liteのトランシーバを間欠受信に改造 TWE-LiteのSDKに含まれている<a href="http://mono-wireless.com/jp/products/TWE-ZERO/App_Audio/index.html">オーディオアプリ</a>はスリープしない連続動作ですが、これから作ろうとしているトランシーバはインターホン的な利用を想定しているので、少なくとも1-2か月は電池交換せずに使いたいと思っています。<br />
間欠受信のコツは自転車発見機の制作で理解していたいので、基本のモードが間欠受信となるように改造してみました。<br />
<br />
<ul>
<li>1秒に一度、32msの受信待ちを行う</li>
<li>受信待ちの間にパケットを受信しなかった場合はスリープする</li>
<li>パケットを受信した場合はスリープせずに受信した音声データを出力する</li>
<li>PTTボタンが押されたらスリープを解除して送信を行う</li>
<li>パケット受信またはPTTボタン押下の無い状態が5秒間継続したらスリープする</li>
</ul>
このような動作で、1日当たり数十秒の通話を行ったとして、単三エネループで2カ月程度はもつ見込みです。<br />
<br />ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-67897670073767947172016-05-01T13:52:00.002+09:002016-05-08T09:54:54.131+09:00TWE-Liteのトランシーバを試作<div>
TWE-Liteの<a href="http://mono-wireless.com/jp/products/TWE-ZERO/App_Audio/index.html">アナログ通信アプリ</a>を、ブレッドボード上で試作してみました。送信側にはマイクアンプを、受信側にはLPF+アンプ+スピーカーを外付けして、普通に聞き取れることが確認できました。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX74KhbjhGJrljLy2wZFkUbU7znlH8oHlxGkXcRe88QsqlrscXcNisGbV0zlUR8XqztnaboCs4XgYEIbs1t1LMIy9hTkIjpx7vj-rTi1bbRXblfH6b2h9aUzLcWafTbo6ogoZua75njeQ/s1600/DSC_0268.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX74KhbjhGJrljLy2wZFkUbU7znlH8oHlxGkXcRe88QsqlrscXcNisGbV0zlUR8XqztnaboCs4XgYEIbs1t1LMIy9hTkIjpx7vj-rTi1bbRXblfH6b2h9aUzLcWafTbo6ogoZua75njeQ/s320/DSC_0268.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
実際に使いたい用途があるので、これから基板を設計して、プラスチックケースに収納できるようにします。常時通電では電池が持たないので、待ち受け中は間欠受信するようにソフトを改造する予定です。</div>
<div>
<br /></div>
ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-49311722564779349572016-04-13T22:37:00.001+09:002016-05-01T13:53:01.380+09:00自転車発見器の無音モード 閑静な住宅地など、使用する場所によっては、自転車発見器のメロディーが邪魔になる場合が考えられます。そのような場合を想定し、受信機のオプションビットで音を消せるようにしてあります。しかし、この方法では、インタラクティブモードに入らないと切替ができません。<br />
ところが、もっと単純で利便性の高い方法がありました。その方法とは、休符のみのプリセットメロディーを用意しておくだけです。iPhoneでアラームを無音にする方法と同じです。<br />
早速、ソースコードを修正して、<a href="https://github.com/true-nature/App_BicycleFinder/commit/562bc7b510809719e47fee81d9ed9dfdd2fa825f#diff-a1f9859a36bbdbfc982cc1ff8d8b49ca">プリセットメロディーを追加</a>しました。<br />
<br />
因みに、自転車発見器のメロディー停止は、ごく短い休符1個だけのメロディーを再生するという方法で実現しています。これは、ベースにしたApp_Melodyの機能をそのまま引き継いだものです。ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0tag:blogger.com,1999:blog-79653376393800925.post-9096146604661244912016-02-15T22:27:00.002+09:002016-02-16T01:17:16.759+09:00TWE-Liteの自転車ビーコンにオートペアリングを実装 自転車ビーコンにオートペアリングを実装してみた。<br />
<br />
自転車ビーコンは、ペアリングした送信機と受信機の間でのみ通信が成立する。今までのペアリングは、設定モードに入って手でIDを入力して行っていた。入力を注意深く行うのは面倒だし、動作確認するとはいえ、この方法ではいずれ間違いが発生するのは避けられない。<br />
<br />
オートペアリングでは、コールドスタート時に特定のボタンが押されていたらペアリングモードに入り、ペアリング用のパケットで双方が希望するAppIdとランダムに選んだチャンネルを送り合う。暗黙のルールの下にAppIdを決定し、従属的にチャンネルも決定する。ペアリングのパラメータが決まったら、新しいチャンネルで通信を確認し、一定数のパケットが交換できたらEEPROMに設定を保存する。<br />
オートペアリングで使うAppIdとチャンネルは固定だが、送信出力を最小にする事と、ペアリング用パケットに双方のシリアル番号を含めることによって、確実に1対1でペアリングする。同時に3台以上がペアリングモードに入ったとしても、ペアリングが成功するのは必ず1対1の組み合わせに限られる(または、ペアリングが失敗する)。<br />
<br />
今のところ、ペアリングのパラメータはAppIdとチャンネルだけ。他のパラメータを含めることも可能だが、自転車ビーコンでは、これ以上は必要無い。<br />
<hr />
ペアリングモードへの入り口は、cbAppColdStart()から呼ばれるvInitHardware()の中。cold startの時にGPIOの状態からモードを設定する箇所に、DI1によるペアリングモード判定を入れている。<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>if (bPortRead(PORT_INPUT1)) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.bPairingMode = TRUE;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
<div>
DI1は押しボタンスイッチなので、M1,M2,M3のようなプルアップ解除は不要。cbAppColdStart()では、オートペアリング用に状態マシンとAppContextを設定。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>// 状態遷移マシンの登録<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (sAppData.bPairingMode) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_Event_Register_State_Machine(vProcessEvCorePairing);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.prPrsEv = (void*) vProcessEvCorePairing;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.bRxOnIdle = TRUE;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.u8TxPower = 0;<span class="Apple-tab-span" style="white-space: pre;"> </span>// 最小出力<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.u32AppId = APP_ID;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u8AppIdentifier = u8CCITT8(<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>(uint8*) &sToCoNet_AppContext.u32AppId, 4);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.u8Channel = CHANNEL; // pairing用に固定<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.u32ChMask = CHMASK;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
</div>
<div>
状態マシンのスタートアップでペアリング用のパラメータを初期化。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;">static void vProcessEvCorePairing(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>switch (pEv->eState) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>case E_STATE_IDLE:<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (eEvent == E_EVENT_START_UP) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16CtRndCt = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32ReqAppId = ToCoNet_u32GetSerial(); // 要求APP ID<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u8ReqCh = ((ToCoNet_u16GetRand() & 0xF) + 11); // 要求channel<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32CandidateAppId = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32AnotherAppId = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u8CandidateCh = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16MatchCount = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16PeerMatched = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
</div>
<div>
相手をスキャンして、見つかったら合意形成フェーズへ移行。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>case E_STATE_APP_PAIR_SCAN:<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// ペアリング相手が現れたら提案確認フェーズ<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (0 < sAppData.u16MatchCount) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>vfPrintf(&sSerStream, "!INF PEER EXIST.@%dms"LB, u32TickCount_ms);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_Event_SetState(pEv, E_STATE_APP_PAIR_PROPOSE);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
</div>
<div>
合意形成フェーズで1秒待ち、この間に相手からの合意パケットが十分な量受信できていたら、確認フェーズへ移行。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>case E_STATE_APP_PAIR_PROPOSE:<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (1000 <= PRSEV_u32TickFrNewState(pEv)) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 1秒待ってから判断<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.bRxOnIdle = FALSE;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_vRfConfig();<span class="Apple-tab-span" style="white-space: pre;"> </span>// 受信を一旦停止<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (AUTO_PAIR_COUNT_MIN <= sAppData.u16MatchCount<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>&& AUTO_PAIR_COUNT_MIN <= sAppData.u16PeerMatched) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_Event_SetState(pEv, E_STATE_APP_PAIR_CONFIRM);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_Event_SetState(pEv, E_STATE_APP_PAIR_FAILED);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>break;</span></blockquote>
</div>
<div>
確認フェーズでは、最初にRF設定を変更。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>case E_STATE_APP_PAIR_CONFIRM:<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (eEvent == E_EVENT_NEW_STATE) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// カウンタを一旦クリア<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16MatchCount = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16PeerMatched = 0;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// u32AppIdはcbAppColdStart以外で変更不可なのでu8AppIdentifierだけを変更<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u8AppIdentifier = u8CCITT8(<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>(uint8*) &sAppData.u32CandidateAppId, 4);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.u8Channel = sAppData.u8CandidateCh;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.u32ChMask = (1UL << sAppData.u8CandidateCh);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 次のパケットのタイミングを仕込む<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16CtRndCt = (ToCoNet_u16GetRand() & 0x3);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sToCoNet_AppContext.bRxOnIdle = TRUE;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_vRfConfig();<span class="Apple-tab-span" style="white-space: pre;"> </span>// 新たなRF設定に切り替える<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
</div>
<div>
確認フェーズでも、十分な合意パケットが受信できたら、完了フェーズへ移行。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>if (1000 <= PRSEV_u32TickFrNewState(pEv)) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 1秒待ってから判断<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (AUTO_PAIR_COUNT_MIN <= sAppData.u16MatchCount<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>&& AUTO_PAIR_COUNT_MIN <= sAppData.u16PeerMatched) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_Event_SetState(pEv, E_STATE_APP_PAIR_COMPLETE);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ToCoNet_Event_SetState(pEv, E_STATE_APP_PAIR_FAILED);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>break;</span></blockquote>
</div>
<div>
完了フェーズでは、新しいAppIdとチャンネルに更新してEEPROMへ保存。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>case E_STATE_APP_PAIR_COMPLETE:<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// AppId,Chを書き換えて保存<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>{<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>tsFlash sFlash = sAppData.sFlash;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sFlash.sData.u32appid = sAppData.u32CandidateAppId;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sFlash.sData.u8ch = sAppData.u8CandidateCh;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sFlash.sData.u32chmask = (1UL << sAppData.u8CandidateCh);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sFlash.sData.u32appkey = APP_ID;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sFlash.sData.u32ver = VERSION_U32;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>bool_t bRet = bFlash_Write(&sFlash, FLASH_SECTOR_NUMBER - 1, 0);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>V_PRINT("!INF FlashWrite %s"LB, bRet ? "Success" : "Failed");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>vWait(100000);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
</div>
<div>
ペアリングモードでやり取りするパケットは、受信コールバックcbToCoNet_vRxEvent()の中でデコード関数に振り分け。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>case TOCONET_PACKET_CMD_APP_USER_PAIRING:<span class="Apple-tab-span" style="white-space: pre;"> </span>// auto pairing<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (PRSEV_eGetStateH(sAppData.u8Hnd_vProcessEvCore) == E_STATE_RUNNING) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>vReceivePairingData(psRx);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>break;</span></blockquote>
</div>
<div>
デコード関数の中では、AppIdの大小で優先度を決定。確定したAppIdが送られてきたら、受信数をカウントする。受信数は状態遷移の判断材料として使用する。</div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>// 要求AppId<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>uint32 u32ReqAppId = G_BE_DWORD();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 要求ch<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>uint8 u8ReqCh = G_OCTET();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>(void)u8ReqCh;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 候補AppId<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>uint32 u32AcceptAppId = G_BE_DWORD();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 対向AppId<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>uint32 u32AnotherAppId = G_BE_DWORD();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// 候補ch<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>uint8 u8AcceptCh = G_OCTET();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>(void)u8AcceptCh;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16PeerMatched = G_BE_WORD();<span class="Apple-tab-span" style="white-space: pre;"> </span>// 相手方pairingマッチカウンタ<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (sAppData.u32CandidateAppId == 0) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (u32ReqAppId < sAppData.u32ReqAppId) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32CandidateAppId = u32ReqAppId;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32AnotherAppId = sAppData.u32ReqAppId;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u8CandidateCh = u8ReqCh;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} else if (sAppData.u32ReqAppId < u32ReqAppId) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32CandidateAppId = sAppData.u32ReqAppId;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u32AnotherAppId = u32ReqAppId;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u8CandidateCh = sAppData.u8ReqCh;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// bad case<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} else if (sAppData.u32CandidateAppId == u32AcceptAppId<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>&& sAppData.u32AnotherAppId == u32AnotherAppId) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sAppData.u16MatchCount++;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// ignore u32AcceptAppId == 0 or bad case(maybe multiple peer).<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></blockquote>
</div>
<div>
その他、詳細は<a href="https://github.com/true-nature/App_BicycleFinder">githubのソースコード</a>を参照。</div>
<div>
<br /></div>
ThinTubehttp://www.blogger.com/profile/14089522703271986416noreply@blogger.com0