2017年10月01日

オルタネーターで遊ぶ その3

 前回、交流出力ができたので、今回はこれを整流し、直流出力を見てみます。

■レクチファイヤを使って直流出力

 今回使ったオルタネーターのレクチファイヤの回路は図のようになっています(前の説明には間違いがありました)。

rect-02.jpg

 三相交流の3本の出力線(R、S、T、中性線は未使用)をレクチファイヤに接続すると、三相全波整流されます。
 回路を見ると、直流のマイナス出力はひとつですが、プラス出力が2系統あるのがわかります。上側のプラス出力(コンデンサがつながっている方)が発電機出力で、バッテリーや車両の電装系に接続されます。もう1組の補助プラス出力(コンデンサがつながっていない方)は、オルタネーター内部で使用します。
 放熱器は2個に分かれていて、それぞれに3個の大きいダイオードが取り付けられています。それぞれの放熱器は、直流出力回路の一部になっています。2個の放熱器は絶縁されており、−側はオルタネーターボディにネジ止めされています。今回は外付けなので、放熱器に端子をネジ止めしています。プラス側はオルタネーターのプラス極ボルト(B端子)と、内部のレギュレーターに接続する端子になっています。−極とB端子側のプラス極の間にはコンデンサが接続されています。
 補助プラス出力用のダイオードは主ダイオードより小型のもので、放熱器を使わず、放熱器の間で空中配線されています(交流入力電線の横の黒い円筒部品)。

rect-04.JPG

 中央の赤白黒の3本は交流入力。これらの線の横の黒っぽい円筒は補助プラス出力用のダイオード。外側の端子に接続されているのは、赤が主プラス出力、白が補助プラス出力。

rect-03.JPG

 マイナス出力は端子の形では用意されていないので、マイナス側放熱器に電線(黒)をネジ止めして引き出しています。

 レクチファイヤの交流入力に三相交流を接続すると、出力端子に2系統の直流が出力されます。三相全波整流回路が2組組み込まれた形ですが、−側は共用されているという変則的な整流回路です。
 三相全波整流では、整流出力は三相交流の頭の部分をつないだ波のような形になります。補助プラス出力は整流してそのままの出力なので、波のある波形になります。わかりやすいように、波形の表示位置を少し上にあげていますが、実際にはほとんど重なる位置になります(ダイオードによる電圧降下が0.5V程度あります)。

ac3-01.jpg

 主プラス出力は、出力側にコンデンサが入っているので、無負荷状態では平滑化され、ほぼきれいな直流になっています。こちらも波形表示位置を少し上にあげています。

ac3-02.png

 交流出力の測定は基準電位として中性線を使いましたが、整流した場合はマイナス出力を基準電位とします(オシロスコープの波形画面は、交流波形と同時に表示するため、直流出力も交流側中性線を基準電位としています)。車の電装系はオルタメーターも含めて車体全体が−極に接続されており(マイナスアース)、使用する電源は+12Vとなります。このように接続するために、オルタネーター内部の交流出力は接地されていません。なお、三相交流の中性線を基準電位とすれば、三相両波整流となり、プラスマイナス出力となります。この場合、オルタネーターボディが電位を持つことになるので、ショートなどに注意する必要があります。

■オルタネーター2号を入手

 思うところあって、ほぼ同形式のオルタネーターをもう1台入手しました。1号よりもちょっときたないですが、これから動作や内部の配線変更などを行っていきます。

alt-no2.JPG

posted by masa at 13:52| 電気機械

2017年09月19日

オルタネーターで遊ぶ その2

 前回分解したオルタネーターを、実験用に組み立てます。

■配線の引き出し

 オルタネーターがエンジンに取り付けられていた時は、直流出力しか必要ないので、ボディアース、ネジ止めのバッテリー端子、そしてコネクタで制御電源とランプ端子が接続されていました。今回は実験のために、必要な別の配線を引き出します。
 まず、オルタネーターを交流同期発電機として動かすための配線を引き出します。電機子コイルのY結線の3本の出力と、未使用だった中性線から配線を引き出します。これで三相4線交流が得られます。この4本の出力はオルタネーターボディには接地されておらず、完全にフローティングになっています。この線は、取り外したレクチファイア用の穴から引き出します。ブラシからの回転子(界磁)用の配線も引き出します。これで外部から励磁電力を送り、回転子を回転させることで、三相交流発電機となります。

