2017年07月02日

ジョグシャトルで遊ぶ その3


 今回は、ジョグモードとシャトルモードの切り替えの説明と、Arduinoで動くサンプルプログラムを示します。

arduino.JPG

■ジョグとシャトルの切り替え

 ツマミを上から押すことで、ノック式ボールペンのような機構的な仕組みによりジョグモードとシャトルモードが切り替わります。この変化は、軸の上下を検出するフォトインタラプタから得られるモード信号を調べることで検出できます。
 これとは別に、シャトルモードで使うための、シャトルセンター位置を示す信号があります。これは羽が1枚だけ付いた回転する板が、シャトルのセンター位置の時に、フォトインタラプタの光を遮るという形で信号を生成します。
 この部品はシャトルモードの時はツマミ軸に噛み合って回転し、回転範囲を制限し、クリック位置を定めます。ジョグモードの時は軸から切り離され、スプリングでセンター位置に移動します。したがって、ジョグモードからシャトルモードに移行した時は、常にセンター位置から始まることになります。
 このような機械的な動作に合わせて、プログラムを作ります。動作は次のようになります。

・シャトルモードでは、回転パルスによってnShuttle変数を増減させる。
・センター信号の検出で、nShuttle変数を0にリセットする。
・ジョグモードでは、回転パルスによってJogFwd()関数かJogRev()関数を呼び出す。
・シャトルモードに移行した時は、センター信号を検出してから動作を始める。
・ジョグモードに切り替えた直後は、ツマミの回転検出を一定時間行わない(切り替え時に意図しない移動をしないようにするため)。


 これを実現するために、ジョグ/シャトルのモードの状態は、過渡的なものも含めて以下のようになります。

・状態1: ジョグモードに移行(回転検出を行わない)
・状態2: ジョグモード(回転検出を行う)
・状態3: シャトルモードに移行(センター未確認)
・状態4: シャトルモード(センター確認済み、回転検出を行う)

 これらの状態は、時間経過やジョグ/シャトルの動作によって別の状態に移動します。定常状態は状態2状態4で、ここでは回転の検出を行い、そして必要に応じて、状態2ではJogFwd()関数かJogRev()関数の呼び出しを行い、状態4ではnShuttleの更新を行います。
 状態1から状態2へは時間経過で、状態3から状態4はセンター検出で移行します。またすべての状態において、モード切替の検出を行います。

state.jpg

 状態は以下の定数で表します。


enum {
JsJogOn = 0, // シャトルからジョグに移行
kJsJog, // 現在、ジョグモードである
kJsShOn, // ジョグからシャトルに移行(センター未確定)
kJsSh // 現在、シャトルモードである(センター確定)
};


 状態はグローバル変数jsModeに保持し、この値で場合分けして、各状態での処理、別の状態への遷移を行います。kJsJogOnkJsShOnは過渡的な状態を示すもので、実際のジョグ動作はkJsJog状態で、シャトル動作はkJsSh状態で処理を行います。
 状態の遷移は、モード信号(GetMode()関数)でジョグモード(kJsJogOn)かシャトルモード(kJsShOn)かを判定します。シャトルモードに移行した場合、その後、センター位置をGetCenter()関数で判断してkJsShに遷移します。
 ジョグモード(kJsJogOn)に遷移した時は、ツマミを押す操作で多少ツマミが回転してしまうため、それをカウントしないように500ミリ秒ほど待機してから、実際にジョグ操作を行う状態(kJsJog)に移行します。
 シャトル処理、ジョグ処理は、ChkRot()関数で回転を検出します。この関数はGetClk()関数で現在のΦ1、Φ2信号を読み込み、以前の信号の状態(prev変数)を組み合わせてテーブルを引き、動作内容を返します。この値に応じて、ジョグモードの場合はJogFwd()関数かJogRev()関数を呼び出し、シャトルモードではnShuttle変数を増減します。またnShuttle変数が変化した時は、JogShuttle()関数は非0を返します。
 シャトルモードでの処理は、常にセンター信号を監視し、センターであればnShuttle変数を0にリセットします。実はここでちょっと問題があります。このジョグ/シャトルユニットは、センターとして認識される角度範囲が意外と広く、この範囲中でカウントが進むことがあるのです。そのためカウントミスが発生し、変数の増減で0になったにも関わらず、センター信号が検出ず、さらに進んでセンターと判断されてしまいます。具体的には、2、1、0、-1、0(センター検出)という出力になってしまいます。このような動作はまずいので、カウントが0になるのにセンター信号が検出されない時は、カウントを0にせず、前の値を維持し、0になるのはセンター信号を検出した時だけとしています。
 JogShuttle()関数を呼び出す前に、変数の初期化が必要です。これは、prev変数に最初の状態を読み込む、jsModeに最初の状態を読み込むといった処理を行います。

 これらの処理を行うプログラム例(Arduino用)を以下に示します。関数JogShuttle()がジョグ/シャトルのためのポーリングルーチンです。この関数はジョグ/シャトルの信号線を読み込み、以前の状態と組み合わせて動作を判定し、必要な作業を行うという処理を1回だけ行います。なので、実際にジョグ/シャトルを使う際は、この関数を繰り返し呼び出す必要があります。呼び出し間隔が長く、その間にツマミが何ステップ分も回されると、データの取りこぼしとなります。ジョグをすばやく回した時でもパルスの取りこぼしがないようにするには、1秒間に数百回程度は呼び出す必要があるでしょう。
 また、この関数を呼び出す前に、最初に使う以前の状態データ、ジョグ/シャトルの状態データを初期化しておく必要があります(setup()関数中で実施)。

 以下のプログラム例は、ATmega328のArduino用のもので、信号入力はすべて別関数として定義しています(GetClk()GetMode()GetCenter())。初期化はsetup()で、メイン部分のloop()は繰り返し呼び出されます。


