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

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

 

 

 

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

 - 電子工作

  関連記事

耳コピミキサー 半田付け #1

お疲れ様です。高橋です。 耳コピ用ミキサーの半田付けを行いました。 ブレッドボー …

FM音源 FB-01の動作試験

お疲れ様です。高橋です。 先日、会社の大大大先輩からFB-01を貰ったので、本日 …

音階LED完成、YMZのノイズの原因判明

お疲れ様です。高橋です。 音階LEDの実装が完了しました。 青色LEDが眩しすぎ …

電子オルゴール 動作試験 #2

お疲れ様です。高橋です。 Pro Mini互換機とYMZ294、EEPROMで作 …

iPhoneでルンバを操作してみたい

お疲れ様です。高橋です。 突然ですがiPhoneでルンバを操作したいと思います。 …

ルネサス RX621でLチカするまで

お疲れ様です。高橋です。 とある事情のため購入した、ルネサスのRX621マイコン …

YMZ294の基板が動いた。

お疲れ様です。高橋です。 先日「ブレッドボード上のYMZ294をユニバーサル基板 …

4桁7セグLEDを基板に実装

お疲れ様です。高橋です。 昨日に引き続き今日も奇跡的に早く帰宅する事が出来たため …

bluetoothモジュールHC-06とAndroid

お疲れ様です。高橋です。 先日AliExpressで購入したbluetoothモ …

電子オルゴール 回路図

お疲れ様です。高橋です。 電子オルゴールの回路図を書いてみました。 実体配線図よ …