ESP8266 loopt vast

Software vragen voor ESP chip familie
Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

ESP8266 loopt vast

Berichtdoor René » 03 Feb 2017, 18:19

Ik heb een esp8266 draaien die elke 5 minuten de produktie van mijn zonnepanelen doorstuurt naar PVoutput.org. Dat werkt maar....
Na een aantal uren loopt het systeem vast. Ik zie dan nog wel een blauw ledje oplichten als er een puls binnenkomt maar er wordt geen data meer verstuurt.
Voor zover ik het begrijp zou het een memory lek kunnen zijn.
Naast dit vervelende probleem zitten er in de code ook nog wel verbeterpunten: zo haal ik bijvoorbeeld de tijd op van een website maar die is in GMT ik vertaal die nu erg primitief naar onze tijd.
Iemand ideeën over het vastlopen en verdere vebetering van de code?

cpp code
/*
* programma meet de SO pulsen van een kwh meter die de levering van zonnepanelen meet
* programma stuurt data via HTTP GET requests naar PVoutput.org service.
* programma draait op een esp8266 v1.5.0
* via een website (google.com) wordt de tijd opgehaald
*/

#include <ESP8266WiFi.h>
#include <stdlib.h>

//Number of pulses, used to measure energy.
long pulseCount = 0;
//Used to measure power.
unsigned long pulseTime,lastTime;

//power and energy
//double power, newpower, elapsedkWh, newelapsedkWh, opbrengst;
double power, opbrengst;
//Number of pulses per wh - found or set on the meter.
int ppwh = 1; //1000 pulses/kwh = 1 pulse per wh

const char* ssid = "rebr";
const char* password = "XXXXXXXXXXXX";
const char* host = "pvoutput.org";
const char* SystemId = "49832";
const char* APIKey = "XXXXXXXXXXXXXXX";
int datum = 20170117;

String dag = "02";
String maand = "02";
String jaar = "1949";
String uur = "01";
String minuut = "01";
String tijd = "13:13";

void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// KWH pulsen worden geteld via interrupt
attachInterrupt(2, onPulse, FALLING);
}


void loop() {

// convert to string
char buf[16];

Serial.print(opbrengst);
Serial.print(" \"in loop\" ");
Serial.println(power);
Serial.println(getTime());

String stringOne = (getTime());
dag = stringOne.substring(5,7);
maand = stringOne.substring(8,11);
jaar = stringOne.substring(12,16);
uur = stringOne.substring(17,19);
minuut = stringOne.substring(20,22);

// 1 uur tijdsverschil met gmt(wellicht gaat het mis met zomertijd moet slimmer kunnen!)
if (uur == "00") uur = "01";
else if (uur == "01") uur = "02";
else if (uur == "02") uur = "03";
else if (uur == "03") uur = "04";
else if (uur == "04") uur = "05";
else if (uur == "05") uur = "06";
else if (uur == "06") uur = "07";
else if (uur == "07") uur = "08";
else if (uur == "08") uur = "09";
else if (uur == "09") uur = "10";
else if (uur == "10") uur = "11";
else if (uur == "11") uur = "12";
else if (uur == "12") uur = "13";
else if (uur == "13") uur = "14";
else if (uur == "14") uur = "15";
else if (uur == "15") uur = "16";
else if (uur == "16") uur = "17";
else if (uur == "17") uur = "18";
else if (uur == "18") uur = "19";
else if (uur == "19") uur = "20";
else if (uur == "20") uur = "21";
else if (uur == "21") uur = "22";
else if (uur == "22") uur = "23";
else if (uur == "23") uur = "00";

tijd = (uur + ":" + minuut);

if (maand == "Jan") maand = "01";
else if (maand == "Feb") maand = "02";
else if (maand == "Mar") maand = "03";
else if (maand == "Apr") maand = "04";
else if (maand == "May") maand = "05";
else if (maand == "Jun") maand = "06";
else if (maand == "Jul") maand = "07";
else if (maand == "Aug") maand = "08";
else if (maand == "Sep") maand = "09";
else if (maand == "Oct") maand = "10";
else if (maand == "Nov") maand = "11";
else if (maand == "Dec") maand = "12";

Serial.print("connecting to ");
Serial.println(host);

// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}

// We now create a URI for the request

String url = "/service/r2/addstatus.jsp?";
url += "key=";
url += APIKey;
url += "&sid=";
url += SystemId;
url += "&d=";
url += jaar;
url += maand;
url += dag;
url += "&t=";
url += tijd;
url += "&v1=";
url += opbrengst;
url += "&v2=";
url += power;



Serial.print("Requesting URL: ");
Serial.println(url);
// Serial.println("/service/r2/addoutput.jsp?key=c68ae892fa3a6644c5a6d0dd1cde82cbf37dc659&sid=49832&d=20170129&g=13330");
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");

unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}

// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}

Serial.println();
Serial.println("closing connection");