//
// ジョグ/シャトルのテストプログラム (Arduino ATmega328)
//

// 回転を検出するテーブル
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
};

// ジョグモードとシャトルモードの遷移
enum {
kJsJogOn = 0, // ジョグモードに移行
kJsJog, // ジョグモード確定
kJsShuttleOn, // シャトルモードに移行
kJsShuttle // シャトルモード確定
};

// 使用するグローバル変数
int jsMode;
unsigned long tMode;
int nShuttle;
unsigned char prev;

//
// セットアップ
//

// ピンの割り当て
const int Clk1 = 2;
const int Clk2 = 3;
const int Center = 4;
const int Mode = 5;

void setup()
{
// ピンの動作を定義
pinMode(LED_BUILTIN, OUTPUT);

pinMode(Clk1, INPUT_PULLUP);
pinMode(Clk2, INPUT_PULLUP);
pinMode(Center, INPUT_PULLUP);
pinMode(Mode, INPUT_PULLUP);
Serial.begin(9600);

// 初期状態を取得
jsMode = (GetMode() == HIGH) ? kJsJogOn : kJsShuttleOn;
prev = GetClk();
nShuttle = 0;
tMode = millis(); // 現在時刻を取得

return;
}

//
// メインループ
//
void loop() {
// ひたすら繰り返し呼び出す
if (JogShuttle()) {
// シャトル値が更新された
Serial.print("S=");
Serial.println(nShuttle);
}

return;
}

//
// ジョグ/シャトルの状態をスキャンし、必要に応じて適切な処理を行う
// シャトル値が変化した時は、非0を返す
//

int JogShuttle()
{
unsigned char act;
int ret = 0; // シャトル値に変化があった場合、1を返す

// 状態の変化の処理、現在の状態での処理など
switch (jsMode) {
case kJsJogOn: // ジョグモードに切り替わった
// モード変更の判定
if (GetMode() == LOW) { // シャトルモードに移行
jsMode = kJsShuttleOn;
break;
}
// 一定時間待ってからジョグモードに移行(回転検出はしない)
if (millis() >= (tMode + 500)) {
jsMode = kJsJog;
prev = GetClk();
}
break;

case kJsJog: // ジョグモード
// モード変更の判定
if (GetMode() == LOW) { // シャトルモードに移行
jsMode = kJsShuttleOn;
break;
}
// ジョグの回転の検出
act = ChkRot();
if (act == kRotFwd) {
JogFwd();
} else if (act == kRotRev) {
JogRev();
}
break;

case kJsShuttleOn: // シャトルモードに切り替わった
// モード変更の判定
if (GetMode() == HIGH) { // ジョグモードに移行
jsMode = kJsJogOn;
tMode = millis();
nShuttle = 0;
ret = 1;
break;
}
// センターを確認してシャトルモードに移行
if (GetCenter() == HIGH) { // シャトルがセンター位置
jsMode = kJsShuttle;
nShuttle = 0;
ret = 1;
prev = GetClk();
}
break;

case kJsShuttle: // シャトルモード
// モード変更の判定
if (GetMode() == HIGH) { // ジョグモードに移行
jsMode = kJsJogOn;
tMode = millis();
nShuttle = 0;
ret = 1;
break;
}
if (GetCenter() == HIGH) { // シャトルがセンター位置
if (nShuttle != 0) {
ret = 1;
}
prev = GetClk();
nShuttle = 0;
} else {
// シャトル回転の検出
act = ChkRot();
if (act == kRotFwd) {
if (nShuttle != -1) { // センターの例外処理
nShuttle++;
ret = 1;
}
} else if (act == kRotRev) {
if (nShuttle != 1) { // センターの例外処理
nShuttle--;
ret = 1;
}
}
}
}
return ret;
}

