■ジョグ/シャトルをマイコンにつなぐ
ジョグシャトルをマイコンなどに接続するためには、ジョグ/シャトルから送られてくる信号を適切に処理し、回転やモードを検出する必要があります。ジョグ/シャトルコントローラに5V電源を供給すると、2相パルス、モード、センターのデジタル信号(0Vと約5V、要プルアップ)が得られます。
・2相パルス
1回転で24サイクル、各相は90度ずれている。
・モード
ジョグ時にH、シャトル時にL。
・センター
シャトルセンター時にH、それ以外でL。ジョグ時はH。
これらの信号をマイコンで適当に処理すると、ジョグ/シャトルの動作をプログラムで検出することができます。まず、回転を検出する処理を考えます。
■回転の検出
まず2相パルス信号から回転を検出する方法を考えます。この時、回転方向も調べなければなりません。位相のずれた2相パルスを生成するのは、回転方向を調べるためです。ここでは2本の信号をΦ1とΦ2とします。
基本的な考え方は以下のようになります。
・Φ1を回転パルスの基準とする。Φ1の信号がLからHに変化した時(ポジティブエッジ)に、ツマミがまわされたと判断する。ツマミには24のスリットを持つ羽根車がつながっているので、ツマミ1回転で、15度おきに、24回のポジティブエッジが発生する。
・Φ1がLからHに変化した時のΦ2の状態を、回転方向とする。
これだけでいいの?って感じですが、これでいいのです。図は位相が90度ずれた2つのクロックです。ツマミの回転に応じて、波形上の位置が左から右に移動していきます。この時、Φ1がLからHに変わるとき、Φ2は必ずHです。

赤い上向きの矢印がΦ1のポジティブエッジで、この時のΦ2の値を回転方向と判断します。つまりこの回転方向はロジックレベルHとなります。
ジョグを逆回しすると、Φ1とΦ2の位相がずれ、次の図のようになります。

逆に回すとΦ1とΦ2のタイミングが変わり、Φ1がLからHに変わるとき、Φ2はLになっています。
つまり、Φ1のポジティブエッジのタイミングでのΦ2の値は、回転方向を示すのです。下の図は、途中で回転方向を変えたときに、波形がどのようになるかを示しています。オレンジの線のタイミングで回転方向を変えています。

これで、回転と方向の検出ができます。しかしこのやり方では、ツマミ1回転で24ステップしか情報が得られません。もう少し細かく欲しい場合はどうすればいいでしょうか? 前の方法では、Φ1のポジティブエッジに着目しましたが、それに加えて、Φ1がHからLに変わる時(ネガティブエッジ)も考えれば、倍の48ステップにできます。回転方向の判定はちょっと複雑になり、ポジティブエッジの時とネガティブエッジの時では、同じ方向にまわっていても、その時のΦ2の値は逆になります。まぁ、この辺は後で考えます。

Φ1のポジティブ、ネガティブエッジの間で、Φ2の信号も変化しています。これも回転を検出するタイミングとして使えます。この場合、Φ2のエッジをタイミングとし、その時のΦ1の値を方向とすればいいのです。こうすればさらに倍の96ステップになります。

ただこのやり方は、方向判定がさらに複雑になります。Φ1とΦ2のそれぞれのポジティブ、ネガティブエッジを回転検出のタイミングとし、その時の他方の信号の状態によって方向を判断するというのは、まぁプログラムで条件判断や論理式をごりごり書けばどうにかなりますが、もう少しすっきりさせましょう。
Φ1とΦ2の値は、Hを1、Lを0とすると、プログラムから見たとき、以下の組み合わせのどれかとなります。
Φ1 Φ2
0 0
0 1
1 1
1 0
この4通りだけです。つまみを一方向に回した時、Φ1とΦ2はこのように変化します。0から3までの2進数とはちょっと違いますが、とりあえず2ビットで4通りの組み合わせです。
このような変化パターンをグレイコードといいます。いかなる変化の場合であっても、1ビットしか変化しない(ハミング距離が1)という特徴があります。
ある時点でのΦ1とΦ2の状態は、2ビットのデータとして表せます。その後のΦ1とΦ2の状態も同じように2ビットで表せます。つまりΦ1とΦ2の変化のパターンは、4ビットの組み合わせ、16通りしかないのです。この程度だったら、if-elseをいくつも組み合わせて判断したり、論理演算で考えるより、テーブルにまとめてしまったほうが簡単です。
この状態変化を表すのは、4ビットの添え字、つまり16要素の配列で済みます。上位2ビットが以前の状態、下位2ビットを新しい状態でとします。この添え字で示される配列要素の値は、その添え字で表される変化パターンの意味、つまり正回転、逆回転などを示します。
16要素で4ビットの全組み合わせがあるので、この中には状態が変化していない組み合わせ、つまり以前の状態と現在の状態が同じものも含まれています。これは動きがなかったとみなすことができます。また前述したビット変化のパターンには、2ビットが同時に変化するという組み合わせはありません。例えば00から11に変化することはなく、00からだと必ず01か10になります。もし00から11になったとすると、途中の01か10を読み損ねた可能性があります。これらも考えると、パターン変化の組み合わせは、不動、正回転、逆回転、読み取りミスの4種類となります。
Φ1とΦ2の変化パターン(2進数)を添え字とし、そのパターンに応じた動作を定数kRotNotMove、kRotFwd、kRotRev、kRotMissとした場合、変化パターンのテーブルを構成する配列は以下のようになります。
enum {
kRotNotMove = 0,
kRotFwd,
kRotRev,
kRotMiss
};
const unsigned char jsPhPat[16] = {
kRotNotMove, // 00 -> 00 Not move
kRotFwd, // 00 -> 01 +
kRotRev, // 00 -> 10 -
kRotMiss, // 00 -> 11 Miss
kRotRev, // 01 -> 00 -
kRotNotMove, // 01 -> 01 Not move
kRotMiss, // 01 -> 10 Miss
kRotFwd, // 01 -> 11 +
kRotFwd, // 10 -> 00 +
kRotMiss, // 10 -> 01 Miss
kRotNotMove, // 10 -> 10 Not move
kRotRev, // 10 -> 11 -
kRotMiss, // 11 -> 00 Miss
kRotRev, // 11 -> 01 -
kRotFwd, // 11 -> 10 +
kRotNotMove // 11 -> 11 Not move
};
たとえば以前の状態が01で、それが11に変化した場合、添え字は0111(7)となり、正回転で1ステップ進んだことになります。
Φ1とΦ2が接続された2ビットのポートを繰り返し読み出し、1回前の読み出しデータを保存しておけば、次のようなコード(ループの内部)で回転パルスの検出と方向判定を行うことができます。
unsigned char t;
unsigned char pat;
unsigned char action;
t = GetClk(); // 現在のΦ1とΦ2を2ビットデータとして読み込み
pat = (prev << 2) | t; // 以前の状態と組み合わせて添え字を算出
action = jsPhPat[pat]; // 添え字から動作を判定
prev = t; // 次に使うために現在の値を保存
switch (action) {
case kRotFed: // 正回転
// 正回転の処理
break;
case kRotRev: // 逆回転
// 逆回転の処理
break;
case kRotNotMove: // 移動せず(何もしない)
break;
case kRotMiss: // 読み取りミス
// 必要に応じてエラー処理
}
ジョグモードであれば、正回転と逆回転はステップ送りの処理を行い、シャトルモードであれば、シャトルのポジションを示す変数を更新する(そしてプログラムのどこかでその値を参照する)ことになるでしょう。
次は、ジョグモードとシャトルモードの切り替えについて考えます。
【電子工作の最新記事】