Nゲージ電車模型のポイント切替回路の製作




Nゲージ電車模型に最近初めてさわりました.
コイルに電気を流して、ポイントを切り替える左写真のようなアイテムを入手しました.

がっ、どんな信号を与えて切り替えるのかがわかりません.

調べたところ、こんな仕様でした.

●12V

●通電時間は0.05秒ぐらい.
通電し続けると、発熱して、プラスチックが溶解して固着して動かなくなります.実際に子供がやってしまい、修理しました.

●実動作させたところでは、12V0.6Aの電源ではうんともすんとも動かなかったので、瞬時には2Aぐらい流さなくちゃいけないと推測します.

●ホビー用のポイント切替SWっていう製品がもちろん売られているわけなのですが、通電時間の制御って、それなりに回路投資が必要ですよね.どうやってるんだろうと調べたら、すごいアバウトな方式でした.  レバーを動かすと、内部に仕込んであるバネがパチンと跳ねて、一瞬だけ通電するっていうからくりだそうです.アバウトだが、最も安価な方法と言えます.さすがはおもちゃ.




●一瞬だけしか通電しないので、なんらかのラッチング的挙動が必要だと思われます.どうやっているのでしょうか?
分解したところ、可動磁石が、左右のコイルのコアに引きつけられることでラッチしていました.可動磁石には、リンク機構がついていて、ポイントを切り替えるようになっています.








というわけで、STM8S discoveryで製作しました.ポイントは、

●電源は、手持ちの12V4Aのアダプタを利用します.

●±12Vの切替のために、Hブリッジをつかいます.トランジスタは、秋月電子で売られていた、2SD1830+2SB1228を使います.(Hブリッジ1回路あたり¥400)      3Aぐらい流せるトランジスタだったと思います.電流スペック的にはもすこし余裕があるに越したことはありませんが、これ以上大きくて高価なトランジスタを奢る気もありませんので、これで手打ちします.

●フライホイールダイオードは、ACを整流できるような類のものです.秋月で調達しました.1S1558のような小信号整流用のダイオードだと焼けてしまうと思いますので、オススメしません.

●タイミング制御は、STM8S discoveryでやります.通電時間は、実動作で0.05秒ぐらいに設定しました.当初の実験では0.7秒ぐらい通電したのですが、触れないほど熱くなってしまいました.0.05秒だと、バチバチ切り替えてもほんのり暖かい程度で済みます.

手書きの ヘタレ回路図はこちらです.(別ウインドウ)     とくに説明するほどのことはないとおもいます.



これがつくった現物です.

白い小基板がHブリッジです.2ヶあるのは、冒頭の写真のように、切替ポイントが2カ所あったからです.

Hブリッジの製作って嫌いなんですよ.どうしても、配線が汚くなってしまうので.

STM8S discovery上のトグルSWは、ポイント切替スイッチです.

STM8S discoveryの、STM32Fが載った基板は切断してありますので、小さく見えてますので、ご注意ください.









つぎはソフト開発です.

STVDのプロジェクトフォルダはこちら を解凍してください.(zip)   
私の開発環境は、windowsXP上のVS2008 professionalを使っています.これ以外の環境では、トラブるかもです. フォルダ設定などのトラブルシュートは こちらのページをご覧ください.助けになるかもしれません.

免責: このコード及び解説を利用した結果生じた、いかなる損害についても、当方は一切関知しません.コイルが溶けたとか、トランジスタが焼けたとか、家が焼けたとか言われても、知らないです.

ソースコードの説明をします.


プロジェクトフォルダを開くとこんなファイルがあります.

自分で書いたファイルは、main.c gpio.c gpio.h です.

プロジェクトを作成すると自動生成されるファイルであり、少し書き換える必要があるファイルは、stm8s_interrupt_vector.c  stm8s.h  stm8s_conf.h です.

それ以外のヘッダファイルは、STM8S用にSTMicro社から提供されているFWライブラリを解凍して、このフォルダにコピーしたものです.FWライブラリは、このURLからダウンロードできます.インストール方法は、こちらのURL を参考にするとよいです.

その下の.dep .pdb .spy .stp はビルドで生成されるファイルなので自分で書き換える必要はないです.








main( )  のキモのところを説明

●includeには、おきまりの stm8s.h はかならず記述しておきます.
あと、GPIOのビット読みルーチンを自作しましたので、gpio.h も記述しておきます.
  #include "stm8s.h"
  #include "gpio.h"

