Web server for Classic using Arduino DUE

Started by dgd, March 12, 2015, 01:00:24 AM

Previous topic - Next topic

dgd

#45
Gauge display looks a little nicer now. Modified arduino sketch now deals with request from browser to load a jpg file so I copied sasa.jpg to the SD, adjusted the html css for background image control, changed the svg panel colours and transparency and arrived at the display below.
Also messed about with transparency on the meters, changed face colours, text and tick colours but in end went back to non transparent white faces with hints of colour except the battery voltage with stronger colours. Of course any jpg image could be used for the background.

Now to wrap up the Arduino black box server I just want to get the DUE working with up to 4 Classics and/or Kids and figure out what a possible gauges and svg panels web page should look like.
The gauges now run with 1 to 1.5 second updating after reviewing code to remove some delays from the modbus lib

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

After some experimenting with the SimpleModbusMaster library its more obvious that it is not really very suitable for dealing with multiple rs232 connections - its really designed to deal with an rs485 bus with attached devices identified by unique device ID numbers.
My earlier method of just rerunning the configure with a different serial port specified then waiting a few seconds before moving to the next port, etc in a round robin manner, is just not going to work  for a realtime gauge type display.
So the solution has been to not use SimpleModbusMaster but just take out the bits needed and use a. configure that does not specify the serial port. Instead have the port as part of the packet string so that one call to update_modbus reads packets as needed from all rs232 attached Classics.
This appears to work quite well with under 1 second retreival time of data from 3 Classics. This, in turn, gets a gauge refresh time of about 1.3 seconds which looks pretty close to real time.

The Canv gauge also looks possible to modify. I looked at a double gauge with left and right sections each  with its own needle and value ticks, looks nice but gets weird with 4 Classics on a quarter of a gauge each. I sort of abandoned the multineedle gauge as the best looking display I could make for 4 Classics, was two double gauges for input volts or output amps. Just didn't look right either. Far too many gauges on one screen.

The best looking gauge screen (for me) was just Battery volts, Watts, WBjr amps in 3 qauges beside each other then a separate svg panel for the battery info and then one for each Classic. Radio buttons allows the Watts gauge to display either total watts being output or the watts from any of the Classics. Other data: input volts, output amps, kwh, temps, charging state were text and numbers in the svg panel.
Images below soon  :)

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

Now have several different web page display options on SD card, same Arduino code with Ajax updating  of display data fields just different loaded web page.
Justgage gauges for a different look  :)

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

#48
..looking at some methods to display multiple gauges for the 2 to 4 controllers  rs232 interfaced to the DUE.
this one looked interesting with overlaid gauges and mousing over the top of a gauge brought it to the surface.
All rendered in HTML5 canvas so only the web page changes, the same XML is provided from the DUE server code.
These Rchart gauges can be configured for LHS or RHS half display so its easy, but impractical, to make a porsche 911 dash lookalike  :P    several images below of different gauges on surface

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

#49
An updated version of the index.htm file stored on SD card that is the web code served by the Arduino DUE or Mega with the five canv gauges and svg panel for one Classic with Wbjr fitted.
This code now works with most browsers - Firefox, IE, Safari, Chrome etc.. I have tested it on several PCs, Apple Ipad, Iphone and various pads and phones using Android versions.

There should also be a background image file named sasa.jpg on the SD card. This can be any jpg image.

dgd


<!DOCTYPE html>
<html>
    <head>
        <title>Classic Canv gauges</title>
        <script>
var batV_val = 22;
var batA_val  = 0;
                var Cwatts_val = 0;
var Cvin_val = 0;
var Camps_val = 0;

<!--- Start of gauge code  --->
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};
while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('t W=v(f){W.2t.3T(A);A.B={Z:2u,19:1q,1h:1q,1J:U,1b:D,K:0,V:[\'0\',\'20\',\'40\',\'2A\',\'2B\',\'D\'],2r:10,2C:M,1E:U,2q:{2D:3,2E:2},2H:M,1c:{2j:10,2m:3y,2O:\'3v\'},J:{2P:\'#4h\',V:\'#31\',2r:\'#3k\',1J:\'#37\',1E:\'#37\',3e:\'#31\',1t:{2s:\'1e(3Y, 3d, 3d, 1)\',3c:\'1e(1Y, 5I, 5E, .9)\'}},1o:[{1n:20,1D:2A,1F:\'#3j\'},{1n:2A,1D:2B,1F:\'#36\'},{1n:2B,1D:D,1F:\'#5n\'}]};t g=0,1p=A,N=0,1S=0,1G=U;A.5d=v(a){N=f.1c?g:a;t b=(f.1b-f.K)/D;1S=a>f.1b?1S=f.1b+b:a<f.K?f.K-b:a;g=a;f.1c?3l():A.1g();C A};A.3m=v(a){N=g=a;A.1g();C A};A.4T=v(){g=N=1S=A.B.K;A.1g();C A};A.4R=v(){C g};A.13=v(){};v 2k(a,b){Q(t i 4P b){z(1H b[i]=="1W"&&!(4O.4y.2V.4p(b[i])===\'[1W 4n]\')&&i!=\'Z\'){z(1H a[i]!="1W"){a[i]={}}2k(a[i],b[i])}O{a[i]=b[i]}}};2k(A.B,f);A.B.K=1R(A.B.K);A.B.1b=1R(A.B.1b);f=A.B;N=g=f.K;z(!f.Z){4m 4j("4g 4d 4b 46 44 41 3Z 3W W 1W!");}t j=f.Z.5K?f.Z:2R.5v(f.Z),q=j.3u(\'2d\'),1i,1y,1A,14,17,u,1d;v 2M(){j.19=f.19;j.1h=f.1h;1i=j.4s(M);1d=1i.3u(\'2d\');1y=j.19;1A=j.1h;14=1y/2;17=1A/2;u=14<17?14:17;1i.2J=U;1d.3P(14,17);1d.G();q.3P(14,17);q.G()};2M();A.4Z=v(a){2k(A.B,a);2M();A.1g();C A};t k={4q:v(p){C p},4e:v(p){C E.1L(p,2)},4c:v(p){C E.1L(p,5)},3v:v(p){C 1-E.1O(E.5C(p))},5k:v(p){C 1-(v(p){Q(t a=0,b=1;1;a+=b,b/=2){z(p>=(7-4*a)/11){C-E.1L((11-6*a-11*p)/4,2)+E.1L(b,2)}}})(1-p)},4S:v(p){C 1-(v(p){t x=1.5;C E.1L(2,10*(p-1))*E.1T(20*E.1a*x/3*p)})(1-p)}};t l=2u;v 3S(d){t e=2v 3R;l=2x(v(){t a=2v 3R-e,1M=a/d.2m;z(1M>1){1M=1}t b=1H d.2g=="v"?d.2g:k[d.2g];t c=b(1M);d.3Q(c);z(1M==1){2b(l)}},d.2j||10)};v 3l(){l&&2b(l);t b=(1S-N),1n=N,29=f.1c;3S({2j:29.2j,2m:29.2m,2g:29.2O,3Q:v(a){N=1R(1n)+b*a;1p.1g()}})};q.5l="3O";A.1g=v(){z(!1i.2J){1d.3M(-14,-17,1y,1A);1d.G();t a=q;q=1d;3L();3K();3I();3H();3F();3D();3z();1i.2J=M;q=a;5G a}q.3M(-14,-17,1y,1A);q.G();q.4a(1i,-14,-17,1y,1A);z(!W.28){t b=2x(v(){z(!W.28){C}2b(b);2K();2L();z(!1G){1p.13&&1p.13();1G=M}},10)}O{2K();2L();z(!1G){1p.13&&1p.13();1G=M}}C A};v S(a){C a*E.1a/4J};v 1l(a,b,c){t d=q.4Y(0,0,0,c);d.1V(0,a);d.1V(1,b);C d};v 3L(){t a=u/D*5g,3x=u-a,2a=u/D*5q,5u=u-2a,1f=u/D*5z,5A=u-1f;3t=u/D*5F;q.G();z(f.2H){q.2o=3x;q.2n=\'1e(0, 0, 0, 0.5)\'}q.P();q.16(0,0,a,0,E.1a*2,M);q.L=1l(\'#42\',\'#43\',a);q.T();q.R();q.P();q.16(0,0,2a,0,E.1a*2,M);q.L=1l(\'#49\',\'#36\',2a);q.T();q.P();q.16(0,0,1f,0,E.1a*2,M);q.L=1l(\'#3j\',\'#3s\',1f);q.T();q.P();q.16(0,0,3t,0,E.1a*2,M);q.L=f.J.2P;q.T();q.G()};v 3H(){t r=u/D*2T;q.2e=2;q.2U=f.J.V;q.G();Q(t i=0;i<f.V.H;++i){t a=45+i*(1U/(f.V.H-1));q.1z(S(a));q.P();q.1K(0,r);q.F(0,r-u/D*15);q.1X();q.R();q.G()}z(f.2C){q.1z(S(2X));q.P();q.16(0,0,r,S(45),S(4N),U);q.1X();q.R();q.G()}};v 3I(){t r=u/D*2T;q.2e=1;q.2U=f.J.2r;q.G();t b=f.2r*(f.V.H-1);Q(t i=0;i<b;++i){t a=45+i*(1U/b);q.1z(S(a));q.P();q.1K(0,r);q.F(0,r-u/D*7.5);q.1X();q.R();q.G()}};v 3F(){t r=u/D*55;Q(t i=0;i<f.V.H;++i){t a=45+i*(1U/(f.V.H-1)),p=1w(r,S(a));q.1x=20*(u/1q)+"2i 2Y";q.L=f.J.3e;q.2e=0;q.2h="2f";q.27(f.V[i],p.x,p.y+3)}};v 3D(){z(!f.1J){C}q.G();q.1x=24*(u/1q)+"2i 2Y";q.L=f.J.1J;q.2h="2f";q.27(f.1J,0,-u/4.25);q.R()};v 3z(){z(!f.1E){C}q.G();q.1x=22*(u/1q)+"2i 2Y";q.L=f.J.1E;q.2h="2f";q.27(f.1E,0,u/3.25);q.R()};v 32(a){t b=f.2q.2E,34=f.2q.2D;a=1R(a);t n=(a<0);a=E.35(a);z(b>0){a=a.5t(b).2V().1j(\'.\');Q(t i=0,s=34-a[0].H;i<s;++i){a[0]=\'0\'+a[0]}a=(n?\'-\':\'\')+a[0]+\'.\'+a[1]}O{a=E.3O(a).2V();Q(t i=0,s=34-a.H;i<s;++i){a=\'0\'+a}a=(n?\'-\':\'\')+a}C a};v 1w(r,a){t x=0,y=r,1O=E.1O(a),1T=E.1T(a),X=x*1T-y*1O,Y=x*1O+y*1T;C{x:X,y:Y}};v 3K(){q.G();t a=u/D*2T;t b=a-u/D*15;Q(t i=0,s=f.1o.H;i<s;i++){t c=f.1o[i],39=(f.1b-f.K)/1U,1P=S(45+(c.1n-f.K)/39),1N=S(45+(c.1D-f.K)/39);q.P();q.1z(S(2X));q.16(0,0,a,1P,1N,U);q.R();q.G();t d=1w(b,1P),3a=1w(a,1P);q.1K(d.x,d.y);q.F(3a.x,3a.y);t e=1w(a,1N),3b=1w(b,1N);q.F(e.x,e.y);q.F(3b.x,3b.y);q.F(d.x,d.y);q.1C();q.L=c.1F;q.T();q.P();q.1z(S(2X));q.16(0,0,b,1P-0.2,1N+0.2,U);q.R();q.1C();q.L=f.J.2P;q.T();q.G()}};v 2L(){t a=u/D*12,1f=u/D*8,1u=u/D*3X,1r=u/D*20,2l=u/D*4,1B=u/D*2,38=v(){q.3f=2;q.3g=2;q.2o=10;q.2n=\'1e(5L, 3h, 3h, 0.45)\'};38();q.G();z(N<0){N=E.35(f.K-N)}O z(f.K>0){N-=f.K}O{N=E.35(f.K)+N}q.1z(S(45+N/((f.1b-f.K)/1U)));q.P();q.1K(-1B,-1r);q.F(-2l,0);q.F(-1,1u);q.F(1,1u);q.F(2l,0);q.F(1B,-1r);q.1C();q.L=1l(f.J.1t.2s,f.J.1t.3c,1u-1r);q.T();q.P();q.F(-0.5,1u);q.F(-1,1u);q.F(-2l,0);q.F(-1B,-1r);q.F(1B/2-2,-1r);q.1C();q.L=\'1e(1Y, 1Y, 1Y, 0.2)\';q.T();q.R();38();q.P();q.16(0,0,a,0,E.1a*2,M);q.L=1l(\'#3s\',\'#36\',a);q.T();q.R();q.P();q.16(0,0,1f,0,E.1a*2,M);q.L=1l("#47","#48",1f);q.T()};v 3i(x,y,w,h,r){q.P();q.1K(x+r,y);q.F(x+w-r,y);q.23(x+w,y,x+w,y+r);q.F(x+w,y+h-r);q.23(x+w,y+h,x+w-r,y+h);q.F(x+r,y+h);q.23(x,y+h,x,y+h-r);q.F(x,y+r);q.23(x,y,x+r,y);q.1C()};v 2K(){q.G();q.1x=40*(u/1q)+"2i 30";t a=32(g),2Z=q.4f(\'-\'+32(0)).19,y=u-u/D*33,x=0,2W=0.12*u;q.G();3i(-2Z/2-0.21*u,y-2W-0.4i*u,2Z+0.3n*u,2W+0.4k*u,0.21*u);t b=q.4l(x,y-0.12*u-0.21*u+(0.12*u+0.3o*u)/2,u/10,x,y-0.12*u-0.21*u+(0.12*u+0.3o*u)/2,u/5);b.1V(0,"#37");b.1V(1,"#3k");q.2U=b;q.2e=0.3n*u;q.1X();q.2o=0.3p*u;q.2n=\'1e(0, 0, 0, 1)\';q.L="#4o";q.T();q.R();q.3f=0.3q*u;q.3g=0.3q*u;q.2o=0.3p*u;q.2n=\'1e(0, 0, 0, 0.3)\';q.L="#31";q.2h="2f";q.27(a,-x,y);q.R()}};W.28=U;(v(){t d=2R,h=d.3r(\'4r\')[0],2S=4t.4u.4v().4w(\'4x\')!=-1,2Q=\'4z://4A-4B.4C/4D/4E/4F-7-4G.\'+(2S?\'4H\':\'4I\'),1I="@1x-4K {"+"1x-4L: \'30\';"+"4M: 2Q(\'"+2Q+"\');"+"}",1s,r=d.3w(\'1v\');r.2N=\'1I/4Q\';z(2S){h.2p(r);1s=r.2I;1s.3A=1I}O{4U{r.2p(d.4V(1I))}4W(e){r.3A=1I}h.2p(r);1s=r.2I?r.2I:(r.4X||d.3B[d.3B.H-1])}t b=2x(v(){z(!d.3C){C}2b(b);t a=d.3w(\'50\');a.1v.51=\'30\';a.1v.52=\'53\';a.1v.1h=a.1v.19=0;a.1v.54=\'56\';a.57=\'.\';d.3C.2p(a);58(v(){W.28=M;a.59.5a(a)},3y)},1)})();W.2t=[];W.2t.5b=v(a){z(1H(a)==\'5c\'){Q(t i=0,s=A.H;i<s;i++){z(A[i].B.Z.18(\'5e\')==a){C A[i]}}}O z(1H(a)==\'5f\'){C A[a]}O{C 2u}};v 3E(a){z(2G.3G){2G.3G(\'5h\',a,U)}O{2G.5i(\'5j\',a)}}3E(v(){v 2F(a){t b=a[0];Q(t i=1,s=a.H;i<s;i++){b+=a[i].1Z(0,1).5m()+a[i].1Z(1,a[i].H-1)}C b};v 3J(a){C a.5o(/^\\s+|\\s+$/g,\'\')};t c=2R.3r(\'5p\');Q(t i=0,s=c.H;i<s;i++){z(c[i].18(\'1k-2N\')==\'5r-5s\'){t d=c[i],B={},1m,w=2c(d.18(\'19\')),h=2c(d.18(\'1h\'));B.Z=d;z(w){B.19=w}z(h){B.1h=h}Q(t e=0,1s=d.3N.H;e<1s;e++){1m=d.3N.5w(e).5x;z(1m!=\'1k-2N\'&&1m.1Z(0,5)==\'1k-\'){t f=1m.1Z(5,1m.H-5).5y().1j(\'-\'),I=d.18(1m);z(!I){2z}5B(f[0]){2y\'J\':{z(f[1]){z(!B.J){B.J={}}z(f[1]==\'1t\'){t k=I.1j(/\\s+/);z(k[0]&&k[1]){B.J.1t={2s:k[0],3c:k[1]}}O{B.J.1t=I}}O{f.5D();B.J[2F(f)]=I}}26}2y\'1o\':{z(!B.1o){B.1o=[]}2w=I.1j(\',\');Q(t j=0,l=2w.H;j<l;j++){t m=3J(2w[j]).1j(/\\s+/),1Q={};z(m[0]&&m[0]!=\'\'){1Q.1n=m[0]}z(m[1]&&m[1]!=\'\'){1Q.1D=m[1]}z(m[2]&&m[2]!=\'\'){1Q.1F=m[2]}B.1o.3T(1Q)}26}2y\'1c\':{z(f[1]){z(!B.1c){B.1c={}}z(f[1]==\'2O\'&&/^\\s*v\\s*\\(/.5H(I)){I=3U(\'(\'+I+\')\')}B.1c[f[1]]=I}26}5J:{t n=2F(f);z(n==\'13\'){2z}z(n==\'V\'){I=I.1j(/\\s+/)}O z(n==\'2C\'||n==\'2H\'){I=I==\'M\'?M:U}O z(n==\'2q\'){t o=I.1j(\'.\');z(o.H==2){I={2D:2c(o[0]),2E:2c(o[1])}}O{2z}}B[n]=I;26}}}}t g=2v W(B);z(d.18(\'1k-3V\')){g.3m(1R(d.18(\'1k-3V\')))}z(d.18(\'1k-13\')){g.13=v(){3U(A.B.Z.18(\'1k-13\'))}}g.1g()}}});',62,358,'||||||||||||||||||||||||||ctx|||var|max|function||||if|this|config|return|100|Math|lineTo|save|length|attrValue|colors|minValue|fillStyle|true|fromValue|else|beginPath|for|restore|radians|fill|false|majorTicks|Gauge|||renderTo||||onready|CX||arc|CY|getAttribute|width|PI|maxValue|animation|cctx|rgba|r2|draw|height|cache|split|data|lgrad|prop|from|highlights|self|200|rOut|ss|needle|rIn|style|rpoint|font|CW|rotate|CH|pad2|closePath|to|units|color|imready|typeof|text|title|moveTo|pow|progress|ea|sin|sa|hlCfg|parseFloat|toValue|cos|270|addColorStop|object|stroke|255|substr||025||quadraticCurveTo|||break|fillText|initialized|cfg|r1|clearInterval|parseInt||lineWidth|center|delta|textAlign|px|delay|applyRecursive|pad1|duration|shadowColor|shadowBlur|appendChild|valueFormat|minorTicks|start|Collection|null|new|hls|setInterval|case|continue|60|80|strokeTicks|int|dec|toCamelCase|window|glow|styleSheet|i8d|drawValueBox|drawNeedle|baseInit|type|fn|plate|url|document|ie|81|strokeStyle|toString|th|90|Arial|tw|Led|444|padValue||cint|abs|ccc|888|shad|vd|pe|pe1|end|128|numbers|shadowOffsetX|shadowOffsetY|143|roundRect|eee|666|animate|setRawValue|05|045|012|004|getElementsByTagName|f0f0f0|r3|getContext|cycle|createElement|d0|250|drawUnits|cssText|styleSheets|body|drawTitle|domReady|drawNumbers|addEventListener|drawMajorTicks|drawMinorTicks|trim|drawHighlights|drawPlate|clearRect|attributes|round|translate|step|Date|_animate|push|eval|value|the|77|240|creating||when|ddd|aaa|specified||not|e8e8e8|f5f5f5|fafafa|drawImage|was|quint|element|quad|measureText|Canvas|fff|04|Error|07|createRadialGradient|throw|Array|babab2|call|linear|head|cloneNode|navigator|userAgent|toLocaleLowerCase|indexOf|msie|prototype|http|smart|ip|net|styles|fonts|digital|mono|eot|ttf|180|face|family|src|315|Object|in|css|getValue|elastic|clear|try|createTextNode|catch|sheet|createLinearGradient|updateConfig|div|fontFamily|position|absolute|overflow||hidden|innerHTML|setTimeout|parentNode|removeChild|get|string|setValue|id|number|93|DOMContentLoaded|attachEvent|onload|bounce|lineCap|toUpperCase|999|replace|canvas|91|canv|gauge|toFixed|d1|getElementById|item|nodeName|toLowerCase|88|d2|switch|acos|shift|122|85|delete|test|160|default|tagName|188'.split('|'),0,{}))
<!--- End of gauge code --->

function GetArduinomodbus()
{
    nocache = "&nocache=" + Math.random() * 1000000;
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
if (this.readyState == 4)
        {
        if (this.status == 200)
{
if (this.responseXML != null)
{
    batA_val = this.responseXML.getElementsByTagName('bamps')[0].childNodes[0].nodeValue;
    batV_val = this.responseXML.getElementsByTagName('bvolts')[0].childNodes[0].nodeValue;
    Cvin_val = this.responseXML.getElementsByTagName('cvin')[0].childNodes[0].nodeValue;
    Cwatts_val = this.responseXML.getElementsByTagName('cwatts')[0].childNodes[0].nodeValue;
    Camps_val = this.responseXML.getElementsByTagName('camps')[0].childNodes[0].nodeValue;

    document.getElementById("CL_NAME").textContent =
      this.responseXML.getElementsByTagName('clname')[0].childNodes[0].nodeValue;
    document.getElementById("CL_MODEL").textContent =
      this.responseXML.getElementsByTagName('clmodel')[0].childNodes[0].nodeValue;
    document.getElementById("CL_SERNO").textContent =
      this.responseXML.getElementsByTagName('clserno')[0].childNodes[0].nodeValue;

    document.getElementById("CL_STATE").textContent =
      this.responseXML.getElementsByTagName('clstate')[0].childNodes[0].nodeValue;
    document.getElementById("CL_KWH").textContent =
      this.responseXML.getElementsByTagName('clkwh')[0].childNodes[0].nodeValue;
    document.getElementById("CL_AH").textContent =
      this.responseXML.getElementsByTagName('bah')[0].childNodes[0].nodeValue;
    document.getElementById("CL_AHR").textContent =
      this.responseXML.getElementsByTagName('bahr')[0].childNodes[0].nodeValue;

    document.getElementById("CL_SOC").textContent =
      this.responseXML.getElementsByTagName('bsoc')[0].childNodes[0].nodeValue;

    document.getElementById("Fet_Temp").textContent =
      this.responseXML.getElementsByTagName('fettemp')[0].childNodes[0].nodeValue;
    document.getElementById("Pcb_Temp").textContent =
      this.responseXML.getElementsByTagName('pcbtemp')[0].childNodes[0].nodeValue;
    document.getElementById("Bat_Temp").textContent =
      this.responseXML.getElementsByTagName('battemp')[0].childNodes[0].nodeValue;
    document.getElementById("Rem_Temp").textContent =
      this.responseXML.getElementsByTagName('remtemp')[0].childNodes[0].nodeValue;

    document.getElementById("Peak_Pwr").textContent =
      this.responseXML.getElementsByTagName('peakpwr')[0].childNodes[0].nodeValue;
    document.getElementById("Peak_Time").textContent =
      this.responseXML.getElementsByTagName('peaktime')[0].childNodes[0].nodeValue;

}
}
}
    }
    request.open("GET", "ajax_inputs" + nocache, true);
    request.send(null);
    setTimeout('GetArduinomodbus()', 500);
}
</script>
        <style>
          html {
            background: url(sasa.jpg) no-repeat center center fixed;
            background-size: cover;
          }

          body {
            color: white;
          }
        </style>

    </head>
    <body onload="GetArduinomodbus()">
    <table>
    <tr>
    <td width="100"></td>
    <td>
    </canvas>
    <canvas id="CV_gauge" width="350" height="350"
               data-type="canv-gauge"
               data-title="Input"
               data-major-ticks="0 30 60 90 120 150"
               data-minor-ticks="6"           
               data-units="Volts"
               data-value-format="3.1"
               data-max-value="150"
               data-min-value="0"
               data-highlights="0 150 #ffe"
               data-onready="setInterval( function ()
{ Gauge.Collection.get('CV_gauge').setValue(Cvin_val);
},500);">
    </canvas>
    </td>
    <td>
    </canvas>
    <canvas id="CW_gauge" width="450" height="450"
               data-type="canv-gauge"
               data-title="Power"
               data-major-ticks="0 250 500 750 1000 1250 1500 1750 2000"
               data-minor-ticks="5"           
               data-units="Watts"
               data-value-format="4.0"
               data-max-value="2000"
               data-min-value="0"
               data-color-plate="#0FF"
               data-highlights="0 2000 #FFe"
               data-onready="setInterval( function ()
{ Gauge.Collection.get('CW_gauge').setValue(Cwatts_val);
},500);">
    </canvas>
    </td>

    <td>
    </canvas>
    <canvas id="Ca_gauge" width="350" height="350"
               data-type="canv-gauge"
               data-title="Output"
               data-major-ticks="0 10 20 30 40 50 60 70 80 90 100"
               data-minor-ticks="4"           
               data-units="Amps"
               data-value-format="2.1"
               data-max-value="100"
               data-min-value="0"
               data-highlights="0 100 #ebffd6 "
               data-onready="setInterval( function ()
{ Gauge.Collection.get('Ca_gauge').setValue(Camps_val);
},500);">
    </canvas>
    </td>
    </tr>
</table>

<table>
<tr>
    <td width="100"></td>
    <td>
    </td>
    <td>
    <canvas id="BV_gauge" width="350" height="350"
               data-type="canv-gauge"
               data-title="Battery"
               data-major-ticks="22 23 24 25 26 27 28 29 30 31"
               data-minor-ticks="5"           
               data-units="Volts"
               data-value-format="2.1"
               data-max-value="31"
               data-min-value="22"
               data-highlights="22 23 #F00, 23 24 #ff1, 24 29 #0F1, 29 30 #ff1, 30 31 #F02"
               data-onready="setInterval( function ()
{ Gauge.Collection.get('BV_gauge').setValue(batV_val);
},500);">
    </canvas>
    </td>
    <td>
  <svg width="450" height="350">
  <defs>
    <radialGradient id="gradsq" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
      <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:0" />
      <stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
    </radialGradient>
    <filter id="filter" x="0" y="0">
      <feGaussianBlur stdDeviation="5" />
      <feOffset dx="5" dy="5" />
    </filter>
  </defs>

  <rect x="10" y="20" rx="20" ry="20" width="430" height="330" style="fill:blue;stroke:black;stroke-width:5;opacity:0.8" />
  <text font-size="20" font-family="Verdana" x="25" y="56" fill="white">
          <tspan id="CL_NAME">........</tspan> C<tspan id="CL_MODEL">...</tspan> #<tspan id="CL_SERNO"></tspan>
          </text>
 
  <text id="CL_STATE" font-size="25" font-family="Verdana" x="25" y="96" fill="white"></text>

  <text font-size="20" font-family="Verdana" x="25" y="131" fill="white">Energy kwh <tspan id="CL_KWH">...</tspan>    Battery SOC <tspan id="CL_SOC">...</tspan>%</text>
   <text font-size="20" font-family="Verdana" x="25" y="166" fill="white">Battery Ah Net <tspan id="CL_AH">.....</tspan> remaining      <tspan id="CL_AHR">....</tspan></text>
   
  <text font-size="20" font-family="Verdana" x="25" y="201" fill="white">Temps oC</text>
  <text font-size="18" font-family="Verdana" x="150" y="201" fill="white">Bat <tspan id="Bat_Temp">....</tspan></text>
  <text font-size="18" font-family="Verdana" x="275" y="201" fill="white">Fet <tspan id="Fet_Temp">....</tspan></text>
  <text font-size="18" font-family="Verdana" x="150" y="236" fill="white">Pcb <tspan id="Pcb_Temp">....</tspan></text>
  <text font-size="18" font-family="Verdana" x="275" y="236" fill="white">Rem <tspan id="Rem_Temp">....</tspan></text>

  <text font-size="20" font-family="Verdana" x="25" y="271" fill="white">Peak Power <tspan id="Peak_Pwr">....</tspan> watts at <tspan      id="Peak_Time">........</tspan>
         </text>

  <a xlink:href="node14.htm">
  <rect x="25" y="300" rx="5" ry="5" width="80" height="30" style="fill:yellow;stroke:black;stroke-width:2;opacity:1" />
  <text class="text" font-size="20" x="35" y="322"  fill="blue" text-anchor="start">10mlog</text>
  </a>
  <a xlink:href="node17.htm">
  <rect x="125" y="300" rx="5" ry="5" width="80" height="30" style="fill:yellow;stroke:black;stroke-width:2;opacity:1" />
  <text class="text" font-size="20" x="135" y="322"  fill="blue" text-anchor="start">Daylog</text>
  </a>
  <a xlink:href="hchart.htm">
  <rect x="225" y="300" rx="5" ry="5" width="80" height="30" style="fill:yellow;stroke:black;stroke-width:2;opacity:1" />
  <text class="text" font-size="20" x="235" y="322"  fill="blue" text-anchor="start">HChart</text>
  </a>

  Sorry, your browser does not support inline SVG.
    </svg>
    </td>
    <td>

    <canvas id="BA_gauge" width="350" height="350"
               data-type="canv-gauge"
               data-title="WBjr"
               data-major-ticks="-80 -60 -40 -20 0 20 40 60 80"
               data-minor-ticks="4"           
               data-units="Amps"
               data-value-format="2.1"
               data-max-value="80"
               data-min-value="-80"
               data-colors-plate="#fff"
               data-highlights="-80 0 #ffcccc, 0 80 #ebffd6"
               data-onready="setInterval( function ()
{ Gauge.Collection.get('BA_gauge').setValue(batA_val);
},500);">
    </canvas>
    </td>
</tr>
</table>
</html>
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

#50
Just a coupe of pics and details of the hardware used for the dashboard gauge display.
For connecting to a single Classic with Wbjr installed.

This uses the Arduino Mega 2560 with ethernet/SD card shield and a single port RS232 shield.
http://www.ebay.com/itm/New-ATmega2560-16AU-Improved-version-CH340G-MEGA2560-R3-Board-For-Arduino-OT8G-/221770058429?pt=LH_DefaultDomain_0&hash=item33a2868abd
http://www.ebay.com/sch/i.html?_from=R40&_trksid=p2047675.m570.l1313.TR0.TRC0.H0.Xethernet+shield+Arduino.TRS0&_nkw=ethernet+shield+Arduino&_sacat=0
http://www.ebay.com/itm/RS232-Shield-V1-for-Arduino-/321752984988?pt=LH_DefaultDomain_0&hash=item4ae9f8ed9c

These, along with a small 2 relay card, are mounted in an ex-computer power supply case, an aluminum slotted cover design. Makes a nice 'black box' computer  :D
The 2560 on bottom then ethernet/SD shield plugged into it then serial card plugged into ehernet shield.
The rx/tx leds on the serial card are visible through the slots and are continually blinking as serial data is input from the Classic and I like seeing blinky lights  :)
Still need to neaten up the wiring and get it inside a bit of flex conduit.
The two small changeover relays, not connected yet, are to provide two additional AUX ports and a tiny  circuit board, also not installed yet, will bring two PWM outputs to a small terminal block.

The version of this to connect up to four Classics is based on the Arduino DUE and uses a different sketch, multiport serial card and different html code on SD card.

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

#51
Have just updated the index.htm file for Classic canv gauge dashboard that is listed in previous posting.

This now includes two buttons that display further web pages.
The first is a 20 line text list of 10 minute intervals of Classic data, similar to that node14(?) list that was part of the mynidnite testing a couple of years ago
The second is  Highchart graph(s) with selectable graph types and data to graph.
Will post these additional web pages after some more testing. Highcharts is a very easy charting system to include and supports many chart types and configurations.

The Arduino code is also updated to save a 1 minute interval csv file on SD storage, up to several months to a years data in total. Just need to let this build up for a few days/weeks to get enough data to test graph dispays
The web pages display this csv file data.

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

#52
Listed below is the file node14.htm that is stored on SD card in ARduino ethernet card. This is the file loaded to web browser when the rightmost yellow button CLdata is pressed in the window of the gauges display.
It loads a web page showing the text list log of 10 minute data records from Classic

The html and javascript code is not too arduous, it loads data from file CLlog.xml that is created by the Arduino server, extracting runtime data from memory arrays and formatting into XML file format.
Layout uses simple html tables with some css colour and layout definitions.
Data is displayed latest first down list to oldest in lhs table then continues in rhs table.
Will eventually use svg design to make visually nicer.
Web page example as produced by this file several messages below

dgd


<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
    border: 1px solid black;
    border-collapse:collapse;
    font-family:"Verdana";
}
th, td {
    padding: 5px;
}
caption {
    caption-side: top;
    text-align:left;
    background-color: rgba(128, 255, 255, 0.5);
    font-faamily:"Verdana";
}
body { background-color: #F5F5DC;}  /* beige */
th { background-color: rgba(0, 0, 255, 0.3);}  /* blue with opacity */
td { background-color: rgba(0, 0, 255, 0.1);}  /* blue with opacity */
</style>
</head>

<body>

<title> CLlog.xml test </title>
<script>
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }

xmlhttp.open("GET","CLlog.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
var x=xmlDoc.getElementsByTagName("CLdata");

  document.write("<table><caption>  Ten minute Log records for ");
  document.write(x[0].getElementsByTagName("clname")[0].childNodes[0].nodeValue);
  document.write("  C");
  document.write(x[0].getElementsByTagName("clmodel")[0].childNodes[0].nodeValue);
  document.write("  #");
  document.write(x[0].getElementsByTagName("clserno")[0].childNodes[0].nodeValue);
  document.write("</b></caption><tr><td>");

document.write

("<table><tr><th>Time</th><th>State</th><th>InpV</th><th>KwH</th><th>Watts</th><th>BattV</th><th>OutA</th>");
document.write("<th>BattA</th><th>SoC</th><th>AhRem</th><th>AhNet</th></tr>");

for (i=1;i<x.length;i++)
  {
     if (i == 25)
     {
           document.write("</td></tr></table></td><td valign=\"top\">");
           document.write     

("<table><tr><th>Time</th><th>State</th><th>InpV</th><th>KwH</th><th>Watts</th><th>BattV</th><th>OutA</th>");
           document.write("<th>BattA</th><th>SoC</th><th>AhRem</th><th>AhNet</th></tr>");
     }
  document.write("<tr><td>");
  document.write(x[i].getElementsByTagName("HRS")[0].childNodes[0].nodeValue);
  document.write(":");
  if ( x[i].getElementsByTagName("MINS")[0].childNodes[0].nodeValue.length == 1)
     document.write("0");
  document.write(x[i].getElementsByTagName("MINS")[0].childNodes[0].nodeValue);
  document.write("</td><td>");
  switch (x[i].getElementsByTagName("STATE")[0].childNodes[0].nodeValue)
  {
  case '0':
    document.write("Resting");
    break;
  case '3':
    document.write("Absorb");
    break;
  case '4':
    document.write("BulkMppt");
    break;
  case '5':
    document.write("Float");
    break;
  case '6':
    document.write("Float Mppt");
    break;
  case '7':
    document.write("Equalize");
    break;
  case "10":
    document.write("HyperVOC");
    break;
  case "18":
    document.write("Eq Mppt");
    break;
  default:
    document.write("Unknown");
  }
  document.write("</td><td>");
  var val=(x[i].getElementsByTagName("INV")[0].childNodes[0].nodeValue.slice(0,
          x[i].getElementsByTagName("INV")[0].childNodes[0].nodeValue.length -1));
  document.write(val);
  document.write("</td><td>");
  document.write(x[i].getElementsByTagName("KWH")[0].childNodes[0].nodeValue);
  document.write("</td><td>");
  document.write(x[i].getElementsByTagName("WATTS")[0].childNodes[0].nodeValue);
  document.write("</td><td>");
  var val=(x[i].getElementsByTagName("BATTV")[0].childNodes[0].nodeValue.slice(0,
          x[i].getElementsByTagName("BATTV")[0].childNodes[0].nodeValue.length -1));
  document.write(val);
  document.write("</td><td>");
  var val=(x[i].getElementsByTagName("OUTA")[0].childNodes[0].nodeValue.slice(0,
          x[i].getElementsByTagName("OUTA")[0].childNodes[0].nodeValue.length -1));
  document.write(val);
  document.write("</td><td>");
  var val=(x[i].getElementsByTagName("BATTA")[0].childNodes[0].nodeValue.slice(0,
          x[i].getElementsByTagName("BATTA")[0].childNodes[0].nodeValue.length -1));
  document.write(val);
  document.write("</td><td>");
  document.write(x[i].getElementsByTagName("SOC")[0].childNodes[0].nodeValue);
  document.write("</td><td>");
  document.write(x[i].getElementsByTagName("AHREM")[0].childNodes[0].nodeValue);
  document.write("</td><td>");
  document.write(x[i].getElementsByTagName("AHR")[0].childNodes[0].nodeValue);

  document.write("</td></tr>");

  }
document.write("</table></td></tr></table>");
</script>

</body>
</html>


Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

paul alting

Gosh, I think i have missed a few posts here from you David,
Just caught up and read what I have missed and am impressed with your progress David.
The background image is striking and the way you have used it looks good.
Normally I don't use background images, but this one, I like.

Now, way back you asked me a question, which I haven't yet answered.
QuoteI managed to find one of these Taijiuino DUE boards complete with a programming interface card.
/snip
As you pointed out the Wiznet uses the spi interface, as does the SD card, and even with the latest IDE1.6.3 the drivers appear broken, each works well by itself but using both ethernet and SD card just does not work very well.
So question is - has there been any progress towards completing a DUE ethernet library for the Taijiuino?
The is so much program flash,512k, and ram 96k, that I can get my more advanced (analogue gauges) web interface for Classic into memory and not bother the SD storage. However the SD would be very useful for log file storage.
Unfortunately it has mostly come to a standstill, through circumstance.
Surprisingly, not a lot of people showed interest in having the onboard EMAC put into play with a suitable PHY chip and having the Ethernet library developed for the DUE family.
Coding such a library for this EMAC sub section is a fair sized task and not without some difficulties.
It's a shame really, as being able to use the onboard EMAC on the DUE would bring the DUE into the realms of what a larger computer such as Cubieboard can do in terms of Ethernet connectivity.
It would be fast, very fast and be totally separate from the SD sub section. The library together with this hardware would support a greater number of TCP connections that what the standard Wiznet shield can support.

Yes, with all that extra onboard flash and RAM on the DUE, many exciting things would be possible.

I did come to the realisation not long after our little group was looking at writing the Ethernet library, that for more intensive Ethernet based projects, making use of small GNU/Linux boards was more likely the better way to go. Also, we were going to invest a lot of effort into writing this library for who, and for how long was the DUE going to be around, considering new boards were being launched every other day with more features. And lastly, the DUE, as good as it seems to be, has many, not quite design flaws, but feature flaws, and would possibly see the DUE the odd one out and not so loved as other Arduino boards.

Still, I do love my Taijuino , alongside with my Ether-Mega and Ether-Ten :)

QuoteOr maybe I have reached the limits of the DUE and its time to get to the Cubie2  :)
Yes, for me, both have relevancy, Arduino style boards for that direct low level I/O work and critical timing, much like how we use and put trust into a PLC in an industrial situation. And the Cubieboard II or what ever flavour excite your taste buds, used for actual data processing and connecting with higher level devices and to us humans. :)
_____
Paul
6 x 200W PV into home-brew 6 stage MOSFET charge controller : Microhydro 220Vac 3 phase IMAG
8 x 400Ah LiFeYPO4 Winston : Latronics LS2412 inverter
QuadlogSCADA control and monitoring system : Tasmania, Australia : http://paulalting.com

zoneblue

Quote
that for more intensive Ethernet based projects, making use of small GNU/Linux boards was more likely the better way to go.

Have you guys thought about contributing to theblackboxproject instead of redoing everything ive done from scratch? If the svn or anything else is a turnoff, let me i know. Blackbox code is written in a modular way, such that you can easily add support for new devices, multiple devices. Writing a web app in c does seem like an awful chore, when php was designed exactly for that. And php uses a lot of c syntax so easy learning curve.
6x300W CSUN, ground mount, CL150Lite, 2V/400AhToyo AGM,  Outback VFX3024E, Steca Solarix PL1100
http://www.zoneblue.org/cms/page.php?view=off-grid-solar

dgd

#55
Quote from: zoneblue on June 11, 2015, 02:46:12 AM
Have you guys thought about contributing to theblackboxproject instead of redoing everything ive done from scratch? If the svn or anything else is a turnoff, let me i know. Blackbox code is written in a modular way, such that you can easily add support for new devices, multiple devices. Writing a web app in c does seem like an awful chore, when php was designed exactly for that. And php uses a lot of c syntax so easy learning curve.

Good point. I want to move my efforts to the cubie2 with Linux, Apache and maybe PHP sometime soon.
The main reason I went off in the Arduino direction was to eventually design and build hardware and software for an embedded processor addon for the Classic Lite that would essentially be a plug in faceplate like the MNGP or MNLP.
Because of the very limited resources such processors have its not feasible to have an OS like linux, featured web server programs such as Apache or have available high density/high speed storage interfaces.
Also the software needed to be tight and small in size and served web pages had to hand off as much processing as possible to the web browser. ALthough I have used the SD card to store and serve web pages from, the pages use javascript for the browser to execute and hence do much of the work, also the pages are so small they coud easily fit in program memory of an embedded cpu.
As you are aware, PHP is a server side processing system with all sorts of good interfacing to databases, files etc and does most of the complicated stuff on the server and presents straight forward html to the web browser - ok thats a bit simplified  :)
The Cubie2 is, IMHO, more of a general data processing system like my asus laptop but with some good lower level interfaces
Little annoyances like not easily getting an OS that boots and loads from hdd are disappointing. ANyway, will get there soon

Sorry for the long reply but there is also another reason for doing all the Arduino stuff, its just damm good fun and C++ is the only real development language.
Also I do appreciate the efforts you have made with the blackbox project, there is some good stuff there and I do look forward to getting involved with it.
dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

Quote from: paul alting on June 10, 2015, 08:24:59 AM
I did come to the realisation not long after our little group was looking at writing the Ethernet library, that for more intensive Ethernet based projects, making use of small GNU/Linux boards was more likely the better way to go. Also, we were going to invest a lot of effort into writing this library for who, and for how long was the DUE going to be around, considering new boards were being launched every other day with more features. And lastly, the DUE, as good as it seems to be, has many, not quite design flaws, but feature flaws, and would possibly see the DUE the odd one out and not so loved as other Arduino boards.

I can see the logic in this. I just noticed in the last couple of weeks a new Chinese single board Arduino Mega sized PcDuino
system. Arm A20 cpu, flash, gpu, Lots of interfaces, ethernet, SATA, SD, wireless etc and it has an Arduino interface for various shields.

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

zoneblue

Youve no doubt heard about the upcoming "9 dollar computer". Its Arm Cortex, and very tiny.  Has wifi but no ethernet, but maybe thats not a major, given the power overheads of ethernet, and the ubiquity of wifi these days.

https://www.kickstarter.com/projects/1598272670/chip-the-worlds-first-9-computer/description

They won 2 mill on their kickstarter, impressive.
6x300W CSUN, ground mount, CL150Lite, 2V/400AhToyo AGM,  Outback VFX3024E, Steca Solarix PL1100
http://www.zoneblue.org/cms/page.php?view=off-grid-solar

dgd

#58
replaced node14.html  in previous posting with new version that displays up to 48 ten minute log records in two 24 record side by side tables in one screen. This covers 8 hours of log records and gives a more complete picture of a days power production. Some cosmetic changes too to make it look neater.
Example screen display below..
There is enough screen width left to probably include temperatures in the tables.

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand

dgd

#59
The second, left button in the Canv gauge display, loads the file bocfet.htm stored on SD card. This file provides several graph report options that use log file data stored in memory data structures in the Arduino Mega or DUE.
In the initial version the data is 10 minute snapshot records of Classic modbus register values, time and date stamped.
The Mega with 8k ram can store near 100 records covering a 16 hour period, however this can extend to the power input periods of nearer two days if zero input power periods are not stored. This only applies to solar input where predictable period of darkness is known. With wind a different approach testing for adjacent periods of zero power and creating a time started/stopped special record is used.
With the DUE there is almost unlimited memory for log records covering a week to 10 days.
Each day after the Classic resets  KwHr to zero the 16 hours, or less, of power input measurements are compressed then stored to a log file bocolog.dat  This file can then be transferred using AJAX as input to a HighStock graph (using another SD file outlog.htm)

html files in following posts with display examples.

dgd
Classic 250, 150,  20 140w, 6 250w PVs, 2Kw turbine, MN ac Clipper, Epanel/MNdc, Trace SW3024E (1997), Century 1050Ah 24V FLA (1999). Arduino power monitoring and web server.  Off grid since 4/2000
West Auckland, New Zealand