ユーザ用ツール

サイト用ツール


dsshieldauto

差分

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

この比較画面にリンクする

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
dsshieldauto [2018/01/21 09:37]
yaasan [タクトスイッチによるルート切り替え]
dsshieldauto [2018/01/27 08:44] (現在)
yaasan [C言語の基本]
行 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で並列処理を書くのが難しいため。
 +  * 大電流を消費する環境。
 +  * 大きなレイアウト。
  
 ===== 必要な物 ===== ===== 必要な物 =====
行 42: 行 56:
 ==== 全体の構成 ==== ==== 全体の構成 ====
  
-Arduinoのスケッチは、setup()とloop()で大きく構成されます。一方で、AUTOスケッチでは、user_init()とuser_program()の2つで構成されます。setup()とloop()は、DCC制御で使用しておりますので、user_の関数にプログラミングしていただきます。なお、user_initはsetupからコールされています。user_programはloopからコールされています。ほとんど同じように使用することが出来ます。+Arduinoのスケッチは、setup()とloop()で大きく構成されます。一方で、AUTOスケッチでは、user_init()とuser_program()の2つで構成されます。\\ setup()とloop()は、DCC制御で使用しておりますので、user_の関数にプログラミングしていただきます。なお、user_initはsetupからコールされています。user_programはloopからコールされています。ほとんど同じように使用することが出来ます。
  
 +{{::dsauto_route6.png|}}
 ==== 使用できるピン ==== ==== 使用できるピン ====
  
行 78: 行 93:
 |アナログおよび\\ デジタル入出力ピン|A2,A3| デジタルに加え、光センサや可変抵抗器などのアナログセンサを使えます。 | |アナログおよび\\ デジタル入出力ピン|A2,A3| デジタルに加え、光センサや可変抵抗器などのアナログセンサを使えます。 |
 |I2C通信または\\ アナログおよび\\ デジタル入出力ピン|A4,A5|上記に加え、I2C通信が使用できます。wire.hをインクルードする必要があります。| |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です。\\ 
行 98: 行 114:
 |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検出"); | |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>
行 115: 行 212:
 void user_program(void) void user_program(void)
 { {
- SerialDS.println("Power On");+ Serial.println("Power On");
  CMD_Power(1);  CMD_Power(1);
   
行 122: 行 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){}
行 144: 行 241:
  
 ==== タクトスイッチによるルート切り替え ==== ==== タクトスイッチによるルート切り替え ====
 +
 +詳細は、[[http://powerele.sblo.jp/article/182189558.html|管理者ブログの記事(DSシールドをPLCのようにする その3)]]を参照ください。
  
 <code> <code>
行 202: 行 301:
 Youtube動画:\\  Youtube動画:\\ 
 {{youtube>JmZzkg3p--U?medium}} {{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.1516495020.txt.gz · 最終更新: 2018/01/21 09:37 by yaasan