●128000というのは、2つあるSTM8S内蔵クロックオシレータのうち、低速クロックオシレータの周波数である、128kHzのことを意味しています.
20というのは、20Hzでタイマ割り込みさせるという意味です.通電時間を決めるために割り込みを利用するためです.
ARR という計算式は、20Hzの割り込みをするために、タイマは128kHzを何回カウントすればよいのかを計算するための式です.この場合ですと、6400カウントさせることになります.

  #define PRS_Hz     128000      // prescaler output freq.
  #define INT_Hz     20             // interrupt freq.
  #define ARR    (int)((float)PRS_Hz/(float)INT_Hz)  // 16bit counter max value

●CPUクロックを設定します.キモのところは、CLK_SOURCE_LSI です.LSIというのが、128kHzの内部クロックオシレータを表しています.クロック設定について詳しいことは、こちらの解説
 を読んでください.

 CLK_ClockSwitchConfig( CLK_SWITCHMODE_AUTO, CLK_SOURCE_LSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE );

●GPIOの定義.  ポイントスイッチのための入力ポートを2ヶ用意します.

 GPIO_Init(GPIOE, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT); // right sw
 GPIO_Init(GPIOE, GPIO_PIN_2, GPIO_MODE_IN_PU_NO_IT); // left sw

●GPIOの定義.  動作モニタのためのLEDのための出力ポートを、GPIODとGPIOEに5ヶ用意します.不要なら削除してしまっても問題ないです.

 GPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_OUT_PP_HIGH_SLOW); // LED
 GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_SLOW); // LED
 GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); // LED
 GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_SLOW); // LED
 GPIO_Init(GPIOE, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_SLOW); // LED

●GPIOの定義.  Hブリッジを駆動するための出力ポートをGPIODに8ヶ用意します. Hブリッジ1ヶあたり4本もの制御信号が必要で、それが2回路あるので、8出力ポートが必要です.  この煩雑さがHブリッジ回路を製作するうえでかったるいところです.

  // bit7531 ---> actuator left H bridge
  // bit6420 ---> actuator right H bridge
  GPIO_Init(GPIOB, 0b11111111, GPIO_MODE_OUT_PP_LOW_FAST);  // actuator

bit7,5,3,1 が、左側のポイント切替スイッチに対応するHブリッジの制御線です.
bit6,4,2,0 が、右側のポイント切替スイッチに対応するHブリッジの制御線です.

●タイマの設定
TIM2_TimeBaseInit( ) は、プリスケーラは使わずに、6400回カウントしてねと指示しています.
TIM2_ITConfig( ) は、タイマのカウンタがオーバーフローしたら、すなわち6400回カウントしたら、タイマ2
割り込みを発生させてくれ、と指示しています.
TIM2_Cmd( ) は、タイマ2に動けと指示しています.

  TIM2_TimeBaseInit( TIM2_PRESCALER_1, ARR-1 );
  TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
  TIM2_Cmd(ENABLE);

タイマについて詳しいことは、こちら を参照してください.

●パワーオン直後のいま、ポイント切替スイッチがどっちに倒れているのかを、読みとります.

  state_left =GPIO_ReadPin(GPIOE, GPIO_PIN_2);  // sw left
  state_right=GPIO_ReadPin(GPIOE, GPIO_PIN_3);  // sw right

●enableInterrupts();  で、タイマ割り込みをオンにします.

● while(1){} は、永久にループしつづけます.全ての制御は、タイマ割り込みルーチンで処理されます.



タイマ割り込みルーチンのキモのところを説明

●@far @interrupt void Tim2Update_isr(void)       20Hz=0.05秒ごとに割り込み処理するルーチン

●次回の割り込み準備のためTIM2割り込みフラグをクリアするおまじないをします.

  TIM2_ClearFlag(TIM2_FLAG_UPDATE);

●割り込みモニタLEDを点滅させます.ポート出力を反転させる関数です.
 
  GPIO_WriteReverse(GPIOD,GPIO_PIN_0);

