Java Microbit Serial data connect 〜シリアル通信〜

イントロダクション

ここ数日、マイクロビットでのデータ通信をやりたいと思い。。。色々と調べていました。Bluetoothで繋ごうと思ったけど、WenBluetooth APIは制限が多く面倒なので、シリアル通信をやって見てはどうだろうか?と思い調べて見たところヒット!右中間を抜けて2ベースヒットくらいの勢いです。

ちなみに、今までやったのは以下のリンクにあります。

  1. MicrobitでHttpリクエストを飛ばすためのメモ
  2. Microbitで遊ぶ〜ボタンを押す〜
  3. Microbitで遊ぶ〜シリアル通信をする〜

マイクロビットからシリアル通信でデータを飛ばす→PCで受信することを確認したので、今度は受信したデータをHTTPリクエストで送信することを考えます。

そしたらJavaの出番かね?

このように思いました。じゃ、早速調べます。。。

「Javaでシリアル通信を行う」を調べて、見つけたのはjavax.commパッケージを使用してttyの入力を受け取る方法です。

javax.commパッケージのダウンロード

上のリンクからJARファイルをダウンロード。

そして、javax.commの使い方(サンプル)を見て実装(写経)します。

いつものように、ビルドパスの設定を行います。

  1. プロジェクトを右クリック
  2. プロジェクトのプロパティを開く
  3. Java BuildPathを選択する

そしてAdd External Jarsを選択して、ダウンロードしてきたJarファイルを選択します。 ※comm-2.0.jarを選択


そして写経する。。。

 

package jp.zenryoku.app.microbit;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;

import javax.comm.CommDriver;
import javax.comm.CommPortIdentifier;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;

/**
 * シリアル通信で送られてきたデータを受信します。
 * 使用する外部ライブラリ: javax.comm
 * 
 * @see http://www.java2s.com/Code/Jar/c/Downloadcomm20jar.htm
 * @author takunoji
 * 2018/12/05
 */
public class SerialReciever implements Runnable, SerialPortEventListener {
	/** シリアルポート(ID) */
	static CommPortIdentifier portId;
	/** 使用可能なポートのEnumeration */
	static Enumeration portList;
	/** 入力 */
	InputStream inputStream;
	/** シリアルポート */
	SerialPort serialPort;
	/** 受信するスレッド(Javaの起動スレッド) */
	Thread readThread;
	
	public static void main(String[] args) {
		// 初期化処理(必要な情報を集めます)
		initReciever(true);
		System.out.println("*** System Propertiees ***");
		System.out.println("java.home: " + System.getProperty("java.home"));
		System.out.println("**************************");
		// ポートが、あるか、ないか。。。
		boolean portFound = false;
		// デフォルトポート
		String defaultPort = "/dev/tty.usbmodemFA132";
		CommPortIdentifier.addPortName(defaultPort, CommPortIdentifier.PORT_SERIAL, null);
		if (args.length > 0) {
			// プログラム引数がある場合はこれをデフォルトポートにする
			defaultPort = args[0];
		}
		// ポートの取得
		portList = CommPortIdentifier.getPortIdentifiers();
		System.out.println("hasMoreElements: " + portList.hasMoreElements());
		while (portList.hasMoreElements()) {
			portId = (CommPortIdentifier) portList.nextElement();
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				String portName = portId.getName();
				System.out.println("portName: " + portName);
				if (defaultPort.equals(portName)) {
					System.out.println("PortFound: " + portName);
					portFound = true;
					SerialReciever recieve = new SerialReciever();
				}
			}
		}
		if (portFound == false) {
			System.out.println(defaultPort + " is not found...");
		}
		
	}

	/**
	 * コマンドを実行して必要な情報を集める
	 * @param isExecute プロパティの取得のみを行う場合はfalseに設定する
	 */
	public static void initReciever(boolean isExecute) {
		
		if (isExecute == false) {
			System.exit(0);
		}
	}
	public SerialReciever() {
		try {
		    serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);
		} catch (PortInUseException e) {}

		try {
		    inputStream = serialPort.getInputStream();
		} catch (IOException e) {}

		try {
		    serialPort.addEventListener(this);
		} catch (TooManyListenersException e) {}

		serialPort.notifyOnDataAvailable(true);

		try {
		    serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, 
						   SerialPort.STOPBITS_1, 
						   SerialPort.PARITY_NONE);
		} catch (UnsupportedCommOperationException e) {}

		readThread = new Thread(this);

		readThread.start();
	    }

	    /**
	     * Method declaration
	     *
	     *
	     * @see
	     */
	    public void run() {
		try {
		    Thread.sleep(20000);
		} catch (InterruptedException e) {}
	    } 

	    /**
	     * Method declaration
	     *
	     *
	     * @param event
	     *
	     * @see
	     */
	    public void serialEvent(SerialPortEvent event) {
		switch (event.getEventType()) {

		case SerialPortEvent.BI:

		case SerialPortEvent.OE:

		case SerialPortEvent.FE:

		case SerialPortEvent.PE:

		case SerialPortEvent.CD:

		case SerialPortEvent.CTS:

		case SerialPortEvent.DSR:

		case SerialPortEvent.RI:

		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
		    break;

		case SerialPortEvent.DATA_AVAILABLE:
		    byte[] readBuffer = new byte[20];

		    try {
			while (inputStream.available() > 0) {
			    int numBytes = inputStream.read(readBuffer);
			} 

			System.out.print(new String(readBuffer));
		    } catch (IOException e) {}

		    break;
		}
    } 

}