// ジョグ操作に対応する処理
void JogFwd()
{
Serial.print(">");
return;
}

void JogRev()
{
Serial.print("<");
return;
}

// 回転の検出
int ChkRot()
{
unsigned char t;
unsigned char pat;
unsigned char action;

t = GetClk();
pat = (prev << 2) | t;
action = jsPhPat[pat];
prev = t;

if (action == kRotMiss) {
Serial.print("*");
}

return action;
}

// 2相クロックの読み込み (Arduino用コード)
unsigned char GetClk()
{
unsigned char val;

val = (digitalRead(Clk1) == HIGH) ? 2 : 0;
if (digitalRead(Clk2) == HIGH) {
val |= 1;
}
return val;
}

// モード信号の読み込み (Arduino用コード)
int GetMode()
{
return digitalRead(Mode);
}

// センター信号の読み込み (Arduino用コード)
int GetCenter()
{
return digitalRead(Center);
}


posted by masa at 21:07| 電子工作

2017年06月28日

ジョグシャトルで遊ぶ その2


■ジョグ/シャトルをマイコンにつなぐ

 ジョグシャトルをマイコンなどに接続するためには、ジョグ/シャトルから送られてくる信号を適切に処理し、回転やモードを検出する必要があります。ジョグ/シャトルコントローラに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です。

rot1.jpg

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

rot2.jpg

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

rot3.jpg

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

rot4.jpg

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

rot5.jpg

 ただこのやり方は、方向判定がさらに複雑になります。Φ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進数)を添え字とし、そのパターンに応じた動作を定数kRotNotMovekRotFwdkRotRevkRotMissとした場合、変化パターンのテーブルを構成する配列は以下のようになります。


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: // 読み取りミス
// 必要に応じてエラー処理
}


 ジョグモードであれば、正回転と逆回転はステップ送りの処理を行い、シャトルモードであれば、シャトルのポジションを示す変数を更新する(そしてプログラムのどこかでその値を参照する)ことになるでしょう。
 次は、ジョグモードとシャトルモードの切り替えについて考えます。



posted by masa at 14:09| 電子工作

2017年06月21日

ジョグシャトルで遊ぶ その1

 テープ時代のビデオ編集をやったことがある人なら、ジョグ/シャトルコントローラを知っているでしょう。VHSやベータのビデオでも、高級な機種には本体やリモコンに装備されていました。
 ジョグ/シャトルは、実はビデオ編集に限らず、何かと便利に使うことができます。単発からある程度の周波数まで、パルス発生のためのコントローラとして便利に使うことができます。筆者は、CNCフライス盤のMPGに、このコントローラを使おうと考えています。MPG(Manual Pulse Generator)は、ツマミを回してテーブル移動用ステッピングモーターを回転させるコントローラです。つまりハンドルを手で回す代わりに、モーターで動かせるようにするのです。駆動はパルスに比例して回転するステッピングモーターを使うので、モーター制御にジョグ/シャトルは好都合です。微動はジョグモードで、早送りや定速送りはシャトルでと考えています。

■ジョグ/シャトルコントローラ

 ジョグ/シャトルはVTRのテープの早送りからコマ送りまでを円滑に行えるコントローラです。ジョグ/シャトルという名前が示すように、ジョグとシャトルという2つの機能があります。

