PICマイコンを使ってNゲージレイアウトのポイントマシンと信号の制御機能を製作中。I2C通信を使って複数のPICマイコンを連携させようとしているが、この中にRaspberry Pi3も組み込む予定。Raspberry Pi3でI2C通信を使用する設定はずいぶん前に行っているが、再確認してみた。
Nゲージレイアウト用制御盤 (その4) PWMコントローラ
電気機関車の運転台を模した、PWMコントローラを製作中であるが、これはハンドル類が複数になる予定。
動いている列車を眺めるなら、スイッチ1つで運転ができるコントローラ(パワーパック)が欲しい。
ということでロータリースイッチ1つで運転できるPWMコントローラを作って制御盤に組み込んだ。
「ArduinoでPWMパワーパックを作ってみた」というページを参考にさせていただいて、それをベースにごちょごちょとカスタマイズ。
アリガトウゴザイマシタ・・。
制御盤部の工作
プログラムやハード部分がちょっこっと違ったバージョンを3つほど作成する予定。
4つ目のコントローラは手持ちのトミックスのパワーパック。
ここまでを制御盤上に置くことにした。
現在作成中の電気機関車の運転台を模したコントローラはPICマイコンを使ったものになるが、電車用も作るつもり。これらは制御盤とは離しておく。
コントローラ(パワーパック)の数は合計6台。
一方、レイアウトの方は固定式として線路配置の案もできた。
運転線区は上り線、下り線、機関区など8個のブロックになる。
運転線区とコントローラをくくりつけてしまうと、PWMコントローラで動かない列車はその線区で運転できなかったり、運転パターンがマンネリになるので、ロータリースイッチでコントローラと運転線区の対応が切り換えられるようにした。
8連のプッシュターミナルを制御盤の背面に取り付け、ここから線路に配線する。
右隣の2連のプッシュターミナルは、制御盤の外に作る電機用と電車用のコントローラからの入力。
表面には文字を印刷したシールを貼り付ける。
左側は各種音源の再生スイッチ。
右側はコントローラと運転線区の対応を切り換えるロータリースイッチ。
各種音源のMP3再生ボードの再生スイッチは基板上にタクトスイッチを配置、合板にはタクトスイッチ本体分が収まる穴をあけ、表面にはタクトスイッチの丸い頭の部分のみがでるようにした。
ロータリースイッチは軸の部分が樹脂製で長さを自由にカットできるタイプ。
つまみが表面にギリギリになるようにカットして合板に止めた。
左:ロータリースイッチ
右:タクトスイッチを配置した基板
スイッチを配置するパネル、完成。
8個ならんでいるロータリースイッチでコントローラと線路の対応が切り換えられる。
上り本線をコントローラ1で走らせたり、コントローラ2で走らせたりという感じで。
Nゲージレイアウト用制御盤 (その1)で作ったMP3再生ボードの再生スイッチ。
ロータリースイッチの左側は、こちらもPICマイコンで制御するつもりだが、駅の発車の合図、発車の際の汽笛類などのサウンドが再生される・・予定。
まだまだ、作りこむ部分がいっぱいあるのだが、なんとか形になってきた。
コントローラが動かない
冒頭にあるように、ここで製作したコントローラは、「ArduinoでPWMパワーパックを作ってみた」というHPを参考にさせてもらって作り始めた。
自分のレイアウト用にカスタマイズする予定なのだが、最初からカスタマイズすると動作しない時、何が悪いのか切り分けが面倒になるので、まずはHPに掲載されている回路図とソースプログラムをそのまま使用させてもらって構築。
電圧が出てこない
電源を投入すると7セグメントLEDに値が表示されたが、ロータリースイッチを回していくと多くのポジションで0などと表示され・・どうも、出力先には電圧が印加される気配がない。
ソースプログラムを見ると、ロータリースイッチの入力を判定する部分は、次の部分のよう。
#define MASCON masconvol( analogRead( 3 ) + 42) // ロータリースイッチ 1~12 int masconvol(int vol){ // マスコン位置検出 // 0~1023の入力を12段階に分ける さらに3段階に分けて真ん中の時だけ採用 // 中途半端な位置の時にでたらめな入力になるので int a; if ( (vol * 10 / 284) % 3 == 1 ){ a = 13 - vol / 85; } else { a = 0; } return a; }
#define MASCON masconvol( analogRead( 3 ) + 42) // ロータリースイッチ 1~12 int masconvol(int vol){ // マスコン位置検出 // 0~1023の入力を12段階に分ける さらに3段階に分けて真ん中の時だけ採用 // 中途半端な位置の時にでたらめな入力になるので int a; if ( (vol * 10 / 284) % 3 == 1 ){ a = 13 - vol / 85; } else { a = 0; } return a; }
推測するに、私が作成したロータリースイッチの回路からの入力では、analogReadで返される値は、3で割ったときに余りが1にならない?
ひとまず、何が返ってきているのか確認。
ロータリースイッチの部分のみをArduino unoのボードの5V端子とGND端子、A0端子にとりつけ、シリアルモニターに出力。
void setup() { Serial.begin(115200UL); } void loop() { int value = analogRead(A0); Serial.println(value); delay(1000); }
返ってきた値は、
1023 931 838 745 651 558 464 371 277 184 90 0
ちなみに、ロータリースイッチはノンショーティー。
上記のように1000ms毎にanalogReadすると、切り換えた瞬間に、たまに戻ってくる値が1くらいふらつくことがあるが、すぐに安定して上記のような同じ値を返してきている模様。
ということは、余りが1以外となる値で安定すると、マスコンの位置は常に0と判断される。
ロータリースイッチにつけている抵抗の誤差もあるし、電源も基準電圧回路ではないので、もし、動かない人がいれば、このあたりのソースを変更されたらいいんじゃないかなぁと思う。
ちがったら、ゴメン m(__)m
私の回路の場合、ロータリースイッチを回しきったところ(スイッチ 12)では0が返っているので、
#define MASCON masconvol( analogRead( 3 ) ) // ロータリースイッチ 1~12
とし、
int masconvol(int vol){ // マスコン位置検出 return 12 - (int)(((float)vol / 90.0) + 0.5); }
として試してみた。
プログラムを書き込んだマイコンを実回路上に組み込むとデバッグが面倒なんで、(int)(float)など、間違いがないようにこれでもかとキャストしているが・・余分なところは・・当然・・いりません(^^;
最後に「+ 0.5」 を入れているのは、スイッチ 11の時、89などと90以下の値が返った場合に0となるのを防止するための切り上げ。
ひとまず、アタイのはこれでOK。
よし、続いては自分の制御盤専用にカスタマイズじゃ。