From bfb6f394dca4a77002e8f907421c6b4f8c5973cc Mon Sep 17 00:00:00 2001 From: Wilhelm Date: Tue, 10 Apr 2018 21:35:28 +0200 Subject: [PATCH 1/3] Added labels to legend --- app/src/processing/app/SerialPlotter.java | 70 ++++++++++++++++++++--- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/app/src/processing/app/SerialPlotter.java b/app/src/processing/app/SerialPlotter.java index 363753749fe..336cbd43e7e 100644 --- a/app/src/processing/app/SerialPlotter.java +++ b/app/src/processing/app/SerialPlotter.java @@ -46,6 +46,7 @@ public class SerialPlotter extends AbstractMonitor { private static class Graph { public CircularBuffer buffer; private Color color; + public String label; public Graph(int id) { buffer = new CircularBuffer(BUFFER_CAPACITY); @@ -185,12 +186,24 @@ public void paintComponent(Graphics g1) { g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0)); float xstep = (float) (bounds.width - xOffset - xPadding) / (float) BUFFER_CAPACITY; - int legendLength = graphs.size() * 10 + (graphs.size() - 1) * 3; + // draw legend + int legendXOffset = 0; for(int i = 0; i < graphs.size(); ++i) { graphs.get(i).paint(g, xstep, minY, maxY, rangeY, bounds.height); - if(graphs.size() > 1) { - g.fillRect(bounds.width - (xOffset + legendLength + 10) + i * 13, 10, 10, 10); + if(graphs.size() > 1) { + //draw legend rectangle + g.fillRect(10 + legendXOffset, 10, 10, 10); + legendXOffset += 13; + //draw label + g.setColor(boundsColor); + String s = graphs.get(i).label; + if(s != null && s.length() > 0) { + Rectangle2D fBounds = fm.getStringBounds(s, g); + int sWidth = (int)fBounds.getWidth(); + g.drawString(s, 10 + legendXOffset, 10 + (int)fBounds.getHeight() /2); + legendXOffset += sWidth + 3; + } } } } @@ -282,17 +295,60 @@ public void message(final String s) { } int validParts = 0; + int validLabels = 0; for(int i = 0; i < parts.length; ++i) { - try { - double value = Double.valueOf(parts[i]); + Double value = null; + String label = null; + + // column formated name value pair + if(parts[i].contains(":")) { + // get label + String[] subString = parts[i].split("[:]+"); + + if(subString.length > 0) { + int labelLength = subString[0].length(); + + if(labelLength > 32) { + labelLength = 32; + } + label = subString[0].substring(0, labelLength); + } else { + label = ""; + } + + if(subString.length > 1) { + parts[i] = subString[1]; + } else { + parts[i] = ""; + } + } + + try { + value = Double.valueOf(parts[i]); + } catch (NumberFormatException e) { + // ignored + } + //CSV header + if(label == null && value == null) { + label = parts[i]; + } + + if(value != null) { if(validParts >= graphs.size()) { graphs.add(new Graph(validParts)); } graphs.get(validParts).buffer.add(value); validParts++; - } catch (NumberFormatException e) { - // ignore } + if(label != null) { + if(validLabels >= graphs.size()) { + graphs.add(new Graph(validLabels)); + } + graphs.get(validLabels).label = label; + validLabels++; + } + if(validParts > validLabels) validLabels = validParts; + else if(validLabels > validParts) validParts = validLabels; } } From cdd66b63f686ebe3535dd5fc5f6b9cc592ce8263 Mon Sep 17 00:00:00 2001 From: Wilhelm Wiens Date: Tue, 5 Mar 2019 01:06:35 +0100 Subject: [PATCH 2/3] Serialplotter protocol documentation --- ArduinoSerialPlotterProtocol.pdf | Bin 0 -> 27160 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ArduinoSerialPlotterProtocol.pdf diff --git a/ArduinoSerialPlotterProtocol.pdf b/ArduinoSerialPlotterProtocol.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e2e0b7024f9fc696180b7beafecdd79c1534c678 GIT binary patch literal 27160 zcmagG1CS;`(=IyZ4t8wYHg;^=wr$(9W81c|W81dPcRY9ZyZ<@=x#yl6w<9VtD?76) zy8Fq9?5cj6R9;w=mXVGHhIF84plhIIAQy&-fPuiy&=Q7+hhEym*38+QfcdXQkzUlo z+S$aBUewya*+kgH$j;b=j}OMl+0n$n2F5+BT1zSpr}bygP3>tTu*~RwW55tlXQc|z zP8QT?-zcpsh!6~--UmPlf$vS_5>G?jyoB@9$6FaSN(9Zs*7fb+%rCL8mmv&WdTm21 z$M^f_44+^6+lQ&uTJbrtJ$+3pYG=9Rv~=hD6AaDPA#!Yc)A+z9=hAxsy;r*T%l`)C z3(KiLx0eriP>ZUVUWt-4PR2+g{vv@O_v;~8C4D0rj?9`fGz+-5JF}0@bC=i=M1Loh zHykgF@TN-(Fr6;VTh`U(ZDvb%EItK>L(iJo;P6nu$$`ZnVG2JwXlJGaLIj3Ymiurh z3AyP(%p9A@xx7CRiLCGwzJ3in4I71b#`Ms^Ui!&Um>xE70r$KzOm0vR8&ex4QqDE&O5QsltmxO zg)`A4uU)GqSIT&P9*eM!WYk3>erZ#s&;Lm#%Zt=JGBiGe!$!RkqQceK*S3^ZXX*Fb zaFv)cZn@p0r|^>Ru?B4noC+=z^miTbuK_p9gAPn#l8K_^(;oAJE@=J=2 zy3vCFZqv*ZLHhPZl;|!E3#T?a2>MnvcP%VlLUw9h#ryq9PI$MPfsSkCbbaAu>bt2- z-ZZ1lc7wB$kVVKaOlJ?RG#ph;#gSwwQMGeec0)wS88XZXb&8_6{v{O;vs_y1Aj7~O1a$dv!zZp*izjhdNYC*;%G|W zJ9JW8ed7*}2NydlhGk?O zHM`oEF01;R4;S@q<@Tj4?di4*exm{By6kf{dbpvT!HU~-t*)-R$9GtTkATU5C%1Iw zJLBsfx*8|f_w#ja^&Rrv`VYs!&8>A{#D~znoX50j&jGq0;%$hZ&rs<-Stk1j`px&p z$HBt;Nog)yHKZjQu*mi%$2w)xaKJ^8W*77#sBi3tAYUTO-Zef^K-&p}`dYr(f^+1;wm5;kx*qY4{gGCl$xvZd-t$lV$-Fjb+; zS>cYNO_84e4hjT86!d-qV%TjS7#o&a!Yq-8;kY~Eb4akfZTuW@XI))V#`w9lH{r#W zOxjQXY-CKfckCmInRZ$)H*li*(d4Z&{2eN;$131t9`Q!)>3!kts>0VxlmD3mkuRqY z*oKtdn-cC~gl=%#KWRC*n0MNH`xl>uQ5-pQ6s?G_(H5(h378!C;`gVJEe8uw#X^Ea zoxmaWIUOVz4!BY@Lu&$Aoog^i_Mc)#;0x)lxnL!b_%(hWfZ|=2{jsirPGR$ZafSgLR92@dRQD$+Pe! z%7UD^RKdQQ#mIFl`N&00WS7l2m%0=5r?IE3~V%UE%xy zqPlw``)iSp@u(lr`|N+kp9u7TYIH*Sw^w%7c_>QdEq#J?I}vXD8^VOZOees{tE>Z- zub*J4uw@y3bQ4D2%gI-XemfHTt>Gpdj>(PaU|xz0e33158bu8SY|IG;tS55tZLqr? zoYC(7cqLQgKJN2#wRqz;n#f3$oBLQ;(d`v8l9vhgf}q)kPCrS)IA87N8N5iEGB0iI28@|8T>0K_E_ z`$3&g3gj%f53L8SsEORt*hkIkzsjfOE@Gw4DcK{D2>51n; zV2-QbmlfmJi4E?uls`~U>~T(%M?7v%6sR-Hboz@WQW)R$XJ1}p9~275Re$kblUs_L zFZfI`As>cr9-8r#j6GMyA1zzSkW^viK0s5FY&?oGX;W~LER+gKLw^oDMzl_JTT&?4 zn3;;;gzXvFnDJj}bp|%hqvAd$SiYO!NOhazKM(zjT7_8LLS~hd5Zx_INlX?h#|4sM zLE*8dV6KB^e4G6<20pwnGYI|^UfkM%=UEI#UVrMwYxh*nNl+hN<3RVckA09hA3jST zDGICHpw~$$(~ZqskeBl-oU&wfU!@JuHffi&|C9HM6rzWqi^0^ zU_b)GZ1~#tx%ejnnVc$eq=ZO02dHiPoGii-O3IzV=+<0B0n(lDsZAY!v?6uFgg^%{ zm6^^#Y}Z_H=_Kp}T7%o*b9Im68|#9I;PiFKxq)fMBW!Ldyi&Mfw&EQ~jj?A+k!i}$qaeiv?ld!YEJx_1KQ_mgf{ zz4!tI$X9iJx`Fb8IG3&M>0+QI=-5#NJ4N%6NS3RDeFFr^Z+*f<&0F!E151}Gezr9c zUYh0vWWawp)$jEbG_Kx;=TCD_thcYOHKwBrSoorh{odg=gzI2{I^dx37B=0TbT~lY zr-K3cWczR`QaZEajG(9dBXZnc;-*zH&@4Sdjlf82xSTVsi}SH!{HSFIr-JNHk17v! zUaqZM2W51oC`HgEQK4b{_DeOr6cz%(5kqd}p{R(n)>C8Dg(o%ig(Ir*!gy-!uDSrk zPAxignvTu8*P;lS2X~z{Fex;+&3^>hzCA;E_p@OBkDJ2bBGg~Vqp6N(T0-r4wH3VP z6$BVD5|vrW=*Nbi;KT`HQ2O_M3$;`*ul<-7DQ< zm{Rz|Q2Jt41MDIN`}WL~uo3pRVQ&28`_tn-2zu-@jPVEgP}%ELhIKgG)TEA$&vHU_ zI$fr=EgF@+qkhuD_hdy}S%4V0wr#@stoQ)E{y*SpKE@pq$~p>cjEm+oYujQ8HT3O^ zejnKAEew!>wFDbGV^9?5YuvhH|AjZtYR@-L|Bxq4m(GdG-jFv;&(7fzG%#0IPMCiC zr`FyTU7c@?Jlz+XU@t@!vi}#k-hVPWoyM#5#;mFHTz2xg?-;TLJL!0Yo6l+VZMe~? z&e`8ldCL~&ljRfNIT*Ce6ze?c0+P|t9=3lY=PhsL<;P`j?KStL7S53|K|4~!_ zSIx~xz{tVL!SKIU*jrw(&dMXd&E0mq#2)6%uRmN^6OQ2lu|?^>SplQXb35=>g!rI8 zGl6hI{T>sc^J0&oM_@aCboZH$vzTcJS595qcWkaH#*(ws?@+&^QB?Hi)lv9=@qa== z{ze`O<}wy2yaa?I0FV;Qxd2}=y^Yi-d|$n5us&3rkvU?evjUG&i-~mRq7E$4t{}&6 zGk`fcASr%_#SqsPU?v?Zkb2_^j*~16_$0=0d-*et`rhB!RkN%Jm-5wWt#l_DeA(m8E`EiHFveL^aAgj!rcGSoNp#j zvSZeE>un$!-5Jv*Il3f9_@L4R-s6KYEDP@_rBJ9pREjvC!NtA4v0ST#t=H(eG`@^F zVMIG66ElI8V)-=Jv7SM?q!NX$LPrCenu3CkiuR&n5-^i_RTr5;(>P{6Yjz5jLyUpS zPB{h5sSz)J4=zcgD)=CYPw-YFM3TUimtj{VF%B(Cwj*8+e6%Z*q#3E$DHN(w(vJqvVmL&-~t+!kI|m?! z`5+tJm5ip^t7~y2zeb)#NQ@V~+LsC*KC2TRnUAQ*pHLu!z)VlCr+*N#mS@RENyt}R zi|(1$4>=>6?8}%XkeZAwdj{8JrN~aCYEAzVCgDp^d%s=sDY=AJ5ph zP$SbO-$oCVo;Ru-UD^`o#%C*!J_j5XDS+yKRbNp1m&{VVi=>RbQ6x{g=LLXN%G9X( z!yPRYv5?MxyTO@&g0>fNV8Rxc^i&g^R!Mef&ezjKAZ0EzC+wAot~YEp@z155gB%rCU2y~vIW3S=8P8DvR1V<6 zrmVNZJXH}`_=^4ND`MX}3rl9BaC7&Ts75AhQ#!*qEsBIdf{_+-;#)RMps~6z*Qsr) zxjHYCbR$vuwRZPalDSHOn}dQa-(Iv`o5~#?b^#{%6VZ_wNK%OQgN*sZ^CgnNKD4-E zU7p%aA0eYO)RqL)ap9LyM(nYjK9#(SCR*l6NukDWBhB%h%bQ|uf+5I|V~0UmeyL#0 z6uN_N9hg7ypV0g=n#S_!3EXl2`SKrQ613X_BcekCMOkPNi5{Lc>$amhsew`UfCwv-1 z^*L+a8~%I?XIg|glTJO2?Or{N9fgUqzQE0^HKC1$eAUhMWqHLP!&Q61f%w{9f&&OO zH|HG0g5pp5S|bvHV-3PWC(x+lT+^ew)EFu9G$QlS(#%N!9*U>)KO3(|fx<~7&i}f5Leb0Zzo6g)WdZH9m$=LMG)%lNy+k_h_&JzTq-P!m z#Q~a}^M^v)iz#SjCMkCoy0?aR>?hD1bZh~5Bwur;4ehwnni=GoR9~~Vj%VK-EP9}v3 z@^X8+MaP5;6HtF)8LQ$ID8lYhK+Y4&R&JbCYFk%R=nG1nz)<_NF}kT}WpTw-X7FzUce!jB2`A;ce-(! zA|R%RDS)m%B!uL%93guL=63La;TeplHGyo%9X);mXRIANq!k_F;L`A}dQoIllOC$G z7Ktv&;8w?aI9Ls$yA*Wj)gvDvRcKv4H+<8tgjdSWBQDmwGxbpKDnVOKSB)H+rh#Vx zN;3M1>x?(dpk9ig4E`|vR-f|`8fqTvb#@+`kiBzC@B3hV(VbaghF`0xMY&h2A;kD0 zwQ>L6x(MxASTnxwklsxHy_Jpcquz9vu5)p_um|T>t?jV_ffjCvA}CJYmuA&&X9c)R zela{ck|a{*qW(qg)vh5B3~B7w>r02Z^9oUe8C&abg^|dwVjqzfdFd{o7CE$@ z(-J8PH+%u{uHSV8{t1%>{sj^XIEYdX0qb430XUJd`_A|b$xL_bI3lwj?DpTZ*R+jl ztZ32g7o?lIP^Shq&s}4|7m2J9##fB9@KY&aK6*M$F;a#9l`x z{6gU_P)8r~>%kcMW{s2+nGqRtQt;-8youP4px8zkvPt@bO6!mH5vJfx=Sk?vIG!E7 zf1uDs(Lu-s6&))K&KjwsFe!F-MDgYE2vBgOi;NT2i%IZN=%S9~E^H%O#~=k)ur@O0 zf1y~~450wla zS#i*e=GB4~4yAG@xI$FAeKMhAhNj@*Au)cN6vZ$7DNMv{YwA;W7of7bvCv5Tgjtwt zb?k}fh1&seg0U?_GJKhR3Smd`ZgK2T?g9#(fk`RwHqfBQ;0JrA2U~p1eDgDk#S}|@ zcakZ(h>|gNx~_1sv0RwuX|Jqp)mISfc093uAE>_Kl#zLoz35vD1--gzcVSI#32MZ4 zy%~N^!mKW9K^>39jHa|wE{bZSmu5_MiGdwpNlk1ySF0eB{kG%gpI+U6Y%QlX% z3bBf_>WxAtnhxjhUplUud{vwt;N;1l*tTI9`MWO7|H?Xt`S5-O?5DPeM{3?tRYeep;6VpI-x z<9Y+*TDN;pyJ5DoJl~99)m;ie8`C%cbRZK0SPTu~)cM_f)mIX$#hnqTuE)QL#h@X) zhX6Q6tG1!n)67cMliz5TzOYliOt-UkG8@5`vI2QURN9pMRQT~R2Y>y(8-tcV!n(5z za_JDZNiu=z@-x%AVesCXlr6zxz?6EJ=U6sKYld0fC~e?P`=9_#XUQ1#y1HKz6++)2 zsxTgA+G;Wq6|KfWUreAcP@ab!oi?(HRa3j8t*@ORR`|HMOs(V%avLTELL3qdT$1Vw zD~r`>M7p=U>KL`ge%nao)iVpm(iyEvS+t&)ILe9ZS9H{!T+`KELUv=Ls}#v{XHk7A z6}R8q{quH1kVa31{u+j`;{)FDQ6u*izuda&?W4I( z`x%ucn`rP5A}98rH=Tn)GR@T~?UJIHRoz&#{lZl}J
X5cLg1Q#7c%DM|2Xjf(B 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 Date: Tue, 19 Mar 2019 00:29:18 +0100 Subject: [PATCH 3/3] Create ArduinoSerialPlotterProtocol.md --- ArduinoSerialPlotterProtocol.md | 170 ++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 ArduinoSerialPlotterProtocol.md diff --git a/ArduinoSerialPlotterProtocol.md b/ArduinoSerialPlotterProtocol.md new file mode 100644 index 00000000000..162c66d2f66 --- /dev/null +++ b/ArduinoSerialPlotterProtocol.md @@ -0,0 +1,170 @@ +# SerialPlotter protocol + +One message can consist of multiply parts. +One part can consist of one label, one label and a value or only a value. + +| | | +| --- | --- | +| End of message symbol | \n | +| Part separator symbols | ' '(space), '\t'(tab), ','(comma) | +| Label-value separator symbol | : | + +# Valid messages are + +## Labels and value messages: +| | | | | | | +|-------------------|----|-------------------|-----|-------------------|----| +| Label : Value | | | | | \n | +| Label 1 : Value 1 | \t | Label 2 : Value 2 | | | \n | +| Label 1 : Value 1 | \t | Label 2 : Value 2 | ... | Label n : Value n | \n | + +## Label only messages +| | | | | | | +|-----------|----|-----------|-----|----------|----| +| Label: | | | | | \n | +| Label 1 : | \t | Label 2 : | | | \n | +| Label 1 : | \t | Label 2 | ... | Label n: | \n | + +There is a special case, the CSV header style. + +| | | | | | | +|-------|----|---------|-----|---------|----| +|Label 1| \t | Label 2 | ... | Label n | \n | + +But in this format, labels consisting of only numbers are not recognised as labels. +It is safer to just use the normal label only message. + +## Value only messages Value +This is not recommended if you using a board with USB to UART converter. +Because when the label is sent, before you had the SerialPlotter opened, then the label/labels get/gets never set. + +| | | | | | | +|---------|----|---------|-----|---------|----| +| Value 1 | \t | Value 2 | | | \n | +| Value 1 | \t | Value 2 | ... | Value n | \n | + + +# Examples +## Single Trace without label + +This example plots on line on serial plotter without setting a label + +```ino +void setup() { + Serial.begin(9600); +} + +void loop() { + int sensorValue1 = analogRead(A0); + + Serial.println(sensorValue1); + + delay(100); +} +``` + +The output looks like this +``` +10\n +11\n +12\n +13\n +14\n +``` +## Single Trace with label + +This example sends the label once in the setup routine. Afterwards only the value is send. + +```ino +void setup() { + Serial.begin(9600); + Serial.println("Label 1:"); +} + +void loop() { + int sensorValue1 = analogRead(A0); + + Serial.println(sensorValue1); + + delay(100); +} +``` + +The output looks like this +``` +Label 1:\n +10\n +11\n +12\n +13\n +14\n +``` + +## Single Trace with label send every time + +This example sends the label every time together with the value. + +```ino +void setup() { + Serial.begin(9600); +} + +void loop() { + int sensorValue1 = analogRead(A0); + + Serial.print("Label 1:"); Serial.println(sensorValue1); + + delay(100); +} +``` + +The output looks like this +``` +Label 1:10\n +Label 1:11\n +Label 1:12\n +Label 1:13\n +Label 1:14\n +``` +## Two Traces with label send every time + +This example sends two values together with the labels. + +```ino +void setup() { + Serial.begin(9600); +} + +float avg = 0; + +void loop() { + int sensorValue1 = analogRead(A0); + + // send lable and value seperated by ':' + Serial.print("Value:"); Serial.print(sensorValue1); + + + avg = (avg * 4 + analogRead(A0)) / 5.0; + // send part devider '\t' + Serial.print("\t"); + // send the second lable and value + Serial.print("AVG5:"); Serial.println(avg); + + + delay(100); +} +``` + +The output looks like this +``` +Value:377 AVG5:431.01 +Value:338 AVG5:408.81 +Value:392 AVG5:395.85 +Value:583 AVG5:427.28 +Value:221 AVG5:383.42 +Value:195 AVG5:343.74 +Value:202 AVG5:314.19 +Value:209 AVG5:292.15 + +``` +