せっかく動作用の回路にフルカラーのLEDを実装しているのに、今回の練習で使っているプログラムは、やっていることはRGBすべてを点灯するか消灯する、要するに白黒するだけのプログラムだった。これではフルカラーLEDの立つ瀬がないので、せめて「色をつけてピカピカ」ぐらいしてあげたい。では、どうすればいいだろうか?
「乱数で色を決定する」といいたいところだが、「コンピュータで乱数を作る」というテーマだけで論文が1つ書けてしまうぐらい厄介なシロモノ(プログラムの説明も面倒)で、これだけで工作教室夏春分合わせても足りないぐらい。
実のところ、点滅のサイクルを早くしてRGBを順番に光らせるだけで、それなりの感じになる。つまりGPIOのGP0からGP2の3ビット分の点灯(オン=1)と消灯(オフ=0)を、3ピット分まとめた数値「1」(ビットでいうと001)から「7」(同じく111)で光らせるとよい。3ビットだから「0」(同000)もあるでしょ?、と言われそうなので補足しておくが、「0」では黒、つまり光らないので、これが入ると周期的に値を変更しているのがバレてしまう。
メインルーチンを書き換えて、まっとうなプログラムにすると以下のようになるだろう。LED用のワークレジスタを用意して、それをインクリメントし、「8」だったら「1」に戻す。先のプログラムを改変するとこうなる。以下、最初のテストプログラムから変更部分のみ記載する。
初期化ルーチンに2行追加してあるが、これが内蔵オシレータの補正値を使うためのプログラムだ(詳しくはデータシートのセクション9.2.5.1とEXAMPLE9-1を参照)。
メインルーチンではちょっと変なテクニックを使っている。それが「8」だったら「1」に戻すというところで、実際には必要な下位3ビットだけ「AND」を行い、その結果が「0」ならZフラグが立つので、これをBTFSC命令でチェックし、「0」ならさらに+1、つまり「1」になるわけだ。
PICの命令はともかくシンプルだが、こんな妙なところもあるので注意したい。さて、ここまでできたらシミュレータでGPIOをモニタしながらanimation実行するとGPIOの値が「1」から「7」の間で書き換わっているのが分かるだろう。
今回のサンプルのように小さいプログラムには不要なのだが、一応例題として最適化ということも考えてみたい。
PICの命令は種類が少ないので、実行の効率が上がるように作り変えるのはなかなか難しい。そのなかでもPICプログラミングで「壁」となるのが「RAMが少ない」という点だ。RAMと言ってもワークレジスタなので、ちょっと複雑なことをさせるとワークレジスタ不足に陥るのだ。
プログラムをジーっと眺めているとLEDのデータをワークレジスタで用意しているが、別にGPIOというシステムレジスタに書き込んでも問題ないし、レジスタ間のコピー命令がいらなくなるので、その分シンプルに仕上がる。
PIC用命令のちょっとヘンな点として、汎用レジスタを1つ足す(もしくは引く)という命令があるのにアキュムレータにはこの命令がないことが挙げられる。
だが、任意の数を足すADDLW命令があり、これで「1を足す」とすればいい。実行時間も命令数も同じなので実用上の問題はない。
プログラミングの世界では手作業での最適化というのは効率は上がるが、実際にはさまざまな条件を考えなければならず、もし業務として取り組む場合は非効率になる。
しかし「個人的な勉強」ならば、さまざまなケースを想定して試してみることも重要だ。より効率のよい(これには「命令数を減らす」というのと、「実行時間を減らす」という2つの方向性がある)コードを可能にする方法を考えてみるとよいだろう。
さて、この路線に沿って、サンプルプログラムの最適化をもうちょっと考えると
と、条件分岐つきインクリメント命令INCFSZを使うことで命令数を半減できるかもしれない。GP3が入力専門で読み出しが常に0になることを利用してみる、と期待したが、デバッガで見るとダメであることが判明(フラグ判定はインクリメントしたデータを利用するので当たり前なのだが)。
ここで、動作が確認できたら、時間待ちのサブルーチン(今まで使ってきたサンプルプログラムからコピペする)を加えて完成だ。ただし、実際にLEDを光らせてみると分かるが、待ち時間が1秒程度だと周期的に光っているのがばれてしまう。この改善のために、短い時間待ちループにするとよいだろう。
時間待ちループのパラメータを以下に用意しておくので、適宜変更して使ってみよう。表の見方だが、左が待ち時間で真ん中の3つがCOUNT1、2、3のそれぞれに与える初期値、最後はルーチン終了の前に入れるNOPの数だ。これらの値はこの3重ループでの最適値なので、そのまま流用するとよい。
COUNT | 1 | 2 | 3 | NOP |
1000ms | A7 | 8 | F8 | 1 |
500ms | 23 | BD | 25 | 0 |
300ms | 29 | 47 | 21 | 0 |
100ms | 1A | 11 | 4A | 1 |
実は「ボーっと光らせる」とか、「ランダムで光らせる」など色々なパターンを考えていたのだが4回連載という話なのでここでいったん終了する。PICのプログラムとしては初歩の初歩だが、実際にモノを作らなくてもシミュレータで試行錯誤するだけでも遊べるというのが理解していただけると幸いだ。
要望が多ければ別の題材をテーマにもう1歩深く突っ込んだPIC講座をお届けできるだろう。「こんなものを作ってほしい」という要望があればぜひ編集部までアイディアを寄せてほしい(メカトロで遊ぼう!は企画中でテストプログラムも書きだしていたりする)。
Copyright © ITmedia, Inc. All Rights Reserved.