koheiのおもちゃ修理記録

宇部おもちゃ病院 毎月第2土曜日 13:00~16:00
宇部新天町の西の端、市民活動センターで開院してます。

8/8 宇部定期開院②~Qステアクローン送信機製作

2020-08-30 | PIC・電子工作
という事で、8月度の宇部おもちゃ病院定期開院に来たQステア(Q-STEER)、実機があるのをいい機会に、クローン送信機を作っておこうと思います。

いつも参考にさせて頂き&お世話になっている、つつじヶ丘おもちゃ病院の大泉さんの記事「Q-STEER送信機の修理(マイコン換装)」のプログラムを使わせて頂くことにしますが、デバイス(使用マイコン)をPIC12F509→16F1503に変更する事にしました。

記事の当時(2016年/7月頃)に12F509を採用された理由は、
・当時秋月で最安:50円。16F1503を使うと80円と1.6倍になってしまう。
・DIP-14はスペース的にも厳しい。
といった事で、DIP-8の12F509になったとの事。しかし、SW入力で5PIN、LED出力に1PIN(それとVddとVss)で、これ以上ポートが無く、ポートでチャンネルセレクトができない。

ところが、当時と部品調達事情が変わって、16F1503もAliExpressで50円程度で購入できるようになりました。例えばこのショップ。

スペースの問題も、SOP-14なら何とか元のケースに入ると思われます。基板作るのはちょっと苦労しますが、基板入れても厚さも空中配線のDIPと同じくらいに収まるかな?

ということで、A~Dのチャンネルセレクトも元と同じ形のクローン送信機を作ることにしました。
元の送信機の基板はこんな感じ。

左にSOP-14の16F1503を置いてますが、きっと収まると思います。SW面はこんな感じ。

チャンネルセレクトは予想通り2ビット。(COBにどう繋がってるかはよく分かりませんでした。)

大泉さんに「こんな物を作ろうと思います」とお伝えすると、「ほい、出来ました」とあっという間に先に作られてしまうので(w)、毎度、なるべく自力で作ろうとするのですが、結局毎度うまく動かず、大泉さんに相談する事になってしまいますww。
今回もちょっとしたミスや元プログラムの理解不足からくる間違いで問い合わせをして、お手数をお掛けしてしまいました。

12F509→16F1503に移植するにあたり、「Cで作ろうかな…(元のプログラムはMPASM)」とも思ったのですが、ASMのままの方が変更が少なそうなのでASMのまま作ることにしました。

移植・変更作業としては、
・POR時のチャンネル設定や、「TURBO単独で2.5秒以上押したら再設定」の部分はカット
・替わりに、sleepから起きるたびにポートを読んでチャンネル設定をする
・12F509版では必要のなかったBANK SELECTに気を付ける
・多機能な分、必要なポートの初期設定が増えて、define文がだいぶ増えた
・リセット/割込みベクタの書き方は?
ぐらいでしょうか。

プロジェクトをストレージに上げておきます。(「ここ」)
(2020/9/19追記)スリープ時の消費電流を測ると12.5μAでした。「ちょっと高いなぁ…」と大泉さんに尋ねると、「通常スリープ時の電流としてはそんなもの。低電力スリープを使えば1μA以下に下がる」と教えて頂きました。設定部分に「bsf VREGCON,VREGPM」を追加して低電力スリープにしたところ、手持ちの安物DMM(最小分解能0.1μA)で、消費電流0.2μAまで下がりました。プログラムをそのまま使う人は居ないかもしれませんが、ストレージも更新しておきます。

簡単な回路なので、プログラムの中身(ポートの定義)を見れば作れると思いますが、一応回路図載せておきます。(回路図見た方がイメージしやすい人も居るかもしれませんのでw。)

実機はLEDはNPNトランジスタでドライブしてますが、少なくとも今回はポートで直接駆動にしてます。(12F509はポートの最大絶対定格:25mAですが、16F1503は50mAで、表書きの概要には連続25mAと書いてあります。十分直接駆動できます。)
チャンネルセレクトは、最初コモンをプラスに繋いでプルダウンにしようかと思いましたが、それだとsleep時にも(チャンネルセレクトが1個でもONになってると)常時電流を消費してしまうので、スキャンの時だけポートから電圧を掛ける仕様にしています。(内部プルアップが使えれば、内部プルアップのON-OFFでいけるのですが、16F1503はポートAしかWPUが使えません。IOCもポートAのみなので、ポートAは操作SWに割り振るしかなく、チャンネルセレクトにPICの内部プルアップが使えません。)

製作した基板の写真も載せておきます。まず表:

裏:

今回は小さく作る必要ないのでDIP-14を使ってますが、基板はケチって、5×7cmの半分を使いました。裸で使うので、ビニール線は表のみにしてます。(回路図には載せてませんが、電源ラインに100uFの電解コンデンサを入れてあります。)

まず、OSCCONの設定の前にBANKの切り替えを入れ忘れてクロックが切り替わらない所でモタついて、大泉さんにヘルプを出してしまいました。
BANK切り替えミスに気付いてビルド・書き込み仕直したつもりだったのですが、HEXファイルが更新されてなかったみたい。(油断すると時々、ビルド成功してるのにHEXやLSTファイルが更新されない事があるような気がする。)
ついでに、「PICはsleepからの復帰はピン変化だけでよく、interruptを使わなくてもいい」の指摘や、フラグクリアに関する指摘を貰いました。

IOC=Interrupt on changeを使うのですが、「Interrupt」って書いてあるじゃん?と思うのですが(w)、データシートをよく読むと、

確かにGIEをdisableでinterruptが発生しなくても、sleepからのwake-upができる様に書いてありました。
フラグは、IOCIFが立ったままだとsleepできない図ですが、データシートをよく読むと、IOCIFはread onlyで書き込めず、IOCIFクリアの為にはIOCAFをクリアしておく必要がある。(そんなことがデータシートのなかのあちこちに分散して書いてあるw。)
GIEはセットせずに、IOCIEだけセットする。IOCAFをクリアしてからsleepを実行するように修正。

これで概ね動くようになってそれっぽい信号が出るようになったのですが、まだ受信機が信号を認識してくれない…。オシロとにらめっこしながら各信号の長さを微調整して何とか認識してくれるようになりましたが、12F509→16F1503への移植に際して、元のプログラムよりBANK切り替えが増えた分遅くなってる事に気づいて、38kHz信号を作るところの時間調整のnopを外したりして、再度時間調整して、一応の完成を見ました。

しかし、元のプログラムだと、チャンネルをA→Dへと切り替えると1フレームの長さが長くなるのが気になった。赤外受光モニターで音を聞いてても、チャンネルDまですると、明らかに信号の密度が下がる。これだと最悪、受信機側が「送信が切れた」と判断して、モータ駆動が切れ切れになる可能性がないか…?
第2データ送信後の待ち時間を(定数-data_time)にして、第1データと第2データ間の時間(=data_time)が変わってもフレーム長を一定にしようとしたのだけど思ったようにいかず、またもや大泉さんにヘルプ。メールのやりとりでヒントを貰って、何とか解決しました。
これでようやく完成です。

最後に、受信機側の考察をしておきます。
今回は、とりあえず受信機のクローンは作りませんw。実機のモータの駆動方法に疑問があるためです。
車体側の基板はこんな感じ。

ステアリング用の電磁石への配線は、Aがコモンで多分常時プラス。B・Cがそれぞれ電磁石のシンクで、基板上のNPNトランジスタでON-OFFしてます。
トランジスタのMarkingは「K1Y」で、Fairchild社のKSC3265-Yグレードと思われます。
この電磁石の駆動に基板のかなりの面積を使ってるのに、メインモータの正逆駆動回路がみあたりません…。これ以上分解はしてませんが、部品は片面にしか配置されてない様に見受けられます(電解コンデンサが1個付いてるかな?)。COBの中にブリッジ回路まで入れてあるのかしら…?
SOP8のマイコンとSOP8のモータドライバを使うと、この大きさで作れそうにありません…。(HブリッジをSMD部品で組むと、SOP8よりもっと面積食う。)

低速とターボの切り替えはPWMと思われます。「ここがモータ行きかな?」のところに電線繋いで、オシロで見てみます。

やっぱりPWMです。ターボを押すとDUTY=100%の連続電圧になります。(V=2Vぐらいなので、FETじゃなくてトランジスタによるブリッジかもしれません。)

現在動いてる修理依頼品をこれ以上つついて動かなくなるとマズいので、今回はこれ以上追及しませんが、「フレームが長くなるとモータ駆動が切れ切れにならないか?」の確認だけしておきます。

上と同じ点の電圧を見ながら、フレーム短めの時の状態:

データ間を200msにした時の状態:

(記事書きながらDCモードに切り替えてなかったことに気付いて、上の100usの方は撮り直したのですが、下の2つは撮り直してません。DCレベルがズレてますが、ご勘弁をw。)
どうやら、無信号が200ms続いてもPWM信号は切れてない様です。限界は確認していませんが、少なくとも200msまでは大丈夫そうです。

低速とターボの切り替えがPWMなら、ICは前後左右で4PIN(前後はPWM出力)、信号INとVdd・Vssで計7PIN。まだ1PIN余裕があるので、実機と同じくA/BまたはC/Dのチャンネルセレクトも付けて、SOP8のマイコンで換装できるかな?
とりあえず今回の検討はここまでにしておきますw。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

6/5 マイコンボードいっぱい買った②~RX621マイコンボード動作確認

2020-06-05 | PIC・電子工作
前回記事「マイコンボードいっぱい買った①~Nucleoボード動作確認」に続いて、次はRX621マイコンボードの動作確認をします。

結構大変でした。Arduinoほど初心者に優しくない。ネットでいちいち調べるも、なかなか進みませんでした。「マニュアルが日本語だから簡単だろう」と思ったら大間違い、ルネサスのマニュアルが全然解読できない…。全く初心者の為に書かれてないんだろうなぁ。

