チャンネルデバイダーのVR制御(構想編6)

f:id:torusanada98:20180623213809j:plain

構想編6

表示処理で残ったミュート表示を構想します。

ミュート仕様

ミュート状態には以下の2つの動作で入る事にします。

①ボリュームミニマム(ATTstate=0)時(ATT表示は-36dB)

②通常状態時(mute=0 and ATTstate!=0)にミュートボタンを押す

 但し、ATTstate=1の時はATTstate=0,mute=0としてミュート状態とする

ミュート状態解除は以下の3つの動作時とします。

①ボリュームミニマム時にUpボタンを押す(ATTstateは0→1)

②ミュート状態(mute=1)時にミュートボタンを押して通常状態とする

③ボリュームミニマム時にミュートボタンを押す(ATTstateを0→1)

ミュート状態時もUp/Downボタンを有効として、ATTstateの変更を許可します。とまとめてみたものの、少し複雑な仕様なのでちゃんと実装できるか心配です。

ミュート表示

いろいろ考えてみましたが、回路がシンプルになることから、ミュート状態でATT表示をブリンクさせる事としました。表示モジュールにブリンクの機能があれば処理も簡単に実装できますが、残念ながらありません。仕方がないので表示の点滅を表示の明るさコマンドを使って、またブリンクのタイミングもソフトで実現させる事にします。

ブリンク表示

ブリンク表示のソフト処理は、タイマー割り込みを使うとシンプルに実装できます。そこでArduinoのタイマー割り込みについて調べてみました。ArduinoUNOのAVRマイコンには、ハードウェアタイマーが3個(Timer0, Timer1, Timer2)あり、それらを使ってTimer系の関数を実現しているとの事です。それぞれのTimerは以下のとおり利用されています。

・Timer0

8bitタイマーでdelay(), millis(), micros()と5,6ピンのPWMで使用されます。

・Timer1

16bitタイマーでServoライブラリと9,10ピンのPWMで使用されます。

・Timer2

8bitタイマーでtone()と3,11ピンのPWMで使用されます。

今回の処理では、Timer0以外の機能は使用していないので、Timer1とTimer2を流用する事ができます。標準の状態では、これらを流用できませんが、便利なライブラリがありました。MsTimer2です。これはTimer2を使ってタイマー割り込み機能を提供するものです。このライブラリで提供される関数は以下のとおりです。

f:id:torusanada98:20180623213845p:plain

これらの関数を使って割り込みによる7セグの点滅動作を実装します。

MsTimer2の利用

まずはじめに「MsTimer2.zip」をArduino Playgroundからダウンロードします。

f:id:torusanada98:20180623213955j:plain

コンソールから「スケッチ」→「ライブラリをインクルード」→「.zip形式のライブラリをインクルード」をクリックしてダウンロードしたファイルを選択します。

f:id:torusanada98:20180623214052j:plain

この状態でスケッチの先頭でMsTimer2.hをインクルードすれば提供される関数が利用できるようになります。使い方はいたって簡単で、MsTimer2::set(ms, void(*f)())で割り込み処理を宣言し、MsTimer2::start()で、割り込み処理が有効となります。割り込み処理自体はvoid(*f)()で記述します。割り込み処理を一時的に無効とする場合は、MsTimer2::stop()関数を使用します。さっそく処理を追加してみます。ミュートボタンのオン確定時に、適切なミュート状態遷移処理を追加します。ミュートボタンを押したときの処理を整理します。

1)ATTstate=1の場合、ATTstate=0 and MUTE=0

2)ATTstate=0の場合、ATTstate=1 and MUTE=0

3)ATTstateが0と1以外でMUTE=0の場合、MUTE=1

4)ATTstateが0と1以外でMUTE=1の場合、MUTE=0

上記の設定により、割り込み処理内で適切な処理(ブリンクオンorオフ処理等)を行います。割り込み処理を整理すると以下となります。

①MUTE=0 and ATTstate!=0の場合、そのままreturn

②MUTE=1 or ATTstate=0でdim=1の場合dim=0, 表示消灯してreturn

③MUTE=1 or ATTstate=0でdim=0の場合dim=1, 表示点灯してreturn

ここで、dimは7セグの点灯状態を表し、dim=1で点灯を意味します。コーディングは上記のとおり仕様が明確になっていたので、それほど苦労しませんでした。

ミュートデバッグ

最初はMsTimer2の割り込み許可の記述を間違えて(startの後の括弧を忘れた)、割り込みが有効となっていませんでしたが、その時のキー操作による状態遷移は正しく動作していました。当然の事ながらミュート状態でも表示はブリンクしません。すぐに記述間違いに気づき、修正したところ、プログラムの動作がすぐに止まってしまいます。1度目のMsTimer2割り込み処理の途中で止まっているようです。散々ソースを確認しましたが、ミスは見つかりませんでした。もしやwire.hでtimer2を使っていないかと、ネット検索してみたところwire.hでtimer2は使っていませんでしたが、2つのライブラリを同時に使用する場合に注意が必要な事がわかりました。wire.hライブラリでも割り込み処理が使用されていますが、MsTimer2の割り込み処理では、他の割り込みが禁止されるため、wire.hライブラリが正しく動作しなくなるとの事でした。対策としては、MsTimer2の割り込み処理の先頭でsei()関数をコールし、MsTimer2割り込み処理内でも他の優先度の高い割り込み処理を許可することで、対策する事ができました。下記がデバッグ時の画面です。

f:id:torusanada98:20180623214310p:plain

この割り込み許可による対策は、文章で書くと1行ですが、この対策を見つけるためにそこそこ消耗してしまいました。単純な事でも気づくかどうかが勝負のプログラムデバッグの怖い点です。アイキャッチ写真では目立ちませんが、dim=0の時もうっすら点灯しています。それでも点滅に見えるので機能上は問題ありません。次回は最後に残ったリレー駆動ブロックを構想します。

 

つづく(構想編7)