連載の前半ではハードを中心に説明しました。
後半はソフトウェアを説明していきます。
第4回は「パッ」と点いて「ジワーッ」と消えていく動作をマイコンで実現している方法を説明します。
●メイン・プログラムと周期割り込み
光り方やタイミングはメイン・プログラムで作成しています。また、一定周期で割り込みを発生させ、その中でPWMの出力、タイミング用の基本時間を作成します。その橋渡しは変数を使います。
メイン・プログラムで明るさを算出したときはledという変数に格納しておけば、割り込みで勝手に出力してくれます。また、割り込みではtimecという変数を調べ、0より上のときに-1しています。メイン・プログラムではtimecに数値を格納しておいて0になるのを待つことでウェイトを作ることができるのです。
●光り方はノコギリ波
「パッ」と点くときは、明るさに127をセットし、約10msごとに一つずつ減らしていけば約1.2秒かけて「ジワーッ」と消えていきます。その後ランダムな時間消灯させます。実際には、約10msごとに1ずつ加算されるcondという変数を基準にし、ランダムな消灯時間をtermという変数に格納します。termの値は256~511(時間にして約2.5~5.2秒)の範囲です。この二つの変数から、下記のルールで繰り返すことで一連の光り方を実現しています。

●明るさの分解能は32段階
実際は後述する理由から明るさは32段階です。人間の目にはこの程度の分解能でも段階的な変化には見えないものです。0~127の128段階を32段階に減らすには右2シフトして1/4にします。式は((128-cond)>>2)となります。
●マイコンで時間を計数する
時間計数にはタイマ・モジュールを使います。今回のPICでは3個あるタイマのうちTimer0だけを使用し、オーバフローしたところで割り込みを発生させ、定期イベントを起こします。
具体的には原振が8MHzの場合、主クロックは2MHz、その1/2のクロックをタイマに入力します。256カウントで割り込みが入るので、その周期は256μsということになります。メイン・プログラムではこの周期を40カウントした10.24msで上記ノコギリ波作成などのタイミングを作り、それをさらに8437500 カウントして24時間を計測します。
割り込みの中では、メイン・プログラムから橋渡し変数ledに書き込まれた明るさ数値をPWMとして出力しています。
●PWM信号を発生させる
アナログ回路のノコギリ波とコンパレータの組み合わせと同じことを割り込みごとにソフトウェアで行います。一回の割り込みで+1ずつ増えるscancという変数を用意します。scancは32になると0に戻します。これがノコギリ波の役割をしています。毎回明るさ変数とscancを比較して明るさが大きければ出力をHigh、以下ならばLowにセットします。PWMの周期は割り込み32回分なので、256μs×32で8.192ms(8MHzクロックの場合)となります。

この周期の選定ですが、一般的にはちらつきを防ぐには30ms以内の周期にします。そのために分解能は30ms/256μs=117以下となりますが、シフトに適する117以下の2の倍数は64です。今回の作品は離れた距離から観るため、ちょっと視線を動かしただけでちらつく可能性が大きいので、もう一段階周期を短くして32としました。このため分解能が犠牲になりました。
次回は、実際のマイコンのプログラムの流れとポイントを説明します。
光り方やタイミングはメイン・プログラムで作成しています。また、一定周期で割り込みを発生させ、その中でPWMの出力、タイミング用の基本時間を作成します。その橋渡しは変数を使います。
メイン・プログラムで明るさを算出したときはledという変数に格納しておけば、割り込みで勝手に出力してくれます。また、割り込みではtimecという変数を調べ、0より上のときに-1しています。メイン・プログラムではtimecに数値を格納しておいて0になるのを待つことでウェイトを作ることができるのです。
●光り方はノコギリ波
「パッ」と点くときは、明るさに127をセットし、約10msごとに一つずつ減らしていけば約1.2秒かけて「ジワーッ」と消えていきます。その後ランダムな時間消灯させます。実際には、約10msごとに1ずつ加算されるcondという変数を基準にし、ランダムな消灯時間をtermという変数に格納します。termの値は256~511(時間にして約2.5~5.2秒)の範囲です。この二つの変数から、下記のルールで繰り返すことで一連の光り方を実現しています。
ルール
condが128未満の時は(128-cond)を明るさ出力にセットする。
condが128以上のときは、明るさは0にして、termと比較しterm未満の場合は何もしない。term以上になったら、condをゼロにして、明るさを127にセットし、termを再計算して次のランダムな消灯時間を決めておきます。
ノコギリ波プログラム
これをさらに、8個分をループさせて全部を制御します。●明るさの分解能は32段階
実際は後述する理由から明るさは32段階です。人間の目にはこの程度の分解能でも段階的な変化には見えないものです。0~127の128段階を32段階に減らすには右2シフトして1/4にします。式は((128-cond)>>2)となります。
●マイコンで時間を計数する
時間計数にはタイマ・モジュールを使います。今回のPICでは3個あるタイマのうちTimer0だけを使用し、オーバフローしたところで割り込みを発生させ、定期イベントを起こします。
具体的には原振が8MHzの場合、主クロックは2MHz、その1/2のクロックをタイマに入力します。256カウントで割り込みが入るので、その周期は256μsということになります。メイン・プログラムではこの周期を40カウントした10.24msで上記ノコギリ波作成などのタイミングを作り、それをさらに8437500 カウントして24時間を計測します。
割り込みの中では、メイン・プログラムから橋渡し変数ledに書き込まれた明るさ数値をPWMとして出力しています。
●PWM信号を発生させる
アナログ回路のノコギリ波とコンパレータの組み合わせと同じことを割り込みごとにソフトウェアで行います。一回の割り込みで+1ずつ増えるscancという変数を用意します。scancは32になると0に戻します。これがノコギリ波の役割をしています。毎回明るさ変数とscancを比較して明るさが大きければ出力をHigh、以下ならばLowにセットします。PWMの周期は割り込み32回分なので、256μs×32で8.192ms(8MHzクロックの場合)となります。
PWM説明
この周期の選定ですが、一般的にはちらつきを防ぐには30ms以内の周期にします。そのために分解能は30ms/256μs=117以下となりますが、シフトに適する117以下の2の倍数は64です。今回の作品は離れた距離から観るため、ちょっと視線を動かしただけでちらつく可能性が大きいので、もう一段階周期を短くして32としました。このため分解能が犠牲になりました。
次回は、実際のマイコンのプログラムの流れとポイントを説明します。
<高野慶一>