ルネサスの統合環境:e2studioでプログラミングしたのですが、下記のところで引っかかりました。
①ヘッダファイルをインクルードしてエディタ上で認識されても、ビルド時には別に指定してやらないとビルド・エラーになる。
②デフォルトではHEXファイルが生成されない。「ロード・モジュール・コンバータを実行する」をチェックしとかないといけない。
③アセンブル結果を見たければ、「アセンブリ・ソース・ファイルを出力する」に設定しないといけない。
④RX621ボードのDIPスイッチは、書き込み時:1100にして書き込んで、一旦電源を落として0100にして電源を入れるとプログラム実行開始になる。

買ってきて繋いでみて、「Lチカ」までどんぐらいで出来るか?
Arduinoや先日のNucleoは10分ぐらいで行けそうですが、今回のRX621は…丸一日は掛かった感じかな。「素人が何を!」と言う人もいるかもしれませんが、もっと素人へのハードルを下げてくれたら、もっとメジャーになるのに…と思いました。

さて、e2studioのインストールは他のサイトにお任せして、とりあえずLチカまで辿り着いてみます。
①のライブラリの指定ですが、

この画面:プロジェクトのプロパティから「C/C++ ビルド→設定→Liblary Generetor→構成」で、使うライブラリは全部指定しとかないと、ビルドがエラーになります。

②のHEXファイルの生成ですが、「C/C++ ビルド→設定→Converter→出力」で、「ロード・モジュール・コンバータを実行する」をチェックしておかなければなりません。

ネットで探すと「(プログラム名).motのファイルができます」との事ですが、モトローラSフォーマットのHEXファイルなんですね。ボードへのプログラムの書き込みには、別途RenasasFlashProgrammerを使います。画面の通り、フォーマットはインテルHexフォーマットも選べるようですが、RenasasFlashProgrammerでの書き込みには、とりあえずモトローラ形式でいいようです。(他の選択肢:インテルとバイナリーは試してみてません。)

③のアセンブル結果は、時間管理の厳しいプログラムを作ろうと思ったら、見たくなる場合があるかもしれません。
「C/C++ ビルド→設定→Compiler→出力」から、「アセンブリ・ソース・ファイルを出力する」をチェックしておけば、workspaceの¥プログラム名¥Release¥srcにリストファイルが出力されます。(画面は省略。)

④のRX621ボードのDIPスイッチですが、秋月が商品説明に載せてる説明書にもあまりはっきり書いてないというか、いまいち分かりにくい…。(今読むと、一応ちゃんと書いてあるw。)
DIPスイッチを切り替える時には一旦電源を切る、とにかくプログラム書き込みの時は「1100」で、プログラム実行の時は「0100」にする。

秋月の説明書で「CN4の1ピン」と書いてあるのが、DIPスイッチの一番左ですが、「ONでUSB Bootモード、OFFでSingleモード」との事ですが、その説明が分かりにくいのよね…。「一番左をONでプログラム書き込み、OFFでプログラム実行」ってことですね。
一番左をONにしておかないと、RenasasFlashProgrammerで「エラー(E3000201): 指定したツールが見つかりません。」と言われて接続ができません。

DIPスイッチの2番目は、説明書に「CN4の2ピンは、Endianの切り替えSWです」と書いてあるヤツ。RX621はEndianをLittle/Bigで切り替え可能との事ですが、素人には切り替える必要性が理解できないww。(過去に違うEndianで作ったソフトを移植するのに便利とかかなぁ…)
Endianは、e2studio側でも設定できるようですが、デフォルトはLittleになってました。(CPUによって違うかも。)
このEndian設定が一致してないと、RenasasFlashProgrammerでの書き込み時に「エラー(E300010D): 不明なデータを受信しました。(0x80)」と言われて失敗するっぽいです。(試してみるとたまに通ったり、たまに通らなくて電源を入り切りしたりしたw。)


さて、あちこち引っかかりながら、やっとLチカw。e2studioで新規でC/C++プロジェクトを作ると、void main(void)を含む空のプログラムが出来ます。サンプルプログラムが使えると書いてあるサイトもありましたが、自分はできませんでした…(インストールの失敗かしら…)
空のプログラムの中で、不要で消していいものと消したらビルド通らないものとがあったようですが、よく分かりませんw。
とにかく、mainの中にプログラムを書いていきます。

D0にLEDを繋いで点けたり消したりするだけのプログラムです。PORTレジスタを直接操作してます。方向指定はDDR、出力指定はDRですね。
Arduinoの「delay」に相当する関数が無いか相当探したのですが、どうも無さそう…。for文で作ります。今後作ろうと思っているプログラムで実行時間の微調整が必要になりそうなので、machine.hをインクルードして、nop( )を使ってます。
作業中の写真です。

これで、だ~~~いぶ時間がかかりましたが、何とかLチカまで辿り着きましたw。


コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

5/31 マイコンボードいっぱい買った①~Nucleoボード動作確認

2020-05-31 | PIC・電子工作
外出自粛や各種会場の閉鎖で外でやる用事がガックリ減ってるけど、ぼけ~~~っとしてる暇はない!やりたいことがいっぱいあるw。
長年温めてる「やりたい事」があって、速度・メモリに余裕のあるマイコンボードを購入しようと検討。秋月でガッポリ買ってみましたw。

左から、NucleoのSTM32F411RE、同じくNucleoでSTM32F446RE。
右から2番目は、日本が誇る半導体メーカー:ルネサスエレクトロニクスのRX621マイコンボード、一番左が(オマケで)Seeeduino XIAO。

購入時現在の価格と各スペックは下記の通り。
①STM32F411RE:1,850円、Clock100MHz、Flash512KB、SRAM:128KB
②STM32F446RE:1,980円、Clock180MHz、Flash512KB、SRAM:128KB
③RX621マイコンボード:2,700円、Clock96MHz、Flash512KB、RAM(96KB)
④Seeeduino XIAO:580円、Clock48MHz、Flash256KB、SRAM:32KB

作りたいと思ってるものに対して、Arduinoは…、日本での情報も多いしちょっとした工作には大変便利なんだけど…ATMegaでクロックが8or16Mhz主体なので、ちょっと遅すぎる…。最近CPUがCortexに変わってスピードアップしつつある様だけど、まだバリエーションがあまり多くない感じ…。
以前に「LED工作第1弾(?)」として作った3×3×3 LED-Cubeで使ったルネサスのGR-SAKURAはなかなか良かったんだけど、どうももう売ってない…。
いろいろ探すと、①や②のNucleoというボードが、安くてスペック高そう。という事で、試し買いにF411と、本命でClock180MHzのF446を購入。
それから、GR-SAKURAの代りに、同じルネサスでスペックも近いRX621ボードを購入。
ついでに「このスペックでこの値段はお得じゃない?!」と、Seeeduino XIAOを買っといてみた。(ポートはあまりいらないけど速度やメモリが欲しいときに便利かも、と。)
(最近ちまたで大人気らしいRasberry Piも考えてみたんだけど、OS上で動く前提なので、厳密に時間を管理したいプログラムには向かないらしい。OSを外して「ベアメタルでラズパイ」という使い方もできるらしく、楽しそうでめっちゃ心そそられるけど、どうも統合環境なしでコンパイルしないといけなそうなので、初心者は手を出さない事にしましたw。)

とりあえずまず、Nucleoのボードの使い方を勉強してみるw。

秋月の商品ページでは「mbedで開発しなさい」と書いてある。(書いてない?)
「mbedとはなんぞや?」どうやら、Cortexを作ってるARMのボードもしくは開発環境の事らしい。mbedの使い方はいろんなサイトに書いてあるので、参考にしながらとりあえずオンライン版のmbedにユーザー登録して使ってみる。

Nucleoボードは、USBで繋ぐとUSBストレージとしてパソコンに認識される。サンプルプログラムを取ってきてコンパイルすると、(プログラム名).binのファイルができるので、それをどこかに保存してからエクスプローラでドラッグ&ドロップすると、あっという間に書き込み出来て、本体のLEDが点滅する。
(実際には、自宅にボードが到着する前にあーでもないこーでもないと悩んだのだけど、ボードが到着して繋いでみたら、あっという間だったw。)

さてこのボード、秋月のページには「(STM32F411)クロック:最大100MHz」と書いてある。ほんとに100MHzで動いてるのだろうか…。
サイトを探すと、「裏にシールが貼ってあって、C-01は内部クロックで動作、C-02はST-LINKからクロックを供給」(※Nucleoボードの上3分の1は、USBでの書き込み用にマイコンが1個乗ってて、その部分をST-LINKと言うらしい。)と書いてあったのだけど、買ったボードには「C-04」のシールが貼ってあって、クロックがどうなってるのかよく分からない…。
分からないなら調べるしかない。ネットであちこち探して調査する。

昨日一日散々悩んでうまくいかなかったけど、一晩寝てやり直してみるとスッキリ。概ね調査が終わりました。
「MCOピンにクロックが出力できる」との事で、出力させてオシロで確認。
CH1がHSI(内部クロック)、CH2がHSE(外部クロック)です。

外部クロックには8MHzが入ってるようです。(ST-LINKの水晶は8MHzが乗ってます。)
続いて、MCOの出力パラメータをRCC_MCO2SOURCE_HSE→RCC_MCO2SOURCE_SYSCLKに変更して、システムクロックを確認。(ちょっと早すぎるので、パラメータで4分周にして出力させる。)

オシロの値がだいぶ振れるけど、どうやら4分周で25MHz→システムクロック=100MHzで動作中らしい。

続いて、下記のプログラム:HALのGetOscConfigを使って、クロック周辺の設定を確認してみる。

RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_RCC_GetOscConfig(&RCC_OscInitStruct);

printf("System Clock = %d\r\n", HAL_RCC_GetSysClockFreq());
printf("OscillatorType : %d\r\n", RCC_OscInitStruct.OscillatorType);
printf("HSEState       : %d\r\n", RCC_OscInitStruct.HSEState);
printf("PLLState       : %d\r\n", RCC_OscInitStruct.PLL.PLLState);
printf("PLLSource      : %d\r\n", RCC_OscInitStruct.PLL.PLLSource);
printf("PLLM           : %d\r\n", RCC_OscInitStruct.PLL.PLLM);
printf("PLLN           : %d\r\n", RCC_OscInitStruct.PLL.PLLN);
printf("PLLP           : %d\r\n", RCC_OscInitStruct.PLL.PLLP);
printf("PLLQ           : %d\r\n", RCC_OscInitStruct.PLL.PLLQ);