delay(300000);// elke 5 minuten kan/mag er data naar PVoutput worden gestuurd
}


String getTime() {
WiFiClient client;
while (!!!client.connect("www.google.com", 80)) {
Serial.println("connection failed, retrying...");
}

client.print("HEAD / HTTP/1.1\r\n\r\n");

while(!!!client.available()) {
yield();
}

while(client.available()){
if (client.read() == '\n') {
if (client.read() == 'D') {
if (client.read() == 'a') {
if (client.read() == 't') {
if (client.read() == 'e') {
if (client.read() == ':') {
client.read();
String theDate = client.readStringUntil('\r');
client.stop();
return theDate;
}
}
}
}
}
}
}
}


// The interrupt routine
void onPulse()
{
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 1500) //declare the debounce/block out interval in setup
{

//used to measure time between pulses.

lastTime = pulseTime;
pulseTime = millis();

//pulseCounter
pulseCount++;

//Calculate power
power = (3600000.0 / (pulseTime - lastTime))/ppwh;

//Find kwh elapsed
opbrengst = (1.0*pulseCount/(ppwh)); //multiply by 1000 to convert pulses per wh to kwh

Serial.print(opbrengst,0);
Serial.print(" in pulse ");
Serial.println(power,0);
Serial.println(freeRam());
}
last_interrupt_time = interrupt_time;
}

Advertisement

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 03 Feb 2017, 19:33

Een paar mogelijke boosdoeners:
a) gebruik van String en dan zo vaak dat er fragmentatie ontstaat waardoor die url niet meer opgebouwd kan worden. String moet je eigenlijk nooit gebruiken. Gewoon char arrays.
b) De ISR is al een interrupt. Daarbinnen worden meerdere interrupts uitgevoerd o.a. Serial en millis. Gebruik in ieder geval nooit Serial in een ISR.
c) beperk de ISR uitsluitend tot het detecteren van de pulse. Zet dan een boolean aan die je weer in de loop uitleest en reset.
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: ESP8266 loopt vast

Berichtdoor René » 04 Feb 2017, 13:38

Bedankt Nico,
Punt 2 snap ik en kan ik (denk ik) Ik laat de Serial.print gewoon weg na mijn testen.
Punt 3 snap ik (denk ik) maar geeft wel de volgende vraag: Als ik alleen een boolean aanzet zal mijn loop "vaker" moeten draaien dan ik pulsen verwacht. Nu zit in mijn loop een delay van 5 minuten om te voorkomen dat ik te vaak data op stuur. In die vijf minuten komen er veel vaker pulsen langs. Die kan ik dan niet tellen. Dat kan ik oplossen door het zenden niet meer te vertragen met een delay maar door een if statement waarbij de tijd tot de vorige verzending worden gemeten?

Punt 1 is op dit moment het lastigst. Het werken met array's snap ik eigenlijk niet erg goed.
Zou je een voorbeeld kunnen geven hoe ik een van mijn String's omzet in een char array. Bijvoorbeeld bij de String getTime() functie?
Code: Alles selecteren
String getTime() {
  WiFiClient client;
  while (!!!client.connect("www.google.com", 80)) {
    Serial.println("connection failed, retrying...");
  }
 
  client.print("HEAD / HTTP/1.1\r\n\r\n");
 
  while(!!!client.available()) {
     yield();
  }
 
  while(client.available()){
    if (client.read() == '\n') {   
      if (client.read() == 'D') {   
        if (client.read() == 'a') {   
          if (client.read() == 't') {   
            if (client.read() == 'e') {   
              if (client.read() == ':') {   
                client.read();
                String theDate = client.readStringUntil('\r');
                client.stop();
                return theDate;
              }
            }
          }
        }
      }
    }
  }
}

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 04 Feb 2017, 15:25

