落穂ひろいの電子工作(続き)赤外線学習リモコンで遊ぶ
遂にパワーダウンスリープの不具合が解消された(5/8/2016)
機械式自動巻時計のゼンマイを巻く自動巻機(ややこしい)の不具合の話を前の記事に書いた。結局、原因解明ができず途中であきらめたのだが、記事の最後に「閃いた」というコメントを残しておいた。
「閃いた」のは以前、似たような状況でAVRのマイコンに、ある機能を組み込んだことを思い出したことである。それは電子ボリュームの赤外線リモコンを作ったとき、パワーダウン時のEEPROM書き込みの誤動作をさけるフューズビットの設定、BOD(Brown Out Detect)機能である。 BODとはVccが低電圧になったとき、CPUが誤動作しないよう内部でリセットする機能で、デフォルトでは設定されていない。ウェブ上でこんな記事を見つけたことも、BODが気になるきっかけになった。
この記事は、スリープから目覚めるときにはBODを設定しておいた方が良いという内容で、直接現在の不具合とは関係ない。ただ今度の不具合は、CPU内部の不可思議な動き(電源断のときの電圧降下の遅さ/速さで症状が違う)に関連がありそうで、何となく臭う。
こじつければ、電源が切れた後、パワーダウンスリープからVccが徐々に下がっていくとき、何らかの予期しない動きがあって今の状態になると考えれば、Vccが下がると同時にリセットがかかる方が望ましいことには違いない。
ということで半信半疑だったが、藁をもつかむ思いで、件(くだん)のTiny2313にBODを設定してみることにした。フューズビットを見てみると、現在の状況では未設定である。何の確証もないが、物は試しである。4.3Vでリセットがかかるようにする。
おおお、何ということだ。これでパワーダウンスリープで電源を抜いても、問題なく初期状態でCPUは動き始めたのである。いつも必ずトラブルが起きていた、ACアダプターのACコード側の抜き差しでも、全く症状は起きない。
実際に運用してみた。見事、1週間問題なく動いた。やれやれ、何だったのだろう。全く根拠はないが、BOD設定をフューズビットに設定するだけで直ってしまった(その後も、順調に稼働中5/31記)。
すごい、DS3231の月差は1.2秒(5/10/1216)
久しぶりにWiFiモジュールのESP8266を動かす。最後に触ったのは、I2CリアルタイマークロックRTC(DS3231)の動作テストである。このRTCはバッテリーバックアップがついているので、精度を調べるために大分前に正確な時刻を設定して放置してあった(4/1設定)。
UARTをつないで、ESP8266に電源を入れる。現状のプログラムはUART上に5秒ごとに時刻を表示するようになっている。スマホや手持ちの電波時計の正確な時刻と見比べる。ふむふむ、なんと、殆ど誤差がない。こいつはすごい。
このあいだ調べたデータシートのスペックによれば、月差で4秒近辺ということだが、今の時刻は2秒もずれていない。これまでに40数日間動いているのだ。多めだが2秒としてこれを365日12ヶ月で月差を換算すると1.2秒である。大したものである。 まあ、最近はGPSが正確な時間をくれるようだが、こんなスタンドアロンのしかも廉価なチップがこの精度なのは偉い。この製品も、以前の超音波距離センサーと同様、オリジナルをコピーした中華製のようだが、こうした電子部品が普及することはアマチュアにとっては有り難いことである。
長い目で見れば、先行開発にチャレンジする人(や会社)を減らすことになって産業全体では悪い影響を及ぼすのかもしれないが、ジェネリック薬品と同じような位置づけと考えれば、そう心配することもないのではないか(トップメーカーの囲い込みを防げる)と勝手な理屈をこねる。
AitendoでUSBプラグを買い、Tiny24で遊ぶ(5/11/2016)
AVRのTiny13は安いし小さいので重宝している。しかし使えるI/Oピンとフラッシュサイズが少ないのが難点である。これまでのソフト資産を生かしたまま、ちょっと機能を拡張したくても次の適当な製品がない。
Tiny85は、USIがつき、フラッシュも大きくなるが、なにせ8ピンなのでI/Oピンの制約は変わらない。といって、Tiny2313や、Tiny861は20ピンで急に大きくなりすぎる。データシートなどを調べると、このあいだには、14ピンの24/44シリーズがあるらしいが、日本の市場には出ていないと思っていた。
それがAitendoのサイトを見ていたら、SOPのTiny24とTiny44が売られているのを発見した(Tiny24/44にはDIP版がない)。たまたまUSBのAタイプオスコネクター(ジャック)を探していて、いきつけの秋月や千石に気に入ったものがなくて、Aitendoで良さそうなものを見つけたところである。
ちょうど良い機会なので、久しぶりに直営ショップへでかけることにした。ここは秋葉原というより上野に近い。地下鉄日比谷線の仲御徒町の駅から歩いて5分かからない。おやあ、1階に店が見える。始め、全部がここへ移ったのか勘違いしたが、どうも狭すぎる。店員に聞いたら3Fにもあるという(ちょっと日本語が覚束ない女性店員が答えて)、そちらに回る。
3Fのメインの売り場は前と同じ場所にあった。1Fの店はキット製品だけの売り場らしい。相変わらず結構な客の入りだ。膨大な品数だが、女性店員は的確に陳列場所に案内してくれる。Tiny24/44はすぐ見つかった。2つづつ買う。値段もリーズナブルだ(¥120と¥200)
帰ってきて、早速ブレッドボード上で使えるように、手持ちのSOPの変換基板を取り出したのだが、こいつが、やたらとごつく大きすぎる。長さが700mil(7ピン)なのは仕方がないが、幅は明らかに広すぎる(600mil)。20ピンの2313や、x61より大きく見えるのでは洒落にならない。
というので、今までのテーマ(学習赤外線ユニット)そっちのけで、自分で変換基板を作り始めた。動きだした手が止まらない。切り出した汎用基板に耐熱絶縁シートを張って、その上に接着剤で表面実装チップを固定し、0.2ミリのUEW線で配線する。
前から憧れていたChaNさんの得意技である。作ってみると意外にしっかりしていて美しい。幅は、100milしか狭くならなかったが、完全な自己満足の世界である。興に乗って2つ(Tiny24と44)も作ってしまった。
赤外線LEDの制御にTiny24とFETを持ち出す(5/15/2016)
前から考えているテーマはESP8266とスマホを使った赤外線リモコンの遠隔操作である。既成のリモコン信号を学習して、スマホから操作できる。いくつかの作例があり、ソースコードも公開されている。簡単にできそうだ。ESP8266の適当なアプリとして、部品も大分前に揃えてあった。
しかし、部品を目の前にして、急に気分が変わった。このままブレッドボードに部品を差し、ソースをArduino IDEにコピペして動かすだけでは何か物足りない気がする。赤外線リモコンは、前に受信側は自作したが、送信側はまだ作ったことはない。
ウェブの情報によれば、何やら送信用の赤外線LEDは、離れたところから動作させるには、1A近い電流量が必要になるらしい。マイコンのI/Oピンの最大電流は数十mAなので、当然なんらかのドライバーが必要になる。
そういうことも含めて、すべてお仕着せのスペックで作るのが惜しくなった。ちょうどSOPのTiny24がブレッドボードで使えるように変換基板を作ったところだ。赤外線リモコンをこれで作りたくなった。
赤外線LEDの送信側のハード制作は初めてで、それに慣れておこうという魂胆もある。トランジスターで動かしている例が多いが、ここは久しぶりにFETで制御してみることにした。改めてネットでFETのおさらいをする。1A程度のスイッチングなら手持ちの小さなFET (2SJ327)で十分だ。
まずFETの点灯テストから始める。念のため、可視光線のLEDを並列につなぐ。受信側はセンサーの出力をオシロで確認する。点灯する。あれえ、反応がない。オシロを良く見ると、小さなパルスは入っている。
念のため、エアコンや、電子ボリューム用の汎用リモコン(ソニー仕様)などを当ててみる。問題なく連続パルスが出ている。それなのに何故出ない? 暫くして、その理由がわかった。はっはっは、情けない話だが、サブキャリア―(35Khz前後)が必要なことをここで始めて理解した。
だから「赤外線受信素子」ではなく、「赤外線受信モジュール」なのだ。サブキャリアーを発生させるしかけが必要である。まだ先の話だと思っていたが、あわててTiny24の変換基板をブレッドボードに載せ、35Khzのサブキャリアー発生装置を作り始めた(照れ隠しもある)。
Tiny24/44のデータシートを改めて子細に眺める。タイマーや、ADコンバーターなどのペリフェラルは、殆どx61に近い装備で2313のようなUARTはついておらず、例のUSIが代わりにある。タイマー割り込みを使って、35Khz 1/3デューティのパルスを作る。
特に迷うことなく、赤外線のサブキャリアー発生装置が完成した。早速、テストに入る。想定した周波数より少し低いが(30khz)パルスが出た。受信モジュールに向けてみる。問題なくタクトスイッチで入り切りする出力が、受信モジュールの変化と同期した。
このあたりの赤外線リモコンのフォーマットについては、何といってもChaNさんのサイトが一番わかりやすくておすすめである。ただ、今度の学習リモコンは、各種のリモコンを汎用的に使いたいので、ここでの中身のフォーマットは関係ない。出来るだけ、原波形を忠実に再現することが重要だ。
SRAMが256バイトでは記録できない。いっそのことMega88にするか(5/23/2016)
次は、赤外線データ列の記録である。赤外線パルス列の受信は、以前電子ボリュームの時に実装しているので、ソースコードをそっくり持ち込み、テストする。あっさり動いた。しかし、エアコンのデータ受信で頓挫した。
エアコン(三菱)の送信データ列が多すぎて、Tiny24/44では入りきらないのである。配列が溢れて暴走する。データ蓄積を止めて回数だけで調べる。274イベントもあった。Tiny44のSRAMは256バイトでスタックを考えれば到底入らない。
困った。何とかならないか。EEPROMにしまいながらとか、色々頭を捻ったが、最少で500μs単位で発生する赤外線データの蓄積を、ミリセカンドオーダーの記録装置でやろうということに、そもそも無理がある。
最終ゴールはESP8266なので、テストベンチに凝るのも本末転倒である。潔く、換装を決意する。SRAMの大きさは、折角換装するなら1Kバイトくらいは欲しい。すると、Mega88あたりか。Tiny861では不足だろう。始め、Megaにするつもりでデータシートを見ていたが、861でもSRAMが512バイトあることを発見した。
少し、迷ったが、Tinyシリーズの中の移植の方が、Megaシリーズへの移植より楽な気がして、SRAMの量に不安は残ったが、Tiny861に移すことにした(これが、えらいトラブルの元になるとはこの時点では露知らず)。
Tiny861の罠(わな) コンペアマッチとキャプチャー機能が排他的とは(5/25/2016)
Tiny24/44とTinyx61のタイマーの構成はちょうど逆で、受信の時に使うインプットキャプチャー(邦版データシートでは、捕獲入力)機能は、Tiny24/44のタイマー1から、Tiny861のタイマー0に変わっている。
それ以外は大きな違いはなく、順調に移植が終わった。コンパイルする。おやあ、インプットキャプチャーしたときの値を収容するICR0(Tiny24/44ではICR1)レジスターがヘッダーファイルにないので未定義エラーになる。
何かおかしい。それと、通信のタイムアウト用に設定したタイマー0のコンペアマッチの割り込みルーチンが動いていないようだ。UARTで設定したOCR0Aレジスターの値を表示させてみると、0になっている(未定義エラーはとりあえずコメント化して回避)。
暫く頭を抱えていた。データシートがどうも不審なのである。日本語版では、ICR0レジスターが存在するかのような説明(本項では捕獲入力レジスタはICR0と呼ばれますが、これは比較レジスタへの参照です)があるが、これでは何のことかわからない。
念のため原文を引くと、Even though the Input Capture register is called ICR0 in this section, it is refering to the Output Compare Register(s).
で、どうもコンペアマッチレジスターが実体で、捕獲入力のレジスターは仮想的な感じだ。
さらに、データシートを調べていって、決定的な表を見つけた。
表11-2. 動作種別(ページ48)
番号 ICEN0 TCW0 CTC0 動作種別 TOP値 OCR0x更新時 TOV0設定時
--------------------------------------------------------------
0 0 0 0 標準8ビット動作 $FF 即時 MAX($FF)
1 0 0 1 8ビット比較一致
タイマ/カウンタ解除(CTC)動作 OCR0A 即時 MAX($FF)
2 0 1 x 16ビット動作 $FFFF 即時 MAX($FFFF)
3 1 0 x 8ビット捕獲入力動作 $FF 即時 MAX($FF)
4 1 1 x 16ビット捕獲入力動作 $FFFF 即時 MAX($FFFF)
なんのことはない。これではっきりした。動作種別があって、もともとTinyx61のタイマー0は、インプットキャプチャーか、コンペアマッチにしかならないのだ。Tinyx61はTiny24/44に較べると古い設計のようで、インプットキャプチャー機能が独立していない。
まあ、データシートを読み込まなかった自分が悪いのだけれど、何とも後味の悪い解決だ。データシートにちゃんと書いていない。OCR0Aレジスターは、インプットキャプチャーをenableにすると、コンペアマッチレジスターにならないのだ。
いかにも両方出来るように書いてある。しかも、インプットキャプチャーのレジスター定義(ICR0)がデータシートにあるのに、ヘッダーファイルにない。混乱する。捕獲入力の値はOCR0AとOCR0Bレジスターに16ビット分が、TCNT0LとTCNT0Hから移されるというのオチである。
インプットキャプチャーとコンペアマッチ機能は排他的だと、ひとこと書いてくれれば、何もここまで迷うことはなかったのにと八つ当たりである。いずれにしても、データシートのとおり、OCR0Aなどを使って、初期の目的は、Tiny861でもやっと実現した。274イベントのエアコン波形もめでたく記録された。
ロジアナの波形を頼りにプログラムの改修。至福の時(5/28/2016)
めでたく全部のデータが記録されたので、中身の検証に入る。ここからは、オシロやUARTでは無理で、ロジアナの登板である。赤外線受信モジュールのふるまいは、正確にロジアナで捉えられている。
それに加えて、マイコン内の割り込みルーチンや、データの処理部分にプローブ(GPIOピン)を設定し、調べ始める。20ピンのTiny861なので気楽に設定できる。
うーむ、採集された値は、だいぶ原データと違う値だ。受信モジュールの割り込みから、本来のデータ収集をする時点がばらばらなので。誤差が大きい。これは、割り込み時点ではフラグをだすだけで処理をメインに持ってきているので、そのあいだに別の割り込みが入ったりして違ってくるのだろう。この方式では駄目だ。
これはやっぱり、割り込みルーチンの中で処理を全部済ませる必要がある。どうせなのでソースコードをつらつら眺め、コードの短縮化を図る。元のプログラムは律儀にピン(キャプチャーピン)の状態を忠実に調べてから、割り込みの区別(立下りか、立ち上がり)を換えているが、考えてみれば、これは必要ない(単にスイッチするだけで良い)。
さらに、赤外線データのひとかたまりのデータの最初とそれ以降を区別するフラグを設けていたが、これも考えてみればいらない。最初につかんだデータは使わなければ良いだけだ。ただ、これによりタイムアウトだけが最後まで解決できなかった。データを受信したという印がなければタイムアウトを起こせない。 結局、このデータが来始めたことを知らせるフラグを復活させ、「データが来始めてタイムアウトするときだけ」真のタイムアウトとし、他のタイムアウトは無視するという逆転の発想で解決した。
こうして、割り込みプログラムの誤差はどんどん小さくなり、最終的には、当初200μs以上誤差のあったキャプチャーは、すべての遅れを5μsまで下げることが出来た。これは痛快だった。Arduinoを使っている限りでは、味わえない醍醐味である(シールドの設計者が独占している)。
ロジアナの画面に、綺麗に揃ったパルス列を並べて至福の時を過ごす。UARTのデータもきっちり5%以下の誤差で記録されている(0.33~0.31の範囲なので、2/32 = 6.25%)。あとは、この値に基づいて赤外線LEDを制御するだけである。紙数が増えてきたので、このあたりで報告しておこう。
| 固定リンク
「AVR」カテゴリの記事
- ソフトI2Cはクロックストレッチまで手を出してあえなく沈没(2017.09.02)
- オシロのテストどころかソフト開発で大はまり(2017.07.26)
- 超音波方式の人感センサーI2C化と新しいオシロ(2017.06.29)
- motionの動体検知はRaspi3の電源が安定しない(2017.04.16)
- 赤外線学習リモコンはデータ再現で挫折したまま進まず(2016.07.21)
「電子工作」カテゴリの記事
- 生存証明2(2022.10.19)
- 生存証明(2022.01.23)
- パソコン連動テーブルタップの修理を諦めて自作(2021.02.16)
- 半年ぶりのブログ更新に漕ぎつけた(2019.09.19)
- 研究所活動は停滞したままでCCDカメラ顕微鏡導入など(2019.02.08)
コメント