Arduinoとモータドライバで動く!鉄道模型のPWMコントローラ

記事内に広告が含まれています。

先日,大好きな電気機関車「EF64」のHOゲージを買った.

さっそく遊びたいのだけれど,鉄道模型を動かすためには,「パワーパック」が必要.

素直にパワーパックを買って遊ぶのもいいけど,手元にあったArduinoを使って鉄道模型を制御してみたいな~と思うのです.手づくり最高.せっかく学科でパワーエレクトロニクスも勉強したし.

というわけで,このパワーパックと同じような機能をもつ回路を,

ArduinoとモータドライバICを使って実装してみることにした.

まずはブレッドボード上で実装.

スポンサーリンク

鉄道模型用PWMパワーパック制作

今回作成した回路

鉄道模型はDCモータで動く.

前回記事で紹介した「ArduinoとモータドライバICによるDCモータの速度制御」を,ちょこっと改良すればいい.

この記事では,前回記事で紹介した制御回路からの変更点を書いていく.

具体的には以下の通り.

  1. 電源電圧を12Vに変更(ACアダプタ・ジャックの導入)
  2. 簡単なON/OFFスイッチの実装
  3. ユニトラックへの給電(線路側)
  4. PWM周波数の変更(→32kHz)

以下で順番に紹介していく.

全体のスケッチ・回路図

と,その前にまずは全体のスケッチと回路図を書いておく.

/* Arduino UnoとモータドライバICを用いてDCモータを制御する */
/* 電源ボタンとしてプッシュスイッチを使用するプログラム */
/* スイッチを押すとON,もう一度押すとOFF */
/* スイッチOFFの間はストップ(モータドライバの出力はHi-Z) */
const int IN1PIN = 9;
const int IN2PIN = 10;
const int BUTTON = 7;
const int TOGGLE_L = 12;
const int TOGGLE_R = 13;
const int VR = 3;     /* analogPin(=A3)*/

const int LED = 3;   /* 電源ON・OFF確認用LED接続PIN */

int old_button = 0;  /* buttonの前の値を保存しておく変数 */
int state = 0;       /* LED状態変数 (0:OFF, 1:ON) NORMALLY OFF */
  
void setup() {
  Serial.begin(9600);
  pinMode(IN1PIN, OUTPUT);
  pinMode(IN2PIN, OUTPUT);
  pinMode(BUTTON, INPUT);
  pinMode(TOGGLE_L, INPUT);
  pinMode(TOGGLE_R, INPUT);
  pinMode(VR, INPUT);
  pinMode(LED, OUTPUT);

  /* 分周比設定:分周比1 */
  /* 9, 10ピンの出力を31.4kHzとする */
  TCCR1B &= B11111000;
  TCCR1B |= B00000001;
  /* 分周比設定ここまで */
  int rpm = 0;
  float val_VR = 0.0;
  int front = LOW;
  int back = LOW;
  int button = 0;         // ボタン状態用変数
}

void loop() {
  /* analogRead()は整数型なのでfloatに型変換して除算する */
  float val_speed = (float)analogRead(VR) / 1023;  //analog値0~1023を0~1に変換
//float val_speed = analogRead(VR) / 1023 大きい型に合わせて計算されるのでこれだと0,1のみ
  
  int rpm = val_speed * 255;  // 最小値0,最大値X=100(<255)とする
  Serial.println(rpm);       // 値の監視

  /* 各スイッチの状態を変数に格納 */
  int button = digitalRead(BUTTON);
  int front = digitalRead(TOGGLE_L);
  int back = digitalRead(TOGGLE_R);

  /* buttonで電源ON/OFFを切り替え */
  if ((button == HIGH) && (old_button == LOW)){
    state = 1 - state;
    delay(10);                // チャタリング対策の遅延
  }
  old_button = button;        // 前状態をold_buttonへ格納
  if (state == 1) {
    /* 電源ONになったら */
    digitalWrite(LED, HIGH);  // LED ON(電源ON)
    if(front == HIGH){
      frontRotate(rpm);
    } else if(back == HIGH){
      backRotate(rpm);
    } else {
      brake(); /* 中立はブレーキ */
    }
  } 
  else {
    /* 電源がOFFになったら */
    digitalWrite(LED, LOW);   // LED OFF(電源OFF)
    stopRotate();             // STOP     
  }
}
/* 正転 */
void frontRotate(int val){
  analogWrite(IN1PIN, val); 
  analogWrite(IN2PIN, 0);
}
/* 逆転 */
void backRotate(int val){
  analogWrite(IN1PIN, 0); 
  analogWrite(IN2PIN, val);
}
/* ブレーキ */
void brake(){
  analogWrite(IN1PIN, 0);
  analogWrite(IN2PIN, 0);
}
/* ストップ */
void stopRotate(){
  analogWrite(IN1PIN, 0);
  analogWrite(IN2PIN, 0);
}