・三相4線交流出力(4本)
 Y結線の三相出力と中性線です。

amt4.JPG

・回転子励磁電流(2本)
 回転子を励磁するための直流12Vの配線です。

rot.JPG

alt-schem.jpg

 交流出力は、中性線がN、三相出力がR、S、Tです。回転子はF+とF-です。

 レギュレーターICはブラシホルダーと一体に組み込まれているため、外部に取り出せません。そのため、レギュレーターの配線もオルタネーター内部から引き出します。レギュレーターは物理的にオルタネーター内部に残っていますが、電気的には完全に分離されています。
 レギュレーターの配線については、後で直流発電の実験をする際に説明します。

 これらの配線を接続したら、オルタネーターを組み立てます。


■モーターの準備

 オルタネーターを、インバーター制御の三相誘導モーターで回します。
 モーター軸にVベルト用プーリーを取り付けます。プーリーは汎用品なので、軸穴は自分で加工する必要があります。そのため、9mmの下穴のモーター軸に合わせて11mmに広げ、さらに押ネジ用の穴を加工します。

motor1.JPG

inv.JPG


 モーター側プーリーは3インチタイプで、オルタネーター側のプーリーよりちょっと大きいものです。誘導モーターを120Hzで運転すればたぶん3500 RPMくらいで回るので、オルタネーターは4000 RPM程度でしょうか。実際にエンジンに装着している状態ではもっと高回転になるはずなので、今回の実験では、電圧や出力は低くなるでしょう。


■台座

 適当な木材にモーターとオルタネーターを取り付けます。ベルト駆動なので、張り調整もできるようにしておきます。オルタネーターからの配線は、後でいろいろ実験できるように、端子台に接続します。

bench1.JPG

bench2.JPG

bench3.JPG


■交流の発電

 同期発電機は、磁石である回転子(界磁)を回転させることで、固定子(電機子)側に交流起電力が発生します。回転子に永久磁石を使えば回転させるだけで発電しますが、電磁石の場合は、励磁電流を流す必要があります。
 回転子に励磁電流を流して回転させれば、電機子巻線に交流電圧が発生します。三相4線式で、Yの接続部を中性点とできるので、オシロスコープをつないでちゃんと三相交流の波形を見ることができます。これがデルタ結線だったり、Y結線でも中性線がないと、基準電位にできる中性点がないので、そのままではこの波形を見られません。

ac1.JPG

 実は、励磁電流を流さなくても、わずかな電圧が発生します。回転子は直流励磁なので、鉄心に以前の励磁による残留磁束があり、これによりわずかな電圧が発生するのです。うまくやれば、この電圧を利用して励磁することで徐々に発電電圧が上昇し、外部から電力を供給することなく、発電を開始することもできます。
 実験してみたところ、励磁電流なしで、1Vちょいの起電力が観察できました。下の画像は、1目盛が0.2Vです。やたらノイズが乗っているのは、インバーターに由来するものでしょうか?

osc0A.png

 回転子は抵抗が3-4Ω程度なので、12Vを加えると数アンペアの電流が流れます。実験はとりあえず1A程度(印加電圧は約5V)で実験を行いました。励磁電流が実際にどれくらい流れるのかは、レギュレーターを接続した実験で見てみます。下の波形は1目盛が5Vです。

osc1A.png


 このオルタネーターは、回転子が12極(S-Nペアが6組)、電機子側は36スロットの分布巻きで、発電機1回転につき6サイクルの交流が発生します。
 モーターとオルタネーターのプーリー直径比が約1.25(増速)で、モーターを60Hzで駆動した場合(同期速度1800 RPM)、発電出力は約200Hz(2000 RPM)となります。


posted by masa at 01:05| 電気機械

2017年08月30日

オルタネーターで遊ぶ その1


 ふと、三相同期発電機をいじくりたくなったのです。
 一般人の日常生活で、もっとも身近な三相同期発電機は(というかほとんど唯一の選択肢は)、自動車のオルタネーターでしょう。という訳で、自動車用オルタネーターで遊んでみます。

