ブログトップ 記事一覧 ログイン 無料ブログ開設

チラシ裏日記上等!! このページをアンテナに追加 RSSフィード Twitter

2011-05-05

RXTXを使ってArduinoと通信

| 23:36 | RXTXを使ってArduinoと通信を含むブックマーク RXTXを使ってArduinoと通信のブックマークコメント

Arduinoで遊ぼう

f:id:Tomato-360:20110505222243j:image

久しぶりにArduinoで遊びます。今回はArduinoに装着した自作LCDシールドに文字を表示させて遊んでみました。

RXTX

まずはjavaArduinoシリアル通信するためにRXTXというライブラリダウンロードします。Java Communication APIというのもあるのですが、Windows版がなぜかないという不思議。まぁその代わりにJava Communication APIと互換性のあるRXTXというライブラリを使います。

ですがそのライブラリもなぜか公式ページでダウンロードできないという不思議。やっぱりjavaシリアル通信する人なんてあんまりいないんですかね?組み込み屋さんじゃないのでよくわからないのですが。ということで下のリンク先でダウンロードできたのでそれを使用するといいかも。

Google Code Archive - Long-term storage for Google Code Project Hosting.

そしてそれを組み込んだソースはこちら。

package jp.gui.test.sirial;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

public class SirialCommunicator {
	private CommPortIdentifier portID;
	private SerialPort port;

	/**
	 * COMポート番号を取得する
	 * @return portArray
	 */
	public List<String> getComPort(){
		List<String> portArray = new ArrayList<String>();

		Enumeration portList = CommPortIdentifier.getPortIdentifiers();

		CommPortIdentifier portID;
		while(portList.hasMoreElements()){
			// リストからポートを取り出す
			portID = (CommPortIdentifier)portList.nextElement();

			if(!portID.isCurrentlyOwned()){
				if(portID.getPortType() == CommPortIdentifier.PORT_SERIAL){
					portArray.add(portID.getName());
				}
			}
		}

		return portArray;
	}

	/**
	 * ポートを開く
	 * @param portNum
	 * @return
	 */
	public Boolean openComport(String portNum){
		try {
			portID =  CommPortIdentifier.getPortIdentifier(portNum);
			port = (SerialPort) portID.open("SirialTest", 5000);

			//ボーレート、データビット数、ストップビット数、パリティを設定
			port.setSerialPortParams( 57600,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE );

			//フロー制御はしない
			port.setFlowControlMode( SerialPort.FLOWCONTROL_NONE );
		} catch (NoSuchPortException e) {
			e.printStackTrace();
			return false;
		} catch (PortInUseException e) {
			e.printStackTrace();
			return false;
		} catch (UnsupportedCommOperationException e) {
			e.printStackTrace();
			return false;
		}

		return true;
	}

	/**
	 * 送信
	 * @param text
	 */
	public void submit(String text){
		OutputStream output = null;
		try {
			byte[] data = text.getBytes();
			output = port.getOutputStream();
			//ここでしばらく待たないとうまく表示されない
			Thread.sleep(1000);
			output.write(data);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			try {
				output.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

			port.close();
		}
	}

}

これは外部のプログラムから呼び出すように作ったためこれだけじゃ動きませんのであしからず(見りゃわかる)。僕はGUIで動かすつもりでした。付録のソースは最後に。

Arduinoプログラム

次はArduinoシリアル通信で受信できるようにプログラムを組みます。いろいろなサイトを巡ってつぎはぎで作ったため自分でも完全に説明できないというていたらく。まぁ専門じゃないと言うことで許して欲しい。そうはいっても学校で使ってるんですけどね・・・。

#include <LiquidCrystal.h>

int data[128]={};
int incomingByte;
int dataLength = 0;
//LCD
LiquidCrystal lcd(12,11,5,4,3,2);

void setup(){
  Serial.begin(57600);
  
  //LCDの桁数と行数をセットアップ
  lcd.begin(16,2);
  lcd.clear();
}

void loop()
{
  // set the LCD cursor to (0,0):
  lcd.setCursor(0, 0);
  
  int count = Serial.available();
  if (count > 0) {
    dataLength = count;
    for(int i = 0; i < count; i++){
      incomingByte = Serial.read();
      data[i] = incomingByte;
    }
  }
  
  for(int i = 0; i < dataLength;i++){
    lcd.write(data[i]);
    delay(300);
  }
  
  delay(300);
  lcd.clear();
  delay(300);
}

シリアル通信で受け取ったデータをバッファして一文字ずつ表示している・・・はず。少なくともそういう風に見えた。いやはやちゃんと理解しないといけませんね。でも動くからよし!でもこういうスタンスで仕事とかしちゃだめだろって感じ。でも今は仕事じゃない!趣味だ!

結果どうなったか

どういう風な動きをするか動画で撮りました。以下のように動きます。

ねぇ?何のことはないでしょ?でもこれ作るのに結構時間かかりました。

まとめ

シリアル通信って難しいですね。ほとんどソフトのことしか勉強してこなかったからすこしハードよりのことになるとさっぱりです。でもできた瞬間は歓喜しました。こういう気持ちはいつまでも持っていたいですね。

さて、次はArduinoで何をしようか。そろそろ光とか光らせたりセンサ使って頭よさげなものを作っても良さそうじゃない?いろいろ考えてみたいと思います。

参考にしたサイト

参考にしたサイトをまとめます。

Arduino + Bluetooth + Androidで遊ぶ

Japaninoとシリアル通信してみる - andooのメモとか

no title

RXTXライブラリをインストールする - Javaでシリアル通信(2)

付録

javaSwingを使ったGUIのソースです。

package jp.gui.test;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTextField;

import jp.gui.test.sirial.SirialCommunicator;



public class GuiAndSirialTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		JFrame frame = new JFrame("GUIAndSirialTest");
		MainPanel mainPanel = new MainPanel();