・ジョグ
 ジョグは、何回転でも自由に回るツマミを回して、ビデオのコマ送りをする機能です。時計回りで正送り、反時計回りで逆送りで、ツマミの1回転で数フレームから数十フレームのコマ送りができます。
 VHSやベータ、8mmなどの家庭用アナログ機、DVなどのデジタル機では、ジョグを一定角度回転させるごとに1フレーム送りという形でしたが、ベータカムなどではフレーム単位ではなく、まさにテープを微動させるという形で制御できました。つまり1フレームの途中で好きなところで止めることができました。
 ビデオ編集において、フレーム単位(あるいはフィールド単位)でテープの位置決めをする際には、ジョグは欠かせない機能でした。

・シャトル
 シャトルは、正方向、逆方向に、静止画から早送りまで、速度を自由に変えながらテープを送る機能です。ツマミのセンターが静止で、左右にそれぞれ数十度から150程度回すことができます。もちろん、センターから回すほど送り速度が高まります。
 家庭用のシャトルは、手を離すとセンターに戻るものが多かったですが、SONYの業務用のものは、手を放しても戻りません。

DSCN1929.JPG

■ジョグ/シャトルコントローラの構成

 家庭用VTRや一部の業務用のジョグ/シャトルコントローラは、中央にジョグツマミがあり、その周囲にシャトルのリングがあるという構成です。ジョグツマミは自由に回転しますが、シャトルは左右に一定角度しか回転しません。
 一方、SONYの業務用VTRや編集機に使われていたものは構造がちょっと異なります。丸いツマミが1つだけで、上から押すごとにジョグとシャトルが切り替わります。ジョグモードの時は自由に回転し、シャトルモードの時は、中央から左右に150度程度回転します。手を放しても中央には戻らず、中央位置には、中央であること示すクリックがあります。また最大角度に回した時にもクリックがあります。
 ツマミが回転すると、羽車と2組のフォトインタラプタによって、位相が90度ずれた2相パルスが生成されます。各相は1回転で24サイクルなのです。どのエッジに着目するかで、1回転あたりの回転検出数は24回から96回となります。
 ツマミを上から押すと、ノック式ボールペンと同じような仕組みで、ツマミの位置が上下します。ツマミが上に上がっている時はシャトルモードで、ツマミの回転範囲が制限されます。ツマミが沈んでいる時はジョグモードで、回転範囲の制限が外れ、自由に回転できます。この回転角を制限する部品は、シャトルモードの時は軸とともに回転しますが、ジョグモードの時は軸との結合が外れ、スプリングでセンターに戻っています。そのためジョグモードからシャトルモードに切り替わった時は、必ずセンター位置から始まります。
 現在のモードがジョグであるかシャトルであるかは、ツマミの軸受け部分の上下方向の位置を別のフォトインタラプタで検出します。また、シャトルモードの際のセンター位置も、フォトインタラプタによって検出されます。

DSC_3926.JPG

DSC_3919.JPG

DSC_3913.JPG

DSC_3722.JPG

 2相の回転パルス、ジョグ/シャトルモードの判定、シャトルのセンター検出の合計4個のフォトインタラプタは、ユニット側面の基板に装着されており、そこからの信号は基板上のコンパレータICで処理されます。このICとフォトインタラプタの電源は+5Vで、信号出力は0Vか5Vのデジタル信号となります。ただし回路の都合により信号を受ける側に適当なプルアップ抵抗が必要です。

DSC_3908.JPG

 回転パルスのためのフォトインタラプタはヒステリシス特性を持つシュミット回路になっており、境界付近での振動を避けるようになっています。モード切替とセンターのほうは単純に出力をデジタル化しているだけです。
 配線の色は筆者の入手した部品のものです。ほかのものが同じである保証はありません(コネクタは筆者が交換したものです)。

