ESP8266 loopt vast
ESP8266 loopt vast
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
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
- nicoverduin
- Berichten: 5043
- Geregistreerd: 13 Mei 2013, 20:57
- Woonplaats: Heemskerk
Re: ESP8266 loopt vast
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.
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.
Re: ESP8266 loopt vast
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?
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;
}
}
}
}
}
}
}
}
- nicoverduin
- Berichten: 5043
- Geregistreerd: 13 Mei 2013, 20:57
- Woonplaats: Heemskerk
Re: ESP8266 loopt vast
cpp code
Nu krijg je een char * pointer terug die begint bij het datum veld. En zo zijn er nog vele mogelijkheden.
Het zoiets kunnen zijn
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
- nicoverduin
- Berichten: 5043
- Geregistreerd: 13 Mei 2013, 20:57
- Woonplaats: Heemskerk
Re: ESP8266 loopt vast
Net nog wat aanpassingen aangebrachtRené schreef:TNX Ga het gelijk proberen.....wordt vervolgd
Re: ESP8266 loopt vast
Ik heb nu de volgende functie :
cpp code
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.
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.
- nicoverduin
- Berichten: 5043
- Geregistreerd: 13 Mei 2013, 20:57
- Woonplaats: Heemskerk
Re: ESP8266 loopt vast
cpp code
Moet natuurlijk
cpp code
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).
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).
Re: ESP8266 loopt vast
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.
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.
Re: ESP8266 loopt vast
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
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
Wie is er online?
Gebruikers in dit forum: Geen geregistreerde gebruikers en 0 gasten