		frame.setJMenuBar(mainPanel.bar);
		frame.getContentPane().add(mainPanel);
		frame.setSize(320, 240);
		frame.setVisible(true);

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

}

/**
 * MainPanelクラス
 *
 */
public class MainPanel extends JPanel implements ItemListener, ActionListener{
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	boolean flag = false;

	String comPort = null;
	SirialCommunicator communicator = new SirialCommunicator();

	//パネル
	JPanel radioPanel = null;
	JPanel textAriaPanel = null;
	JPanel buttonPanel = null;

	//ラジオボタンのグループ
	ButtonGroup group = new ButtonGroup();

	//ラジオボタン
	JRadioButton rButton1 = new JRadioButton("文字");
	JRadioButton rButton2 = new JRadioButton("数字");
	JRadioButton rButton3 = new JRadioButton("テキストフィールド");

	//ボタン
	JButton button1 = new JButton("Start");
	JButton button2 = new JButton("Stop");

	//ラベル
	JLabel label1 = new JLabel("Hello World!");
	JLabel label2 = new JLabel("123456");

	//テキストフィールド
	JTextField textField = new JTextField(15);

	JMenuBar bar = null;
	JMenu menu = null;

	/**
	 * MainPanelのコンストラクタ
	 */
	public MainPanel(){
		setLayout(new GridLayout(3,1));

		//各パネル
		radioPanel = new JPanel();
		textAriaPanel = new JPanel();
		buttonPanel = new JPanel();

		//ラジオボタンをグループ化
		group.add(rButton1);
		group.add(rButton2);
		group.add(rButton3);

		//ラジオボタンパネルに追加
		radioPanel.add(rButton1);
		radioPanel.add(rButton2);
		radioPanel.add(rButton3);

		//ボタンパネルに追加
		buttonPanel.add(button1);
		buttonPanel.add(button2);

		textAriaPanel.add(textField);

		this.add(radioPanel);
		this.add(textAriaPanel);
		this.add(buttonPanel);

		rButton1.addItemListener(this);
		rButton2.addItemListener(this);
		rButton3.addItemListener(this);

		button1.addActionListener(this);
		button2.addActionListener(this);

		//メニュー
		bar = new JMenuBar();
		menu = new JMenu("ポート番号");

		List<String> portList = communicator.getComPort();

		ButtonGroup group = new ButtonGroup();
		for(String port: portList){
			JRadioButtonMenuItem rItem = new JRadioButtonMenuItem(port);
			rItem.addActionListener(this);
			group.add(rItem);
			menu.add(rItem);
		}
		bar.add(menu);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == button1){
			if(comPort != null){
				if(communicator.openComport(comPort)){
					communicator.submit(textField.getText());
				}
			} else {
				textField.setText("Please Select COMPort");
			}
		} else if(e.getSource() == button2){
			flag = false;
		} else {
			comPort = e.getActionCommand();
		}
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		if(e.getSource() == rButton1){
			textField.setText("Hello world");
		} else if (e.getSource() == rButton2){
			textField.setText("12345");
		} else if (e.getSource() == rButton3){
			textField.setText("Black Ops");
		}
	}


}

Connection: close