printfの結果は…、TeraTermで受けれるのかな?出力画面はこうなる。

結局、cubeMX(後で説明)でのクロック設定は、

こうなって、結論としては、外部からのクロック入力は8Mhzで、CPUの動作クロック=HSE÷M×N÷P=8Mhz÷4×200÷4=100MHz という事になってるらしい。

続いて同様に、STM32F446の方のクロックも確認しておく。やはりHSEは8MHz。

4分周したシステムクロックは約45MHz。

システムクロックは書いてある通り180MHzで動作中の様子。
クロックの各設定は、

cubeMXで表現すると、

となって、結論としては、外部からのクロック入力は8Mhzで、CPUの動作クロック=HSE÷M×N÷P=8Mhz÷8×360÷2=180MHz という事になってるらしい。
(OscillatorType=15になってるのがちょっと気になる…。「15」は多分、「RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI」の合計と思われる。同時に設定した場合には優先順位があるのかな…。)
(「NucleoはPF0にオンボードのST-LinkからのMSOを入力すれば自動でクロック源をHSIからHSEに変えてくれる」と書いてあるページがあったので、OR取って全部指定していたら、HSEを優先してくれるのかもしれません。)

ということで、STM32F411もSTM32F446も、設定を変えなければ、多分ST-LINK側の水晶発振を使って、秋月の商品ページに書いてある最大周波数で動いてる事が確認できました。
(設定を変更しようとしたのだけど、mbedで作ったプログラムで変更できなかった…。やり方が悪いのか、後述のSW4STM32からなら変更できるのかまだ分からないけど、とりあえずは最高周波数で動かしたいので放置しておくw。)

ところで、オンライン版のmbedですが、関数とか定義済みの定数とかの定義が見れない…。

関数は、カーソルを合わせると説明の窓が出るけど、ドキュメントには飛べないし、定義のライブラリにも飛ばない。定数の説明も出ない…。
例えばMCOの設定に、「RCC_MCO2SOURCE_HSE以外の何があるんだろう?」という際には、定義に飛んでくれないと大変不便…。
mbedの方で調べたけど、どうにも分からない。オンライン版じゃなくてダウンロード版もあるらしいのでインストールしてみたけど、そちらはライブラリがリンクできずにコンパイル出来なかった…。
秋月のサイトには、Nucleoボードは「mbedでプログラム開発しなさい」と書いてある(書いてないw?)のだけど、あちこち調べると「cubeMX+SW4STM32で開発しよう!」と書いてあるサイトがあったので、参考にさせて貰いながら入れてみました。

「cubeMX」は、Nucleoのボードに使われているSTM32F4を製造しているSTMicroelectronics社のソフトで、サイトの説明によると「STM32マイクロコントローラの設定を簡略化し、対応する初期化用Cコードを段階を追って生成できるグラフィカル・ツール」との事で、プログラム本体を作る前にポートやクロック等の面倒な設定の部分を作ってくれるソフトらしい。
「SW4STM32」は、フルネームは「System Workbench for STM32」で、同じくSTMicroelectronics社のソフトで、つまり自社製のSTM32プログラム開発用の統合環境の様である。

オンライン版のmbedで定義が参照できなくて困ったけど、SW4STM32ならctrl押しながら語句をクリックすると定義に飛んでくれたので、上記のクロック設定の確認とかは、SW4STM32とオンラインmbedとをいったりきたりして作りました。
まだ全部は理解できてないけど、とりあえずオンラインmbedの方がarduinoライクに簡単にプログラムが書けそうだけど、もっと詳細な設定をしていきたければ、cubeMXで設定作ってmbedに必要な部分だけコピペするか、「cubeMX+SW4STM32」で作った方がいい、といったところかな~?

画面のコピーばっかりになったので、作業もしてるんだよ、という写真も載せておきますw。

上のmbedの画面コピーの下の方にこっそり書いてあるプログラムで、PA0に繋いだLEDの「Lチカ」をしてる所です。(基板のLEDを点けるだけじゃ、ほんとに言う事聞いてくれてるかどうか実感が無いのでw。)

参考にさせて頂いたサイトを記載しておきます。(それぞれお断りしてませんが、リンクご了承くださいw。)
SW4STM32とCubeMXを用いてNucleo開発環境を整える:CubeMXとSW4STM32のインストール手順と使い方を手取り足取り書いてくれているページ。初心者には大変助かりましたw。
電子工作専科のぐうたラボ「NucleoのClock (2)」:MCOの設定がしっかり書いてある。そのままコピーさせて頂いて使いましたw。
STMのGPIOはどうなってるのか(LEDをつける):GPIOレジスタの直接操作方法を一から説明してくれてるページ。実行サイクルの厳しいプログラムを作ろうと思ったら必須かな。

ところで、上のGPIOの使い方を説明してくれてるサイトにも書いてありますが、普通のマイコン(PICとか)は、ポートは方向指定をしてあげるぐらいで使えると思うのですが、STM32は、まずポートに電源を供給してやらないといけないらしい。それは「ペリフェラルにクロック供給」という仕組みとの事。そしてそのクロックは、cubeMXで見てみると、CPUの方を最大クロックで使用していると、最高でもCPUクロックの半分の周波数までしか供給できないみたい。
ゴソゴソやってる時に、GPIOを直接H-Lとした時に、オシロでHが拾えずにだいぶ悩んだ。DegitalWrite等を使わずに1サイクルでGPIOをH-Lとすると、CPUのクロックにGPIOがついてきてないのかもしれない。時間に厳密なプログラムを書くときには、ちょっと意識しないといけないかも、と思いました。

さて、次はRX621マイコンボードの使い方だな~w。


コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

5/16 自動車用フラッシャーリレー製作~第2報

2020-05-16 | PIC・電子工作
GWにがんばって作った、愛車カプチーノ用のフラッシャーリレー。
車に乗る用事が無いので実車にて確認できてませんでしたが、先日ちょっと走ってみると、不具合発生…。

最初は好調で、tiny13くんが起きて、寝て、起きて、寝て、とけなげに働いてると思うと「かわいいな~w」などと思いながら走ってたのですが、そのうち「点きっ放し」になってしまった。
ウインカーSWを切れば物理的にランプへの通電が切れるので当然消灯しますが、リレーがONしっ放しになってる様です。予想通りですが、エンジン・ACCを一回切って掛け直すと、動作不良も復活します。
30分ぐらいの走行で、点きっ放し2回は発生しました。これは…、ノイズによるデバイス誤動作ではないかしら…?

またもや先輩から「デバイス側の不具合なのか回路側の不具合なのか切り分けすべき。動作不具合の時にPB0とPB1の電圧を測定して」との助言。
どうしようかと考えましたが、結局せま~~~い車内にノートパソコン持ち込んで、USBオシロで測定しました。
基板から1mずつ4本線を出して準備。この状態で、多分よりノイズを拾うようになったのだろう、近くの公園までちょっと車動かすだけで、不具合多発。さらにオシロのプローブを繋ぐと、ほとんどまともに動かないというほど不具合さらに多発。やっぱりノイズによるデバイス誤動作の気がする…。

まず通常動作時:

電源電圧:3.3Vの変動は、時間軸拡大してみてもそんなに大きくない。200kΩでプルアップしてるPB0のHレベルは、いまいちデコボコしてる。点滅周期は約1.5Hzぐらいに調整してある。

次に、「点きっ放し」が始まった所の結果:

やっぱりリレーON指示のPB1がHのままで、回路側でFETが勝手にONしっ放しになってる訳ではなく、tinyからリレーON指令が出っ放しになってると思われる。(リレーがONの間は、PB0はHのままになって正常。)

ところが、誤動作は「点きっ放し」だけでなく、点かないとか、一瞬点くとか様々発生。
その中で、「点灯」だけ短くなって周期が早くなってしまう誤動作が発生!
その時の電圧観測結果:

点灯と消灯の時間はどちらも、最初にADCから取った値=voltを使って、「(定数+volt/2)×2ms」で、SW変化の待ち時間を含めて同じになるようにプログラムしてる。
こんな点滅になるためには…、点灯の方だけ上式の「定数+」が抜けた状態じゃないとこの点灯時間にならない…。
そんな事が起きるか分からないけど、tiny内で「命令の抜け(飛ばし)」が起きてるとしか思えないなぁ…。(たとえば、ノイズでクロックが1個余分にカウントされて、命令終了前にプログラムカウンタが1個進んでしまうとか??)

という事で、何かノイズ対策を検討する。先輩からはWDTを勧められたけど、それはあくまでも「誤動作した時のリカバリー」策。「誤動作しにくくなる対策」の方がいい気がするし、ICSP使用になってないので、プログラム書き換えるのめんどくさくってww。

外部と繋がってて一番怪しいのは、PB0への入力信号。電圧が違うのでダイオード(BAV99)でブロックしてるつもりだけど、微小高電圧のノイズがブロックしきれてないのかも。
手持ちの家電ジャンクを覗いてみると、仕様不明だがDIP4のフォトカプラが見つかった。これを使って信号ラインを切り離そう。

回路検討、Markingからフォトカプラの型番がぴったり見つからないけど、シャープのPC817というフォトカプラが名前が似てる…。これを参考に、LED側はVf=1.2V、If=6mA程度で抵抗設定して、ブレッドボードで動作確認。各抵抗等を下記で設定。

PB0のプルアップは200k→50kに変更。(これだとtinyの内部プルアップを使うのと変わらないけど、プログラム書き換えが面倒なので、外部プルアップのままにするw。)
スペース厳しいけど、これでフォトカプラ部の基板を作って今まで作った基板に追加する。

DIP4なので、最小で万能基板の2×4穴は要るけど、さすがにそれじゃ厳しい。3×4穴使う。表はフォトカプラのみ。

裏はSMD部品を無理やり搭載し、出入りの線を4本接続。

なんとかこれが「最小」基板かな?これを何とかケーシングに収まるように搭載すると、こんな感じに完成。

フォトカプラは、両面テープでtinyに張り付けて何となく固定。まあ、何とか配線切れずにもつかな~?

これで机上で試運転→一発OK!
車に搭載して、ちょこっとその辺を5分ぐらい走ってみたところ、まあ問題なさそう。「良くなった」かどうかは、もうちょっと長時間走ってみないと分からないけど、少なくとも悪くはなってなさそう。
そもそも車あまり動かさず、おもちゃ病院と試合(アイスホッケーと野球)に行く時ぐらいしか車使わないので、コロナでどれも中止中で全然車を使わないw。まあいずれ確認して、これでもまだ誤動作発生する様なら、次はWDTによるリセットを考えてみますw。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

5/4 自動車用フラッシャーリレー製作

2020-05-02 | PIC・電子工作
いや~、待ってましたGW~。やりたいことが一杯あるのねw。
ぼくの愛車のカプチーノですが、平成4年式→もう28年物!あちこちボロボロなだけでなく、古い車なのもあって不具合な所が多いのよね。

カプチーノは電装系が弱いことで有名。例えば、夜信号待ちで、ヘッドライト付けた状態でウインカーを点けると、ヘッドライトがウインカーの点滅に合わせて明暗変わるし、インパネも明暗する。
電装系の弱さをカバーするため省電力を図るには、とりあえずヘッドライトのLED化が一番効くんだけど、それは結構大変…。そこで、ヘッドライト以外のほとんどをLED化してます。
(ちなみにヘッドライトが55W×2、ウインカーが合計47W(×2:ハザード時)、テールランプ/ブレーキランプ42&10WはLED化済み。インパネ周り:15WもLED化済み。エアコンは絶対に使わないw。)

最初にウインカー球をLEDに替えた際は、電流低すぎ=球切れ判断でハイフラッシュ状態になってしまいましたが、純正のウインカーリレーの中の回路の抵抗を変えて、何とか60Hz程度に調整してました。
しかし、それだとDUTYが50%じゃなくなっちゃったので、次にシャント抵抗を上げて
ハイフラッシュ回避してました。これで数年やってました。

しかし車検の時に「ウインカーが黄色い!」という指摘で車検通らず(「橙色」の決まりらしい…)、車検の時だけ電球に戻して車検を通す、という事になった。
ところが、純正のウインカーリレーは、電流低すぎ検知だけじゃなくて、電流高すぎ検知もしてるようで、LEDでちょうどいいシャント抵抗にした状態で白熱電球に戻すと、DUTY20%ぐらいの変な点滅になってしまう…。

という事で、もう電流監視はせずに、LEDを付けても白熱電球を付けても、どっちでも使えるウインカーリレーを作ってしまおう、という目論見です。
(ちなみに、LED用ハイフラ回避ウインカーリレーも売ってますが、「電子音はイヤ!昔ながらのカッチン、カッチンの方がいい!」とか、LED用のリレー刺した状態で白熱灯に戻すとリレーが壊れる、とかの事情で却下ですw。)

元のウインカーリレーはこれです。(ケース外してます。)

これの端子・基板・リレーを転用して、まるっきり作り変えてしまいます。

前置きが長くなりましたが、マイコン使う手もありましたが、最初「タイマーIC:NE555」で作ろう、と思い、TTLタイプNE555を購入しておきました。マイコンと比べての利点は、
・電源が~15Vまでなので、バッテリーから直でいける。電源を用意しなくていい。
・プログラム作らなくていいw。
…ぐらいかしら。
しかし、3極のフラッシャーリレー、「B」端子に給電したらウインカー点き始めるのかと思ってたけど、調べてみるとそうではないらしい…。
回路図はいろいろあったけど、簡略化して書くと、こんな感じらしい。

メインスイッチを入れる(鍵を回す)と、ウインカーリレーは常に電源供給状態になり、ウインカー灯の側でGNDラインを繋げると、ウインカーが点灯(点滅)する、という構造らしい。
これは困った…。555で電源入れっぱなしの発振回路作って、ウインカーを点けたいときにGND側を接続するだけと、点滅の中途半端な途中から始まって、ウインカーレバーを入れてすぐに点かなかったり、点いたけど瞬間切れて遅れたりとかになってしまう…。これはヤだなぁ…。
Lの端子がGNDに落ちたのを検知して電源を入れて、ランプ点灯中は自己保持する、という回路の例があったけど、ちょっと部品点数が増えすぎな気が…。

そこで、マイコンで作ることにしました。
目指す機能は、
・ウインカーつけると、例えば60Hzなら、必ず点灯0.5秒-消灯0.5秒…の最初から始まる。
・点滅周期は、60~120Hzぐらいの可変にする。
・点灯制御は機械式リレーを転用する。
在庫の余ったPICで作ろうかとも思いましたが、Attiny13aならSOP8を持ってて、そっちの方が小さく作れるので、使用デバイスはAttiny13aにしました。

プログラムにちょっと行き詰ったところでいつもの先輩に相談したところ、全体に渡っていろいろとご指摘を頂き、最終的に回路はこうなりました。

プログラムは後で載せますが、ブレッドボードで動作確認。

今回のSOP8のAttiny13aへの書き込みは、SOP8用アダプタを使いました。

AliでSOP用のアダプタを買おうかずっと悩んでたのですが、他のおもちゃドクターの記事で紹介されてた、SOP8→DIP8変換基板を使って挟み込んでネジで締めるアダプタを作ってみました。これで、基板に取り付けずに書き込みできました。

ブレッドボードでの動作確認は、リレーは付けずに出力にLEDを繋いで模擬。PINB0に繋ぐ「SW入った」検知ラインは赤色LEDを経由してGNDに落して実機を模擬。
プログラムは何度か間違い修正してちゃんと動くようになったものの、LEDをGNDに落しただけではPINB0がLになりませんでした…。
LEDの順方向電圧が乗っちゃって、PINB0の内部プルアップ使用時は、LEDをGNDに繋いでもPINB0=1.65Vで点滅が全くスタートせず。内部プルアップをやめて1MΩの外部プルアップにして1.45Vで、点滅がスタートしたりしなかったり…。
先輩の助言から、プルダウン用の抵抗(回路図の、LEDに並列に入れてる10kΩ)が必要という結論になりました。これだと、12Vブロック用のダイオード(BAV99)の電圧降下を考慮しても、PINB0がちゃんとLになってくれると思われます。
プルダウン時の電流と抵抗の電力とプルアップとのバランス考えて、プルアップは200kΩ、プルダウンは10kΩとして、上述の最終回路となりました。
検知ラインのダイオードは、順方向電圧降下の低いショットキーを使おうかと思いましたが、耐逆電圧の高いスイッチングダイオードを選択しました。(家電基板から取った、Marking:KJEのBAV99を使いました。)

さて、プログラムが完成、いけそうな目途が立ったので、いよいよ、元のリレーの部品を全部取っ払って、作り替えていきます。
残りICだけになった所。

型番調べても出てこない、多分法人専用と思われます。ちなみに、リレーも型番からヒットしません…。

1.27mmピッチのスルーホール基板に乗せますが、限られたスペースで、なかなか頭を使いました。こんな感じの出来上がり。

基板の拡大。

おもちゃ修理で鍛えられて「小さく作るのはお手の物!」といいながら、なかなか大変でした。(あまりキレイじゃないのはご勘弁を…)
基板裏面。

1.27mm基板の方のスペースが厳しくて、検知ラインのダイオードは、こっちの基板裏に付けました。また、リレーコイルの逆起電力からFETを保護するためのダイオードも、基板裏に直付けしてます。(回路図に型番書いてませんが、手持ちであったそれっぽいヤツですw。)

これで、車に付けてたLED取ってきて繋いで動作確認……期待通りに動かない…。
LEDをGNDに落すと、点きっ放し、約0.5秒おきに一瞬切れる、という動き…。
PINB0のH→Lがちゃんとできてない?と、オシロ繋いで確認したりしましたが、これは…、リレーの物理的なSWが遅いので、リレーがOFFになってすぐにPINB0が確実にLになりきってない→時間待ちの追加が必要、と思われます…。
もう「プログラムは完成だ!」と、全部組んじゃった…。けど、まだ間に合う。(というか、これが完成しないと車に乗れないw。)
完全にICSPするように作ってないので、一部配線外し&配線を引き出して、無理やり再書き込みをします!

プログラムに時間待ちを追加して、注意深く配線して、書き込み…一発でOK!

プログラムの最終はこうなりました。