しかし、パソコンのOSに依存する実装しかできないため、シリアルポート通信を諦めるのでした。。。

よく考えてみれば、USBシリアルポートを使うんだもんなぁ。。。そりゃOSに依存するようなぁ(笑)

 

Microbitで遊ぶ〜シリアル通信をする〜

イントロダクション

前回は、マイクロビットでボタンを押したら△を表示するプログラムを作成しました。

Microbitで遊ぶ〜ボタンを押す〜

こいつをカスタムする

上の状態で、ボタンを押したのか、押してないのかがマイクロビット上で確認できるので、今度はこれに「シリアル通信」をつけて見ます。コードは下に。。。

そして、シリアル通信の確認をするためパソコンで受信した文字を表示するようにします。

<参考サイト>

  1. Macでのシリアル通信確認
  2. マイクロビットのドキュメント

<Macでの受信確認手順>

1:確認するためのプログラムがあるか確認する。

ターミナルを開き「ls /dev/tty.*」コマンドを入力

$ ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port
/dev/tty.usbmodemFA132

Bluetoothでの接続はペアリングなどが面倒なのでUSB接続usbmodemFA132を使用します。

上の確認ができたら以下の手順を実行します。

  1. マイクロビットに作成したコードをコンパイルしてダウンロード
  2. screen /dev/tty.usbmodemFA132 115200コマンドを入力
  3. マイクロビットのAボタンを押す

※シリアル通信確認時のポート番号は適当(なんでも良い)なものを使用して良いのですが、他のアプリケーションと被らないようにする必要があります。

下に実際にやって見た動画を作成したので参考になれば。。。


Microbitで遊ぶ〜ボタンを押す〜

イントロダクション

マイクロビットで遊んでみようと思います。

スマホのアプリもあるのですが、調子が悪いのでPCでコードを作成して実行します。

手順

  1. ブラウザでエディターを開きます。
  2. コード(ブロック)を書きます。
  3. ダウンロードします。
  4. 起動確認します。

<作成したコード>

左下にある「Download」ボタンを押下してhexファイルをダウンロードします。

microbitにファイルをコピペしてやります。


MicrobitでHttpリクエストを飛ばすためのメモ

作戦その1:ブロックからC++を呼び出す

イベントハンドラを使用する

下のブロックは

下のコードに変換されるらしい

// このメソッド(関数)がイベントに反応して起動する
void onButtonA(MicroBitEvent e)
{
    uBit.display.print("A");
}

int main()
{
    uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButtonA);
}

ということは、ブロックで作成したものを取得できるかもしれない。。。

→ブロック言語からC++が作成されるのであれば。。。

作戦その2:「ラジオ」ブロックを使用する

ラジオブロックのCコードは、uBit.serial.sendのようだ。

ここのサイトでは、以下の項目に関して記載がある

  1. MicrobitでのWifi接続手順
  2. TCP/IPでのリクエスト送信方法

しかし、なんで温度の表示を行う記事ばかりあるのかね?

 作戦その3

マイクロビットからUSBシリアルポートでのデータ通信を行う。

Javaでシリアルデータを受けてHttpリクエストを行う。参考サイト

Microbitで遊ぶ〜シリアル通信をする〜

Microbitで遊んでみる

マイクロビットで遊ぶ

とりあえず、ここをクリックして下のサイトに飛びます。

https://makecode.microbit.org/#editor

上記のような画面が開くと思います。※ログインとかが必要になるかも?

そして中央にある。「Blocks」の隣にある「JavaScript」をクリックすると。。。

ブロックがJavaScriptに変わります。そして下のようなコードを記述して見ます。

そして、元に戻すと。。。

こんなブロックができました。

実際のところ定義のみだから起動しませんが(笑)