jogShSchm.JPG

 1. 赤 +5V
 2. オレンジ 回転でH/L
 3. 黄 回転でH/L
 4. 青 シャトル時: センターでH、それ以外でL ジョグ時: 常時H
 5. 紫 ジョグ時にH、シャトル時にL
 6. 茶 Gnd

 SONYのこのコントローラは、業務/放送用VTR、編集機に広く使われました。慣れるととても便利に使えます。今では、テープ編集はほとんど行われないため、当時の機材がオークションなどで安く放出されており、うまく探せば、1個1000円程度で入手することができます。例えば1980年代後半から1990年ごろまでの代表的な編集機であるSONY RM-450は、このコントローラを2基備えていますが、1000円から2000円で落札することができます(今回使った部品は、2台のRM-450から取り外したものです)。多くは25年くらい前のものですが、放送用品質のおかげか、今でもほとんど問題なく使うことができます。
 これより新しいものだと、ジョグ/シャトルの切り替えが機械式ではなく電磁式になったようです。このタイプは、ツマミのそばにあるプッシュスイッチでモードを決めるようで、自分で遊ぶにはさらに解析やら付加回路やらが必要そうです。

 次回は、ドライバプログラムについて説明します。
posted by masa at 14:41| 電子工作

2017年06月11日

LEDリングライトをつくる


■ リングライトとは

 小物の撮影や接写を行っていると、被写体にうまく光があてられないことがあります。被写体とカメラが近いために、うまく光源を配置することができないためです。つまり、カメラや被写体そのものが邪魔で、撮影部分が影になってしまうのです。こんな時、レンズのすぐそばに光源を置くことができれば、被写体に光を当てることができます。リングライトは、そのような用途のために、レンズ前部に取り付ける照明装置です。
 レンズの前縁部に円周状に光源を用意すれば、カメラや被写体自体が邪魔になって光が当たらないという状態を回避できます。リングライトはスチル写真では昔から使われている機材で、かつては環状のキセノン灯(ストロボ)が使われていました。これをレンズのフィルターねじを使ってレンズ先端に取り付けることで、レンズを中心として光源が配置され、被写体に均等に光を当てることができます。被写体がレンズ面から数センチ程度の距離であっても、光を当てることができます。また、肉眼では見ることのできない穴の底なども、光源で照らして撮影することができます。
 この写真は、200mmマクロレンズに装着したストロボタイプのリングライトです。

xelight.JPG

 リングライトの特徴は、影ができないことです。光源がレンズ周辺に環状にあるので、事実上、光源とレンズが同一軸上に位置するためです。そのため、影で細部が見えないということはなくなりますが、陰影がつきにくいので、画像はのっぺりした感じになります。

■ リングライトをつくる

 写真に示したように、ストロボタイプのリングライトは持っているのですが、これにはいくつか問題があります。

・昔の銀塩カメラ時代のもので、取り付け口径が小さい(52mm程度)。
・ストロボなので、動画撮影ができない。

 というわけで、白色LEDを使った連続発光のリングライトをつくります。

■ 本体

 本体は3Dプリンタで製作し、レンズのフィルター枠にはまる構造とします。うちの3Dプリンタはフィルター用のネジなどとても造形できないので、プラスチックの弾力でなんとなくはまるという構造としました。

mount.JPG

 使っているデジタル一眼2機種、ビデオカメラ1機種で使えるように、フィルター径52mmと72mmのものを作ります。アタッチメントを付け替えてどうこうするのではなく、それぞれのサイズ用に個別に作りました。52mmのほうはLEDを24個、72mmは36個使います。
 最初に52mm用をつくりました。52mm用は、おもにNikonの200mmマクロレンズ(MF時代のもの)と、エントリークラスのデジタル一眼についている標準(18-55mm f3.5-5.6)ズーム用です。この標準ズームは妙に寄れるレンズで、全焦点距離で28cmくらいまで近づけます。なのでちょっとした物撮りなら、マクロレンズを持ち出さなくてもこれで済んでしまうという、使い勝手のよいレンズです。

rl52-3.JPG

 LEDはちょっと内側に向けて取り付けています。LEDは指向性があるので、単純に正面に向けると、極近接時に中心部分が光量不足になりますが、内側に向けることで、リングライト表面から30mmくらいの位置でも、そこそこ均等に照らせます。離れると周辺光量が低下してしまいますが、まぁ接写で使う分には問題ないでしょう。

rl52-4.JPG

 24個のLEDは12個ずつ配線し、2個のトグルスイッチで別々に点灯できます。この点灯数切り替えは、光量調整のために1個おきに配線したのですが、上下に分けて影をつける効果のための配置にしてもよかったかもしれません。

