この後パターンが裏焼きだったことが発覚! |
前回の投稿からのつづきです
プログラムの作成と公開
プログラムは C で書いて、MPLABX 上の xc8 コンパイラで処理しました。
ソースは github に置いておこうと思ったのですが、どのファイルを配布すればよいのかという点でつまづきました。
MCC を使うと I/O やチップの設定ファイルがいくつもできてしまうのです。MCC を使わないときは、設定と手順のすべてを main.c に書いて、テキストファイルでも貼っておけばよかったのですが、どうもそうもいかないようです。
あちこち調べてみた結果、 gitignore.io で MPLABX 向けの .gitignore ファイルを取得できたのでこれを使い、プロジェクトフォルダごとアップロードすることにしました。
https://github.com/hiromiura/led_dice
にプロジェクトファイルを置きました。ダウンロードしてMPLABXに読み込むことができると思います。
プログラムの動作
SW1は片方をMCLRピンに、他方をGNDに接続しているため、押下するとLOレベルとなってシステムにリセットがかかり、プログラムを先頭から実行します。
サイコロの目は乱数を発生させて得た値を、点灯パターンを格納してある配列の引数として使い、このパターンに基づいて出力ピン(RA0,1,4,5)をオンオフしLEDを点滅させています。
圧電スピーカはPWM出力ピン P1A (5番ピン)に接続し、目が変化する時と、目が確定したときに音が出るようにプログラムしてあります。
目が確定した後、約3秒で自動的に電源がオフに(スリープモードに)なるようにしています。再起動は前述のとおりMCLRリセットです。
乱数の発生で困った
C言語の乱数は疑似乱数のため、リセットの都度、異なったランダムシードを与えてやらないといつも同じパターンの目が出てしまいます。常時電源が入っているような場合は、内蔵タイマ TMR0 の値をシードにしてやることができますが、今回は起動=リセットのため、シードの与え方を工夫する必要がありました。
未使用のアナログピンがあれば、ピンを浮かせておいて得られたノイズ値をシードとすることができますが、今回はすべてのピンを出力で使ってしまっています。
はじめ、圧電スピーカがつながっている P1A を、リセット直後だけアナログ入力 AN2 に切り替え、読み込んだ値をシードにしてみたのですが、偏った値が出ることが多くサイコロとしては不適であることがわかりました。
いろいろ調べた結果、PICのEEPROM領域に乱数表を書き込んでおいて、これを順次シードとして使っていくアイデアがあることがわかりました。とはいえ、乱数表を順に読むだけでは結局一定のパターンがサイクリックに表れることになるため、これは不採用としました。
最終的に採用したのは、実行時に発生させた乱数をひとつ、EEPROMに記録しておいて、次回の起動時には、この値を読み出してシードとする方法です。おおむね均等に目が出るようになったと思います。
これで完成としました。小中学生向けの工作教室で提供する予定です。
(この項終わり)
0 件のコメント:
コメントを投稿