cpp code
char charArray[30];                        // ff ruim genomen
uint8_t charArrayIndex[0] = '\0'; // string leeg
while(client.available()){
charArray[charArrayIndex] = client.read(); // lees teken in de tabel
if (charArray[charArrayIndex] == '\r' ){ // blijven lezen tot er een return komt
chararray[charArrayIndex] = '\0'; // en sluit te tekst af met een '\0'. De return halen we gelijk weg
break;
}
CharArrayIndex++;
}
client.stop();
//
// er is nu een string in gelezen. We zijn alleen geïnteresseerd in de feitelijke datum
// dus kijk ff of de eerste 7 tekens kloppen
//
if (strnstr(charArray, "\nDate: ", 7) {
//
// het staat in de regel dus geef de rest terug de tekst vanaf positie 7 (bij een index vanaf 0) is de datum
//
return (&charArray[7]);
} else {
return (char *) null;
}


Nu krijg je een char * pointer terug die begint bij het datum veld. En zo zijn er nog vele mogelijkheden.

Het zoiets kunnen zijn
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: ESP8266 loopt vast

Berichtdoor René » 04 Feb 2017, 15:47

TNX Ga het gelijk proberen.....wordt vervolgd

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 04 Feb 2017, 17:20

René schreef:TNX Ga het gelijk proberen.....wordt vervolgd
Net nog wat aanpassingen aangebracht
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: ESP8266 loopt vast

Berichtdoor René » 04 Feb 2017, 19:56

Ik heb nu de volgende functie :

cpp code
String getTime() {
WiFiClient client;
while (!!!client.connect("www.google.com", 80)) {
Serial.println("connection failed, retrying...");
}

client.print("HEAD / HTTP/1.1\r\n\r\n");

while(!!!client.available()) {
yield();
}

char charArray[30]; // ff ruim genomen
uint8_t charArrayIndex[0] = '\0'; // string leeg
while(client.available()){
charArray[charArrayIndex] = client.read(); // lees teken in de tabel
if (charArray[charArrayIndex] == '\r' ){ // blijven lezen tot er een return komt
charArray[charArrayIndex] = '\0'; // en sluit te tekst af met een '\0'. De return halen we gelijk weg
break;
}
charArrayIndex++;
}
client.stop();
//
// er is nu een string in gelezen. We zijn alleen geïnteresseerd in de feitelijke datum
// dus kijk ff of de eerste 7 tekens kloppen
//
if (strnstr(charArray, "\nDate: ", 7) {
//
// het staat in de regel dus geef de rest terug de tekst vanaf positie 7 (bij een index vanaf 0) is de datum
//
return (&charArray[7]);
} else {
return (char *) null;
}


}



maar krijg de volgende foutmeldingen. I had zelf al 3 type? foutjes gevonden. Maar de andere fouten zeggen mij niets en
Googlelen helpt me niet verder.

Arduino: 1.8.1 (Windows XP), Board:"Generic ESP8266 Module, 80 MHz, 40MHz, DIO, 115200, 1M (512K SPIFFS), ck, Disabled, None"

C:\Arduino\arduino-1.8.1\Portable\sketchbook\zonnepaneelversie_3\zonnepaneelversie_3.ino: In function 'String getTime()':

zonnepaneelversie_3:237: error: array must be initialized with a brace-enclosed initializer

uint8_t charArrayIndex[0] = '\0'; // string leeg

^

zonnepaneelversie_3:239: error: invalid types 'char [30][uint8_t [0] {aka unsigned char [0]}]' for array subscript

charArray[charArrayIndex] = client.read(); // lees teken in de tabel

^

zonnepaneelversie_3:240: error: invalid types 'char [30][uint8_t [0] {aka unsigned char [0]}]' for array subscript

if (charArray[charArrayIndex] == '\r' ){ // blijven lezen tot er een return komt

^

zonnepaneelversie_3:241: error: invalid types 'char [30][uint8_t [0] {aka unsigned char [0]}]' for array subscript

charArray[charArrayIndex] = '\0'; // en sluit te tekst af met een '\0'. De return halen we gelijk weg

^

zonnepaneelversie_3:244: error: lvalue required as increment operand

charArrayIndex++;

^

zonnepaneelversie_3:251: error: 'strnstr' was not declared in this scope

if (strnstr(charArray, "\nDate: ", 7)) {

^

zonnepaneelversie_3:257: error: 'null' was not declared in this scope

return (char *) null;

^

exit status 1
array must be initialized with a brace-enclosed initializer

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 04 Feb 2017, 21:05

cpp code
uint8_t charArrayIndex[0] = '\0';       // string leeg


Moet natuurlijk
cpp code
uint8_t charArrayIndex = 0;
charArray[0] = '\0'; // string leeg

Was ff uit het losse polsje...

null moet NULL zijn... Scheelt nog wel eens hier en daar.

Agv. Van dit alles geef je dus geen String meer terug maar een char pointer (char *) en dat betekent weer dat het veel verder ingrijpt.... samenvattend..... gewoon opnieuw beginnen en dan helemaal geen String gebruiken (zoals al zo vaak hier is aangegeven).
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: ESP8266 loopt vast

Berichtdoor René » 04 Feb 2017, 21:28

Dank je Nico "natuurlijk" :) (flauwe grap maar je moet mijn kennis niet te hoog inschatten, ik waardeer je oplossingen maar vooral ook je uitleg er bij, ik leer er veel van op mijn 68ste:)

Ik ben bijna van de foutmeldingen af nu alleen nog :


zonnepaneelversie_3:256: error: 'strnstr' was not declared in this scope

if (strnstr(charArray, "\nDate: ", 7)) {

^

exit status 1
'strnstr' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: ESP8266 loopt vast

Berichtdoor René » 05 Feb 2017, 01:29

Als ik het laatste stukje code niet gebruik en ik na client.stop(); opvraag:
Serial.print(&charArray[0]);
dan krijg ik :
HTTP/1.1 302 Found

in plaats van:

Sat, 04 Feb 2017 22:49:57 GMT

er komen meerdere regels terug van de website

Volgende

Terug naar ESP Software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 1 gast