alt-01.JPG

■自動車のオルタネーター

 自動車用のオルタネーターは、自動車で消費する電力を供給し、さらにバッテリーに充電するために、12Vか24Vの直流電力を発電します。実際には12V(24V)バッテリーに充電するために、14V(28V)程度の出力電圧になります。
 オルタネーターは交流発電機のことですが、自動車用のオルタネーターは直流出力です。これは、オルタネーター内部に整流/出力調整機能を持っているからです。オルタネーターは、ベルトを介してエンジンによって回転し、三相交流電力を発電します。そして三相全波整流器(レクチファイア)によって直流に変換します。
 エンジンの回転数は10倍近い範囲で変動するので、それに応じてオルタネーターの発電電圧も変わりますが、出力電圧が過剰にならないように、レギュレーターによって調整します。これにより、回転数が変わっても出力電圧が一定値を超えることはなく、自動車の電装品とバッテリーに安定した電圧で電力を供給できます。


■実験用オルタネーターを入手

 ネットオークションで適当なオルタネーターを仕入れました。条件はVベルトプーリー駆動であること。今時の車はたいていリブベルトを使っているのですが、プーリー入手がちと面倒そうです。Vベルトならプーリーもベルトも標準部品を簡単に入手できます。
 入手したのは、スズキキャリイ(軽トラ)用の、12V45A出力のものです。レクチファイアとレギュレーターは内蔵されており、電気的には以下の端子があります。

・アース(ボディ)
 マイナス極です。

・バッテリー(B)端子
 ケース背面にネジ止め端子で、オルタネーターの直流出力端子です。バッテリーと電装系の+母線に接続します。ここにはバッテリーによって常時12Vが加わります。

・制御電源(R)端子
 イグニッションキーにより12Vが供給される端子です。この電源によりレギュレーターの制御回路が機能し、オルタネーターのローターに励磁電流が流れます。つまりこの端子に12Vを加えないと、オルタネーターは(たとえ回転していても)発電しないということです。エンジン始動時はこの12Vはバッテリーから供給されますが、始動後は自身が発電した電力が使われます。
 この端子の名称はメーカーによっても変わるようです。

・チャージランプ(L)端子
 チャージランプ端子です。これは、オルタネーターに制御電源が供給されている(イグニッションキーがON)で、発電出力が発生していないときに、警告ランプを点灯させるための端子です。具体的には、発電出力がない時にグラウンドに落ちます。

conn-01.jpg

■分解

 オルタネーターを三相発電機として使うためには、電機子コイルの出力から配線を引き出す必要があります。またレクチファイアは必要ありません。ローターへの励磁電流も、外部から供給できるようにします。ローター用のスリップリング/ブラシ部はレギュレーターと一体になっているので、ブラシの電線だけ切り離し、ビニール線でブラシ配線を引き出します。また実験のために、レギュレーターの各端子への配線も引き出しておきます。
 オルタネーターの分解は、ネットで調べれば手順がいくらでも出てきます。ちょっと難しいのは、最初にプーリーの固定ナットを外すことです。ローターの回転を押さえなければならず、エンジンに取り付けられていればどうにかなりますが、オルタネーター単体だとうまく押さえられません。インパクトレンチを使えば簡単に外せます。

pulley.JPG

 あとはケースのボルトを外し、軸をプラハンマーなどで叩けば、ケースを前後に分解し、ローターを抜き取ることができます。

alt-02.JPG

 電機子コイルからの配線はレクチファイアにハンダ付けされているので、これを外して電機子、レクチファイア/レギュレーターを外します。レクチファイアの直流出力がレギュレーターにハンダ付けされているので、これも外します。スリップリングのブラシもレギュレーターにハンダ付けされているので、外します。

alt-03.JPG

 一般にオルタネーターの分解は、ベアリングやブラシの交換のために行うのですが、今回は、配線を変えるのが目的なので、その辺は手を加えません。


■オルタネーターの内部構成

 オルタネーターは以下の部品で構成されています。

・電機子コイル
 オルタネーターケースの内側の固定巻線で、三相Y結線になっています。この出力をレクチファイアで三相全波整流することで、直流出力を得ています。今回の入手したものは中性線を使わない構成でしたが、3本の巻線を接続している部分を露出させ、中性線を引きだしました。

