update visualizations for current tacho

This commit is contained in:
interfisch 2021-03-26 20:00:48 +01:00
parent 8c42a7ffd0
commit 2ff4fb2d88
2 changed files with 120 additions and 48 deletions

View File

@ -2,13 +2,13 @@
abstract class Visualization abstract class Visualization
{ {
float value=0; float value=0;
float value2=1; float value2=-1000;
PVector posOrigin = new PVector(100,100); PVector posOrigin = new PVector(100,100);
float valueMin=0; float valueMin=0;
float valueMax=100; float valueMax=0;
float value2Min=0; //value 2 for twodimensional visualization float value2Min=0; //value 2 for twodimensional visualization or second displayed value
float value2Max=1; float value2Max=0;
float valueMinRecord = Float.NaN; //nan means no value here float valueMinRecord = Float.NaN; //nan means no value here
float valueMaxRecord = Float.NaN; float valueMaxRecord = Float.NaN;
@ -18,6 +18,7 @@ abstract class Visualization
//default colors (not all used by every implementation) //default colors (not all used by every implementation)
color cmain = color(255,255,255); color cmain = color(255,255,255);
color cmain2 = color(255,255,255);
color cscale = color(100,100,100); color cscale = color(100,100,100);
color cborder = color(200,200,200); color cborder = color(200,200,200);
color cmin = color(0,150,0); color cmin = color(0,150,0);
@ -29,7 +30,9 @@ abstract class Visualization
int showdecimals=2; int showdecimals=2;
String title=""; String title="";
String title2="";
String valueUnit=""; String valueUnit="";
String value2Unit="";
public abstract void drawVis(); public abstract void drawVis();
@ -86,6 +89,9 @@ abstract class Visualization
public void setcmain(color pc){ public void setcmain(color pc){
this.cmain=pc; this.cmain=pc;
} }
public void setcmain2(color pc){
this.cmain2=pc;
}
public void setcscale(color pc){ public void setcscale(color pc){
this.cscale=pc; this.cscale=pc;
} }
@ -106,10 +112,18 @@ abstract class Visualization
this.title=pt; this.title=pt;
} }
public void setTitle2(String pt) {
this.title2=pt;
}
public void setValueUnit(String pt) { public void setValueUnit(String pt) {
this.valueUnit=pt; this.valueUnit=pt;
} }
public void setValue2Unit(String pt) {
this.value2Unit=pt;
}
public void setshowdecimals(int pd) { public void setshowdecimals(int pd) {
this.showdecimals=pd; this.showdecimals=pd;
} }
@ -155,6 +169,7 @@ public class BarV extends Visualization {
rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y ); rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y );
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
text(super.getFormattedValue(super.valueMin)+valueUnit,super.posOrigin.x+this.size.x+1,super.posOrigin.y+super.textsize/2); text(super.getFormattedValue(super.valueMin)+valueUnit,super.posOrigin.x+this.size.x+1,super.posOrigin.y+super.textsize/2);
text(super.getFormattedValue(super.valueMax)+valueUnit,super.posOrigin.x+this.size.x+1,super.posOrigin.y-this.size.y+super.textsize/2); text(super.getFormattedValue(super.valueMax)+valueUnit,super.posOrigin.x+this.size.x+1,super.posOrigin.y-this.size.y+super.textsize/2);
@ -203,6 +218,7 @@ public class BarV_cmd extends Visualization {
line(super.posOrigin.x,super.posOrigin.y-zeroy,super.posOrigin.x+this.size.x,super.posOrigin.y-zeroy); //zero line line(super.posOrigin.x,super.posOrigin.y-zeroy,super.posOrigin.x+this.size.x,super.posOrigin.y-zeroy); //zero line
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
//text(super.getFormattedValue(super.valueMin),super.posOrigin.x+this.size.x+1,super.posOrigin.y+super.textsize/2); //text(super.getFormattedValue(super.valueMin),super.posOrigin.x+this.size.x+1,super.posOrigin.y+super.textsize/2);
//text(super.getFormattedValue(super.valueMax),super.posOrigin.x+this.size.x+1,super.posOrigin.y-this.size.y+super.textsize/2); //text(super.getFormattedValue(super.valueMax),super.posOrigin.x+this.size.x+1,super.posOrigin.y-this.size.y+super.textsize/2);
@ -252,6 +268,7 @@ public class BarH extends Visualization {
rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y ); rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y );
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
text(super.getFormattedValue(super.valueMin)+valueUnit,super.posOrigin.x-super.getFormattedValue(super.valueMin).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); text(super.getFormattedValue(super.valueMin)+valueUnit,super.posOrigin.x-super.getFormattedValue(super.valueMin).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1);
text(super.getFormattedValue(super.valueMax)+valueUnit,super.posOrigin.x+this.size.x-super.getFormattedValue(super.valueMax).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); text(super.getFormattedValue(super.valueMax)+valueUnit,super.posOrigin.x+this.size.x-super.getFormattedValue(super.valueMax).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1);
@ -299,6 +316,7 @@ public class BarH_cmd extends Visualization {
rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y ); rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y );
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
//text(super.getFormattedValue(super.valueMin),super.posOrigin.x-super.getFormattedValue(super.valueMin).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); //text(super.getFormattedValue(super.valueMin),super.posOrigin.x-super.getFormattedValue(super.valueMin).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1);
//text(super.getFormattedValue(super.valueMax),super.posOrigin.x+this.size.x-super.getFormattedValue(super.valueMax).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); //text(super.getFormattedValue(super.valueMax),super.posOrigin.x+this.size.x-super.getFormattedValue(super.valueMax).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1);
@ -318,6 +336,8 @@ public class Tacho extends Visualization {
public Tacho(int px, int py, int psize, float pvmin, float pvmax) { public Tacho(int px, int py, int psize, float pvmin, float pvmax) {
super.valueMin=pvmin; super.valueMin=pvmin;
super.valueMax=pvmax; super.valueMax=pvmax;
super.value2Min=pvmin; //same scale
super.value2Max=pvmax; //same scale
super.posOrigin= new PVector(px,py); //circle center super.posOrigin= new PVector(px,py); //circle center
this.size = psize; //radius from the center this.size = psize; //radius from the center
} }
@ -330,6 +350,12 @@ public class Tacho extends Visualization {
float angle=PI-super.getValueNormalized()*PI; //0=right, positive=CCW float angle=PI-super.getValueNormalized()*PI; //0=right, positive=CCW
line(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+cos(angle)*this.size*0.8 ,super.posOrigin.y-sin(angle)*this.size*0.8); //draw tacho needle line(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+cos(angle)*this.size*0.8 ,super.posOrigin.y-sin(angle)*this.size*0.8); //draw tacho needle
if (super.value2!=-1000) {
stroke(super.cmain2);
float angle2=PI-super.getValue2Normalized()*PI; //0=right, positive=CCW
line(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+cos(angle2)*this.size*0.8 ,super.posOrigin.y-sin(angle2)*this.size*0.8); //draw tacho needle
}
if (!Float.isNaN(super.valueMinRecord)){ if (!Float.isNaN(super.valueMinRecord)){
stroke(this.cmin); stroke(this.cmin);
float angleMin=PI-super.getValueMinNormalized()*PI; //0=right, positive=CCW float angleMin=PI-super.getValueMinNormalized()*PI; //0=right, positive=CCW
@ -352,10 +378,20 @@ public class Tacho extends Visualization {
} }
//text //text
fill(super.cmain);
text(super.getFormattedValue(super.value)+valueUnit,super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize/2-this.size*0.3); text(super.getFormattedValue(super.value)+valueUnit,super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize/2-this.size*0.3);
if (super.value2!=-1000) { //value2 is used
fill(super.cmain2);
text(super.getFormattedValue(super.value2)+value2Unit,super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize/2*4-this.size*0.3);
}
//Title //Title
text(super.title, super.posOrigin.x-super.title.length()*super.textWidthScale, super.posOrigin.y+super.textsize*1.5); textAlign(CENTER);
fill(super.ctext);
text(super.title, super.posOrigin.x, super.posOrigin.y+super.textsize*1.5);
if (super.title2!="") {
text(super.title2, super.posOrigin.x, super.posOrigin.y+super.textsize*1.5*2);
}
} }
} }
@ -421,6 +457,7 @@ public class Direction extends Visualization {
line(super.posOrigin.x+cos(angle+0.1)*_vecsize*0.9,super.posOrigin.y-sin(angle+0.1)*_vecsize*0.9,super.posOrigin.x+cos(angle)*_vecsize,super.posOrigin.y-sin(angle)*_vecsize); line(super.posOrigin.x+cos(angle+0.1)*_vecsize*0.9,super.posOrigin.y-sin(angle+0.1)*_vecsize*0.9,super.posOrigin.x+cos(angle)*_vecsize,super.posOrigin.y-sin(angle)*_vecsize);
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
text(super.getFormattedValue(super.value)+valueUnit,super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize*1.5*1); text(super.getFormattedValue(super.value)+valueUnit,super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize*1.5*1);
if (super.value2<super.value2Max){ //display only if in use if (super.value2<super.value2Max){ //display only if in use
@ -518,6 +555,7 @@ public class GraphRoll extends Visualization {
} }
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
text(super.getFormattedValue(super.value)+valueUnit, super.posOrigin.x+this.size.x-50, super.posOrigin.y+super.textsize*1.5); text(super.getFormattedValue(super.value)+valueUnit, super.posOrigin.x+this.size.x-50, super.posOrigin.y+super.textsize*1.5);
text(super.getFormattedValue(super.valueMin)+valueUnit, super.posOrigin.x+this.size.x+1, super.posOrigin.y+super.textsize*0.5-1); text(super.getFormattedValue(super.valueMin)+valueUnit, super.posOrigin.x+this.size.x+1, super.posOrigin.y+super.textsize*0.5-1);
@ -618,12 +656,13 @@ public class GraphRoll_minimal extends Visualization {
} }
//text //text
textAlign(LEFT);
fill(super.ctext); fill(super.ctext);
text(super.getFormattedValue(super.value)+valueUnit, super.posOrigin.x+this.size.x+1, super.posOrigin.y-this.valuearray[(_cpos)%this.valuearray.length]*this.size.y); text(super.getFormattedValue(super.value)+valueUnit, super.posOrigin.x+this.size.x+1, super.posOrigin.y-this.valuearray[(_cpos)%this.valuearray.length]*this.size.y);
//text(super.getFormattedValue(super.valueMin), super.posOrigin.x+this.size.x+1, super.posOrigin.y+super.textsize*0.5-1); //text(super.getFormattedValue(super.valueMin), super.posOrigin.x+this.size.x+1, super.posOrigin.y+super.textsize*0.5-1);
//text(super.getFormattedValue(super.valueMax), super.posOrigin.x+this.size.x+1, super.posOrigin.y-this.size.y+super.textsize*0.5-1); //text(super.getFormattedValue(super.valueMax), super.posOrigin.x+this.size.x+1, super.posOrigin.y-this.size.y+super.textsize*0.5-1);
//Title //Title
text(super.title, super.posOrigin.x, super.posOrigin.y+super.textsize*1.5); text(super.title, super.posOrigin.x, super.posOrigin.y-this.size.y+super.textsize);
} }
} }

