Like many others, I was excited to see and play with the new Serial Plotter. It is a cool tool, with amazing prospect - if developed correctly. I've seen some suggestions for improvement and added functionality; they all seem reasonable, each in its own way, but putting them all together will cause the Plotter to become a white elephant.
So I've done some thinking, with the following ideas in mind - I think we all agree on them:
The Serial Plotter's GUI should be kept as clean as possible, no extra buttons or menus if we can avoid them.
New versions of the plotter will have to be backward-compatible.
Users should have maximal control, if they choose to: the Plotter should be flexible, but not force the users to run all sorts of initialization rituals just to get it running.
The Plotter is always looking at the serial data stream anyway...
My suggestion, therefore, is to create an Escape Code framework for controlling the Plotter. Just like the good old terminals.
For instance, printing "[PCLR" to the Serial will cause the graph to clear (reset); "[P" is the escape code prefix for Plotter commands, and "CLR" means "Clear".
Or, "[PCOLff0000" will change the line COLor to #ff0000 (red).
Or, "[PTIM100" will cause the plotter to run as a TIMe-based graph, with 100ms between datapoints (if none arrive, copy last one or whatever)
and so on.
For convenience, these escape codes can be later wrapped in functions, e.g.
plotterClear();
plotterLineColor(0xff0000);
The downside is of course that this will require some serious programming behind the scenes.
robtillaart:
You could implement HPGL the plotter language of HP. It is a defacto standard for plotters.
Thanks. I had to do a little reading, since it's actually the first time I've heard of HPGL
I think HPGL, as it is (according to wikipedia anyway), is too low-level for the typical Arduino user. Even the Serial Plotter in its current minimal state may be non-trivial to write in HPGL.
We can probably find some useful ideas in HPGL commands, but the "instruction set" for Arduino's Serial Plotter should be different - based perhaps on the most likely uses of this tool.
robtillaart:
Can you give a list of the 8 or 10 basic instructions it should support?
Well, building on the way the Serial Plotter is working right now, I'd suggest having, first of all, several independent "data series". Then you'll have:
1 ) Clear (erase entire graph and data, return to the leftmost position)
2 ) Select current data series (i.e. which series gets the upcoming numbers)
3 ) Restart current data series (keep others on the graph, if drawn)
4 ) Set pen color for current data series
5 ) Set Y-axis minimum, maximum and "baseline" (make that a visible horizontal line)
6 ) Set data buffer size (currently it's 500, maybe less or more is desirable per application)
7 ) Freeze/Unfreeze (temporarily stop inserting new data)
8 ) Fill/No-Fill (Area under graph painted or not - this isn't really important, but visually pleasing)
I also think something should be done about the time dimension, but I'm still not sure how - it can easily create serious conflicts with the idea of the independent series.
SBS 256; CLR; SCDS 1; SPC 0x00FF00; followed by values or so?
That's the general idea, yes. The particular format should be chosen so that it's easiest to isolate and extract commands from the stream - hence my earlier suggestion of an "escape code prefix". Maybe a postfix will help too (e.g. "[SBS:256]") We'll need the programmers feedback on this.
Unfortunately I don't know Java, so I can't help with the actual implementation. Still, it's better to have a solid plan before people start to implement things
I did some searching but didn't find much on how SCDS works with HGPL. If you are plotting multiple signals would each value need to have an id attached to it?
The current proposal is to allow multiple signals to be plotted at the same time. So it would be best if commands such as SPC and SBS could configure for multiple inputs. Otherwise you will have to send the commands for each value which will slow things down a lot. So for 2 signals maybe it could be something like:
void setup() {
Serial.begin(115200);
Serial.print(F("[SBS:256,256][SPC:#FF0000,#00FF00]")); //configure the serial plotter
}
void loop() {
Serial.print(sensorOneReading());
Serial.print(",");
Serial.print(sensorTwoReading());
Serial.println();
}
Just to be sure everyone is on the same page in this topic, igendel is referring to the serial plotter feature included in Arduino IDE 1.6.6 under Tools > Serial Plotter. igendel did a write up on it here: http://www.idogendel.com/en/archives/489. In another topic I had mentioned that there is a recent pull request from the author of the Serial Plotter to add support for plotting multiple signals. igendel expressed concern that the development was going in the wrong direction so I recommended anyone interested to get involved with the discussion on how this should be implemented while the new version is still under active development. I think this topic can allow forum users to discuss this and then maybe some of the feedback from this topic can be transferred to the pull request.
pert:
The current proposal is to allow multiple signals to be plotted at the same time.
I answered this... where did my post go? :o
My answer was that forcing the user to feed N data series at the "same time" is limiting. If we add to my scheme a short command for "jump to next data series" - this can even be the comma character - we'll get the same effect without added delays, and still keep the flexibility for other uses.
igendel:
forcing the user to feed N data series at the "same time" is limiting. If we add to my scheme a short command for "jump to next data series" - this can even be the comma character - we'll get the same effect without added delays, and still keep the flexibility for other uses.
So that would allow signals with different sampling intervals to be plotted, right? Can you post a sample sketch demonstrating how you would implement it?
pert:
So that would allow signals with different sampling intervals to be plotted, right?
Not necessarily - my main concern right now is just keeping the options open
Let's say I want to compare, visually, sensor readings under two conditions. I'd draw a 500-point graph for condition 1, switch to condition 2 and draw the new graph on top of the previous. For this kind of thing you need separate data series, feeded separately.
igendel:
Let's say I want to compare, visually, sensor readings under two conditions. I'd draw a 500-point graph for condition 1, switch to condition 2 and draw the new graph on top of the previous. For this kind of thing you need separate data series, feeded separately.
That's very different than the current system because it plots values in real time. For that kind of application I'd just format my readings as csv and then do the graphing in LibreOffice Calc.
I think robtillart's system could be very useful for different sampling intervals. Lets say you need to sample channel 1 as fast as possible but then channel 2 is something like a temperature where there is no need to waste time in your code to take a reading that won't have changed since the last one or even send a dummy value. The Serial Plotter would do the work of either just repeating the same value of channel 2 until it receives another value(which would produce a "stair step") or even better once the next value is received from channel 2 it would draw a straight line from that point to the last received point from channel 2. I think sending values in the most compact form possible is best, something like separating values from a single channel by "," and channels by ";". Would you post a version of your sketch that shows how you propose to set the colors for each channel please robtillart?
one cannot determine the amount of channels when just separate them with ;
and are they consecutive?
1;2;3;4;5;6;7;8; etc
how many channels are there and which value belongs to which channel?
And if a value drops out (communication error) how to sync again (OK small chance)
colors ... something like this? (just thinking out loud...)
one humidity per minute
one temperature per second
int tempChannel = 1;
int humChannel = 2;
void setup()
{
Serial.begin(115200);
setChannelColor(tempChannel, 0xFF0000); // RGB
setChannelColor(humChannel, 0x00FF00);
}
void loop()
{
int a = analogRead(A0);
int b = analogRead(A1);
plot(humChannel, b);
plot(tempChannel, a);
for (int i=0; i<60; i++) // 60 samples to last channel
{
a = analogRead(A0);
plot(a);
delay(1000);
}
}
// The Serial plotter should have a default set of colours
// that can be overruled by the CHC call
void setChannelColor(int ch, long color);
{
Serial.print("CHC");
Serial.print(ch);
Serial.print(",");
Serial.print(color);
Serial.print(";");
}
void plot(int ch, int val)
{
Serial.print("CH");
Serial.print(ch);
Serial.print(";");
Serial.print(val);
Serial.print(";");
}
void plot(int val)
{
Serial.print(val);
Serial.print(";");
}