trainDrive_circuit_ver1
赤色が前回からの変更点

電源電圧を変更

鉄道模型は,2本の線路に直流電圧を印可する.

電圧が印可された2本の線路(正極,負極)上を,導電性をもつ車輪が通過する.

これにより,モータへ電流が流れて車両が走り続けることができる.

したがって,車両の速度制御は線路への電圧の大小によって決まる.

前回記事で紹介した,DCモータの速度制御も電圧で行っていたので,これをそのまま応用すればいい.

変更すべきなのは,「最大電圧」.前回使ったマブチモータは絶対定格が5V程度だったのに対し,HOゲージの車両(線路)には,通常12V 程度,長編成や高速走行は16V印可することができるようだ.

今回は短編成を,小さいエンドレス線路で走らせるので12Vあれば十分だろう.

DC 12 Vを供給するためには,ACアダプタ(コンセントのAC100VをDC電圧に変換)が必要.

これは秋月電子で買った.いろいろ調べた結果,2Aくらいで十分らしい.

ACアダプタの出力端子はDCプラグ(φ2.1).

モータドライバへの供給は以下の2通り考えられる.

今回は,「ブレッドボード用DCジャックDIP化キット」を使って,1.のルートで電力を供給することにした.このキットは,ブレッドボード上や基板上に,DCジャックを設置することができる優れもの.

はんだ付けしてブレッドボードに差し込んだら,ACアダプタの出力端子を差し込む.

DCジャックDIP化キット

ジャックの足元からジャンパ線で,Arduinoとモータドライバへ電源を供給する.

これで,DC12Vの電力が,モータドライバのOUTPUT端子から出力できるようになった.

ON/OFFスイッチ実装

前回マブチモータを制御する回路では,プッシュスイッチを押している間だけモータが回転するようになっていた.

今回は鉄道模型を運転する回路.

なので,スイッチを押すとON/OFF,運転の可不可が切り替えられるようにしたい.

この機能は,プッシュスイッチとLEDによって実現した.

達成したい動作は以下の通り.

LEDの状態とモータドライブの動作を対応させればよい.

LEDのボタンによる制御スケッチは,「Arduinoをはじめよう」に掲載されていたものを引用した.

追記したスケッチがこちら(…は省略した箇所)

const int LED = 3;   /* 電源ON・OFF確認用LED接続PIN */
int old_button = 0;  /* buttonの前の値を保存しておく変数 */
int state = 0;       /* LED状態変数 (0:OFF, 1:ON) NORMALLY OFF */

void setup() {
  ...
  pinMode(LED, OUTPUT);
  ...
}
void loop() {
...
/* 各スイッチの状態を変数に格納 */
 int button = digitalRead(BUTTON);
...
/* buttonで電源ON/OFFを切り替え */
 if ((button == HIGH) && (old_button == LOW)){
   state = 1 - state;
   delay(10);                // チャタリング対策の遅延
 }
 old_button = button;        // 前状態をold_buttonへ格納
 if (state == 1) {
   /* 電源ONになったら */
   digitalWrite(LED, HIGH);  // LED ON(電源ON)
   if(front == HIGH){
     frontRotate(rpm);
   } else if(back == HIGH){
     backRotate(rpm);
   } else {
     brake(); /* 中立はブレーキ */
   }
 }
 else {
   /* 電源がOFFになったら */
   digitalWrite(LED, LOW);   // LED OFF(電源OFF)
   stopRotate();             // STOP     
 }
}

電源ボタンの状態読み取り→LEDの状態読み取り→正転/逆転/ブレーキの切り替え

という,なんとも雑な設計になっている()

まあ,今回は動作速度は度外視して,動けばいいや~と思ってやっているので,そこはご容赦ください.

3番ピンは,前の回路ではモータドライブへのPWM出力信号用になっていたけど,PWM出力信号は9,10ピンへ変更した(後述).

走行中はLEDが点灯する

ユニトラック(線路)への給電

さて,ここまででブレッドボード上の制御回路とArduinoのスケッチは完成した.

あとは,ユニトラック(線路)へ給電するのみ.

給電には,給電用のケーブルがつながった専用の線路が必要.

今回は,amazonでKATOのレールを1本購入した.

今はブレッドボード上で実験している.が,フィーダー線路のコードの先っぽは,白いコネクタが付いている.

ブレッドボード上に,フィーダのコネクタに合う規格のコネクタを載せられれば一番いいけれど…今回はそこまでできなかった.なので,とりあえずコネクタは根元から切って,電線部を露出させた状態にした(さよならコネクタ…)

先の被覆を少し剥いて,短めのジャンパ線(両側の被覆を剥いておく)をはんだ付けした.