coil-01.JPG

・ローター(界磁)コイル
 回転するローターは直流で励磁される電磁石です。励磁電力はスリップリングで供給されます。レギュレーターはこの励磁電流を制御することで、オルタネーターの出力を制御します。今回入手したものは、12極ローターです。
 軸端に厚みのあるベアリングがあり、それとローターの間にほぼ同径のスリップリングが2組あります。

slip-01.JPG

・レギュレーター
 R端子に12Vが与えられると動作します。レギュレーターは、ブラシとスリップリングを介してローターコイルに励磁電流を供給します。B端子の電圧が規定以下の場合(回転していない、あるいは回転しているが出力電圧が低い)、レギュレーターはローターコイルに励磁電流を供給します。回転数が上がって電圧が上昇し、規定電圧(約14V)以上になると励磁電流をカットし、電圧上昇を抑えます。ローター電流の断切を高速に繰り返すことで、母線電圧を規定電圧に保ちます。制御は断続的ですが、バッテリーが平滑回路として働き、母線では滑らかな直流となります。
 チャージランプは、R端子に12Vが加えらており、オルタネーターが十分な電圧を発生していない場合に点灯します。つまり回転していないか、出力電圧が下限値以下である時に、トランジスタを介してL端子が接地します。自動車の場合、キーをONにすると点灯し、エンジンが始動し、回転が安定して発電を開始すると消灯することになります。
 写真は、レギュレーターとレクチファイアが接続された状態のものです。ハンダ付けを外せば分離できます。

reg-rect-01.JPG

・レクチファイア
 6個のダイオードで三相全波整流します。+出力はB端子、−出力はケースにアースされます。またこの+出力は、レギュレーターの電圧検知端子(オルタネーター内部の接続)にも送られます。ノイズ防止用に、プラス極とマイナス極の間にコンデンサが接続されています。(間違ってました。今度訂正します。)
 写真では、絶縁用のプラスチック部品が割れてしまっていますが、これを再度組み付けることはないので気にしません。

rect-01.JPG

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

2017年07月13日

Marantz 7 風プリアンプを作ってみる


 2016年の話です。
 春日無線の2A3シングルアンプが2015年に稼働したので、これにCDのライン出力をつないで聴いていたのですが、やはりレコードもこれで聴きたくなります。しばらくは市販のトランジスタアンプのフォノEQを使っていたのですが、せっかくなので真空管プリアンプを作ることにしました。ネットでいろいろ調べ、有名どころのMarantz 7の回路を作ることにしました。

front1.JPG

■アンプの構成

 Marantz 7はもう60年くらい前の製品ですが、今でもこれが好きな人が多く、資料も容易に入手できます。詳しくはhttp://www.takobeya.com/Marantz7C/Marantz7.htmlにまとめてあるので、そちらを参照してください。
 今回作ったプリアンプの構成、特徴はこんな感じです。

・Marantz 7のフォノEQ、バッファアンプを作る(トーンコントロールは省略)
・Marantz 7っぽい基板、真空管まわりとする
・使用する部品にはこだわらない。

■真空管ソケット周辺

 Marantz 7は、ケース内部の垂直の板に真空管ソケットが取り付けられています。つまり真空管は水平に配置されます。ケース背面には長穴があいていて、シールドケースがケース背面から少し飛び出します。
 今回作ったアンプは、この構造を踏襲し、真空管ソケットをアルミアングルに取り付け、ケース背面にあけた穴からシールドケースが飛び出すように配置してあります。ケース背面はCNCで穴抜きしました。オリジナルは12AX7を6本使っていますが、トーンアンプを組み込まないので、本作は4本構成です。

rear2.JPG

rear1.JPG

■基板

 Marantz 7はラグ板配線ではなく、基板を使っています。しかしプリント基板ではなく、ベークライト板に貫通ポストを立てて、CR類を結線します。本作では、3mm黒色ベークライト板に2.5mmネジを切り、ポストを立てています。この基板の両面にCとRを取り付けます。基板は真空管ソケットに隣接しており、基板とソケットを結ぶCRは、直接ハンダ付けしています。基板に信号配線を接続する部分にはポストを立てています。電源の接続はポスト間のスズメッキ線に直接接続しています。このような構造なので、後から部品交換を行うのはかなり大変です。

