Right now I have a Java file that can read serial data, and it just prints it in the console. In another file, I have a JFreeChart graph that generates random data into a real-time graph.
These files are both in the same project. How could I add the serial data to the real time graph, instead of the random data I am using now?
The first code below is the file of the real-time graph.
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);
}
In the action performed is where the random data is generated. Then in this code of the other file, this prints the Arduino serial data to the console, so how could I get this to show up in the real time graph?
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
inputLine=input.readLine();
System.out.println(inputLine);
}
catch (Exception e) {
}
}
}
You need to either move the content of your serialEvent
into your actionPerformed
method by merging the classes or provide a public addDataPoint(double point)
method in test224
that can be called from the class containing your serial event. I think that in either case you will need to move the processing in serialEvent into a separate thread.
You could try something like this:
@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();
}
The public addDataPoint(double point)
solution is preferable as you maintain a separation of concerns.
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) {
}
}
}
You will still need to ensure that the Serial Point is being monitored on a separate thread.