View File

@ -38,12 +38,18 @@ Visualization vis_graph_currentAll;
Visualization vis_graph_speed_mean; Visualization vis_graph_speed_mean;
long lastTimeData=0; //last time data received Visualization vis_c_graph_receivedelay;
Table logdata; Table logdata;
int nextID=0; //next row number to be displayed int nextID=0; //next row number to be displayed
long nextTime=0; //time of nextID row long lastTimeData=0; //last time data received
long nextTimeData=0; //time of nextID row
long lastTimeMillis=0; //local time
long nextTimeMillis=0; //local time
int dataErrorCount=0; int dataErrorCount=0;
@ -92,7 +98,7 @@ void setup() {
println("loaded "+logdata.getRowCount()+" lines. Times: "+logdata.getRow(0).getFloat("time")+"s to "+logdata.getRow(logdata.getRowCount()-1).getFloat("time")+"s"); println("loaded "+logdata.getRowCount()+" lines. Times: "+logdata.getRow(0).getFloat("time")+"s to "+logdata.getRow(logdata.getRowCount()-1).getFloat("time")+"s");
} }
PVector pos_vis_cmd = new PVector(100,150); PVector pos_vis_cmd = new PVector(100,200);
PVector size_vis_cmd = new PVector(10,100); PVector size_vis_cmd = new PVector(10,100);
PVector dist_vis_cmd = new PVector(80,150); PVector dist_vis_cmd = new PVector(80,150);
@ -166,23 +172,39 @@ void setup() {
vis_c_speed_mean = new Tacho(width/2-150,height-150,100,-100,600); vis_c_speed_mean = new Tacho(width/2-150,height-150,100,-100,600);
vis_c_speed_mean.setTitle("Speed"); vis_c_speed_mean.setTitle("Speed");
vis_c_speed_mean.setValueUnit("rpm"); vis_c_speed_mean.setValueUnit("rpm");
vis_c_speed_mean.setShowMinMax(true);
//Current //Current
color c_currentall=color(240,255,50);
vis_currentAll = new Tacho(width/2+150,height-150,100,-1,10); vis_currentAll = new Tacho(width/2+150,height-150,100,-1,10);
vis_currentAll.setTitle("minCurrent"); vis_currentAll.setTitle("minCurrent");
vis_currentAll.setValueUnit("A"); vis_currentAll.setValueUnit("A");
vis_currentAll.setcmain(c_currentall); //currentAll color
vis_currentAll.setShowMinMax(true);
vis_currentAll.setValue2Unit("A");
vis_currentAll.setTitle2("avgCurrent/wheel");
vis_currentAll.setcmain2(c_current);
//Graph //Graph
vis_graph_speed_mean = new GraphRoll_minimal(700, 250, 400,200,-100,600,1); PVector size_vis_graph1= new PVector(400,200);
PVector pos_vis_graph1= new PVector(width-size_vis_graph1.x-60,250);
vis_graph_speed_mean = new GraphRoll_minimal(int(pos_vis_graph1.x), int(pos_vis_graph1.y), int(size_vis_graph1.x),int(size_vis_graph1.y),-100,600,1);
vis_graph_speed_mean.setcborder(c_speed); vis_graph_speed_mean.setcborder(c_speed);
vis_graph_speed_mean.setcmain(c_speed); vis_graph_speed_mean.setcmain(c_speed);
vis_graph_speed_mean.setValueUnit("rpm"); vis_graph_speed_mean.setValueUnit("rpm");
vis_graph_currentAll = new GraphRoll_minimal(700, 250, 400,200,-1,10,1); vis_graph_currentAll = new GraphRoll_minimal(int(pos_vis_graph1.x), int(pos_vis_graph1.y), int(size_vis_graph1.x),int(size_vis_graph1.y),-1,10,1);
vis_graph_currentAll.setcborder(c_current); vis_graph_currentAll.setcborder(c_currentall);
vis_graph_currentAll.setcmain(c_current); vis_graph_currentAll.setcmain(c_currentall);
vis_graph_currentAll.setValueUnit("A"); vis_graph_currentAll.setValueUnit("A");
color c_receivedelay=color(150,150,150);
vis_c_graph_receivedelay = new GraphRoll_minimal(5, vis_textsize*2+40, 200,40,0,1000,1);
vis_c_graph_receivedelay.setcborder(c_receivedelay);
vis_c_graph_receivedelay.setcmain(c_receivedelay);
vis_c_graph_receivedelay.setValueUnit("ms");
vis_c_graph_receivedelay.setTitle("receivedelay");
@ -194,35 +216,38 @@ void draw() {
long loopmillis=millis()+25000; long loopmillis=millis()+25000;
if (useSerial) { if (useSerial) {
while (serial.available() > 0) { if (serial.available() > 0) {
serialString = serial.readStringUntil(serial_endchar); serialString = serial.readStringUntil(serial_endchar);
//println("read:"+serialString); //println("read:"+serialString);
if (serialString != null) { if (serialString != null) {
println(serialString); println(serialString);
String[] list = split(serialString, ','); String[] list = split(serialString, ',');
if (list.length==20) { if (list.length==20) { //data ok
lastTimeData=nextTime; lastTimeMillis=nextTimeMillis;
nextTime=int(parseFloat(list[0])*1000); nextTimeMillis=loopmillis;
cmd_FrontL=parseInt(list[1]);
cmd_FrontR=parseInt(list[2]); lastTimeData=nextTimeData;
cmd_RearL=parseInt(list[3]); nextTimeData=int(parseFloat(list[0])*1000);
cmd_RearR=parseInt(list[4]); cmd_FrontL=parseInt(list[1]);
current_FrontL=parseFloat(list[5]); cmd_FrontR=parseInt(list[2]);
current_FrontR=parseFloat(list[6]); cmd_RearL=parseInt(list[3]);
current_RearL=parseFloat(list[7]); cmd_RearR=parseInt(list[4]);
current_RearR=parseFloat(list[8]); current_FrontL=parseFloat(list[5]);
speed_FrontL=parseInt(list[9]); current_FrontR=parseFloat(list[6]);
speed_FrontR=parseInt(list[10]); current_RearL=parseFloat(list[7]);
speed_RearL=parseInt(list[11]); current_RearR=parseFloat(list[8]);
speed_RearR=parseInt(list[12]); speed_FrontL=parseInt(list[9]);
temp_Front=parseFloat(list[13]); speed_FrontR=parseInt(list[10]);
temp_Rear=parseFloat(list[14]); speed_RearL=parseInt(list[11]);
vbat_Front=parseFloat(list[15]); speed_RearR=parseInt(list[12]);
vbat_Rear=parseFloat(list[16]); temp_Front=parseFloat(list[13]);
currentAll=parseFloat(list[17]); temp_Rear=parseFloat(list[14]);
throttle=parseInt(list[18]); vbat_Front=parseFloat(list[15]);
brake=parseInt(list[19]); vbat_Rear=parseFloat(list[16]);
currentAll=parseFloat(list[17]);
throttle=parseInt(list[18]);
brake=parseInt(list[19]);
}else{ //data missing or too much }else{ //data missing or too much
dataErrorCount++; dataErrorCount++;
} }
@ -230,10 +255,13 @@ void draw() {
} }
} }
}else{ }else{
if (loopmillis>=nextTime){ //New Data if (loopmillis>=nextTimeData){ //New Data
TableRow row = logdata.getRow(nextID); TableRow row = logdata.getRow(nextID);
lastTimeData=nextTime; lastTimeData=nextTimeData;
nextTime=(long)(row.getFloat("time")*1000); //get time and convert from seconds to ms nextTimeData=(long)(row.getFloat("time")*1000); //get time and convert from seconds to ms
lastTimeMillis=nextTimeMillis;
nextTimeMillis=loopmillis;
cmd_FrontL=row.getInt("cmd_FrontL"); cmd_FrontL=row.getInt("cmd_FrontL");
cmd_FrontR=row.getInt("cmd_FrontR"); cmd_FrontR=row.getInt("cmd_FrontR");
@ -255,9 +283,9 @@ void draw() {
throttle=row.getInt("throttle"); throttle=row.getInt("throttle");
brake=row.getInt("brake"); brake=row.getInt("brake");
if (loopmillis-nextTime>1000 && nextTime>lastTimeData) {//too much behind if (loopmillis-nextTimeData>1000 && nextTimeData>lastTimeData) {//too much behind
long _timestep=nextTime-lastTimeData; //approximated time step long _timestep=nextTimeData-lastTimeData; //approximated time step
nextID+=(loopmillis-nextTime)/_timestep* 0.9; //fast forward estimated time steps nextID+=(loopmillis-nextTimeData)/_timestep* 0.9; //fast forward estimated time steps
} }
nextID++; nextID++;
nextID=nextID%logdata.getRowCount(); nextID=nextID%logdata.getRowCount();
@ -290,15 +318,20 @@ void draw() {
int speed_mean=int((speed_FrontL+speed_FrontR+speed_RearL+speed_RearR)/4.0); int speed_mean=int((speed_FrontL+speed_FrontR+speed_RearL+speed_RearR)/4.0);
vis_c_speed_mean.setValue(speed_mean); vis_c_speed_mean.drawVis(); vis_c_speed_mean.setValue(speed_mean); vis_c_speed_mean.drawVis();
vis_currentAll.setValue(currentAll); vis_currentAll.drawVis();
vis_currentAll.setValue(currentAll);
float current_mean=(current_FrontL+current_FrontR+current_RearL+current_RearR)/4.0;
vis_currentAll.setValue2(current_mean); vis_currentAll.drawVis();
vis_graph_speed_mean.setValue(speed_mean); vis_graph_speed_mean.drawVis(); vis_graph_speed_mean.setValue(speed_mean); vis_graph_speed_mean.drawVis();
vis_graph_currentAll.setValue(currentAll); vis_graph_currentAll.drawVis(); vis_graph_currentAll.setValue(currentAll); vis_graph_currentAll.drawVis();
vis_c_graph_receivedelay.setValue(loopmillis-lastTimeMillis); vis_c_graph_receivedelay.drawVis();
//Temperature //Temperature
PVector pos_temperature = new PVector(220,12); PVector pos_temperature = new PVector(500,12);
colorMode(HSB, 360, 100, 100); colorMode(HSB, 360, 100, 100);
fill(color(map(temp_Front,16,50,180,360),50,100)); fill(color(map(temp_Front,16,50,180,360),50,100));
text("temp_Front="+(temp_Front)+"°C", pos_temperature.x,pos_temperature.y); text("temp_Front="+(temp_Front)+"°C", pos_temperature.x,pos_temperature.y);
@ -317,14 +350,14 @@ void draw() {
fill(color(200,200,200)); fill(color(200,200,200));
textAlign(LEFT); textAlign(LEFT);
textSize(vis_textsize); textSize(vis_textsize);
text("d="+(nextTime-lastTimeData)+"ms", 5+70,12); text("d="+(nextTimeData-lastTimeData)+"ms", 5+75,12);
if (!useSerial && loopmillis-lastTimeData>(nextTime-lastTimeData)*10) { //deviation too high when reading from file if (!useSerial && loopmillis-lastTimeData>(nextTimeData-lastTimeData)*10) { //deviation too high when reading from file
text("ff="+(loopmillis-lastTimeData)+"ms", 5+70+70,12); //show warning text("ff="+(loopmillis-lastTimeData)+"ms", 5+75*2,12); //show warning
} }
text("t="+(loopmillis/1000.0)+"s", 5,12); text("t="+(loopmillis/1000.0)+"s", 5,12);
text(""+(dataErrorCount)+" errors", 5,12+vis_textsize); text(""+(dataErrorCount)+" errors", 5+70*3,12);
} }