layout.JPG

board1.JPG

board2.JPG

base.JPG

board3.JPG

■回路

 回路については、Marantz 7ほぼそのままです。詳しくはWebサイトのほうに書いてあります。Phono入力の抵抗が47kΩと1MΩが並列にはいってますが、これはWebサイトにも書いた通り、オリジナルの回路構成の都合です。47kΩはフォノイコライザ動作の時にのみ挿入され、1MΩは(マイク、テープヘッドなどのために)常時挿入されている入力抵抗です。実装上では、1MΩは基板上、47kΩは入力端子に接続しています。
 使っている部品は、抵抗がごく普通の金属皮膜抵抗、電界コンデンサも普通のもの、信号系のコンデンサはフィルムタイプです。イコライザの時定数はマイラーコンデンサで、オリジナル回路の容量とするために、2つのコンデンサを並列につないでいます。

sch.JPG

test1.JPG

■入力セレクタやボリュームなど

 今回は、Photoが1入力、Lineが2入力です。
 ケース背面のRCAコネクタからの配線は、オリジナルではフロントパネルのセレクタ類に直接伸びていますが、作例では配線長を短くするため、セレクタとボリュームを真空管のすぐ上に取り付け、コネクタからの配線長を数十ミリに抑えています。
 オリジナルは、Line入力時にはPhono入力をグラウンドに落とすという回路になっているのですが、引き回し長が伸び、スイッチ回路が増えるので短絡回路は省略しました。

front2.JPG

side.JPG

 セレクタとボリュームは、延長軸でフロントパネルのつまみに接続していますが、ケース組立誤差により、軸が一直線に揃いませんでした。そのためユニバーサルジョイントを作りました。スパイダー部は金属ですが、ヨークがジュラコン樹脂なので、絶縁継手となっています。もちろん、タイトカップリングなどの市販品を使うのが普通で、わざわざジョイントを自作したのはただの自己満足です。

joint1.JPG

joint2.JPG

■電源

 東栄(http://toei-trans.jp/)で買ったP-260Bというトランスで、次の巻線があります。

・260-0-260V 30mA
・0-6.3-15-17V 2A
・6.3V 1A

 これを、基板側への漏洩磁束がなるべく少なくなるような位置に取り付けました。10ターンのコイルをいろいろ動かし、それに発生する1mVほどの電圧を見ながら、位置と向きを決めています。ショートリング付きなのでさほど漏れないのですが、まぁ気持ちの問題です。
 B電源は260V-0V-260Vの巻線をシリコンダイオードで両波整流し、CRフィルターで平滑化しています。フォノイコライザーは245V、フォノEQ出力段と出力バッファのカソードフォロワは280Vの電源を接続しますが、これはCRフィルターの適当なところから引き出すことで、目的の電圧としています。抵抗値は現物合わせで決めました(写真は仮付抵抗で調整中のもの)。

ps2.JPG

 ヒーター電源は、12AX7のヒーターを管内で直列で使用し、DC 12.6Vで点灯しています。トランスの15V巻線から適当なシリコンブリッジで全波整流し、LM338で安定化しています。

ps1.JPG

 セレン整流器? 何だっけそれ? 昔、鉄道模型のヘッドライト切り替えやパワーパックの整流に使ってたっけ(遠い目)。。。

■問題点

 特に問題もなく音が出たのですが、実は未解決の問題が残っています。
 MCカートリッジのDL-103を接続し、MCトランスをスルーにすると(つまり入力にDL-103を直接接続すると)フォノイコライザーが発振するという症状があります。トランスでステップアップしたり、インピーダンスの高いMMカートリッジを使う分には問題ありません。DL-103の内部抵抗に近い抵抗をつないでも問題なし、DL-103の小さなL分がある時のみだめなようです。
 発振時には入力側にも数十mVの電圧がかかってしまい、カートリッジによくないので、じっくりと各部を調べる訳にもいかず、また実用上の問題もないので放置状態です。今のカートリッジが腐ったら実験してみます。

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

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| 電子工作