Skip to content

Serial plotter remote commands #7461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
110 changes: 97 additions & 13 deletions app/src/processing/app/SerialPlotter.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class SerialPlotter extends AbstractMonitor {

private final StringBuffer messageBuffer;
private JComboBox<String> serialRates;
private JButton clearButton;
private JSpinner graphWidth;
private Serial serial;
private int serialRate, xCount;

Expand All @@ -50,15 +52,18 @@ public class SerialPlotter extends AbstractMonitor {
private JComboBox<String> lineEndings;

private ArrayList<Graph> graphs;
private final static int BUFFER_CAPACITY = 500;
private final static int BUFFER_CAPACITY_DEFAULT = 500;
private final static int BUFFER_CAPACITY_MAX = 5000;
private final static int BUFFER_CAPACITY_MIN = 10;
private int buffer_capacity = BUFFER_CAPACITY_DEFAULT;

private static class Graph {
public CircularBuffer buffer;
private Color color;
public String label;

public Graph(int id) {
buffer = new CircularBuffer(BUFFER_CAPACITY);
public Graph(int id, int capacity) {
buffer = new CircularBuffer(capacity);
color = Theme.getColorCycleColor("plotting.graphcolor", id);
}

Expand Down Expand Up @@ -156,12 +161,12 @@ public void paintComponent(Graphics g1) {
}

// handle data count
int cnt = xCount - BUFFER_CAPACITY;
if (xCount < BUFFER_CAPACITY) cnt = 0;
int cnt = xCount - buffer_capacity;
if (xCount < buffer_capacity) cnt = 0;

double zeroTick = ticks.getTick(0);
double lastTick = ticks.getTick(ticks.getTickCount() - 1);
double xTickRange = BUFFER_CAPACITY / ticks.getTickCount();
double xTickRange = buffer_capacity / ticks.getTickCount();

for (int i = 0; i < ticks.getTickCount() + 1; i++) {
String s;
Expand All @@ -177,7 +182,7 @@ public void paintComponent(Graphics g1) {
s = String.valueOf((int)(xTickRange * i)+cnt);
fBounds = fm.getStringBounds(s, g);
sWidth = (int)fBounds.getWidth()/2;
xValue = (int)((bounds.width - xOffset - xPadding) * ((xTickRange * i) / BUFFER_CAPACITY) + xOffset);
xValue = (int)((bounds.width - xOffset - xPadding) * ((xTickRange * i) / buffer_capacity) + xOffset);
}
// draw graph x axis, ticks and labels
g.setColor(boundsColor);
Expand All @@ -194,8 +199,8 @@ public void paintComponent(Graphics g1) {
g.drawLine(xOffset, (int) transformY(zeroTick), bounds.width - xPadding, (int)transformY(zeroTick));

g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0));
float xstep = (float) (bounds.width - xOffset - xPadding) / (float) BUFFER_CAPACITY;

float xstep = (float) (bounds.width - xOffset - xPadding) / (float) buffer_capacity;
// draw legend
int legendXOffset = 0;
for(int i = 0; i < graphs.size(); ++i) {
Expand Down Expand Up @@ -255,6 +260,10 @@ public SerialPlotter(BoardPort port) {

messageBuffer = new StringBuffer();
graphs = new ArrayList<>();

graphWidth.addChangeListener(cl -> {commandNewSize((int)graphWidth.getValue()); } );

clearButton.addActionListener(ae -> {commandClearGraph();});
}

protected void onCreateWindow(Container mainPane) {
Expand All @@ -272,10 +281,24 @@ protected void onCreateWindow(Container mainPane) {
for (String serialRateString : serialRateStrings) serialRates.addItem(serialRateString + " " + tr("baud"));

serialRates.setMaximumSize(serialRates.getMinimumSize());


clearButton = new JButton(tr("Clear output"));

graphWidth = new JSpinner(new SpinnerNumberModel(
BUFFER_CAPACITY_DEFAULT, //initial value
BUFFER_CAPACITY_MIN, //min
BUFFER_CAPACITY_MAX, //max
1)); //step
graphWidth.setMaximumSize(graphWidth.getMinimumSize());
JSpinner.NumberEditor editor = new JSpinner.NumberEditor(graphWidth);
editor.getFormat().setGroupingUsed(false);
graphWidth.setEditor(editor);

pane.add(Box.createHorizontalGlue());
pane.add(Box.createRigidArea(new Dimension(8, 0)));
pane.add(serialRates);
pane.add(clearButton);
pane.add(graphWidth);

mainPane.add(pane, BorderLayout.SOUTH);

Expand Down Expand Up @@ -373,14 +396,17 @@ public void onSendCommand(ActionListener listener) {
sendButton.addActionListener(listener);
}

public void appyPreferences() {
public void applyPreferences() {
// Apply line endings.
if (PreferencesData.get("serial.line_ending") != null) {
lineEndings.setSelectedIndex(PreferencesData.getInteger("serial.line_ending"));
}
}

protected void onEnableWindow(boolean enable) {
serialRates.setEnabled(enable);
graphWidth.setEnabled(enable);
clearButton.setEnabled(enable);
textField.setEnabled(enable);
sendButton.setEnabled(enable);
}
Expand All @@ -389,6 +415,34 @@ private void onSerialRateChange(ActionListener listener) {
serialRates.addActionListener(listener);
}

private void setNewBufferCapacity(int capacity){
if(buffer_capacity != capacity) {
if(capacity > BUFFER_CAPACITY_MAX) buffer_capacity = BUFFER_CAPACITY_MAX;
else if(capacity < BUFFER_CAPACITY_MIN) buffer_capacity = BUFFER_CAPACITY_MIN;
else buffer_capacity = capacity;

for(int i = 0; i < graphs.size(); i++) {
graphs.get(i).buffer.newCapacity(buffer_capacity);
}

xCount=0;
}
}

private void commandClearGraph()
{
graphs.clear();
xCount=0;
}

private void commandNewSize(int newSize)
{
setNewBufferCapacity(newSize);
if((int)graphWidth.getValue() != newSize) {
graphWidth.setValue(newSize);
}
}

public void message(final String s) {
messageBuffer.append(s);
while (true) {
Expand All @@ -413,6 +467,35 @@ public void message(final String s) {
int validParts = 0;
int validLabels = 0;
for(int i = 0; i < parts.length; ++i) {
// all commands start with #
if(parts[i].startsWith("#") && parts[i].length() > 1) {
String command = parts[i].substring(1, parts[i].length()).trim();
if("CLEAR".equals(command)) {
commandClearGraph();
}
else if(command.startsWith("SIZE:")) {
String[] subString = parts[i].split("[:]+");
int newSize = BUFFER_CAPACITY_DEFAULT;
if(subString.length > 1) {
try {
newSize = Integer.parseInt(subString[1]);
} catch (NumberFormatException e) {
// Ignore
}
}
commandNewSize(newSize);
}
} else {
try {
double value = Double.valueOf(parts[i]);
if(validParts >= graphs.size()) {
graphs.add(new Graph(validParts, buffer_capacity));
}
graphs.get(validParts).buffer.add(value);
validParts++;
} catch (NumberFormatException e) {
// ignore
}
Double value = null;
String label = null;

Expand Down Expand Up @@ -451,14 +534,14 @@ public void message(final String s) {

if(value != null) {
if(validParts >= graphs.size()) {
graphs.add(new Graph(validParts));
graphs.add(new Graph(validParts, buffer_capacity));
}
graphs.get(validParts).buffer.add(value);
validParts++;
}
if(label != null) {
if(validLabels >= graphs.size()) {
graphs.add(new Graph(validLabels));
graphs.add(new Graph(validLabels, buffer_capacity));
}
graphs.get(validLabels).label = label;
validLabels++;
Expand All @@ -467,10 +550,11 @@ public void message(final String s) {
else if(validLabels > validParts) validParts = validLabels;
}
}

}
SwingUtilities.invokeLater(SerialPlotter.this::repaint);
}


public void open() throws Exception {
super.open();

Expand Down
10 changes: 8 additions & 2 deletions app/src/processing/app/helpers/CircularBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

public class CircularBuffer {

private final double[] elements;
private double[] elements;
private int start = -1;
private int end = -1;
private final int capacity;
private int capacity;

public void add(double num) {
end = (end + 1) % capacity;
Expand Down Expand Up @@ -37,6 +37,12 @@ public CircularBuffer(int capacity) {
elements = new double[capacity];
}

public void newCapacity(int capacity) {
elements = new double[capacity];
this.capacity = capacity;
start = end = 0;
}

public double min() {
if (size() == 0) {
throw new NoSuchElementException();
Expand Down