将串行通信数据添加到实时Java图形中

时间:2013-02-24 22:44:35

标签: java serial-port arduino real-time jfreechart

现在我有一个可以读取串行数据的Java文件,它只是在控制台中打印出来。在另一个文件中,我有一个JFreeChart图表,可以将随机数据生成到实时图表中。

这些文件都在同一个项目中。如何将串行数据添加到实时图表中,而不是我现在使用的随机数据?

下面的第一个代码是实时图表的文件。

public class test224 extends ApplicationFrame implements ActionListener {
    String s;
    String tempbuff;
    private TimeSeries series;

    private double lastValue = 10.0;

    private Timer timer = new Timer(1000, this);
    DynamicTimeSeriesCollection dataset;
    float[] newData = new float[1];

    public test224(final String title) {
        super(title);
        this.series = new TimeSeries("Sensor Value", Millisecond.class);

        final TimeSeriesCollection dataset = new TimeSeriesCollection(this.series);
        final JFreeChart chart = createChart(dataset);
        timer.setInitialDelay(1000);
        chart.setBackgroundPaint(Color.LIGHT_GRAY);
        final JPanel content = new JPanel(new BorderLayout());
        final ChartPanel chartPanel = new ChartPanel(chart);
        content.add(chartPanel);
        chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
        setContentPane(content);
        timer.start();
    }

    private JFreeChart createChart(final XYDataset dataset) {
        final JFreeChart result = ChartFactory.createTimeSeriesChart(
            "Dynamic Line Chart of Arduino Data",
            "Zeit",
            "Wert",
            dataset,
            true,
            true,
            false
        );

        final XYPlot plot = result.getXYPlot();

        plot.setBackgroundPaint(new Color(0xffffe0));
        plot.setDomainGridlinesVisible(true);
        plot.setDomainGridlinePaint(Color.lightGray);
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.lightGray);

        ValueAxis xaxis = plot.getDomainAxis();
        xaxis.setAutoRange(true);

        xaxis.setFixedAutoRange(60000.0);
        xaxis.setVerticalTickLabels(true);

        ValueAxis yaxis = plot.getRangeAxis();
        yaxis.setRange(0.0, 300.0);

        return result;
    }

    public void actionPerformed(final ActionEvent e) {
        final double factor = 0.9 + 0.2*Math.random();
        this.lastValue = this.lastValue * factor;

        final Millisecond now = new Millisecond();
        this.series.add(new Millisecond(), this.lastValue);
    }

    public static void main(final String[] args) {
        final test224 demo = new test224("Dynamic Line And TimeSeries Chart");
        demo.pack();

        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

在执行的操作中是生成随机数据的位置。然后在另一个文件的代码中,这会将Arduino串行数据打印到控制台,那么我怎样才能将它显示在实时图形中呢?

public synchronized void serialEvent(SerialPortEvent oEvent) {
    if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            inputLine=input.readLine();
            System.out.println(inputLine);

        }
        catch (Exception e) {
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您需要通过合并类别将serialEvent的内容移动到actionPerformed方法中,或者在public addDataPoint(double point)中提供可以从中调用的test224方法包含序列事件的类。我认为在任何一种情况下,您都需要将serialEvent中的处理移动到一个单独的线程中。

您可以尝试这样的事情:

@Override
public void actionPerformed(final ActionEvent e) {

  //Initialise the serial port here before starting the new thread

  Runnable task = new Runnable() {

    @Override
    public void run() {
        if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {
                inputLine = input.readLine();
                System.out.println( inputLine );
                final Millisecond now = new Millisecond();
                series.add(new Millisecond(), Double.parseDouble(inputLine));  

            } catch (Exception e) {                             
            }
        }
    }
  };
  Thread serialThread = new  Thread(task);
  serialThread.start();
}

public addDataPoint(double point)解决方案更可取,因为您保持关注点分离。

public synchronized void serialEvent(SerialPortEvent oEvent) {
    if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            inputLine=input.readLine();
            System.out.println(inputLine);
            dataChart.addPoint(Double.parseDouble(inputLin));

        } catch (Exception e) {                             
        }
    }
}

您仍需要确保在单独的线程上监视串行点。

答案 1 :(得分:1)

我不愿意更新图表的数据集,而不会将调用包含在适合Runnable的{​​{1}}中。此example会从匿名后台主题更新invokeLater()

更好的是,使用TableModel,如图所示here。您可以使用SwingWorker方法和doInBackground()有用的结果来操纵串口,相信publish()会在event dispatch thread上运行。

相关问题