2011-01-29 108 views
1

我正在研究一个简单的程序,用于从简单的旧串行端口读取连续的数据流。该程序是在Processing中编写的。执行数据的简单读取并转储到控制台上工作得很好,但是每当我为程序添加任何其他功能(图形,数据库条目)时,端口就会开始失步并且所有数据从串口开始变得腐败。处理/读取串行端口数据流崩溃程序

从串口输入数据是按以下格式:
A [TAB] //开始标志
数据1 [TAB]
数据2 [TAB]
数据3 [TAB]
数据4 [TAB]
数据5 [TAB]
数据6 [TAB]
数据7 [TAB]
数据8 [TAB]
COUNT [TAB] //消息数的计数发送
Z [CR] //结束标志,然后回车

那么作为说明,如果我运行下面的程序,只是把它输出到控制台,它运行没有问题罚款几个小时。如果添加图形功能或数据库连接,串行数据开始出现乱码,并且串行端口处理程序永远无法再正确解码该消息。我已经尝试了各种解决方法来解决这个问题,认为这是一个计时问题,但降低串口速度似乎没有改变。

如果您看到串口处理程序,我提供了一个大缓冲区,以防终止Z字符被切断。我检查以确保A和Z字符在正确的位置,反过来说创建的“子字符串”是正确的长度。当程序开始失败时,子字符串会持续失败,直到程序崩溃。有任何想法吗?我尝试了几种不同的阅读串口的方式,并开始怀疑我是否在这里失去了一些愚蠢的东西。

//Serial Port Tester 
import processing.serial.*; 
import processing.net.*; 
import org.gwoptics.graphics.graph2D.Graph2D; 
import org.gwoptics.graphics.graph2D.traces.ILine2DEquation; 
import org.gwoptics.graphics.graph2D.traces.RollingLine2DTrace; 
import de.bezier.data.sql.*; 

SQLite db; 
RollingLine2DTrace r1,r2,r3,r4; 
Graph2D g; 
Serial mSerialport;     //the serial port 
String[] svalues = new String[8];  //string values 
int[] values = new int[8];    //int values 
int endflag = 90;  //Z 
byte seperator = 13; //carriage return 

class eq1 implements ILine2DEquation { 
    public double computePoint(double x,int pos) { 
    //data function for graph/plot 
    return (values[0] - 32768); 
    } 
} 

void connectDB() 
{ 
    db = new SQLite(this, "data.sqlite"); 
    if (db.connect()) 
    { 
    db.query("SELECT name as \"Name\" FROM SQLITE_MASTER where type=\"table\""); 
    while (db.next()) 
    { 
     println(db.getString("Name")); 
    } 
    } 
} 

void setup() { 
    size(1200, 1000);   
    connectDB(); 
    println(Serial.list()); 
    String portName = Serial.list()[3]; 
    mSerialport = new Serial(this, portName, 115200); 
    mSerialport.clear(); 
    mSerialport.bufferUntil(endflag); //generate serial event when endflag is received 

    background(0); 
    smooth(); 
    //graph setup 
    r1 = new RollingLine2DTrace(new eq1(),250,0.1f); 
    r1.setTraceColour(255, 0, 0); 
    g = new Graph2D(this, 1080, 500, false); 
    g.setYAxisMax(10000); 
    g.addTrace(r1); 
    g.position.y = 50; 
    g.position.x = 100; 
    g.setYAxisTickSpacing(500); 
    g.setXAxisMax(10f); 
} 

void draw() { 
    background(200); 
    //g.draw(); enable this and program crashes quickly 
} 

void serialEvent (Serial mSerialport) 
{ 
    byte[] inBuffer = new byte[200]; 
    mSerialport.readBytesUntil(seperator, inBuffer); 
    String inString = new String(inBuffer); 
    String subString = ""; 
    int startFlag = inString.indexOf("A"); 
    int endFlag = inString.indexOf("Z"); 
    if (startFlag == 0 && endFlag == 48) 
    { 
    subString = inString.substring(startFlag+1,endFlag); 
    } 
    else 
    { 
    println("ERROR: BAD MESSAGE DISCARDED!"); 
    subString = ""; 
    } 

    if (subString.length() == 47) 
    { 
    svalues = (splitTokens(subString)); 
    values = int(splitTokens(subString)); 
    println(svalues); 

    // if (db.connect()) //enable this and program crashes quickly 
    // { 
    //  if (svalues[0] != null && svalues[7] != null) 
    //  { 
    //  statement = svalues[7] + ", " + svalues[0] + ", " + svalues[1] + ", " + svalues[2] + ", " + svalues[3] + ", " + svalues[4] + ", " + svalues[5] + ", " + svalues[6]; 
    //  db.execute("INSERT INTO rawdata (messageid,press1,press2,press3,press4,light1,light2,io1) VALUES (" + statement + ");"); 
    //  } 
    // } 
    } 
} 

回答

1

虽然我不熟悉你的特定平台,我从读你的问题的描述首先想到的是,你仍然有一个计时问题。在115,200bps的速度下,数据进入的速度非常快 - 每毫秒超过10个字符。因此,如果您花费宝贵的时间打开数据库(慢速文件IO)或绘制图形(也可能很慢),则可能无法跟上数据。

因此,它可能是把串口处理在自己的线程是一个好主意,中断等,这可能使多任务处理变得更加容易。再一次,这只是一个受过教育的猜测。

而且,你说你的程序“崩溃”当您启用其他操作。你的意思是说整个过程实际上是崩溃的,或者你得到了损坏的数据,或者两者兼而有之?是否有可能超过200字节inBuffer []?在115kbps的速度下,这并不需要20ms。

+0

问题很奇怪 - 这往往是数据的组合被破坏,随后不久将崩溃。就像你说的那样,它似乎确实是一个计时问题。我试图通过将数据库插入移动到draw()函数来补救这一点 - 所以它不会经常被调用。我也完全删除了对db.connect()的检查,这是不安全的,但似乎该函数的开销导致了一些事情。我还将波特率加倍,但保持数据发送到端口的速度不变。这些东西似乎有所帮助,但仍然让我感到好奇。 – mhilmi 2011-01-30 02:20:21