Arduino通过串口与linux上的java进程通讯

来源:互联网 发布:淘宝全屏海报热点代码 编辑:程序博客网 时间:2024/06/08 03:03

【原创文章,转载请注明出处,谢谢】

arduino官网有篇文章,自己研究了半天才偶然发现,真是。。。踏破铁鞋无觅处。。。

http://playground.arduino.cc/Interfacing/Java

最近好久没认真研究arduino了,这几天又想起这个事打算实验下,现把过程记录在下面。

我使用的是64位的Ubuntu系统。

首先,下载Rxtx,Rxtx是一个用于多平台串口和并口通讯的java扩展包:

http://rxtx.qbang.org/wiki/index.php/Main_Page

解压后,将RXTXcomm.jar,复制到 jdk/lib下,将x86_64/的 librxtxSerial.so复制到 jdk/amd64/lib 下。

然后在eclipse中右键单击项目,选择“build path”,选择“add external jars”,找到前面的jar包,确定。

注:我在实际测试中发现,在java程序中调用CommPortIdentifier.getPortIdentifiers()取不到通过usb链接的arduino,原因不明,网上有人认为是rxtx新版本的bug。解决办法是在调用该方法之前,增加下面这行代码:

System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyACM0")

其中的“/dev/ttyACM0”可以通过别的方法得到,比如直接查看arduino专用的IDE的右下角,会有连接到哪个串口的提示,再比如,在用于processing语言的PDE中,使用下面的方法打印所有已连接串口设备也可以找到:

println(Serial.list());

java代码如下,read和write方法分别用于从arduino“读”数据和向arduino“写”数据。

【注意】向arduino写数据时,要在建立链接后至少让线程sleep 1 秒之后再继续操作。
package com.xiaomi.micloud.utils;

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

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Enumeration;

public class ArduinoSerial {

    private SerialPort serialPort;
    private InputStream in;
    private OutputStream out;

    public ArduinoSerial(SerialPort serialPort) throws IOException {
        this.serialPort = serialPort;
        this.in = serialPort.getInputStream();// 得到输入流
        this.out = serialPort.getOutputStream();// 得到输出流
    }

    public void read() {
        try {
            // 进行输入输出操作
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void write() throws InterruptedException {
        try {
            Thread.sleep(2000);// 链接后暂停2秒再继续执行
            System.out.println("connected!");
            // 进行输入输出操作
            OutputStreamWriter writer = new OutputStreamWriter(out);
            BufferedWriter bw = new BufferedWriter(writer);
            for (int i = 0; i < 3; i++) {
                bw.write("a");
                bw.flush();
            }
            bw.close();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() throws IOException {
        in.close();
        out.close();
    }

    public static void main(String[] args) {
        try {
            System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyACM0");
            Enumeration portList = CommPortIdentifier.getPortIdentifiers();
            CommPortIdentifier portId = null;
            while (portList.hasMoreElements()) {
                CommPortIdentifier tmpPortId = (CommPortIdentifier) portList.nextElement();
                System.out.println(tmpPortId.getName());
                // 如果端口类型是串口则判断名称
                if (tmpPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                    if (tmpPortId.getName().startsWith("/dev")) {
                        portId = tmpPortId;
                    }
                }
            }
            if (portId == null) {
                System.out.println("not detected");
            }
            SerialPort serialPort = (SerialPort) portId.open("ArduinoSerial", 1000);// 打开串口的超时时间为1000ms
            // 设置串口速率为9600,数据位8位,停止位1们,奇偶校验无
            serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            ArduinoSerial testObj = new ArduinoSerial(serialPort);
            testObj.read();
            testObj.close();
            serialPort.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

以下是在arduino上运行的程序,

这段代码将使arduino板在收到从java程序发送的数据时,令位于13号数字接口的LED闪烁一次。

void setup() {
    pinMode(13,OUTPUT);
    Serial.begin(9600);
}

void loop() {
    if(Serial.available()){
        int readByte = Serial.read();
        Serial.println((char)readByte);
        digitalWrite(13,HIGH);
        delay(400);
        digitalWrite(13,LOW);
        delay(400);
        digitalWrite(13,HIGH);
        delay(400);
        digitalWrite(13,LOW);
        delay(400);
    }
}

下面这段代码比较简单,将使arduino板向串口循环写入数据,然后java程序可运行read()方法获取数据:

注意:由于java程序中用的是in.readLine()获取数据,所以arduino程序发送的数据必须以“\n\r”结尾,或者直接用Serial.println()方法。

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

void loop() {
    Serial.print("a");
    Serial.println("b");
    //等效于Serial.print("ab\n\r");
    delay(1000);
}

//TODO 下一步是实验通过一个USB Hub链接多个arduino板,估计只是多识别到几个串口而已。

1 0
原创粉丝点击