如何使用Jfreechart绘制随时间从arduino接收的数据的图形

时间:2018-06-21 18:04:03

标签: java graph arduino real-time jfreechart

我有四个压力传感器通过串行端口连接(使用jSerialComm进行通信)连接到Arduino Uno板,然后连接到PC。我希望能够以半实时方式绘制四个读数的图形(以每秒获取100次数据,但不必以如此快的速度绘制数据),以便随后可以进行简短的计算。

Arduino代码:

int vals[4];
int a0,a1,a2,a3;

void setup() {
  Serial.flush();
  Serial.begin(9600);
  delay(1000);
}

void loop() {
  a0 = analogRead(0);
  a1 = analogRead(1);
  a2 = analogRead(2); 
  a3 = analogRead(3);
  vals[0] = a0;
  vals[1] = a1;
  vals[2] = a2;
  vals[3] = a3;
  Serial.print("<,");
  delay(1);
  for(int i=0;i<4;i++)
    {
      Serial.print(vals[i]);
      Serial.print(",");
    }
  delay(1);  
  Serial.println('>');
}

和Java代码:

import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

import com.fazecast.jSerialComm.SerialPort;

public class SerialTest extends ApplicationFrame
{

    private TimeSeriesCollection timeSeriesCollection;
    private TimeSeries series0; // a0 series data
    private TimeSeries series1; // a1 series data
    private TimeSeries series2; // a2 series data
    private TimeSeries series3; // a3 series data

    private BufferedReader input; // input reader
    private SerialPort thisPort; // serial port object

    public SerialTest(String title) throws IOException
    { 
        super(title);

        connectArduino();

        timeSeriesCollection = new TimeSeriesCollection();
        series0 = new TimeSeries("Sensor0");
        series1 = new TimeSeries("Sensor1");
        series2 = new TimeSeries("Sensor2");
        series3 = new TimeSeries("Sensor3");

        timeSeriesCollection.addSeries(series0);
        timeSeriesCollection.addSeries(series1);
        timeSeriesCollection.addSeries(series2);
        timeSeriesCollection.addSeries(series3);

        JFreeChart chart = createChart();
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setMouseWheelEnabled(true);
        chartPanel.setPreferredSize(new java.awt.Dimension(1000,500));
        chartPanel.setInitialDelay(1000);
        setContentPane(chartPanel);
        getData();
    }

    public boolean connectArduino()
    {
        thisPort = SerialPort.getCommPorts()[0]; //set serial port to first port we find
        thisPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 0, 0); 
        thisPort.closePort();
        thisPort.openPort();
        input = new BufferedReader(new InputStreamReader(thisPort.getInputStream())); //give BufferedReader a stream of chars
        return thisPort.isOpen();
    }

    public void getData() throws IOException
    {
        if (thisPort.isOpen() == true)
        {
            try
            {
                while ((input.readLine())!=null )
                {   
                String inputLine = input.readLine();
                String[] inputVals = inputLine.split(",");

                while(!inputVals[0].equals("<") || !inputVals[inputVals.length -1].equals(">"))
                {
                    inputLine = input.readLine();
                    inputVals = inputLine.split(",");
                }
                if (inputVals[0].equals("<") && inputVals[inputVals.length -1].equals(">"))
                {
                    System.out.println("OK" + inputLine);
                    for(int i=1; i<inputVals.length-2; i++)
                        inputVals[i].replaceAll("[^\\d.]", "");

                    int in_0 = new Integer(inputVals[1]).intValue();
                    int in_1 = new Integer(inputVals[2]).intValue();
                    int in_2 = new Integer(inputVals[3]).intValue();
                    int in_3 = new Integer(inputVals[4]).intValue();

                    timeSeriesCollection.getSeries(0).add(new Millisecond(),in_0);
                    timeSeriesCollection.getSeries(1).add(new Millisecond(),in_1);
                    timeSeriesCollection.getSeries(2).add(new Millisecond(),in_2);
                    timeSeriesCollection.getSeries(3).add(new Millisecond(),in_3);

                    getData();
                }
                else getData();
                }
            } catch(Exception e) {}
        }else System.out.println("port not open");
    }

    public JFreeChart createChart()
    {
        JFreeChart chart = ChartFactory.createTimeSeriesChart("Force Plat", "Time", "ADC Reading", timeSeriesCollection, true, true, false);
        chart.setBackgroundPaint(Color.white);
        XYPlot plot = (XYPlot) chart.getPlot();
        DateAxis axis = (DateAxis) plot.getDomainAxis();
        axis.setAutoRange(true);
        axis.setFixedAutoRange(60000);
        return chart;
    }

    public void close()
    {
        if(thisPort != null)
            thisPort.closePort();
    }

    public static void main(String[] args) throws IOException
    {
        SerialTest demo = new SerialTest("demo");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}

Arduino会打印一个开始字符'<'和结束字符'>'来标识每个字符串的开头,每个读数之间用逗号分隔。它偶尔会打印错误的<或>,似乎对程序影响不大。

我认为我遇到的主要问题是在getData()方法中。它将绘制一个或两个传感器数据点,然后不再显示。我不确定是否需要像现在这样的事件监听器,例如排序,线程或递归。

0 个答案:

没有答案