シリアル3サムネ


こんにちは、猫子です。(プロフィールはこちら)
書きかけで放置してしまっていた、Arduinoゲームコントローラー記事ですが、
続きの更新はないのかとお問合せを頂きました。
遅くなってしまいすみませんメッセージありがたいです~(^^)

プログラム作るのは楽しいけど、アウトプットが面倒くさくなっちゃうんですよね~。
とはいえ、自分も勉強中はネットに上がっている情報にたくさん助けられたので、次の世代に恩返しして行きたいという気持ちだけはあります。なので、気軽にコメント、リクエストなど頂けるとブログを書くモチベーションになって嬉しいです!

前回、【Arduino→Visual Studio】へシリアル通信をしました。
今回は逆方向【Visual Studio→Arduino】へのシリアル通信です。

=================================================
(1) ゲームコントローラーを作ろう【Arduino】
(2) VisualStudioでシリアルを受信しよう【Arduino / Visual Studio】
(3) PC→Arduinoへシリアル通信しよう【Arduino / Visual Studio】←今ここ
(3) Windowsフォーム(C#)でゲームを作ろう【Visual Studio】前編
(4) Windowsフォーム(C#)でゲームを作ろう【Visual Studio】後編
=================================================

(1)で作成したArduinoの回路と、(2)で作成したWindowsFormを引き続き使います。
まだの方はそちらから見てみてくださいね!



Visual Studioのコード【送信側】

前回WindowsFormでのシリアルポートの設定は完了しているので、今回は単純に出力するだけです。

シリアルを1行出力するには、下記の関数を使用します。
serialPort1.WriteLine("Sukina_Moji");

ダブルクオーテーションの中には好きな文字列を挿入しましょう。
文字列は日本語でもいいのですが、文字コードでバグが起こる可能性があるので、アルファベットで書くのがよいでしょう。

シリアル出力する場所ですが、テストボタンを配置して確認します。
こちらも前回と同じく、テスト用なので実際のゲームでは使いませんが、
コツコツひとつずつ動作を確認するのが大事なのです!(・v・)

デザインウィンドウ → ツールボックス
3_3


ボタンをダブルクリックで配置します。
(検索窓に頭文字bを入力するとスムーズに見つかります)
3_4


ボタンができました。好きな場所にドラッグで配置します。
3_5


できたボタンをダブルクリックすると、ボタンクリックイベントのコードが自動生成されます。

        private void button1_Click(object sender, EventArgs e)
        {

        }

(もしくはボタンを選択した状態でプロパティ→イベント(稲妻マーク)→Clickをダブルクリックでも生成)
3_6


生成されたボタンクリックイベントの中に、先ほどのコードを入れます。
        private void button1_Click(object sender, EventArgs e)
        {
		serialPort1.WriteLine("Sukina_Moji");
        }

これで、ボタンをクリックしたときにArduinoに文字列を送るコードができました。


Arduinoのコード【受信側】


Arduinoのコードはこうなります。

  /* ==== シリアルデータ受信 ==== */
  int check_Serial = Serial.available();  // シリアルポートにデータがあるかを確認
  if (check_Serial > 0) {
    String inStr = Serial.readStringUntil('\n'); // データを読み込む
if (inStr == "Sukina_Moji") { //
tone(12, 261, 100); //♪ドの音 }
}
メインループの中で、毎回データを受信してるかをチェックし、あればinStrに読み込みます。
VisualStudio側で使用したWriteLineは一行書き込むメソッドなので、最後に改行コード'\n'が追加されています。
シリアル受信した文字列の終わりはこの改行コードで判定するわけです。
文字列inStrには、改行コード以前の文字が格納されます。
格納された文字列に応じて、処理(ここではスピーカーから音を鳴らす)を行います。

全体のソースコード

前回、前々回のコードと合わせるとこうなります。

Visual Studioのコード

namespace neko_game
{
    public partial class Form1 : Form
    {
        public string str;                  //シリアル受信用

        public Form1()
        {
            InitializeComponent();
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            str = serialPort1.ReadLine();
            this.Invoke(new EventHandler(Check_input));

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            serialPort1.Open();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            serialPort1.Close();
        }

        private void Check_input(object sender, EventArgs e)
        {
            textBox1.Text = str;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.WriteLine("Sukina_Moji");
        }
    }
}

ボタンを押すとシリアルに文字列を送信する処理が追加されました。

Arduinoのコード

#define NON   0 //無入力
#define LEFT  1 //←キー
#define UP    2 //↑キー
#define RIGHT 3 //→キー
#define DOWN  4 //↓キー

/* ==== 関数宣言 ==== */
int judge_analogKey(void);

/* ==== グローバル変数 ==== */
int pre_key = NON;        //前回キー記録

void setup() {
  Serial.begin(9600);

  pinMode(2, OUTPUT);   //LED
  pinMode(3, OUTPUT);   //LED
  pinMode(4, OUTPUT);   //LED

}

void loop() {

  /* ==== 十字キー入力を取得しシリアルに出力 ==== */
  int key = judge_analogKey();
  if (pre_key != key) {
    switch (key) {
      case NON:
        Serial.println("NON");
        break;
      case LEFT:
        Serial.println("LEFT");
        break;
      case UP:
        Serial.println("UP");
        break;
      case RIGHT:
        Serial.println("RIGHT");
        break;
      case DOWN:
        Serial.println("DOWN");
        break;
    }
  }
  pre_key = key;

  /* ==== シリアルデータ受信 ==== */
  int check_Serial = Serial.available();  // シリアルポートにデータがあるかを確認
  if (check_Serial > 0) {
    String inStr = Serial.readStringUntil('\n'); // データを読み込む
    if (inStr == "Sukina_Moji") {     // 
       tone(12, 261, 100);  //♪ドの音
    }
  }
}
  /*  ===== アナログキーのボタン判定をする関数 =====  */
  int judge_analogKey(void) {
    int keyVal = analogRead(A0);
    delay(10);

    if (keyVal > 1005) {                           /* 0Ω */
      return LEFT;
    } else if ( 990 <= keyVal && keyVal <= 1005 ) { /* 220Ω */
      return UP;
    } else if ( 505 <= keyVal && keyVal <= 515 ) {  /* 10kΩ */
      return RIGHT;
    } else if ( 5 <= keyVal && keyVal <= 12 ) {     /* 1MΩ */
      return DOWN;
    } else {                                        /* キー入力なし */
      return NON;
    }
  }

メインループの後半にシリアルデータ受信部分ができました。

Arduinoにプログラム書き込み後、VisualStudioを実行して、ボタンを押したときに音が鳴ったら成功です!

送信する文字列は命名センスが大事

今回はテストなので"Sukina_Moji"というふざけた文字列を送りましたが、あとから読んだらなんのこっちゃですよね。
みなさんはちゃんと内容に即した名前をつけてくださいね~!

この場合だと、音をならすので、"Buzzer", "Sound"などがよいでしょう。


良いプログラマの第一条件は、ネーミングセンスが良いことだという一説もあります。
名前はよく考えてつけましょう~!

通信部分のテストは完了


ここまでで、最もハマりやすい、シリアル通信の動作確認ができました!
(ITスラングの「ハマる」=問題が解決しないことの意。これけっこう日常で使っちゃうけど、通じないよね~)

次回からはゲームを作りこんで行きましょう~!

にほんブログ村 IT技術ブログへ
にほんブログ村に参加中。
いいね!と思ったらクリックしてね




▼今回使用した部品が全部入っている便利なスターターキットはこちら▼


▼Arduino UNOボード単体はこちら▼


▼この本が楽しい&わかりやすくてオススメです!▼



初回からおさらいする方はこちらへどうぞ。