1:  /*
2:  * FlashRelay.cpp
3:   *
4:  * Created: 2020/04/29 10:04:27
5:  * Author : Kohei Murakami
6:  */ 
7:
8:  /*
9:  車載フラッシャーリレー用プログラム
10:  【ヒューズ設定】
11:  ”FEF9”
12:  内蔵オシレータ4.8MHzの8分周無し、BOD無効
13:  ピン数には余裕あるが、RESET無効・低電圧プログラミング無効にしておく
14:
15:  【PIN割当て】
16:  PIN1:NC
17:  PIN2:NC
18:  PIN3:NC
19:  PIN4:GND
20:  PIN5:PB0(INT0)ウインカーSW入り検出、外部pull-up
21:  PIN6:PB1 リレー駆動FET行き出力
22:  PIN7:PB2(ADC1) 点滅速度調節用VR
23:  PIN8:Vdd
24:  */
25:
26:  #define F_CPU 4800000 // 4.8MHz
27:
28:  #include <avr/io.h>
29:  #include <util/delay.h>
30:  #include <avr/interrupt.h>
31:
32:  /* ピン変化割込みハンドラ */
33:  ISR(PCINT0_vect)
34:  {
35:  	//何もしない
36:  }
37:
38:  int main(void)
39:  {
40:  	unsigned char i,volt;
41:
42:  // 初期設定
43:  	PORTB = 0b00000000;	// 全ポートL(内部プルアップ不使用)
44:  	DDRB = 0b00000010;	// PB1のみ出力、他は入力(Hi-Z)
45:  	ADMUX = 0b00100001;	// 基準電圧=Vcc、左寄せ、PB2
46:  	MCUCR = 0b00110000;	// パワーダウンモード、Sleep許可
47:  	PCMSK = 0b00000001;	// PINB0のみ割り込みを許可
48:
49:  // 点滅周期取得のため、ADC1電圧を読み込む
50:  	_delay_ms(20);	// 電圧安定時間を取る
51:  	ADCSRA = 0b11000000;	// AD変換許可、変換開始、自動起動不可、完了割込み不可、分周CK/2
52:  	while(!(ADCSRA & (1 << ADIF)));	// 変換終了まで待つ
53:  	volt = ADCH;	// 値取得(上位8bitのみ)
54:  	ADCSRA = 0b00000000;	// AD変換不可
55:
56:  	/* メインループ */
57:  	while (1)
58:  	{
59:  		// PB0がHならsleepに入る
60:  		if (PINB & (1 << PINB0)) {
61:  			GIFR=(1<<PCIF);	// 割り込みフラグをクリア
62:  			GIMSK = 0b00100000;	// ピン変化割り込みを有効
63:  			sei();	// 割り込み許可
64:  			__asm__ __volatile__ ("sleep");		//Sleep
65:  			cli();	// 割り込み禁止
66:  			GIMSK = 0;			//割り込み無効
67:  		}
68:
69:  		for(;;)
70:  		{
71:  			// 出力ON
72:  			PORTB |= (1 << PINB1); // PB1をHに
73:  			for(i=0;i<=100+volt/2;++i) {
74:  				_delay_ms(2);
75:  				__asm__ __volatile__ ("nop");	// OFFと時間を合わせる
76:  				__asm__ __volatile__ ("nop");
77:  			}
78:			
79:  			// 出力OFF
80:  			PORTB &= ~(1 << PINB1); // PB1をLに
81:  			_delay_ms(100);
82:  			for(i=0;i<=50+volt/2;++i) {
83:  				_delay_ms(2);
84:  				if (PINB & (1 << PINB0)) goto OUT;	// 出力OFF時にPINB0がHならloopを抜ける
85:  			}
86:  		}
87:  		OUT:
88:  		;
89:  	}
90:  }

(あい変わらず「不等号」がちゃんと書けないので、倍角に変えてます。コピー時は注意願います。誰もコピーして使わないと思うけどww。)
81行目が、後から追加した時間待ちです。最初20msにしてましたが、失敗してもう一回書き込みするのはイヤだったので、長めに0.1s取っておきました。これを長くしても、次の消灯中のforループを短くすれば影響なしです。(この0.1sの間は、ウインカーSWを入れたり切ったりしても検知してくれませんが、人間の操作には影響ありませんねw。「切り」は、物理的に切断されるので、切った時に切れが遅くなる心配はありません。)

先輩から「デバイスの省電力を狙わないならsleepの必要ないでしょ?」と指摘されましたが、例えば2時間のロングドライブ、そのうちウインカーを点けるのが例えば30秒×20回。その10分の為に残りの1時間50分プログラムがぐるぐる走ってるのは無駄かなぁ、と思って、必要ないときはsleepにしました。

電源ONの最初に1回だけ、ADCを読み込んで点滅周期を決める作りにしてます。
まあ、言ってみれば単なる「Lチカ」ですが、ADC・sleep等、データシート熟読・先輩にダメ出しされながら、いろいろと勉強になりましたw。

さてさて、再書き込みの為にバラしたのを元に戻して、プルダウンを追加したLEDを繋いで動作確認…バッチリ期待通りの動き!!
後は、実車にて、どこにプルダウン抵抗を入れるか検討・実行すれば完成。

外してきたフロントウインカーとLED。

左はサイド用のウェッジ球。右が前後ウインカーに使ってるLED。
「ウインカーが黄色い!」と言われて車検が通らない、黄色LEDを買ったかと思ってたけど、どうやら白色LEDを買ってたみたい。
点灯させて、HDR(明るさ調整)かけて撮ると

こんな感じですが、明るさ調整なしだと

こんな感じ。プラスチックはある程度橙色なのですが、白が強すぎて黄色っぽくなってしまうようです。LEDの表面をオレンジの油性マジックで塗ってみたけど、ほとんど変わりませんでした。何とかならないかなぁ…。

フロント・サイド・リアと確認しましたが、このフロントウインカーでプルダウン取るのが一番簡単そう。被覆の一部を切って、線間に抵抗を入れます。

あとビニールテープ巻いて終了!実車装着して試運転…、とりあえず走ってはないけど、バッチリでした~!
(5/16:追記)
実車装着して走ってみると、不具合発生しました…。
「5/16 自動車用フラッシャーリレー製作~第2報」にて改造実施です。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

8/25 インテルHexFormatViewer~不具合修正

2019-08-25 | PIC・電子工作
ちょっと前の記事「6/1 インテルHexフォーマットファイルのViewer、作ってみた~バージョンアップ
」で掲載した、インテルHexフォーマットのファイルを色付きで表示するViewer、先日使ってたら、上書き保存ができないバグがあったので、修正しました。

(上の画像は「1BYTE表示」の例。「2BYTE表示」にもできます。)

実行ファイルが欲しいだけの人は→ココ
プロジェクト全部が欲しい人は→ココ

見直してみたら、パス付ファイル名とパスとがごっちゃになってました。
とりあえずちゃんと動くようにしたけど、まだバグがあるかもなぁ…。

これだけの記事ではつまらないので、プログラミングに関する雑感を少し。
近々、小学校でプログラミングが必修になるとか。どうなることやらww。
必ずしも、何かの言語でプログラムが組めるようになるのを目指す訳ではなく、「プログラミング的思考を習得する」が目標という話もある…。

「プログラミング的思考」とは何ぞや?
文科省さんの定義によると、
「自分が意図する一連の活動を実現するために、どのような動きの組合せが必要であり、一つ一つの動きに対応した記号を、どのように組み合わせたらいいのか、記号の組合せをどのように改善していけば、より意図した活動に近づくのか、といったことを論理的に考えていく力」
だそうな。まあ、「プログラム」という物を無理やり言葉で説明するとこんなふうになるんだろうけど、さっぱり分からん~ww。

上の「IntelHexViewer」は、結構なボリュームのプログラムになったけど、あれぐらいのプログラムが作れるという事は、ぼくは「プラグラミング的思考ができる」(レベルはともかくw)という事だと思うけど、それはどうやって習得したのか?
小5の頃にいわゆる「マイコンブーム」が始まって、N-BASICやZ-80のマシン後の勉強をちょっとした。技術・知識よりも創造力が足りなかったので(w)、雑誌のプログラムを入力して遊んでたぐらいだけど、まあ、プログラムというものがどういうものかは、小学校の頃にあらかた習得してたのではないかしら?

小学校では、特定のプログラミング言語によらずに「プログラミング的思考」を習得するために、Scratchとかの「ビジュアルプログラミング」を使うとかの噂もあるけど、そんなまどろっこしい事せずに、VisualBasicとかで直接プログラムの勉強すればいいのに、と思うのでした…。
(何が言いたいのかよく分からないけど、とりあえず終了ですww。)
コメント (2)
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

8/7 チャーリープレクシングについての考察(続編3)

2019-08-04 | PIC・電子工作
英語版wikiのCharlieplexingには、他のいくつかの派生形の解説がある。それらもどんなものか理解しておこう~。wikiに出てる順番に書いていきます。

1.Tucoplexing
解説記事は「Tucoplexing: A New Charliplex For Buttons And Switches」。
「3つのポートで、4個のLEDと4個のスイッチ」との事で、回路は下記。

これは…、ちょっとズルいなぁw、アナログな要素が入ってますね。まあそもそも、Charlieplexing自体が「狙ったLED以外にも電流が流れるLEDがあるけど、Vf不足で点灯はしない」というアナログ要素が入ってるし、「続編2」の「3ポートで12LED」ほどアナログでもないし、ポートもデジタルしか使わないけどねぇ。

Charlieplexingは、3ポートならA-B、B-C、A-Cの3つの組み合わせを使うけど、LED用にはA-B、B-Cだけを使って4LED。A-C間はスイッチに使うけど、ダイオード追加スイッチで2点に加え、コンデンサの充電を使って倍に増やして、スイッチ4個、という回路。

スイッチ入力確認方法の英文の説明がちっとも理解できないw。単にボクの英語力が足りない問題だけではない気がするのだけど…。
SW1検出の為には、PAを内部プルアップの入力・PCをL出力にして、PAがLならSW1押された、というスキャンをするはず。ただこれが、時間が短い場合には、SW2が押されてても、PAはLになる。SW2が押された場合は、0.1uのコンデンサが充電されると10kΩ経由でGNDに落ちる回路になるので…、この10kΩがコントローラの内部プルアップの抵抗より十分大きかったら(3倍以上とか?)、PAはHと判断される…かな?
①PAを内部プルアップの入力・PCをL出力にして、すぐチェックしてPAがLなら、SW1orSW2が押されてる ②しばらく経ってから再度PAをチェックして、LのままならSW1、Hに変わってたらSW2
というスキャン方法かな…?

(ちなみに「Tucoplex」というネーミングは、飼い猫の名前から付けたらしい。元の「Charlieplexing」も「チャーリーさんの考えたMultiplex回路」というネーミングで、この記事のスタートになったラジオペンチさんのブログでも「意味の分かる名前を付けてくれればいいのに」と苦言を呈されていたけど、まさか飼い猫からとは…w。)

回路として使うかなぁ…。よっぽどぴったり「4LED&4スイッチ」のニーズがある場合じゃないと使わないかも。でもまあ、Charlieplexingのペアの中にLEDとスイッチを混在させるアイディアはおもしろいかも、といった所かな。

ひらめいた!先日の記事「7/28 チャーリープレクシングについての考察(続編1)」で、「8PINマイコンの限界に挑戦!」とか称して、3ポートのCharlieplexingを2つ使って、6LED&6スイッチの回路を作ってみたけど、4ポートでペア組み合わせが6組できる。これを、3つをLED、3つをスイッチに使えば、4ポートで6LED&6スイッチができてしまうじゃないの~?!
4ポートで回路を書いて論理表を付けると、こんな感じ。

Charlieplexはポートを増やすとずんずん操作可能数が増えるので、コンデンサで無理せずとも、n×(n-1)の点数を、LEDとスイッチで好きに割り振れる、と思えば、応用が広がるかも!
(上の回路図では、A-B・A-C・A-DをLED、B-C・B-D・C-Dをswitchに割り振って、Port-Aにのみ電流制限抵抗を入れたが、割り振り方によっては電流制限抵抗の入れ方も変えないといけない。それと、この回路では、switchスキャン時にはAがプルアップ無しのZなので、LEDはどれも点灯しないが、LEDとswitchが混在すると、switchスキャン時のプルアップ有りZでLEDが点いてしまう可能性があるかと…。まあ、switchスキャンの時間はダイナミック点灯の時間と比べてうんと短いので、目に見えない程度かもしれないけど。)

2.GuGaplexing
分かりやすいEDNの日本語記事は「LEDの多重制御で必要なI/O端子数を削減」。
作品例としては「GuGaplexed Valentine LED Heart」が挙げられている。
チャーリープレクシングのLED数を倍にできる回路。基本回路は下記。

真ん中のトランジスタの回路、見た事あります。インバータ回路ですね。
チャーリープレクシングは、逆並列のLEDをペアのポートで挟んで、”01”と”10”の2通りで点灯させるので、nC2×2のLEDが制御できますが、GuGaPlexingでは”01”,”10”,”00”,”11”の4通りで点灯させるため、nC2×4のLEDが制御でき、Charlieplexingの倍になります。
インバータ回路の左側は、Charlieplexingと同じで、”01”と”10”で点灯しますが、”00”にすると、インバータの後ろ側では”10”になってD3が点灯、”11”にすると”01”になってD4が点灯、となります。
どちらかのポートがZの時は不点灯ですが、PAがZだとインバータの出力がVcc÷2程度になる為、その時に”Z0”や”Z1”でD3orD4が点灯しない様に、VccがLEDのVfの2倍より、ある程度余裕をもって低い必要がある。(例えば、Vf=1.8Vの赤色LEDなら、電源電圧は3V以下ぐらいがいいでしょう。)
ただこれは、Charlieplexingでも似たような状況がありますね。

(ちなみにネーミングは、発案者2名:Sarthak Gupta/Dhananjay Gadreの名字の最初を取ったみたいなので、発音は「グガ」で良さそうな気がする。)

LTSpiceで確認すると、

D3にかかる電位差は「1.77V」ですが、3.5mA流れてて、点灯してしまいそうです。電源を3Vまで下げると、電位差1.72V、電流2.1mAまで下がるので、やはり電源電圧は3V位の方が無難そうです。
(※日本語版EDNの説明では、LTSpiceで検証した結果「入力がHi-Zの時のインバータ回路の出力は、広い電源範囲でVcc/2になる」と書いてありますが……、それは、LEDを繋いでないインバータ回路単体の検証ではないかしら…?
上のLTSpiceシミュレーション結果で、PNP-Q2は、Q2→R1→D1→R5の経路でベース電流が流れる為、NPN-Q1よりもベース電流が約6μA多く流れてます。多分その影響で、PR2はVcc/2より少し高くなってます。作品例の「GuGaplexed Valentine LED Heart」のデモ動画でも、関係ないLEDが薄っすら点灯してる事があるみたい。
インバータ回路のベース抵抗を10kΩぐらいまで上げると、計算上では少し緩和するので、トランジスタのHfeに合わせてベース抵抗を調整すれば、なんとかベストが狙えるかも。)

ポート4つに拡張すると、下記の回路になります。

インバータ回路は、ポート数-1の個数が必要です。
どこにどのLED組をぶら下げてどのポートに繋げるかは、逆並列LEDのChalieplexing基本回路と、これをバーLEDの様に1列に並べたときに、上側にどれを繋げるか、下側にどれを繋げるか、を理解すれば、簡単にわかります。上に繋げるLED組だけにインバータを入れます。
4ポートなら、組み合わせはA-B・A-C・A-D、B-C・B-D、C-Dの6通り。Aが上のLED組は3つで、相手はB・C・D。Bが上のLED組は2つで、相手はC・D、Cが上のLED組は1つで、相手はD。Dが上の組は無いので、Dにはインバータは不要、となります。
そして、インバータの後ろにも、同じ組み合わせのLEDをぶら下げれば完成です。

さて、3ポートで12個,4ポートで24個,5ポートで40個…は、なかなかの個数ですが、実際に使うには、追加の部品点数が多すぎる気がする…。まあ、隣国から直輸入のSMD部品を使えば1~2円/個とかなので、インバータ回路1ヶ所10円程度ではあるけど、それでもPICのピン数を増やした方が安くつきそう。
「74HC04みたいなインバータ使えばいいじゃん?(まだその方が安いw)」と思ったけど、そうすると「え?!8PINのIC1個で40個のLEDを独立制御なんて、どうやってるの???」という、電子工作のロマンがなくなるww。
そのロマンと製作欲を満たしたいのでなければ、おとなしくPICのピン数を増やした方が無難だな、という感想~ww。(ただ、作品例の「GuGaplexed Valentine LED Heart」は、ちょっと作ってみたいw。)

3.Chipiplexing
英語版の元記事は「“Chipiplexing” efficiently drives multiple LEDs using few microcontroller ports」。
EDNの日本語記事は「少ないI/Oで多数のLEDを制御、同時点灯も可能」。
Charlieplexingと比べてLEDの個数は増えないが、LEDを同時点灯できる組み合わせができて、ダイナミック点灯時の分割回数が減らせるので、明るさを増やせるとか、ポートの出力電流を減らせるとかのメリットがあるとの事…。

4ポートで表現した回路は下記。(紹介記事は3ポートで書いてあったけど、3ポートだとメリットがほとんど感じられないので…)

ポート”H”の場合は変わらないが、”L”の方はエミッタフォロワで使ったトランジスタでGNDに落ちる為、コントローラの方にはごくわずかな電流しか流れず、LEDの駆動電流はほぼ一定の電圧降下(Vce≒0.7V)でGNDに流される仕組みのよう。
これにより、同時に複数のLEDを点灯しても、明るさが変わらない(という回路らしいw。)

例えばPA~PDを”1011”にすると、D1・D8・D10の3つを同時点灯できる。
”1”を出力してるポートは、それぞれ1個のLEDしか点灯させないので、ポートの負荷は変わらない。
エミッタフォロア回路無しのCharlieplexing回路で同じことをすると、PBに繋がってる電流制限抵抗の電圧降下が大きくなって、LEDの点灯が暗くなってしまうと思われる。
(ポート1個だけ”H”・残り3つを”L”でも複数同時点灯すると思うけど、LEDは暗くなるでしょう。)
結果、N-1個のLEDを同時点灯する事が出来て、ダイナミック点灯の時間を増やせる。
ポート数が多くなるほどメリットが大きくなり、5ポート20LEDの場合、Charlieplexingでは1/20に対し、Chipiplexでは1/5で済む、との事。(ほんとかなぁw、検証はめんどくさいなぁ…w。)

使うかなぁ…。同時に点灯させる場合分けのアルゴリズムが複雑な気がする…(作ってしまえばそうでもないのかもしれないけど)。かなり無理させた回路で、どうしても明るさを稼ぎたい時には役に立つかも…といった所。


さてこれで、長らくかかったCharlieplexingの研究wは、とりあえず終了です。
「このぐらいの事は、元の記事みりゃ分かるわ~」という人もおられるでしょうけど、何事も自分で考えてみるのが大事w。誰かほかの人の為の記事というよりも、自分の勉強の為の記事という事でww。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

8/3 チャーリープレクシングについての考察(続編2)

2019-08-03 | PIC・電子工作
引き続き「チャーリープレクシング」について調べてると、「LED = n×(n-1) + 2n」で「3ポートで12個のLEDを制御する例」という回路を見つけました。
元記事は「Three microcontroller ports drive 12 LEDs(December 15, 2006)」。
日本語版もあるらしいとの事なので探してみたところ「3つのマイコンポートで12個のLEDを駆動 (1/2)」。

テーブルと回路を見比べてみれば、まあ、やりたい事は分からなくもない。
チャーリープレクシングは、2つのポートで逆並列LEDを挟んでHとLを出力、他のポートはHi-Zにして、1つのLEDを狙い撃ちにするけど、1つだけLにして他のラインからVccを供給するか、1つだけHにして他のラインでGNDに落とすかで、チャーリープレクシングでは使えていないポートのTri-Stateの組み合わせを使って、LEDを点灯させるんでしょう。
しかしこの回路、見ただけではちゃんと意図通りに動くか理解できない…。
例えば、D9を点灯させようと「Z-0-Z」にすれば、D9が点きそうな気はする。
しかし、D1を点灯させようと「1-0-Z」にしたときに、D9やD8が点灯しない?

疑問はやってみるしかない!
この回路、左側のチャーリープレクシングの部分を除いた右側、書き換えるとこうなってるのではないかしら。

普通は、ハイサイドのスイッチングをPNP、ローサイドをNPNですると思うのだけど、逆になってる。例えばハイサイドのNPNで言えば、LEDとPNPの状態によってはNPNのVeが上がってVbeが確保できずにIbが流せない→トランジスタOff、といった、2個分のLEDのVfとトランジスタのVbeをうま~くバランスさせるような回路かしら…。

実機を組むのがめんどうだったので、回路シミュレータ「LTSpice」で試してみたけど、うまく行かない…。ポートを1個だけLにすると、狙ったLEDに4μA程度の電流が流れるけど、これじゃあLEDが点灯しない。
「VfとVbeの微妙なバランス」みたいなシミュレートはLTSpiceには無理なのかしら?
止む無くブレッドボードで、上記の右側のみの回路を組んでやってみるけど、やっぱりLED点灯できない。(ちなみにトランジスタは、リード部品で手持ちがあったSS8050とSS8550を使った。)

