arduino / Arduino

Arduino IDE 1.x
https://www.arduino.cc/en/software
Other
14.15k stars 7.01k forks source link

IDE 1.6.11 java issues with serial monitor & plotter #5316

Closed h2ad2 closed 8 years ago

h2ad2 commented 8 years ago

After board reset or upload, a bunch of errors show when a monitor window is open or opened.

Dump below:

Sketch uses 6,652 bytes (20%) of program storage space. Maximum is 32,256 bytes.
Global variables use 590 bytes (28%) of dynamic memory, leaving 1,458 bytes for local variables. Maximum is 2,048 bytes.
Exception in thread "AWT-EventQueue-0" java.util.NoSuchElementException
    at processing.app.helpers.CircularBuffer.min(CircularBuffer.java:42)
    at processing.app.SerialPlotter$GraphPanel.computeBounds(SerialPlotter.java:90)
    at processing.app.SerialPlotter$GraphPanel.paintComponent(SerialPlotter.java:124)
    at javax.swing.JComponent.paint(JComponent.java:1056)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
    at javax.swing.JComponent.paint(JComponent.java:1042)
    at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
    at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
    at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
    at java.awt.Container.paint(Container.java:1975)
    at java.awt.Window.paint(Window.java:3904)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
    at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Exception in thread "AWT-EventQueue-0" java.util.NoSuchElementException
    at processing.app.helpers.CircularBuffer.min(CircularBuffer.java:42)
    at processing.app.SerialPlotter$GraphPanel.computeBounds(SerialPlotter.java:90)
    at processing.app.SerialPlotter$GraphPanel.paintComponent(SerialPlotter.java:124)
h2ad2 commented 8 years ago

Could be a buffer overflow somewhere. Serial.println() call with a short(er) string did not show the problem.

Is there a max string length for Serial.println()? This error occurred with a string of only 75 chars. With 55 chars it worked OK.

NONONO: just removed the string completely. The issue keeps coming back. Hard to reproduce, but happens too often.

xloem commented 8 years ago

I'm running into this issue. I think it's a duplicate of #4722 caused by serial corruption at high baud.

xloem commented 8 years ago

I think this happens due to brief serial corruption which reads as more data series than actually exist; when these "extra" data series scroll off the screen, they are left as empty graphs with no content. The code does not expect empty graphs and dies when calculating their bounds. I haven't verified this scenario entirely, but I wrote a patch assuming the above description, and it fixed the issue for me:

diff --git a/app/src/processing/app/SerialPlotter.java b/app/src/processing/app/SerialPlotter.java
index 4cfb9da..93dc5b6 100644
--- a/app/src/processing/app/SerialPlotter.java
+++ b/app/src/processing/app/SerialPlotter.java
@@ -87,8 +87,10 @@ public class SerialPlotter extends AbstractMonitor {
       minY = Double.POSITIVE_INFINITY;
       maxY = Double.NEGATIVE_INFINITY;
       for(Graph g : graphs) {
-        minY = Math.min(g.buffer.min(), minY);
-        maxY = Math.max(g.buffer.max(), maxY);
+        if (!g.buffer.isEmpty()) {
+          minY = Math.min(g.buffer.min(), minY);
+          maxY = Math.max(g.buffer.max(), maxY);
+        }
       }

       final double MIN_DELTA = 10.0;

I'll see if I can make a pull request.

xloem commented 8 years ago

I added debugging output locally and verified that my problem description was accurate, at least in my case. Sometimes bytes are lost at high baud, and then two lines may appear together because the linebreak is not received. This is read as a very long line with extra data series, which causes the issue.

Another cause and issue is the accumulation of bogus data when the baud rate is set wrongly. This can increase memory usage as the line buffer is continuously filled without registering a line break. Then many empty graphs may be created when the baud is finally set correctly, and the invalid line is parsed, which slows the program and further uses extra memory.

The current implementation attempts to ignore invalid data items and continue using every line, but it might be better to discard lines which contain non-numeric values and warn the user, to prevent problems such as this. Unfortunately this would break any programs out there which assume that it is okay to intersperse e.g. labels in the output.

cmaglie commented 8 years ago

The current implementation attempts to ignore invalid data items and continue using every line, but it might be better to discard lines which contain non-numeric values and warn the user, to prevent problems such as this. Unfortunately this would break any programs out there which assume that it is okay to intersperse e.g. labels in the output

Another solution may be to keep the current approach (discard all invalid data) but limit the size of the input line to, say, 200 bytes? It will allow to plot a fair amount of lines but avoid crashing when the serial monitor goes crazy.