智慧小車製作過程全紀錄: 三、軟體平臺--- Java 平臺串列埠通訊
嵌入式Linux上大部分都是有C/C++來做開發的,主要的原因還是為了效率,但本人最近幾年用Java比較多所以決定用Java比較多所以決定還是用Java來開發,再者個人認為現在硬體的發展,對於實時性沒有苛刻要求的環境Java足可以勝任了,所以言歸正傳,下面開始實際行動:
1、Java虛擬機器的安裝,OpenJava,Oracle Java都可以,這裡用Oracle Java為例
:
a. Ubuntu本身是Apt-get是沒有Oracle java的源的,所以首先的先新增源:
sudo sh -c ‘echo “deb http://ppa.launchpad.net/webupd8team/java/ubuntu
sudo sh -c ‘echo “deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main” >> /etc/apt/sources.list
sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys EEA14886
b 用apt-get update安裝即可,Ubuntu core安裝Oracle Java時間比較久,要耐心等待
.sudo apt-get update
sudo apt-get install oracle-java8-installer
2、Java串列埠通訊
Java串列埠通訊用到了Rxtxcomm這個包,
下載地址:最新版本rxtx 2.2pre2 http://rxtx.qbang.org/wiki/index.php/Download
安裝說明
http://rxtx.qbang.org/wiki/index.php/Installation_on_Linux
官方給出了詳細的安裝說明,但是按照這個安裝說明,在呼叫這個包的時候提示jar包和動態連結庫.so 檔案不一致的問題,這是這個版本的一個bug,解決辦法如下:
首先用apt-get 安裝,已操作過的可以忽略此步驟
apt-get install librxtx-java
執行完此步驟後,會在/usr/lib/jni/目錄下發現動態連結庫檔案librxtxSerial.so,這時候用cp命令將此檔案拷貝到Java Home下
cp /usr/lib/jni/librxtxSerial.so /usr/lib/jvm/java-8-oracle/jre/lib/arm
接下來下載原始碼,按照官方按照教程,在原始碼目錄執行如下命令:
sh ./configure
make
執行完後會發現原始碼目錄下多出一個RXTXcomm.jar,在Java工程中直接引用即可,也可以到百度網盤下載https://pan.baidu.com/s/1jHD0aj0
執行完成後,在NanoPC T3呼叫官方示例中的listport還是找不到串列埠,後來研究程式碼發現Linux中的裝置是用檔案來表示的,所有的裝置都是放在/dev目錄下的,而NanoPC T3的串列埠是用ttySAC1,ttySAC3,ttySAC4這樣的方式命名的,而rxtxcomm的串列埠查詢沒有匹配這種命名方式,可以看/src/gnu/io/RXTXCommDriver.java 577~581行的程式碼
只需要增加NanoPC T3的命名格式,重新編譯一下就好了,改完後的程式碼如下:
if(osName.equals("Linux"))
{
String[] Temp = {
"ttyS", // linux Serial Ports
"ttySA", // for the IPAQs
"ttySAC",///for friendarm
"ttyUSB", // for USB frobs
"rfcomm", // bluetooth serial device
"ttyircomm", // linux IrCommdevices (IrDA serial emu)
};
CandidatePortPrefixes=Temp;
}
現在可以呼叫官方sample中的connect開啟串列埠了,開啟串列埠3和4的方式如下:
connect(“/dev/ttySAC3”);
connect(“/dev/ttySAC4”);
官方connect函式程式碼如下:
public void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
OutputStream out = serialPort.getOutputStream();
BufferedReader r = new BufferedReader(reader);
//(new Thread(new ReaderSerial(r))).start();
//(new Thread(new WriterSerial(out))).start();
rs=new ReaderSerial(r);
// pool.execute(rs);
rs.start();
ws=new WriterSerial(out);
// pool.execute(ws);
// // ws.start();
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
3、 最後針對小車驅動對串列埠通訊重新包裝了一下
SerialComm.java 串列埠操作的封裝類
ReaderSerial.java 串列埠讀的封裝類
WriterSerial.java 串列埠寫的類
DriverCMD.java 小車底盤控制命令類,配合Arduino 程式碼的串列埠命令
SerialComm.java
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
public class SerialComm {
//private String msg="";
//private String lastmsg="";
private ReaderSerial rs=null;
private WriterSerial ws=null;
//ExecutorService pool = Executors.newCachedThreadPool();
public void setMsg(String msg) {
if (ws!=null){
//System.out.println("******step 3");
ws.setMsg(msg);
ws.writeSerial();
}
}
public SerialComm()
{
super();
}
public void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
OutputStream out = serialPort.getOutputStream();
BufferedReader r = new BufferedReader(reader);
//(new Thread(new ReaderSerial(r))).start();
//(new Thread(new WriterSerial(out))).start();
rs=new ReaderSerial(r);
// pool.execute(rs);
rs.start();
ws=new WriterSerial(out);
// pool.execute(ws);
// // ws.start();
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
public static void listPorts()
{
@SuppressWarnings("unchecked")
java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
while ( portEnum.hasMoreElements() )
{
CommPortIdentifier portIdentifier = portEnum.nextElement();
System.out.println(portIdentifier.getName() + " - " + getPortTypeName(portIdentifier.getPortType()) );
}
}
static String getPortTypeName ( int portType )
{
switch ( portType )
{
case CommPortIdentifier.PORT_I2C:
return "I2C";
case CommPortIdentifier.PORT_PARALLEL:
return "Parallel";
case CommPortIdentifier.PORT_RAW:
return "Raw";
case CommPortIdentifier.PORT_RS485:
return "RS485";
case CommPortIdentifier.PORT_SERIAL:
return "Serial";
default:
return "unknown type";
}
//return "";
}
}
ReaderSerial.java
import java.io.BufferedReader;
import java.io.IOException;
public class ReaderSerial extends Thread{
BufferedReader in;
public ReaderSerial ( BufferedReader in )
{
this.in = in;
}
public void run ()
{
try
{
String line;
while ((line = in.readLine()) != null){
System.out.println(line);
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
}
WriterSerial.java
public class WriterSerial/* extends Thread*/{
private OutputStream out;
private String msg="";
//private String lastmsg="";
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
System.out.println("******step 4 this.msg= "+this.msg);
}
public WriterSerial ( OutputStream out)
{
this.out = out;
}
public void writeSerial(){
if (msg != null && msg.length() != 0) {
System.out.println("******before write, the msg is " + msg);
try {
out.write(this.msg.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
DriverCMD.java
public class DriverCMD {
private SerialComm driverCMDComm;
private String stopcar="5";
private String forward="1";
private String backward="2";
private String right="3";
private String left="4";
private String automate="6";
private String manual="7";
public void openSAC(String portName){
driverCMDComm=new SerialComm();
try {
driverCMDComm.connect(portName);
System.out.println("******the SAC "+portName+" has been opened!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stop(){
driverCMDComm.setMsg(stopcar);
}
public void forward(){
//System.out.println("******step 2");
driverCMDComm.setMsg(forward);
}
public void backward(){
driverCMDComm.setMsg(backward);
}
public void right(){
driverCMDComm.setMsg(right);
}
public void left(){
driverCMDComm.setMsg(left);
}
public void manual(){
driverCMDComm.setMsg(manual);
}
public void automate(){
driverCMDComm.setMsg(automate);
}
public void mycmd(String cmdstr){
System.out.println("******"+cmdstr);
try{
if(cmdstr.equals("FORWARD")){
forward();
Thread.sleep(2000);
stop();
}
if(cmdstr.equals("BACKWARD")){
backward();
Thread.sleep(2000);
stop();
}
if(cmdstr.equals("RIGHT")){
right();
Thread.sleep(1000);
stop();
}
if(cmdstr.equals("LEFT")){
left();
Thread.sleep(1000);
stop();
}
if(cmdstr.equals("EXIT")){
System.exit(0);
}
if(cmdstr.equals("STOP")){
stop();
}
if(cmdstr.equals("MANUAL")){
manual();
}
if(cmdstr.equals("AUTOMATE")){
automate();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(0);
}
}
public void test(){
try {
System.out.println("******step 1");
forward();
Thread.sleep(3000);
backward();
Thread.sleep(3000);
right();
Thread.sleep(3000);
left();
Thread.sleep(3000);
stop();
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(0);
}
}
}
在main函式中可以按照如下方法呼叫:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
SerialComm.listPorts();
DriverCMD driver =new DriverCMD();
driver.openSAC("/dev/ttySAC3");
driver.test();
//......
}
}