●左側ポイント切替スイッチを制御するシーケンサルーチンです.

  switch(seqL){

●左側ポイント切替スイッチを読みとりまして、CPUが承知している状態から変化があったらスイッチが操作されたと判断し、seqLをインクリメントして、シーケンスを1に進めます.そして、割り込みルーチンからは脱出します.

  case 0: {
   sw_left=GPIO_ReadPin(GPIOE, GPIO_PIN_2);
   if(state_left!=sw_left);
   seqL++; break;
  }

●次の割り込みすなわち0.05秒後には、シーケンス=1なので、ここに到達します.もういちど、左側ポイント切替スイッチを読んで、CPUが承知してい る状態と同じだったら、チャタリングによる間違い情報だったんだと判断して、シーケンス=0に戻して、なにもせずに、割り込みを脱出します.
次に、左側ポイント切替スイッチが0か1かで、処理が分岐します.0の時だけ説明しますと、まず、片方のモニタLEDを光らせます.次に、Hブリッジの制御ポートである GPIOBを変化させます.左側ポイント切替スイッチに対応するHブリッジは、GPIODのbit 7,5,3,1 に配線してあります.bit 7,1をLOWにし、bit 5,3 を HIGH にして、通電します.
ポイント切替スイッチが1の時は、bit 7,1をHIGHにし、bit 5,3 を LOW にすることで、逆極性で通電します.
末尾では、今通電した状態を、CPUが承知している状態にセットしてから、シーケンス=2にして割り込みを脱出します.

  case 1: {
   sw_left=GPIO_ReadPin(GPIOE, GPIO_PIN_2);
   if(state_left==sw_left){ seqL=0; break; } // no action
   if(sw_left==0){
    GPIO_WriteHigh(GPIOD,GPIO_PIN_7); // monitor LED
    GPIO_WriteLow (GPIOD,GPIO_PIN_5); // monitor LED
    tmp = GPIO_ReadInputData(GPIOB);
    tmp = tmp & 0b01010101;
    tmp = tmp | 0b00101000;
    GPIO_Write(GPIOB, tmp); // actuator
   }
   else{
    GPIO_WriteLow (GPIOD,GPIO_PIN_7); // monitor LED
    GPIO_WriteHigh(GPIOD,GPIO_PIN_5); // monitor LED
    tmp = GPIO_ReadInputData(GPIOB);
    tmp = tmp & 0b01010101;
    tmp = tmp | 0b10000010;
    GPIO_Write(GPIOB, tmp); // actuator
   }
   state_left=sw_left;
   seqL++; break;
  }

●次の割り込みすなわち0.05秒後には、シーケンス=2なので、ここに到達します.
モニタLEDを消灯します.
Hブリッジ制御信号であるGPIOD bit7531を全部ゼロにして、通電を終わらせます.つまり、0.05秒しか通電しないわけです.
末尾でシーケンスをインクリメントしていますが、これは、ゼロにするべきですね.実害はないですが、バグです.  orz        割り込みから脱出します.

  case 2: {
   GPIO_WriteHigh(GPIOD,GPIO_PIN_7); // monitor LED
   GPIO_WriteHigh(GPIOD,GPIO_PIN_5); // monitor LED
   tmp = GPIO_ReadInputData(GPIOB);
   tmp = tmp & 0b01010101;
   GPIO_Write(GPIOB, tmp); // actuator off
   seqL++; break;
  }

●次の割り込みすなわち0.05秒後には、シーケンス=3なので、どこにも行きようがないので、defaultであるここに到達します.
defaultケースを日常的に利用するという、こういうシーケンサは反則ですので、皆さんはやらないようにしましょう.ではなんでdefaultがあるのかというと、電源投入直後にシーケンス=255とかありえない数字になってしまうリスクを回避するのが目的なんです.
改めて、モニタLEDを消灯し、Hブリッジをゼロにしているので、外見上はなにもやってないのと同じです.
末尾で、シーケンス=0 にして、次に左側ポイントスイッチが操作されるのを待ちます.

  default: {
   GPIO_WriteHigh(GPIOD,GPIO_PIN_7); // monitor LED
   GPIO_WriteHigh(GPIOD,GPIO_PIN_5); // monitor LED
   tmp = GPIO_ReadInputData(GPIOB);
   tmp = tmp & 0b01010101;
   GPIO_Write(GPIOB, tmp); // actuator off
   seqL=0; break;
  }

●右側ポイント切替スイッチを制御するシーケンサです.やっていることは、左側ポイント切替スイッチと同じなので解説は割愛します.異なるのは、Hブリッジの制御信号線が、GPIOD bit6420 であるところだけです.

  switch(seqR){




stm8_interrupt_vector.c

●プロジェクトを作ったときに、自動的に生成されるファイルですが、一部修正します.

●main.cで定義した割り込み処理用の関数をexternしておきます.

   extern @far @interrupt void Tim2Update_isr(void);  

●タイマ2の割り込み信号はIRQ13に接続されていますので、割り込みルーチンを、IRQ13にヒモ付けしておきます.

   {0x82, Tim2Update_isr}, /* irq13 */ 



stm8s.h

プロジェクトを作ったときに、自動的に生成されるファイルですが、一部修正します.


 /* #define STM8S208 */
 /* #define STM8S207 */
#define STM8S105                       これのコメントを外して、STM8S105であると宣言します
 /* #define STM8S103 */
 /* #define STM8S903 */



stm8s_conf.h

プロジェクトを作ったときに、自動的に生成されるファイルですが、一部修正します.

#define _CLK (1)            FWライブラリをつかうペリフェラルのコメントを外しておきます
#define _GPIO (1)
#define _TIM2 (1)






release  2010.9

inserted by FC2 system