これで,給電用のケーブルを,ブレッドボードに直刺しできるようになった.

【追記: 2021/9/10】基盤への実装時には,給電線にコネクタを付けた。ブレッドボード用のコネクタもありそうなので,見た目が気になる場合は付けてみるといいかもしれない。

参考:Arduinoでつくる鉄道模型PWMコントローラ【基板実装編】

指すべき場所は,ずばりモータドライバICのOUTPUT端子.

給電線をOUT1,OUT2へ

ここに差し込むことで,制御されたOUTPUT電圧(最大12V)が線路へ給電できるようになる.

PWMの周波数変更

このままでも運転はできるけど,モータの励磁音が耳障り.

低速域で「ぷーん」と,貨物列車らしくない音が響く.

これは,Arduinoから出力されるPWM信号の周波数が原因.

デフォルトでは5,6番ピンが1kHz,それ以外は500Hzくらいらしい.

いずれの周波数も可聴域なので,この周波数で動作すると励磁音が聞こえてくるわけだ.

「音鉄」なのでモータの音は大歓迎なのだが・・・EF64という車両には似つかわしくない.しかも,鳴る音は一定の周波数でしかない.これなら,周波数を上げて鳴らないようにした方がいい.

周波数を変更するために,以下の記事などを参考にした.「Arduino PWM周波数変更」とか検索すれば,いっぱいヒットする.

同じようなことを考える人がいて,しかもわかりやすくまとめてくれている.インターネットは凄い.

これらを基にして,分周比とPWMを出力するピンを変更した.追記したのは以下のコード.

const int IN1PIN = 9;
const int IN2PIN = 10; 
...(中略)...
 /* 分周比設定:分周比1 */
  /* 9, 10ピンの出力を31.4kHzとする */
  TCCR1B &= B11111000;
  TCCR1B |= B00000001;
  /* 分周比設定ここまで */
...

意外とあっさりと書けた.

もちろん,周波数はある程度自由に変更できる.ただ,今回は可聴域外まで上げられればよかったので,これだけ追記しておいた.

もっと詳しい動作原理などは,以下の記事も参考になる.

Arduino で PWM の周波数を変える - Qiita
ATMega328p (168p) の Arduino で PWM の周波数を変えたい。ちゃんと理解をするには…
http://www.nina.jp/server/arduino/PWM/PWM.html

いずれモータを鳴らすためにも,ちゃんと理解したいところだ.

周波数変更のコードを追記したスケッチをArduinoに書き込む.

そして,出力ピンを3,11から9,10へ繋ぎ変える.

周波数を上げたスケッチでEF64を動かすと,励磁音はほとんどなくなった.

周波数はだいたい31.3~31.4kHz

滑らかな走り出しで,ジョイント音がはっきり聞こえるのが素晴らしい.

今後の課題

手作りのパワーパックで,EF64を運転することができるようになった.

概ねうまくいったのだが,これは直したいな~というところも見つかった.

進行方向逆側の前照灯も点灯してしまう問題

普通のパワーパックで鉄道模型を運転すると,前照灯は進行方向側のみ点灯する.(YouTubeに上がっているいろいろな走行動画を観ていただくとわかると思う)

しかし,今回ブレッドボード上に実装した回路では,進行方向逆側の前照灯も点灯してしまうのだ.これは「再現度」という観点からは,好ましくない現象だ.また,貨車を繋げることを考えると,「見栄え」もあまりよろしくない.

原因としては,PWM信号がOFFの時間帯で発生する逆起電力が考えられる.

PWM信号の周波数は32kHzに設定.つまり,モータドライブへ流す信号のON/OFFは,1秒間に32,000回切り替わっている.厳密にいうと,前照灯(LED)も1秒間に32,000回点灯消灯を繰り返している.

でも,前照灯はチラチラすることなく,しっかりと点灯している.

これは,人間の目では,1秒間に32,000回の点灯消灯を判別することはできない(OFF時間が短すぎる)からだ.

なので,Duty比を0(OFF時間0)にしない限りは,ずっとONに見えるのだ.

また,モータへの電流も,1秒間に32,000回ON/OFFを繰り返しながら流れる.でも,鉄道模型はガクガクせず,スムーズに走る.これは,PWM信号がOFFでも,モーターが「惰性」で回り続けているからだ.

モータが発電機になり「回生」が起こる

惰性で回り続けるモータは,つまり,電流ではなく「回転力」によって自力で回っている.

モータ(回転機)は

外から電流を流す→回転機(Motor)

力を加えて回転させる→発電機(Generator)

として働く.

水力発電や火力発電は,高温の蒸気で羽の付いたタービンを回すことで,電力を発生させている.PWM信号がOFF時間帯において,惰性で回っている鉄道模型のモータは,発電機として働いてしまうのだ.

この発電機が,進行方向とは逆向きの電力をレールへ向かって回生させてしまう.

ほんの数μsで発生する逆起電力だが,車両上にはLEDと電流制限用の抵抗のみが負荷として載っている状態.モータは発電機となっているため,電力消費はできない.

つまり,回生された逆起電力を消費するのはLEDしかないのだ.

LEDというのは微弱電流でも,閾値電圧を超えれば点灯できてしまう.

逆向きの回生電力が車両へ流れ込むことで,
進行方向と逆側のLEDが点灯してしまうのだ.

Duty比が100近くなり,最大電圧Vmax=12[V]付近の電圧で運転すると,逆起電力が前照灯点灯の閾値電圧を下回り,進行方向逆側のLEDは消灯することが確認されている.

「スナバ回路」で解決?

この問題の解決策としては,「進行方向逆側の前照灯以外で,逆起電力を消費する」ことが挙げられるのだろう.でも,どうやってやればいいんだろう?車両側に細工をするほどの技術はないので,できれば制御回路側を何とかしたい.

そう思って調べてみると,以下の記事が見つかった.

どうやら,「スナバ回路」というものを使えばいいらしい,ことがわかってきた.

スナバ回路とは、電気回路中にあってスイッチの遮断時に生じる過渡的な高電圧を吸収する保護回路のこと。 回路の電流を突然遮断すると自己インダクタンスによって電圧が急上昇するが、スナバ回路がこのスパイク状の高電圧を抑制することで、スイッチ自身や周囲の電子部品の損傷を防ぎ電磁ノイズを最小化する

結局,PWMはスイッチング動作を電気的に行っているにすぎず,回路の上流には車両の自己インダクタンスが存在している.急激に回路への電流をOFFにすると,自己インダクタンスによってスパイク状の電圧が起こるわけだ.

そのスイッチと並列にスナバ回路を接続することで,急峻な電圧を抑制し,ON時間帯に消費しようというわけだ.

スナバ回路はまだ実装はできていないので,ぜひとも試してみたい.実際の回路とか,回路定数とかは次回別の記事で紹介する予定.

【追記: 2021/9/10】スナバ回路付きモータドライバを使用することで,この問題は解決できた。

次の記事:Arduinoでつくる鉄道模型PWMコントローラ【基板実装編】

【重要な追記】モータドライバ故障

(2021.9.10)
ここまで組んで動いた回路だったが,ある時点で故障してしまった。故障個所は,モータドライバだ。Arduinoの制御信号は正しいものの,モータドライバからの出力が出なくなってしまった。

次の「基板実装編」には書いたが,重要なことなのでこちらにも追記した。

このモジュールを購入した動機というのは,以前使っていたモジュール(TB67H450)が原因不明の故障を引き起こしてしまったから。入力のPWM信号は正しそうなのだけど,出力が不連続になってしまっていた。

これについて,「デュアルモータドライバIC」を使うと,故障なく動いた。製品はこちら: KKHMF デュアルモータドライバモジュール TB6612FNG

いろいろ考えてみたけど,おそらく過電流検出が一要因だと思われる。モータドライバの多くは,一度過電流検出で停止した場合,リセットのための動作が必要になる。これを作って,壊した直後は思い当たらなかったけれど,リセット動作をすれば直るのかもしれない。

いままでこうやって自分で設計した電子回路を組むことはなかった。上記の原因が正しい場合,もしICに安全装置が付いていないと,ジュール熱によって火を噴きかねない事案だった。というわけで,教訓は以下。

教訓: 適切な電流値に収まるように設計すること

まとめ:とりあえず試運転完了!

以上,ArduinoとモータドライバICを使った,鉄道模型制御回路の紹介.

周波数変更だけは大変で,難しかったけれど・・・

それ以外はDCモータ制御回路の延長で動かすことができた.

やっぱり手作りはいい.

次は,前照灯問題のスナバ回路による解決,

これがうまくいったら基板上に実装してみようと思う.

回路設計とはんだ付けするぞ~

==今回使用した工作道具・素子==

【モータドライバIC】

TB67H450モータードライバーモジュール: 半導体 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作TB67H450モータードライバーモジュール秋月電子通商 電子部品通信販売

【DCジャックDIP化キット】

ブレッドボード用2.1mm標準DCジャックDIP化キット: ケーブル・コネクター 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作ブレッドボード用2.1mm標準DCジャックDIP化キット秋月電子通商 電子部品通信販売

【スイッチングACアダプタ―12V2A】

スイッチングACアダプター12V2A ATS024T-W120U: 電源・トランス 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作スイッチングACアダプター12V2A ATS024T-W120U秋月電子通商 電子部品通信販売

関連記事

タイトルとURLをコピーしました