rl52-2.JPG

 72mm用はフルサイズ一眼の標準ズームとビデオカメラ用で、どちらも極端な接写には使わないので、36個のLEDは正面を向けて取り付けています。またスイッチ2個による光量調整もあまり使わないので、スイッチは1個だけです。

rl62-3.JPG

rl62-2.JPG

■ LED

 LEDは高演色タイプというもので、秋月で1個40円程度のものです(http://akizukidenshi.com/catalog/g/gI-04762/)。これはパッケージ内で白2個と赤1個の3個のLEDチップが直列につながっており、赤のスペクトルを増やしています。低い電圧でぼんやり点灯させると、3個の素子が発光しているのがわかります。
 ただ3個のLEDが直列になる構造なので、VFが約8.5Vと高くなっています。普通なら、数個のLEDを直列にして電流制限抵抗や定電流ダイオードをいれるのですが、このVFのため、今回はLEDひとつにつき100Ωの抵抗1本を直列に入れ、9.6V電源で点灯させることにしました。
 本体ケースへのLEDの固定はホットボンドを使っています。

led1.JPG

led2.JPG

■ 撮ってみる

 出来上がったリングライトをカメラに装着すると、こんな感じになります。電線を引きずるのでちょっとうっとうしいですが、リングストロボよりは格段に使い勝手が向上しています。

rl52-1.JPG

rl62-1.JPG

 Nikonの18-55標準ズーム(DX)で望遠側でめいっぱい寄ると、こんな感じで撮れます。

closeup1.JPG

 ベローズと200mmマクロレンズ(DXカメラなので300mm相当)を組み合わせて大げさに撮影すると、こんな感じです。非点灯時のLEDの写真は、直径5mmのLEDをこの構成で撮影したものです。トリミングはしていません。

closeup2.JPG



posted by masa at 01:33| いろんな工作

2017年03月26日

三菱のインバータで遊んでみる その4

 今回使っている三菱電機のE-700シリーズは、汎用磁束ベクトル制御とアドバンスト磁束ベクトル制御という2種類のセンサレスベクトル制御がサポートされていますが、アドバンスト制御のほうが高性能で、汎用のほうは過去の製品との互換性のために用意されているようです。ここではアドバンスト制御を使います。ちなみに、出荷時状態はV/F制御になっています。
 ベクトル制御を正確に行うには、さまざまなパラメータが必要になります。なので、実際に使う前にこれらのパラメータを設定する必要があります。パラメータには、使用するモーターの仕様で決まるものと、モーターそのものの電気的な(仕様書などには示されていない)特性値があります。いまどきのインバータは賢いので、電気的な特性値を自動的に求める機能が備わっています。特性値を調べ、設定する機能を「チューニング」といいます。

■アドバンスト磁束ベクトル制御の設定

 ベクトル制御を行う際は、モーターに関するいくつかのパラメータを設定する必要があります(以下の説明には、ベクトル制御専用のパラメータ以外のものも含まれます)。モーターの出力、極数などの情報は、ユーザーが直接指定します。ここでは以下のパラメータを設定します。おもにインバータ出荷時設定からの変更ですが、初期設定のままのものもあります。見出しの後のPnnは、パラメータnnの意味です。
 電流、周波数のパラメータは、単位を示すA、HzのLEDが点灯します。電圧のVは単位表示はありません。これらのパラメータは、小数点も表示されます。

・上限周波数 P1
 インバータが出力する最高周波数、つまり最高回転数の指定になります。ここでは定格周波数の倍の120(出荷時設定値)とします。これはV/F制御でも参照されます。

・下限周波数 P2
 インバータが出力する最低周波数、つまり最低回転数の指定になります。ここでは0(出荷時設定値)とします。これはV/F制御でも参照されます。

・電子サーマル P9
 サーマルはサーマルリレーの略で、電流による発熱で動作する保護機構です。過負荷などによる過電流を検出し、出力を遮断して機器を保護します。一般にサーマルリレーは独立した部品、あるいは開閉器とセットで使われますが、インバータには、電子的に等価な操作を行う機能、つまり過電流が流れた時に出力を遮断する機能が組み込まれています。これが電子サーマルです。初期設定ではインバータの定格に見合った電流値が設定されていますが、定格より小さなモーターを使う場合は、この値を小さくする必要があります。この値は0.01A単位で設定できます。今回使った200Wモーターの定格電流は60Hzで0.98Aです。汎用モーターの場合は、これを1.1倍した値(1.1A)を設定します(詳細はマニュアルを参照)。

・適用モーター P71
 使用するモーターの種類で、三菱の汎用、高効率、定トルク、他社製などがあります(マニュアル参照)。三菱の指定形式以外の場合、後述するオートチューニングが必要になります。今回、日立の汎用モーターを使っているので、他社汎用モーターを意味する3を指定し、後でオフラインチューニングを行います。

・モーター容量 P80
 モーター容量をkW単位で指定します。9999だとV/F制御(モーター容量は関係しない)となります。ベクトル制御の場合は、0.01kW単位でモーター容量を指定します。今回は200Wモーターなので、0.20を設定します。

・モーター極数 P81
 モーターの極数で、2、4、6などがあります。V/F制御の場合は9999にします。極数が多いほど、同じ周波数でも回転数が低くなります。60Hzの場合、2極だと3600RPM弱、4極だと1800RPM弱になります。今回は4極を使うので4を設定します。

・モーター定格電圧 P83
 モーターの定格電圧を0.1V単位で設定します。ここでは200V(出荷時設定値)を指定します。

・モーター定格周波数 P84
 モーターの定格周波数を0.01Hz単位で設定します。ここでは60Hz(出荷時設定値)を指定します。

・速度制御ゲイン P89
 負荷変動により回転数が変化したときの回復動作の応答性のパラメータで、100(%)が標準です。設定は0.1%単位で行います。9999だと指定したモーターのデフォルト値が使われます。この数字が小さいと変化に対する応答がゆっくりになり、大きいと早くなります。値が大きすぎると、状況によっては過負荷になったり、速度の振動が発生することがあります。このパラメータは実際に負荷をかけた運転で調整することにし、ここでは9999(出荷時設定値)としておきます。

・制御方法 P800
 汎用かアドバンストかを指定します。ここではアドバンスト磁束ベクトル制御なので、20を設定します。

 これらのパラメータを設定すると、アドバンスト磁束ベクトル制御モードとなります。つまり、モーター容量(P80)と極数(P81)を設定するとV/Fモードからベクトル制御モードになり、さらにP800で汎用かアドバンストかの制御方法を決めるということです。
 ベクトル制御を選択した場合は、実際に運転する前に、次に説明するオフラインオートチューニングを行う必要があります。

■オフラインオートチューニングの実行

 アドバンスト磁束ベクトル制御では、モーターの巻線の抵抗やインダクタンスなどのパラメータが必要になりますが、これらはインバータが自身で測定し、設定できます。接続されたモーターに適当な電圧を加え、それに対する電流値を測定することで、これらのパラメータを求めます。これをオフラインオートチューニングといいます。
 オフラインチューニングではモーターは回転させず(多少軸が動くことはあるようです)、必要な調査を行うので、モーターを機器に組み込んだ状態でも実施できます。オフラインチューニングにより、P82P90-94P859が自動的に設定されます。あるいは事前に求めておいたこれらのパラメータをインバータに設定することで、個々の機材でのチューニングを省略することもできるようです。
 オフラインチューニングとは別に、通常運転中にパラメータを調べ、最適な状態に自動的に調整するオンラインチューニングという機能もあります。
 オフラインオートチューニングは、以下のように行います。

・オートチューニング P96
 オートチューニングの実行、現在の状態を示します。0はチューニングを実行しない、1はアドバンスト制御のためのチューニングの実行を示します。

 前述のパラメータ設定を行った後、P96に1を設定し、PU運転モードにしてRUNボタンを押します。この時、LED表示を電流や電圧以外にしておくと、進行が数字で表示され、1から3まで進みます。
 途中で停止する場合はSTOP/RESETを押します。チューニングには数秒から数十秒かかります。RUN LEDが点滅したら正常終了で、STOP/RESETを押してチューニングを終了します。これでパラメータが設定されます。終了後にP96の値を変更する必要はありません(変更するとパラメータが無効化されます)。

 これで出荷時のV/F制御からアドバンスト磁束ベクトル制御になったはずですが、無負荷で回転させる実験では違いがわかりません。このモードの違いは、実際に負荷がかかった環境で低速運転や負荷が変動する運転をしないとわからないでしょう。

posted by masa at 18:34| 電気機械