curious4dev

中国旅行、Arduinoなどを使った電子工作、その他色々。

*

PCとArduinoをJavaでシリアル通信

 

お疲れ様です。高橋です。

先日作ったコレ。

042901

よくよく考えると、書き込む際にいちいちArduinoに曲データを解釈させる必要性が無い事に、帰宅中ハタと気づいてしまいました。

PC上で生成したArduino用コードをいちいちArduinoに食わせるまでもなく、先日のバイナリルールに則って変換したバイト配列をシリアル通信でそのまま何か使って書き込めば良いのです。

043002

そうすると、書き込み時に毎回Arduino側でスケッチを作成する必要も無いので、純然たる書き込みスケッチと読み込みスケッチさえあれば、もっと簡単。

Javaでシリアル通信

Arduino IDEはシリアルモニターがあるのですが、バイナリデータは書き込めないような感じです。PCで動く、ArduinoのCOMポートに対してシリアルでデータを書き込むためのツールが必要です。Androidアプリ開発用のためにEclipse環境が整っていましたので、Javaで作ることにしました。

基本設計は、

  1. smf2ymzで出力したArduino用コードをどっかに保存 (e.g. d:/Arduino/sample.txt)
  2. Arduinoとのシリアル通信用COMポートを設定する (e.g. COM3)
  3. bpsを設定する (e.g. 9600)
  4. シリアル通信用の準備
  5. ファイルを1行ずつ読み込み、バイト配列に変換する
  6. 書き込む
  7. 最後に終了用バイト配列を書き込む

という感じ。

ライブラリを調達

Javaでシリアル通信をする際、ライブラリが必須です。

Windows 64bit用のライブラリはhttp://fizzed.com/oss/rxtx-for-javaからダウンロード出来ました。

mfz-rxtx-2.2-20081207-win-x64.zipを展開すると、下記のようなファイル達が解凍されます。

043003

Install.txtを読めばわかるのですが、jarを適当なパス(lib系)に配置し、dllも適当なパス(bin系)に配置します。

どこに配置すれば良いのか不明な場合は、JAVA_HOMEを確認するなり、

System.out.println(System.getProperty("java.library.path"));

を動かすなりして、調べます。

Javaでの実装

下記を作りました。

package serialTest;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

public class SerialWrite {

    // -- bps
    public static String COM_PORT = "COM3";
    public static int BPS = 9600;
    public static String FILE_PATH = "D:/Arduino/sample.txt";

    public static void main(String arg[]) throws IOException {

        BufferedReader br = null;
        SerialPort port = null;
        OutputStream out = null;
        try {

            /***************************************************
             * create serial connector
             ***************************************************/
            // create serial ID
            CommPortIdentifier comID = CommPortIdentifier.getPortIdentifier(COM_PORT);
            // open ID (application_name, timeout)
            CommPort commPort = comID.open("SerialTest02", 2000);
            // cast to port
            port = (SerialPort) commPort;

            /***************************************************
             * configure serial port
             ***************************************************/
            port.setSerialPortParams(BPS, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);

            out = port.getOutputStream();

            /***************************************************
             * write data to Serial
             * 
             * read from Arduino code exported by kalshagar's library.
             * https://kalshagar.wikispaces.com/Arduino+and+a+YMZ294
             * 
             ***************************************************/

            br = new BufferedReader(new FileReader(FILE_PATH));
            String line = "";
            int intValue = 0;
            int intAddress = 1;
            char[] data = { 0x00, 0x00, 0x00 };

            while ((line = br.readLine()) != null) {
                // set command to byte #1.
                if (line.indexOf("set_ch") >= 0) {
                    data[0] = 0x01;

                    // set channel to byte #2.
                    if (line.indexOf("ADDR_FREQ_A") >= 0) {
                        data[1] = 0x01;
                    } else if (line.indexOf("ADDR_FREQ_B") >= 0) {
                        data[1] = 0x02;
                    } else if (line.indexOf("ADDR_FREQ_C") >= 0) {
                        data[1] = 0x03;
                    }
                    intValue = readValue(line, ",", "\\)");
                    data[2] = (char) intValue;
                } else if (line.indexOf("delay") >= 0) {
                    data[0] = 0x02;
                    intValue = readValue(line, "\\(", "\\)");
                    data[1] = (char) (intValue / 100);
                    data[2] = (char) (intValue % 100);
                }
                writeDataToSerial(intAddress, out, data);
                intAddress += 3;
                if (intAddress % 64 == 0) intAddress++;
            }
            data[0] = 0x03;
            data[1] = 0x00;
            data[2] = 0x00;
            writeDataToSerial(intAddress, out, data);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            br.close();
            out.close();
            port.close();
        }

    }

    public static int readValue(String line, String regex1, String regex2) {

        String[] ary01 = line.split(regex1, 0);
        String[] ary02 = ary01[1].split(regex2, 0);
        int intShort = Integer.parseInt(ary02[0]);
        return intShort;
    }

    public static void writeDataToSerial(int intAddress, OutputStream out, char data[]) throws IOException {

        System.out.print("Address [" + intAddress + "] data [");
        System.out.print(Integer.toHexString(data[0]));
        System.out.print(" ");
        System.out.print(Integer.toHexString(data[1]));
        System.out.print(" ");
        System.out.println(Integer.toHexString(data[2]) + "]");
        // out.write(data[0]);
        // out.write(data[1]);
        // out.write(data[2]);

    }
}

実行結果

テキストから読み込んだ物は正常にバイト配列にする事が出来ました。

043004

シリアル通信も多分問題ないけど、明日は書き込みスケッチの実装です。

 

 

 

以上、よろしくお願い致します。

 - 電子工作

  関連記事

クオーツ時計を100倍速&リバースモード付きに改造してみた。

お疲れ様です。高橋です。 今日、奥さんから壊れた時計を貰いました。電池を入れ替え …

音階LED仮組み

お疲れ様です。高橋です。 先日設計し直した音階LEDを、B型基板上に部品を載せて …

MIDI INの実験

お疲れ様です。高橋です。 Arduino+YMZをMIDI化するための第一歩の実 …

Raspberry Pi2 model B

お疲れ様です。高橋です。 今年見た初夢、「猫×おもちゃ×動画×アプリ」の実現のた …

耳コピを簡単にするミキサー構想

お疲れ様です。高橋です。 私が普段耳コピをする時は、iPhoneで音楽を鳴らしな …

Arduino電源ON/OFF機

お疲れ様です。高橋です。 Arduinoを使っている時、特に2個とか複数同時に使 …

YMZシールドのMIDI化を検討

お疲れ様です。高橋です。 Arduino UNOにYMZシールドをくっつけ、さら …

赤外線リモコンをケースに格納

お疲れ様です。高橋です。 先日作ったATtiny13Aの赤外線リモコンを、ケース …

Arduino nano互換機でオナラ検知デバイス

お疲れ様です。高橋です。 今日のお昼、会社の大先輩から、綺麗にケーシングした自作 …

aitendoで買った4桁7セグLEDを使う

お疲れ様です。高橋です。 aitendoの4桁7セグLED aitendoで1個 …