この回路、VfとVbeやHfeとベース電流等をしっかり調整しないと点灯しないのでは?
という事で「動かないじゃ~ん」と一旦諦めて、ブレッドボードの仮組みも全部撤収した後、つらつらと考え事してたら、「Hfeが低いんじゃ。ならベース電流を上げてやればいい~」と思いついた。

LTSpiceで、上のNPNも下のNPNもバイアス抵抗を1kΩに変更した所、狙ったLEDに点灯する程度の電流が流れるシミュレーションができました~。
ポートBのみLにした計算結果。

D9のみ1.79mA流れて、なんとかD9が点灯するかな。(R1~R3ももっと下げていいかな。)

ポートAをH、BをLにした計算結果。

D1に3mA程度流れて、点いちゃうんじゃないかと思ったD8・D9には10~20μAぐらいしか電流が流れておらず、D1のみが点灯しそう。

一旦片付けちゃってめんどうだけど、もう一回ブレッドボードで組んでみよう。
作業風景はこんな感じ。

右半分だけの回路を組んで、NPNのバイアス抵抗を1k、PNPの方も1k、間の抵抗は5kに変更した結果、ちゃんと「1個だけH、1個だけL」で、狙ったLEDが点灯する様になりました。

しかしまだ、ポートの「1個をH、1個をL」にすると、LEDが2個点灯してしまう…。「やっぱり無理なんじゃ…」と挫けかけたけど、ふと「左半分のチャーリープレクシング部分もセットじゃないといけないのか?」と思い当たり、ブレッドボード上に左半分も組付けて確認。これでちゃんと、一番上の論理表のとおりに点灯する様になりました~!

今回の最終の回路は下記。

これでも、左半分のLEDと比べて、右半分のLEDの点きが暗い。
SS8050とSS8550は、IcMAXが大きい反面、Hfeが低くVceも大きいんじゃなかったかな?
もっと小電流でいいので、Hfeが大きいトランジスタを使って、各抵抗の値を調整すれば、なんとか全部のLEDを同じ明るさにできるかしら…?

とりあえずこの「3つのマイコンポートで12個のLEDを駆動」の回路、一応期待通りに動く事は確認できたけど、ちゃんと動くには、使うトランジスタの特性に合わせた抵抗値調整と、各LEDの明るさ調整のための抵抗値調整とが、かなり面倒そうという事が分かりました。
12個のLEDを点灯させたかったら、チャーリープレクシングのみで4ポート使った方が無難だな~ww。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

7/28 チャーリープレクシングについての考察(続編1)

2019-07-28 | PIC・電子工作
さて先日、福岡から山口に、深夜車で帰りながら、「チャーリープレクシングについての記事を書こう~」と、つらつらと考えていたら、ふと「スイッチ入力にも使えるんじゃないかい?」と思い当たった!

PICは使えるポート数が少なく、ポート数を増やすと値段が高くなってしまう。
PICでポートを節約して入力点数を増やすには「抵抗分圧」という常套手段がある。
しかし、全てのデバイスにアナログ入力がある訳ではない。それに、優秀な定電圧電源を使うならいいけど、「おもちゃ」として応用するには、電池電圧の低下や、モーターが起動する時の電源電圧の変動等も考慮して、あまり無理せず1ポート当たり3点ぐらいに抑えるとか、電源電圧の参照を取るとか、いろいろと不便もありそう。

チャーリープレクシングでのLED点灯の理屈を応用できれば、3ポートで6入力、4ポートで12入力、5ポートで20入力…が実現できる。12個もスイッチがあるおもちゃのマイコン換装をするかどうかは分からないけど、考えておいたらいつか役に立つかも…。

チャーリープレクシングの「ミソ」は、LEDは逆電圧を掛けても点灯しないことを利用して、正負を逆にして個数を2倍にしてる所かも。極性のない電球を使ったのでは、実現できない。
これをスイッチに応用するには、やはり、スイッチに極性を持たせないといけない。つまり、余分にダイオードを入れてやれば、実現するのでは?

具体的に3ポートで書くと、こんな感じ。

プルアップは、マイコン側の内部プルアップを使用する。
使わないポートは入力設定でHi-Z(プルアップ)にしておいて、スキャンの条件は、
SW1検出 : b=0,a=IN → a=0
SW2検出 : a=0,b=IN → b=0
SW3検出 : c=0,b=IN → b=0
SW4検出 : b=0,c=IN → c=0
SW5検出 : c=0,a=IN → a=0
SW6検出 : a=0,c=IN → c=0
これで行けそうな気がする。但し「2個同時押し」といった時にはどうなるか?回路を眺めてても、組み合わせが多くてよく分からないので、実際に組んで試してみよう~!
8PINマイコンで、入力にもLED表示にもチャーリープレクシングを使って、6入力-6LED表示をやってみる!

最初、PICでやってみようと思ったけど、プログラムを作り始める前に、「PICはMCLRと兼用のポートは入力のみ」に制限されてることを思い出した。チャーリープレクシングの為にはTRIS(Tri-State)が全部必要。
14PINのPICに変更してしまったら「8PINマイコンで6入力-6LED表示!」の「限界にチャレンジ!」にならなくなるので、ここは、6ポートの全部を入出力に使えるATtiny13aを使う事にする。

ブレッドボードでの作業状況。

ブレッドボードでの試作は…、あんまり好きじゃないなぁ。考えようによっては学研の「電子ブロック」みたいかもしれないけど、縦が全部繋がってて制約多いし、接続今にも間違えそうだし…。
(実際、接続間違えてトランジスタが「バチッ」と焼けたのが1回、ICが焼けたのが1回あるww。でも、こんな試作にユニバーサル基板を1枚消費したくないww。)

プログラム組んで走らせてみた。案の定一発でうまくいかず、またもや点灯回路を確認するためだけのプログラムに書き換えてみたけど、点灯回路はOK。
ポートを設定した後の電圧安定待ち時間の為に「asm(NOP);」を1個入れてたのを、3個に増やしてもまだダメ。for文で10回ループさせたら、ちゃんと動くようになった。

最終のプログラムは、電圧安定待ち時間には、「delay.h」の「_delay_us」を使って2μs待たせた。LED表示は、スイッチ複数押し時の状態確認のため、ダイナミック表示にしてある。

#define F_CPU 9600000 // 9.6MHz

#include <avr/io.h>
#include <util/delay.h>

#define LED_a PINB0
#define LED_b PINB1
#define LED_c PINB2
#define SW_a PINB3
#define SW_b PINB4
#define SW_c PINB5

void disp_LED(unsigned char disp_data)
{
   DDRB = 0b00000000; // PB0~5を全て入力
   // LED_1
   if ((disp_data & (1 << 0)) != 0 )
   {
      PORTB |= (1 << LED_a); // LED_aをHに
      PORTB &= ~(1 << LED_b); // LED_bをLに
      DDRB |= (1 << LED_a); // LED_aを出力に
      DDRB |= (1 << LED_b); // LED_bを出力に
   }
   _delay_ms(2);
   DDRB = 0b00000000; // PB0~5を全て入力

   // LED_2
   if ((disp_data & (1 << 1)) != 0 ) // LED_bをHに
   {
      PORTB |= (1 << LED_b); // LED_bをHに
      PORTB &= ~(1 << LED_a); // LED_aをLに
      DDRB |= (1 << LED_b); // LED_bを出力に
      DDRB |= (1 << LED_a); // LED_aを出力に
   }
   _delay_ms(2);
   DDRB = 0b00000000; // PB0~5を全て入力

   // LED_3
   if ((disp_data & (1 << 2)) != 0 )
   {
      PORTB |= (1 << LED_b); // LED_bをHに
      PORTB &= ~(1 << LED_c); // LED_aをLに
      DDRB |= (1 << LED_b); // LED_bを出力に
      DDRB |= (1 << LED_c); // LED_cを出力に
   }
   _delay_ms(2);
   DDRB = 0b00000000; // PB0~5を全て入力

   // LED_4
   if ((disp_data & (1 << 3)) != 0 )
   {
      PORTB |= (1 << LED_c); // LED_cをHに
      PORTB &= ~(1 << LED_b); // LED_bをLに
      DDRB |= (1 << LED_c); // LED_cを出力に
      DDRB |= (1 << LED_b); // LED_bを出力に
   }
   _delay_ms(2);
   DDRB = 0b00000000; // PB0~5を全て入力

   // LED_5
   if ((disp_data & (1 << 4)) != 0 )
   {
      PORTB |= (1 << LED_a); // LED_aをHに
      PORTB &= ~(1 << LED_c); // LED_cをLに
      DDRB |= (1 << LED_a); // LED_aを出力に
      DDRB |= (1 << LED_c); // LED_cを出力に
   }
   _delay_ms(2);
   DDRB = 0b00000000; // PB0~5を全て入力

   // LED_6
   if ((disp_data & (1 << 5)) != 0 )
   {
      PORTB |= (1 << LED_c); // LED_cをHに
      PORTB &= ~(1 << LED_a); // LED_aをLに
      DDRB |= (1 << LED_c); // LED_cを出力に
      DDRB |= (1 << LED_a); // LED_aを出力に
   }
   _delay_ms(2);
   DDRB = 0b00000000; // PB0~5を全て入力
}

int main(void)
{
   unsigned char LED_disp; // LED1~6の点灯をセットするための変数:対応ビットの1で点灯

   while (1)
   {

// キー入力スキャン部
      DDRB = 0b00000000; // PB0~5を全て入力
      PORTB = 0b00111000; // PB3~5を内部プルアップ、他はLow出力
      LED_disp = 0x00; // LED_disp初期値としてゼロを代入

      // SW_1
      PORTB = 0b00111000 & ~(1 << SW_b); // SW_bだけLowに
      DDRB = (1 << SW_b); // SW_bだけ出力に
      _delay_us(2);
      if ((PINB & (1 << SW_a)) == 0 ) LED_disp |= 0b00000001;

      // SW_2
      PORTB = 0b00111000 & ~(1 << SW_a); // SW_aだけLowに
      DDRB = (1 << SW_a); // SW_aだけ出力に
      _delay_us(2);
      if ((PINB & (1 << SW_b)) == 0 ) LED_disp |= 0b00000010;

      // SW_3
      PORTB = 0b00111000 & ~(1 << SW_c); // SW_cだけLowに
      DDRB = (1 << SW_c); // SW_cだけ出力に
      _delay_us(2);
      if ((PINB & (1 << SW_b)) == 0 ) LED_disp |= 0b00000100;

      // SW_4
      PORTB = 0b00111000 & ~(1 << SW_b); // SW_bだけLowに
      DDRB = (1 << SW_b); // SW_bだけ出力に
      _delay_us(2);
      if ((PINB & (1 << SW_c)) == 0 ) LED_disp |= 0b00001000;

      // SW_5
      PORTB = 0b00111000 & ~(1 << SW_c); // SW_cだけLowに
      DDRB = (1 << SW_c); // SW_cだけ出力に
      _delay_us(2);
      if ((PINB & (1 << SW_a)) == 0 ) LED_disp |= 0b00010000;

      // SW_6
      PORT = 0b00111000 & ~(1 << SW_a); // SW_aだけLowに
      DDRB = (1 << SW_a); // SW_aだけ出力に
      _delay_us(2);
      if ((PINB & (1 << SW_c)) == 0 ) LED_disp |= 0b00100000;

// LED表示
   disp_LED(LED_disp);
   }
}

(ココのgooブログで、プログラム内の「<」と「>」の入力・表示がうまくいかない…。とりあえず1回は入力・保存できるようになったけど、もう一度編集・保存すると、中身が変わってしまう。問い合わせをしたけど、完全解決しない…。なんとかして~!)
AVRのポート操作は、なんでこんなめんどうなんだろう。調べ直して思い出しながらなんとか出来上がったけど、出来てから見ても暗号みたいww。

これで、1~6まで単独で押して、対応するLEDがちゃんと点灯するのが確認できた。
同時押しは…、期待通りに点灯する組み合わせもあるが、余分なLEDが点いてしまう組み合わせもある…。
1と2、3と4、5と6はOK。1と5はOKだけど、1と6を押すと、4も点いてしまう…など。

実機で組んで、誤判断する組み合わせが分かれば、誤判断の理由も分かる。
LED点灯回路の時に、「LEDを2個通る別の経路があるけど、Vfの関係でそっちは電流が流れても点灯しない」のと同じ状態。
例えば、4を検出するために、「b=0,c=IN」で「C=0」を確認するのだが、1と6をONにしてると、4を直接通る経路ではなく、6→1を経由して2回ダイオードを通る経路が出来てしまって、あたかも4がONしてるかのように、CをLと判断してしまうんですね…。
ダイオードのVf×2でCをLと判断しないようにできないか、電源電圧をLEDが光るギリギリ:2.2Vぐらいまで下げてみても、誤判断は解消できませんでした。
使った信号用のダイオード、電流が低いとVfがかなり低い様です。(LEDも似たような性質とは思いますが。)

結果とすれば、同時押しを考慮しなくていいなら、チャーリープレクシングの理屈で、ポート数:nに対して、n×(n-1)の入力の検出ができそうです。
SW1から順にスキャンしていって、1個ONが検出されたらbreakして残りはスキャンしないようにすれば、同時押しによる誤作動は回避できると思います。(後日:いや、それじゃあ甘いなぁ。もちょっと良く考えなければ…)
アナログ入力による「抵抗分圧」でも、普通は「同時押し」は検知できないので、これでもいいと思いますが、例えば、ペアの1と2、3と4、5と6は、同時押ししても誤判断しないので、同時押しを考慮したい組み合わせに制限を掛ける手もあるかもしれません。

さてこれで、チャーリープレクシングの理屈を応用して、入力点数に対してポート数を減らせる見込みが立ちました。これがいつか役に立つ日が来るか、誰か「役に立った~!」という人が現れるか?
もし、「役に立った~!」という人が居れば、是非コメント下さいww。

(後日:wikiの英語版には、inputへの応用の記事がちゃんとありました。回路は載ってなかったけど、PICを入力&プルアップにして検知する方法も載ってました。まあ何事も、自分でやってみる事に意義があるという事でw。)

(後日2:wiki英語版の「Input data multiplexing」の個所には「スイッチ複数同時押しを考慮しなくていいなら、ダイオード4個で組める。ダイオード12個なら、スイッチとデータは必ず1対1で対応する」と書いてある。
「ダイオード4個で組める」の回路は、多分下記になると思う(検証はしてない)。

しかし「ダイオード12個なら、スイッチとデータは必ず1対1で対応する」は、テストでは実現できなかった…。入力ポートのプルアップには、マイコン内部の「Weak pull-up」を使ったが、もっと強いプルアップで、Lのポートに数mAぐらい流してダイオードのVfを上げるか、元々Vfの高いダイオードを使ったりすれば、実現できるかなぁ…)
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

7/28 断線チェッカー続き~チャーリープレクシングについての考察

2019-07-28 | PIC・電子工作
先日の「断線チェッカー作ってみた」の回路ですが、「ポート4つでLED10個を制御。どんなロジック…?」と思いましたが、「チャーリープレクシング」という回路だそうです。
とりあえず、直近で参照されたのは「ラジオペンチ」さんの記事。以前にちらっと読んだ気はするのですが、難しくて全然記憶に残ってませんでしたw。自分で手を動かしてみないと、見ただけではなかなか理解できない…。より理解を深めるべく、自分で回路書いて考えてみます。

基本の回路は下図。

A~Dの4つの中から2つを取る組み合わせは、LED組の左から順に、A-B・B-C・C-D、A-C・B-D、A-Dの6通り。
式で書くと、4C2=(4×3)÷2=6。
このポート組の間に、逆並列のLEDを挟んで点灯させるので、12個のLEDが制御できる。
式で書くと、4C2×2=(4×3)÷2×2=12。
結果、使うポート数をnとすれば、n×(n-1)個のLEDが制御でき、3ポートで6個、4ポートで12個、5ポートで20個、6ポートで30個…と、普通のマトリックスを使うより少ないポート数で、多くのLEDの点灯が制御できます。
難点としては、例えば8×7のマトリックスだと、列ごとに点灯を制御するので、7分の1(又は8分の1)のダイナミック点灯で出来ますが、チャーリープレクシングでは1個づつの点灯になるので、56分の1のダイナミック点灯となり、制御も煩雑、という事があると思います。

さて、ラジオンペンチさんの記事からは、居酒屋ガレージさんの「電波チェッカ用12LEDレベル表示回路」という記事が参照されてますが、そちらに書いてある回路は、LEDの電流制限抵抗を1回しか通らない回路です。この回路と、元の「逆並列LED」の回路は同じ物でしょうか…?
理解してみれば、記事内の「LEDは対向させずに、カソード側をコモンにしてつないでみました」で理解しろよ~という事かもしれませんが、自分なりに解釈して回路を書いてみます。

上の回路にて、各ダイオードのアノードに着目すると、Aからアノードに繋がってるLEDは3つあります。同様に、BもCもDも、アノードに繋がってるLEDが3つずつあります。
例えば、Cについて見ると、下図の通り。

という事は、LED:12個を、「アノードに繋がってるLED」でまとめると、

となります。

この下がどうなるか、最初「基本回路①」のLEDに番号を振って対応させようとしましたが、組み合わせを理解すれば簡単な事。
Aの下にはB・C・D、Bの下にはA・C・D、Cの下にはA・B・D、Dの下にはA・B・Cが繋がります。
これを回路として書くと、

となり、LEDを同じ向きで並べた回路の完成です。
各ポートの出力の、分岐の前に電流制限抵抗を変更すれば、「基本回路①」と同様に、抵抗を2回通る回路になります。
ここでひらめいた!「逆並列」の基本回路①では、A-BとB-Aを区別せずに、4C2×2と捉えましたが、LEDを同じ方向に表現すると、A-BとB-Aを区別して、順列「4P2=4×3=12」で表現した事になるのではないかと思います。

ラジオペンチさんの記事では、これを「マトリックス形式」に変形してますが、ここも自分で考えてみます。
同様に「アノードに繋がってるLED」を意識して書くと、下図のようになります。

各ポートからの出力を横共通線として、アノードに繋がるLEDが3つずつ付いてます。そして、「LEDを同じ向きで並べた回路」と同様に、今度は縦線を共通線として、「Aの下にはB・C・D、Bの下にはA・C・D、Cの下にはA・B・D、Dの下にはA・B・C」が繋がります。
見ても同じかどうか判別できませんが、きっと同じ回路ですw。

このマトリックスをよ~~~く見てると、あるものに似てるのに気が付いた!
スポーツ大会等で見る、リーグ戦の「対戦表」です。

4チームの中から2つを選ぶ対戦の組み合わせは6通りで、6試合となりますが、①の試合はAチームvsBチームで、①’は①と同じ試合ですが、BチームvsAチームとなって、①をひっくり返した結果になります。
つまり、マトリックス形式で書いた場合、右上半分と左下半分は、アノードとカソードをひっくり返した関係にあるという事ですね~。

ラジオペンチさんの記事では、マトリックスの隙間をつぶす為、右上半分のLEDをひっくり返した回路を紹介したのち、「SparkFun」のLEDマトリックスの回路を紹介していますが、上図の「マトリックス①」の右上半分を、そのまま「むぎゅ~~~」っと左に詰めると、下記の様な回路になります。

SparkFunの回路は、右上半分のLED群を下に詰めて、ポートとの接続が上側に出てますが、「アノードで整理」をスタートにすると、このような書き方に辿り着きました。

ラジオペンチさんの記事では、さらに「ikkeiさん」という方の記事が紹介されており、7セグLEDの点灯をチャーリープレクシングでポート数を減らす回路や、8×8LEDマトリックスの制御ポートを減らす回路が紹介されており、これまっっった難しいのですが、とりあえず、基本は理解できたかな~w。
(「チャーリープレクシングについての考察(続編)」に続くww。)
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする