ユーザ用ツール

サイト用ツール


dsshieldauto

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
dsshieldauto [2018/01/21 08:56]
– [主な命令] yaasan
dsshieldauto [2018/01/27 08:44] (現在)
– [C言語の基本] yaasan
行 1: 行 1:
 ====== DSshieldAUTO ====== ====== DSshieldAUTO ======
  
-DSshieldAUTOは、[[dsshield]]とArduinoUNOだけで、パソコンなしに小規模な自動運転を実現するためのソフトウェアソリューションです。 +DSshieldAUTO(AUTOスケッチ)は、[[dsshield]]とArduinoUNOだけで、パソコンなしに小規模な自動運転を実現するためのソフトウェアソリューションです。\\  
-小さいジオラマの車両やギミックをDCCで自動制御して、手を離しながら模型やジオラマをお楽しみいただける仕組みを提供しています。+小さいジオラマの車両やギミックを小さなArduinoUNO+[[dsshield]]によるコマンドステーション、DCCの自動制御ができます。手を離しながら模型やジオラマをお楽しみいただける仕組みを提供しています。ボリュームの入力でスピードを変えたり、ボタンで動き方を変えたり、いろいろな演出が出来ます。
  
 +
 +===== AUTOスケッチでできること =====
 +
 +  * パソコンなしで、DCC車両やポイントを気軽に動かせます。(最初のプログラミングするときだけ、パソコンを使用します)。ボタンやセンサーに応じて、車両やポイントを動かすことも出来ます。ArduinUNOにACアダプタをつなげるだけ。
 +  * DSシールドだけで完結。小規模な用途にも、数万円の高価なコマンドステーションは不要。
 +  * メルクリン(Marklin Motorola, MM1, MM2)やDCCの車両・ポイントに対応
 +  * 教育向け、研修向け、自分の技術向上、ジオラマのギミックのパワーアップなどに使用できます。
 +
 +
 +===== AUTOスケッチでできないこと =====
 +
 +  * 複雑な制御。並列で何個も複雑な条件で動く制御パターン。Arduinoで並列処理を書くのが難しいため。
 +  * 大電流を消費する環境。
 +  * 大きなレイアウト。
  
 ===== 必要な物 ===== ===== 必要な物 =====
行 30: 行 44:
  
 ===== スケッチの作り方 ===== ===== スケッチの作り方 =====
 +
 +
 +==== はじめに ====
 +
 +Arduinoの仕組みを使って、DCC鉄道模型の制御を行います。このため、Arduinoの入門書や知識が必要となります。
 +
 +参考サイト:\\ 
 +  * [[http://www.musashinodenpa.com/arduino/ref/|Arduino 日本語リファレンス]]
  
  
 ==== 全体の構成 ==== ==== 全体の構成 ====
 +
 +Arduinoのスケッチは、setup()とloop()で大きく構成されます。一方で、AUTOスケッチでは、user_init()とuser_program()の2つで構成されます。\\ setup()とloop()は、DCC制御で使用しておりますので、user_の関数にプログラミングしていただきます。なお、user_initはsetupからコールされています。user_programはloopからコールされています。ほとんど同じように使用することが出来ます。
 +
 +{{::dsauto_route6.png|}}
 +==== 使用できるピン ====
 +
 +ピン・端子を使用するときは、pinModeをuser_init()の中で必ずピンの設定します。
 +
 +<code>
 +//D8ピンを出力にする。
 +pinMode(8, OUTPUT);
 +
 +//D7ピンを入力にする。
 +pinMode(7, INPUT);
 +
 +//A2ピンを入力にする。
 +pinMode(A2, INPUT);
 +</code>
 +
 +実際に使う場合には、以下のように使用します。
 +
 +<code>
 +//D8ピンをHIGH(1)で出力する。ピンには5Vが出力される。0VにしたいときはLOW(0)を指定する。
 +digitalWrite(8, HIGH);
 +
 +//D7ピンからピン状態を読み取る。D7が5Vのときは1がaSensorに入る。0Vのときは0が入る。
 +int aSensor = digitalRead(7);
 +
 +//A2ピンからアナログの状態を読み取る。A2ピンが5Vのとき1024が入る。2.5Vのとき512、0Vのときは0になる。
 +int aAnalog = analogRead(A2);
 +</code>
 +
 +DSシールドで解放されているピンは以下の通りです。この他は、S88や電圧チェック機能で使用されています。
 +なお、いかに記載はありませんが、5V、3.3V、GNDピンは自由に使用できます。
 +
 +|デジタル入出力ピン|D7,D8,D11,D12| 0V,5Vの信号読み取りや、出力を行えます。ボタンの入力、LEDの出力に使用できます。 |
 +|アナログおよび\\ デジタル入出力ピン|A2,A3| デジタルに加え、光センサや可変抵抗器などのアナログセンサを使えます。 |
 +|I2C通信または\\ アナログおよび\\ デジタル入出力ピン|A4,A5|上記に加え、I2C通信が使用できます。wire.hをインクルードする必要があります。|
  
 ==== 主な命令 ==== ==== 主な命令 ====
  
-AUTOスケッチでは、Arduinoの命令は全部使えますが、たぶん混乱するだけなので、以下の命令まずは使ってみてください。+AUTOスケッチでは、Arduinoの命令は全部使えますが、たぶん混乱するだけなので、以下の命令を中心に、まずは使ってみてください。\\ 
  
-車両アドレス: 「ADDR_DCC+DCCアドレス」で指定してください。DCCアドレス8102であれば、ADDR_DCC+8102です。MM2アドレス5なら、ADDR_MM2+5です。 +車両アドレス: 「ADDR_DCC+DCCアドレス」で指定してください。DCCアドレス8102であれば、ADDR_DCC+8102です。MM2アドレス5なら、ADDR_MM2+5です。\\  
-アクセサリアドレス:「ADDR_ACC_DCC+DCCアクセサリアドレス」で指定してください。DCCポイント32であれば、ADDR_ACC_DCC+32です。MM2のポイント5であれば、ADDR_ACC_MM2+5です。+アクセサリアドレス:「ADDR_ACC_DCC+DCCアクセサリアドレス」で指定してください。DCCポイント32であれば、ADDR_ACC_DCC+32です。MM2のポイント5であれば、ADDR_ACC_MM2+5です。\\ 
  
  
行 50: 行 110:
 |CMD_LocSpeed(車両アドレス, 速度)| 速度は、0-1023で与えてください。| CMD_LocSpeed(ADDR_DCC+3,500);| |CMD_LocSpeed(車両アドレス, 速度)| 速度は、0-1023で与えてください。| CMD_LocSpeed(ADDR_DCC+3,500);|
 |CMD_LocDirection(車両アドレス, 進行方向);| 進行方向は0:FWD, 1:REVです。 |CMD_LocDirection(ADDR_DCC+3,1);| |CMD_LocDirection(車両アドレス, 進行方向);| 進行方向は0:FWD, 1:REVです。 |CMD_LocDirection(ADDR_DCC+3,1);|
-|CMD_LocFunction(車両アドレス, ファンクション番号, ファンクション状態);| ファンクション番号(0-28)を操作します。|CMD_LocFunction(ADDR_DCC+3,1,1);|+|CMD_LocFunction(車両アドレス, ファンクション番号, ファンクション状態);| ファンクション番号(0-28)を操作します。 |CMD_LocFunction(ADDR_DCC+3,1,1);|
 |CMD_LocFunctionMomentary(車両アドレス, ファンクション番号);| ファンクション番号(0-28)を操作します。0->1->0のMomentary動作を自動で行います。|CMD_LocFunctionMomentary(ADDR_DCC+3,1);| |CMD_LocFunctionMomentary(車両アドレス, ファンクション番号);| ファンクション番号(0-28)を操作します。0->1->0のMomentary動作を自動で行います。|CMD_LocFunctionMomentary(ADDR_DCC+3,1);|
 |CMD_Turnout(アクセサリアドレス, 分岐状態) | ポイントや信号機を操作します。0:分岐, 1:直進です。| CMD_Turnout(ADDR_ACC_DCC+32,1);| |CMD_Turnout(アクセサリアドレス, 分岐状態) | ポイントや信号機を操作します。0:分岐, 1:直進です。| CMD_Turnout(ADDR_ACC_DCC+32,1);|
 +|Serial.print, Serial,println| シリアル通信でPC等にメッセージを送れます。|Serial.println("車両1検出"); |
 +
 +==== C言語の基本 ====
 +
 +C言語の細かい記述方法は、本屋さんに売っているC言語入門の本を斜め読みしながら覚えてください。いきなり全てを覚える必要はありません。サンプルをいじりながら、修正してみて手探りしながら体で覚えていただく形が良いと思います。
 +
 +まず、変数を覚えましょう。
 +
 +<code>
 +//0-255の値を使うとき、aHako を作る
 +byte aHako;
 +//-32768~32767を使うとき、intを使う
 +int aHako;
 +</code>
 +
 +staticを付けると、変数は消されずに値が保持されます。
 +
 +<code>
 +static byte sHako;
 +</code>
 +
 +なお、C言語のルールでは無く、独自のルールですが、変数の名前は先頭に種類を示す小文字を付けると見やすくなります。関数内で宣言して使う変数には"a"(autoのa)、1つのソースファイル全体で使う変数には"g"(globalのg)、関数内でstatic宣言して使う変数には"s"(staticのs)とします。
 +
 +プログラムは基本3要素で成り立っています。シーケンス(順序実行)、分岐、繰り返しです。
 +
 +<code>
 +//シーケンスの例
 +Serial.println("Power On");
 +CMD_Power(1);
 +
 +CMD_LocFunction(ADDR_DCC + 3, 0, 1);
 +CMD_LocFunction(ADDR_DCC + 3, 1, 1);
 +CMD_Wait(500);
 +
 +Serial.println("Loc 3, Func 10, On");
 +CMD_LocFunction(ADDR_DCC + 3, 10, 1);
 +CMD_Wait(500);
 +</code>
 +
 +分岐は以下の通りです。
 +
 +<code>
 +//分岐の例。A,Bルートが交互に実行される
 +static byte sFlag0 = 10;
 +
 +if( sFlag0 == 10)
 +{
 + //Aルート
 + sFlag0 = 0;
 + Serial.println("Loc 3, Func 10, On");
 + CMD_LocFunction(ADDR_DCC + 3, 10, 1);
 + CMD_Wait(500);
 + CMD_LocFunction(ADDR_DCC + 3, 10, 0);
 +}
 +else
 +{
 + //Bルート
 + sFlag0 = 10;
 + Serial.println("Loc 3, Func 10, On");
 + CMD_LocFunction(ADDR_DCC + 3, 11, 1);
 + CMD_Wait(500);
 + CMD_LocFunction(ADDR_DCC + 3, 11, 0);
 +}
 +</code>
 +
 +繰り返しは、似たような命令を、シンプルに表現する方法です。繰り返しは、シーケンスと分岐を組み合わせるとできますが、C言語では専用命令forやwhileがありますので、これを使うと楽が出来て便利です。
 +
 +スピードを徐々にあげるような命令は、繰り返し命令を使うと短く記載できて楽です。
 +
 +<code>
 +//繰り返しの例。車両のスピードを変える
 +
 +for( int i = 0; i < 11; i++)
 +{
 + CMD_LocSpeed(ADDR_DCC + 3, i * 10);
 + CMD_Wait(200);
 +}
 +
 +</code>
  
 ===== スケッチの例 ===== ===== スケッチの例 =====
  
 ==== アドレス3車両のファンクション操作 ==== ==== アドレス3車両のファンクション操作 ====
 +
 +車両のファンクションを動かすサンプルです。[[http://powerele.sblo.jp/article/182179937.html|DSシールドをPLCのようにする その2(挫折&方針変更)]]で詳細を紹介しています。
 +
  
 <code> <code>
行 62: 行 204:
 /*  User Program Area                                            */ /*  User Program Area                                            */
 /*****************************************************************/ /*****************************************************************/
 +
 +void user_init(void)
 +{
 +
 +}
  
 void user_program(void) void user_program(void)
 { {
- SerialDS.println("Power On");+ Serial.println("Power On");
  CMD_Power(1);  CMD_Power(1);
   
行 72: 行 219:
  CMD_Wait(500);  CMD_Wait(500);
   
- SerialDS.println("Loc 3, Func 10, On");+ Serial.println("Loc 3, Func 10, On");
  CMD_LocFunction(ADDR_DCC + 3, 10, 1);  CMD_LocFunction(ADDR_DCC + 3, 10, 1);
   
  CMD_Wait(500);  CMD_Wait(500);
   
- SerialDS.println("Loc 3, Func 11, On");+ Serial.println("Loc 3, Func 11, On");
  CMD_LocFunction(ADDR_DCC + 3, 11, 1);  CMD_LocFunction(ADDR_DCC + 3, 11, 1);
   
  CMD_Wait(500);  CMD_Wait(500);
   
- SerialDS.println("Loc 3, Func 9, On");+ Serial.println("Loc 3, Func 9, On");
  CMD_LocFunction(ADDR_DCC + 3, 9, 1);  CMD_LocFunction(ADDR_DCC + 3, 9, 1);
   
  CMD_Wait(500);  CMD_Wait(500);
   
- SerialDS.println("End...");+ Serial.println("End...");
  /* 永久ループ(終了) */  /* 永久ループ(終了) */
  while(1){}  while(1){}
行 94: 行 241:
  
 ==== タクトスイッチによるルート切り替え ==== ==== タクトスイッチによるルート切り替え ====
 +
 +詳細は、[[http://powerele.sblo.jp/article/182189558.html|管理者ブログの記事(DSシールドをPLCのようにする その3)]]を参照ください。
  
 <code> <code>
行 102: 行 251:
 void user_init(void) void user_init(void)
 { {
-  
  pinMode(8, INPUT);  pinMode(8, INPUT);
  pinMode(11, INPUT);  pinMode(11, INPUT);
行 151: 行 299:
 {{http://buin2gou.sakura.ne.jp/sblo_files/powerele/image/DSAUTO_RouteSCH-thumbnail2.png}} {{http://buin2gou.sakura.ne.jp/sblo_files/powerele/image/DSAUTO_RouteSCH-thumbnail2.png}}
  
 +Youtube動画:\\ 
 +{{youtube>JmZzkg3p--U?medium}}
 +
 +
 +==== メルクリン車両の単純往復シャトル運転 ====
 +
 +メルクリン車両(Marklin Digital, Marklin Motorola 2)の往復シャトル運転です。
 +ファンクション操作や、ボタンでスタートをかけるなどの動きを実現しています。
 +
 +詳細は、[[http://powerele.sblo.jp/article/182228893.html|管理者ブログの記事(DSシールドをPLCのようにする その5)]]を参照ください。
 +
 +
 +<code>
 +/*****************************************************************/
 +/*  User Program Area                                            */
 +/*****************************************************************/
 +
 +void user_init(void)
 +{
 +
 + pinMode(8, INPUT);
 + pinMode(11, INPUT);
 + pinMode(12, INPUT);
 +
 + digitalWrite(8, HIGH);//内部プルアップON
 + digitalWrite(11, HIGH);//内部プルアップON
 + digitalWrite(12, HIGH);//内部プルアップON
 +
 + //F0 Light ON
 + CMD_LocFunction(ADDR_MM2 + 2, 0, 1);
 +
 + //SPEED 0
 + CMD_LocSpeed(ADDR_MM2 + 2, 0);
 +
 + //POWER ON
 + CMD_Power(1);
 + Serial.println("Power On");
 +}
 +
 +
 +void user_program(void)
 +{
 + static byte sButtonState = 1;
 +
 +
 + //ボタンが押されたとき、digitalReadは0を返す。押さないときは1を返す。
 +
 + if( digitalRead(8) == 0)
 + {
 + Serial.println("Button 1");
 +
 + sButtonState = 1;
 + CMD_Wait(100);
 +
 + /* 前進 */
 + //FWD
 + CMD_LocDirection(ADDR_MM2 + 2, 0);
 +
 + //警笛
 + CMD_LocFunction(ADDR_MM2 + 2, 2, 1);
 + CMD_Wait(2000);
 + CMD_LocFunction(ADDR_MM2 + 2, 2, 0);
 +
 + //急加速
 + CMD_LocSpeed(ADDR_MM2 + 2, 100);
 + }
 +
 + if( digitalRead(11) == 0)
 + {
 + Serial.println("Button 2");
 +
 + sButtonState = 2;
 + CMD_Wait(100);
 + //急停車
 + CMD_LocSpeed(ADDR_MM2 + 2, 100);
 + }
 +
 + if( digitalRead(12) == 0)
 + {
 + Serial.println("Button 3");
 +
 + sButtonState = 3;
 + CMD_Wait(100);
 + }
 +
 + /* S88のスキャン */
 + CMD_ScanS88();
 +
 +
 + if( CMD_GetS88(0) == 1)
 + {
 + Serial.println("S88 Detected");
 +
 + CMD_LocSpeed(ADDR_MM2 + 2, 100);
 + CMD_Wait(500);
 + CMD_LocSpeed(ADDR_MM2 + 2, 75);
 + CMD_Wait(500);
 + CMD_LocSpeed(ADDR_MM2 + 2, 50);
 + CMD_Wait(500);
 + CMD_LocSpeed(ADDR_MM2 + 2, 25);
 + CMD_Wait(500);
 + CMD_LocSpeed(ADDR_MM2 + 2, 0);
 + CMD_Wait(1000);
 +
 + //REV
 + CMD_LocDirection(ADDR_MM2 + 2, 1);
 + Serial.println("REV");
 +
 + //警笛
 + CMD_LocFunction(ADDR_MM2 + 2, 2, 1);
 + CMD_Wait(2000);
 + CMD_LocFunction(ADDR_MM2 + 2, 2, 0);
 +
 + /* 加速 */
 + CMD_LocSpeed(ADDR_MM2 + 2, 25);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 50);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 75);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 100);
 + CMD_Wait(3000);
 +
 + CMD_LocFunction(ADDR_MM2 + 2, 3, 1);
 + CMD_Wait(2000);
 + CMD_LocFunction(ADDR_MM2 + 2, 3, 0);
 +
 + /* 減速 */
 + CMD_LocSpeed(ADDR_MM2 + 2, 75);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 50);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 25);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 0);
 + CMD_Wait(2000);
 +
 + //FWD
 + CMD_LocDirection(ADDR_MM2 + 2, 0);
 + Serial.println("FWD");
 +
 + //Clear
 + CMD_ScanS88();
 +
 + //警笛
 + CMD_LocFunction(ADDR_MM2 + 2, 2, 1);
 + CMD_Wait(100);
 + CMD_LocFunction(ADDR_MM2 + 2, 2, 0);
 +
 + /* 加速 */
 + CMD_LocSpeed(ADDR_MM2 + 2, 25);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 50);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 75);
 + CMD_Wait(1000);
 + CMD_LocSpeed(ADDR_MM2 + 2, 100);
 + }
 +}
 +</code>
 +
 +Youtube動画:\\ 
 +{{youtube>mtIwlYd2Fds?medium}}
  
dsshieldauto.1516492619.txt.gz · 最終更新: 2018/01/21 08:56 by yaasan

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki