//Licenced under GNU General Public Licence more details here
// openenergymonitor.org
/////////////////////////EnergyWebDuino V7 rev7.1 – 29/03/16 – Sagittarius ©2016/////////////////////////////
//// Ethernet
#include <Ethernet.h>
#include <SPI.h>
//#include <Wire.h>
#include <DS1302.h>
//////———————————————————–//// Mem
#include <pgmspace.h> // for progmem
#define P(name) static const prog_uchar name[] PROGMEM // declare a static string
//////———————————————————–//// 1302 RTC
int DS1302CLKPin=6;
int DS1302IOPin=7;
int DS1302CEPin=8;
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
//////———————————————————–
//// V/I input sensors
//Set Voltage and current input pins
int inPinI = 5;//=>Ana
const int inPinV = 4;//=>Ana
int inPinI2 = 2;//=>Ana
//////———————————————————–
//// Pulse count
/*—–( Declare Constants )—–*/
#define ANALOG_SENSOR_PIN A3 //=>Ana
#define DIGITAL_SENSOR_PIN 5 //=>Digi
#define LEDPIN 13 //=>Digi The onboard LED
#define cpt1 0//=>Digi RX Teleinfo
int Counter = 0;/*—–( Declare Variables )—–*/
int switch_state; /* Holds the last digital value */
int LightAnalogValue; /* Holds the last analog value */
unsigned long pulseCount = 0; // Counts power pulses in interrupt, 1 pulse = 1 watt
unsigned long pulseTotal = 0; // Total power used since the sketch started
volatile int pulseFlag = 0;
//////———————————————————–//// RTC int
char buf[50]; // time output string for debugging
DS1302 rtc(DS1302CEPin, DS1302IOPin, DS1302CLKPin);
//////———————————————————–//// KWh prod
int last_hour = 0;
int hour = 12, minute = 0, second = 0;
double usekwh = 0, genkwh = 0;
double usewh =0, genwh = 0;
double use_history[7], gen_history[7];
int cval_use, cval_gen;
byte page = 1;
unsigned long fast_update, slow_update;
//const int SolarPV_type=1; // Select solar PV wiring type – Type 1 is when use and gen can be monitored seperatly. Type 2 is when gen and use can only be monitored together, see solar PV application documentation for more info
const int maxgen=3000; // peak output of soalr PV system in W – used to calculate when to change cloud icon to a sun
const int PV_gen_offset=50; // When generation drops below this level generation will be set to zero – used to force generation level to zero at night
//////———————————————————–//// Sampling
int numberOfSamples = 3000;
//Enter the values of your setup below
// Voltage is reduced both by wall xfmr & voltage divider
#define AC_WALL_VOLTAGE 230.0
#define AC_ADAPTER_VOLTAGE 10.5
// Ratio of the voltage divider in the circuit
#define AC_VOLTAGE_DIV_RATIO 10
// CT: Voltage depends on current, burden resistor, and turns
#define CT_BURDEN_RESISTOR 33
#define CT_TURNS 2000
#define ADC_COUNTS (1<<ADC_BITS)
#if defined(__arm__)
#define ADC_BITS 12
#else
#define ADC_BITS 10
#endif
//////———————————————————–//// Calibration coeficients
//These need to be set in order to obtain accurate results
//Set the above values first and then calibrate futher using normal calibration method described on how to build it page.
double VCAL = 1.00;
double ICAL = 1.00;//0.99;
double PHASECAL = 2.3;//1.7;//2.5
// Initial gueses for ratios, modified by VCAL/ICAL tweaks
double I_RATIO = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL;
int lastSampleV,sampleV; //sample_ holds the raw analog read value, lastSample_ holds the last sample
int lastSampleI,lastSampleI2,sampleI,sampleI2;
double lastFilteredV,filteredV; //Filtered_ is the raw analog value minus the DC offset
double lastFilteredI,lastFilteredI2,filteredI,filteredI2;
//Stores the phase calibrated instantaneous voltage.
double shiftedV;
double phaseShiftedV; //Holds the calibrated phase shifted voltage.
double sqV,sumV,sqI,sqI2,sumI,sumI2,instP,instP2,sumP,sumP2; //sq = squared, sum = Sum, inst = instantaneous
//Calibration coeficients
double VAC = 230.0;
long readVcc();
//Useful value variables
double realPower,
realPower2,
apparentPower,
apparentPower2,
powerFactor,
powerFactor2,
Vrms,
/*Vrms2,*/
Irms,
Irms2;
int startV; //Instantaneous voltage at start of sample window.
boolean lastVCross,checkVCross; //Used to measure number of times threshold is crossed.
int crossCount,crossCount2;
//////———————————————————–//// FREQUENCY MEASURMENT VARIABLES—————————
unsigned long vLastZeroMsec; //time in microseconds when the voltage waveform last crossed zero.
unsigned long vPeriod; //Micro seconds since last zero-crossing
unsigned long vPeriodSum; //Sum of vPeriod’s to obtain an average.
unsigned long vPeriodCount; //Number of periods summed
float freq; //Frequency
//Used to filter out fringe vPeriod readings.
unsigned long expPeriod = 20000; //Configured for 50Hz 20000 //- If your 60Hz set expPeriod = 16666
unsigned long filterWidth = 2000;
int n;
//////———————————————————–#define NETTIMECHECK 120
long netTimeout = 0; // counter to check for net activity
//// analog in and filter
long VCCread=0;
long readVcc() {
// call: readVcc();
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
// delay(100);
}
double V_RATIO; // for use after calibration KLL
//////———————————————————–//// ———— Init connec réseau local
//byte ip[] = { 192, 168, 1, 111 }; //Manual setup only
IPAddress ip(192,168,1,111);
byte gateway[] = { 192, 168, 1, 1 }; //Manual setup only
byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetServer server = EthernetServer(80); //port 80
//////———————————————————–const int MAX_PAGENAME_LEN = 8; // max characters in page name
char buffer[MAX_PAGENAME_LEN+1]; // additional character for terminating nullvoid setup()
{
msTick=millis(); // Initialise the msTick counter
// initialisation du port série sur broches 0-1 : 1200,7,E,1 pour connexion téléinfo
//// Serial & Web init
//Serial.begin(115200); // réinitialise communication série
Ethernet.begin(mac, ip, gateway, subnet); //for manual setup
server.begin();
// Wire.begin();
//////———————————————————–// Set the clock to run-mode, and disable the write protection
// setup 1302
Time t = rtc.time();
snprintf(buf, sizeof(buf), « DS1302 time: %02d:%02d:%02d »,
t.hr, t.min, t.sec);
//////———————————————————–//// Pulse count
/*Initialize INT0 for accepting interrupts */
PORTD |= 0x04;
DDRD &=~ 0x04;
pinMode(LEDPIN, OUTPUT);
//Enable interrupt for light sensor on Digital 3
attachInterrupt(1, Pulse, FALLING);
//////———————————————————–//analogReference(INTERNAL);
netTimeout = millis(); // timer to make sure the net is active}
void Pulse() // routine called when light sensor interrupt is triggered
{
//pulseFlag = 0;
detachInterrupt(0);
//int pulseState = digitalRead(PORTD);
//if (pulseState > 0) {
pulseFlag = 1;
pulseCount = 1;
//}
}void loop()
{
uint16_t plen, dat_p;
delay(1000);
VCCread=readVcc(); // calibrate on Vcc in millivolt
V_RATIO = AC_WALL_VOLTAGE / AC_ADAPTER_VOLTAGE * AC_VOLTAGE_DIV_RATIO * VCCread / 1024.0 * VCAL / 1000.0;
I_RATIO = CT_TURNS / CT_BURDEN_RESISTOR * VCCread / 1024.0 * ICAL / 1000.0;
for (int n=0; n<numberOfSamples; n++)
{
//Used for offset removal
lastSampleV=sampleV;
lastSampleI=sampleI;
lastSampleI2=sampleI2;
//Read in voltage and current samples.
sampleV = analogRead(inPinV);
sampleI = analogRead(inPinI);
sampleI2 = analogRead(inPinI2);
//Used for offset removal
lastFilteredV = filteredV;
lastFilteredI = filteredI; //kll
lastFilteredI2 = filteredI2; //kll
//Digital high pass filters to remove 2.5V DC offset.
filteredV = 0.996*(lastFilteredV+sampleV-lastSampleV);
//filteredV = sampleV – 512; // mod KLL
filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);
filteredI2 = 0.996*(lastFilteredI2+sampleI2-lastSampleI2);
//filteredI = sampleI – 512; // mod KLL
//Phase calibration goes here.
shiftedV = lastFilteredV + PHASECAL * (filteredV – lastFilteredV);
//Root-mean-square method voltage
//1) square voltage values
sqV= filteredV * filteredV;
//2) sum
sumV += sqV;
//Root-mean-square method current
//1) square current values
sqI = filteredI * filteredI;
sqI2 = filteredI2 * filteredI2;
//2) sum
sumI += sqI;
sumI2 += sqI2;
//Instantaneous Power
instP = shiftedV * filteredI;
instP2 = shiftedV * filteredI2;
//Sum
sumP +=instP;
sumP2 +=instP2;////–FREQUENCY MEASURMENT—————————
if (n==0) vLastZeroMsec = micros();
//Check for zero crossing from less than zero to more than zero
if (lastFilteredV < 0 && filteredV >= 0 && n>1)
{
vPeriod = micros() – vLastZeroMsec; //period of voltage waveform
//Filteres out any erronous period measurments
//Increases accuracy considerably
if (vPeriod > (expPeriod-filterWidth) && vPeriod<(expPeriod+filterWidth))
{
vPeriodSum += vPeriod;
vPeriodCount++;
}
vLastZeroMsec = micros();
} // wave form cross 0
}
//////———————————————————–//// Calculation of the root of the mean of the voltage and current squared (rms)
//Calibration coeficients applied.
/* double V_RATIO = VCAL *((5000/1000.0) / (ADC_COUNTS));// supply voltage: 5000=5v;3300=3,3v
double I_RATIO = ICAL *((5000/1000.0) / (ADC_COUNTS));*/
Vrms = V_RATIO*sqrt(sumV / numberOfSamples);
Irms = I_RATIO*sqrt(sumI / numberOfSamples);
Irms2 = I_RATIO*sqrt(sumI2 / numberOfSamples);
//Calculation power values
realPower = V_RATIO*I_RATIO*sumP / numberOfSamples;
realPower2 = V_RATIO*I_RATIO*sumP2 / numberOfSamples;
apparentPower = Vrms * Irms;
apparentPower2 = Vrms * Irms2;
powerFactor = apparentPower / realPower;
powerFactor2 = apparentPower2 / realPower2;// / apparentPower2;
//////———————————————————–//// FREQUENCY CALCULATION————————–
freq = (1000000.0 * vPeriodCount) / vPeriodSum;
vPeriodSum=0;
vPeriodCount=0;
//////———————————————————–
//// Go to the web page
//Serial.println();
EthernetClient client = server.available();
if (client)
{
String readString = String(30);
while (client.connected())
{
if (client.available())
{
// if you’ve gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
char c = client.read();//6
if (readString.length() < 30){//lenreadstr) readString += c; //créé le message reçu
readString += c;
}
if (c == ‘\n’) { //teste que le message reçu est complet
if (readString.indexOf(« cmd=1 ») >0)
{//// Téléinfo
client.println(F(« HTTP/1.1 200 OK »));
client.println(F(« Content-Type: text/html « ));
client.println(F(« Connection: close »)); // indique au client que la connexion est fermée après réponse
// à noter que la connexion est persistante par défaut coté client en l’absence de cette ligne
client.println(); // ligne blanche obligatoire après l’entete HTTP envoyée par le serveur
client.println(F(« <html><head><title></title></head><body> »));client.println(F(« </body> »));
client.println(F(« </html> »));delay(5000); // give the web browser time to receive the data
client.stop(); // close the connection:
break;
}//no ;
else if (readString.indexOf(« cmd=0 ») || !readString)
{
//client.print(F(« GET /?cmd= »));
//client.print(F(« 0 »));
client.println(F(« HTTP/1.1 200 OK »));
client.println(F(« Content-Type: text/html « ));
client.println(F(« Connection: close »)); // indique au client que la connexion est fermée après réponse
// à noter que la connexion est persistante par défaut coté client en l’absence de cette ligne
client.println(); // ligne blanche obligatoire après l’entete HTTP envoyée par le serveur
client.println(F(« <!DOCTYPE HTML><html><head><meta content=’text/html; charset=UTF-8’http-equi »
« v=’content-type’><META HTTP-EQUIV=’Refresh’ CONTENT=’60’; URL=’#’></head><bod »
« y><meta name=’HandheldFriendly’ content=’True’><meta name=’MobileOptimized’ »
« content=’320′><meta name=’viewport’ content=’user-scalable=no, width=device- »
« width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0′><meta http-eq »
« uiv=’cleartype’ content=’on’><meta name = ‘format-detection’ content = ‘tele »
« phone=no’><meta name=’apple-mobile-web-app-capable’ content=’yes’><meta name »
« =’apple-mobile-web-app-status-bar-style’ content=’black’><meta name=’apple-m »
« obile-web-app-title’ content=’ASFDuino’><style type=’text/css’>a {text-decor »
« ation: none;}font {font-family: Arial, Helvetica, sans-serif;}</style><title »
« >Serveur Web Arduido</title> »));client.print(F(« </head><body bgcolor=’#707274′ style=’margin-top:-17px;margin-left:-2px;’><p »
» align=’left’><table width=’320′ align=’top’ border=’0′><tr><td width=' »
« 320′ height=’80’ style=’padding: 3px;background: #EBEBEB;border: 2px solid # »
« F5F5F5;border-radius: 11px;-moz-border-radius: 11px;-webkit-border-radius: 1 »
« 1px;box-shadow: inset 0px 0px 9px 1px rgba(119, 119, 119, 0.44);-moz-box-sha »
« dow: inset 0px 0px 9px 1px rgba(119, 119, 119, 0.44);-webkit-box-shadow: ins »
« et 0px 0px 9px 1px rgba(119, 119, 119, 0.44);line-height: 12px;’><div style= »
« ‘text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.87);color: #0080ff;font-size: 16px »
« ;’><center><b>SERVEUR HTTP embarqué sur carte Arduino©</b></cent »
« er></div><br><center><font size=’1′ color=’Black’><b>Accès via liaison »
» ETHERNET</b><br><font size=’-1′><a href=’http://%5Byourserver%5D’ target=’_blank’>{nameofyourserver]</a></font></center></font><hr align=center width =90%/><font size=’1′ col »
« or=’Black’><center><b>Monitoring Compteur ErDF & »
« Panneaux solaires<br>Drink your coffee easy!</b></center></font><hr align=cent »
« er width =90%/></td></tr><tr><td height=’400′ style=’padding: 3px;b »
« ackground: #EBEBEB;border: 2px solid #F5F5F5;border-radius: 11px;-moz-border »
« -radius: 11px;-webkit-border-radius: 11px;box-shadow: inset 0px 0px 9px 1px »
« rgba(119, 119, 119, 0.44);-moz-box-shadow: inset 0px 0px 9px 1px rgba(119, 1 »
« 19, 119, 0.44);-webkit-box-shadow: inset 0px 0px 9px 1px rgba(119, 119, 119, »
» 0.44);’> »));
memset(buffer,0, sizeof(buffer)); // clear the buffer//// RTC part
// Get the current time and date from the chip
Time t = rtc.time();
second=t.sec;
minute=t.min;
hour=t.hr;
///////
client.print(F(« <center> »));
client.print(hour);
client.print(F(« : »));
if (minute < 10)
{
client.print(« 0 »),client.print(minute);
}else{
if (minute == 60){
client.print(F(« 00 »));
}else{
client.print(minute);
}
}
client.print(F(« </center> »));
// client.print(kwh);
// client.println(F( » KWh »);
///////
client.print(F(« <font size=’1′ color=’Black’><u>Production PV:</u> »));
if (realPower < 100.00)
{
client.print(F(« <div style=’position: absolute; center: 138px; width: 418px; height: 20px;’><div style=’display: inline;’>Etat PV: </div><div style=’display: inline;color: red;’>Off</div> <div style=’display: inline;’> >Panne< ou >Nuit< </div></div> »));
// client.println(F(« <br><br />Intensité: 0.00 <b>A</b><br />Puissance réelle: 0.00 W</b><br />Puissa »
// « nce apparente: 0.00 <b>VA</b><br />Facteur de puissance: 0.00 <b>%</b><br /> »
// « <u>Consommation ErDF:</u> »));
}
else {
client.print(F(« <div style=’position: absolute; center: 138px; width: 418px; height: 20px;’><div style=’display: inline;’>Etat PV: </div><div style=’display: inline;color: green;’>On</div></div> »));
}
client.print(F(« <br><br />Intensité: <font style=’color: blue;’> »));
client.print(Irms);
client.print(F( » </font><b>A</b><br />Puissance réelle: <font style=’color: blue;’> »));
client.print(realPower);
client.print(F( » </font><b>W</b><br />Puissance apparente: <font style=’color: blue;’> »));
client.print(apparentPower);
client.print(F( » </font><b>VA</b><br />Facteur de puissance: <font style=’color: blue;’> »));
client.print(powerFactor2);
client.print(F( » </font><b>%</b><br /><u>Consommation ErDF:</u> »));
client.print(F(« <br />Intensité2: <font style=’color: blue;’> »));
client.print(Irms2);
client.print(F( » </font><b>A</b><br />Puissance réelle 2: <font style=’color: blue;’> »));
client.print(realPower2);
client.print(F( » </font><b>W</b><br />Puissance apparente 2: <font style=’color: blue;’> »));
client.print(apparentPower2);
client.print(F( » </font><b>VA</b><br />Facteur de puissance 2: <font style=’color: blue;’> »));
client.print(powerFactor2);
client.print(F( » </font><b>%</b><br />Différenciel PV/ErDF: <font style=’color: blue;’> »));
if (realPower < 100.00)
{
client.print(realPower – realPower2);
client.print(F( » </font><b>W</b> »));
}
else {
client.print(realPower – realPower2);
client.print(F( » </font><b>W</b><br />Ratio: <font style=’color: blue;’> »));
client.print(2900.00 / realPower);
client.print(F( » </font><b>%</b> »));
}
client.print(F(« <br /><u>Divers:</u><br />Tension secteur: <font style=’color: blue;’> »));
client.print(Vrms + AC_ADAPTER_VOLTAGE);
client.print(F( » </font><b>V</b><br /> »));
client.print(F(« Fréquence réseau: <font style=’color: blue;’> »));
client.print(freq);
client.print(F( » </font><b>Hz</b><br />Sensor1: « ));
// client.println(prt,1);
client.print(F(« <br />Sensor2: « ));
// client.println(prt,2);
//// Pulse count
if (pulseFlag == 1)
{
pulseCount ++;
// pulseFlag = 0;
client.print(« <br />Impulsions: <font style=’color: blue;’> »);
client.print(pulseCount);
client.print(F( » </font>pulse en « ));
client.print(millis());
client.print(F( » ms »));
delay(10);
attachInterrupt(0, Pulse, LOW);
}
else{
client.print(« <br />Impulsions: <font style=’color: blue;’> »);
client.print(pulseCount);
client.print(F( » </font>pulse depuis « ));
client.print(millis()/100);
client.print(F( » s »));
}
////////// KWh prod
if ((millis()-fast_update)>200)
{
fast_update = millis();
//DateTime// int last_hour = hour;
// char nowhour = rtc.hour();
// char nowminute = rtc.minute();if (realPower < 100.00)
{
if (realPower2 < 100.00)
{
usekwh = 0.00;
usewh = 0.00;
genkwh = 0.00;
genwh = 0.00;
}
else{
usekwh += (realPower2 * 0.2) / 3600000;
usewh += usekwh * 1000;
genkwh = 0.00;
genwh = 0.00;
}
}
else{
// if (SolarPV_type==1){
usekwh += (realPower2 * 0.2) / 3600000;
usewh += usekwh * 1000;
genkwh += (realPower * 0.2) / 3600000;
genwh += genkwh * 1000;
// }
}
// if (SolarPV_type==2){
// usekwh += ((realPower2 + realPower) * 0.2) / 3600000;
// usewh += usekwh * 1000;
// genkwh += (realPower * 0.2) / 3600000;
// genwh += genkwh * 1000;
// }if (last_hour == 23 && hour == 00)
{
int i;
for (i=6; i>0; i–) gen_history[i] = gen_history[i-1];
genkwh = 0;
genwh = 0;
for(i=6; i>0; i–) use_history[i] = use_history[i-1];
usekwh = 0;
usewh = 0;}
gen_history[0] = genkwh;
use_history[0] = usekwh;// if (SolarPV_type==1){
cval_use = cval_use + (realPower2 – cval_use)*0.50;
cval_gen = cval_gen + (realPower – cval_gen)*0.50;
// }// if (SolarPV_type==2){
// cval_use = cval_use + ((realPower2+realPower) – cval_use)*0.50;
// cval_gen = cval_gen + (realPower – cval_gen)*0.50;
// }if (cval_gen<PV_gen_offset) cval_gen=0; //set generation to zero when generation level drops below a certian level (at night) eg. 20W
//use, usekwh, gen, maxgen, genkwh, temp, mintemp, maxtemp, hour, minute, last_emontx, last_emonbase)
//client.println(cval_use);
client.print(F(« <br />Consommation ErDF: <font style=’color: blue;’> »));
client.print(usekwh);
client.print(F( » </font>KWh (<font style=’color: blue;’> »));
client.print(usewh);
client.print(F(« </font> Wh)<br />Production PV: <font style=’color: blue;’> »));
client.print(genkwh);
client.print(F(« </font> KWh (<font style=’color: blue;’> »));
client.print(genwh);
client.print(F(« </font> Wh)<br /> »));
//client.println(temp);
//client.print(F( » | « ));
//client.println(mintemp);
//client.print(F( » | « ));
//client.println(maxtemp);
//client.print(F( » | « ));// client.print(kwh);
// client.println(F( » KWh »);
client.print(F(« </font></td></tr></table></p> »));//<form method=’GET’><input type=’hidden’ name=’cmd’ value=’teleinfo’ /><input type=’submit’ value=’Téléinfo’ /></form></td></tr></table></p> »));
client.print(F(« <p style=’display: none;’>INSERT INTO enerduino VALUES (‘ »));//(id, h, min, irmspv, rppv, appv, pfpv, irmsedf, rpedf, apedf, pfedf, ratio, u, f, pc, usepw, genpw, s1, s2, rawti)
client.print(F(« ‘, ‘ »));
client.print(hour);
client.print(F(« ‘, ‘ »));
if (minute < 10){
client.print(F(« 0 »)),client.print(minute);
}else{
if (minute == 60){
client.print(F(« 00 »));
}else{
client.print(minute);
}
}
client.print(F(« ‘, ‘ »));
client.print(Irms);
client.print(F(« ‘, ‘ »));
client.print(realPower);
client.print(F(« ‘, ‘ »));
client.print(apparentPower);
client.print(F(« ‘, ‘ »));
client.print(powerFactor);
client.print(F(« ‘, ‘ »));
client.print(Irms2);
client.print(F(« ‘, ‘ »));
client.print(realPower2);
client.print(F(« ‘, ‘ »));
client.print(apparentPower2);
client.print(F(« ‘, ‘ »));
client.print(powerFactor2);
client.print(F(« ‘, ‘ »));
client.print(2900/realPower);
client.print(F(« ‘, ‘ »));
client.print(Vrms + AC_ADAPTER_VOLTAGE);
client.print(F(« ‘, ‘ »));
client.print(freq);
client.print(F(« ‘, ‘ »));
client.print(pulseCount);
client.print(F(« ‘, ‘ »));
client.print(usekwh);
client.print(F(« ‘, ‘ »));
client.print(genkwh);
client.print(F(« ‘, ‘0’, ‘0’, ‘0’)</p> »));
// client.print(F(« 0 »));
// client.print(F(« ‘)</p> »)); // message debug Terminal Arduino
//////——————————————————-
client.print(F(« </body></html> »));
readString = « »;
break;
}//if milli
}//if clcmd 1 ou 0
}//if c
//////————————————————————————-
}//if clientav
///////
}//while clientcon
delay(10000); // give the web browser time to receive the data
client.stop(); // close the connection:
}//if client
//Reset accumulators
sumV = 0;
sumI = 0;
sumP = 0;
// sumV2 = 0;
sumI2 = 0;
sumP2 = 0;
delay(10);
//////———————————————————–
}
void printP(const prog_uchar *str)
{
EthernetClient client = server.available();
// copy data out of program memory into local storage, write out in
// chunks of 32 bytes to avoid extra short TCP/IP packets
// from webduino library Copyright 2009 Ben Combee, Ran Talbott
uint8_t buffer[32];
size_t bufferEnd = 0;while (buffer[bufferEnd++] = pgm_read_byte(str++))
{
if (bufferEnd == 32)
{
client.write(buffer, 32);
bufferEnd = 0;
}
}
// write out everything left but trailing NUL
if (bufferEnd > 1)
client.write(buffer, bufferEnd – 1);
}